~ubuntu-branches/ubuntu/dapper/malaga/dapper

« back to all changes in this revision

Viewing changes to source/pools.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Bushnell, BSG
  • Date: 2005-01-10 11:52:04 UTC
  • mfrom: (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050110115204-hpgncw5pb0m1t8i6
Tags: 6.13-5
debian/control (malaga-doc Recommends): Suggest gv as a
postscript-viewer instead of ghostview.  (Closes: #289701).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* This file is part of Malaga, a system for Natural Language Analysis.
2
 
 * Copyright (C) 1995-1999 Bjoern Beutel
3
 
 *
4
 
 * Bjoern Beutel
5
 
 * Universitaet Erlangen-Nuernberg
6
 
 * Abteilung fuer Computerlinguistik
7
 
 * Bismarckstrasse 12
8
 
 * D-91054 Erlangen
9
 
 * e-mail: malaga@linguistik.uni-erlangen.de 
10
 
 *
11
 
 * This program is free software; you can redistribute it and/or modify
12
 
 * it under the terms of the GNU General Public License as published by
13
 
 * the Free Software Foundation; either version 2 of the License, or
14
 
 * (at your option) any later version.
15
 
 *
16
 
 * This program is distributed in the hope that it will be useful,
17
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 
 * GNU General Public License for more details.
20
 
 *
21
 
 * You should have received a copy of the GNU General Public License
22
 
 * along with this program; if not, write to the Free Software
23
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
24
 
 
25
 
/* description ==============================================================*/
26
 
 
27
 
/* This module defines a new data type, "pool_t", for growing vectors of items 
28
 
 * of an arbitrary type.
29
 
 * A pool is a linked list of chunks which are of fixed size once allocated. */
30
 
 
31
 
/* includes =================================================================*/
32
 
 
33
 
#include <stdlib.h>
34
 
#include <stdio.h>
35
 
#include <string.h>
36
 
#include "basic.h"
37
 
#include "files.h"
38
 
 
39
 
#undef GLOBAL
40
 
#define GLOBAL
41
 
 
42
 
#include "pools.h"
43
 
 
44
 
/* constants ================================================================*/
45
 
 
46
 
#define MIN_CHUNK_SIZE 400
47
 
/* the minimum number of the data table in a chunk */
48
 
 
49
 
/* macros ===================================================================*/
50
 
 
51
 
#define CHUNK_DATA(chunk_ptr) ((u_byte_t *) ((chunk_ptr) + 1))
52
 
/* Use this macro to access the data in a chunk. */
53
 
 
54
 
/* types ====================================================================*/
55
 
 
56
 
typedef struct CHUNK_T
57
 
{
58
 
  int_t chunk_size; /* the maximum number of items in this chunk */
59
 
  int_t num_items; /* the actual number of items in this chunk */
60
 
  struct CHUNK_T *next; /* the next chunk in the pool */
61
 
  int_t pad; /* pad to the next 8-byte boundary */
62
 
  /* items follow here */
63
 
} chunk_t;
64
 
 
65
 
/* the pool implementation type
66
 
 * (use "new_pool" before you use any other functions on a pool variable) */
67
 
struct POOL_T
68
 
{
69
 
  int_t item_size; /* size of the items that are stored in this pool */
70
 
  int_t num_items; /* the overall number of items stored in this pool */
71
 
  int_t chunk_size; /* the size of new chunks */
72
 
  chunk_t *first_chunk; /* first chunk of this pool */
73
 
  chunk_t *current_chunk; /* the chunk where items will currently be stored
74
 
                           * (note this isn't necessarily the last chunk) */
75
 
};
76
 
 
77
 
/* functions ================================================================*/
78
 
 
79
 
GLOBAL pool_t new_pool (int_t item_size)
80
 
/* Create a new pool that records items of size <item_size>. */
81
 
{
82
 
  pool_t pool = new_mem (sizeof (struct POOL_T));
83
 
 
84
 
  pool->item_size = item_size;
85
 
  pool->num_items = 0;
86
 
  pool->chunk_size = MIN_CHUNK_SIZE / item_size;
87
 
  pool->first_chunk = NULL;
88
 
  pool->current_chunk = NULL;
89
 
 
90
 
  return pool;
91
 
}
92
 
 
93
 
/*---------------------------------------------------------------------------*/
94
 
 
95
 
GLOBAL void clear_pool (pool_t pool)
96
 
/* Clear <pool> (do not free any memory used by the pool). */
97
 
{
98
 
  chunk_t *current_chunk;
99
 
 
100
 
  for (current_chunk = pool->first_chunk; 
101
 
       current_chunk != NULL; 
102
 
       current_chunk = current_chunk->next)
103
 
    current_chunk->num_items = 0;
104
 
 
105
 
  pool->num_items = 0;
106
 
  pool->current_chunk = pool->first_chunk;
107
 
}
108
 
 
109
 
/*---------------------------------------------------------------------------*/
110
 
 
111
 
GLOBAL void *pool_to_vector (pool_t pool)
112
 
/* Return <pool> as a C vector (contiguous memory).
113
 
 * The vector can be freed with "free" after use. */
114
 
{
115
 
  void *vector = new_vector (pool->item_size, pool->num_items);
116
 
  u_byte_t *chunk; /* position where next chunk is to be copied */
117
 
  chunk_t *current_chunk;
118
 
  
119
 
  /* Collect all chunks in a new vector */
120
 
  chunk = (u_byte_t *) vector;
121
 
  for (current_chunk = pool->first_chunk; 
122
 
       current_chunk != NULL; 
123
 
       current_chunk = current_chunk->next) 
124
 
    {
125
 
      memcpy (chunk, CHUNK_DATA (current_chunk), 
126
 
              pool->item_size * current_chunk->num_items);
127
 
      chunk += pool->item_size * current_chunk->num_items;
128
 
      if (current_chunk == pool->current_chunk)
129
 
        /* Only chunks up to <pool_i>->current_chunk have items in them. */
130
 
        break;
131
 
    }
132
 
 
133
 
  return vector;
134
 
}
135
 
 
136
 
/*---------------------------------------------------------------------------*/
137
 
 
138
 
GLOBAL void write_pool (pool_t pool, FILE *stream, string_t file_name)
139
 
/* Write <pool> to <stream> (<file_name> is given for error messages). */
140
 
{
141
 
  chunk_t *current_chunk;
142
 
 
143
 
  /* Collect all chunks to the new vector. */
144
 
  for (current_chunk = pool->first_chunk; 
145
 
       current_chunk != NULL; 
146
 
       current_chunk = current_chunk->next)
147
 
  {
148
 
    write_vector (CHUNK_DATA (current_chunk), pool->item_size, 
149
 
                  current_chunk->num_items, stream, file_name);
150
 
    if (current_chunk == pool->current_chunk)
151
 
      /* Only chunks up to <pool_i>->current_chunk have items in them. */
152
 
      break;
153
 
  }
154
 
}
155
 
 
156
 
/*---------------------------------------------------------------------------*/
157
 
 
158
 
GLOBAL void *get_pool_space (pool_t pool, int_t num_items, int_t *index)
159
 
/* Get space for <num_items> contiguous items in pool <pool>,
160
 
 * return its address as the function's result and the index in *<index>,
161
 
 * if <index> != NULL. */
162
 
{
163
 
  void *new_ptr; /* pointer to the pool space */
164
 
  chunk_t **chunk_ptr; /* address of a chunk pointer */
165
 
 
166
 
  /* Find the first chunk that is big enough. */
167
 
  for (chunk_ptr = &pool->current_chunk;
168
 
       *chunk_ptr != NULL 
169
 
       && (*chunk_ptr)->num_items + num_items > (*chunk_ptr)->chunk_size;
170
 
       chunk_ptr = &(*chunk_ptr)->next)
171
 
  {
172
 
  }
173
 
 
174
 
  /* If we haven't found a chunk that fits, allocate a new one. */
175
 
  if (*chunk_ptr == NULL)
176
 
  {
177
 
    if (pool->chunk_size < num_items)
178
 
      pool->chunk_size = num_items;
179
 
    
180
 
    *chunk_ptr = new_mem (sizeof (chunk_t) 
181
 
                          + pool->item_size * pool->chunk_size);
182
 
    (*chunk_ptr)->chunk_size = pool->chunk_size;
183
 
    (*chunk_ptr)->num_items = 0;
184
 
    (*chunk_ptr)->next = NULL;
185
 
    
186
 
    /* If this is the first chunk allocated, save its address. */
187
 
    if (pool->first_chunk == NULL)
188
 
      pool->first_chunk = *chunk_ptr;
189
 
  }
190
 
  
191
 
  /* Remember address and index of current position in pool. */
192
 
  new_ptr = (void *) (CHUNK_DATA (*chunk_ptr) 
193
 
                      + pool->item_size * (*chunk_ptr)->num_items);
194
 
  if (index != NULL)
195
 
    *index = pool->num_items;
196
 
  
197
 
  /* Adjust indices. */
198
 
  (*chunk_ptr)->num_items += num_items;
199
 
  pool->num_items += num_items;
200
 
  
201
 
  pool->current_chunk = *chunk_ptr;
202
 
 
203
 
  return new_ptr;
204
 
}
205
 
 
206
 
/*---------------------------------------------------------------------------*/
207
 
 
208
 
GLOBAL int_t pool_items (pool_t pool)
209
 
/* Return the number of the items in <pool>. */
210
 
{
211
 
  return pool->num_items;
212
 
}
213
 
 
214
 
/*---------------------------------------------------------------------------*/
215
 
 
216
 
GLOBAL void *pool_item (pool_t pool, int_t index)
217
 
/* Return the address of item with <index> in pool <pool>,
218
 
 * or NULL if there is no such item. */
219
 
{
220
 
  chunk_t *chunk;
221
 
 
222
 
  if (index < 0 || index >= pool->num_items)
223
 
    return NULL;
224
 
 
225
 
  /* Find the right chunk. */
226
 
  chunk = pool->first_chunk;
227
 
  while (index >= chunk->num_items)
228
 
  {
229
 
    index -= chunk->num_items;
230
 
    chunk = chunk->next;
231
 
  }
232
 
 
233
 
  /* Return the address of the item. */
234
 
  return CHUNK_DATA (chunk) + pool->item_size * index;
235
 
}
236
 
 
237
 
/*---------------------------------------------------------------------------*/
238
 
 
239
 
GLOBAL int_t pool_index (pool_t pool, void *item)
240
 
/* Return the index of <item> in <pool>.
241
 
 * Report an error if <item> doesn't exist in <pool>. */
242
 
{
243
 
  int_t index;
244
 
  chunk_t *chunk;
245
 
  u_byte_t *item_i = (u_byte_t *) item;
246
 
 
247
 
  index = 0;
248
 
  for (chunk = pool->first_chunk; chunk != NULL; chunk = chunk->next)
249
 
  {
250
 
    if (item_i >= CHUNK_DATA (chunk) 
251
 
        && item_i < CHUNK_DATA (chunk) + pool->item_size * chunk->num_items)
252
 
      return index + (item_i - CHUNK_DATA (chunk)) / pool->item_size;
253
 
        
254
 
    index += chunk->num_items;
255
 
  }
256
 
  error ("item doesn't exist in chunk");
257
 
}
258
 
 
259
 
/*---------------------------------------------------------------------------*/
260
 
 
261
 
GLOBAL void *copy_to_pool (pool_t pool, 
262
 
                           void *ptr, 
263
 
                           int_t num_items, 
264
 
                           int_t *index)
265
 
/* Copy the vector *<ptr> of length <num_items> into <pool>.
266
 
 * The items of *<ptr> must be of same size as the items in <pool>.
267
 
 * Return the address of the copy as the function's result and the
268
 
 * index in *<index>, if <index> != NULL. */
269
 
{
270
 
  void *new_ptr = get_pool_space (pool, num_items, index);
271
 
 
272
 
  /* Copy the data into the pool. */
273
 
  memcpy (new_ptr, ptr, pool->item_size * num_items);
274
 
 
275
 
  return new_ptr;
276
 
}
277
 
 
278
 
/*---------------------------------------------------------------------------*/
279
 
 
280
 
GLOBAL string_t copy_string_to_pool (pool_t pool, 
281
 
                                     string_t string, 
282
 
                                     int_t *index)
283
 
/* Copy the string <string> into <pool>, which must be a string pool.
284
 
 * Return the copy of the string as the function's result as well as
285
 
 * its index in *<index>, if <index> != NULL. */
286
 
{
287
 
  return (string_t) (copy_to_pool (pool, (void *) string, 
288
 
                                   strlen (string) + 1, index));
289
 
}
290
 
 
291
 
/*---------------------------------------------------------------------------*/
292
 
 
293
 
GLOBAL void free_pool (pool_t *pool)
294
 
/* Free all memory used by <*pool>. */
295
 
{
296
 
  chunk_t *chunk, *next_chunk;
297
 
 
298
 
  if (*pool == NULL)
299
 
    return;
300
 
 
301
 
  /* Free all chunks of this pool. */
302
 
  for (chunk = (*pool)->first_chunk; chunk != NULL; chunk = next_chunk) 
303
 
  {
304
 
    next_chunk = chunk->next;
305
 
    free_mem (&chunk);
306
 
  }
307
 
 
308
 
  free_mem (pool);
309
 
}
310
 
 
311
 
/* end of file ==============================================================*/