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

1.1       root        1: /* str_list.c */
                      2: 
                      3: /* Functions to deal with NULL-terminated string lists */
                      4: 
1.1.1.2 ! root        5: /* $Id: str_list.c,v 1.37 2009/08/14 10:02:22 rswindell Exp $ */
1.1       root        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:  *                                                                                                                                                     *
1.1.1.2 ! root       11:  * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html         *
1.1       root       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: 
1.1.1.2 ! root       46: str_list_t strListInit(void)
1.1       root       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: 
1.1.1.2 ! root       66: int strListIndexOf(const str_list_t list, const char* str)
        !            67: {
        !            68:        size_t          i;
        !            69: 
        !            70:        if(list==NULL)
        !            71:                return -1;
        !            72: 
        !            73:        for(i=0; list[i]!=NULL; i++) {
        !            74:                if(list[i]==str)
        !            75:                        return i;
        !            76:        }
        !            77:        
        !            78:        return -1;
        !            79: }
        !            80: 
1.1       root       81: static char* str_list_append(str_list_t* list, char* str, size_t index)
                     82: {
                     83:        str_list_t lp;
                     84: 
                     85:        if((lp=(str_list_t)realloc(*list,sizeof(char*)*(index+2)))==NULL)
                     86:                return(NULL);
                     87: 
                     88:        *list=lp;
                     89:        lp[index++]=str;
                     90:        lp[index]=NULL; /* terminate list */
                     91: 
                     92:        return(str);
                     93: }
                     94: 
                     95: static char* str_list_insert(str_list_t* list, char* str, size_t index)
                     96: {
                     97:        size_t  i;
                     98:        size_t  count;
                     99:        str_list_t lp;
                    100: 
                    101:        count = strListCount(*list);
                    102:        if(index > count)       /* invalid index, do nothing */
                    103:                return(NULL);
                    104: 
                    105:        count++;
                    106:        if((lp=(str_list_t)realloc(*list,sizeof(char*)*(count+1)))==NULL)
                    107:                return(NULL);
                    108: 
                    109:        *list=lp;
                    110:        for(i=count; i>index; i--)
                    111:                lp[i]=lp[i-1];
                    112:        lp[index]=str;
                    113: 
                    114:        return(str);
                    115: }
                    116: 
                    117: char* strListRemove(str_list_t* list, size_t index)
                    118: {
                    119:        char*   str;
                    120:        size_t  i;
                    121:        size_t  count;
                    122:        str_list_t lp;
                    123: 
                    124:        count = strListCount(*list);
                    125: 
                    126:        if(index==STR_LIST_LAST_INDEX && count)
                    127:                index = count-1;
                    128: 
                    129:        if(index >= count)      /* invalid index, do nothing */
                    130:                return(NULL);
                    131: 
                    132:        count--;
                    133:        if((lp=(str_list_t)realloc(*list,sizeof(char*)*(count+1)))==NULL)
                    134:                return(NULL);
                    135: 
                    136:        *list=lp;
                    137:        str=lp[index];
                    138:        for(i=index; i<count; i++)
                    139:                lp[i]=lp[i+1];
                    140:        lp[count]=NULL;
                    141: 
                    142:        return(str);
                    143: }
                    144: 
                    145: BOOL strListDelete(str_list_t* list, size_t index)
                    146: {
                    147:        char*   str;
                    148: 
                    149:        if((str=strListRemove(list, index))==NULL)
                    150:                return(FALSE);
                    151: 
                    152:        free(str);
                    153: 
                    154:        return(TRUE);
                    155: }
                    156: 
                    157: char* strListReplace(const str_list_t list, size_t index, const char* str)
                    158: {
                    159:        char*   buf;
                    160:        size_t  count;
                    161: 
                    162:        if(str==NULL)
                    163:                return(NULL);
                    164: 
                    165:        count = strListCount(list);
                    166: 
                    167:        if(index==STR_LIST_LAST_INDEX && count)
                    168:                index = count-1;
                    169: 
                    170:        if(index >= count)      /* invalid index, do nothing */
                    171:                return(NULL);
                    172: 
                    173:        if((buf=(char*)realloc(list[index],strlen(str)+1))==NULL)
                    174:                return(NULL);
                    175: 
                    176:        list[index]=buf;
                    177:        strcpy(buf,str);
                    178: 
                    179:        return(buf);
                    180: }
                    181: 
                    182: BOOL strListSwap(const str_list_t list, size_t index1, size_t index2)
                    183: {
                    184:        char*   tmp;
                    185:        size_t  count;
                    186: 
                    187:        count = strListCount(list);
                    188: 
                    189:        if(index1==STR_LIST_LAST_INDEX && count)
                    190:                index1 = count-1;
                    191: 
                    192:        if(index2==STR_LIST_LAST_INDEX && count)
                    193:                index2 = count-1;
                    194: 
                    195:        if(index1 >= count || index2 >= count || index1 == index2)      
                    196:                return(FALSE);  /* invalid index, do nothing */
                    197: 
                    198:        tmp=list[index1];
                    199:        list[index1]=list[index2];
                    200:        list[index2]=tmp;
                    201: 
                    202:        return(TRUE);
                    203: }
                    204: 
                    205: char* strListAppend(str_list_t* list, const char* str, size_t index)
                    206: {
                    207:        char* buf;
                    208: 
                    209:        if(str==NULL)
                    210:                return(NULL);
                    211: 
                    212:        if((buf=strdup(str))==NULL)
                    213:                return(NULL);
                    214: 
                    215:        if(index==STR_LIST_LAST_INDEX)
                    216:                index=strListCount(*list);
                    217: 
                    218:        return(str_list_append(list,buf,index));
                    219: }
                    220: 
                    221: size_t strListAppendList(str_list_t* list, const str_list_t add_list)
                    222: {
                    223:        size_t  i;
                    224:        size_t  count;
                    225: 
                    226:        count=strListCount(*list);
                    227:        for(i=0; add_list[i]!=NULL; i++)
                    228:                strListAppend(list,add_list[i],count++);
                    229: 
                    230:        return(count);
                    231: }
                    232: 
                    233: char* strListInsert(str_list_t* list, const char* str, size_t index)
                    234: {
                    235:        char* buf;
                    236: 
                    237:        if(str==NULL)
                    238:                return(NULL);
                    239: 
                    240:        if((buf=strdup(str))==NULL)
                    241:                return(NULL);
                    242: 
                    243:        return(str_list_insert(list,buf,index));
                    244: }
                    245: 
                    246: size_t strListInsertList(str_list_t* list, const str_list_t add_list, size_t index)
                    247: {
                    248:        size_t  i;
                    249: 
                    250:        for(i=0; add_list[i]!=NULL; i++)
                    251:                if(strListInsert(list,add_list[i],index++)==NULL)
                    252:                        break;
                    253: 
                    254:        return(i);
                    255: }
                    256: 
                    257: str_list_t strListSplit(str_list_t* lp, char* str, const char* delimit)
                    258: {
                    259:        size_t  count;
                    260:        char*   token;
                    261:        char*   tmp;
                    262:        str_list_t      list;
                    263: 
                    264:        if(str==NULL || delimit==NULL)
                    265:                return(NULL);
                    266: 
                    267:        if(lp==NULL) {
                    268:                if((list = strListInit())==NULL)
                    269:                        return(NULL);
                    270:                lp=&list;
                    271:                count=0;
                    272:        } else
                    273:                count=strListCount(*lp);
                    274: 
                    275:        for(token = strtok_r(str, delimit, &tmp); token!=NULL; token=strtok_r(NULL, delimit, &tmp))
                    276:                if(strListAppend(lp, token, count++)==NULL)
                    277:                        break;
                    278: 
                    279:        return(*lp);
                    280: }
                    281: 
                    282: str_list_t strListSplitCopy(str_list_t* list, const char* str, const char* delimit)
                    283: {
                    284:        char*           buf;
                    285:        str_list_t      new_list;
                    286: 
                    287:        if(str==NULL || delimit==NULL)
                    288:                return(NULL);
                    289: 
                    290:        if((buf=strdup(str))==NULL)
                    291:                return(NULL);
                    292: 
                    293:        new_list=strListSplit(list,buf,delimit);
                    294: 
                    295:        free(buf);
                    296: 
                    297:        if(list!=NULL)
                    298:                *list = new_list;
                    299: 
                    300:        return(new_list);
                    301: }
                    302: 
1.1.1.2 ! root      303: size_t strListMerge(str_list_t* list, str_list_t add_list)
1.1       root      304: {
                    305:        size_t  i;
                    306:        size_t  count;
                    307: 
                    308:        count=strListCount(*list);
                    309:        for(i=0; add_list[i]!=NULL; i++)
                    310:                str_list_append(list,add_list[i],count++);
                    311: 
                    312:        return(i);
                    313: }
                    314: 
1.1.1.2 ! root      315: char* strListCombine(str_list_t list, char* buf, size_t maxlen, const char* delimit)
        !           316: {
        !           317:        size_t  i;
        !           318:        char*   end;
        !           319:        char*   ptr;
        !           320: 
        !           321:        if(list==NULL || maxlen<1)
        !           322:                return(NULL);
        !           323: 
        !           324:        if(buf==NULL)
        !           325:                if((buf=(char*)malloc(maxlen))==NULL)
        !           326:                        return(NULL);
        !           327: 
        !           328:        *buf=0;
        !           329:        end=buf+maxlen;
        !           330:        for(i=0, ptr=buf; list[i]!=NULL && buf<end; i++)
        !           331:                ptr += safe_snprintf(ptr, end-ptr, "%s%s", i ? delimit:"", list[i]);
        !           332: 
        !           333:        return(buf);
        !           334: }
        !           335: 
