]>
git.proxmox.com Git - mirror_frr.git/blob - lib/csv.c
14 #define log_error(fmt, ...) \
15 do { if (DEBUG_E) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
16 __LINE__, __func__, ##__VA_ARGS__); } while (0)
18 #define log_verbose(fmt, ...) \
19 do { if (DEBUG_V) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
20 __LINE__, __func__, __VA_ARGS__); } while (0)
22 struct _csv_field_t_
{
23 TAILQ_ENTRY(_csv_field_t_
) next_field
;
28 struct _csv_record_t_
{
29 TAILQ_HEAD(, _csv_field_t_
) fields
;
30 TAILQ_ENTRY(_csv_record_t_
) next_record
;
36 TAILQ_HEAD(, _csv_record_t_
) records
;
48 return (csv
->csv_len
);
57 csv
= malloc(sizeof(csv_t
));
59 log_error("CSV Malloc failed\n");
63 memset(csv
, 0, sizeof(csv_t
));
67 TAILQ_INIT(&(csv
->records
));
72 csv_clean (csv_t
*csv
)
77 rec
= TAILQ_FIRST(&(csv
->records
));
79 rec_n
= TAILQ_NEXT(rec
, next_record
);
80 csv_remove_record(csv
, rec
);
94 csv_init_record (csv_record_t
*record
)
96 TAILQ_INIT(&(record
->fields
));
101 csv_record_iter (csv_t
*csv
)
103 return(TAILQ_FIRST(&(csv
->records
)));
107 csv_record_iter_next (csv_record_t
*rec
)
109 if(!rec
) return NULL
;
110 return(TAILQ_NEXT(rec
, next_record
));
114 csv_field_iter (csv_record_t
*rec
,
117 if(!rec
) return NULL
;
118 *fld
= TAILQ_FIRST(&(rec
->fields
));
119 return ((*fld
)->field
);
123 csv_field_iter_next (csv_field_t
**fld
)
125 *fld
= TAILQ_NEXT(*fld
, next_field
);
126 if ((*fld
) == NULL
) {
129 return ((*fld
)->field
);
133 csv_field_len(csv_field_t
*fld
)
136 return fld
->field_len
;
142 csv_decode_record(csv_record_t
*rec
)
144 char *curr
= rec
->record
;
148 field
= strpbrk(curr
, ",");
149 while (field
!= NULL
) {
150 fld
= malloc(sizeof(csv_field_t
));
152 TAILQ_INSERT_TAIL(&(rec
->fields
), fld
, next_field
);
154 fld
->field_len
= field
-curr
;
157 field
= strpbrk(curr
, ",");
159 field
= strstr(curr
, "\n");
160 fld
= malloc(sizeof(csv_field_t
));
163 fld
->field_len
= field
-curr
;
164 TAILQ_INSERT_TAIL(&(rec
->fields
), fld
, next_field
);
169 csv_add_field_to_record(csv_t
*csv
,
174 char *str
= rec
->record
;
175 int rlen
= rec
->rec_len
;
176 int blen
= csv
->buflen
;
178 fld
= malloc(sizeof(csv_field_t
));
180 log_error("field malloc failed\n");
181 /* more cleanup needed */
184 TAILQ_INSERT_TAIL(&(rec
->fields
), fld
, next_field
);
185 fld
->field
= str
+rlen
;
186 fld
->field_len
= snprintf((str
+rlen
), (blen
- rlen
), "%s", col
);
187 rlen
+= fld
->field_len
;
193 csv_encode (csv_t
*csv
,
199 char *buf
= csv
->buf
;
200 int len
= csv
->buflen
;
201 int pointer
= csv
->pointer
;
210 /* allocate sufficient buffer */
211 str
= (char *)malloc(csv
->buflen
);
213 log_error("field str malloc failed\n");
218 va_start(list
, count
);
219 rec
= malloc(sizeof(csv_record_t
));
221 log_error("record malloc failed\n");
224 csv_init_record(rec
);
226 TAILQ_INSERT_TAIL(&(csv
->records
), rec
, next_record
);
230 * Iterate through the fields passed as a variable list and add them
232 for (tempc
= 0; tempc
< count
; tempc
++) {
233 col
= va_arg(list
, char *);
234 fld
= csv_add_field_to_record(csv
, rec
, col
);
236 log_error("fld malloc failed\n");
237 csv_remove_record(csv
, rec
);
240 if (tempc
< (count
- 1)) {
241 rec
->rec_len
+= snprintf((str
+rec
->rec_len
), (len
- rec
->rec_len
), ",");
244 rec
->rec_len
+= snprintf((str
+rec
->rec_len
), (len
- rec
->rec_len
), "\n");
246 csv
->csv_len
+= rec
->rec_len
;
247 csv
->pointer
+= rec
->rec_len
;
252 csv_num_records (csv_t
*csv
)
255 return csv
->num_recs
;
261 csv_encode_record (csv_t
*csv
,
270 csv_field_t
*fld
= NULL
;
273 va_start(list
, count
);
274 str
= csv_field_iter(rec
, &fld
);
275 for (tempc
= 0; tempc
< count
; tempc
++) {
276 col
= va_arg(list
, char *);
277 for (i
= 0; i
< fld
->field_len
; i
++) {
280 str
= csv_field_iter_next(&fld
);
287 csv_append_record (csv_t
*csv
,
294 int len
= csv
->buflen
, tlen
;
300 /* not only works with discrete bufs */
305 /* create a new rec */
306 rec
= calloc(1, sizeof(csv_record_t
));
308 log_error("record malloc failed\n");
311 csv_init_record(rec
);
312 rec
->record
= calloc(1, csv
->buflen
);
314 log_error("field str malloc failed\n");
318 csv_insert_record(csv
, rec
);
323 va_start(list
, count
);
325 if (rec
->rec_len
&& (str
[rec
->rec_len
-1] == '\n'))
326 str
[rec
->rec_len
-1] = ',';
329 * Iterate through the fields passed as a variable list and add them
332 for (tempc
= 0; tempc
< count
; tempc
++) {
333 col
= va_arg(list
, char *);
334 fld
= csv_add_field_to_record(csv
, rec
, col
);
336 log_error("fld malloc failed\n");
339 if (tempc
< (count
- 1)) {
340 rec
->rec_len
+= snprintf((str
+rec
->rec_len
),
341 (len
- rec
->rec_len
), ",");
344 rec
->rec_len
+= snprintf((str
+rec
->rec_len
),
345 (len
- rec
->rec_len
), "\n");
347 csv
->csv_len
+= (rec
->rec_len
- tlen
);
348 csv
->pointer
+= (rec
->rec_len
- tlen
);
353 csv_serialize(csv_t
*csv
, char *msgbuf
, int msglen
)
358 if (!csv
|| !msgbuf
) return -1;
360 rec
= csv_record_iter(csv
);
361 while (rec
!= NULL
) {
362 if ((offset
+ rec
->rec_len
) >= msglen
)
364 offset
+= sprintf(&msgbuf
[offset
], "%s", rec
->record
);
365 rec
= csv_record_iter_next(rec
);
372 csv_clone_record (csv_t
*csv
, csv_record_t
*in_rec
, csv_record_t
**out_rec
)
377 /* first check if rec belongs to this csv */
378 if(!csv_is_record_valid(csv
, in_rec
)){
379 log_error("rec not in this csv\n");
383 /* only works with csv with discrete bufs */
385 log_error("un-supported for this csv type - single buf detected\n");
389 /* create a new rec */
390 rec
= calloc(1, sizeof(csv_record_t
));
392 log_error("record malloc failed\n");
395 csv_init_record(rec
);
396 curr
= calloc(1, csv
->buflen
);
398 log_error("field str malloc failed\n");
402 rec
->rec_len
= in_rec
->rec_len
;
403 strcpy(rec
->record
, in_rec
->record
);
405 /* decode record into fields */
406 csv_decode_record(rec
);
412 csv_remove_record (csv_t
*csv
, csv_record_t
*rec
)
414 csv_field_t
*fld
, *p_fld
;
416 /* first check if rec belongs to this csv */
417 if(!csv_is_record_valid(csv
, rec
)){
418 log_error("rec not in this csv\n");
423 csv_field_iter(rec
, &fld
);
426 csv_field_iter_next(&fld
);
427 TAILQ_REMOVE(&(rec
->fields
), p_fld
, next_field
);
431 TAILQ_REMOVE(&(csv
->records
), rec
, next_record
);
434 csv
->csv_len
-= rec
->rec_len
;
435 csv
->pointer
-= rec
->rec_len
;
442 csv_insert_record (csv_t
*csv
, csv_record_t
*rec
)
444 /* first check if rec already in csv */
445 if(csv_is_record_valid(csv
, rec
)){
446 log_error("rec already in this csv\n");
450 /* we can only insert records if no buf was supplied during csv init */
452 log_error("un-supported for this csv type - single buf detected\n");
456 /* do we go beyond the max buf set for this csv ?*/
457 if ((csv
->csv_len
+ rec
->rec_len
) > csv
->buflen
) {
458 log_error("cannot insert - exceeded buf size\n");
462 TAILQ_INSERT_TAIL(&(csv
->records
), rec
, next_record
);
464 csv
->csv_len
+= rec
->rec_len
;
465 csv
->pointer
+= rec
->rec_len
;
469 csv_concat_record (csv_t
*csv
,
477 /* first check if rec1 and rec2 belong to this csv */
478 if(!csv_is_record_valid(csv
, rec1
) ||
479 !csv_is_record_valid(csv
, rec2
)) {
480 log_error("rec1 and/or rec2 invalid\n");
484 /* we can only concat records if no buf was supplied during csv init */
486 log_error("un-supported for this csv type - single buf detected\n");
490 /* create a new rec */
491 rec
= calloc(1, sizeof(csv_record_t
));
493 log_error("record malloc failed\n");
496 csv_init_record(rec
);
498 curr
= (char *)calloc(1, csv
->buflen
);
500 log_error("field str malloc failed\n");
505 /* concat the record string */
506 ret
= strstr(rec1
->record
, "\n");
508 log_error("rec1 str not properly formatted\n");
512 snprintf(curr
, (int)(ret
- rec1
->record
+ 1), "%s", rec1
->record
);
515 ret
= strstr(rec2
->record
, "\n");
517 log_error("rec2 str not properly formatted\n");
521 snprintf((curr
+strlen(curr
)), (int)(ret
- rec2
->record
+ 1), "%s",
524 rec
->rec_len
= strlen(curr
);
528 (csv
->csv_len
- rec1
->rec_len
- rec2
->rec_len
+ rec
->rec_len
));
530 /* decode record into fields */
531 csv_decode_record(rec
);
533 /* now remove rec1 and rec2 and insert rec into this csv */
534 csv_remove_record(csv
, rec1
);
535 csv_remove_record(csv
, rec2
);
536 csv_insert_record(csv
, rec
);
542 csv_decode (csv_t
*csv
, char *inbuf
)
548 buf
= (inbuf
)? inbuf
:csv
->buf
;
549 pos
= strpbrk(buf
, "\n");
550 while (pos
!= NULL
) {
551 rec
= calloc(1, sizeof(csv_record_t
));
552 csv_init_record(rec
);
553 TAILQ_INSERT_TAIL(&(csv
->records
), rec
, next_record
);
558 rec
->record
= calloc(1, csv
->buflen
);
560 log_error("field str malloc failed\n");
563 strncpy(rec
->record
, buf
, pos
-buf
+1);
565 rec
->rec_len
= pos
-buf
+1;
566 /* decode record into fields */
567 csv_decode_record(rec
);
569 pos
= strpbrk(buf
, "\n");
574 csv_is_record_valid(csv_t
*csv
, csv_record_t
*in_rec
)
579 rec
= csv_record_iter(csv
);
585 rec
= csv_record_iter_next(rec
);
592 csv_dump (csv_t
*csv
)
598 rec
= csv_record_iter(csv
);
599 while (rec
!= NULL
) {
600 str
= csv_field_iter(rec
, &fld
);
601 while (str
!= NULL
) {
602 fprintf(stderr
, "%s\n", str
);
603 str
= csv_field_iter_next(&fld
);
605 rec
= csv_record_iter_next(rec
);
612 get_memory_usage (pid_t pid
)
615 char buf
[4096], status_child
[BUFSIZ
];
618 sprintf(status_child
, "/proc/%d/status", pid
);
619 if ((fd
= open(status_child
, O_RDONLY
)) < 0)
628 vm
= strstr(buf
, "VmData:");
630 sscanf(vm
, "%*s %d", &data
);
632 vm
= strstr(buf
, "VmStk:");
634 sscanf(vm
, "%*s %d", &stack
);
649 char hdr1
[32], hdr2
[32];
651 log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
652 csv_init(&csv
, buf
, 256);
653 sprintf(hdr1
, "%4u", 0);
654 sprintf(hdr2
, "%4u", 1);
655 log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1
),
656 strlen(hdr2
), atoi(hdr1
), atoi(hdr2
));
657 rec
= csv_encode(&csv
, 2, hdr1
, hdr2
);
658 csv_encode(&csv
, 4, "name", "age", "sex", "hei");
659 csv_encode(&csv
, 3, NULL
, "0", NULL
);
660 csv_encode(&csv
, 2, "p", "35");
661 for (i
=0; i
< 50; i
++) {
662 csv_encode(&csv
, 2, "p", "10");
664 csv_encode(&csv
, 2, "pdfadfadfadsadsaddfdfdsfdsd",
665 "35444554545454545");
666 log_verbose("%s\n", buf
);
667 sprintf(hdr1
, "%4u", csv
.csv_len
);
668 sprintf(hdr2
, "%4u", 1);
669 log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1
),
670 strlen(hdr2
), atoi(hdr1
), atoi(hdr2
));
671 rec
= csv_encode_record(&csv
, rec
, 2, hdr1
, hdr2
);
672 log_verbose("(%d/%d)\n%s\n", rec
->rec_len
, csv
.csv_len
, buf
);
674 log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
676 log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
677 csv_init(&csv
, buf
, 256);
678 csv_decode(&csv
, NULL
);
679 log_verbose("AFTER DECODE\n");
682 log_verbose("Mem: %ld\n", get_memory_usage(getpid()));