TPCCLIB
Loading...
Searching...
No Matches
csv.c File Reference

CSV struct processing. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "tpccsv.h"

Go to the source code of this file.

Functions

void csvInit (CSV *csv)
 
void csvFree (CSV *csv)
 
int csvAllocate (CSV *csv, int nr)
 
int csvDuplicate (CSV *csv1, CSV *csv2)
 Make a duplicate of CSV structure.
 
int csvPutString (CSV *csv, const char *s, int newline)
 
int csvPutDouble (CSV *csv, double v, int newline, int tointl)
 
int csvPutInt (CSV *csv, int v, int newline)
 
int csvRowLength (CSV *csv, int row)
 
int csvSetDimensions (CSV *csv)
 
int csvIsRegular (CSV *csv)
 
int csvTrimRight (CSV *csv)
 
char * csvCell (CSV *csv, int row, int col)
 
int csvCellReplace (CSV *csv, int row, int col, const char *s)
 
int csvRemoveItem (CSV *csv, int i)
 
int csvRemoveEmptyRows (CSV *csv)
 
int csvRemoveComments (CSV *csv)
 
int csvReorg (CSV *d, TPCSTATUS *status)
 
int csvTranspose (CSV *csv)
 

Detailed Description

CSV struct processing.

Test
Update test function arguments.

Definition in file csv.c.

Function Documentation

◆ csvAllocate()

int csvAllocate ( CSV * csv,
int nr )

Allocate memory for list of field items for CSV data.

Any previous content is preserved.

Precondition
Before first use initialize the CSV struct with csvInit().
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
csvInit, csvFree, csvDuplicate, csvSetDimensions, csvList
Parameters
csvPointer to CSV.
nrNr of field items to add to the list.

Definition at line 58 of file csv.c.

63 {
64 if(csv==NULL) return TPCERROR_FAIL;
65 if(nr<1) return TPCERROR_OK;
66
67 /* If not allocated previously, then just allocate and thats it */
68 if(csv->_item_nr==0) {
69 csv->c=(CSV_item*)calloc(nr, sizeof(CSV_item));
70 if(csv->c==NULL) return TPCERROR_OUT_OF_MEMORY;
71 csv->_item_nr=nr;
72 return TPCERROR_OK;
73 }
74
75 /* How many unused places there are already? */
76 int unused=csv->_item_nr-csv->nr;
77 /* Check if enough memory is already allocated */
78 if(unused>=nr) return TPCERROR_OK;
79
80 /* Ok, we have to reallocate more memory for the list */
81 nr+=csv->nr;
82 CSV_item *new_list;
83 new_list=(CSV_item*)realloc(csv->c, nr*sizeof(CSV_item));
84 if(new_list==NULL) return TPCERROR_OUT_OF_MEMORY;
85 else csv->c=new_list;
86 /* Initiate the list */
87 for(int i=csv->_item_nr; i<nr; i++) {
88 csv->c[i].row=0; csv->c[i].col=0; csv->c[i].content=NULL;
89 }
90 csv->_item_nr=nr;
91 return TPCERROR_OK;
92}
int col
Definition tpccsv.h:28
int row
Definition tpccsv.h:26
char * content
Definition tpccsv.h:30
CSV_item * c
Definition tpccsv.h:38
int nr
Definition tpccsv.h:42
int _item_nr
Definition tpccsv.h:40
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.

Referenced by csvDuplicate(), csvPutString(), parWriteCSV(), and tacWriteCSV().

◆ csvCell()

char * csvCell ( CSV * csv,
int row,
int col )

Get the CVS field contents in specified row and column.

Returns
Returns pointer to the content string, or NULL if not found.
Author
Vesa Oikonen
See also
csvRead, csvSearchField, csvFindField, csvCellReplace, csvSetDimensions
Parameters
csvPointer to CSV.
rowCSV row index.
colCSV column index.

Definition at line 358 of file csv.c.

