/// <include file='../../docs.xml' /// path='docs/doc[@name="M:PeterO.Cbor.CBORDataUtilities.ParseJSONNumber(System.String,System.Boolean,System.Boolean,System.Boolean)"]/*'/> public static CBORObject ParseJSONNumber( string str, bool integersOnly, bool positiveOnly, bool preserveNegativeZero) { if (String.IsNullOrEmpty(str)) { return(null); } var offset = 0; var negative = false; if (str[0] == '-' && !positiveOnly) { negative = true; ++offset; } var mantInt = 0; FastInteger2 mant = null; var mantBuffer = 0; var mantBufferMult = 1; var expBuffer = 0; var expBufferMult = 1; var haveDecimalPoint = false; var haveDigits = false; var haveDigitsAfterDecimal = false; var haveExponent = false; var newScaleInt = 0; FastInteger2 newScale = null; int i = offset; // Ordinary number if (i < str.Length && str[i] == '0') { ++i; haveDigits = true; if (i == str.Length) { if (preserveNegativeZero && negative) { return(CBORObject.FromObject( EDecimal.NegativeZero)); } return(CBORObject.FromObject(0)); } if (!integersOnly) { if (str[i] == '.') { haveDecimalPoint = true; ++i; } else if (str[i] == 'E' || str[i] == 'e') { haveExponent = true; } else { return(null); } } else { return(null); } } for (; i < str.Length; ++i) { if (str[i] >= '0' && str[i] <= '9') { var thisdigit = (int)(str[i] - '0'); if (mantInt > MaxSafeInt) { if (mant == null) { mant = new FastInteger2(mantInt); mantBuffer = thisdigit; mantBufferMult = 10; } else { if (mantBufferMult >= 1000000000) { mant.Multiply(mantBufferMult).AddInt(mantBuffer); mantBuffer = thisdigit; mantBufferMult = 10; } else { mantBufferMult *= 10; mantBuffer = (mantBuffer << 3) + (mantBuffer << 1); mantBuffer += thisdigit; } } } else { mantInt *= 10; mantInt += thisdigit; } haveDigits = true; if (haveDecimalPoint) { haveDigitsAfterDecimal = true; if (newScaleInt == Int32.MinValue) { newScale = newScale ?? (new FastInteger2(newScaleInt)); newScale.AddInt(-1); } else { --newScaleInt; } } } else if (!integersOnly && str[i] == '.') { if (!haveDigits) { // no digits before the decimal point return(null); } if (haveDecimalPoint) { return(null); } haveDecimalPoint = true; } else if (!integersOnly && (str[i] == 'E' || str[i] == 'e')) { haveExponent = true; ++i; break; } else { return(null); } } if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal)) { return(null); } if (mant != null && (mantBufferMult != 1 || mantBuffer != 0)) { mant.Multiply(mantBufferMult).AddInt(mantBuffer); } if (haveExponent) { FastInteger2 exp = null; var expInt = 0; offset = 1; haveDigits = false; if (i == str.Length) { return(null); } if (str[i] == '+' || str[i] == '-') { if (str[i] == '-') { offset = -1; } ++i; } for (; i < str.Length; ++i) { if (str[i] >= '0' && str[i] <= '9') { haveDigits = true; var thisdigit = (int)(str[i] - '0'); if (expInt > MaxSafeInt) { if (exp == null) { exp = new FastInteger2(expInt); expBuffer = thisdigit; expBufferMult = 10; } else { if (expBufferMult >= 1000000000) { exp.Multiply(expBufferMult).AddInt(expBuffer); expBuffer = thisdigit; expBufferMult = 10; } else { // multiply expBufferMult and expBuffer each by 10 expBufferMult = (expBufferMult << 3) + (expBufferMult << 1); expBuffer = (expBuffer << 3) + (expBuffer << 1); expBuffer += thisdigit; } } } else { expInt *= 10; expInt += thisdigit; } } else { return(null); } } if (!haveDigits) { return(null); } if (exp != null && (expBufferMult != 1 || expBuffer != 0)) { exp.Multiply(expBufferMult).AddInt(expBuffer); } if (offset >= 0 && newScaleInt == 0 && newScale == null && exp == null) { newScaleInt = expInt; } else if (exp == null) { newScale = newScale ?? (new FastInteger2(newScaleInt)); if (offset < 0) { newScale.SubtractInt(expInt); } else if (expInt != 0) { newScale.AddInt(expInt); } } else { newScale = newScale ?? (new FastInteger2(newScaleInt)); if (offset < 0) { newScale.Subtract(exp); } else { newScale.Add(exp); } } } if (i != str.Length) { // End of the string wasn't reached, so isn't a number return(null); } if ((newScale == null && newScaleInt == 0) || (newScale != null && newScale.Sign == 0)) { // No fractional part if (mant != null && mant.CanFitInInt32()) { mantInt = mant.AsInt32(); mant = null; } if (mant == null) { // NOTE: mantInt can only be 0 or greater, so overflow is impossible #if DEBUG if (mantInt < 0) { throw new ArgumentException("mantInt (" + mantInt + ") is less than 0"); } #endif if (negative) { mantInt = -mantInt; if (preserveNegativeZero && mantInt == 0) { return(CBORObject.FromObject( EDecimal.NegativeZero)); } } return(CBORObject.FromObject(mantInt)); } else { EInteger bigmant2 = mant.AsBigInteger(); if (negative) { bigmant2 = -(EInteger)bigmant2; } return(CBORObject.FromObject(bigmant2)); } } else { EInteger bigmant = (mant == null) ? ((EInteger)mantInt) : mant.AsBigInteger(); EInteger bigexp = (newScale == null) ? ((EInteger)newScaleInt) : newScale.AsBigInteger(); if (negative) { bigmant = -(EInteger)bigmant; } EDecimal edec; edec = EDecimal.Create( bigmant, bigexp); if (negative && preserveNegativeZero && bigmant.IsZero) { EDecimal negzero = EDecimal.NegativeZero; negzero = negzero.Quantize(bigexp, null); edec = negzero.Subtract(edec); } return(CBORObject.FromObject(edec)); } }
internal FastInteger2 Add(FastInteger2 val) { EInteger valValue; switch (this.integerMode) { case 0: if (val.integerMode == 0) { if ((this.smallValue < 0 && (int)val.smallValue < Int32.MinValue - this.smallValue) || (this.smallValue > 0 && (int)val.smallValue > Int32.MaxValue - this.smallValue)) { // would overflow if (val.smallValue >= 0) { this.integerMode = 1; this.mnum = new MutableNumber(this.smallValue); this.mnum.Add(val.smallValue); } else { this.integerMode = 2; this.largeValue = (EInteger)this.smallValue; this.largeValue += (EInteger)val.smallValue; } } else { this.smallValue += val.smallValue; } } else { this.integerMode = 2; this.largeValue = (EInteger)this.smallValue; valValue = val.AsBigInteger(); this.largeValue += (EInteger)valValue; } break; case 1: if (val.integerMode == 0 && val.smallValue >= 0) { this.mnum.Add(val.smallValue); } else { this.integerMode = 2; this.largeValue = this.mnum.ToEInteger(); valValue = val.AsBigInteger(); this.largeValue += (EInteger)valValue; } break; case 2: valValue = val.AsBigInteger(); this.largeValue += (EInteger)valValue; break; default: throw new InvalidOperationException(); } return(this); }
internal FastInteger2 Add(FastInteger2 val) { EInteger valValue; switch (this.integerMode) { case 0: if (val.integerMode == 0) { if ((this.smallValue < 0 && (int)val.smallValue < Int32.MinValue - this.smallValue) || (this.smallValue > 0 && (int)val.smallValue > Int32.MaxValue - this.smallValue)) { // would overflow if (val.smallValue >= 0) { this.integerMode = 1; this.mnum = new MutableNumber(this.smallValue); this.mnum.Add(val.smallValue); } else { this.integerMode = 2; this.largeValue = (EInteger)this.smallValue; this.largeValue += (EInteger)val.smallValue; } } else { this.smallValue += val.smallValue; } } else { integerMode = 2; largeValue = (EInteger)smallValue; valValue = val.AsBigInteger(); largeValue += (EInteger)valValue; } break; case 1: if (val.integerMode == 0 && val.smallValue >= 0) { this.mnum.Add(val.smallValue); } else { integerMode = 2; largeValue = mnum.ToEInteger(); valValue = val.AsBigInteger(); largeValue += (EInteger)valValue; } break; case 2: valValue = val.AsBigInteger(); this.largeValue += (EInteger)valValue; break; default: throw new InvalidOperationException(); } return this; }
/// <summary>Internal API.</summary> /// <param name='val'>The parameter <paramref name='val'/> is an /// internal parameter.</param> /// <returns>A FastInteger2 object.</returns> internal FastInteger2 Subtract(FastInteger2 val) { EInteger valValue; switch (this.integerMode) { case 0: if (val.integerMode == 0) { int vsv = val.smallValue; if ((vsv < 0 && Int32.MaxValue + vsv < this.smallValue) || (vsv > 0 && Int32.MinValue + vsv > this.smallValue)) { // would overflow, convert to large this.integerMode = 2; this.largeValue = (EInteger)this.smallValue; this.largeValue -= (EInteger)vsv; } else { this.smallValue -= vsv; } } else { this.integerMode = 2; this.largeValue = (EInteger)this.smallValue; valValue = val.AsBigInteger(); this.largeValue -= (EInteger)valValue; } break; case 1: if (val.integerMode == 1) { // NOTE: Mutable numbers are // currently always zero or positive this.mnum.Subtract(val.mnum); } else if (val.integerMode == 0 && val.smallValue >= 0) { this.mnum.SubtractInt(val.smallValue); } else { this.integerMode = 2; this.largeValue = this.mnum.ToEInteger(); valValue = val.AsBigInteger(); this.largeValue -= (EInteger)valValue; } break; case 2: valValue = val.AsBigInteger(); this.largeValue -= (EInteger)valValue; break; default: throw new InvalidOperationException(); } return(this); }
/// <include file='../../docs.xml' /// path='docs/doc[@name="M:PeterO.Cbor.FastInteger2.Subtract(PeterO.Cbor.FastInteger2)"]/*'/> internal FastInteger2 Subtract(FastInteger2 val) { EInteger valValue; switch (this.integerMode) { case 0: if (val.integerMode == 0) { int vsv = val.smallValue; if ((vsv < 0 && Int32.MaxValue + vsv < this.smallValue) || (vsv > 0 && Int32.MinValue + vsv > this.smallValue)) { // would overflow, convert to large this.integerMode = 2; this.largeValue = (EInteger)this.smallValue; this.largeValue -= (EInteger)vsv; } else { this.smallValue -= vsv; } } else { integerMode = 2; largeValue = (EInteger)smallValue; valValue = val.AsBigInteger(); largeValue -= (EInteger)valValue; } break; case 1: if (val.integerMode == 1) { // NOTE: Mutable numbers are // currently always zero or positive this.mnum.Subtract(val.mnum); } else if (val.integerMode == 0 && val.smallValue >= 0) { mnum.SubtractInt(val.smallValue); } else { integerMode = 2; largeValue = mnum.ToEInteger(); valValue = val.AsBigInteger(); largeValue -= (EInteger)valValue; } break; case 2: valValue = val.AsBigInteger(); this.largeValue -= (EInteger)valValue; break; default: throw new InvalidOperationException(); } return this; }