TPCCLIB
Toggle main menu visibility
Loading...
Searching...
No Matches
libtpccsv
csv.c
Go to the documentation of this file.
1
5
/*****************************************************************************/
6
#include "tpcclibConfig.h"
7
/*****************************************************************************/
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <math.h>
11
#include <time.h>
12
#include <string.h>
13
/*****************************************************************************/
14
#include "
tpccsv.h
"
15
/*****************************************************************************/
16
17
/*****************************************************************************/
22
void
csvInit
(
24
CSV
*csv
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
}
30
/*****************************************************************************/
31
32
/*****************************************************************************/
38
void
csvFree
(
40
CSV
*csv
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
}
47
/*****************************************************************************/
48
49
/*****************************************************************************/
58
int
csvAllocate
(
60
CSV
*csv,
62
int
nr
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
}
93
/*****************************************************************************/
94
95
/*****************************************************************************/
102
int
csvDuplicate
(
104
CSV
*csv1,
106
CSV
*csv2
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
}
135
/*****************************************************************************/
136
137
/*****************************************************************************/
144
int
csvPutString
(
146
CSV
*csv,
148
const
char
*s,
150
int
newline
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
}
184
/*****************************************************************************/
185
186
/*****************************************************************************/
193
int
csvPutDouble
(
195
CSV
*csv,
197
double
v,
199
int
newline,
201
int
tointl
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
}
213
/*****************************************************************************/
214
215
/*****************************************************************************/
222
int
csvPutInt
(
224
CSV
*csv,
226
int
v,
228
int
newline
229
) {
230
int
ret;
231
char
s[128];
232
sprintf(s,
"%d"
, v);
233
ret=
csvPutString
(csv, s, newline);
234
return
ret;
235
}
236
/*****************************************************************************/
237
238
/*****************************************************************************/
244
int
csvRowLength
(
246
CSV
*csv,
248
int
row
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
}
258
/*****************************************************************************/
259
260
/*****************************************************************************/
269
int
csvSetDimensions
(
271
CSV
*csv
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
}
284
/*****************************************************************************/
285
286
/*****************************************************************************/
292
int
csvIsRegular
(
294
CSV
*csv
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
}
310
/*****************************************************************************/
311
312
/*****************************************************************************/
321
int
csvTrimRight
(
323
CSV
*csv
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
}
350
/*****************************************************************************/
351
352
/*****************************************************************************/
358
char
*
csvCell
(
360
CSV
*csv,
362
int
row,
364
int
col
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
}
372
/*****************************************************************************/
373
374
/*****************************************************************************/
380
int
csvCellReplace
(
382
CSV
*csv,
384
int
row,
386
int
col,
388
const
char
*s
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
}
402
/*****************************************************************************/
403
404
/*****************************************************************************/
409
int
csvRemoveItem
(
411
CSV
*csv,
413
int
i
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
}
426
/*****************************************************************************/
427
428
/*****************************************************************************/
434
int
csvRemoveEmptyRows
(
436
CSV
*csv
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
}
463
/*****************************************************************************/
464
465
/*****************************************************************************/
470
int
csvRemoveComments
(
472
CSV
*csv
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
}
485
/*****************************************************************************/
486
487
/*****************************************************************************/
489
490
static
int
csvReorgQSort(
const
void
*c1,
const
void
*c2)
491
{
492
if
(((
CSV_item
*)c2)->row > ((
CSV_item
*)c1)->row)
return
(-1);
493
if
(((
CSV_item
*)c2)->row < ((
CSV_item
*)c1)->row)
return
(+1);
494
if
(((
CSV_item
*)c2)->col > ((
CSV_item
*)c1)->col)
return
(-1);
495
if
(((
CSV_item
*)c2)->col < ((
CSV_item
*)c1)->col)
return
(+1);
496
return
(0);
497
}
499
503
int
csvReorg
(
505
CSV
*d,
507
TPCSTATUS
*status
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
}
521
/*****************************************************************************/
522
523
/*****************************************************************************/
530
int
csvTranspose
(
532
CSV
*csv
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
}
567
/*****************************************************************************/
568
569
/*****************************************************************************/
csvInit
void csvInit(CSV *csv)
Definition
csv.c:22
csvIsRegular
int csvIsRegular(CSV *csv)
Definition
csv.c:292
csvPutInt
int csvPutInt(CSV *csv, int v, int newline)
Definition
csv.c:222
csvRemoveComments
int csvRemoveComments(CSV *csv)
Definition
csv.c:470
csvCell
char * csvCell(CSV *csv, int row, int col)
Definition
csv.c:358
csvAllocate
int csvAllocate(CSV *csv, int nr)
Definition
csv.c:58
csvCellReplace
int csvCellReplace(CSV *csv, int row, int col, const char *s)
Definition
csv.c:380
csvRemoveItem
int csvRemoveItem(CSV *csv, int i)
Definition
csv.c:409
csvSetDimensions
int csvSetDimensions(CSV *csv)
Definition
csv.c:269
csvTrimRight
int csvTrimRight(CSV *csv)
Definition
csv.c:321
csvDuplicate
int csvDuplicate(CSV *csv1, CSV *csv2)
Make a duplicate of CSV structure.
Definition
csv.c:102
csvTranspose
int csvTranspose(CSV *csv)
Definition
csv.c:530
csvPutString
int csvPutString(CSV *csv, const char *s, int newline)
Definition
csv.c:144
csvReorg
int csvReorg(CSV *d, TPCSTATUS *status)
Definition
csv.c:503
csvRowLength
int csvRowLength(CSV *csv, int row)
Definition
csv.c:244
csvRemoveEmptyRows
int csvRemoveEmptyRows(CSV *csv)
Definition
csv.c:434
csvPutDouble
int csvPutDouble(CSV *csv, double v, int newline, int tointl)
Definition
csv.c:193
csvFree
void csvFree(CSV *csv)
Definition
csv.c:38
statusSet
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition
statusmsg.c:142
strReplaceChar
void strReplaceChar(char *s, char c1, char c2)
Definition
stringext.c:134
CSV_item
Definition
tpccsv.h:24
CSV_item::col
int col
Definition
tpccsv.h:28
CSV_item::row
int row
Definition
tpccsv.h:26
CSV_item::content
char * content
Definition
tpccsv.h:30
CSV
Definition
tpccsv.h:36
CSV::row_nr
int row_nr
Definition
tpccsv.h:44
CSV::col_nr
int col_nr
Definition
tpccsv.h:46
CSV::separator
char separator
Definition
tpccsv.h:49
CSV::c
CSV_item * c
Definition
tpccsv.h:38
CSV::nr
int nr
Definition
tpccsv.h:42
CSV::_item_nr
int _item_nr
Definition
tpccsv.h:40
TPCSTATUS
Definition
tpcextensions.h:242
TPCSTATUS::verbose
int verbose
Verbose level, used by statusPrint() etc.
Definition
tpcextensions.h:243
tpccsv.h
Header file for library libtpccsv.
TPCERROR_FAIL
@ TPCERROR_FAIL
General error.
Definition
tpcextensions.h:193
TPCERROR_OUT_OF_MEMORY
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
Definition
tpcextensions.h:194
TPCERROR_OK
@ TPCERROR_OK
No error.
Definition
tpcextensions.h:192
TPCERROR_NO_DATA
@ TPCERROR_NO_DATA
File contains no data.
Definition
tpcextensions.h:204
TPCERROR_MISSING_DATA
@ TPCERROR_MISSING_DATA
File contains missing values.
Definition
tpcextensions.h:208
Generated on
for TPCCLIB by
1.18.0