GetNextDigit() private method

private GetNextDigit ( ) : bool
return bool
		private static bool ParseFractionExact(ref __DTString str, int maxDigitLen, ref double result)
		{
			if (!str.GetNextDigit())
			{
				str.Index--;
				return false;
			}
			result = (double)str.GetDigit();
			int i;
			for (i = 1; i < maxDigitLen; i++)
			{
				if (!str.GetNextDigit())
				{
					str.Index--;
					break;
				}
				result = result * 10.0 + (double)str.GetDigit();
			}
			result /= Math.Pow(10.0, (double)i);
			return i == maxDigitLen;
		}
示例#2
0
        /*=================================ParseFractionExact==================================
        **Action: Parse the number string in __DTString that are formatted using
        **        the following patterns:
        **        "0", "00", and "000..0"
        **Returns: the fraction value
        **Arguments:    str: a __DTString.  The parsing will start from the
        **              next character after str.Index.
        **Exceptions: FormatException if error in parsing number.
        ==============================================================================*/

        private static bool ParseFractionExact(ref __DTString str, int maxDigitLen,  ref double result) {
            if (!str.GetNextDigit()) {
                str.Index--;
                return false;
            }
            result = str.GetDigit();

            int digitLen = 1;
            for (; digitLen < maxDigitLen; digitLen++) {
                if (!str.GetNextDigit()) {
                    str.Index--;
                    break;
                }
                result = result * 10 + str.GetDigit();
            }

            result = ((double)result / Math.Pow(10, digitLen));
            return (digitLen == maxDigitLen);
        }
		internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result)
		{
			result = 0;
			int index = str.Index;
			int i;
			for (i = 0; i < maxDigitLen; i++)
			{
				if (!str.GetNextDigit())
				{
					str.Index--;
					break;
				}
				result = result * 10 + str.GetDigit();
			}
			if (i < minDigitLen)
			{
				str.Index = index;
				return false;
			}
			return true;
		}
示例#4
0
 private static bool ParseFractionExact(ref __DTString str, int maxDigitLen, ref double result)
 {
     if (!str.GetNextDigit())
     {
         str.Index--;
         return false;
     }
     result = str.GetDigit();
     int num = 1;
     while (num < maxDigitLen)
     {
         if (!str.GetNextDigit())
         {
             str.Index--;
             break;
         }
         result = (result * 10.0) + str.GetDigit();
         num++;
     }
     result = ((double) result) / Math.Pow(10.0, (double) num);
     return (num == maxDigitLen);
 }
示例#5
0
 internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result) {
     Contract.Assert(minDigitLen > 0, "minDigitLen > 0");
     Contract.Assert(maxDigitLen < 9, "maxDigitLen < 9");
     Contract.Assert(minDigitLen <= maxDigitLen, "minDigitLen <= maxDigitLen");
     result = 0;
     int startingIndex = str.Index;
     int tokenLength = 0;
     while (tokenLength < maxDigitLen) {
         if (!str.GetNextDigit()) {
             str.Index--;
             break;
         }
         result = result * 10 + str.GetDigit();
         tokenLength++;
     }
     if (tokenLength < minDigitLen) {
         str.Index = startingIndex;
         return false;
     }
     return true;
 }
示例#6
0
 internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result)
 {
     result = 0;
     int index = str.Index;
     int num2 = 0;
     while (num2 < maxDigitLen)
     {
         if (!str.GetNextDigit())
         {
             str.Index--;
             break;
         }
         result = (result * 10) + str.GetDigit();
         num2++;
     }
     if (num2 < minDigitLen)
     {
         str.Index = index;
         return false;
     }
     return true;
 }
