source: vendor/emx/current/src/emxomf/grow.c

Last change on this file was 18, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 8.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 "defs.h"
39#include "grow.h"
40
41/* A program using this module has to define the following two
42 functions: */
43
44extern void *xrealloc (void *ptr, size_t n);
45extern void *xmalloc (size_t n);
46
47/* Initialize a growing array. G points to the struct grow used for
48 controlling the array, PTR is a pointer to the associated pointer
49 of the desired type -- that pointer is used for accessing the
50 array. SIZE is the size of one array element, INC is the number of
51 array elements to add when growing the array. The smaller SIZE is,
52 the bigger you should choose INC. */
53
54void grow_init (struct grow *g, void *ptr, size_t size, int inc)
55{
56 g->count = 0;
57 g->alloc = 0;
58 g->ptr = ptr;
59 g->size = size;
60 g->inc = inc;
61 *g->ptr = NULL;
62}
63
64
65/* Deallocate a growing array. Do not use the associated array
66 pointer after calling this function. */
67
68void grow_free (struct grow *g)
69{
70 if (g->ptr != NULL)
71 {
72 if (*g->ptr != NULL)
73 free (*g->ptr);
74 *g->ptr = NULL;
75 }
76 g->ptr = NULL;
77 g->count = 0;
78 g->alloc = 0;
79}
80
81
82/* Grow the growing array G to NEW_COUNT elements. If the array is
83 already big enough, nothing is done. Otherwise, the array is
84 enlarged by at least INC (of grow_init()) elements. The associated
85 array pointer may change. */
86
87void grow_to (struct grow *g, int new_count)
88{
89 if (new_count > g->alloc)
90 {
91 g->alloc += g->inc;
92 if (g->alloc < new_count)
93 g->alloc = new_count;
94 *g->ptr = xrealloc (*g->ptr, g->alloc * g->size);
95 }
96}
97
98
99/* Grow the growing array G to make it big enough for INC additional
100 elements. If the array is already big enough, nothing is done.
101 Otherwise, the array is enlarged by at least INC (of grow_init())
102 elements. The associated array pointer may change. */
103
104void grow_by (struct grow *g, int inc)
105{
106 grow_to (g, g->count + inc);
107}
108
109
110/* Initialize a growing buffer. B is a pointer to the buffer
111 descriptor. */
112
113void buffer_init (struct buffer *b)
114{
115 b->size = 0;
116 b->alloc = 0;
117 b->buf = NULL;
118}
119
120
121/* Deallocate a growing buffer. Do not use the buffer after calling
122 this function. */
123
124void buffer_free (struct buffer *b)
125{
126 if (b->buf != NULL)
127 {
128 free (b->buf);
129 b->buf = NULL;
130 }
131}
132
133
134/* Grow the buffer B by N bytes. The buffer size is always an
135 integral multiple of 512. The buffer may move in memory. */
136
137static void buffer_grow_by (struct buffer *b, size_t n)
138{
139 if (b->size + n > b->alloc)
140 {
141 n = (n | 0x1ff) + 1;
142 b->alloc += n;
143 b->buf = xrealloc (b->buf, b->alloc);
144 }
145}
146
147
148/* Append the 8-bit byte X to the buffer B. */
149
150void buffer_byte (struct buffer *b, byte x)
151{
152 buffer_grow_by (b, 1);
153 b->buf[b->size++] = x;
154}
155
156
157/* Append the 16-bit word X to the buffer B. The LSB comes first. */
158
159void buffer_word (struct buffer *b, word x)
160{
161 buffer_grow_by (b, 2);
162 b->buf[b->size++] = x & 0xff;
163 b->buf[b->size++] = (x >> 8) & 0xff;
164}
165
166
167/* Append the 32-bit word X to the buffer B. The LSB comes first. */
168
169void buffer_dword (struct buffer *b, dword x)
170{
171 buffer_grow_by (b, 4);
172 b->buf[b->size++] = x & 0xff;
173 b->buf[b->size++] = (x >> 8) & 0xff;
174 b->buf[b->size++] = (x >> 16) & 0xff;
175 b->buf[b->size++] = (x >> 24) & 0xff;
176}
177
178
179/* Append LEN bytes at MEM to the buffer B. */
180
181void buffer_mem (struct buffer *b, const void *mem, int len)
182{
183 buffer_grow_by (b, len);
184 memcpy (b->buf + b->size, mem, len);
185 b->size += len;
186}
187
188
189/* Append the string STR to the buffer B. The string is preceded by
190 its length (one byte). If the string length exceeds 255
191 characters, the string is truncated to 255 characters. */
192
193void buffer_nstr (struct buffer *b, const char *str)
194{
195 int len;
196
197 if (str == NULL)
198 buffer_byte (b, 0);
199 else
200 {
201 len = strlen (str);
202 if (len > 255)
203 len = 255;
204 buffer_byte (b, len);
205 buffer_mem (b, str, len);
206 }
207}
208
209
210/* Append the string STR to the buffer B. The string is preceded by
211 its length (one byte or two bytes). If the string length exceeds
212 32767 characters, the string is truncated to 32767 characters. */
213
214void buffer_enc (struct buffer *b, const char *str)
215{
216 size_t len;
217
218 len = strlen (str);
219 if (len > 0x7fff)
220 len = 0x7fff;
221 if (len <= 0x7f)
222 buffer_byte (b, len);
223 else
224 {
225 buffer_byte (b, (len >> 8) | 0x80);
226 buffer_byte (b, len & 0xff);
227 }
228 buffer_mem (b, str, len);
229}
230
231
232/* Patch the 16-bit word in the buffer B at offset INDEX to X. */
233
234void buffer_patch_word (struct buffer *b, int index, word x)
235{
236 b->buf[index+0] = x & 0xff;
237 b->buf[index+1] = (x >> 8) & 0xff;
238}
239
240
241/* The size of the string pool hash table. Should be prime. */
242
243#define STRPOOL_HASH_SIZE 211
244
245/* This structure holds one string. Note that the first character of
246 the string is part of this structure. */
247
248struct string
249{
250 struct string *next; /* Pointer to next string in same bucket */
251 char string[1]; /* The string */
252};
253
254/* A string pool consists of its hash table. */
255
256struct strpool
257{
258 struct string *table[STRPOOL_HASH_SIZE];
259};
260
261
262/* Create and return a new string pool. Initially, the string pool is
263 empty. */
264
265struct strpool *strpool_init (void)
266{
267 int i;
268 struct strpool *p;
269
270 p = xmalloc (sizeof (*p));
271 for (i = 0; i < STRPOOL_HASH_SIZE; ++i)
272 p->table[i] = NULL;
273 return p;
274}
275
276/* Destroy the string pool P. The hash table and the strings are
277 deallocated. */
278
279void strpool_free (struct strpool *p)
280{
281 struct string *v1, *v2;
282 int i;
283
284 for (i = 0; i < STRPOOL_HASH_SIZE; ++i)
285 for (v1 = p->table[i]; v1 != NULL; v1 = v2)
286 {
287 v2 = v1->next;
288 free (v1);
289 }
290 free (p);
291}
292
293
294/* Add the string S of LEN characters to the string pool P. The
295 string must not contain null characters. A pointer to a string of
296 the string pool is returned. If a string identical to S already
297 exists in the string pool, a pointer to that string is returned.
298 Otherwise, a new string entry is added to the string pool. */
299
300const char *strpool_addn (struct strpool *p, const char *s, int len)
301{
302 unsigned hash;
303 int i;
304 struct string *v;
305
306 hash = 0;
307 for (i = 0; i < len; ++i)
308 hash = hash * 65599 + s[i];
309 hash %= STRPOOL_HASH_SIZE;
310 for (v = p->table[hash]; v != NULL; v = v->next)
311 if (strlen (v->string) == len && memcmp (v->string, s, len) == 0)
312 return v->string;
313 v = xmalloc (sizeof (*v) + len);
314 memcpy (v->string, s, len);
315 v->string[len] = 0;
316 v->next = p->table[hash];
317 p->table[hash] = v;
318 return v->string;
319}
320
321
322/* Add the null-terminated string S to the string pool P. A pointer
323 to a string of the string pool is returned. If a string identical
324 to S already exists in the string pool, a pointer to that string is
325 returned. Otherwise, a new string entry is added to the string
326 pool. */
327
328const char *strpool_add (struct strpool *p, const char *s)
329{
330 if (s == NULL)
331 return NULL;
332 return strpool_addn (p, s, strlen (s));
333}
Note: See TracBrowser for help on using the repository browser.