fastcsv 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,8 @@
2
2
  #line 1 "ext/fastcsv/fastcsv.rl"
3
3
  #include <ruby.h>
4
4
  #include <ruby/encoding.h>
5
+ #include <stdbool.h>
6
+
5
7
  // CSV specifications.
6
8
  // http://tools.ietf.org/html/rfc4180
7
9
  // http://w3c.github.io/csvw/syntax/#ebnf
@@ -38,11 +40,11 @@ typedef struct {
38
40
  } Data;
39
41
 
40
42
 
41
- #line 172 "ext/fastcsv/fastcsv.rl"
43
+ #line 156 "ext/fastcsv/fastcsv.rl"
42
44
 
43
45
 
44
46
 
45
- #line 46 "ext/fastcsv/fastcsv.c"
47
+ #line 48 "ext/fastcsv/fastcsv.c"
46
48
  static const int raw_parse_start = 4;
47
49
  static const int raw_parse_first_final = 4;
48
50
  static const int raw_parse_error = 0;
@@ -50,7 +52,7 @@ static const int raw_parse_error = 0;
50
52
  static const int raw_parse_en_main = 4;
51
53
 
52
54
 
53
- #line 175 "ext/fastcsv/fastcsv.rl"
55
+ #line 159 "ext/fastcsv/fastcsv.rl"
54
56
 
55
57
  // 16 kB
56
58
  #define BUFSIZE 16384
@@ -81,6 +83,38 @@ static void rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_enco
81
83
  }
82
84
  }
83
85
 