365 {
366 if(csv==NULL) return((char*)NULL);
367 for(int i=0; i<csv->nr; i++)
368 if(csv->c[i].row==row && csv->c[i].col==col)
369 return(csv->c[i].content);
370 return((char*)NULL);
371}

Referenced by csvDuplicate(), csvRemoveEmptyRows(), csvWrite(), parReadFIT(), parReadRES(), tacRead(), tacReadCarimasTxt(), tacReadInveonCSV(), tacReadMat(), tacReadQView(), tacReadSIF(), and tacReadSimple().

◆ csvCellReplace()

int csvCellReplace ( CSV * csv,
int row,
int col,
const char * s )

Replace the value of CVS field.

Returns
tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
csvRead, csvSearchField, csvCell, csvRemoveItem, csvTranspose
Parameters
csvPointer to CSV.
rowCSV row index.
colCSV column index.
sField string to add; can be empty ("" or NULL).

Definition at line 380 of file csv.c.

389 {
390 if(csv==NULL) return(TPCERROR_FAIL);
391 int ci=-1;
392 for(int i=0; i<csv->nr; i++) if(csv->c[i].row==row && csv->c[i].col==col) {ci=i; break;}
393 if(ci<0) return(TPCERROR_MISSING_DATA);
394 /* Delete the previous value */
395 free(csv->c[ci].content);
396 /* Save the new item */
397 if(s==NULL || *s=='\0') csv->c[ci].content=strdup("");
398 else csv->c[ci].content=strdup(s);
399 if(csv->c[ci].content==NULL) return(TPCERROR_OUT_OF_MEMORY);
400 return(TPCERROR_OK);
401}
char * strdup(const char *s)
Definition stringext.c:185
@ TPCERROR_MISSING_DATA
File contains missing values.

◆ csvDuplicate()

int csvDuplicate ( CSV * csv1,
CSV * csv2 )

Make a duplicate of CSV structure.

Previous contents are copied. In the duplicate the space is allocated for row_nr times col_nr cells.

See also
csvInit, csvAllocate, csvFree
Returns
Returns TPCERROR status (0 when successful).
Parameters
csv1Pointer to the source CSV.
csv2Pointer to the target CSV; must be initiated; any old contents are deleted.

Definition at line 102 of file csv.c.

107 {
108 if(csv1==NULL || csv2==NULL) return TPCERROR_FAIL;
109 if(csv1->nr<1 || csv1->_item_nr<csv1->nr || csv1->row_nr<1 || csv1->col_nr<1) return TPCERROR_NO_DATA;
110
111 /* Empty the duplicate */
112 csvFree(csv2);
113
114 /* Allocate memory for csv2 */
115 int ret=csvAllocate(csv2, csv1->row_nr*csv1->col_nr);
116 if(ret!=TPCERROR_OK) return(ret);
117 csv2->col_nr=csv1->col_nr;
118 csv2->row_nr=csv1->row_nr;
119 csv2->nr=csv2->col_nr*csv2->row_nr;
120
121 /* Copy the contents */
122 csv2->separator=csv1->separator;
123 int ni=0, fulln=0;
124 for(int ri=0; ri<csv2->row_nr; ri++)
125 for(int ci=0; ci<csv2->col_nr; ci++) {
126 csv2->c[ni].row=ri;
127 csv2->c[ni].col=ci;
128 char *cp=csvCell(csv1, ri, ci);
129 if(cp==NULL) csv2->c[ni].content=NULL; else {csv2->c[ni].content=strdup(cp); fulln++;}
130 ni++;
131 }
132 if(fulln<1) return TPCERROR_NO_DATA;
133 return TPCERROR_OK;
134}
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:358
int csvAllocate(CSV *csv, int nr)
Definition csv.c:58
void csvFree(CSV *csv)
Definition csv.c:38
int row_nr
Definition tpccsv.h:44
int col_nr
Definition tpccsv.h:46
char separator
Definition tpccsv.h:49
@ TPCERROR_NO_DATA
File contains no data.

