2 /* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 1, or (at your option) any later
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file LICENSE. If not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
31 #define PTABLE(T) name2(T,_ptable)
32 #define PASSOC(T) name2(T,_passoc)
33 #define PTABLE_ITERATOR(T) name2(T,_ptable_iterator)
35 extern unsigned next_ptable_size(unsigned);
36 extern unsigned long hash_string(const char *);
38 #define declare_ptable(T) \
48 class PTABLE_ITERATOR(T) { \
52 PTABLE_ITERATOR(T)(PTABLE(T) *); \
53 int next(const char **, T **); \
60 enum { FULL_NUM = 2, FULL_DEN = 3, INITIAL_SIZE = 17 }; \
64 void define(const char *, T *); \
65 T *lookup(const char *); \
66 friend class PTABLE_ITERATOR(T); \
70 #define implement_ptable(T) \
72 PASSOC(T)::PASSOC(T)() \
77 PTABLE(T)::PTABLE(T)() \
79 v = new PASSOC(T)[size = INITIAL_SIZE]; \
83 PTABLE(T)::~PTABLE(T)() \
85 for (unsigned i = 0; i < size; i++) { \
91 void PTABLE(T)::define(const char *key, T *val) \
94 unsigned long h = hash_string(key); \
95 for (unsigned n = unsigned(h % size); \
97 n = (n == 0 ? size - 1 : n - 1)) \
98 if (strcmp(v[n].key, key) == 0) { \
105 if (used*FULL_DEN >= size*FULL_NUM) { \
106 PASSOC(T) *oldv = v; \
107 unsigned old_size = size; \
108 size = next_ptable_size(size); \
109 v = new PASSOC(T)[size]; \
110 for (unsigned i = 0; i < old_size; i++) \
111 if (oldv[i].key != 0) { \
112 if (oldv[i].val == 0) \
113 a_delete oldv[i].key; \
115 for (unsigned j = unsigned(hash_string(oldv[i].key) % size); \
117 j = (j == 0 ? size - 1 : j - 1)) \
119 v[j].key = oldv[i].key; \
120 v[j].val = oldv[i].val; \
123 for (n = unsigned(h % size); \
125 n = (n == 0 ? size - 1 : n - 1)) \
129 char *temp = new char[strlen(key)+1]; \
136 T *PTABLE(T)::lookup(const char *key) \
139 for (unsigned n = unsigned(hash_string(key) % size); \
141 n = (n == 0 ? size - 1 : n - 1)) \
142 if (strcmp(v[n].key, key) == 0) \
147 PTABLE_ITERATOR(T)::PTABLE_ITERATOR(T)(PTABLE(T) *t) \
152 int PTABLE_ITERATOR(T)::next(const char **keyp, T **valp) \
154 unsigned size = p->size; \
155 PASSOC(T) *v = p->v; \
156 for (; i < size; i++) \
157 if (v[i].key != 0) { \