@@ -681,6 +681,8 @@ static void parse_double_regular_core(const char **pch, double *target)
681681 static const int_fast32_t FLOAT_MAX_DIGITS = 18 ;
682682 const char * ch = * pch ;
683683
684+ * target = NA_FLOAT64 ;
685+
684686 if (* ch == '0' && args .keepLeadingZeros && IS_DIGIT (ch [1 ])) return ;
685687 bool neg , Eneg ;
686688 ch += (neg = * ch == '-' ) + (* ch == '+' );
@@ -710,7 +712,7 @@ static void parse_double_regular_core(const char **pch, double *target)
710712 ch ++ ;
711713 e ++ ;
712714 }
713- if (* ch != dec && * ch != 'e' && * ch != 'E' ) goto fail ;
715+ if (* ch != dec && * ch != 'e' && * ch != 'E' ) return ;
714716 }
715717
716718 // Read the fractional part of the number, if it's present
@@ -743,17 +745,17 @@ static void parse_double_regular_core(const char **pch, double *target)
743745 }
744746 // Check that at least 1 digit was present in either the integer or
745747 // fractional part ("+1" here accounts for the decimal point char).
746- if (ch == start + 1 ) goto fail ;
748+ if (ch == start + 1 ) return ;
747749 }
748750 // If there is no fractional part, then check that the integer part actually
749751 // exists (otherwise it's not a valid number)...
750752 else {
751- if (ch == start ) goto fail ;
753+ if (ch == start ) return ;
752754 }
753755
754756 // Finally parse the "exponent" part of the number (if present)
755757 if (* ch == 'E' || * ch == 'e' ) {
756- if (ch == start ) goto fail ; // something valid must be between [+|-] and E, character E alone is invalid.
758+ if (ch == start ) return ; // something valid must be between [+|-] and E, character E alone is invalid.
757759 ch += 1 /*E*/ + (Eneg = ch [1 ]== '-' ) + (ch [1 ]== '+' );
758760 int_fast32_t E = 0 ;
759761 if ((digit = AS_DIGIT (* ch ))< 10 ) {
@@ -769,11 +771,11 @@ static void parse_double_regular_core(const char **pch, double *target)
769771 }
770772 } else {
771773 // Not a single digit after "E"? Invalid number
772- goto fail ;
774+ return ;
773775 }
774776 e += Eneg ? - E : E ;
775777 }
776- if (e < -350 || e > 350 ) goto fail ;
778+ if (e < -350 || e > 350 ) return ;
777779
778780 long double r = (long double )acc ;
779781 if (e < -300 || e > 300 ) {
@@ -792,10 +794,6 @@ static void parse_double_regular_core(const char **pch, double *target)
792794 r = e < 0 ? r /pow10lookup [- e ] : r * pow10lookup [e ];
793795 * target = (double )(neg ? - r : r );
794796 * pch = ch ;
795- return ;
796-
797- fail :
798- * target = NA_FLOAT64 ;
799797}
800798
801799static void parse_double_regular (FieldParseContext * ctx ) {
@@ -903,7 +901,9 @@ static void parse_double_hexadecimal(FieldParseContext *ctx)
903901 uint64_t neg ;
904902 bool Eneg , subnormal = 0 ;
905903 init ();
904+
906905 ch += (neg = (* ch == '-' )) + (* ch == '+' );
906+ * target = NA_FLOAT64 ;
907907
908908 if (ch [0 ]== '0' && (ch [1 ]== 'x' || ch [1 ]== 'X' ) &&
909909 (ch [2 ]== '1' || (subnormal = ch [2 ]== '0' )) && ch [3 ]== '.' ) {
@@ -916,7 +916,7 @@ static void parse_double_hexadecimal(FieldParseContext *ctx)
916916 ch ++ ;
917917 }
918918 size_t ndigits = (uint_fast8_t )(ch - ch0 );
919- if (ndigits > 13 || !(* ch == 'p' || * ch == 'P' )) goto fail ;
919+ if (ndigits > 13 || !(* ch == 'p' || * ch == 'P' )) return ;
920920 acc <<= (13 - ndigits ) * 4 ;
921921 ch += 1 + (Eneg = ch [1 ]== '-' ) + (ch [1 ]== '+' );
922922 uint64_t E = 0 ;
@@ -925,7 +925,7 @@ static void parse_double_hexadecimal(FieldParseContext *ctx)
925925 ch ++ ;
926926 }
927927 E = 1023 + (Eneg ? - E : E ) - subnormal ;
928- if (subnormal ? E : (E < 1 || E > 2046 )) goto fail ;
928+ if (subnormal ? E : (E < 1 || E > 2046 )) return ;
929929
930930 * ((uint64_t * )target ) = (neg << 63 ) | (E << 52 ) | (acc );
931931 * (ctx -> ch ) = ch ;
@@ -942,9 +942,6 @@ static void parse_double_hexadecimal(FieldParseContext *ctx)
942942 * (ctx -> ch ) = ch + 8 ;
943943 return ;
944944 }
945-
946- fail :
947- * target = NA_FLOAT64 ;
948945}
949946
950947/*
@@ -961,28 +958,29 @@ static void parse_iso8601_date_core(const char **pch, int32_t *target)
961958
962959 int32_t year = 0 , month = 0 , day = 0 ;
963960
961+ * target = NA_INT32 ;
962+
964963 str_to_i32_core (& ch , & year , true);
965964
966965 // .Date(.Machine$integer.max*c(-1, 1)):
967966 // -5877641-06-24 -- 5881580-07-11
968967 // rather than fiddle with dates within those terminal years (unlikely
969968 // to be showing up in data sets any time soon), just truncate towards 0
970969 if (year == NA_INT32 || year < -5877640 || year > 5881579 || * ch != '-' )
971- goto fail ;
970+ return ;
972971
973972 // Multiples of 4, excluding 3/4 of centuries
974973 bool isLeapYear = year % 4 == 0 && (year % 100 != 0 || year /100 % 4 == 0 );
975974 ch ++ ;
976975
977976 str_to_i32_core (& ch , & month , true);
978977 if (month == NA_INT32 || month < 1 || month > 12 || * ch != '-' )
979- goto fail ;
978+ return ;
980979 ch ++ ;
981980
982981 str_to_i32_core (& ch , & day , true);
983- if (day == NA_INT32 || day < 1 ||
984- (day > (isLeapYear ? leapYearDays [month - 1 ] : normYearDays [month - 1 ])))
985- goto fail ;
982+ if (day == NA_INT32 || day < 1 || (day > (isLeapYear ? leapYearDays [month - 1 ] : normYearDays [month - 1 ])))
983+ return ;
986984
987985 * target =
988986 (year /400 - 4 )* cumDaysCycleYears [400 ] + // days to beginning of 400-year cycle
@@ -991,10 +989,6 @@ static void parse_iso8601_date_core(const char **pch, int32_t *target)
991989 day - 1 ; // day within month (subtract 1: 1970-01-01 -> 0)
992990
993991 * pch = ch ;
994- return ;
995-
996- fail :
997- * target = NA_INT32 ;
998992}
999993
1000994static void parse_iso8601_date (FieldParseContext * ctx ) {
@@ -1009,27 +1003,33 @@ static void parse_iso8601_timestamp(FieldParseContext *ctx)
10091003 int32_t date , hour = 0 , minute = 0 , tz_hour = 0 , tz_minute = 0 ;
10101004 double second = 0 ;
10111005
1006+ * target = NA_FLOAT64 ;
1007+
10121008 parse_iso8601_date_core (& ch , & date );
10131009 if (date == NA_INT32 )
1014- goto fail ;
1015- if (* ch != ' ' && * ch != 'T' )
1016- goto date_only ;
1017- // allows date-only field in a column with UTC-marked datetimes to be parsed as UTC too; test 2150.13
1010+ return ;
1011+ if (* ch != ' ' && * ch != 'T' ) {
1012+ * target = 86400 * (double )date ;
1013+
1014+ * (ctx -> ch ) = ch ;
1015+ return ;
1016+ }
1017+ // allows date-only field in a column with UTC-marked datetimes to be parsed as UTC too; test 2150.13
10181018 ch ++ ;
10191019
10201020 str_to_i32_core (& ch , & hour , true);
10211021 if (hour == NA_INT32 || hour < 0 || hour > 23 || * ch != ':' )
1022- goto fail ;
1022+ return ;
10231023 ch ++ ;
10241024
10251025 str_to_i32_core (& ch , & minute , true);
10261026 if (minute == NA_INT32 || minute < 0 || minute > 59 || * ch != ':' )
1027- goto fail ;
1027+ return ;
10281028 ch ++ ;
10291029
10301030 parse_double_regular_core (& ch , & second );
10311031 if (second == NA_FLOAT64 || second < 0 || second >= 60 )
1032- goto fail ;
1032+ return ;
10331033
10341034 if (* ch == 'Z' ) {
10351035 ch ++ ; // "Zulu time"=UTC
@@ -1041,41 +1041,35 @@ static void parse_iso8601_timestamp(FieldParseContext *ctx)
10411041 // three recognized formats: [+-]AA:BB, [+-]AABB, and [+-]AA
10421042 str_to_i32_core (& ch , & tz_hour , true);
10431043 if (tz_hour == NA_INT32 )
1044- goto fail ;
1044+ return ;
10451045 if (ch - start == 5 && tz_hour != 0 ) { // +AABB
10461046 if (abs (tz_hour ) > 2400 )
1047- goto fail ;
1047+ return ;
10481048 tz_minute = tz_hour % 100 ;
10491049 tz_hour /= 100 ;
10501050 } else if (ch - start == 3 ) {
10511051 if (abs (tz_hour ) > 24 )
1052- goto fail ;
1052+ return ;
10531053 if (* ch == ':' ) {
10541054 ch ++ ;
10551055 str_to_i32_core (& ch , & tz_minute , true);
10561056 if (tz_minute == NA_INT32 )
1057- goto fail ;
1057+ return ;
10581058 }
10591059 }
10601060 } else {
10611061 if (!args .noTZasUTC )
1062- goto fail ;
1062+ return ;
10631063 // if neither Z nor UTC offset is present, then it's local time and that's not directly supported yet; see news for v1.13.0
10641064 // but user can specify that the unmarked datetimes are UTC by passing tz="UTC"
10651065 // if local time is UTC (env variable TZ is "" or "UTC", not unset) then local time is UTC, and that's caught by fread at R level too
10661066 }
10671067 }
10681068
1069- date_only :
1070-
10711069 // cast upfront needed to prevent silent overflow
10721070 * target = 86400 * (double )date + 3600 * (hour - tz_hour ) + 60 * (minute - tz_minute ) + second ;
10731071
10741072 * (ctx -> ch ) = ch ;
1075- return ;
1076-
1077- fail :
1078- * target = NA_FLOAT64 ;
10791073}
10801074
10811075static void parse_empty (FieldParseContext * ctx )
0 commit comments