示例#7
0
        //
        // This is the lexer. Check the character at the current index, and put the found token in dtok and
        // some raw date/time information in raw.
        //
        private static void Lex(
            int dps, __DTString str, DateTimeToken dtok, DateTimeRawInfo raw, DateTimeResult result, ref DateTimeFormatInfo dtfi) {
            
            int sep;
            dtok.dtt = DTT_Unk;     // Assume the token is unkown.

            //
            // Skip any white spaces.
            //
            if (!str.SkipWhiteSpaceComma()) {
                //
                // SkipWhiteSpaceComma() will return true when end of string is reached.
                //
                dtok.dtt = DTT_End;
                return;
            }

            char ch = str.GetChar();
            if (Char.IsLetter(ch))
            {
                //
                // This is a letter.
                //

                int month, dayOfWeek, era, timeMark;

                //
                // Check if this is a beginning of a month name.
                // And check if this is a day of week name.
                //
                if (raw.month == -1 && (month = GetMonthNumber(str, dtfi)) >= 1)
                {
                    //
                    // This is a month name
                    //
                    switch(sep=GetSeparator(str, raw, dtfi))
                    {
                        case SEP_End:
                            dtok.dtt = DTT_MonthEnd;
                            break;
                        case SEP_Space:
                            dtok.dtt = DTT_MonthSpace;
                            break;
                        case SEP_Date:
                            dtok.dtt = DTT_MonthDatesep;
                            break;
                        default:
                            //Invalid separator after month name
                            throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                    }
                    raw.month = month;
                }
                else if (raw.dayOfWeek == -1 && (dayOfWeek = GetDayOfWeekNumber(str, dtfi)) >= 0)
                {
                    //
                    // This is a day of week name.
                    //
                    raw.dayOfWeek = dayOfWeek;
                    dtok.dtt = DTT_DayOfWeek;
                    //
                    // Discard the separator.
                    //
                    GetSeparator(str, raw, dtfi);
                }
                else if (GetTimeZoneName(str))
                {
                    //
                    // This is a timezone designator
                    //
                    // NOTENOTE                     : for now, we only support "GMT" and "Z" (for Zulu time).
                    //
                    dtok.dtt = DTT_TimeZone;
                    result.timeZoneUsed = true;
                    result.timeZoneOffset = new TimeSpan(0);
                } else if ((raw.era == -1) && ((era = GetEra(str, result, ref dtfi)) != -1)) {
                    raw.era = era;
                    dtok.dtt = DTT_Era;
                } else if (raw.timeMark == -1 && (timeMark = GetTimeMark(str, dtfi)) != -1) {
                    raw.timeMark = timeMark;
                    GetSeparator(str, raw, dtfi);
                } else {
                    //
                    // Not a month name, not a day of week name. Check if this is one of the
                    // known date words. This is used to deal case like Spanish cultures, which
                    // uses 'de' in their Date string.
                    // 
                    //                    
                    if (!str.MatchWords(dtfi.DateWords)) {
                        throw new FormatException(
                            String.Format(Environment.GetResourceString("Format_UnknowDateTimeWord"), str.Index));
                    }                    
                    GetSeparator(str, raw, dtfi);                    
                }
            } else if (Char.IsDigit(ch)) {
                if (raw.numCount == 3) {
                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                }
                //
                // This is a digit.
                //
                int number = ch - '0';

                int digitCount = 1;

                //
                // Collect other digits.
                //
                while (str.GetNextDigit())
                {
                    number = number * 10 + str.GetDigit();
                    digitCount++;
                }

                // If the previous parsing state is DS_T_NNt (like 12:01), and we got another number,
                // so we will have a terminal state DS_TX_NNN (like 12:01:02).
                // If the previous parsing state is DS_T_Nt (like 12:), and we got another number,
                // so we will have a terminal state DS_TX_NN (like 12:01:02).
                //
                // Look ahead to see if the following character is a decimal point or timezone offset.
                // This enables us to parse time in the forms of:
                //  "11:22:33.1234" or "11:22:33-08".
                if (dps == DS_T_NNt || dps == DS_T_Nt) {
                    char nextCh;
                    if ((str.Index < str.len - 1)) {
                        nextCh = str.Value[str.Index];
                        switch (nextCh) {                        
                            case '.':
                                if (dps == DS_T_NNt) {
                                    // Yes, advance to the next character.
                                    str.Index++;
                                    // Collect the second fraction.
                                    raw.fraction = ParseFraction(str);
                                }
                                break;
                            case '+':
                            case '-':
                                if (result.timeZoneUsed) {
                                    // Should not have two timezone offsets.
                                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                                }
                                result.timeZoneUsed = true;
                                result.timeZoneOffset = ParseTimeZone(str, nextCh);
                                break;
                        }
                    }
                }
                
                if (number >= 0)
                {
                    dtok.num = number;
                    if (digitCount >= 3)
                    {
                        if (raw.year == -1)
                        {
                            raw.year = number;
                            //
                            // If we have number which has 3 or more digits (like "001" or "0001"),
                            // we assume this number is a year. Save the currnet raw.numCount in
                            // raw.year.
                            //
                            switch (sep = GetSeparator(str, raw, dtfi))
                            {
                                case SEP_End:
                                    dtok.dtt     = DTT_YearEnd;
                                    break;
                                case SEP_Am:
                                case SEP_Pm:
                                case SEP_Space:
                                    dtok.dtt    = DTT_YearSpace;
                                    break;
                                case SEP_Date:
                                    dtok.dtt     = DTT_YearDateSep;
                                    break;
                                case SEP_YearSuff:
                                case SEP_MonthSuff:
                                case SEP_DaySuff:
                                    dtok.dtt    = DTT_NumDatesuff;
                                    dtok.suffix = sep;
                                    break;
                                case SEP_HourSuff:
                                case SEP_MinuteSuff:
                                case SEP_SecondSuff:
                                    dtok.dtt    = DTT_NumTimesuff;
                                    dtok.suffix = sep;
                                    break;
                                default:
                                    // Invalid separator after number number.
                                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                            }
                            //
                            // Found the token already. Let's bail.
                            //
                            return;
                        }
                        throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                    }
                } else
                {
                    //
                    // number is overflowed.
                    //
                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                }

                switch (sep = GetSeparator(str, raw, dtfi))
                {
                    //
                    // Note here we check if the numCount is less than three.
                    // When we have more than three numbers, it will be caught as error in the state machine.
                    //
                    case SEP_End:
                        dtok.dtt = DTT_NumEnd;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Am:
                    case SEP_Pm:
                        dtok.dtt = DTT_NumAmpm;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Space:
                        dtok.dtt = DTT_NumSpace;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Date:
                        dtok.dtt = DTT_NumDatesep;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Time:
                        if (!result.timeZoneUsed) {
                            dtok.dtt = DTT_NumTimesep;
                            raw.num[raw.numCount++] = dtok.num;
                        } else {
                            // If we already got timezone, there should be no
                            // time separator again.
                            throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                        }
                        break;
                    case SEP_YearSuff:
                        dtok.num = dtfi.Calendar.ToFourDigitYear(number);
                        dtok.dtt    = DTT_NumDatesuff;
                        dtok.suffix = sep;
                        break;
                    case SEP_MonthSuff:
                    case SEP_DaySuff:
                        dtok.dtt    = DTT_NumDatesuff;
                        dtok.suffix = sep;
                        break;
                    case SEP_HourSuff:
                    case SEP_MinuteSuff:
                    case SEP_SecondSuff:
                        dtok.dtt    = DTT_NumTimesuff;
                        dtok.suffix = sep;
                        break;
                    case SEP_LocalTimeMark:
                        dtok.dtt = DTT_NumLocalTimeMark;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    default:
                        // Invalid separator after number number.
                        throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                }
            }
            else
            {
                //
                // Not a letter, not a digit. Just ignore it.
                //
                str.Index++;
            }
            return;
        }
