Annotation of sbbs/src/xpdev/str_list.c, revision 1.1.1.1

1.1       root        1: /* str_list.c */
                      2: 
                      3: /* Functions to deal with NULL-terminated string lists */
                      4: 
                      5: /* $Id: str_list.c,v 1.35 2006/08/14 22:55:48 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This library is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU Lesser General Public License          *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU Lesser General Public License for more details: lgpl.txt or     *
                     18:  * http://www.fsf.org/copyleft/lesser.html                                                                     *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include <stdlib.h>            /* malloc and qsort */
                     39: #include <string.h>            /* strtok */
                     40: #if defined(_WIN32)
                     41:  #include <malloc.h>    /* alloca() on Win32 */
                     42: #endif
                     43: #include "genwrap.h"   /* stricmp */
                     44: #include "str_list.h"
                     45: 
                     46: str_list_t strListInit()
                     47: {
                     48:        str_list_t list;
                     49: 
                     50:        if((list=(str_list_t)malloc(sizeof(char*)))==NULL)
                     51:                return(NULL);
                     52: 
                     53:        list[0]=NULL;   /* terminated by default */
                     54:        return(list);
                     55: }
                     56: 
                     57: size_t strListCount(const str_list_t list)
                     58: {
                     59:        size_t i;
                     60: 
                     61:        COUNT_LIST_ITEMS(list,i);
                     62: 
                     63:        return(i);
                     64: }
                     65: 
                     66: static char* str_list_append(str_list_t* list, char* str, size_t index)
                     67: {
                     68:        str_list_t lp;
                     69: 
                     70:        if((lp=(str_list_t)realloc(*list,sizeof(char*)*(index+2)))==NULL)
                     71:                return(NULL);
                     72: 
                     73:        *list=lp;
                     74:        lp[index++]=str;
                     75:        lp[index]=NULL; /* terminate list */
                     76: 
                     77:        return(str);
                     78: }
                     79: 
                     80: static char* str_list_insert(str_list_t* list, char* str, size_t index)
                     81: {
                     82:        size_t  i;
                     83:        size_t  count;
                     84:        str_list_t lp;
                     85: 
                     86:        count = strListCount(*list);
                     87:        if(index > count)       /* invalid index, do nothing */
                     88:                return(NULL);
                     89: 
                     90:        count++;
                     91:        if((lp=(str_list_t)realloc(*list,sizeof(char*)*(count+1)))==NULL)
                     92:                return(NULL);
                     93: 
                     94:        *list=lp;
                     95:        for(i=count; i>index; i--)
                     96:                lp[i]=lp[i-1];
                     97:        lp[index]=str;
                     98: 
                     99:        return(str);
                    100: }
                    101: 
                    102: char* strListRemove(str_list_t* list, size_t index)
                    103: {
                    104:        char*   str;
                    105:        size_t  i;
                    106:        size_t  count;
                    107:        str_list_t lp;
                    108: 
                    109:        count = strListCount(*list);
                    110: 
                    111:        if(index==STR_LIST_LAST_INDEX && count)
                    112:                index = count-1;
                    113: 
                    114:        if(index >= count)      /* invalid index, do nothing */
                    115:                return(NULL);
                    116: 
                    117:        count--;
                    118:        if((lp=(str_list_t)realloc(*list,sizeof(char*)*(count+1)))==NULL)
                    119:                return(NULL);
                    120: 
                    121:        *list=lp;
                    122:        str=lp[index];
                    123:        for(i=index; i<count; i++)
                    124:                lp[i]=lp[i+1];
                    125:        lp[count]=NULL;
                    126: 
                    127:        return(str);
                    128: }
                    129: 
                    130: BOOL strListDelete(str_list_t* list, size_t index)
                    131: {
                    132:        char*   str;
                    133: 
                    134:        if((str=strListRemove(list, index))==NULL)
                    135:                return(FALSE);
                    136: 
                    137:        free(str);
                    138: 
                    139:        return(TRUE);
                    140: }
                    141: 
                    142: char* strListReplace(const str_list_t list, size_t index, const char* str)
                    143: {
                    144:        char*   buf;
                    145:        size_t  count;
                    146: 
                    147:        if(str==NULL)
                    148:                return(NULL);
                    149: 
                    150:        count = strListCount(list);
                    151: 
                    152:        if(index==STR_LIST_LAST_INDEX && count)
                    153:                index = count-1;
                    154: 
                    155:        if(index >= count)      /* invalid index, do nothing */
                    156:                return(NULL);
                    157: 
                    158:        if((buf=(char*)realloc(list[index],strlen(str)+1))==NULL)
                    159:                return(NULL);
                    160: 
                    161:        list[index]=buf;
                    162:        strcpy(buf,str);
                    163: 
                    164:        return(buf);
                    165: }
                    166: 
                    167: BOOL strListSwap(const str_list_t list, size_t index1, size_t index2)
                    168: {
                    169:        char*   tmp;
                    170:        size_t  count;
                    171: 
                    172:        count = strListCount(list);
                    173: 
                    174:        if(index1==STR_LIST_LAST_INDEX && count)
                    175:                index1 = count-1;
                    176: 
                    177:        if(index2==STR_LIST_LAST_INDEX && count)
                    178:                index2 = count-1;
                    179: 
                    180:        if(index1 >= count || index2 >= count || index1 == index2)      
                    181:                return(FALSE);  /* invalid index, do nothing */
                    182: 
                    183:        tmp=list[index1];
                    184:        list[index1]=list[index2];
                    185:        list[index2]=tmp;
                    186: 
                    187:        return(TRUE);
                    188: }
                    189: 
                    190: char* strListAppend(str_list_t* list, const char* str, size_t index)
                    191: {
                    192:        char* buf;
                    193: 
                    194:        if(str==NULL)
                    195:                return(NULL);
                    196: 
                    197:        if((buf=strdup(str))==NULL)
                    198:                return(NULL);
                    199: 
                    200:        if(index==STR_LIST_LAST_INDEX)
                    201:                index=strListCount(*list);
                    202: 
                    203:        return(str_list_append(list,buf,index));
                    204: }
                    205: 
                    206: size_t strListAppendList(str_list_t* list, const str_list_t add_list)
                    207: {
                    208:        size_t  i;
                    209:        size_t  count;
                    210: 
                    211:        count=strListCount(*list);
                    212:        for(i=0; add_list[i]!=NULL; i++)
                    213:                strListAppend(list,add_list[i],count++);
                    214: 
                    215:        return(count);
                    216: }
                    217: 
                    218: char* strListInsert(str_list_t* list, const char* str, size_t index)
                    219: {
                    220:        char* buf;
                    221: 
                    222:        if(str==NULL)
                    223:                return(NULL);
                    224: 
                    225:        if((buf=strdup(str))==NULL)
                    226:                return(NULL);
                    227: 
                    228:        return(str_list_insert(list,buf,index));
                    229: }
                    230: 
                    231: size_t strListInsertList(str_list_t* list, const str_list_t add_list, size_t index)
                    232: {
                    233:        size_t  i;
                    234: 
                    235: 
                    236:        for(i=0; add_list[i]!=NULL; i++)
                    237:                if(strListInsert(list,add_list[i],index++)==NULL)
                    238:                        break;
                    239: 
                    240:        return(i);
                    241: }
                    242: 
                    243: str_list_t strListSplit(str_list_t* lp, char* str, const char* delimit)
                    244: {
                    245:        size_t  count;
                    246:        char*   token;
                    247:        char*   tmp;
                    248:        str_list_t      list;
                    249: 
                    250:        if(str==NULL || delimit==NULL)
                    251:                return(NULL);
                    252: 
                    253:        if(lp==NULL) {
                    254:                if((list = strListInit())==NULL)
                    255:                        return(NULL);
                    256:                lp=&list;
                    257:                count=0;
                    258:        } else
                    259:                count=strListCount(*lp);
                    260: 
                    261:        for(token = strtok_r(str, delimit, &tmp); token!=NULL; token=strtok_r(NULL, delimit, &tmp))
                    262:                if(strListAppend(lp, token, count++)==NULL)
                    263:                        break;
                    264: 
                    265:        return(*lp);
                    266: }
                    267: 
                    268: str_list_t strListSplitCopy(str_list_t* list, const char* str, const char* delimit)
                    269: {
                    270:        char*           buf;
                    271:        str_list_t      new_list;
                    272: 
                    273:        if(str==NULL || delimit==NULL)
                    274:                return(NULL);
                    275: 
                    276:        if((buf=strdup(str))==NULL)
                    277:                return(NULL);
                    278: 
                    279:        new_list=strListSplit(list,buf,delimit);
                    280: 
                    281:        free(buf);
                    282: 
                    283:        if(list!=NULL)
                    284:                *list = new_list;
                    285: 
                    286:        return(new_list);
                    287: }
                    288: 
                    289: size_t strListMerge(str_list_t* list, str_list_t add_list)
                    290: {
                    291:        size_t  i;
                    292:        size_t  count;
                    293: 
                    294:        count=strListCount(*list);
                    295:        for(i=0; add_list[i]!=NULL; i++)
                    296:                str_list_append(list,add_list[i],count++);
                    297: 
                    298:        return(i);
                    299: }
                    300: 
                    301: #if defined(_WIN32)
                    302:        #define QSORT_CALLBACK_TYPE     _cdecl
                    303: #else
                    304:        #define QSORT_CALLBACK_TYPE
                    305: #endif
                    306: 
                    307: static int QSORT_CALLBACK_TYPE strListCompareAlpha(const void *arg1, const void *arg2)
                    308: {
                    309:    return stricmp(*(char**)arg1, *(char**)arg2);
                    310: }
                    311: 
                    312: static int QSORT_CALLBACK_TYPE strListCompareAlphaReverse(const void *arg1, const void *arg2)
                    313: {
                    314:    return stricmp(*(char**)arg2, *(char**)arg1);
                    315: }
                    316: 
                    317: static int QSORT_CALLBACK_TYPE strListCompareAlphaCase(const void *arg1, const void *arg2)
                    318: {
                    319:    return strcmp(*(char**)arg1, *(char**)arg2);
                    320: }
                    321: 
                    322: static int QSORT_CALLBACK_TYPE strListCompareAlphaCaseReverse(const void *arg1, const void *arg2)
                    323: {
                    324:    return strcmp(*(char**)arg2, *(char**)arg1);
                    325: }
                    326: 
                    327: void strListSortAlpha(str_list_t list)
                    328: {
                    329:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlpha);
                    330: }
                    331: 
                    332: void strListSortAlphaReverse(str_list_t list)
                    333: {
                    334:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlphaReverse);
                    335: }
                    336: 
                    337: void strListSortAlphaCase(str_list_t list)
                    338: {
                    339:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlphaCase);
                    340: }
                    341: 
                    342: void strListSortAlphaCaseReverse(str_list_t list)
                    343: {
                    344:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlphaCaseReverse);
                    345: }
                    346: 
                    347: void strListFreeStrings(str_list_t list)
                    348: {
                    349:        size_t i;
                    350: 
                    351:        FREE_LIST_ITEMS(list,i);
                    352: }
                    353: 
                    354: void strListFree(str_list_t* list)
                    355: {
                    356:        if(*list!=NULL) {
                    357:                strListFreeStrings(*list);
                    358:                FREE_AND_NULL(*list);
                    359:        }
                    360: }
                    361: 
                    362: static str_list_t str_list_read_file(FILE* fp, str_list_t* lp, size_t max_line_len)
                    363: {
                    364:        char*           buf=NULL;
                    365:        size_t          count;
                    366:        str_list_t      list;
                    367: 
                    368:        if(max_line_len<1)
                    369:                max_line_len=2048;
                    370: 
                    371:        if(lp==NULL) {
                    372:                if((list = strListInit())==NULL)
                    373:                        return(NULL);
                    374:                lp=&list;
                    375:        }
                    376: 
                    377:        if(fp!=NULL) {
                    378:                count=strListCount(*lp);
                    379:                while(!feof(fp)) {
                    380:                        if(buf==NULL && (buf=(char*)alloca(max_line_len+1))==NULL)
                    381:                                return(NULL);
                    382:                        
                    383:                        if(fgets(buf,max_line_len+1,fp)==NULL)
                    384:                                break;
                    385:                        strListAppend(lp, buf, count++);
                    386:                }
                    387:        }
                    388: 
                    389:        return(*lp);
                    390: }
                    391: 
                    392: size_t strListInsertFile(FILE* fp, str_list_t* lp, size_t index, size_t max_line_len)
                    393: {
                    394:        str_list_t      list;
                    395:        size_t          count;
                    396: 
                    397:        if((list=str_list_read_file(fp, NULL, max_line_len)) == NULL)
                    398:                return(0);
                    399: 
                    400:        count = strListInsertList(lp, list, index);
                    401: 
                    402:        strListFree(&list);
                    403: 
                    404:        return(count);
                    405: }
                    406: 
                    407: str_list_t strListReadFile(FILE* fp, str_list_t* lp, size_t max_line_len)
                    408: {
                    409:        return str_list_read_file(fp,lp,max_line_len);
                    410: }
                    411: 
                    412: size_t strListWriteFile(FILE* fp, const str_list_t list, const char* separator)
                    413: {
                    414:        size_t          i;
                    415: 
                    416:        if(list==NULL)
                    417:                return(0);
                    418: 
                    419:        for(i=0; list[i]!=NULL; i++) {
                    420:                if(fputs(list[i],fp)==EOF)
                    421:                        break;
                    422:                if(separator!=NULL && fputs(separator,fp)==EOF)
                    423:                        break;
                    424:        }
                    425:        
                    426:        return(i);
                    427: }
                    428: 
                    429: size_t strListBlockLength(char* block)
                    430: {
                    431:        char*   p=block;
                    432:        size_t  str_len;
                    433:        size_t  block_len=0;
                    434: 
                    435:        if(block==NULL)
                    436:                return(0);
                    437: 
                    438:        /* calculate total block length */
                    439:        while((str_len=strlen(p))!=0) {
                    440:                block_len+=(str_len + 1);
                    441:                p+=(str_len + 1);
                    442:        }
                    443:        /* block must be double-NULL terminated */
                    444:        if(!block_len)
                    445:                block_len=1;
                    446:        block_len++;
                    447: 
                    448:        return(block_len);
                    449: }
                    450: 
                    451: char* strListCopyBlock(char* block)
                    452: {
                    453:        char*   p;
                    454:        size_t  block_len;
                    455:        
                    456:        if((block_len=strListBlockLength(block))==0)
                    457:                return(NULL);
                    458: 
                    459:        if((p=(char*)malloc(block_len))==NULL)
                    460:                return(NULL);
                    461:        memcpy(p, block, block_len);
                    462:        return(p);
                    463: }
                    464: 
                    465: char* strListAppendBlock(char* block, str_list_t list)
                    466: {
                    467:        char*   p;
                    468:        size_t  str_len;
                    469:        size_t  block_len;      
                    470:        size_t  i;
                    471: 
                    472:        if((block_len=strListBlockLength(block))!=0)
                    473:                block_len--;    /* Over-write existing NULL terminator */
                    474: 
                    475:        for(i=0; list[i]!=NULL; i++) {
                    476:                str_len=strlen(list[i]);
                    477:                if(str_len==0)
                    478:                        continue;       /* can't include empty strings in block */
                    479:                if((p=(char*)realloc(block, block_len + str_len + 1))==NULL) {
                    480:                        FREE_AND_NULL(block);
                    481:                        return(block);
                    482:                }
                    483:                block=p;
                    484:                strcpy(block + block_len, list[i]);
                    485:                block_len += (str_len + 1);
                    486:        }
                    487: 
                    488:        /* block must be double-NULL terminated */
                    489:        if(!block_len)
                    490:                block_len=1;
                    491:        block_len++;
                    492:        if((p=(char*)realloc(block, block_len))==NULL) {
                    493:                FREE_AND_NULL(block);
                    494:                return(block);
                    495:        }
                    496:        block=p;
                    497:        memset(block + (block_len-2), 0, 2);
                    498: 
                    499:        return(block);
                    500: }
                    501: 
                    502: char* strListCreateBlock(str_list_t list)
                    503: {
                    504:        return(strListAppendBlock(NULL,list));
                    505: }
                    506: 
                    507: void strListFreeBlock(char* block)
                    508: {
                    509:        if(block!=NULL)
                    510:                free(block);    /* this must be done here for Windows-DLL reasons */
                    511: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.