@@ -434,40 +434,229 @@ char* AdafruitIO_Data::charFromDouble(double d, int precision)
434
434
return _double_buffer;
435
435
}
436
436
437
- bool AdafruitIO_Data::_parseCSV ()
437
+ /*
438
+ * From the csv_parser project by semitrivial
439
+ * https://github.com/semitrivial/csv_parser/blob/93246cac509f85da12c6bb8c641fa75cd863c34f/csv.c - retrieved 2017-11-09
440
+ *
441
+ * MIT License
442
+ *
443
+ * Copyright 2016 Samuel Alexander
444
+ *
445
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
446
+ * of this software and associated documentation files (the "Software"), to
447
+ * deal in the Software without restriction, including without limitation the
448
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
449
+ * sell copies of the Software, and to permit persons to whom the Software is
450
+ * furnished to do so, subject to the following conditions:
451
+ *
452
+ * The above copyright notice and this permission notice shall be included in
453
+ * all copies or substantial portions of the Software.
454
+ *
455
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
456
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
457
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
458
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
459
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
460
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
461
+ * IN THE SOFTWARE.
462
+ *
463
+ */
464
+
465
+ static int count_fields ( const char *line )
466
+ {
467
+ const char *ptr;
468
+ int cnt, fQuote ;
469
+
470
+ for ( cnt = 1 , fQuote = 0 , ptr = line; *ptr; ptr++ )
471
+ {
472
+ if ( fQuote )
473
+ {
474
+ if ( *ptr == ' \" ' )
475
+ {
476
+ if ( ptr[1 ] == ' \" ' )
477
+ {
478
+ ptr++;
479
+ continue ;
480
+ }
481
+ fQuote = 0 ;
482
+ }
483
+ continue ;
484
+ }
485
+
486
+ switch ( *ptr )
487
+ {
488
+ case ' \" ' :
489
+ fQuote = 1 ;
490
+ continue ;
491
+ case ' ,' :
492
+ cnt++;
493
+ continue ;
494
+ default :
495
+ continue ;
496
+ }
497
+ }
498
+
499
+ if ( fQuote )
500
+ {
501
+ return -1 ;
502
+ }
503
+
504
+ return cnt;
505
+ }
506
+
507
+ /*
508
+ * Given a string containing no linebreaks, or containing line breaks
509
+ * which are escaped by "double quotes", extract a NULL-terminated
510
+ * array of strings, one for every cell in the row.
511
+ */
512
+ char **parse_csv ( const char *line )
438
513
{
439
- char *csv = _csv;
440
-
441
- if (csv[0 ] == ' "' ) {
442
- // handle quoted values
443
- csv++;
444
- int end = strstr (csv, " \" ," ) - csv;
445
- strncpy (_value, csv, end);
446
- csv += (end + 2 );
447
- } else {
448
- // handle normal values
449
- strcpy (_value, strtok (csv, " ," ));
514
+ char **buf, **bptr, *tmp, *tptr;
515
+ const char *ptr;
516
+ int fieldcnt, fQuote , fEnd ;
517
+
518
+ fieldcnt = count_fields ( line );
519
+
520
+ if ( fieldcnt == -1 )
521
+ {
522
+ return NULL ;
523
+ }
524
+
525
+ buf = (char **)malloc ( sizeof (char *) * (fieldcnt+1 ) );
526
+
527
+ if ( !buf )
528
+ {
529
+ return NULL ;
530
+ }
531
+
532
+ tmp = (char *)malloc ( strlen (line) + 1 );
533
+
534
+ if ( !tmp )
535
+ {
536
+ free ( buf );
537
+ return NULL ;
538
+ }
539
+
540
+ bptr = buf;
541
+
542
+ for ( ptr = line, fQuote = 0 , *tmp = ' \0 ' , tptr = tmp, fEnd = 0 ; ; ptr++ )
543
+ {
544
+ if ( fQuote )
545
+ {
546
+ if ( !*ptr )
547
+ {
548
+ break ;
549
+ }
550
+
551
+ if ( *ptr == ' \" ' )
552
+ {
553
+ if ( ptr[1 ] == ' \" ' )
554
+ {
555
+ *tptr++ = ' \" ' ;
556
+ ptr++;
557
+ continue ;
558
+ }
559
+ fQuote = 0 ;
560
+ }
561
+ else {
562
+ *tptr++ = *ptr;
563
+ }
564
+
565
+ continue ;
566
+ }
567
+
568
+ switch ( *ptr )
569
+ {
570
+ case ' \" ' :
571
+ fQuote = 1 ;
572
+ continue ;
573
+ case ' \0 ' :
574
+ fEnd = 1 ;
575
+ case ' ,' :
576
+ *tptr = ' \0 ' ;
577
+ *bptr = strdup ( tmp );
578
+
579
+ if ( !*bptr )
580
+ {
581
+ for ( bptr--; bptr >= buf; bptr-- )
582
+ {
583
+ free ( *bptr );
584
+ }
585
+ free ( buf );
586
+ free ( tmp );
587
+
588
+ return NULL ;
589
+ }
590
+
591
+ bptr++;
592
+ tptr = tmp;
593
+
594
+ if ( fEnd )
595
+ {
596
+ break ;
597
+ } else
598
+ {
599
+ continue ;
600
+ }
601
+
602
+ default :
603
+ *tptr++ = *ptr;
604
+ continue ;
605
+ }
606
+
607
+ if ( fEnd )
608
+ {
609
+ break ;
610
+ }
450
611
}
451
612
452
- if (! _value) return false ;
613
+ *bptr = NULL ;
614
+ free ( tmp );
615
+ return buf;
616
+ }
617
+
618
+ // // END simple_csv SECTION
619
+
620
+ bool AdafruitIO_Data::_parseCSV ()
621
+ {
622
+
623
+ int field_count = count_fields (_csv);
453
624
454
- // parse lat from csv and convert to float
455
- char *lat = strtok (NULL , " ," );
456
- if (! lat) return false ;
625
+ if (field_count > 0 )
626
+ {
627
+ // this is normal IO data in `value,lat,lon,ele` format
628
+ char **fields = parse_csv (_csv);
457
629
458
- _lat = atof (lat);
630
+ // first field is handled as string
631
+ strcpy (_value, fields[0 ]);
632
+ field_count--;
459
633
460
- // parse lon from csv and convert to float
461
- char *lon = strtok (NULL , " ," );
462
- if (! lon) return false ;
634
+ // locations fields are handled with char * to float conversion
635
+ if (field_count > 0 )
636
+ {
637
+ _lat = atof (fields[1 ]);
638
+ field_count--;
639
+ }
463
640
464
- _lon = atof (lon);
641
+ if (field_count > 0 )
642
+ {
643
+ _lon = atof (fields[1 ]);
644
+ field_count--;
645
+ }
465
646
466
- // parse ele from csv and convert to float
467
- char *ele = strtok (NULL , " ," );
468
- if (! ele) return false ;
647
+ if (field_count > 0 )
648
+ {
649
+ _ele = atof (fields[1 ]);
650
+ field_count--;
651
+ }
469
652
470
- _ele = atof (ele);
653
+ return field_count == 0 ;
654
+ }
655
+ else
656
+ {
657
+ return false ;
658
+ }
471
659
472
660
return true ;
473
661
}
662
+
0 commit comments