示例#8
0
        /*=================================ParseTimeZone==========================
        **Action: Parse the timezone offset in the following format:
        **          "+8", "+08", "+0800", "+0800"
        **        This method is used by DateTime.Parse().
        **Returns:      The TimeZone offset.
        **Arguments:
        **      str the parsing string
        **Exceptions:
        **      FormatException if invalid timezone format is found.
        ============================================================================*/

        private static TimeSpan ParseTimeZone(__DTString str, char offsetChar) {
            // The hour/minute offset for timezone.
            int hourOffset = 0;
            int minuteOffset = 0;
            
            if (str.GetNextDigit()) {
                // Get the first digit, Try if we can parse timezone in the form of "+8".
                hourOffset = str.GetDigit();
                if (str.GetNextDigit()) {
                    // Parsing "+18"
                    hourOffset *= 10;
                    hourOffset += str.GetDigit();
                    if (str.GetNext()) {
                        char ch;
                        if (Char.IsDigit(ch = str.GetChar())) {
                            // Parsing "+1800"

                            // Put the char back, since we already get the char in the previous GetNext() call.
                            str.Index--;
                            if (ParseDigits(str, 2, true, out minuteOffset)) {
                                // ParseDigits() does not advance the char for us, so do it here.
                                str.Index++;
                            } else {
                                throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                            }
                        } else if (ch == ':') {   
                            // Parsing "+18:00"
                            if (ParseDigits(str, 2, true, out minuteOffset)) {
                                str.Index++;
                            } else {
                                throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                            }
                        } else {
                            // Not a digit, not a colon, put this char back.
                            str.Index--;
                        }
                    }
                }
                // The next char is not a digit, so we get the timezone in the form of "+8".
            } else {
                // Invalid timezone: No numbers after +/-.
                throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
            }
            TimeSpan timezoneOffset = new TimeSpan(hourOffset, minuteOffset, 0);
            if (offsetChar == '-') {
                timezoneOffset = timezoneOffset.Negate();
            }
            return (timezoneOffset);
        }
