From df42f5c0bc1a8757c1b66a92d3fb8faf9a000a87 Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Wed, 4 Aug 2004 09:41:39 +0000 Subject: [PATCH] Replaced csv_file.* and tab_file.* with combined dat_file.* with generic line-based (text) data file API. --- src/xpdev/{csv_file.c => dat_file.c} | 205 +++++++++++++++------------ src/xpdev/{csv_file.h => dat_file.h} | 39 ++++- src/xpdev/tab_file.c | 161 --------------------- src/xpdev/tab_file.h | 56 -------- 4 files changed, 145 insertions(+), 316 deletions(-) rename src/xpdev/{csv_file.c => dat_file.c} (63%) rename src/xpdev/{csv_file.h => dat_file.h} (59%) delete mode 100644 src/xpdev/tab_file.c delete mode 100644 src/xpdev/tab_file.h diff --git a/src/xpdev/csv_file.c b/src/xpdev/dat_file.c similarity index 63% rename from src/xpdev/csv_file.c rename to src/xpdev/dat_file.c index 26119e394b..0271fb088c 100644 --- a/src/xpdev/csv_file.c +++ b/src/xpdev/dat_file.c @@ -1,6 +1,6 @@ -/* csv_file.c */ +/* dat_file.c */ -/* Functions to deal with comma-separated value (CSV) files and lists */ +/* Functions that deal with line-based (text) data files and lists */ /* $Id$ */ @@ -35,12 +35,19 @@ * Note: If this box doesn't appear square, then you need to fix your tabs. * ****************************************************************************/ -#include "csv_file.h" +#include "dat_file.h" #include "genwrap.h" /* lastchar */ +#include "filewrap.h" /* chsize */ #include <stdlib.h> /* malloc */ #include <string.h> /* strdup */ -char* csvEncode(char* field) +#include "truncsp.c" /* truncsp() and truncnl() */ + +/***********************************/ +/* CSV (Comma Separated Value) API */ +/***********************************/ + +static char* csvEncode(char* field) { char* dst; char* src; @@ -80,7 +87,7 @@ char* csvEncode(char* field) return(buf); } -char* csvLine(str_list_t columns) +char* csvLineCreator(str_list_t columns) { char* str=NULL; char* p; @@ -108,35 +115,60 @@ char* csvLine(str_list_t columns) return(str); } -str_list_t csvCreate(str_list_t records[], str_list_t columns) +str_list_t csvLineParser(char* line) { char* p; + char* buf; + size_t count=0; str_list_t list; - size_t i; - size_t li=0; if((list=strListInit())==NULL) return(NULL); - if(columns!=NULL) { - p=csvLine(columns); - strListAppend(&list,p,li++); - free(p); + if((buf=strdup(line))==NULL) { + strListFree(&list); + return(NULL); } - - if(records!=NULL) - for(i=0;records[i]!=NULL;i++) { - p=csvLine(records[i]); - strListAppend(&list,p,li++); - free(p); - } + + truncsp(buf); + + for(p=strtok(buf,",");p;p=strtok(NULL,",")) + strListAppend(&list,p,count++); + + free(buf); return(list); } -#include "truncsp.c" +/*********************/ +/* Tab-Delimited API */ +/*********************/ -str_list_t csvParseLine(char* line) +char* tabLineCreator(str_list_t columns) +{ + char* str=NULL; + char* p; + size_t i,len; + + if(columns==NULL) + return(NULL); + + for(i=0;columns[i]!=NULL;i++) { + len=strlen(columns[i])*2; + if(str) + len+=strlen(str); + if((p=realloc(str,len))==NULL) + break; + str=p; + if(i) strcat(str,"\t"); + else *str=0; + strcat(str,columns[i]); + } + + return(str); +} + +str_list_t tabLineParser(char* line) { char* p; char* buf; @@ -151,7 +183,7 @@ str_list_t csvParseLine(char* line) return(NULL); } - for(p=strtok(buf,",");p;p=strtok(NULL,",")) + for(p=strtok(buf,"\t");p;p=strtok(NULL,"\t")) strListAppend(&list,p,count++); free(buf); @@ -159,9 +191,58 @@ str_list_t csvParseLine(char* line) return(list); } -str_list_t* csvParseList(str_list_t records, str_list_t* columns) +/* Generic API */ + +str_list_t dataCreateList(str_list_t records[], str_list_t columns, dataLineCreator_t lineCreator) +{ + char* p; + str_list_t list; + size_t i; + size_t li=0; + + if((list=strListInit())==NULL) + return(NULL); + + if(columns!=NULL) { + p=lineCreator(columns); + strListAppend(&list,p,li++); + free(p); + } + + if(records!=NULL) + for(i=0;records[i]!=NULL;i++) { + p=lineCreator(records[i]); + strListAppend(&list,p,li++); + free(p); + } + + return(list); +} + +BOOL dataWriteFile(FILE* fp, str_list_t records[], str_list_t columns, dataLineCreator_t lineCreator) +{ + size_t count,total; + str_list_t list; + + rewind(fp); + + if(chsize(fileno(fp),0)!=0) /* truncate */ + return(FALSE); + + if((list=dataCreateList(records,columns,lineCreator))==NULL) + return(FALSE); + + total = strListCount(list); + count = strListWriteFile(fp,list,"\n"); + strListFree(&list); + + return(count == total); +} + +str_list_t* dataParseList(str_list_t records, str_list_t* columns, dataLineParser_t lineParser) { - size_t i=0; + size_t ri=0; + size_t li=0; str_list_t* list; if(records==NULL) @@ -171,21 +252,19 @@ str_list_t* csvParseList(str_list_t records, str_list_t* columns) return(NULL); if(columns!=NULL) { - if((*columns=csvParseLine(records[i++]))==NULL) + if((*columns=lineParser(records[ri++]))==NULL) return(NULL); } - while(records[i]!=NULL) { - list[i]=csvParseLine(records[i]); - i++; - } + while(records[ri]!=NULL) + list[li++]=lineParser(records[ri++]); - list[i]=NULL; /* terminate */ + list[li]=NULL; /* terminate */ return(list); } -str_list_t* csvReadFile(FILE* fp, str_list_t* columns) +str_list_t* dataReadFile(FILE* fp, str_list_t* columns, dataLineParser_t lineParser) { str_list_t* records; str_list_t lines; @@ -196,71 +275,13 @@ str_list_t* csvReadFile(FILE* fp, str_list_t* columns) if((lines=strListReadFile(fp, NULL, 0))==NULL) return(NULL); - /* truncate white-space off end of strings */ + /* truncate line-feed chars off end of strings */ for(i=0; lines[i]!=NULL; i++) - truncsp(lines[i]); + truncnl(lines[i]); - records=csvParseList(lines,columns); + records=dataParseList(lines,columns,lineParser); strListFree(&lines); return(records); } - -#if 0 - -int main() -{ - char* columns[] = {"name", "rank", "serial number", NULL}; - str_list_t data[3]; - str_list_t list; - size_t i; - - data[0]=strListInit(); - strListPush(&data[0],"rob \"the stud\""); - strListPush(&data[0],"general"); - strListPush(&data[0],"549-71-1344"); - - data[1]=strListInit(); - strListPush(&data[1],"mark"); - strListPush(&data[1]," colonel"); - strListPush(&data[1],"x,xx"); - - data[2]=NULL; - - list=csvCreate(data, columns); - - for(i=0;list[i];i++) - printf("%s\n",list[i]); -} - -#elif 0 /* decode and display .csv file */ - -void main(int argc, char** argv) -{ - str_list_t* records; - str_list_t columns; - FILE* fp; - size_t i,j; - - if(argc<2) { - printf("usage: csv_file <file.csv>\n"); - exit(0); - } - - if((fp=fopen(argv[1],"r"))==NULL) { - printf("Error opening %s\n",argv[1]); - exit(0); - } - - if((records=csvReadFile(fp, &columns))==NULL) { - printf("Error reading %s\n",argv[1]); - exit(0); - } - - for(i=0;records[i];i++) - for(j=0;records[i][j];j++) - printf("%s[%d]=%s\n",columns[j],i,records[i][j]); -} - -#endif \ No newline at end of file diff --git a/src/xpdev/csv_file.h b/src/xpdev/dat_file.h similarity index 59% rename from src/xpdev/csv_file.h rename to src/xpdev/dat_file.h index 8bd697a8f9..6766eb7fc3 100644 --- a/src/xpdev/csv_file.h +++ b/src/xpdev/dat_file.h @@ -1,4 +1,4 @@ -/* csv_file.h */ +/* dat_file.h */ /* Functions to deal with comma-separated value (CSV) files and lists */ @@ -35,8 +35,8 @@ * Note: If this box doesn't appear square, then you need to fix your tabs. * ****************************************************************************/ -#ifndef _CSV_FILE_H -#define _CSV_FILE_H +#ifndef _DAT_FILE_H +#define _DAT_FILE_H #include "str_list.h" @@ -44,10 +44,35 @@ extern "C" { #endif -str_list_t csvCreateList(str_list_t records[], str_list_t columns /* optional */); -str_list_t csvParseLine(char* line); -str_list_t* csvParseList(str_list_t list, str_list_t* columns /* optional */); -str_list_t* csvReadFile(FILE* fp, str_list_t* columns /* optional */); +/***************/ +/* Generic API */ +/***************/ + +typedef str_list_t (*dataLineParser_t)(char*); +typedef char* (*dataLineCreator_t)(str_list_t); + +/* columns arguments are optional (may be NULL) */ +str_list_t* dataParseList(str_list_t list, str_list_t* columns, dataLineParser_t); +str_list_t* dataReadFile(FILE* fp, str_list_t* columns, dataLineParser_t); + +str_list_t dataCreateList(str_list_t records[], str_list_t columns, dataLineCreator_t); +BOOL dataWriteFile(FILE* fp, str_list_t records[], str_list_t columns, dataLineCreator_t); + +/* CSV (comma separated value) API */ +char* csvLineCreator(str_list_t); +str_list_t csvLineParser(char* line); +#define csvParseList(list,col) dataParseList(list,col,csvLineParser) +#define csvCreateList(rec,col) dataCreateList(rec,col,csvLineCreator) +#define csvReadFile(fp,col) dataReadFile(fp,col,csvLineParser) +#define csvWriteFile(fp,rec,col) dataWriteFile(fp,rec,col,csvLineCreator) + +/* Tab-delimited API */ +char* tabLineCreator(str_list_t); +str_list_t tabLineParser(char* line); +#define tabParseList(list,col) dataParseList(list,col,tabLineParser) +#define tabCreateList(rec,col) dataCreateList(rec,col,tabLineCreator) +#define tabReadFile(fp,col) dataReadFile(fp,col,tabLineParser) +#define tabWriteFile(fp,rec,col) dataWriteFile(fp,rec,col,tabLineCreator) #if defined(__cplusplus) } diff --git a/src/xpdev/tab_file.c b/src/xpdev/tab_file.c deleted file mode 100644 index 0880df1e07..0000000000 --- a/src/xpdev/tab_file.c +++ /dev/null @@ -1,161 +0,0 @@ -/* tab_file.c */ - -/* Functions to deal with tab-delimited files and lists */ - -/* $Id$ */ - -/**************************************************************************** - * @format.tab-size 4 (Plain Text/Source Code File Header) * - * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * - * * - * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public License * - * as published by the Free Software Foundation; either version 2 * - * of the License, or (at your option) any later version. * - * See the GNU Lesser General Public License for more details: lgpl.txt or * - * http://www.fsf.org/copyleft/lesser.html * - * * - * Anonymous FTP access to the most recent released source is available at * - * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * - * * - * Anonymous CVS access to the development source and modification history * - * is available at cvs.synchro.net:/cvsroot/sbbs, example: * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * - * (just hit return, no password is necessary) * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * - * * - * For Synchronet coding style and modification guidelines, see * - * http://www.synchro.net/source.html * - * * - * You are encouraged to submit any modifications (preferably in Unix diff * - * format) via e-mail to mods@synchro.net * - * * - * Note: If this box doesn't appear square, then you need to fix your tabs. * - ****************************************************************************/ - -#include "tab_file.h" -#include <stdlib.h> /* malloc */ - -char* tabLine(str_list_t columns) -{ - char* str=NULL; - char* p; - size_t i,len; - - if(columns==NULL) - return(NULL); - - for(i=0;columns[i]!=NULL;i++) { - len=strlen(columns[i])*2; - if(str) - len+=strlen(str); - if((p=realloc(str,len))==NULL) - break; - str=p; - if(i) strcat(str,"\t"); - else *str=0; - strcat(str,columns[i]); - } - - return(str); -} - -str_list_t tabCreateList(str_list_t records[], str_list_t columns) -{ - char* p; - str_list_t list; - size_t i; - size_t li=0; - - if((list=strListInit())==NULL) - return(NULL); - - if(columns!=NULL) { - p=tabLine(columns); - strListAppend(&list,p,li++); - free(p); - } - - if(records!=NULL) - for(i=0;records[i]!=NULL;i++) { - p=tabLine(records[i]); - strListAppend(&list,p,li++); - free(p); - } - - return(list); -} - -str_list_t tabParseLine(char* line) -{ - char* p; - char* buf; - size_t count=0; - str_list_t list; - - if((list=strListInit())==NULL) - return(NULL); - - if((buf=strdup(line))==NULL) { - strListFree(&list); - return(NULL); - } - - for(p=strtok(buf,"\t");p;p=strtok(NULL,"\t")) - strListAppend(&list,p,count++); - - free(buf); - - return(list); -} - -str_list_t* tabParseList(str_list_t records, str_list_t* columns) -{ - size_t i=0; - str_list_t* list; - - if(records==NULL) - return(NULL); - - if((list=(str_list_t*)malloc(sizeof(str_list_t*)*(strListCount(records)+1)))==NULL) - return(NULL); - - if(columns!=NULL) { - if((*columns=tabParseLine(records[i++]))==NULL) - return(NULL); - } - - while(records[i]!=NULL) { - list[i]=tabParseLine(records[i]); - i++; - } - - list[i]=NULL; /* terminate */ - - return(list); -} - -#include "truncsp.c" - -str_list_t* tabReadFile(FILE* fp, str_list_t* columns) -{ - str_list_t* records; - str_list_t lines; - size_t i; - - if((lines=strListReadFile(fp, NULL, 0))==NULL) - return(NULL); - - /* truncate new-line chars off end of strings */ - for(i=0; lines[i]!=NULL; i++) - truncnl(lines[i]); - - records=tabParseList(lines,columns); - - strListFree(&lines); - - return(records); -} - diff --git a/src/xpdev/tab_file.h b/src/xpdev/tab_file.h deleted file mode 100644 index 091afa6f95..0000000000 --- a/src/xpdev/tab_file.h +++ /dev/null @@ -1,56 +0,0 @@ -/* tab_file.h */ - -/* Functions to deal with tab-delimited files and lists */ - -/* $Id$ */ - -/**************************************************************************** - * @format.tab-size 4 (Plain Text/Source Code File Header) * - * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * - * * - * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public License * - * as published by the Free Software Foundation; either version 2 * - * of the License, or (at your option) any later version. * - * See the GNU Lesser General Public License for more details: lgpl.txt or * - * http://www.fsf.org/copyleft/lesser.html * - * * - * Anonymous FTP access to the most recent released source is available at * - * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * - * * - * Anonymous CVS access to the development source and modification history * - * is available at cvs.synchro.net:/cvsroot/sbbs, example: * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * - * (just hit return, no password is necessary) * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * - * * - * For Synchronet coding style and modification guidelines, see * - * http://www.synchro.net/source.html * - * * - * You are encouraged to submit any modifications (preferably in Unix diff * - * format) via e-mail to mods@synchro.net * - * * - * Note: If this box doesn't appear square, then you need to fix your tabs. * - ****************************************************************************/ - -#ifndef _TAB_FILE_H -#define _TAB_FILE_H - -#include "str_list.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -str_list_t tabCreateList(str_list_t records[], str_list_t columns /* optional */); -str_list_t tabParseLine(char* line); -str_list_t* tabParseList(str_list_t list, str_list_t* columns /* optional */); -str_list_t* tabReadFile(FILE* fp, str_list_t* columns /* optional */); - -#if defined(__cplusplus) -} -#endif - -#endif /* Don't add anything after this line */ -- GitLab