internal static int InferSimpleType(string s, ref bool bNeedsRangeCheck)
{
bool bNegative = false;
bool bPositive = false;
bool bDate = false;
bool bTime = false;
bool bMissingDay = false;
if (s.Length==0) return TF_string;
int i = 0;
switch (s[i])
{
case 't':
case 'f':
if (s == "true")
return TF_boolean | TF_string;
else if (s == "false")
return TF_boolean | TF_string;
else
return TF_string;
case 'N': //try to match "NaN"
if (s == "NaN")
return TF_float | TF_double | TF_string;
else
return TF_string;
//else
case 'I': //try to match "INF"
INF:
if (s.Substring(i) == "INF")
return TF_float | TF_double | TF_string;
else return TF_string;
case '.': //try to match ".9999" decimal/float/double
FRACTION:
bNeedsRangeCheck = true;
i++;
if (i==s.Length)
{
if ((i==1) || (i==2 && (bPositive || bNegative))) //"." "-." "+."
return TF_string;
else
return TF_decimal | TF_float | TF_double | TF_string;
}
switch (s[i])
{
case 'e':
case 'E':
goto EXPONENT;
default:
if (s[i]>='0' && s[i]<='9')
goto DEC_PART;
else
return TF_string;
}
DEC_PART:
i++; if (i==s.Length) return TF_decimal | TF_float | TF_double | TF_string; //"9999.9" was matched
switch (s[i])
{
case 'e':
case 'E':
goto EXPONENT;
default:
if (s[i]>='0' && s[i]<='9')
goto DEC_PART;
else
return TF_string;
}
EXPONENT:
i++; if (i==s.Length) return TF_string;
switch (s[i])
{
case '+':
case '-':
goto E1;
default:
if (s[i]>='0' && s[i]<='9')
goto EXP_PART;
else
return TF_string;
}
E1:
i++; if (i==s.Length) return TF_string; //".9999e+" was matched
if (s[i]>='0' && s[i]<='9')
goto EXP_PART;
else
return TF_string; //".999e+X was matched
EXP_PART:
i++; if (i==s.Length) return TF_float | TF_double | TF_string; //".9999e+99" was matched
if (s[i]>='0' && s[i]<='9') //".9999e+9
goto EXP_PART;
else
return TF_string; //".9999e+999X" was matched
case '-':
bNegative = true;
i++; if (i==s.Length) return TF_string;
switch (s[i])
{
case 'I': //try to match "-INF"
goto INF;
case '.': //try to match "-.9999"
goto FRACTION;
case 'P':
goto DURATION;
default:
if (s[i]>='0' && s[i]<='9') //-9
goto NUMBER;
else return TF_string;
}
case '+':
bPositive = true;
i++; if (i==s.Length) return TF_string;
switch (s[i])
{
case '.': //try to match "+.9999"
goto FRACTION;
case 'P':
goto DURATION;
default:
if (s[i]>='0' && s[i]<='9') //"+9
goto NUMBER;
else return TF_string;
}
case 'P': //try to match duration
DURATION:
i++; if (i==s.Length) return TF_string;
switch (s[i])
{
case 'T':
goto D7;
default:
if (s[i]>='0' && s[i]<='9') //"P9"
goto D1;
else return TF_string;
}
D1:
i++; if (i==s.Length) return TF_string; //"P999" was matched
switch (s[i])
{
case 'Y':
goto D2;
case 'M':
goto D4;
case 'D':
goto D6;
default:
if (s[i]>='0' && s[i]<='9')
goto D1;
else
return TF_string;
}
D2:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"P999Y" was matched
}
switch (s[i])
{
case 'T':
goto D7;
default:
if (s[i]>='0' && s[i]<='9')
goto D3;
else
return TF_string;
}
D3:
i++; if (i==s.Length) return TF_string; //"P999Y9" was matched
switch (s[i])
{
case 'M':
goto D4;
case 'D':
goto D6;
default:
if (s[i]>='0' && s[i]<='9')
goto D3;
else
return TF_string;
}
D4:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"P999Y999M" was matched
}
switch (s[i])
{
case 'T':
goto D7;
default:
if (s[i]>='0' && s[i]<='9')
goto D5;
else
return TF_string;
}
D5:
i++; if (i==s.Length) return TF_string; //"P999Y999M9" was matched
switch (s[i])
{
case 'D':
goto D6;
default:
if (s[i]>='0' && s[i]<='9')
goto D5;
else
return TF_string;
}
D6:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"P999Y999M999D" was matched
}
switch (s[i])
{
case 'T':
goto D7;
default:
return TF_string;
}
D7:
i++; if (i==s.Length) return TF_string; //"P999Y999M9999DT" was matched
if (s[i]>='0' && s[i]<='9')
goto D8;
else
return TF_string;
D8:
i++; if (i==s.Length) return TF_string; //"___T9" was matched
switch (s[i])
{
case 'H':
goto D9;
case 'M':
goto D11;
case '.':
goto D13;
case 'S':
goto D15;
default:
if (s[i]>='0' && s[i]<='9')
goto D8;
else
return TF_string;
}
D9:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"___T999H" was matched
}
if (s[i]>='0' && s[i]<='9')
goto D10;
else
return TF_string;
D10:
i++; if (i==s.Length) return TF_string; //"___T999H9" was matched
switch (s[i])
{
case 'M':
goto D11;
case '.':
goto D13;
case 'S':
goto D15;
default:
if (s[i]>='0' && s[i]<='9')
goto D10;
else
return TF_string;
}
D11:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"___T999H999M" was matched
}
if (s[i]>='0' && s[i]<='9')
goto D12;
else
return TF_string;
D12:
i++; if (i==s.Length) return TF_string; //"___T999H999M9" was matched
switch (s[i])
{
case '.':
goto D13;
case 'S':
goto D15;
default:
if (s[i]>='0' && s[i]<='9')
goto D12;
else
return TF_string;
}
D13:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"___T999H999M999." was matched
}
if (s[i]>='0' && s[i]<='9')
goto D14;
else
return TF_string;
D14:
i++; if (i==s.Length) return TF_string; //"___T999H999M999.9" was matched
switch (s[i])
{
case 'S':
goto D15;
default:
if (s[i]>='0' && s[i]<='9')
goto D14;
else
return TF_string;
}
D15:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_duration | TF_string; //"___T999H999M999.999S" was matched
}
else return TF_string;
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
NUMBER:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
if (bNegative || bPositive)
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
else
{
if (s=="0" || s=="1")
return TF_boolean | TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
else
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
}
}
switch (s[i])
{
case '.':
goto FRACTION;
case 'e':
case 'E':
bNeedsRangeCheck = true;
return TF_float | TF_double | TF_string;
default:
if (s[i]>='0' && s[i]<='9')
goto N2;
else
return TF_string;
}
N2:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
if (bNegative || bPositive)
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
else
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
}
switch (s[i])
{
case '.':
goto FRACTION;
case ':':
bTime = true;
goto MINUTE;
case 'e':
case 'E':
bNeedsRangeCheck = true;
return TF_float | TF_double | TF_string;
default:
if (s[i]>='0' && s[i]<='9')
goto N3;
else
return TF_string;
}
N3:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true; //three digits may not fit byte and unsignedByte
if (bNegative || bPositive)
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
else
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
}
switch (s[i])
{
case '.':
goto FRACTION;
case 'e':
case 'E':
bNeedsRangeCheck = true;
return TF_float | TF_double | TF_string;
default:
if (s[i]>='0' && s[i]<='9')
goto N4;
else
return TF_string;
}
N4:
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
if (bNegative || bPositive)
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
else
return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
}
switch (s[i])
{
case '-':
bDate = true;
goto DATE;
case '.':
goto FRACTION;
case 'e':
case 'E':
bNeedsRangeCheck = true;
return TF_float | TF_double | TF_string;
default:
if (s[i]>='0' && s[i]<='9')
goto N4;
else
return TF_string;
}
DATE:
i++; if (i==s.Length) return TF_string; //"9999-"
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string; //"9999-9"
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++;
if (i==s.Length)
{
bNeedsRangeCheck = true;
return TF_gYearMonth | TF_string; //"9999-99"
}
switch (s[i])
{
case '-':
goto DAY;
case 'Z':
case 'z':
bMissingDay = true;
goto ZULU;
case '+':
bMissingDay = true;
goto ZONE_SHIFT;
default:
return TF_string;
}
DAY:
i++; if (i==s.Length) return TF_string; //"9999-99-"
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string; //"9999-99-9"
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return DateTime(s, bDate, bTime); //"9999-99-99"
switch (s[i])
{
case 'Z':
case 'z':
goto ZULU;
case '+':
case '-':
goto ZONE_SHIFT;
case 'T':
bTime=true;
goto TIME;
case ':':
bMissingDay = true;
goto ZONE_SHIFT_MINUTE;
default:
return TF_string;
}
ZULU:
i++;
if (i==s.Length)
{
if (bMissingDay)
{
bNeedsRangeCheck=true;
return TF_gYearMonth | TF_string;
}
else
{
return DateTime(s, bDate, bTime);
}
}
else
return TF_string;
ZONE_SHIFT:
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i] != ':')
return TF_string;
ZONE_SHIFT_MINUTE:
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++;
if (i==s.Length)
{
if (bMissingDay)
{
bNeedsRangeCheck=true;
return TF_gYearMonth | TF_string;
}
else
{
return DateTime(s, bDate, bTime);
}
}
else return TF_string;
TIME:
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i] != ':')
return TF_string;
MINUTE:
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i] != ':')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
i++; if (i==s.Length) return DateTime(s, bDate, bTime);
switch (s[i])
{
case 'Z':
case 'z':
goto ZULU;
case '+':
case '-':
goto ZONE_SHIFT;
case '.':
goto SECOND_FRACTION;
default:
return TF_string;
}
SECOND_FRACTION:
i++; if (i==s.Length) return TF_string;
if (s[i]<'0' || s[i]>'9')
return TF_string;
FRACT_DIGITS:
i++; if (i==s.Length) return DateTime(s, bDate, bTime);
switch (s[i])
{
case 'Z':
case 'z':
goto ZULU;
case '+':
case '-':
goto ZONE_SHIFT;
default:
if (s[i]>='0' && s[i]<='9')
goto FRACT_DIGITS;
else
return TF_string;
}
default:
return TF_string;
}
}