示例#9
0
        /*=================================ParseFractionExact==================================
        **Action: Parse the number string in __DTString that are formatted using
        **        the following patterns:
        **        "0", "00", and "000..0"
        **Returns: the fraction value
        **Arguments:    str: a __DTString.  The parsing will start from the
        **              next character after str.Index.
        **Exceptions: FormatException if error in parsing number.
        ==============================================================================*/
        
        private static bool ParseFractionExact(__DTString str, int digitLen, bool isThrowExp, ref double result) {
            if (!str.GetNextDigit()) {
                return (ParseFormatError(isThrowExp, "Format_BadDateTime"));
            }
            result = str.GetDigit();

            for (int i = 1; i < digitLen; i++) {
                if (!str.GetNextDigit()) {
                    return (ParseFormatError(isThrowExp, "Format_BadDateTime"));
                }
                result = result * 10 + str.GetDigit();
            }

            result = ((double)result / Math.Pow(10, digitLen));
            return (true);
        }
示例#10
0
        /*=================================ParseDigits==================================
        **Action: Parse the number string in __DTString that are formatted using
        **        the following patterns:
        **        "0", "00", and "000..0"
        **Returns: the integer value
        **Arguments:    str: a __DTString.  The parsing will start from the
        **              next character after str.Index.
        **Exceptions: FormatException if error in parsing number.
        ==============================================================================*/
        
        private static bool ParseDigits(__DTString str, int digitLen, bool isThrowExp, out int result) {
            result = 0;
            if (!str.GetNextDigit()) {
                return (ParseFormatError(isThrowExp, "Format_BadDateTime"));
            }
            result = str.GetDigit();

            if (digitLen == 1) {
                // When digitLen == 1, we should able to parse number like "9" and "19".  However,
                // we won't go beyond two digits.
                //
                // So let's look ahead one character to see if it is a digit.  If yes, add it to result.
                if (str.GetNextDigit()) {
                    result = result * 10 + str.GetDigit();
                } else {
                    // Not a digit, let's roll back the Index.
                    str.Index--;
                }
            } else if (digitLen == 2) {
                if (!str.GetNextDigit()) {
                    return (ParseFormatError(isThrowExp, "Format_BadDateTime"));    
                }
                result = result * 10 + str.GetDigit();
            } else {
                for (int i = 1; i < digitLen; i++) {
                    if (!str.GetNextDigit()) {
                        return (ParseFormatError(isThrowExp, "Format_BadDateTime"));
                    }
                    result = result * 10 + str.GetDigit();
                }
            }

            return (true);
        }