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>