File:  [ELWIX - Embedded LightWeight unIX -] / gpl / axl / src / axl_factory.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 8 07:09:12 2011 UTC (13 years, 1 month ago) by misho
Branches: axl, MAIN
CVS tags: HEAD, AXL0_6_7, AXL0_6_1
3th party - XML

    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>