Commit df42f5c0 authored by rswindell's avatar rswindell
Browse files

Replaced csv_file.* and tab_file.* with combined dat_file.* with generic

line-based (text) data file API.
parent c290acf7
/* 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
/* 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)
}
......
/* 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);
}
/* 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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment