@@ -49,6 +49,8 @@ extern const char EndOfUDF[] = "EndOf";
49
49
extern const char ShiftYearsUDF[] = " ShiftYears" ;
50
50
extern const char ShiftQuartersUDF[] = " ShiftQuarters" ;
51
51
extern const char ShiftMonthsUDF[] = " ShiftMonths" ;
52
+ extern const char ParseUDF[] = " Parse" ;
53
+ extern const char Parse64UDF[] = " Parse64" ;
52
54
53
55
extern const char TMResourceName[] = " DateTime2.TM" ;
54
56
extern const char TM64ResourceName[] = " DateTime2.TM64" ;
@@ -2942,33 +2944,42 @@ class TShift : public TBoxedValue {
2942
2944
const TSourcePosition Pos_;
2943
2945
};
2944
2946
2945
- template <size_t Digits>
2946
- struct ParseExaclyNDigits ;
2947
+ template <size_t Digits, bool Variable = false >
2948
+ struct ParseNDigits ;
2947
2949
2948
- template <>
2949
- struct ParseExaclyNDigits <0U > {
2950
+ template <bool Variable >
2951
+ struct ParseNDigits <0U , Variable > {
2950
2952
template <typename T>
2951
2953
static constexpr bool Do (std::string_view::const_iterator&, T&) {
2952
2954
return true ;
2953
2955
}
2954
2956
};
2955
2957
2956
- template <size_t Digits>
2957
- struct ParseExaclyNDigits {
2958
+ template <size_t Digits, bool Variable >
2959
+ struct ParseNDigits {
2958
2960
template <typename T>
2959
2961
static constexpr bool Do (std::string_view::const_iterator& it, T& out) {
2960
2962
const auto d = *it;
2961
2963
if (!std::isdigit (d)) {
2964
+ // XXX: If the current char is not a digit, the
2965
+ // parsing succeeds iff there are no more digits
2966
+ // to be parsed (see the class specialization
2967
+ // above) or there are given less than N digits
2968
+ // to be parsed.
2969
+ if constexpr (Variable) {
2970
+ return true ;
2971
+ }
2962
2972
return false ;
2963
2973
}
2964
2974
out *= 10U ;
2965
2975
out += d - ' 0' ;
2966
- return ParseExaclyNDigits <Digits - 1U >::Do (++it, out);
2976
+ return ParseNDigits <Digits - 1U , Variable >::Do (++it, out);
2967
2977
}
2968
2978
};
2969
2979
2970
2980
// Parse
2971
2981
2982
+ template <const char * TUdfName, const char * TResourceName>
2972
2983
class TParse : public TBoxedValue {
2973
2984
public:
2974
2985
class TFactory : public TBoxedValue {
@@ -2988,7 +2999,7 @@ class TShift : public TBoxedValue {
2988
2999
};
2989
3000
2990
3001
static const TStringRef& Name () {
2991
- static auto name = TStringRef::Of ( " Parse " );
3002
+ static auto name = TStringRef (TUdfName, std::strlen (TUdfName) );
2992
3003
return name;
2993
3004
}
2994
3005
@@ -3002,15 +3013,10 @@ class TShift : public TBoxedValue {
3002
3013
return false ;
3003
3014
}
3004
3015
3005
- auto resourceType = builder.Resource (TMResourceName);
3006
- auto optionalResourceType = builder.Optional ()->Item (resourceType).Build ();
3007
-
3008
- builder.Args ()->Add <char *>().Flags (ICallablePayload::TArgumentFlags::AutoMap)
3009
- .Add (builder.Optional ()->Item <ui16>())
3010
- .Done ()
3011
- .OptionalArgs (1 );
3012
- builder.RunConfig <char *>().Returns (optionalResourceType);
3013
-
3016
+ builder.OptionalArgs (1 ).Args ()->Add <char *>()
3017
+ .template Add <TOptional<ui16>>();
3018
+ builder.Returns (
3019
+ builder.SimpleSignatureType <TOptional<TResource<TResourceName>>(TAutoMap<char *>)>());
3014
3020
if (!typesOnly) {
3015
3021
builder.Implementation (new TParse::TFactory (builder.GetSourcePosition ()));
3016
3022
}
@@ -3046,7 +3052,7 @@ class TShift : public TBoxedValue {
3046
3052
const std::string_view buffer = args[0 ].AsStringRef ();
3047
3053
3048
3054
TUnboxedValuePod result (0 );
3049
- auto & storage = Reference (result);
3055
+ auto & storage = Reference<TResourceName> (result);
3050
3056
storage.MakeDefault ();
3051
3057
3052
3058
auto & builder = valueBuilder->GetDateBuilder ();
@@ -3098,13 +3104,27 @@ class TShift : public TBoxedValue {
3098
3104
break ;
3099
3105
3100
3106
case ' Y' : {
3101
- static constexpr size_t size = 4 ;
3102
3107
Scanners_.emplace_back ([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
3103
- ui32 year = 0U ;
3104
- if (limit < size || !ParseExaclyNDigits<size>::Do (it, year) || !ValidateYear (year)) {
3105
- return false ;
3108
+ if constexpr (TResourceName == TMResourceName) {
3109
+ static constexpr size_t size = 4 ;
3110
+ ui32 year = 0U ;
3111
+ if (limit < size || !ParseNDigits<size>::Do (it, year) || !ValidateYear (year)) {
3112
+ return false ;
3113
+ }
3114
+ SetYear<TMResourceName>(result, year);
3115
+ } else {
3116
+ static constexpr size_t size = 6 ;
3117
+ i64 year = 0LL ;
3118
+ i64 negative = 1LL ;
3119
+ if (*it == ' -' ) {
3120
+ negative = -1LL ;
3121
+ it++;
3122
+ }
3123
+ if (!ParseNDigits<size, true >::Do (it, year) || !ValidateYear (negative * year)) {
3124
+ return false ;
3125
+ }
3126
+ SetYear<TM64ResourceName>(result, negative * year);
3106
3127
}
3107
- SetYear (result, year);
3108
3128
return true ;
3109
3129
});
3110
3130
break ;
@@ -3113,10 +3133,10 @@ class TShift : public TBoxedValue {
3113
3133
static constexpr size_t size = 2 ;
3114
3134
Scanners_.emplace_back ([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
3115
3135
ui32 month = 0U ;
3116
- if (limit < size || !ParseExaclyNDigits <size>::Do (it, month) || !ValidateMonth (month)) {
3136
+ if (limit < size || !ParseNDigits <size>::Do (it, month) || !ValidateMonth (month)) {
3117
3137
return false ;
3118
3138
}
3119
- SetMonth (result, month);
3139
+ SetMonth<TResourceName> (result, month);
3120
3140
return true ;
3121
3141
});
3122
3142
break ;
@@ -3125,10 +3145,10 @@ class TShift : public TBoxedValue {
3125
3145
static constexpr size_t size = 2 ;
3126
3146
Scanners_.emplace_back ([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
3127
3147
ui32 day = 0U ;
3128
- if (limit < size || !ParseExaclyNDigits <size>::Do (it, day) || !ValidateDay (day)) {
3148
+ if (limit < size || !ParseNDigits <size>::Do (it, day) || !ValidateDay (day)) {
3129
3149
return false ;
3130
3150
}
3131
- SetDay (result, day);
3151
+ SetDay<TResourceName> (result, day);
3132
3152
return true ;
3133
3153
});
3134
3154
break ;
@@ -3137,10 +3157,10 @@ class TShift : public TBoxedValue {
3137
3157
static constexpr size_t size = 2 ;
3138
3158
Scanners_.emplace_back ([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
3139
3159
ui32 hour = 0U ;
3140
- if (limit < size || !ParseExaclyNDigits <size>::Do (it, hour) || !ValidateHour (hour)) {
3160
+ if (limit < size || !ParseNDigits <size>::Do (it, hour) || !ValidateHour (hour)) {
3141
3161
return false ;
3142
3162
}
3143
- SetHour (result, hour);
3163
+ SetHour<TResourceName> (result, hour);
3144
3164
return true ;
3145
3165
});
3146
3166
break ;
@@ -3149,10 +3169,10 @@ class TShift : public TBoxedValue {
3149
3169
static constexpr size_t size = 2 ;
3150
3170
Scanners_.emplace_back ([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
3151
3171
ui32 minute = 0U ;
3152
- if (limit < size || !ParseExaclyNDigits <size>::Do (it, minute) || !ValidateMinute (minute)) {
3172
+ if (limit < size || !ParseNDigits <size>::Do (it, minute) || !ValidateMinute (minute)) {
3153
3173
return false ;
3154
3174
}
3155
- SetMinute (result, minute);
3175
+ SetMinute<TResourceName> (result, minute);
3156
3176
return true ;
3157
3177
});
3158
3178
break ;
@@ -3161,10 +3181,10 @@ class TShift : public TBoxedValue {
3161
3181
static constexpr size_t size = 2 ;
3162
3182
Scanners_.emplace_back ([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
3163
3183
ui32 second = 0U ;
3164
- if (limit < size || !ParseExaclyNDigits <size>::Do (it, second) || !ValidateSecond (second)) {
3184
+ if (limit < size || !ParseNDigits <size>::Do (it, second) || !ValidateSecond (second)) {
3165
3185
return false ;
3166
3186
}
3167
- SetSecond (result, second);
3187
+ SetSecond<TResourceName> (result, second);
3168
3188
limit -= size;
3169
3189
3170
3190
if (!limit || *it != ' .' ) {
@@ -3190,7 +3210,7 @@ class TShift : public TBoxedValue {
3190
3210
while (digits--) {
3191
3211
usec *= 10U ;
3192
3212
}
3193
- SetMicrosecond (result, usec);
3213
+ SetMicrosecond<TResourceName> (result, usec);
3194
3214
return true ;
3195
3215
});
3196
3216
break ;
@@ -3208,7 +3228,7 @@ class TShift : public TBoxedValue {
3208
3228
if (!builder.FindTimezoneId (TStringRef (&*start, size), timezoneId)) {
3209
3229
return false ;
3210
3230
}
3211
- SetTimezoneId (result, timezoneId);
3231
+ SetTimezoneId<TResourceName> (result, timezoneId);
3212
3232
return true ;
3213
3233
});
3214
3234
break ;
@@ -3227,7 +3247,7 @@ class TShift : public TBoxedValue {
3227
3247
if (cnt < size || !ValidateMonthShortName (monthName, month)) {
3228
3248
return false ;
3229
3249
}
3230
- SetMonth (result, month);
3250
+ SetMonth<TResourceName> (result, month);
3231
3251
return true ;
3232
3252
});
3233
3253
break ;
@@ -3247,7 +3267,7 @@ class TShift : public TBoxedValue {
3247
3267
if (!ValidateMonthFullName (monthName, month)) {
3248
3268
return false ;
3249
3269
}
3250
- SetMonth (result, month);
3270
+ SetMonth<TResourceName> (result, month);
3251
3271
return true ;
3252
3272
});
3253
3273
break ;
@@ -3390,7 +3410,8 @@ class TShift : public TBoxedValue {
3390
3410
TToUnits<ToMicrosecondsUDF, ui64, 1000000 >,
3391
3411
3392
3412
TFormat,
3393
- TParse,
3413
+ TParse<ParseUDF, TMResourceName>,
3414
+ TParse<Parse64UDF, TM64ResourceName>,
3394
3415
3395
3416
TParseRfc822,
3396
3417
TParseIso8601,
0 commit comments