Annotation of sbbs/xpdev/dat_file.c, revision 1.1

1.1     ! root        1: /* dat_file.c */
        !             2: 
        !             3: /* Functions that deal with line-based (text) data files and lists */
        !             4: 
        !             5: /* $Id: dat_file.c,v 1.2 2004/09/11 09:24:55 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 2004 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 "dat_file.h"
        !            39: #include "genwrap.h"   /* lastchar */
        !            40: #include "filewrap.h"  /* chsize */
        !            41: #include <stdlib.h>            /* malloc */
        !            42: #include <string.h>            /* strdup */
        !            43: 
        !            44: /***********************************/
        !            45: /* CSV (Comma Separated Value) API */
        !            46: /***********************************/
        !            47: 
        !            48: static char* csvEncode(char* field)
        !            49: {
        !            50:        char* dst;
        !            51:        char* src;
        !            52:        char* buf;
        !            53:        char* comma;
        !            54:        char* quote;
        !            55:        char  first;
        !            56:        char  last;
        !            57:        char* nl;
        !            58:        BOOL  enclose;
        !            59: 
        !            60:        if((buf=malloc(strlen(field)*2))==NULL)
        !            61:                return(NULL);
        !            62: 
        !            63:        nl=strchr(field,'\n');
        !            64:        comma=strchr(field,',');
        !            65:        quote=strchr(field,'"');
        !            66:        first=field[0];
        !            67:        last=*lastchar(field);
        !            68: 
        !            69:        enclose = (quote || comma || nl || first==' ' || last==' ');
        !            70: 
        !            71:        dst=buf;
        !            72:        if(enclose)
        !            73:                *(dst++)='"';
        !            74:        src=field;
        !            75:        while(*src) {
        !            76:                if(*src=='"')
        !            77:                        *(dst++)='"';   /* escape quotes */
        !            78:                *(dst++)=*src++;
        !            79:        }
        !            80:        if(enclose)
        !            81:                *(dst++)='"';
        !            82: 
        !            83:        *dst=0;
        !            84: 
        !            85:        return(buf);
        !            86: }
        !            87: 
        !            88: char* csvLineCreator(str_list_t columns)
        !            89: {
        !            90:        char*   str=NULL;
        !            91:        char*   p;
        !            92:        char*   val;
        !            93:        size_t  i,len;
        !            94: 
        !            95:        if(columns==NULL)
        !            96:                return(NULL);
        !            97: 
        !            98:        for(i=0;columns[i]!=NULL;i++) {
        !            99:                len=strlen(columns[i])*2;
        !           100:                if(str)
        !           101:                        len+=strlen(str);
        !           102:                if((p=realloc(str,len))==NULL)
        !           103:                        break;
        !           104:                str=p;
        !           105:                if(i) strcat(str,",");
        !           106:                else  *str=0;
        !           107:                if((val=csvEncode(columns[i]))==NULL)
        !           108:                        break;
        !           109:                strcat(str,val);
        !           110:                free(val);
        !           111:        }
        !           112: 
        !           113:        return(str);
        !           114: }
        !           115: 
        !           116: str_list_t csvLineParser(char* line)
        !           117: {
        !           118:        char*           p;
        !           119:        char*           buf;
        !           120:        size_t          count=0;
        !           121:        str_list_t      list;
        !           122: 
        !           123:        if((list=strListInit())==NULL)
        !           124:                return(NULL);
        !           125: 
        !           126:        if((buf=strdup(line))==NULL) {
        !           127:                strListFree(&list);
        !           128:                return(NULL);
        !           129:        }
        !           130: 
        !           131:        truncsp(buf);
        !           132: 
        !           133:        for(p=strtok(buf,",");p;p=strtok(NULL,","))
        !           134:                strListAppend(&list,p,count++);
        !           135: 
        !           136:        free(buf);
        !           137: 
        !           138:        return(list);
        !           139: }
        !           140: 
        !           141: /*********************/
        !           142: /* Tab-Delimited API */
        !           143: /*********************/
        !           144: 
        !           145: char* tabLineCreator(str_list_t columns)
        !           146: {
        !           147:        char*   str=NULL;
        !           148:        char*   p;
        !           149:        size_t  i,len;
        !           150: 
        !           151:        if(columns==NULL)
        !           152:                return(NULL);
        !           153: 
        !           154:        for(i=0;columns[i]!=NULL;i++) {
        !           155:                len=strlen(columns[i])*2;
        !           156:                if(str)
        !           157:                        len+=strlen(str);
        !           158:                if((p=realloc(str,len))==NULL)
        !           159:                        break;
        !           160:                str=p;
        !           161:                if(i) strcat(str,"\t");
        !           162:                else  *str=0;
        !           163:                strcat(str,columns[i]);
        !           164:        }
        !           165: 
        !           166:        return(str);
        !           167: }
        !           168: 
        !           169: str_list_t tabLineParser(char* line)
        !           170: {
        !           171:        char*           p;
        !           172:        char*           buf;
        !           173:        size_t          count=0;
        !           174:        str_list_t      list;
        !           175: 
        !           176:        if((list=strListInit())==NULL)
        !           177:                return(NULL);
        !           178: 
        !           179:        if((buf=strdup(line))==NULL) {
        !           180:                strListFree(&list);
        !           181:                return(NULL);
        !           182:        }
        !           183: 
        !           184:        for(p=strtok(buf,"\t");p;p=strtok(NULL,"\t"))
        !           185:                strListAppend(&list,p,count++);
        !           186: 
        !           187:        free(buf);
        !           188: 
        !           189:        return(list);
        !           190: }
        !           191: 
        !           192: /* Generic API */
        !           193: 
        !           194: str_list_t dataCreateList(str_list_t records[], str_list_t columns, dataLineCreator_t lineCreator)
        !           195: {
        !           196:        char*           p;
        !           197:        str_list_t      list;
        !           198:        size_t          i;
        !           199:        size_t          li=0;
        !           200: 
        !           201:        if((list=strListInit())==NULL)
        !           202:                return(NULL);
        !           203: 
        !           204:        if(columns!=NULL) {
        !           205:                p=lineCreator(columns);
        !           206:                strListAppend(&list,p,li++);
        !           207:                free(p);
        !           208:        }
        !           209:                
        !           210:        if(records!=NULL)
        !           211:                for(i=0;records[i]!=NULL;i++) {
        !           212:                        p=lineCreator(records[i]);
        !           213:                        strListAppend(&list,p,li++);
        !           214:                        free(p);
        !           215:                }
        !           216: 
        !           217:        return(list);
        !           218: }
        !           219: 
        !           220: BOOL dataWriteFile(FILE* fp, str_list_t records[], str_list_t columns, dataLineCreator_t lineCreator)
        !           221: {
        !           222:        size_t          count,total;
        !           223:        str_list_t      list;
        !           224: 
        !           225:        rewind(fp);
        !           226: 
        !           227:        if(chsize(fileno(fp),0)!=0)     /* truncate */
        !           228:                return(FALSE);
        !           229: 
        !           230:        if((list=dataCreateList(records,columns,lineCreator))==NULL)
        !           231:                return(FALSE);
        !           232: 
        !           233:        total = strListCount(list);
        !           234:        count = strListWriteFile(fp,list,"\n");
        !           235:        strListFree(&list);
        !           236: 
        !           237:        return(count == total);
        !           238: }
        !           239: 
        !           240: str_list_t* dataParseList(str_list_t records, str_list_t* columns, dataLineParser_t lineParser)
        !           241: {
        !           242:        size_t          ri=0;
        !           243:        size_t          li=0;
        !           244:        str_list_t* list;
        !           245: 
        !           246:        if(records==NULL)
        !           247:                return(NULL);
        !           248: 
        !           249:        if((list=(str_list_t*)malloc(sizeof(str_list_t*)*(strListCount(records)+1)))==NULL)
        !           250:                return(NULL);
        !           251: 
        !           252:        if(columns!=NULL) {
        !           253:                if((*columns=lineParser(records[ri++]))==NULL)
        !           254:                        return(NULL);
        !           255:        }
        !           256: 
        !           257:        while(records[ri]!=NULL)
        !           258:                list[li++]=lineParser(records[ri++]);
        !           259: 
        !           260:        list[li]=NULL; /* terminate */
        !           261: 
        !           262:        return(list);
        !           263: }
        !           264: 
        !           265: str_list_t*    dataReadFile(FILE* fp, str_list_t* columns, dataLineParser_t lineParser)
        !           266: {
        !           267:        str_list_t*     records;
        !           268:        str_list_t      lines;
        !           269:        size_t          i;
        !           270: 
        !           271:        rewind(fp);
        !           272: 
        !           273:        if((lines=strListReadFile(fp, NULL, 0))==NULL)
        !           274:                return(NULL);
        !           275: 
        !           276:        /* truncate line-feed chars off end of strings */
        !           277:        for(i=0; lines[i]!=NULL; i++)
        !           278:                truncnl(lines[i]);
        !           279: 
        !           280:        records=dataParseList(lines,columns,lineParser);
        !           281: 
        !           282:        strListFree(&lines);
        !           283: 
        !           284:        return(records);
        !           285: }

unix.superglobalmegacorp.com

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