* src/devices/grolbp/lbp.h, src/preproc/grn/gprint.h,
[s-roff.git] / src / include / ptable.h
blobdd31c0e39f778be188c0691bab46ed13a7076e69
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2003, 2004
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include <assert.h>
23 #include <string.h>
25 #ifdef TRADITIONAL_CPP
26 #define name2(a,b) a/**/b
27 #else /* not TRADITIONAL_CPP */
28 #define name2(a,b) name2x(a,b)
29 #define name2x(a,b) a ## b
30 #endif /* not TRADITIONAL_CPP */
32 #define PTABLE(T) name2(T,_ptable)
33 #define PASSOC(T) name2(T,_passoc)
34 #define PTABLE_ITERATOR(T) name2(T,_ptable_iterator)
36 extern unsigned next_ptable_size(unsigned);
37 extern unsigned long hash_string(const char *);
39 #define declare_ptable(T) \
41 struct PASSOC(T) { \
42 char *key; \
43 T *val; \
44 PASSOC(T)(); \
45 }; \
47 class PTABLE(T); \
49 class PTABLE_ITERATOR(T) { \
50 PTABLE(T) *p; \
51 unsigned i; \
52 public: \
53 PTABLE_ITERATOR(T)(PTABLE(T) *); \
54 int next(const char **, T **); \
55 }; \
57 class PTABLE(T) { \
58 PASSOC(T) *v; \
59 unsigned size; \
60 unsigned used; \
61 enum { FULL_NUM = 2, FULL_DEN = 3, INITIAL_SIZE = 17 }; \
62 public: \
63 PTABLE(T)(); \
64 ~PTABLE(T)(); \
65 void define(const char *, T *); \
66 T *lookup(const char *); \
67 friend class PTABLE_ITERATOR(T); \
71 // Keys (which are strings) are allocated and freed by PTABLE.
72 // Values must be allocated by the caller (always using new[], not new)
73 // and are freed by PTABLE.
75 #define implement_ptable(T) \
77 PASSOC(T)::PASSOC(T)() \
78 : key(0), val(0) \
79 { \
80 } \
82 PTABLE(T)::PTABLE(T)() \
83 { \
84 v = new PASSOC(T)[size = INITIAL_SIZE]; \
85 used = 0; \
86 } \
88 PTABLE(T)::~PTABLE(T)() \
89 { \
90 for (unsigned i = 0; i < size; i++) { \
91 a_delete v[i].key; \
92 a_delete v[i].val; \
93 } \
94 a_delete v; \
95 } \
97 void PTABLE(T)::define(const char *key, T *val) \
98 { \
99 assert(key != 0); \
100 unsigned long h = hash_string(key); \
101 unsigned n; \
102 for (n = unsigned(h % size); \
103 v[n].key != 0; \
104 n = (n == 0 ? size - 1 : n - 1)) \
105 if (strcmp(v[n].key, key) == 0) { \
106 a_delete v[n].val; \
107 v[n].val = val; \
108 return; \
110 if (val == 0) \
111 return; \
112 if (used*FULL_DEN >= size*FULL_NUM) { \
113 PASSOC(T) *oldv = v; \
114 unsigned old_size = size; \
115 size = next_ptable_size(size); \
116 v = new PASSOC(T)[size]; \
117 for (unsigned i = 0; i < old_size; i++) \
118 if (oldv[i].key != 0) { \
119 if (oldv[i].val == 0) \
120 a_delete oldv[i].key; \
121 else { \
122 unsigned j; \
123 for (j = unsigned(hash_string(oldv[i].key) % size); \
124 v[j].key != 0; \
125 j = (j == 0 ? size - 1 : j - 1)) \
127 v[j].key = oldv[i].key; \
128 v[j].val = oldv[i].val; \
131 for (n = unsigned(h % size); \
132 v[n].key != 0; \
133 n = (n == 0 ? size - 1 : n - 1)) \
135 a_delete oldv; \
137 char *temp = new char[strlen(key)+1]; \
138 strcpy(temp, key); \
139 v[n].key = temp; \
140 v[n].val = val; \
141 used++; \
144 T *PTABLE(T)::lookup(const char *key) \
146 assert(key != 0); \
147 for (unsigned n = unsigned(hash_string(key) % size); \
148 v[n].key != 0; \
149 n = (n == 0 ? size - 1 : n - 1)) \
150 if (strcmp(v[n].key, key) == 0) \
151 return v[n].val; \
152 return 0; \
155 PTABLE_ITERATOR(T)::PTABLE_ITERATOR(T)(PTABLE(T) *t) \
156 : p(t), i(0) \
160 int PTABLE_ITERATOR(T)::next(const char **keyp, T **valp) \
162 unsigned size = p->size; \
163 PASSOC(T) *v = p->v; \
164 for (; i < size; i++) \
165 if (v[i].key != 0) { \
166 *keyp = v[i].key; \
167 *valp = v[i].val; \
168 i++; \
169 return 1; \
171 return 0; \