◆ csvFree()

void csvFree ( CSV * csv)

Free memory allocated for CSV data. All contents are destroyed.

Precondition
Before first use initialize the CSV struct with csvInit().
Author
Vesa Oikonen
See also
csvInit, csvAllocate, csvWrite
Parameters
csvPointer to CSV.

Definition at line 38 of file csv.c.

41 {
42 if(csv==NULL) return;
43 for(int i=0; i<csv->_item_nr; i++) free(csv->c[i].content);
44 free(csv->c);
45 csvInit(csv);
46}
void csvInit(CSV *csv)
Definition csv.c:22

Referenced by csvDuplicate(), parRead(), parWriteCSV(), tacRead(), and tacWriteCSV().

◆ csvInit()

void csvInit ( CSV * csv)

Initiate the CSV struct before any use.

Author
Vesa Oikonen
See also
csvFree, csvAllocate, csvRead
Parameters
csvPointer to CSV.

Definition at line 22 of file csv.c.

25 {
26 if(csv==NULL) return;
27 csv->c=NULL; csv->_item_nr=csv->nr=csv->row_nr=csv->col_nr=0;
28 csv->separator='\t'; //(char)0;
29}

Referenced by csvFree(), parRead(), parWriteCSV(), tacFormatDetermine(), tacRead(), and tacWriteCSV().

◆ csvIsRegular()

int csvIsRegular ( CSV * csv)

Check whether CSV is regular, that is, each row contain the same number of columns.

Author
Vesa Oikonen
See also
csvTranspose, csvTrimRight, csvSetDimensions, csvRowLength, csvRead, csvDuplicate
Returns
Returns 1 if CSV is regular, 0 if not.
Parameters
csvPointer to CSV

Definition at line 292 of file csv.c.

295 {
296 if(csv==NULL) return(0);
297 if(csv->nr<2) return(1);
298 int i, r, n=0, m=0;
299 i=0; r=csv->c[i].row; m++;
300 for(i=1; i<csv->nr; i++) {
301 if(r==csv->c[i].row) {
302 m++;
303 continue;}
304 if(n>0 && m!=n) return(0);
305 r=csv->c[i].row; n=m; m=1;
306 }
307 if(n>0 && m!=n) return(0);
308 return(1);
309}

Referenced by tacRead(), tacReadMat(), and tacReadSimple().

◆ csvPutDouble()

int csvPutDouble ( CSV * csv,
double v,
int newline,
int tointl )

Add specified double value as string into CSV.

Returns
tpcerror (TPCERROR_OK when successful).
Precondition
Before first use initialize the CSV struct with csvInit().
Author
Vesa Oikonen
See also
csvInit, csvPutString, csvPutInt, csvPutLine
Parameters
csvPointer to initiated CSV; previous contents are not changed.
vDouble value to add; NaN is added as an empty field.
newlineNew line (1) or same line (0).
tointlConvert (1) or do not convert (0) commas to semicolons and dots to commas.

Definition at line 193 of file csv.c.

202 {
203 int ret;
204 if(isnan(v)) {
205 ret=csvPutString(csv, "", newline);
206 } else {
207 char s[128];
208 sprintf(s, "%g", v); if(tointl) strReplaceChar(s, '.', ',');
209 ret=csvPutString(csv, s, newline);
210 }
211 return ret;
212}
int csvPutString(CSV *csv, const char *s, int newline)
Definition csv.c:144
void strReplaceChar(char *s, char c1, char c2)
Definition stringext.c:134

Referenced by parWriteCSV(), and tacWriteCSV().

◆ csvPutInt()

int csvPutInt ( CSV * csv,
int v,
int newline )

Add specified integer value as string into CSV.

