Annotation of gpl/axl/src/axl_factory.c, revision 1.1.1.1
1.1 misho 1: /*
2: * LibAxl: Another XML library
3: * Copyright (C) 2006 Advanced Software Production Line, S.L.
4: *
5: * This program is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public License
7: * as published by the Free Software Foundation; either version 2.1 of
8: * the License, or (at your option) any later version.
9: *
10: * This program is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: * GNU Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this program; if not, write to the Free
17: * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18: * 02111-1307 USA
19: *
20: * You may find a copy of the license under this software is released
21: * at COPYING file. This is LGPL software: you are welcome to
22: * develop proprietary applications using this library without any
23: * royalty or fee but returning back any change, improvement or
24: * addition in the form of source code, project image, documentation
25: * patches, etc.
26: *
27: * For commercial support on build XML enabled solutions contact us:
28: *
29: * Postal address:
30: * Advanced Software Production Line, S.L.
31: * Edificio Alius A, Oficina 102,
32: * C/ Antonio Suarez Nº 10,
33: * Alcalá de Henares 28802 Madrid
34: * Spain
35: *
36: * Email address:
37: * info@aspl.es - http://www.aspl.es/xml
38: */
39: #include <axl.h>
40:
41: #define LOG_DOMAIN "axl-factory"
42:
43: typedef struct _axlItemBlock axlItemBlock;
44:
45: struct _axlItemBlock {
46: axlPointer items;
47: axlItemBlock * next;
48: };
49:
50: struct _axlFactory {
51: int count;
52: int step;
53: int type_size;
54:
55: int spare_max;
56: int spare_next;
57: axlPointer * spares;
58:
59: axlItemBlock * block;
60: };
61:
62: /**
63: * @internal Allows to create a new factory, for the provided
64: * type.
65: *
66: * This will cause the function to return an axlFactory with blocks
67: * initialized.
68: *
69: * @param type The type to initialize the factory created.
70: *
71: * @return A newly allocated factory.
72: */
73: axlFactory * axl_factory_create (int size_of_type)
74: {
75: axlFactory * result;
76:
77: result = axl_new (axlFactory, 1);
78: result->type_size = size_of_type;
79: result->step = 256 / size_of_type;
80:
81: /* create available block */
82: result->block = axl_new (axlItemBlock, 1);
83: result->block->items = axl_calloc (result->step, size_of_type);
84:
85: return result;
86:
87: } /* end axl_factory_create */
88:
89: /**
90: * @internal Function that allows to get a block from the factory.
91: *
92: * @param factory The factory that is being used to allocate more
93: * memory.
94: *
95: * @return A reference to newly allocated memory.
96: */
97: axlPointer axl_factory_get (axlFactory * factory)
98: {
99: axlItemBlock * block;
100: axlPointer result;
101:
102: /* check if we have spares available */
103: if (factory->spare_max > 0 && factory->spare_next >= 0) {
104: result = factory->spares[factory->spare_next];
105: factory->spare_next--;
106: return result;
107: } /* end if */
108:
109: /* update factory allocated elements */
110: factory->count++;
111:
112: if ((factory->count) > factory->step) {
113:
114: if (factory->step == (256 / factory->type_size))
115: factory->step = 512 / factory->type_size;
116: else if (factory->step == (512 / factory->type_size))
117: factory->step = 1024 / factory->type_size;
118: else if (factory->step == (1024 / factory->type_size))
119: factory->step = 2048 / factory->type_size;
120:
121: block = axl_new (axlItemBlock, 1);
122: block->items = axl_calloc (factory->step, factory->type_size);
123: factory->count = 1;
124:
125: block->next = factory->block;
126: factory->block = block;
127:
128: } /* end if */
129:
130: return ((char *)factory->block->items) + ((factory->count - 1) * factory->type_size);
131: } /* end if */
132:
133: void axl_factory_release_spare (axlFactory * factory, axlPointer node)
134: {
135: /* check if we have spare structure avaialble */
136: if (factory->spare_max == 0) {
137: /* basic case, where spares structure is not ready (no
138: * previous release done). We initialize and set
139: * maximum spare capacity to 1 and next spare pointer
140: * to retrieve on next axl_factory_get set to 0 */
141: factory->spares = axl_new (axlPointer, 10);
142: factory->spare_max = 9;
143: factory->spare_next = 0;
144: } else if (factory->spare_max > factory->spare_next) {
145: /* found that we have available spare pointer capacity
146: * and spare next is lower, so we don't need to
147: * allocate more memory to store current spares plus
148: * the gone being spared at this moment */
149: if (factory->spare_next == -1)
150: factory->spare_next = 0;
151: else {
152: factory->spare_next++;
153: } /* end if */
154: } else {
155: /* not enough to store spares, realloc and copy */
156: factory->spare_max += 10;
157: factory->spares = realloc (factory->spares, sizeof (axlPointer) * factory->spare_max);
158: factory->spare_max--;
159: factory->spare_next++;
160: }
161:
162: /* store node pointer */
163: factory->spares[factory->spare_next] = node;
164:
165: return;
166: }
167:
168: /**
169: * @brief Allows to get how many spare nodes can be stored (returned
170: * into the factory via axl_factory_release_spare).
171: *
172: * @param factory The factory where the spare value will be returned.
173: *
174: * @return The spare max or -1 if it fails.
175: */
176: int axl_factory_spare_max (axlFactory * factory)
177: {
178: if (factory == NULL)
179: return -1;
180: return factory->spare_max;
181: }
182:
183: /**
184: * @brief Allows to get how many spare nodes are stored (returned into
185: * the factory via axl_factory_release_spare). The value returned is
186: * the index to the next item to return, this means that having the
187: * index + 1 is the number of spares already stored.
188: *
189: * @param factory The factory where the next spare index value will be returned.
190: *
191: * @return The next spare index or -1 if it fails.
192: */
193: int axl_factory_spare_next (axlFactory * factory)
194: {
195: if (factory == NULL)
196: return -1;
197: return factory->spare_next;
198: }
199:
200: /**
201: * @internal Allows to deallocate the axlFactory created.
202: *
203: * @param factory
204: */
205: void axl_factory_free (axlFactory * factory)
206: {
207: axlItemBlock * block;
208: axlItemBlock * aux;
209:
210: /* do nothing if null received */
211: if (factory == NULL)
212: return;
213:
214: /* get the first block */
215: block = factory->block;
216: while (block != NULL) {
217:
218: /* get a reference to the next */
219: aux = block->next;
220:
221: /* free items and the block */
222: axl_free (block->items);
223: axl_free (block);
224:
225: /* get the next */
226: block = aux;
227:
228: } /* end while */
229:
230: axl_free (factory->spares);
231: axl_free (factory);
232:
233: return;
234: }
235:
236: typedef struct _axlStrBlock axlStrBlock;
237:
238: struct _axlStrBlock {
239: char * buffer;
240: axlStrBlock * next;
241: };
242:
243: struct _axlStrFactory {
244: int index;
245: int step;
246: int size;
247: axlStrBlock * block;
248: };
249:
250: /**
251: * @internal Allows to create an string factory, an abstraction that
252: * allows to allocate string chuncks in a memory efficient way,
253: * according to the Axl Library allocation pattern.
254: *
255: * @return A reference to the newly allocated axlStrFactory.
256: */
257: axlStrFactory * axl_string_factory_create (void)
258: {
259: axlStrFactory * factory;
260:
261: /* create a factory */
262: factory = axl_new (axlStrFactory, 1);
263: factory->step = 1024;
264: factory->size = 1024;
265: factory->block = axl_new (axlStrBlock, 1);
266: factory->block->buffer = axl_new (char, factory->size);
267:
268: /* return factory created */
269: return factory;
270: }
271:
272: /**
273: * @internal Allows to allocate a new chunk from the axlStrFactory.
274: *
275: * @param factory The factory that will be used to allocate an string.
276: *
277: * @param size The size to allocate. The amount of memory to allocate
278: * to hold the string.
279: *
280: * @return A pointer to allocated memory to hold the exact amount of
281: * memory requested.
282: */
283: char * axl_string_factory_alloc (axlStrFactory * factory, int size)
284: {
285: axlStrBlock * block;
286: char * result;
287:
288: /* check that we could satisfy the size request with current
289: * block */
290: if ((factory->size - factory->index - 1) < size ) {
291:
292: /* alloc a new block */
293: block = axl_new (axlStrBlock, 1);
294:
295: /* ensure the block can hold the string */
296: if (size > factory->size) {
297: block->buffer = axl_new (char, size + 1);
298: factory->size = size + 1;
299: } else {
300: /* store step allocation */
301: factory->size = factory->step;
302: block->buffer = axl_new (char, factory->size + 1);
303: }
304:
305: /* configure the new block */
306: block->next = factory->block;
307: factory->block = block;
308: factory->index = 0;
309: } /* end if */
310:
311: /* get current index available */
312: result = factory->block->buffer + factory->index;
313:
314: /* nullify to normalize string */
315: result [ size ] = 0;
316:
317: /* reserve size bytes */
318: factory->index += size + 1;
319:
320: return result;
321: }
322:
323: /**
324: * @internal Deallocs the axl stream factory and all chunks allocated.
325: *
326: * @param factory The factory to dealloc.
327: */
328: void axl_string_factory_free (axlStrFactory * factory)
329: {
330: axlStrBlock * block;
331: axlStrBlock * aux;
332:
333: /* do nothing if null received */
334: if (factory == NULL)
335: return;
336:
337: /* get the first block */
338: block = factory->block;
339:
340: while (block != NULL) {
341:
342: /* get a reference to the next */
343: aux = block->next;
344:
345: /* free items and the block */
346: axl_free (block->buffer);
347: axl_free (block);
348:
349: /* get the next */
350: block = aux;
351:
352: } /* end while */
353: axl_free (factory);
354:
355: return;
356: }
357:
358:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>