Annotation of gpl/axl/src/axl_factory.c, revision 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>