internal static Exception TryParse()

in src/dotnet-svcutil/lib/src/FrameworkFork/Microsoft.Xml/Xml/schema/XsdDuration.cs [499:680]


        internal static Exception TryParse(string s, DurationType durationType, out XsdDuration result)
        {
            string errorCode;
            int length;
            int value, pos, numDigits;
            Parts parts = Parts.HasNone;

            result = new XsdDuration();

            s = s.Trim();
            length = s.Length;

            pos = 0;
            numDigits = 0;

            if (pos >= length) goto InvalidFormat;

            if (s[pos] == '-')
            {
                pos++;
                result._nanoseconds = NegativeBit;
            }
            else
            {
                result._nanoseconds = 0;
            }

            if (pos >= length) goto InvalidFormat;

            if (s[pos++] != 'P') goto InvalidFormat;

            errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
            if (errorCode != null) goto Error;

            if (pos >= length) goto InvalidFormat;

            if (s[pos] == 'Y')
            {
                if (numDigits == 0) goto InvalidFormat;

                parts |= Parts.HasYears;
                result._years = value;
                if (++pos == length) goto Done;

                errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
                if (errorCode != null) goto Error;

                if (pos >= length) goto InvalidFormat;
            }

            if (s[pos] == 'M')
            {
                if (numDigits == 0) goto InvalidFormat;

                parts |= Parts.HasMonths;
                result._months = value;
                if (++pos == length) goto Done;

                errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
                if (errorCode != null) goto Error;

                if (pos >= length) goto InvalidFormat;
            }

            if (s[pos] == 'D')
            {
                if (numDigits == 0) goto InvalidFormat;

                parts |= Parts.HasDays;
                result._days = value;
                if (++pos == length) goto Done;

                errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
                if (errorCode != null) goto Error;

                if (pos >= length) goto InvalidFormat;
            }

            if (s[pos] == 'T')
            {
                if (numDigits != 0) goto InvalidFormat;

                pos++;
                errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
                if (errorCode != null) goto Error;

                if (pos >= length) goto InvalidFormat;

                if (s[pos] == 'H')
                {
                    if (numDigits == 0) goto InvalidFormat;

                    parts |= Parts.HasHours;
                    result._hours = value;
                    if (++pos == length) goto Done;

                    errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
                    if (errorCode != null) goto Error;

                    if (pos >= length) goto InvalidFormat;
                }

                if (s[pos] == 'M')
                {
                    if (numDigits == 0) goto InvalidFormat;

                    parts |= Parts.HasMinutes;
                    result._minutes = value;
                    if (++pos == length) goto Done;

                    errorCode = TryParseDigits(s, ref pos, false, out value, out numDigits);
                    if (errorCode != null) goto Error;

                    if (pos >= length) goto InvalidFormat;
                }

                if (s[pos] == '.')
                {
                    pos++;

                    parts |= Parts.HasSeconds;
                    result._seconds = value;

                    errorCode = TryParseDigits(s, ref pos, true, out value, out numDigits);
                    if (errorCode != null) goto Error;

                    if (numDigits == 0)
                    { //If there are no digits after the decimal point, assume 0
                        value = 0;
                    }
                    // Normalize to nanosecond intervals
                    for (; numDigits > 9; numDigits--)
                        value /= 10;

                    for (; numDigits < 9; numDigits++)
                        value *= 10;

                    result._nanoseconds |= (uint)value;

                    if (pos >= length) goto InvalidFormat;

                    if (s[pos] != 'S') goto InvalidFormat;
                    if (++pos == length) goto Done;
                }
                else if (s[pos] == 'S')
                {
                    if (numDigits == 0) goto InvalidFormat;

                    parts |= Parts.HasSeconds;
                    result._seconds = value;
                    if (++pos == length) goto Done;
                }
            }

            // Duration cannot end with digits
            if (numDigits != 0) goto InvalidFormat;

            // No further characters are allowed
            if (pos != length) goto InvalidFormat;

            Done:
            // At least one part must be defined
            if (parts == Parts.HasNone) goto InvalidFormat;

            if (durationType == DurationType.DayTimeDuration)
            {
                if ((parts & (Parts.HasYears | Parts.HasMonths)) != 0)
                    goto InvalidFormat;
            }
            else if (durationType == DurationType.YearMonthDuration)
            {
                if ((parts & ~(XsdDuration.Parts.HasYears | XsdDuration.Parts.HasMonths)) != 0)
                    goto InvalidFormat;
            }
            return null;

        InvalidFormat:
            return new FormatException(string.Format(ResXml.XmlConvert_BadFormat, s, durationType));

        Error:
            return new OverflowException(string.Format(ResXml.XmlConvert_Overflow, s, durationType));
        }