Returns
tpcerror (TPCERROR_OK when successful).
Precondition
Before first use initialize the CSV struct with csvInit().
Author
Vesa Oikonen
See also
csvInit, csvPutDouble, csvPutString, csvPutLine
Parameters
csvPointer to initiated CSV; previous contents are not changed
vInteger value to add; use csvPutString() to add an empty field
newlineNew line (1) or same line (0)

Definition at line 222 of file csv.c.

229 {
230 int ret;
231 char s[128];
232 sprintf(s, "%d", v);
233 ret=csvPutString(csv, s, newline);
234 return ret;
235}

Referenced by parWriteCSV().

◆ csvPutString()

int csvPutString ( CSV * csv,
const char * s,
int newline )

Add specified string to CSV.

Returns
tpcerror (TPCERROR_OK when successful).
Precondition
Before first use initialize the CSV struct with csvInit().
Author
Vesa Oikonen
See also
csvInit, csvPutDouble, csvPutInt, csvPutLine
Parameters
csvPointer to initiated CSV; previous contents are not changed.
sField string to add; can be empty ("" or NULL).
newlineNew line (1) or same line (0).

Definition at line 144 of file csv.c.

151 {
152 if(csv==NULL) return TPCERROR_FAIL;
153 /* Allocate memory, if needed, and if needed, then a bigger chunk */
154 int avail=csv->_item_nr-csv->nr;
155 if(avail<1) {
156 int ret=csvAllocate(csv, 10);
157 if(ret!=TPCERROR_OK) return ret;
158 }
159 /* Write the item */
160 if(s==NULL || *s=='\0') csv->c[csv->nr].content=strdup("");
161 else csv->c[csv->nr].content=strdup(s);
162 if(csv->c[csv->nr].content==NULL) return TPCERROR_OUT_OF_MEMORY;
163 /* Set the row and column number */
164 int r, c;
165 if(csv->nr==0) {r=c=0;}
166 else {
167 if(newline!=0) {
168 c=0;
169 r=csv->c[csv->nr-1].row+1;
170 } else {
171 c=csv->c[csv->nr-1].col+1;
172 r=csv->c[csv->nr-1].row;
173 }
174 }
175 csv->c[csv->nr].col=c; csv->c[csv->nr].row=r;
176 /* Update row_nr and max col nr, if necessary */
177 c++; r++;
178 if(c>csv->col_nr) csv->col_nr=c;
179 if(r>csv->row_nr) csv->row_nr=r;
180
181 csv->nr++;
182 return TPCERROR_OK;
183}

Referenced by csvPutDouble(), csvPutInt(), csvPutLine(), csvPutLineWithSpaces(), parWriteCSV(), tacReadSIF(), and tacWriteCSV().

◆ csvRemoveComments()

int csvRemoveComments ( CSV * csv)

Remove those cells from CSV structure whose contents start with '#'.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
csvIsRegular, csvRemoveEmptyRows
Parameters
csvPointer to CSV.

Definition at line 470 of file csv.c.

473 {
474 if(csv==NULL) return(TPCERROR_FAIL);
475 if(csv->nr<1) return(TPCERROR_NO_DATA);
476
477 int i=csv->nr-1;
478 while(i>=0) {
479 if(csv->c[i].content!=NULL && csv->c[i].content[0]=='#') csvRemoveItem(csv, i);
480 i--;
481 }
482 return(TPCERROR_OK);
483// return(csvRemoveEmptyRows(csv));
484}
int csvRemoveItem(CSV *csv, int i)
Definition csv.c:409

◆ csvRemoveEmptyRows()

int csvRemoveEmptyRows ( CSV * csv)

Remove empty rows from CSV. Rows that contain only empty cells or cells that start with '#' are considered empty.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
csvRemoveComments, csvIsRegular, csvDuplicate, csvCellReplace
Parameters
csvPointer to CSV.

Definition at line 434 of file csv.c.