86
+ static void parse_quoted_field(VALUE* field, rb_encoding* encoding, char quote_char, char* quoted_field_start, char *quoted_field_end) {
87
+ // read the full quoted field, handling any escape sequences
88
+ if (quoted_field_end == quoted_field_start) {
89
+ // empty quoted field is an empty string
90
+ *field = rb_enc_str_new("", 0, encoding);
91
+ } else {
92
+ // largest possible buffer. if there's escaping, the resulting string will
93
+ // not use the entire buffer
94
+ char *copy = ALLOC_N(char, quoted_field_end - quoted_field_start);
95
+ char *reader = quoted_field_start, *writer = copy;
96
+ int escaped = 0;
97
+
98
+ while (quoted_field_end > reader) {
99
+ if (*reader == quote_char && !escaped) {
100
+ // Skip the escaping character.
101
+ escaped = 1;
102
+ }
103
+ else {
104
+ escaped = 0;
105
+ *writer++ = *reader;
106
+ }
107
+ reader++;
108
+ }
109
+
110
+ *field = rb_enc_str_new(copy, writer - copy, encoding);
111
+
112
+ if (copy != NULL) {
113
+ free(copy);
114
+ }
115
+ }
116
+ }
117
+
84
118
  static VALUE raw_parse(int argc, VALUE *argv, VALUE self) {
85
119
  int cs, act, have = 0, curline = 1, io = 0;
86
120
  char *ts = 0, *te = 0, *buf = 0, *eof = 0, *mark_row_sep = 0, *row_sep = 0;
@@ -96,6 +130,8 @@ static VALUE raw_parse(int argc, VALUE *argv, VALUE self) {
96
130
  VALUE option;
97
131
  char quote_char = '"', col_sep = ',';
98
132
 
133
+ bool in_quoted_field = false;
134
+
99
135
  rb_scan_args(argc, argv, "11", &port, &opts);
100
136
  taint = OBJ_TAINTED(port);
101
137
  io = rb_respond_to(port, s_read);
@@ -262,7 +298,7 @@ static VALUE raw_parse(int argc, VALUE *argv, VALUE self) {
262
298
  }
263
299
 
264
300
 
265
- #line 266 "ext/fastcsv/fastcsv.c"
301
+ #line 302 "ext/fastcsv/fastcsv.c"
266
302
  {
267
303
  cs = raw_parse_start;
268
304
  ts = 0;
@@ -270,7 +306,7 @@ static VALUE raw_parse(int argc, VALUE *argv, VALUE self) {
270
306
  act = 0;
271
307
  }
272
308
 
273
- #line 386 "ext/fastcsv/fastcsv.rl"
309
+ #line 404 "ext/fastcsv/fastcsv.rl"
274
310
 
275
311
  while (!done) {
276
312
  VALUE str;
@@ -332,7 +368,7 @@ static VALUE raw_parse(int argc, VALUE *argv, VALUE self) {
332
368
 
333
369
  pe = p + len;
334
370
 
335
- #line 336 "ext/fastcsv/fastcsv.c"
371
+ #line 372 "ext/fastcsv/fastcsv.c"
336
372
  {
337
373
  short _widec;
338
374
  if ( p == pe )
@@ -352,7 +388,7 @@ tr0:
352
388
  }
353
389
  goto st4;
354
390
  tr5:
355
- #line 49 "ext/fastcsv/fastcsv.rl"
391
+ #line 52 "ext/fastcsv/fastcsv.rl"
356
392
  {
357
393
  if (p == ts) {
358
394
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -363,7 +399,7 @@ tr5:
363
399
  ENCODE;
364
400
  }
365
401
  }
366
- #line 138 "ext/fastcsv/fastcsv.rl"
402
+ #line 122 "ext/fastcsv/fastcsv.rl"
367
403
  {
368
404
  if (d->start == 0 || p == d->start) { // same as new_row
369
405
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -380,11 +416,11 @@ tr5:
380
416
  rb_yield(row);
381
417
  }
382
418
  }
383
- #line 170 "ext/fastcsv/fastcsv.rl"
419
+ #line 154 "ext/fastcsv/fastcsv.rl"
384
420
  {te = p+1;}
385
421
  goto st4;
386
422
  tr6:
387
- #line 49 "ext/fastcsv/fastcsv.rl"
423
+ #line 52 "ext/fastcsv/fastcsv.rl"
388
424
  {
389
425
  if (p == ts) {
390
426
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -395,16 +431,22 @@ tr6:
395
431
  ENCODE;
396
432
  }
397
433
  }
398
- #line 95 "ext/fastcsv/fastcsv.rl"
434
+ #line 67 "ext/fastcsv/fastcsv.rl"
399
435
  {
436
+ if (in_quoted_field) {
437
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
438
+ ENCODE;
439
+ in_quoted_field = false;
440
+ }
441
+
400
442
  rb_ary_push(row, field);
401
443
  field = Qnil;
402
444
  }
403
- #line 168 "ext/fastcsv/fastcsv.rl"
445
+ #line 152 "ext/fastcsv/fastcsv.rl"
404
446
  {te = p+1;}
405
447
  goto st4;
406
448
  tr7:
407
- #line 49 "ext/fastcsv/fastcsv.rl"
449
+ #line 52 "ext/fastcsv/fastcsv.rl"
408
450
  {
409
451
  if (p == ts) {
410
452
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -415,14 +457,20 @@ tr7:
415
457
  ENCODE;
416
458
  }
417
459
  }
418
- #line 95 "ext/fastcsv/fastcsv.rl"
460
+ #line 67 "ext/fastcsv/fastcsv.rl"
419
461
  {
462
+ if (in_quoted_field) {
463
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
464
+ ENCODE;
465
+ in_quoted_field = false;
466
+ }
467
+
420
468
  rb_ary_push(row, field);
421
469
  field = Qnil;
422
470
  }
423
- #line 168 "ext/fastcsv/fastcsv.rl"
471
+ #line 152 "ext/fastcsv/fastcsv.rl"
424
472
  {te = p+1;}
425
- #line 138 "ext/fastcsv/fastcsv.rl"
473
+ #line 122 "ext/fastcsv/fastcsv.rl"
426
474
  {
427
475
  if (d->start == 0 || p == d->start) { // same as new_row
428
476
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -441,7 +489,7 @@ tr7:
441
489
  }
442
490
  goto st4;
443
491
  tr12:
444
- #line 138 "ext/fastcsv/fastcsv.rl"
492
+ #line 122 "ext/fastcsv/fastcsv.rl"
445
493
  {
446
494
  if (d->start == 0 || p == d->start) { // same as new_row
447
495
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -458,27 +506,39 @@ tr12:
458
506
  rb_yield(row);
459
507
  }
460
508
  }
461
- #line 170 "ext/fastcsv/fastcsv.rl"
509
+ #line 154 "ext/fastcsv/fastcsv.rl"
462
510
  {te = p+1;}
463
511
  goto st4;
464
512
  tr18:
465
- #line 95 "ext/fastcsv/fastcsv.rl"
513
+ #line 67 "ext/fastcsv/fastcsv.rl"
466
514
  {
515
+ if (in_quoted_field) {
516
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
517
+ ENCODE;
518
+ in_quoted_field = false;
519
+ }
520
+
467
521
  rb_ary_push(row, field);
468
522
  field = Qnil;
469
523
  }
470
- #line 168 "ext/fastcsv/fastcsv.rl"
524
+ #line 152 "ext/fastcsv/fastcsv.rl"
471
525
  {te = p+1;}
472
526
  goto st4;
473
527
  tr19:
474
- #line 95 "ext/fastcsv/fastcsv.rl"
528
+ #line 67 "ext/fastcsv/fastcsv.rl"
475
529
  {
530
+ if (in_quoted_field) {
531
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
532
+ ENCODE;
533
+ in_quoted_field = false;
534
+ }
535
+
476
536
  rb_ary_push(row, field);
477
537
  field = Qnil;
478
538
  }
479
- #line 168 "ext/fastcsv/fastcsv.rl"
539
+ #line 152 "ext/fastcsv/fastcsv.rl"
480
540
  {te = p+1;}
481
- #line 138 "ext/fastcsv/fastcsv.rl"
541
+ #line 122 "ext/fastcsv/fastcsv.rl"
482
542
  {
483
543
  if (d->start == 0 || p == d->start) { // same as new_row
484
544
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -497,11 +557,11 @@ tr19:
497
557
  }
498
558
  goto st4;
499
559
  tr36:
500
- #line 170 "ext/fastcsv/fastcsv.rl"
560
+ #line 154 "ext/fastcsv/fastcsv.rl"
501
561
  {te = p;p--;}
502
562
  goto st4;
503
563
  tr37:
504
- #line 100 "ext/fastcsv/fastcsv.rl"
564
+ #line 78 "ext/fastcsv/fastcsv.rl"
505
565
  {
506
566
  d->start = p;
507
567
 
@@ -532,7 +592,7 @@ tr37:
532
592
  }
533
593
  goto st4;
534
594
  tr43:
535
- #line 100 "ext/fastcsv/fastcsv.rl"
595
+ #line 78 "ext/fastcsv/fastcsv.rl"
536
596
  {
537
597
  d->start = p;
538
598
 
@@ -551,15 +611,15 @@ tr43:
551
611
 
552
612
  curline++;
553
613
  }
554
- #line 169 "ext/fastcsv/fastcsv.rl"
614
+ #line 153 "ext/fastcsv/fastcsv.rl"
555
615
  {te = p;p--;}
556
616
  goto st4;
557
617
  tr44:
558
- #line 169 "ext/fastcsv/fastcsv.rl"
618
+ #line 153 "ext/fastcsv/fastcsv.rl"
559
619
  {te = p;p--;}
560
620
  goto st4;
561
621
  tr45:
562
- #line 100 "ext/fastcsv/fastcsv.rl"
622
+ #line 78 "ext/fastcsv/fastcsv.rl"
563
623
  {
564
624
  d->start = p;
565
625
 
@@ -578,7 +638,7 @@ tr45:
578
638
 
579
639
  curline++;
580
640
  }
581
- #line 138 "ext/fastcsv/fastcsv.rl"
641
+ #line 122 "ext/fastcsv/fastcsv.rl"
582
642
  {
583
643
  if (d->start == 0 || p == d->start) { // same as new_row
584
644
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -595,18 +655,24 @@ tr45:
595
655
  rb_yield(row);
596
656
  }
597
657
  }
598
- #line 170 "ext/fastcsv/fastcsv.rl"
658
+ #line 154 "ext/fastcsv/fastcsv.rl"
599
659
  {te = p+1;}
600
660
  goto st4;
601
661
  tr51:
602
- #line 95 "ext/fastcsv/fastcsv.rl"
662
+ #line 67 "ext/fastcsv/fastcsv.rl"
603
663
  {
664
+ if (in_quoted_field) {
665
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
666
+ ENCODE;
667
+ in_quoted_field = false;
668
+ }
669
+
604
670
  rb_ary_push(row, field);
605
671
  field = Qnil;
606
672
  }
607
- #line 168 "ext/fastcsv/fastcsv.rl"
673
+ #line 152 "ext/fastcsv/fastcsv.rl"
608
674
  {te = p+1;}
609
- #line 100 "ext/fastcsv/fastcsv.rl"
675
+ #line 78 "ext/fastcsv/fastcsv.rl"
610
676
  {
611
677
  d->start = p;
612
678
 
@@ -627,14 +693,20 @@ tr51:
627
693
  }
628
694
  goto st4;
629
695
  tr52:
630
- #line 95 "ext/fastcsv/fastcsv.rl"
696
+ #line 67 "ext/fastcsv/fastcsv.rl"
631
697
  {
698
+ if (in_quoted_field) {
699
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
700
+ ENCODE;
701
+ in_quoted_field = false;
702
+ }
703
+
632
704
  rb_ary_push(row, field);
633
705
  field = Qnil;
634
706
  }
635
- #line 168 "ext/fastcsv/fastcsv.rl"
707
+ #line 152 "ext/fastcsv/fastcsv.rl"
636
708
  {te = p+1;}
637
- #line 100 "ext/fastcsv/fastcsv.rl"
709
+ #line 78 "ext/fastcsv/fastcsv.rl"
638
710
  {
639
711
  d->start = p;
640
712
 
@@ -653,7 +725,7 @@ tr52:
653
725
 
654
726
  curline++;
655
727
  }
656
- #line 138 "ext/fastcsv/fastcsv.rl"
728
+ #line 122 "ext/fastcsv/fastcsv.rl"
657
729
  {
658
730
  if (d->start == 0 || p == d->start) { // same as new_row
659
731
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -681,14 +753,14 @@ st4:
681
753
  case 4:
682
754
  #line 1 "NONE"
683
755
  {ts = p;}
684
- #line 685 "ext/fastcsv/fastcsv.c"
756
+ #line 757 "ext/fastcsv/fastcsv.c"
685
757
  _widec = (*p);
686
758
  _widec = (short)(1152 + ((*p) - -128));
687
759
  if (
688
- #line 156 "ext/fastcsv/fastcsv.rl"
760
+ #line 140 "ext/fastcsv/fastcsv.rl"
689
761
  (*p) == quote_char ) _widec += 256;
690
762
  if (
691
- #line 157 "ext/fastcsv/fastcsv.rl"
763
+ #line 141 "ext/fastcsv/fastcsv.rl"
692
764
  (*p) == col_sep ) _widec += 512;
693
765
  switch( _widec ) {
694
766
  case 1280: goto tr27;
@@ -726,10 +798,10 @@ case 1:
726
798
  _widec = (*p);
727
799
  _widec = (short)(1152 + ((*p) - -128));
728
800
  if (
729
- #line 156 "ext/fastcsv/fastcsv.rl"
801
+ #line 140 "ext/fastcsv/fastcsv.rl"
730
802
  (*p) == quote_char ) _widec += 256;
731
803
  if (
732
- #line 157 "ext/fastcsv/fastcsv.rl"
804
+ #line 141 "ext/fastcsv/fastcsv.rl"
733
805
  (*p) == col_sep ) _widec += 512;
734
806
  switch( _widec ) {
735
807
  case 1280: goto tr2;
@@ -754,7 +826,7 @@ case 1:
754
826
  tr2:
755
827
  #line 1 "NONE"
756
828
  {te = p+1;}
757
- #line 49 "ext/fastcsv/fastcsv.rl"
829
+ #line 52 "ext/fastcsv/fastcsv.rl"
758
830
  {
759
831
  if (p == ts) {
760
832
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -765,7 +837,7 @@ tr2:
765
837
  ENCODE;
766
838
  }
767
839
  }
768
- #line 138 "ext/fastcsv/fastcsv.rl"
840
+ #line 122 "ext/fastcsv/fastcsv.rl"
769
841
  {
770
842
  if (d->start == 0 || p == d->start) { // same as new_row
771
843
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -782,21 +854,21 @@ tr2:
782
854
  rb_yield(row);
783
855
  }
784
856
  }
785
- #line 170 "ext/fastcsv/fastcsv.rl"
857
+ #line 154 "ext/fastcsv/fastcsv.rl"
786
858
  {act = 3;}
787
859
  goto st5;
788
860
  st5:
789
861
  if ( ++p == pe )
790
862
  goto _test_eof5;
791
863
  case 5:
792
- #line 793 "ext/fastcsv/fastcsv.c"
864
+ #line 865 "ext/fastcsv/fastcsv.c"
793
865
  _widec = (*p);
794
866
  _widec = (short)(1152 + ((*p) - -128));
795
867
  if (
796
- #line 156 "ext/fastcsv/fastcsv.rl"
868
+ #line 140 "ext/fastcsv/fastcsv.rl"
797
869
  (*p) == quote_char ) _widec += 256;
798
870
  if (
799
- #line 157 "ext/fastcsv/fastcsv.rl"
871
+ #line 141 "ext/fastcsv/fastcsv.rl"
800
872
  (*p) == col_sep ) _widec += 512;
801
873
  switch( _widec ) {
802
874
  case 1280: goto tr2;
@@ -821,7 +893,7 @@ case 5:
821
893
  tr3:
822
894
  #line 1 "NONE"
823
895
  {te = p+1;}
824
- #line 49 "ext/fastcsv/fastcsv.rl"
896
+ #line 52 "ext/fastcsv/fastcsv.rl"
825
897
  {
826
898
  if (p == ts) {
827
899
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -832,7 +904,7 @@ tr3:
832
904
  ENCODE;
833
905
  }
834
906
  }
835
- #line 119 "ext/fastcsv/fastcsv.rl"
907
+ #line 97 "ext/fastcsv/fastcsv.rl"
836
908
  {
837
909
  mark_row_sep = p;
838
910
 
@@ -843,6 +915,12 @@ tr3:
843
915
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
844
916
  }
845
917
 
918
+ if (in_quoted_field) {
919
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
920
+ ENCODE;
921
+ in_quoted_field = false;
922
+ }
923
+
846
924
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
847
925
  rb_ary_push(row, field);
848
926
  field = Qnil;
@@ -851,13 +929,13 @@ tr3:
851
929
  rb_yield(row);
852
930
  row = rb_ary_new();
853
931
  }
854
- #line 169 "ext/fastcsv/fastcsv.rl"
932
+ #line 153 "ext/fastcsv/fastcsv.rl"
855
933
  {act = 2;}
856
934
  goto st6;
857
935
  tr8:
858
936
  #line 1 "NONE"
859
937
  {te = p+1;}
860
- #line 49 "ext/fastcsv/fastcsv.rl"
938
+ #line 52 "ext/fastcsv/fastcsv.rl"
861
939
  {
862
940
  if (p == ts) {
863
941
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -868,14 +946,20 @@ tr8:
868
946
  ENCODE;
869
947
  }
870
948
  }
871
- #line 95 "ext/fastcsv/fastcsv.rl"
949
+ #line 67 "ext/fastcsv/fastcsv.rl"
872
950
  {
951
+ if (in_quoted_field) {
952
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
953
+ ENCODE;
954
+ in_quoted_field = false;
955
+ }
956
+
873
957
  rb_ary_push(row, field);
874
958
  field = Qnil;
875
959
  }
876
- #line 168 "ext/fastcsv/fastcsv.rl"
960
+ #line 152 "ext/fastcsv/fastcsv.rl"
877
961
  {act = 1;}
878
- #line 119 "ext/fastcsv/fastcsv.rl"
962
+ #line 97 "ext/fastcsv/fastcsv.rl"
879
963
  {
880
964
  mark_row_sep = p;
881
965
 
@@ -886,6 +970,12 @@ tr8:
886
970
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
887
971
  }
888
972
 
973
+ if (in_quoted_field) {
974
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
975
+ ENCODE;
976
+ in_quoted_field = false;
977
+ }
978
+
889
979
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
890
980
  rb_ary_push(row, field);
891
981
  field = Qnil;
@@ -898,7 +988,7 @@ tr8:
898
988
  tr13:
899
989
  #line 1 "NONE"
900
990
  {te = p+1;}
901
- #line 119 "ext/fastcsv/fastcsv.rl"
991
+ #line 97 "ext/fastcsv/fastcsv.rl"
902
992
  {
903
993
  mark_row_sep = p;
904
994
 
@@ -909,6 +999,12 @@ tr13:
909
999
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
910
1000
  }
911
1001
 
1002
+ if (in_quoted_field) {
1003
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1004
+ ENCODE;
1005
+ in_quoted_field = false;
1006
+ }
1007
+
912
1008
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
913
1009
  rb_ary_push(row, field);
914
1010
  field = Qnil;
@@ -917,20 +1013,26 @@ tr13:
917
1013
  rb_yield(row);
918
1014
  row = rb_ary_new();
919
1015
  }
920
- #line 169 "ext/fastcsv/fastcsv.rl"
1016
+ #line 153 "ext/fastcsv/fastcsv.rl"
921
1017
  {act = 2;}
922
1018
  goto st6;
923
1019
  tr20:
924
1020
  #line 1 "NONE"
925
1021
  {te = p+1;}
926
- #line 95 "ext/fastcsv/fastcsv.rl"
1022
+ #line 67 "ext/fastcsv/fastcsv.rl"
927
1023
  {
1024
+ if (in_quoted_field) {
1025
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1026
+ ENCODE;
1027
+ in_quoted_field = false;
1028
+ }
1029
+
928
1030
  rb_ary_push(row, field);
929
1031
  field = Qnil;
930
1032
  }
931
- #line 168 "ext/fastcsv/fastcsv.rl"
1033
+ #line 152 "ext/fastcsv/fastcsv.rl"
932
1034
  {act = 1;}
933
- #line 119 "ext/fastcsv/fastcsv.rl"
1035
+ #line 97 "ext/fastcsv/fastcsv.rl"
934
1036
  {
935
1037
  mark_row_sep = p;
936
1038
 
@@ -941,6 +1043,12 @@ tr20:
941
1043
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
942
1044
  }
943
1045
 
1046
+ if (in_quoted_field) {
1047
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1048
+ ENCODE;
1049
+ in_quoted_field = false;
1050
+ }
1051
+
944
1052
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
945
1053
  rb_ary_push(row, field);
946
1054
  field = Qnil;
@@ -953,13 +1061,13 @@ tr20:
953
1061
  tr38:
954
1062
  #line 1 "NONE"
955
1063
  {te = p+1;}
956
- #line 169 "ext/fastcsv/fastcsv.rl"
1064
+ #line 153 "ext/fastcsv/fastcsv.rl"
957
1065
  {act = 2;}
958
1066
  goto st6;
959
1067
  tr46:
960
1068
  #line 1 "NONE"
961
1069
  {te = p+1;}
962
- #line 119 "ext/fastcsv/fastcsv.rl"
1070
+ #line 97 "ext/fastcsv/fastcsv.rl"
963
1071
  {
964
1072
  mark_row_sep = p;
965
1073
 
@@ -970,6 +1078,12 @@ tr46:
970
1078
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
971
1079
  }
972
1080
 
1081
+ if (in_quoted_field) {
1082
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1083
+ ENCODE;
1084
+ in_quoted_field = false;
1085
+ }
1086
+
973
1087
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
974
1088
  rb_ary_push(row, field);
975
1089
  field = Qnil;
@@ -978,7 +1092,7 @@ tr46:
978
1092
  rb_yield(row);
979
1093
  row = rb_ary_new();
980
1094
  }
981
- #line 100 "ext/fastcsv/fastcsv.rl"
1095
+ #line 78 "ext/fastcsv/fastcsv.rl"
982
1096
  {
983
1097
  d->start = p;
984
1098
 
@@ -997,20 +1111,26 @@ tr46:
997
1111
 
998
1112
  curline++;
999
1113
  }
1000
- #line 169 "ext/fastcsv/fastcsv.rl"
1114
+ #line 153 "ext/fastcsv/fastcsv.rl"
1001
1115
  {act = 2;}
1002
1116
  goto st6;
1003
1117
  tr53:
1004
1118
  #line 1 "NONE"
1005
1119
  {te = p+1;}
1006
- #line 95 "ext/fastcsv/fastcsv.rl"
1120
+ #line 67 "ext/fastcsv/fastcsv.rl"
1007
1121
  {
1122
+ if (in_quoted_field) {
1123
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1124
+ ENCODE;
1125
+ in_quoted_field = false;
1126
+ }
1127
+
1008
1128
  rb_ary_push(row, field);
1009
1129
  field = Qnil;
1010
1130
  }
1011
- #line 168 "ext/fastcsv/fastcsv.rl"
1131
+ #line 152 "ext/fastcsv/fastcsv.rl"
1012
1132
  {act = 1;}
1013
- #line 119 "ext/fastcsv/fastcsv.rl"
1133
+ #line 97 "ext/fastcsv/fastcsv.rl"
1014
1134
  {
1015
1135
  mark_row_sep = p;
1016
1136
 
@@ -1021,6 +1141,12 @@ tr53:
1021
1141
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1022
1142
  }
1023
1143
 
1144
+ if (in_quoted_field) {
1145
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1146
+ ENCODE;
1147
+ in_quoted_field = false;
1148
+ }
1149
+
1024
1150
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1025
1151
  rb_ary_push(row, field);
1026
1152
  field = Qnil;
@@ -1029,7 +1155,7 @@ tr53:
1029
1155
  rb_yield(row);
1030
1156
  row = rb_ary_new();
1031
1157
  }
1032
- #line 100 "ext/fastcsv/fastcsv.rl"
1158
+ #line 78 "ext/fastcsv/fastcsv.rl"
1033
1159
  {
1034
1160
  d->start = p;
1035
1161
 
@@ -1053,12 +1179,12 @@ st6:
1053
1179
  if ( ++p == pe )
1054
1180
  goto _test_eof6;
1055
1181
  case 6:
1056
- #line 1057 "ext/fastcsv/fastcsv.c"
1182
+ #line 1183 "ext/fastcsv/fastcsv.c"
1057
1183
  goto tr37;
1058
1184
  tr4:
1059
1185
  #line 1 "NONE"
1060
1186
  {te = p+1;}
1061
- #line 49 "ext/fastcsv/fastcsv.rl"
1187
+ #line 52 "ext/fastcsv/fastcsv.rl"
1062
1188
  {
1063
1189
  if (p == ts) {
1064
1190
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1069,7 +1195,7 @@ tr4:
1069
1195
  ENCODE;
1070
1196
  }
1071
1197
  }
1072
- #line 119 "ext/fastcsv/fastcsv.rl"
1198
+ #line 97 "ext/fastcsv/fastcsv.rl"
1073
1199
  {
1074
1200
  mark_row_sep = p;
1075
1201
 
@@ -1080,6 +1206,12 @@ tr4:
1080
1206
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1081
1207
  }
1082
1208
 
1209
+ if (in_quoted_field) {
1210
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1211
+ ENCODE;
1212
+ in_quoted_field = false;
1213
+ }
1214
+
1083
1215
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1084
1216
  rb_ary_push(row, field);
1085
1217
  field = Qnil;
@@ -1088,13 +1220,13 @@ tr4:
1088
1220
  rb_yield(row);
1089
1221
  row = rb_ary_new();
1090
1222
  }
1091
- #line 169 "ext/fastcsv/fastcsv.rl"
1223
+ #line 153 "ext/fastcsv/fastcsv.rl"
1092
1224
  {act = 2;}
1093
1225
  goto st7;
1094
1226
  tr9:
1095
1227
  #line 1 "NONE"
1096
1228
  {te = p+1;}
1097
- #line 49 "ext/fastcsv/fastcsv.rl"
1229
+ #line 52 "ext/fastcsv/fastcsv.rl"
1098
1230
  {
1099
1231
  if (p == ts) {
1100
1232
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1105,14 +1237,20 @@ tr9:
1105
1237
  ENCODE;
1106
1238
  }
1107
1239
  }
1108
- #line 95 "ext/fastcsv/fastcsv.rl"
1240
+ #line 67 "ext/fastcsv/fastcsv.rl"
1109
1241
  {
1242
+ if (in_quoted_field) {
1243
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1244
+ ENCODE;
1245
+ in_quoted_field = false;
1246
+ }
1247
+
1110
1248
  rb_ary_push(row, field);
1111
1249
  field = Qnil;
1112
1250
  }
1113
- #line 168 "ext/fastcsv/fastcsv.rl"
1251
+ #line 152 "ext/fastcsv/fastcsv.rl"
1114
1252
  {act = 1;}
1115
- #line 119 "ext/fastcsv/fastcsv.rl"
1253
+ #line 97 "ext/fastcsv/fastcsv.rl"
1116
1254
  {
1117
1255
  mark_row_sep = p;
1118
1256
 
@@ -1123,6 +1261,12 @@ tr9:
1123
1261
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1124
1262
  }
1125
1263
 
1264
+ if (in_quoted_field) {
1265
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1266
+ ENCODE;
1267
+ in_quoted_field = false;
1268
+ }
1269
+
1126
1270
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1127
1271
  rb_ary_push(row, field);
1128
1272
  field = Qnil;
@@ -1135,7 +1279,7 @@ tr9:
1135
1279
  tr14:
1136
1280
  #line 1 "NONE"
1137
1281
  {te = p+1;}
1138
- #line 119 "ext/fastcsv/fastcsv.rl"
1282
+ #line 97 "ext/fastcsv/fastcsv.rl"
1139
1283
  {
1140
1284
  mark_row_sep = p;
1141
1285
 
@@ -1146,6 +1290,12 @@ tr14:
1146
1290
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1147
1291
  }
1148
1292
 
1293
+ if (in_quoted_field) {
1294
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1295
+ ENCODE;
1296
+ in_quoted_field = false;
1297
+ }
1298
+
1149
1299
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1150
1300
  rb_ary_push(row, field);
1151
1301
  field = Qnil;
@@ -1154,20 +1304,26 @@ tr14:
1154
1304
  rb_yield(row);
1155
1305
  row = rb_ary_new();
1156
1306
  }
1157
- #line 169 "ext/fastcsv/fastcsv.rl"
1307
+ #line 153 "ext/fastcsv/fastcsv.rl"
1158
1308
  {act = 2;}
1159
1309
  goto st7;
1160
1310
  tr21:
1161
1311
  #line 1 "NONE"
1162
1312
  {te = p+1;}
1163
- #line 95 "ext/fastcsv/fastcsv.rl"
1313
+ #line 67 "ext/fastcsv/fastcsv.rl"
1164
1314
  {
1315
+ if (in_quoted_field) {
1316
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1317
+ ENCODE;
1318
+ in_quoted_field = false;
1319
+ }
1320
+
1165
1321
  rb_ary_push(row, field);
1166
1322
  field = Qnil;
1167
1323
  }
1168
- #line 168 "ext/fastcsv/fastcsv.rl"
1324
+ #line 152 "ext/fastcsv/fastcsv.rl"
1169
1325
  {act = 1;}
1170
- #line 119 "ext/fastcsv/fastcsv.rl"
1326
+ #line 97 "ext/fastcsv/fastcsv.rl"
1171
1327
  {
1172
1328
  mark_row_sep = p;
1173
1329
 
@@ -1178,6 +1334,12 @@ tr21:
1178
1334
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1179
1335
  }
1180
1336
 
1337
+ if (in_quoted_field) {
1338
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1339
+ ENCODE;
1340
+ in_quoted_field = false;
1341
+ }
1342
+
1181
1343
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1182
1344
  rb_ary_push(row, field);
1183
1345
  field = Qnil;
@@ -1190,7 +1352,7 @@ tr21:
1190
1352
  tr47:
1191
1353
  #line 1 "NONE"
1192
1354
  {te = p+1;}
1193
- #line 119 "ext/fastcsv/fastcsv.rl"
1355
+ #line 97 "ext/fastcsv/fastcsv.rl"
1194
1356
  {
1195
1357
  mark_row_sep = p;
1196
1358
 
@@ -1201,6 +1363,12 @@ tr47:
1201
1363
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1202
1364
  }
1203
1365
 
1366
+ if (in_quoted_field) {
1367
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1368
+ ENCODE;
1369
+ in_quoted_field = false;
1370
+ }
1371
+
1204
1372
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1205
1373
  rb_ary_push(row, field);
1206
1374
  field = Qnil;
@@ -1209,7 +1377,7 @@ tr47:
1209
1377
  rb_yield(row);
1210
1378
  row = rb_ary_new();
1211
1379
  }
1212
- #line 100 "ext/fastcsv/fastcsv.rl"
1380
+ #line 78 "ext/fastcsv/fastcsv.rl"
1213
1381
  {
1214
1382
  d->start = p;
1215
1383
 
@@ -1228,20 +1396,26 @@ tr47:
1228
1396
 
1229
1397
  curline++;
1230
1398
  }
1231
- #line 169 "ext/fastcsv/fastcsv.rl"
1399
+ #line 153 "ext/fastcsv/fastcsv.rl"
1232
1400
  {act = 2;}
1233
1401
  goto st7;
1234
1402
  tr54:
1235
1403
  #line 1 "NONE"
1236
1404
  {te = p+1;}
1237
- #line 95 "ext/fastcsv/fastcsv.rl"
1405
+ #line 67 "ext/fastcsv/fastcsv.rl"
1238
1406
  {
1407
+ if (in_quoted_field) {
1408
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1409
+ ENCODE;
1410
+ in_quoted_field = false;
1411
+ }
1412
+
1239
1413
  rb_ary_push(row, field);
1240
1414
  field = Qnil;
1241
1415
  }
1242
- #line 168 "ext/fastcsv/fastcsv.rl"
1416
+ #line 152 "ext/fastcsv/fastcsv.rl"
1243
1417
  {act = 1;}
1244
- #line 119 "ext/fastcsv/fastcsv.rl"
1418
+ #line 97 "ext/fastcsv/fastcsv.rl"
1245
1419
  {
1246
1420
  mark_row_sep = p;
1247
1421
 
@@ -1252,6 +1426,12 @@ tr54:
1252
1426
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1253
1427
  }
1254
1428
 
1429
+ if (in_quoted_field) {
1430
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1431
+ ENCODE;
1432
+ in_quoted_field = false;
1433
+ }
1434
+
1255
1435
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1256
1436
  rb_ary_push(row, field);
1257
1437
  field = Qnil;
@@ -1260,7 +1440,7 @@ tr54:
1260
1440
  rb_yield(row);
1261
1441
  row = rb_ary_new();
1262
1442
  }
1263
- #line 100 "ext/fastcsv/fastcsv.rl"
1443
+ #line 78 "ext/fastcsv/fastcsv.rl"
1264
1444
  {
1265
1445
  d->start = p;
1266
1446
 
@@ -1284,14 +1464,14 @@ st7:
1284
1464
  if ( ++p == pe )
1285
1465
  goto _test_eof7;
1286
1466
  case 7:
1287
- #line 1288 "ext/fastcsv/fastcsv.c"
1467
+ #line 1468 "ext/fastcsv/fastcsv.c"
1288
1468
  if ( (*p) == 10 )
1289
1469
  goto tr38;
1290
1470
  goto tr37;
1291
1471
  tr27:
1292
1472
  #line 1 "NONE"
1293
1473
  {te = p+1;}
1294
- #line 49 "ext/fastcsv/fastcsv.rl"
1474
+ #line 52 "ext/fastcsv/fastcsv.rl"
1295
1475
  {
1296
1476
  if (p == ts) {
1297
1477
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1302,7 +1482,7 @@ tr27:
1302
1482
  ENCODE;
1303
1483
  }
1304
1484
  }
1305
- #line 138 "ext/fastcsv/fastcsv.rl"
1485
+ #line 122 "ext/fastcsv/fastcsv.rl"
1306
1486
  {
1307
1487
  if (d->start == 0 || p == d->start) { // same as new_row
1308
1488
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1319,21 +1499,21 @@ tr27:
1319
1499
  rb_yield(row);
1320
1500
  }
1321
1501
  }
1322
- #line 170 "ext/fastcsv/fastcsv.rl"
1502
+ #line 154 "ext/fastcsv/fastcsv.rl"
1323
1503
  {act = 3;}
1324
1504
  goto st8;
1325
1505
  st8:
1326
1506
  if ( ++p == pe )
1327
1507
  goto _test_eof8;
1328
1508
  case 8:
1329
- #line 1330 "ext/fastcsv/fastcsv.c"
1509
+ #line 1510 "ext/fastcsv/fastcsv.c"
1330
1510
  _widec = (*p);
1331
1511
  _widec = (short)(1152 + ((*p) - -128));
1332
1512
  if (
1333
- #line 156 "ext/fastcsv/fastcsv.rl"
1513
+ #line 140 "ext/fastcsv/fastcsv.rl"
1334
1514
  (*p) == quote_char ) _widec += 256;
1335
1515
  if (
1336
- #line 157 "ext/fastcsv/fastcsv.rl"
1516
+ #line 141 "ext/fastcsv/fastcsv.rl"
1337
1517
  (*p) == col_sep ) _widec += 512;
1338
1518
  if ( _widec < 1291 ) {
1339
1519
  if ( 1152 <= _widec && _widec <= 1289 )
@@ -1345,13 +1525,14 @@ case 8:
1345
1525
  goto st1;
1346
1526
  goto tr36;
1347
1527
  tr28:
1348
- #line 41 "ext/fastcsv/fastcsv.rl"
1528
+ #line 43 "ext/fastcsv/fastcsv.rl"
1349
1529
  {
1350
1530
  unclosed_line = curline;
1531
+ in_quoted_field = true;
1351
1532
  }
1352
1533
  goto st2;
1353
1534
  tr39:
1354
- #line 100 "ext/fastcsv/fastcsv.rl"
1535
+ #line 78 "ext/fastcsv/fastcsv.rl"
1355
1536
  {
1356
1537
  d->start = p;
1357
1538
 
@@ -1375,11 +1556,11 @@ st2:
1375
1556
  if ( ++p == pe )
1376
1557
  goto _test_eof2;
1377
1558
  case 2:
1378
- #line 1379 "ext/fastcsv/fastcsv.c"
1559
+ #line 1560 "ext/fastcsv/fastcsv.c"
1379
1560
  _widec = (*p);
1380
1561
  _widec = (short)(128 + ((*p) - -128));
1381
1562
  if (
1382
- #line 156 "ext/fastcsv/fastcsv.rl"
1563
+ #line 140 "ext/fastcsv/fastcsv.rl"
1383
1564
  (*p) == quote_char ) _widec += 256;
1384
1565
  if ( _widec < 257 ) {
1385
1566
  if ( 128 <= _widec && _widec <= 255 )
@@ -1391,87 +1572,25 @@ case 2:
1391
1572
  goto st2;
1392
1573
  goto tr0;
1393
1574
  tr11:
1394
- #line 60 "ext/fastcsv/fastcsv.rl"
1575
+ #line 63 "ext/fastcsv/fastcsv.rl"
1395
1576
  {
1396
- if (p == ts) {
1397
- field = rb_enc_str_new("", 0, encoding);
1398
- ENCODE;
1399
- }
1400
- // @note If we add an action on '""', we can skip some steps if no '""' is found.
1401
- else if (p > ts) {
1402
- // Operating on ts in-place produces odd behavior, FYI.
1403
- char *copy = ALLOC_N(char, p - ts);
1404
- memcpy(copy, ts, p - ts);
1405
-
1406
- char *reader = ts, *writer = copy;
1407
- int escaped = 0;
1408
-
1409
- while (p > reader) {
1410
- if (*reader == quote_char && !escaped) {
1411
- // Skip the escaping character.
1412
- escaped = 1;
1413
- }
1414
- else {
1415
- escaped = 0;
1416
- *writer++ = *reader;
1417
- }
1418
- reader++;
1419
- }
1420
-
1421
- field = rb_enc_str_new(copy, writer - copy, encoding);
1422
- ENCODE;
1423
-
1424
- if (copy != NULL) {
1425
- free(copy);
1426
- }
1427
- }
1577
+ // intentionally blank - see parse_quoted_field
1428
1578
  }
1429
- #line 45 "ext/fastcsv/fastcsv.rl"
1579
+ #line 48 "ext/fastcsv/fastcsv.rl"
1430
1580
  {
1431
1581
  unclosed_line = 0;
1432
1582
  }
1433
1583
  goto st3;
1434
1584
  tr40:
1435
- #line 60 "ext/fastcsv/fastcsv.rl"
1585
+ #line 63 "ext/fastcsv/fastcsv.rl"
1436
1586
  {
1437
- if (p == ts) {
1438
- field = rb_enc_str_new("", 0, encoding);
1439
- ENCODE;
1440
- }
1441
- // @note If we add an action on '""', we can skip some steps if no '""' is found.
1442
- else if (p > ts) {
1443
- // Operating on ts in-place produces odd behavior, FYI.
1444
- char *copy = ALLOC_N(char, p - ts);
1445
- memcpy(copy, ts, p - ts);
1446
-
1447
- char *reader = ts, *writer = copy;
1448
- int escaped = 0;
1449
-
1450
- while (p > reader) {
1451
- if (*reader == quote_char && !escaped) {
1452
- // Skip the escaping character.
1453
- escaped = 1;
1454
- }
1455
- else {
1456
- escaped = 0;
1457
- *writer++ = *reader;
1458
- }
1459
- reader++;
1460
- }
1461
-
1462
- field = rb_enc_str_new(copy, writer - copy, encoding);
1463
- ENCODE;
1464
-
1465
- if (copy != NULL) {
1466
- free(copy);
1467
- }
1468
- }
1587
+ // intentionally blank - see parse_quoted_field
1469
1588
  }
1470
- #line 45 "ext/fastcsv/fastcsv.rl"
1589
+ #line 48 "ext/fastcsv/fastcsv.rl"
1471
1590
  {
1472
1591
  unclosed_line = 0;
1473
1592
  }
1474
- #line 100 "ext/fastcsv/fastcsv.rl"
1593
+ #line 78 "ext/fastcsv/fastcsv.rl"
1475
1594
  {
1476
1595
  d->start = p;
1477
1596
 
@@ -1495,14 +1614,14 @@ st3:
1495
1614
  if ( ++p == pe )
1496
1615
  goto _test_eof3;
1497
1616
  case 3:
1498
- #line 1499 "ext/fastcsv/fastcsv.c"
1617
+ #line 1618 "ext/fastcsv/fastcsv.c"
1499
1618
  _widec = (*p);
1500
1619
  _widec = (short)(1152 + ((*p) - -128));
1501
1620
  if (
1502
- #line 156 "ext/fastcsv/fastcsv.rl"
1621
+ #line 140 "ext/fastcsv/fastcsv.rl"
1503
1622
  (*p) == quote_char ) _widec += 256;
1504
1623
  if (
1505
- #line 157 "ext/fastcsv/fastcsv.rl"
1624
+ #line 141 "ext/fastcsv/fastcsv.rl"
1506
1625
  (*p) == col_sep ) _widec += 512;
1507
1626
  switch( _widec ) {
1508
1627
  case 1280: goto tr12;
@@ -1530,7 +1649,7 @@ case 3:
1530
1649
  tr15:
1531
1650
  #line 1 "NONE"
1532
1651
  {te = p+1;}
1533
- #line 138 "ext/fastcsv/fastcsv.rl"
1652
+ #line 122 "ext/fastcsv/fastcsv.rl"
1534
1653
  {
1535
1654
  if (d->start == 0 || p == d->start) { // same as new_row
1536
1655
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1547,31 +1666,43 @@ tr15:
1547
1666
  rb_yield(row);
1548
1667
  }
1549
1668
  }
1550
- #line 170 "ext/fastcsv/fastcsv.rl"
1669
+ #line 154 "ext/fastcsv/fastcsv.rl"
1551
1670
  {act = 3;}
1552
1671
  goto st9;
1553
1672
  tr22:
1554
1673
  #line 1 "NONE"
1555
1674
  {te = p+1;}
1556
- #line 95 "ext/fastcsv/fastcsv.rl"
1675
+ #line 67 "ext/fastcsv/fastcsv.rl"
1557
1676
  {
1677
+ if (in_quoted_field) {
1678
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1679
+ ENCODE;
1680
+ in_quoted_field = false;
1681
+ }
1682
+
1558
1683
  rb_ary_push(row, field);
1559
1684
  field = Qnil;
1560
1685
  }
1561
- #line 168 "ext/fastcsv/fastcsv.rl"
1686
+ #line 152 "ext/fastcsv/fastcsv.rl"
1562
1687
  {act = 1;}
1563
1688
  goto st9;
1564
1689
  tr23:
1565
1690
  #line 1 "NONE"
1566
1691
  {te = p+1;}
1567
- #line 95 "ext/fastcsv/fastcsv.rl"
1692
+ #line 67 "ext/fastcsv/fastcsv.rl"
1568
1693
  {
1694
+ if (in_quoted_field) {
1695
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1696
+ ENCODE;
1697
+ in_quoted_field = false;
1698
+ }
1699
+
1569
1700
  rb_ary_push(row, field);
1570
1701
  field = Qnil;
1571
1702
  }
1572
- #line 168 "ext/fastcsv/fastcsv.rl"
1703
+ #line 152 "ext/fastcsv/fastcsv.rl"
1573
1704
  {act = 1;}
1574
- #line 138 "ext/fastcsv/fastcsv.rl"
1705
+ #line 122 "ext/fastcsv/fastcsv.rl"
1575
1706
  {
1576
1707
  if (d->start == 0 || p == d->start) { // same as new_row
1577
1708
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1592,11 +1723,12 @@ tr23:
1592
1723
  tr29:
1593
1724
  #line 1 "NONE"
1594
1725
  {te = p+1;}
1595
- #line 41 "ext/fastcsv/fastcsv.rl"
1726
+ #line 43 "ext/fastcsv/fastcsv.rl"
1596
1727
  {
1597
1728
  unclosed_line = curline;
1729
+ in_quoted_field = true;
1598
1730
  }
1599
- #line 49 "ext/fastcsv/fastcsv.rl"
1731
+ #line 52 "ext/fastcsv/fastcsv.rl"
1600
1732
  {
1601
1733
  if (p == ts) {
1602
1734
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1607,7 +1739,7 @@ tr29:
1607
1739
  ENCODE;
1608
1740
  }
1609
1741
  }
1610
- #line 138 "ext/fastcsv/fastcsv.rl"
1742
+ #line 122 "ext/fastcsv/fastcsv.rl"
1611
1743
  {
1612
1744
  if (d->start == 0 || p == d->start) { // same as new_row
1613
1745
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1624,13 +1756,13 @@ tr29:
1624
1756
  rb_yield(row);
1625
1757
  }
1626
1758
  }
1627
- #line 170 "ext/fastcsv/fastcsv.rl"
1759
+ #line 154 "ext/fastcsv/fastcsv.rl"
1628
1760
  {act = 3;}
1629
1761
  goto st9;
1630
1762
  tr32:
1631
1763
  #line 1 "NONE"
1632
1764
  {te = p+1;}
1633
- #line 49 "ext/fastcsv/fastcsv.rl"
1765
+ #line 52 "ext/fastcsv/fastcsv.rl"
1634
1766
  {
1635
1767
  if (p == ts) {
1636
1768
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1641,22 +1773,29 @@ tr32:
1641
1773
  ENCODE;
1642
1774
  }
1643
1775
  }
1644
- #line 41 "ext/fastcsv/fastcsv.rl"
1776
+ #line 43 "ext/fastcsv/fastcsv.rl"
1645
1777
  {
1646
1778
  unclosed_line = curline;
1779
+ in_quoted_field = true;
1647
1780
  }
1648
- #line 95 "ext/fastcsv/fastcsv.rl"
1781
+ #line 67 "ext/fastcsv/fastcsv.rl"
1649
1782
  {
1783
+ if (in_quoted_field) {
1784
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1785
+ ENCODE;
1786
+ in_quoted_field = false;
1787
+ }
1788
+
1650
1789
  rb_ary_push(row, field);
1651
1790
  field = Qnil;
1652
1791
  }
1653
- #line 168 "ext/fastcsv/fastcsv.rl"
1792
+ #line 152 "ext/fastcsv/fastcsv.rl"
1654
1793
  {act = 1;}
1655
1794
  goto st9;
1656
1795
  tr33:
1657
1796
  #line 1 "NONE"
1658
1797
  {te = p+1;}
1659
- #line 49 "ext/fastcsv/fastcsv.rl"
1798
+ #line 52 "ext/fastcsv/fastcsv.rl"
1660
1799
  {
1661
1800
  if (p == ts) {
1662
1801
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1667,18 +1806,25 @@ tr33:
1667
1806
  ENCODE;
1668
1807
  }
1669
1808
  }
1670
- #line 41 "ext/fastcsv/fastcsv.rl"
1809
+ #line 43 "ext/fastcsv/fastcsv.rl"
1671
1810
  {
1672
1811
  unclosed_line = curline;
1812
+ in_quoted_field = true;
1673
1813
  }
1674
- #line 95 "ext/fastcsv/fastcsv.rl"
1814
+ #line 67 "ext/fastcsv/fastcsv.rl"
1675
1815
  {
1816
+ if (in_quoted_field) {
1817
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1818
+ ENCODE;
1819
+ in_quoted_field = false;
1820
+ }
1821
+
1676
1822
  rb_ary_push(row, field);
1677
1823
  field = Qnil;
1678
1824
  }
1679
- #line 168 "ext/fastcsv/fastcsv.rl"
1825
+ #line 152 "ext/fastcsv/fastcsv.rl"
1680
1826
  {act = 1;}
1681
- #line 138 "ext/fastcsv/fastcsv.rl"
1827
+ #line 122 "ext/fastcsv/fastcsv.rl"
1682
1828
  {
1683
1829
  if (d->start == 0 || p == d->start) { // same as new_row
1684
1830
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1699,7 +1845,7 @@ tr33:
1699
1845
  tr48:
1700
1846
  #line 1 "NONE"
1701
1847
  {te = p+1;}
1702
- #line 100 "ext/fastcsv/fastcsv.rl"
1848
+ #line 78 "ext/fastcsv/fastcsv.rl"
1703
1849
  {
1704
1850
  d->start = p;
1705
1851
 
@@ -1718,7 +1864,7 @@ tr48:
1718
1864
 
1719
1865
  curline++;
1720
1866
  }
1721
- #line 138 "ext/fastcsv/fastcsv.rl"
1867
+ #line 122 "ext/fastcsv/fastcsv.rl"
1722
1868
  {
1723
1869
  if (d->start == 0 || p == d->start) { // same as new_row
1724
1870
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1735,20 +1881,26 @@ tr48:
1735
1881
  rb_yield(row);
1736
1882
  }
1737
1883
  }
1738
- #line 170 "ext/fastcsv/fastcsv.rl"
1884
+ #line 154 "ext/fastcsv/fastcsv.rl"
1739
1885
  {act = 3;}
1740
1886
  goto st9;
1741
1887
  tr55:
1742
1888
  #line 1 "NONE"
1743
1889
  {te = p+1;}
1744
- #line 95 "ext/fastcsv/fastcsv.rl"
1890
+ #line 67 "ext/fastcsv/fastcsv.rl"
1745
1891
  {
1892
+ if (in_quoted_field) {
1893
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1894
+ ENCODE;
1895
+ in_quoted_field = false;
1896
+ }
1897
+
1746
1898
  rb_ary_push(row, field);
1747
1899
  field = Qnil;
1748
1900
  }
1749
- #line 168 "ext/fastcsv/fastcsv.rl"
1901
+ #line 152 "ext/fastcsv/fastcsv.rl"
1750
1902
  {act = 1;}
1751
- #line 100 "ext/fastcsv/fastcsv.rl"
1903
+ #line 78 "ext/fastcsv/fastcsv.rl"
1752
1904
  {
1753
1905
  d->start = p;
1754
1906
 
@@ -1771,14 +1923,20 @@ tr55:
1771
1923
  tr56:
1772
1924
  #line 1 "NONE"
1773
1925
  {te = p+1;}
1774
- #line 95 "ext/fastcsv/fastcsv.rl"
1926
+ #line 67 "ext/fastcsv/fastcsv.rl"
1775
1927
  {
1928
+ if (in_quoted_field) {
1929
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
1930
+ ENCODE;
1931
+ in_quoted_field = false;
1932
+ }
1933
+
1776
1934
  rb_ary_push(row, field);
1777
1935
  field = Qnil;
1778
1936
  }
1779
- #line 168 "ext/fastcsv/fastcsv.rl"
1937
+ #line 152 "ext/fastcsv/fastcsv.rl"
1780
1938
  {act = 1;}
1781
- #line 100 "ext/fastcsv/fastcsv.rl"
1939
+ #line 78 "ext/fastcsv/fastcsv.rl"
1782
1940
  {
1783
1941
  d->start = p;
1784
1942
 
@@ -1797,7 +1955,7 @@ tr56:
1797
1955
 
1798
1956
  curline++;
1799
1957
  }
1800
- #line 138 "ext/fastcsv/fastcsv.rl"
1958
+ #line 122 "ext/fastcsv/fastcsv.rl"
1801
1959
  {
1802
1960
  if (d->start == 0 || p == d->start) { // same as new_row
1803
1961
  rb_ivar_set(self, s_row, rb_str_new2(""));
@@ -1819,11 +1977,11 @@ st9:
1819
1977
  if ( ++p == pe )
1820
1978
  goto _test_eof9;
1821
1979
  case 9:
1822
- #line 1823 "ext/fastcsv/fastcsv.c"
1980
+ #line 1981 "ext/fastcsv/fastcsv.c"
1823
1981
  _widec = (*p);
1824
1982
  _widec = (short)(128 + ((*p) - -128));
1825
1983
  if (
1826
- #line 156 "ext/fastcsv/fastcsv.rl"
1984
+ #line 140 "ext/fastcsv/fastcsv.rl"
1827
1985
  (*p) == quote_char ) _widec += 256;
1828
1986
  if ( _widec < 257 ) {
1829
1987
  if ( 128 <= _widec && _widec <= 255 )
@@ -1837,7 +1995,7 @@ case 9:
1837
1995
  tr16:
1838
1996
  #line 1 "NONE"
1839
1997
  {te = p+1;}
1840
- #line 119 "ext/fastcsv/fastcsv.rl"
1998
+ #line 97 "ext/fastcsv/fastcsv.rl"
1841
1999
  {
1842
2000
  mark_row_sep = p;
1843
2001
 
@@ -1848,6 +2006,12 @@ tr16:
1848
2006
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1849
2007
  }
1850
2008
 
2009
+ if (in_quoted_field) {
2010
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2011
+ ENCODE;
2012
+ in_quoted_field = false;
2013
+ }
2014
+
1851
2015
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1852
2016
  rb_ary_push(row, field);
1853
2017
  field = Qnil;
@@ -1856,20 +2020,26 @@ tr16:
1856
2020
  rb_yield(row);
1857
2021
  row = rb_ary_new();
1858
2022
  }
1859
- #line 169 "ext/fastcsv/fastcsv.rl"
2023
+ #line 153 "ext/fastcsv/fastcsv.rl"
1860
2024
  {act = 2;}
1861
2025
  goto st10;
1862
2026
  tr24:
1863
2027
  #line 1 "NONE"
1864
2028
  {te = p+1;}
1865
- #line 95 "ext/fastcsv/fastcsv.rl"
2029
+ #line 67 "ext/fastcsv/fastcsv.rl"
1866
2030
  {
2031
+ if (in_quoted_field) {
2032
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2033
+ ENCODE;
2034
+ in_quoted_field = false;
2035
+ }
2036
+
1867
2037
  rb_ary_push(row, field);
1868
2038
  field = Qnil;
1869
2039
  }
1870
- #line 168 "ext/fastcsv/fastcsv.rl"
2040
+ #line 152 "ext/fastcsv/fastcsv.rl"
1871
2041
  {act = 1;}
1872
- #line 119 "ext/fastcsv/fastcsv.rl"
2042
+ #line 97 "ext/fastcsv/fastcsv.rl"
1873
2043
  {
1874
2044
  mark_row_sep = p;
1875
2045
 
@@ -1880,6 +2050,12 @@ tr24:
1880
2050
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1881
2051
  }
1882
2052
 
2053
+ if (in_quoted_field) {
2054
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2055
+ ENCODE;
2056
+ in_quoted_field = false;
2057
+ }
2058
+
1883
2059
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1884
2060
  rb_ary_push(row, field);
1885
2061
  field = Qnil;
@@ -1892,11 +2068,12 @@ tr24:
1892
2068
  tr30:
1893
2069
  #line 1 "NONE"
1894
2070
  {te = p+1;}
1895
- #line 41 "ext/fastcsv/fastcsv.rl"
2071
+ #line 43 "ext/fastcsv/fastcsv.rl"
1896
2072
  {
1897
2073
  unclosed_line = curline;
2074
+ in_quoted_field = true;
1898
2075
  }
1899
- #line 49 "ext/fastcsv/fastcsv.rl"
2076
+ #line 52 "ext/fastcsv/fastcsv.rl"
1900
2077
  {
1901
2078
  if (p == ts) {
1902
2079
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1907,7 +2084,7 @@ tr30:
1907
2084
  ENCODE;
1908
2085
  }
1909
2086
  }
1910
- #line 119 "ext/fastcsv/fastcsv.rl"
2087
+ #line 97 "ext/fastcsv/fastcsv.rl"
1911
2088
  {
1912
2089
  mark_row_sep = p;
1913
2090
 
@@ -1918,6 +2095,12 @@ tr30:
1918
2095
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1919
2096
  }
1920
2097
 
2098
+ if (in_quoted_field) {
2099
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2100
+ ENCODE;
2101
+ in_quoted_field = false;
2102
+ }
2103
+
1921
2104
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1922
2105
  rb_ary_push(row, field);
1923
2106
  field = Qnil;
@@ -1926,13 +2109,13 @@ tr30:
1926
2109
  rb_yield(row);
1927
2110
  row = rb_ary_new();
1928
2111
  }
1929
- #line 169 "ext/fastcsv/fastcsv.rl"
2112
+ #line 153 "ext/fastcsv/fastcsv.rl"
1930
2113
  {act = 2;}
1931
2114
  goto st10;
1932
2115
  tr34:
1933
2116
  #line 1 "NONE"
1934
2117
  {te = p+1;}
1935
- #line 49 "ext/fastcsv/fastcsv.rl"
2118
+ #line 52 "ext/fastcsv/fastcsv.rl"
1936
2119
  {
1937
2120
  if (p == ts) {
1938
2121
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -1943,18 +2126,25 @@ tr34:
1943
2126
  ENCODE;
1944
2127
  }
1945
2128
  }
1946
- #line 41 "ext/fastcsv/fastcsv.rl"
2129
+ #line 43 "ext/fastcsv/fastcsv.rl"
1947
2130
  {
1948
2131
  unclosed_line = curline;
2132
+ in_quoted_field = true;
1949
2133
  }
1950
- #line 95 "ext/fastcsv/fastcsv.rl"
2134
+ #line 67 "ext/fastcsv/fastcsv.rl"
1951
2135
  {
2136
+ if (in_quoted_field) {
2137
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2138
+ ENCODE;
2139
+ in_quoted_field = false;
2140
+ }
2141
+
1952
2142
  rb_ary_push(row, field);
1953
2143
  field = Qnil;
1954
2144
  }
1955
- #line 168 "ext/fastcsv/fastcsv.rl"
2145
+ #line 152 "ext/fastcsv/fastcsv.rl"
1956
2146
  {act = 1;}
1957
- #line 119 "ext/fastcsv/fastcsv.rl"
2147
+ #line 97 "ext/fastcsv/fastcsv.rl"
1958
2148
  {
1959
2149
  mark_row_sep = p;
1960
2150
 
@@ -1965,6 +2155,12 @@ tr34:
1965
2155
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
1966
2156
  }
1967
2157
 
2158
+ if (in_quoted_field) {
2159
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2160
+ ENCODE;
2161
+ in_quoted_field = false;
2162
+ }
2163
+
1968
2164
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
1969
2165
  rb_ary_push(row, field);
1970
2166
  field = Qnil;
@@ -1977,7 +2173,7 @@ tr34:
1977
2173
  tr41:
1978
2174
  #line 1 "NONE"
1979
2175
  {te = p+1;}
1980
- #line 100 "ext/fastcsv/fastcsv.rl"
2176
+ #line 78 "ext/fastcsv/fastcsv.rl"
1981
2177
  {
1982
2178
  d->start = p;
1983
2179
 
@@ -1996,13 +2192,13 @@ tr41:
1996
2192
 
1997
2193
  curline++;
1998
2194
  }
1999
- #line 169 "ext/fastcsv/fastcsv.rl"
2195
+ #line 153 "ext/fastcsv/fastcsv.rl"
2000
2196
  {act = 2;}
2001
2197
  goto st10;
2002
2198
  tr49:
2003
2199
  #line 1 "NONE"
2004
2200
  {te = p+1;}
2005
- #line 119 "ext/fastcsv/fastcsv.rl"
2201
+ #line 97 "ext/fastcsv/fastcsv.rl"
2006
2202
  {
2007
2203
  mark_row_sep = p;
2008
2204
 
@@ -2013,6 +2209,12 @@ tr49:
2013
2209
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2014
2210
  }
2015
2211
 
2212
+ if (in_quoted_field) {
2213
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2214
+ ENCODE;
2215
+ in_quoted_field = false;
2216
+ }
2217
+
2016
2218
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2017
2219
  rb_ary_push(row, field);
2018
2220
  field = Qnil;
@@ -2021,7 +2223,7 @@ tr49:
2021
2223
  rb_yield(row);
2022
2224
  row = rb_ary_new();
2023
2225
  }
2024
- #line 100 "ext/fastcsv/fastcsv.rl"
2226
+ #line 78 "ext/fastcsv/fastcsv.rl"
2025
2227
  {
2026
2228
  d->start = p;
2027
2229
 
@@ -2040,20 +2242,26 @@ tr49:
2040
2242
 
2041
2243
  curline++;
2042
2244
  }
2043
- #line 169 "ext/fastcsv/fastcsv.rl"
2245
+ #line 153 "ext/fastcsv/fastcsv.rl"
2044
2246
  {act = 2;}
2045
2247
  goto st10;
2046
2248
  tr57:
2047
2249
  #line 1 "NONE"
2048
2250
  {te = p+1;}
2049
- #line 95 "ext/fastcsv/fastcsv.rl"
2251
+ #line 67 "ext/fastcsv/fastcsv.rl"
2050
2252
  {
2253
+ if (in_quoted_field) {
2254
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2255
+ ENCODE;
2256
+ in_quoted_field = false;
2257
+ }
2258
+
2051
2259
  rb_ary_push(row, field);
2052
2260
  field = Qnil;
2053
2261
  }
2054
- #line 168 "ext/fastcsv/fastcsv.rl"
2262
+ #line 152 "ext/fastcsv/fastcsv.rl"
2055
2263
  {act = 1;}
2056
- #line 119 "ext/fastcsv/fastcsv.rl"
2264
+ #line 97 "ext/fastcsv/fastcsv.rl"
2057
2265
  {
2058
2266
  mark_row_sep = p;
2059
2267
 
@@ -2064,6 +2272,12 @@ tr57:
2064
2272
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2065
2273
  }
2066
2274
 
2275
+ if (in_quoted_field) {
2276
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2277
+ ENCODE;
2278
+ in_quoted_field = false;
2279
+ }
2280
+
2067
2281
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2068
2282
  rb_ary_push(row, field);
2069
2283
  field = Qnil;
@@ -2072,7 +2286,7 @@ tr57:
2072
2286
  rb_yield(row);
2073
2287
  row = rb_ary_new();
2074
2288
  }
2075
- #line 100 "ext/fastcsv/fastcsv.rl"
2289
+ #line 78 "ext/fastcsv/fastcsv.rl"
2076
2290
  {
2077
2291
  d->start = p;
2078
2292
 
@@ -2096,24 +2310,24 @@ st10:
2096
2310
  if ( ++p == pe )
2097
2311
  goto _test_eof10;
2098
2312
  case 10:
2099
- #line 2100 "ext/fastcsv/fastcsv.c"
2313
+ #line 2314 "ext/fastcsv/fastcsv.c"
2100
2314
  _widec = (*p);
2101
2315
  _widec = (short)(128 + ((*p) - -128));
2102
2316
  if (
2103
- #line 156 "ext/fastcsv/fastcsv.rl"
2317
+ #line 140 "ext/fastcsv/fastcsv.rl"
2104
2318
  (*p) == quote_char ) _widec += 256;
2105
2319
  if ( _widec == 256 )
2106
2320
  goto tr37;
2107
- if ( _widec > 383 ) {
2108
- if ( 384 <= _widec && _widec <= 639 )
2109
- goto tr40;
2110
- } else if ( _widec >= 128 )
2111
- goto tr39;
2112
- goto tr0;
2321
+ if ( _widec > 127 ) {
2322
+ if ( 128 <= _widec && _widec <= 383 )
2323
+ goto tr39;
2324
+ } else
2325
+ goto tr0;
2326
+ goto tr40;
2113
2327
  tr17:
2114
2328
  #line 1 "NONE"
2115
2329
  {te = p+1;}
2116
- #line 119 "ext/fastcsv/fastcsv.rl"
2330
+ #line 97 "ext/fastcsv/fastcsv.rl"
2117
2331
  {
2118
2332
  mark_row_sep = p;
2119
2333
 
@@ -2124,6 +2338,12 @@ tr17:
2124
2338
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2125
2339
  }
2126
2340
 
2341
+ if (in_quoted_field) {
2342
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2343
+ ENCODE;
2344
+ in_quoted_field = false;
2345
+ }
2346
+
2127
2347
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2128
2348
  rb_ary_push(row, field);
2129
2349
  field = Qnil;
@@ -2132,20 +2352,26 @@ tr17:
2132
2352
  rb_yield(row);
2133
2353
  row = rb_ary_new();
2134
2354
  }
2135
- #line 169 "ext/fastcsv/fastcsv.rl"
2355
+ #line 153 "ext/fastcsv/fastcsv.rl"
2136
2356
  {act = 2;}
2137
2357
  goto st11;
2138
2358
  tr25:
2139
2359
  #line 1 "NONE"
2140
2360
  {te = p+1;}
2141
- #line 95 "ext/fastcsv/fastcsv.rl"
2361
+ #line 67 "ext/fastcsv/fastcsv.rl"
2142
2362
  {
2363
+ if (in_quoted_field) {
2364
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2365
+ ENCODE;
2366
+ in_quoted_field = false;
2367
+ }
2368
+
2143
2369
  rb_ary_push(row, field);
2144
2370
  field = Qnil;
2145
2371
  }
2146
- #line 168 "ext/fastcsv/fastcsv.rl"
2372
+ #line 152 "ext/fastcsv/fastcsv.rl"
2147
2373
  {act = 1;}
2148
- #line 119 "ext/fastcsv/fastcsv.rl"
2374
+ #line 97 "ext/fastcsv/fastcsv.rl"
2149
2375
  {
2150
2376
  mark_row_sep = p;
2151
2377
 
@@ -2156,6 +2382,12 @@ tr25:
2156
2382
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2157
2383
  }
2158
2384
 
2385
+ if (in_quoted_field) {
2386
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2387
+ ENCODE;
2388
+ in_quoted_field = false;
2389
+ }
2390
+
2159
2391
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2160
2392
  rb_ary_push(row, field);
2161
2393
  field = Qnil;
@@ -2168,11 +2400,12 @@ tr25:
2168
2400
  tr31:
2169
2401
  #line 1 "NONE"
2170
2402
  {te = p+1;}
2171
- #line 41 "ext/fastcsv/fastcsv.rl"
2403
+ #line 43 "ext/fastcsv/fastcsv.rl"
2172
2404
  {
2173
2405
  unclosed_line = curline;
2406
+ in_quoted_field = true;
2174
2407
  }
2175
- #line 49 "ext/fastcsv/fastcsv.rl"
2408
+ #line 52 "ext/fastcsv/fastcsv.rl"
2176
2409
  {
2177
2410
  if (p == ts) {
2178
2411
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -2183,7 +2416,7 @@ tr31:
2183
2416
  ENCODE;
2184
2417
  }
2185
2418
  }
2186
- #line 119 "ext/fastcsv/fastcsv.rl"
2419
+ #line 97 "ext/fastcsv/fastcsv.rl"
2187
2420
  {
2188
2421
  mark_row_sep = p;
2189
2422
 
@@ -2194,6 +2427,12 @@ tr31:
2194
2427
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2195
2428
  }
2196
2429
 
2430
+ if (in_quoted_field) {
2431
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2432
+ ENCODE;
2433
+ in_quoted_field = false;
2434
+ }
2435
+
2197
2436
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2198
2437
  rb_ary_push(row, field);
2199
2438
  field = Qnil;
@@ -2202,13 +2441,13 @@ tr31:
2202
2441
  rb_yield(row);
2203
2442
  row = rb_ary_new();
2204
2443
  }
2205
- #line 169 "ext/fastcsv/fastcsv.rl"
2444
+ #line 153 "ext/fastcsv/fastcsv.rl"
2206
2445
  {act = 2;}
2207
2446
  goto st11;
2208
2447
  tr35:
2209
2448
  #line 1 "NONE"
2210
2449
  {te = p+1;}
2211
- #line 49 "ext/fastcsv/fastcsv.rl"
2450
+ #line 52 "ext/fastcsv/fastcsv.rl"
2212
2451
  {
2213
2452
  if (p == ts) {
2214
2453
  // Unquoted empty fields are nil, not "", in Ruby.
@@ -2219,18 +2458,25 @@ tr35:
2219
2458
  ENCODE;
2220
2459
  }
2221
2460
  }
2222
- #line 41 "ext/fastcsv/fastcsv.rl"
2461
+ #line 43 "ext/fastcsv/fastcsv.rl"
2223
2462
  {
2224
2463
  unclosed_line = curline;
2464
+ in_quoted_field = true;
2225
2465
  }
2226
- #line 95 "ext/fastcsv/fastcsv.rl"
2466
+ #line 67 "ext/fastcsv/fastcsv.rl"
2227
2467
  {
2468
+ if (in_quoted_field) {
2469
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2470
+ ENCODE;
2471
+ in_quoted_field = false;
2472
+ }
2473
+
2228
2474
  rb_ary_push(row, field);
2229
2475
  field = Qnil;
2230
2476
  }
2231
- #line 168 "ext/fastcsv/fastcsv.rl"
2477
+ #line 152 "ext/fastcsv/fastcsv.rl"
2232
2478
  {act = 1;}
2233
- #line 119 "ext/fastcsv/fastcsv.rl"
2479
+ #line 97 "ext/fastcsv/fastcsv.rl"
2234
2480
  {
2235
2481
  mark_row_sep = p;
2236
2482
 
@@ -2241,6 +2487,12 @@ tr35:
2241
2487
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2242
2488
  }
2243
2489
 
2490
+ if (in_quoted_field) {
2491
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2492
+ ENCODE;
2493
+ in_quoted_field = false;
2494
+ }
2495
+
2244
2496
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2245
2497
  rb_ary_push(row, field);
2246
2498
  field = Qnil;
@@ -2253,7 +2505,7 @@ tr35:
2253
2505
  tr50:
2254
2506
  #line 1 "NONE"
2255
2507
  {te = p+1;}
2256
- #line 119 "ext/fastcsv/fastcsv.rl"
2508
+ #line 97 "ext/fastcsv/fastcsv.rl"
2257
2509
  {
2258
2510
  mark_row_sep = p;
2259
2511
 
@@ -2264,6 +2516,12 @@ tr50:
2264
2516
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2265
2517
  }
2266
2518
 
2519
+ if (in_quoted_field) {
2520
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2521
+ ENCODE;
2522
+ in_quoted_field = false;
2523
+ }
2524
+
2267
2525
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2268
2526
  rb_ary_push(row, field);
2269
2527
  field = Qnil;
@@ -2272,7 +2530,7 @@ tr50:
2272
2530
  rb_yield(row);
2273
2531
  row = rb_ary_new();
2274
2532
  }
2275
- #line 100 "ext/fastcsv/fastcsv.rl"
2533
+ #line 78 "ext/fastcsv/fastcsv.rl"
2276
2534
  {
2277
2535
  d->start = p;
2278
2536
 
@@ -2291,20 +2549,26 @@ tr50:
2291
2549
 
2292
2550
  curline++;
2293
2551
  }
2294
- #line 169 "ext/fastcsv/fastcsv.rl"
2552
+ #line 153 "ext/fastcsv/fastcsv.rl"
2295
2553
  {act = 2;}
2296
2554
  goto st11;
2297
2555
  tr58:
2298
2556
  #line 1 "NONE"
2299
2557
  {te = p+1;}
2300
- #line 95 "ext/fastcsv/fastcsv.rl"
2558
+ #line 67 "ext/fastcsv/fastcsv.rl"
2301
2559
  {
2560
+ if (in_quoted_field) {
2561
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2562
+ ENCODE;
2563
+ in_quoted_field = false;
2564
+ }
2565
+
2302
2566
  rb_ary_push(row, field);
2303
2567
  field = Qnil;
2304
2568
  }
2305
- #line 168 "ext/fastcsv/fastcsv.rl"
2569
+ #line 152 "ext/fastcsv/fastcsv.rl"
2306
2570
  {act = 1;}
2307
- #line 119 "ext/fastcsv/fastcsv.rl"
2571
+ #line 97 "ext/fastcsv/fastcsv.rl"
2308
2572
  {
2309
2573
  mark_row_sep = p;
2310
2574
 
@@ -2315,6 +2579,12 @@ tr58:
2315
2579
  rb_ivar_set(self, s_row, rb_str_new(d->start, p - d->start));
2316
2580
  }
2317
2581
 
2582
+ if (in_quoted_field) {
2583
+ parse_quoted_field(&field, encoding, quote_char, ts + 1, p - 1);
2584
+ ENCODE;
2585
+ in_quoted_field = false;
2586
+ }
2587
+
2318
2588
  if (!NIL_P(field) || RARRAY_LEN(row)) { // same as new_field
2319
2589
  rb_ary_push(row, field);
2320
2590
  field = Qnil;
@@ -2323,7 +2593,7 @@ tr58:
2323
2593
  rb_yield(row);
2324
2594
  row = rb_ary_new();
2325
2595
  }
2326
- #line 100 "ext/fastcsv/fastcsv.rl"
2596
+ #line 78 "ext/fastcsv/fastcsv.rl"
2327
2597
  {
2328
2598
  d->start = p;
2329
2599
 
@@ -2347,11 +2617,11 @@ st11:
2347
2617
  if ( ++p == pe )
2348
2618
  goto _test_eof11;
2349
2619
  case 11:
2350
- #line 2351 "ext/fastcsv/fastcsv.c"
2620
+ #line 2621 "ext/fastcsv/fastcsv.c"
2351
2621
  _widec = (*p);
2352
2622
  _widec = (short)(128 + ((*p) - -128));
2353
2623
  if (
2354
- #line 156 "ext/fastcsv/fastcsv.rl"
2624
+ #line 140 "ext/fastcsv/fastcsv.rl"
2355
2625
  (*p) == quote_char ) _widec += 256;
2356
2626
  switch( _widec ) {
2357
2627
  case 256: goto tr37;
@@ -2367,46 +2637,15 @@ case 11:
2367
2637
  tr42:
2368
2638
  #line 1 "NONE"
2369
2639
  {te = p+1;}
2370
- #line 60 "ext/fastcsv/fastcsv.rl"
2640
+ #line 63 "ext/fastcsv/fastcsv.rl"
2371
2641
  {
2372
- if (p == ts) {
2373
- field = rb_enc_str_new("", 0, encoding);
2374
- ENCODE;
2375
- }
2376
- // @note If we add an action on '""', we can skip some steps if no '""' is found.
2377
- else if (p > ts) {
2378
- // Operating on ts in-place produces odd behavior, FYI.
2379
- char *copy = ALLOC_N(char, p - ts);
2380
- memcpy(copy, ts, p - ts);
2381
-
2382
- char *reader = ts, *writer = copy;
2383
- int escaped = 0;
2384
-
2385
- while (p > reader) {
2386
- if (*reader == quote_char && !escaped) {
2387
- // Skip the escaping character.
2388
- escaped = 1;
2389
- }
2390
- else {
2391
- escaped = 0;
2392
- *writer++ = *reader;
2393
- }
2394
- reader++;
2395
- }
2396
-
2397
- field = rb_enc_str_new(copy, writer - copy, encoding);
2398
- ENCODE;
2399
-
2400
- if (copy != NULL) {
2401
- free(copy);
2402
- }
2403
- }
2642
+ // intentionally blank - see parse_quoted_field
2404
2643
  }
2405
- #line 45 "ext/fastcsv/fastcsv.rl"
2644
+ #line 48 "ext/fastcsv/fastcsv.rl"
2406
2645
  {
2407
2646
  unclosed_line = 0;
2408
2647
  }
2409
- #line 100 "ext/fastcsv/fastcsv.rl"
2648
+ #line 78 "ext/fastcsv/fastcsv.rl"
2410
2649
  {
2411
2650
  d->start = p;
2412
2651
 
@@ -2425,21 +2664,21 @@ tr42:
2425
2664
 
2426
2665
  curline++;
2427
2666
  }
2428
- #line 169 "ext/fastcsv/fastcsv.rl"
2667
+ #line 153 "ext/fastcsv/fastcsv.rl"
2429
2668
  {act = 2;}
2430
2669
  goto st12;
2431
2670
  st12:
2432
2671
  if ( ++p == pe )
2433
2672
  goto _test_eof12;
2434
2673
  case 12:
2435
- #line 2436 "ext/fastcsv/fastcsv.c"
2674
+ #line 2675 "ext/fastcsv/fastcsv.c"
2436
2675
  _widec = (*p);
2437
2676
  _widec = (short)(1152 + ((*p) - -128));
2438
2677
  if (
2439
- #line 156 "ext/fastcsv/fastcsv.rl"
2678
+ #line 140 "ext/fastcsv/fastcsv.rl"
2440
2679
  (*p) == quote_char ) _widec += 256;
2441
2680
  if (
2442
- #line 157 "ext/fastcsv/fastcsv.rl"
2681
+ #line 141 "ext/fastcsv/fastcsv.rl"
2443
2682
  (*p) == col_sep ) _widec += 512;
2444
2683
  switch( _widec ) {
2445
2684
  case 1280: goto tr45;
@@ -2502,7 +2741,7 @@ case 12:
2502
2741
  _out: {}
2503
2742
  }
2504
2743
 
2505
- #line 447 "ext/fastcsv/fastcsv.rl"
2744
+ #line 465 "ext/fastcsv/fastcsv.rl"
2506
2745
 
2507
2746
  if (done && cs < raw_parse_first_final) {
2508
2747
  if (d->start == 0 || p == d->start) { // same as new_row