source: trunk/emx/src/emxomf/grow.c@ 2446

Last change on this file since 2446 was 492, checked in by bird, 22 years ago

#483: Added uppercasing strpool_add* variants.

  • Property cvs2svn:cvs-rev set to 1.4
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 9.2 KB
Line 
1/* grow.c -- Growing arrays, growing buffers and string pools
2 Copyright (c) 1993-1995 Eberhard Mattes
3
4This file is part of emx.
5
6emx is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emx is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emx; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22/* Growing arrays. Such an array consists of two parts: A struct grow
23 which is used in this module for controlling the object, and a
24 pointer (the `associated pointer') of the desired type to the
25 array. The associated pointer may change when calling one of the
26 functions of these module for the struct grow of that array.*/
27
28/* Growing buffers. A growing buffer is an array of bytes. There are
29 functions for putting various binary types into the buffer, while
30 enlarging the buffer as required. */
31
32/* String pool. A string pool contains null-terminated strings of
33 arbitrary length. There are no duplicate strings in a string
34 pool. */
35
36#include <stdlib.h>
37#include <string.h>
38#include <ctype.h>
39#include "defs.h"
40#include "grow.h"
41
42/* A program using this module has to define the following two
43 functions: */
44
45extern void *xrealloc (void *ptr, size_t n);
46extern void *xmalloc (size_t n);
47
48/* Initialize a growing array. G points to the struct grow used for
49 controlling the array, PTR is a pointer to the associated pointer
50 of the desired type -- that pointer is used for accessing the
51 array. SIZE is the size of one array element, INC is the number of
52 array elements to add when growing the array. The smaller SIZE is,
53 the bigger you should choose INC. */
54
55void grow_init (struct grow *g, void *ptr, size_t size, int inc)
56{
57 g->count = 0;
58 g->alloc = 0;
59 g->ptr = ptr;
60 g->size = size;
61 g->inc = inc;
62 *g->ptr = NULL;
63}
64
65
66/* Deallocate a growing array. Do not use the associated array
67 pointer after calling this function. */
68
69void grow_free (struct grow *g)
70{
71 if (g->ptr != NULL)
72 {
73 if (*g->ptr != NULL)
74 free (*g->ptr);
75 *g->ptr = NULL;
76 }
77 g->ptr = NULL;
78 g->count = 0;
79 g->alloc = 0;
80}
81
82
83/* Grow the growing array G to NEW_COUNT elements. If the array is
84 already big enough, nothing is done. Otherwise, the array is
85 enlarged by at least INC (of grow_init()) elements. The associated
86 array pointer may change. */
87
88void grow_to (struct grow *g, int new_count)
89{
90 if (new_count > g->alloc)
91 {
92 g->alloc += g->inc;
93 if (g->alloc < new_count)
94 g->alloc = new_count;
95 *g->ptr = xrealloc (*g->ptr, g->alloc * g->size);
96 }
97}
98
99
100/* Grow the growing array G to make it big enough for INC additional
101 elements. If the array is already big enough, nothing is done.
102 Otherwise, the array is enlarged by at least INC (of grow_init())
103 elements. The associated array pointer may change. */
104
105void grow_by (struct grow *g, int inc)
106{
107 grow_to (g, g->count + inc);
108}
109
110
111/* Initialize a growing buffer. B is a pointer to the buffer
112 descriptor. */
113
114void buffer_init (struct buffer *b)
115{
116 b->size = 0;
117 b->alloc = 0;
118 b->buf = NULL;
119}
120
121
122/* Deallocate a growing buffer. Do not use the buffer after calling
123 this function. */
124
125void buffer_free (struct buffer *b)
126{
127 if (b->buf != NULL)
128 {
129 free (b->buf);
130 b->buf = NULL;
131 }
132}
133
134
135/* Grow the buffer B by N bytes. The buffer size is always an
136 integral multiple of 512. The buffer may move in memory. */
137
138static void buffer_grow_by (struct buffer *b, size_t n)
139{
140 if (b->size + n > b->alloc)
141 {
142 n = (n | 0x1ff) + 1;
143 b->alloc += n;
144 b->buf = xrealloc (b->buf, b->alloc);
145 }
146}
147
148
149/* Append the 8-bit byte X to the buffer B. */
150
151void buffer_byte (struct buffer *b, byte x)
152{
153 buffer_grow_by (b, 1);
154 b->buf[b->size++] = x;
155}
156
157
158/* Append the 16-bit word X to the buffer B. The LSB comes first. */
159
160void buffer_word (struct buffer *b, word x)
161{
162 buffer_grow_by (b, 2);
163 b->buf[b->size++] = x & 0xff;
164 b->buf[b->size++] = (x >> 8) & 0xff;
165}
166
167
168/* Append the 32-bit word X to the buffer B. The LSB comes first. */
169
170void buffer_dword (struct buffer *b, dword x)
171{
172 buffer_grow_by (b, 4);
173 b->buf[b->size++] = x & 0xff;
174 b->buf[b->size++] = (x >> 8) & 0xff;
175 b->buf[b->size++] = (x >> 16) & 0xff;
176 b->buf[b->size++] = (x >> 24) & 0xff;
177}
178
179
180/* Append LEN bytes at MEM to the buffer B. */
181
182void buffer_mem (struct buffer *b, const void *mem, int len)
183{
184 buffer_grow_by (b, len);
185 memcpy (b->buf + b->size, mem, len);
186 b->size += len;
187}
188
189
190/* Append the string STR to the buffer B. The string is preceded by
191 its length (one byte). If the string length exceeds 255
192 characters, the string is truncated to 255 characters. */
193
194void buffer_nstr (struct buffer *b, const char *str)
195{
196 int len;
197
198 if (str == NULL)
199 buffer_byte (b, 0);
200 else
201 {
202 len = strlen (str);
203 if (len > 255)
204 len = 255;
205 buffer_byte (b, len);
206 buffer_mem (b, str, len);
207 }
208}
209
210
211/* Append the string STR to the buffer B. The string is preceded by
212 its length (one byte or two bytes). If the string length exceeds
213 32767 characters, the string is truncated to 32767 characters. */
214
215void buffer_enc (struct buffer *b, const char *str)
216{
217 size_t len;
218
219 len = strlen (str);
220 if (len > 0x7fff)
221 len = 0x7fff;
222 if (len <= 0x7f)
223 buffer_byte (b, len);
224 else
225 {
226 buffer_byte (b, (len >> 8) | 0x80);
227 buffer_byte (b, len & 0xff);
228 }
229 buffer_mem (b, str, len);
230}
231
232
233/* Patch the 16-bit word in the buffer B at offset INDEX to X. */
234
235void buffer_patch_word (struct buffer *b, int index, word x)
236{
237 b->buf[index+0] = x & 0xff;
238 b->buf[index+1] = (x >> 8) & 0xff;
239}
240
241
242/* The size of the string pool hash table. Should be prime. */
243
244#define STRPOOL_HASH_SIZE 211
245
246/* This structure holds one string. Note that the first character of
247 the string is part of this structure. */
248
249struct string
250{
251 struct string *next; /* Pointer to next string in same bucket */
252 char string[1]; /* The string */
253};
254
255/* A string pool consists of its hash table. */
256
257struct strpool
258{
259 struct string *table[STRPOOL_HASH_SIZE];
260};
261
262
263/* Create and return a new string pool. Initially, the string pool is
264 empty. */
265
266struct strpool *strpool_init (void)
267{
268 int i;
269 struct strpool *p;
270
271 p = xmalloc (sizeof (*p));
272 for (i = 0; i < STRPOOL_HASH_SIZE; ++i)
273 p->table[i] = NULL;
274 return p;
275}
276
277/* Destroy the string pool P. The hash table and the strings are
278 deallocated. */
279
280void strpool_free (struct strpool *p)
281{
282 struct string *v1, *v2;
283 int i;
284
285 for (i = 0; i < STRPOOL_HASH_SIZE; ++i)
286 for (v1 = p->table[i]; v1 != NULL; v1 = v2)
287 {
288 v2 = v1->next;
289 free (v1);
290 }
291 free (p);
292}
293
294
295/* Add the string S of LEN characters to the string pool P. The
296 string must not contain null characters. A pointer to a string of
297 the string pool is returned. If a string identical to S already
298 exists in the string pool, a pointer to that string is returned.
299 Otherwise, a new string entry is added to the string pool. */
300
301const char *strpool_addn (struct strpool *p, const char *s, int len)
302{
303 unsigned hash;
304 int i;
305 struct string *v;
306
307 hash = 0;
308 for (i = 0; i < len; ++i)
309 hash = hash * 65599 + s[i];
310 hash %= STRPOOL_HASH_SIZE;
311 for (v = p->table[hash]; v != NULL; v = v->next)
312 if (strlen (v->string) == len && memcmp (v->string, s, len) == 0)
313 return v->string;
314 v = xmalloc (sizeof (*v) + len);
315 memcpy (v->string, s, len);
316 v->string[len] = 0;
317 v->next = p->table[hash];
318 p->table[hash] = v;
319 return v->string;
320}
321
322
323/* Add the null-terminated string S to the string pool P. A pointer
324 to a string of the string pool is returned. If a string identical
325 to S already exists in the string pool, a pointer to that string is
326 returned. Otherwise, a new string entry is added to the string
327 pool. */
328
329const char *strpool_add (struct strpool *p, const char *s)
330{
331 if (s == NULL)
332 return NULL;
333 return strpool_addn (p, s, strlen (s));
334}
335
336/* Add the uppercased string S of LEN characters to the string pool P.
337 See strpool_addn for more details. */
338
339const char *strpool_addnu (struct strpool *p, const char *s, int len)
340{
341 unsigned hash;
342 int i;
343 struct string *v;
344
345 hash = 0;
346 for (i = 0; i < len; ++i)
347 hash = hash * 65599 + toupper(s[i]);
348 hash %= STRPOOL_HASH_SIZE;
349 for (v = p->table[hash]; v != NULL; v = v->next)
350 if (strlen (v->string) == len && memcmp (v->string, s, len) == 0)
351 return v->string;
352 v = xmalloc (sizeof (*v) + len);
353 memcpy (v->string, s, len);
354 v->string[len] = 0;
355 strupr(v->string);
356 v->next = p->table[hash];
357 p->table[hash] = v;
358 return v->string;
359}
360
361/* Add the null-terminated uppercased string S to the string pool P.
362 See strpool_add for more details. */
363
364const char *strpool_addu (struct strpool *p, const char *s)
365{
366 if (s == NULL)
367 return NULL;
368 return strpool_addnu (p, s, strlen (s));
369}
370
Note: See TracBrowser for help on using the repository browser.