437 {
438 if(csv==NULL) return TPCERROR_FAIL;
439 if(csv->nr<1 || csv->row_nr<1 || csv->col_nr<1) return TPCERROR_NO_DATA;
440
441 /* Check the rows */
442 int ri=csv->row_nr-1;
443 while(ri>=0) {
444 int n=0;
445 for(int ci=0; ci<csv->col_nr; ci++) {
446 char *cp=csvCell(csv, ri, ci); if(cp==NULL) continue;
447 if(*cp=='\0' || *cp=='#') continue;
448 n++;
449 }
450 if(n==0) { // this line is empty
451 int i=csv->nr-1;
452 while(i>=0) {
453 if(csv->c[i].row==ri) csvRemoveItem(csv, i);
454 i--;
455 }
456 for(i=0; i<csv->nr; i++) if(csv->c[i].row>ri) csv->c[i].row--;
457 csv->row_nr--;
458 }
459 ri--;
460 }
461 return(TPCERROR_OK);
462}

◆ csvRemoveItem()

int csvRemoveItem ( CSV * csv,
int i )

Remove item from CSV data structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
csvCellReplace, csvFree, csvDuplicate, csvRemoveEmptyRows
Parameters
csvPointer to CSV.
iIndex of item to delete.

Definition at line 409 of file csv.c.

414 {
415 if(csv==NULL || i<0) return TPCERROR_FAIL;
416 if(csv->nr<1 || i>=csv->nr) return TPCERROR_NO_DATA;
417 free(csv->c[i].content); csv->c[i].content=NULL;
418 for(int j=i+1; j<csv->nr; j++) {
419 csv->c[j-1].row=csv->c[j].row;
420 csv->c[j-1].col=csv->c[j].col;
421 csv->c[j-1].content=csv->c[j].content;
422 }
423 csv->nr--; csv->c[csv->nr].content=NULL;
424 return(TPCERROR_OK);
425}

Referenced by csvRemoveComments(), csvRemoveEmptyRows(), and csvTrimRight().

◆ csvReorg()

int csvReorg ( CSV * d,
TPCSTATUS * status )

Sort CSV data array by increasing row and column numbers.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
csvTranspose, csvList, csvAllocate, csvWrite
Parameters
dPointer to CSV structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 503 of file csv.c.

508 {
509 int verbose=0; if(status!=NULL) verbose=status->verbose;
510 if(verbose>0) printf("%s()\n", __func__);
511 /* Check that required data exists */
512 if(d==NULL || d->nr<1) {
513 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
514 return TPCERROR_NO_DATA;
515 }
516 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
517 if(d->nr<2) return TPCERROR_OK;
518 qsort(d->c, d->nr, sizeof(CSV_item), csvReorgQSort);
519 return TPCERROR_OK;
520}
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
int verbose
Verbose level, used by statusPrint() etc.

Referenced by csvTranspose(), and tacReadSIF().

◆ csvRowLength()

int csvRowLength ( CSV * csv,
int row )

Count the nr of columns on specified CSV row.

Author
Vesa Oikonen
See also
csvCell, csvRead, csvIsRegular, csvSetDimensions
Returns
The number of columns.
Parameters
csvPointer to CSV
rowCSV row index

Definition at line 244 of file csv.c.

249 {
250 if(csv==NULL) return(0);
251// int i, n=0;
252// for(i=0; i<csv->nr; i++) if(csv->c[i].row==row) n++;
253// return(n);
254 int n=-1;
255 for(int i=0; i<csv->nr; i++) if(csv->c[i].row==row && csv->c[i].col>n) n=csv->c[i].col;
256 return(1+n);
257}

Referenced by csvWrite(), parReadFIT(), parReadRES(), tacReadDFT(), tacReadSIF(), and tacReadSimple().

◆ csvSetDimensions()

int csvSetDimensions ( CSV * csv)

Set the number of rows and columns in CSV table, based on the row and column stored with each cell. CSV may not be regular, thus maximum row and column numbers are used.