1.1       root      336: #if defined(_WIN32)
                    337:        #define QSORT_CALLBACK_TYPE     _cdecl
                    338: #else
                    339:        #define QSORT_CALLBACK_TYPE
                    340: #endif
                    341: 
                    342: static int QSORT_CALLBACK_TYPE strListCompareAlpha(const void *arg1, const void *arg2)
                    343: {
                    344:    return stricmp(*(char**)arg1, *(char**)arg2);
                    345: }
                    346: 
                    347: static int QSORT_CALLBACK_TYPE strListCompareAlphaReverse(const void *arg1, const void *arg2)
                    348: {
                    349:    return stricmp(*(char**)arg2, *(char**)arg1);
                    350: }
                    351: 
                    352: static int QSORT_CALLBACK_TYPE strListCompareAlphaCase(const void *arg1, const void *arg2)
                    353: {
                    354:    return strcmp(*(char**)arg1, *(char**)arg2);
                    355: }
                    356: 
                    357: static int QSORT_CALLBACK_TYPE strListCompareAlphaCaseReverse(const void *arg1, const void *arg2)
                    358: {
                    359:    return strcmp(*(char**)arg2, *(char**)arg1);
                    360: }
                    361: 
                    362: void strListSortAlpha(str_list_t list)
                    363: {
                    364:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlpha);
                    365: }
                    366: 
                    367: void strListSortAlphaReverse(str_list_t list)
                    368: {
                    369:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlphaReverse);
                    370: }
                    371: 
                    372: void strListSortAlphaCase(str_list_t list)
                    373: {
                    374:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlphaCase);
                    375: }
                    376: 
                    377: void strListSortAlphaCaseReverse(str_list_t list)
                    378: {
                    379:        qsort(list,strListCount(list),sizeof(char*),strListCompareAlphaCaseReverse);
                    380: }
                    381: 
                    382: void strListFreeStrings(str_list_t list)
                    383: {
                    384:        size_t i;
                    385: 
                    386:        FREE_LIST_ITEMS(list,i);
                    387: }
                    388: 
                    389: void strListFree(str_list_t* list)
                    390: {
                    391:        if(*list!=NULL) {
                    392:                strListFreeStrings(*list);
                    393:                FREE_AND_NULL(*list);
                    394:        }
                    395: }
                    396: 
                    397: static str_list_t str_list_read_file(FILE* fp, str_list_t* lp, size_t max_line_len)
                    398: {
                    399:        char*           buf=NULL;
                    400:        size_t          count;
                    401:        str_list_t      list;
                    402: 
                    403:        if(max_line_len<1)
                    404:                max_line_len=2048;
                    405: 
                    406:        if(lp==NULL) {
                    407:                if((list = strListInit())==NULL)
                    408:                        return(NULL);
                    409:                lp=&list;
                    410:        }
                    411: 
                    412:        if(fp!=NULL) {
                    413:                count=strListCount(*lp);
                    414:                while(!feof(fp)) {
                    415:                        if(buf==NULL && (buf=(char*)alloca(max_line_len+1))==NULL)
                    416:                                return(NULL);
                    417:                        
                    418:                        if(fgets(buf,max_line_len+1,fp)==NULL)
                    419:                                break;
                    420:                        strListAppend(lp, buf, count++);
                    421:                }
                    422:        }
                    423: 
                    424:        return(*lp);
                    425: }
                    426: 
                    427: size_t strListInsertFile(FILE* fp, str_list_t* lp, size_t index, size_t max_line_len)
                    428: {
                    429:        str_list_t      list;
                    430:        size_t          count;
                    431: 
                    432:        if((list=str_list_read_file(fp, NULL, max_line_len)) == NULL)
                    433:                return(0);
                    434: 
                    435:        count = strListInsertList(lp, list, index);
                    436: 
                    437:        strListFree(&list);
                    438: 
                    439:        return(count);
                    440: }
                    441: 
                    442: str_list_t strListReadFile(FILE* fp, str_list_t* lp, size_t max_line_len)
                    443: {
                    444:        return str_list_read_file(fp,lp,max_line_len);
                    445: }
                    446: 
                    447: size_t strListWriteFile(FILE* fp, const str_list_t list, const char* separator)
                    448: {
                    449:        size_t          i;
                    450: 
                    451:        if(list==NULL)
                    452:                return(0);
                    453: 
                    454:        for(i=0; list[i]!=NULL; i++) {
                    455:                if(fputs(list[i],fp)==EOF)
                    456:                        break;
                    457:                if(separator!=NULL && fputs(separator,fp)==EOF)
                    458:                        break;
                    459:        }
                    460:        
                    461:        return(i);
                    462: }
                    463: 
                    464: size_t strListBlockLength(char* block)
                    465: {
                    466:        char*   p=block;
                    467:        size_t  str_len;
                    468:        size_t  block_len=0;
                    469: 
                    470:        if(block==NULL)
                    471:                return(0);
                    472: 
                    473:        /* calculate total block length */
                    474:        while((str_len=strlen(p))!=0) {
                    475:                block_len+=(str_len + 1);
                    476:                p+=(str_len + 1);
                    477:        }
                    478:        /* block must be double-NULL terminated */
                    479:        if(!block_len)
                    480:                block_len=1;
                    481:        block_len++;
                    482: 
                    483:        return(block_len);
                    484: }
                    485: 
                    486: char* strListCopyBlock(char* block)
                    487: {
                    488:        char*   p;
                    489:        size_t  block_len;
                    490:        
                    491:        if((block_len=strListBlockLength(block))==0)
                    492:                return(NULL);
                    493: 
                    494:        if((p=(char*)malloc(block_len))==NULL)
                    495:                return(NULL);
                    496:        memcpy(p, block, block_len);
                    497:        return(p);
                    498: }
                    499: 
                    500: char* strListAppendBlock(char* block, str_list_t list)
                    501: {
                    502:        char*   p;
                    503:        size_t  str_len;
                    504:        size_t  block_len;      
                    505:        size_t  i;
                    506: 
                    507:        if((block_len=strListBlockLength(block))!=0)
                    508:                block_len--;    /* Over-write existing NULL terminator */
                    509: 
                    510:        for(i=0; list[i]!=NULL; i++) {
                    511:                str_len=strlen(list[i]);
                    512:                if(str_len==0)
                    513:                        continue;       /* can't include empty strings in block */
                    514:                if((p=(char*)realloc(block, block_len + str_len + 1))==NULL) {
                    515:                        FREE_AND_NULL(block);
                    516:                        return(block);
                    517:                }
                    518:                block=p;
                    519:                strcpy(block + block_len, list[i]);
                    520:                block_len += (str_len + 1);
                    521:        }
                    522: 
                    523:        /* block must be double-NULL terminated */
                    524:        if(!block_len)
                    525:                block_len=1;
                    526:        block_len++;
                    527:        if((p=(char*)realloc(block, block_len))==NULL) {
                    528:                FREE_AND_NULL(block);
                    529:                return(block);
                    530:        }
                    531:        block=p;
                    532:        memset(block + (block_len-2), 0, 2);
                    533: 
                    534:        return(block);
                    535: }
                    536: 
                    537: char* strListCreateBlock(str_list_t list)
                    538: {
                    539:        return(strListAppendBlock(NULL,list));
                    540: }
                    541: 
                    542: void strListFreeBlock(char* block)
                    543: {
                    544:        if(block!=NULL)
                    545:                free(block);    /* this must be done here for Windows-DLL reasons */
                    546: }

unix.superglobalmegacorp.com

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