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>