Author
Vesa Oikonen
See also
csvIsRegular, csvRowLength, csvRead, csvRemoveComments
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
csvPointer to CSV structure.

Definition at line 269 of file csv.c.

272 {
273 if(csv==NULL) return TPCERROR_FAIL;
274 if(csv->nr<1) {csv->col_nr=0; csv->row_nr=0; return(TPCERROR_OK);}
275
276 int maxri=0, maxci=0;
277 for(int i=0; i<csv->nr; i++) {
278 if(csv->c[i].row>maxri) maxri=csv->c[i].row;
279 if(csv->c[i].col>maxci) maxci=csv->c[i].col;
280 }
281 csv->col_nr=1+maxci; csv->row_nr=1+maxri;
282 return(TPCERROR_OK);
283}

Referenced by csvTranspose().

◆ csvTranspose()

int csvTranspose ( CSV * csv)

Transpose data in CSV structure.

To work properly, CSV should not contain comment cells/lines.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
csvIsRegular, csvDuplicate, csvCellReplace, csvReorg, csvRmComments
Parameters
csvPointer to CSV.

Definition at line 530 of file csv.c.

533 {
534 if(csv==NULL) return(TPCERROR_FAIL);
535 if(csv->nr<1) return(TPCERROR_NO_DATA);
536
537 /* Get dimensions */
538 {
539 int ret=csvSetDimensions(csv);
540 if(ret!=TPCERROR_OK) return(ret);
541 }
542 if(csv->row_nr<1 || csv->col_nr<1) return(TPCERROR_NO_DATA);
543
544 /* If only one row and column, then nothing to do */
545 if(csv->row_nr==1 && csv->col_nr==1) return(TPCERROR_OK);
546
547 /* Switch column and row numbers */
548 for(int i=0; i<csv->nr; i++) {
549 int cr=csv->c[i].col;
550 csv->c[i].col=csv->c[i].row;
551 csv->c[i].row=cr;
552 }
553 {
554 int cn=csv->col_nr;
555 csv->col_nr=csv->row_nr;
556 csv->row_nr=cn;
557 }
558
559 /* Sort CSV data by rows and columns */
560 {
561 int ret=csvReorg(csv, NULL);
562 if(ret!=TPCERROR_OK) return(ret);
563 }
564
565 return(TPCERROR_OK);
566}
int csvSetDimensions(CSV *csv)
Definition csv.c:269
int csvReorg(CSV *d, TPCSTATUS *status)
Definition csv.c:503

◆ csvTrimRight()

int csvTrimRight ( CSV * csv)

Remove empty cells from the right side of CVS table until a non-empty column is reached.

Resulting CSV may still not be regular.

Author
Vesa Oikonen
See also
csvIsRegular, csvRowLength, csvRead, csvTranspose
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
csvPointer to CSV

Definition at line 321 of file csv.c.

324 {
325 if(csv==NULL) return TPCERROR_FAIL;
326 if(csv->nr<1 || csv->col_nr<2 || csv->row_nr<2) return TPCERROR_NO_DATA;
327
328 int ci=csv->col_nr-1;
329 while(ci>0) {
330 /* Does this column contain any data? */
331 int n=0;
332 for(int i=0; i<csv->nr; i++) if(csv->c[i].col==ci) {
333 if(csv->c[i].content!=NULL && csv->c[i].content[0]!='\0' && csv->c[i].content[0]!='#') n++;
334 }
335 if(n>0) break; // yes
336 /* No, so let's delete the last column */
337 int i=csv->nr-1;
338 while(i>=0) {
339 if(csv->c[i].col==ci) {
340 if(csvRemoveItem(csv, i)!=TPCERROR_OK) return TPCERROR_FAIL;
341 }
342 i--;
343 }
344 csv->col_nr--;
345 /* Try the previous column */
346 ci--;
347 }
348 return(TPCERROR_OK);
349}

Referenced by tacReadSimple().