mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
Add a set type and support code.
This commit is contained in:
parent
60d03dbdd9
commit
cdc790d0c8
4 changed files with 304 additions and 3 deletions
|
@ -3,5 +3,5 @@ AUTOMAKE_OPTIONS= foreign
|
|||
EXTRA_DIST= class.h codespace.h cpp.h dags.h debug.h def.h defspace.h \
|
||||
diagnostic.h emit.h expr.h function.h grab.h idstuff.h linker.h \
|
||||
method.h obj_file.h obj_type.h opcodes.h options.h qfcc.h qfprogs.h \
|
||||
reloc.h shared.h statements.h strpool.h struct.h switch.h symtab.h \
|
||||
type.h value.h
|
||||
reloc.h set.h shared.h statements.h strpool.h struct.h switch.h \
|
||||
symtab.h type.h value.h
|
||||
|
|
64
tools/qfcc/include/set.h
Normal file
64
tools/qfcc/include/set.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
set.h
|
||||
|
||||
Set manipulation.
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2012/8/4
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef set_h
|
||||
#define set_h
|
||||
|
||||
/** \defgroup qfcc_set Set handling
|
||||
\ingroup qfcc
|
||||
*/
|
||||
//@{
|
||||
|
||||
typedef struct set_s {
|
||||
unsigned size;
|
||||
unsigned *map;
|
||||
unsigned defmap[8];
|
||||
} set_t;
|
||||
|
||||
set_t *set_new (void);
|
||||
void set_delete (set_t *set);
|
||||
void set_add (set_t *set, unsigned x);
|
||||
void set_remove (set_t *set, unsigned x);
|
||||
|
||||
set_t *set_union (set_t *dst, const set_t *src);
|
||||
set_t *set_intersection (set_t *dst, const set_t *src);
|
||||
set_t *set_difference (set_t *dst, const set_t *src);
|
||||
set_t *set_assign (set_t *dst, const set_t *src);
|
||||
set_t *set_empty (set_t *set);
|
||||
|
||||
int set_is_empty (const set_t *set);
|
||||
int set_is_disjoint (const set_t *s1, const set_t *s2);
|
||||
int set_is_intersecting (const set_t *s1, const set_t *s2);
|
||||
int set_is_equivalent (const set_t *s1, const set_t *s2);
|
||||
int set_is_subset (const set_t *set, const set_t *sub);
|
||||
int set_is_member (const set_t *set, unsigned x);
|
||||
|
||||
//@}
|
||||
#endif//set_h
|
|
@ -42,7 +42,7 @@ common_src=\
|
|||
class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \
|
||||
diagnostic.c dot_dag.c dot_expr.c dot_flow.c emit.c expr.c \
|
||||
function.c grab.c idstuff.c linker.c method.c obj_file.c obj_type.c \
|
||||
opcodes.c options.c qfcc.c reloc.c shared.c statements.c strpool.c \
|
||||
opcodes.c options.c qfcc.c reloc.c set.c shared.c statements.c strpool.c \
|
||||
struct.c switch.c symtab.c type.c value.c
|
||||
|
||||
qfcc_SOURCES= qc-lex.l qc-parse.y qp-lex.l qp-parse.y $(common_src)
|
||||
|
|
237
tools/qfcc/source/set.c
Normal file
237
tools/qfcc/source/set.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
set.c
|
||||
|
||||
Set manipulation.
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2012/8/4
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
|
||||
#include "set.h"
|
||||
|
||||
#define BITS (sizeof (unsigned) * 8)
|
||||
|
||||
set_t *
|
||||
set_new (void)
|
||||
{
|
||||
set_t *set;
|
||||
|
||||
set = calloc (1, sizeof (set_t));
|
||||
set->size = sizeof (set->defmap) * 8;
|
||||
set->map = set->defmap;
|
||||
return set;
|
||||
}
|
||||
|
||||
void
|
||||
set_delete (set_t *set)
|
||||
{
|
||||
if (set->map != set->defmap)
|
||||
free (set->map);
|
||||
free (set);
|
||||
}
|
||||
|
||||
static void
|
||||
set_expand (set_t *set, unsigned x)
|
||||
{
|
||||
unsigned *map = set->map;
|
||||
size_t size;
|
||||
|
||||
if (x < set->size)
|
||||
return;
|
||||
|
||||
size = (x + BITS - 1) & ~(BITS - 1);
|
||||
set->map = malloc (size / 8);
|
||||
memcpy (set->map, map, set->size / 8);
|
||||
if (map != set->defmap)
|
||||
free (map);
|
||||
}
|
||||
|
||||
void
|
||||
set_add (set_t *set, unsigned x)
|
||||
{
|
||||
if (x >= set->size)
|
||||
set_expand (set, x);
|
||||
set->map[x / BITS] |= 1 << (x % BITS);
|
||||
}
|
||||
|
||||
void
|
||||
set_remove (set_t *set, unsigned x)
|
||||
{
|
||||
if (x >= set->size)
|
||||
return;
|
||||
set->map[x / BITS] &= ~(1 << (x % BITS));
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_union (set_t *dst, const set_t *src)
|
||||
{
|
||||
unsigned size;
|
||||
unsigned i;
|
||||
|
||||
size = max (dst->size, src->size) - 1;
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
dst->map[i] |= src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_intersection (set_t *dst, const set_t *src)
|
||||
{
|
||||
unsigned size;
|
||||
unsigned i;
|
||||
|
||||
size = max (dst->size, src->size) - 1;
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
dst->map[i] &= src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_difference (set_t *dst, const set_t *src)
|
||||
{
|
||||
unsigned size;
|
||||
unsigned i;
|
||||
|
||||
size = max (dst->size, src->size) - 1;
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
dst->map[i] &= ~src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_assign (set_t *dst, const set_t *src)
|
||||
{
|
||||
unsigned size;
|
||||
unsigned i;
|
||||
|
||||
size = max (dst->size, src->size) - 1;
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
dst->map[i] = src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_empty (set_t *set)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < set->size / BITS; i++)
|
||||
set->map[i] = 0;
|
||||
return set;
|
||||
}
|
||||
|
||||
int
|
||||
set_is_empty (const set_t *set)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < set->size / BITS; i++)
|
||||
if (set->map[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
set_equiv,
|
||||
set_intersecting,
|
||||
set_disjoint,
|
||||
} set_test_e;
|
||||
|
||||
static int
|
||||
set_test (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
unsigned i, end;
|
||||
set_test_e rval = set_equiv;
|
||||
|
||||
end = min (s1->size, s2->size) / BITS;
|
||||
for (i = 0; i < end; i++) {
|
||||
if (s1->map[i] != s2->map[i]) {
|
||||
if (s1->map[i] != s2->map[i])
|
||||
return set_intersecting;
|
||||
else
|
||||
rval = set_disjoint;
|
||||
}
|
||||
}
|
||||
if (rval == set_equiv) {
|
||||
for (; i < s1->size / BITS; i++)
|
||||
if (s1->map[i])
|
||||
return set_disjoint;
|
||||
for (; i < s2->size / BITS; i++)
|
||||
if (s2->map[i])
|
||||
return set_disjoint;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
int
|
||||
set_is_disjoint (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
return set_test (s1, s2) == set_disjoint;
|
||||
}
|
||||
|
||||
int
|
||||
set_is_intersecting (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
return set_test (s1, s2) == set_intersecting;
|
||||
}
|
||||
|
||||
int
|
||||
set_is_equivalent (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
return set_test (s1, s2) == set_equiv;
|
||||
}
|
||||
|
||||
int
|
||||
set_is_subset (const set_t *set, const set_t *sub)
|
||||
{
|
||||
unsigned i, end;
|
||||
|
||||
end = min (set->size, sub->size) / BITS;
|
||||
for (i = 0; i < end; i++) {
|
||||
if (sub->map[i] & ~set->map[i])
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sub->size / BITS; i++)
|
||||
if (sub->map[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
Loading…
Reference in a new issue