public static CBORObject Multiply(CBORObject a, CBORObject b) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); int combo = (a.ItemType << 4) | b.ItemType; BigInteger bvalueA; BigInteger bvalueB; switch (combo) { case (CBORObject.CBORObjectType_Integer << 4) | CBORObject.CBORObjectType_Integer: { long valueA = (long)a.ThisItem; long valueB = (long)b.ThisItem; bool apos = (valueA > 0L); bool bpos = (valueB > 0L); if ( (apos && ((!bpos && (Int64.MinValue / valueA) > valueB) || (bpos && valueA > (Int64.MaxValue / valueB)))) || (!apos && ((!bpos && valueA != 0L && (Int64.MaxValue / valueA) > valueB) || (bpos && valueA < (Int64.MinValue / valueB))))) { // would overflow, convert to BigInteger return CBORObject.FromObject(((BigInteger)valueA) * (BigInteger)valueB); } return CBORObject.FromObject(valueA * valueB); } case (CBORObject.CBORObjectType_Integer << 4) | CBORObject.CBORObjectType_BigInteger: { bvalueA = (BigInteger)(long)a.ThisItem; bvalueB = (BigInteger)b.ThisItem; return CBORObject.FromObject(bvalueA * (BigInteger)bvalueB); } case (CBORObject.CBORObjectType_BigInteger << 4) | CBORObject.CBORObjectType_Integer: { bvalueA = (BigInteger)a.ThisItem; bvalueB = (BigInteger)(long)b.ThisItem; return CBORObject.FromObject(bvalueA * (BigInteger)bvalueB); } case (CBORObject.CBORObjectType_BigInteger << 4) | CBORObject.CBORObjectType_BigInteger: { bvalueA = (BigInteger)a.ThisItem; bvalueB = (BigInteger)b.ThisItem; return CBORObject.FromObject(bvalueA * (BigInteger)bvalueB); } default: return CBORObject.FromObject(a.AsExtendedDecimal().Multiply(b.AsExtendedDecimal())); } }
// This is a more "portable" version of ConvertToBigNum, // but it's much slower on relatively large BigIntegers. private static CBORObject ConvertToBigNumPortable(CBORObject o, bool negative) { if(o.ItemType!=CBORObjectType_ByteString) throw new CBORException("Byte array expected"); byte[] data=(byte[])o.ThisItem; if(data.Length<=7){ long x=0; if(data.Length>0)x|=(((long)data[0])&0xFF)<<48; if(data.Length>1)x|=(((long)data[1])&0xFF)<<40; if(data.Length>2)x|=(((long)data[2])&0xFF)<<32; if(data.Length>3)x|=(((long)data[3])&0xFF)<<24; if(data.Length>4)x|=(((long)data[4])&0xFF)<<16; if(data.Length>5)x|=(((long)data[5])&0xFF)<<8; if(data.Length>6)x|=(((long)data[6])&0xFF); if(negative)x=-x; return FromObject(x); } BigInteger bi=BigInteger.Zero; for(int i=0;i<data.Length;i++){ if(i+7<=data.Length){ long x=(((long)data[i])&0xFF)<<48; x|=(((long)data[i+1])&0xFF)<<40; x|=(((long)data[i+2])&0xFF)<<32; x|=(((long)data[i+3])&0xFF)<<24; x|=(((long)data[i+4])&0xFF)<<16; x|=(((long)data[i+5])&0xFF)<<8; x|=(((long)data[i+6])&0xFF); bi<<=56; bi|=(BigInteger)x; i+=6; } else { bi<<=8; int x=((int)data[i])&0xFF; bi|=(BigInteger)x; } } if(negative){ bi=BigInteger.MinusOne-(BigInteger)bi; // Convert to a negative } return RewrapObject(o,FromObject(bi)); }
public static CBORObject Addition(CBORObject a, CBORObject b) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); int combo = (a.ItemType << 4) | b.ItemType; BigInteger bvalueA; BigInteger bvalueB; switch (combo) { case (CBORObject.CBORObjectType_Integer << 4) | CBORObject.CBORObjectType_Integer: { long valueA = (long)a.ThisItem; long valueB = (long)b.ThisItem; if ((valueA < 0 && valueB < Int64.MinValue - valueA) || (valueA > 0 && valueB > Int64.MaxValue - valueA)) { // would overflow, convert to BigInteger return CBORObject.FromObject(((BigInteger)valueA) + (BigInteger)valueB); } return CBORObject.FromObject(valueA + valueB); } case (CBORObject.CBORObjectType_Integer << 4) | CBORObject.CBORObjectType_BigInteger: { bvalueA = (BigInteger)(long)a.ThisItem; bvalueB = (BigInteger)b.ThisItem; return CBORObject.FromObject(bvalueA + (BigInteger)bvalueB); } case (CBORObject.CBORObjectType_BigInteger << 4) | CBORObject.CBORObjectType_Integer: { bvalueA = (BigInteger)a.ThisItem; bvalueB = (BigInteger)(long)b.ThisItem; return CBORObject.FromObject(bvalueA + (BigInteger)bvalueB); } case (CBORObject.CBORObjectType_BigInteger << 4) | CBORObject.CBORObjectType_BigInteger: { bvalueA = (BigInteger)a.ThisItem; bvalueB = (BigInteger)b.ThisItem; return CBORObject.FromObject(bvalueA + (BigInteger)bvalueB); } default: return CBORObject.FromObject(a.AsExtendedDecimal().Add(b.AsExtendedDecimal())); } }
private static string ObjectMessages(CBORObject o1, CBORObject o2, String s) { if (o1.Type == CBORType.Number && o2.Type == CBORType.Number) { return s + ":\n" + o1.ToString() + " and\n" + o2.ToString() + "\nOR\n" + o1.AsExtendedDecimal().ToString() + " and\n" + o2.AsExtendedDecimal().ToString() + "\nOR\n" + "AddSubCompare(" + ToByteArrayString(o1) + ",\n" + ToByteArrayString(o2) + ");"; } else { return s + ":\n" + o1.ToString() + " and\n" + o2.ToString() + "\nOR\n" + ToByteArrayString(o1) + " and\n" + ToByteArrayString(o2); } }
private static int CompareTestReciprocal(CBORObject o1, CBORObject o2) { if ((o1) == null) throw new ArgumentNullException("o1"); if ((o2) == null) throw new ArgumentNullException("o2"); int cmp = o1.CompareTo(o2); int cmp2 = o2.CompareTo(o1); if (-cmp2 != cmp) { Assert.AreEqual(cmp, -cmp2, ObjectMessages(o1, o2, "Not reciprocal")); } return cmp; }
private static void CompareTestLess(CBORObject o1, CBORObject o2) { if (CompareTestReciprocal(o1, o2) >= 0) Assert.Fail(ObjectMessages(o1, o2, "Not less: " + CompareTestReciprocal(o1, o2))); }
private static void CompareTestEqual(CBORObject o1, CBORObject o2) { if (CompareTestReciprocal(o1, o2) != 0) Assert.Fail(ObjectMessages(o1, o2, "Not equal: " + CompareTestReciprocal(o1, o2))); }
private static void CompareDecimals(CBORObject o1, CBORObject o2) { int cmpDecFrac = o1.AsExtendedDecimal().CompareTo(o2.AsExtendedDecimal()); int cmpCobj = CompareTestReciprocal(o1, o2); if (cmpDecFrac != cmpCobj) { Assert.AreEqual(cmpDecFrac, cmpCobj, ObjectMessages(o1, o2, "Compare: Results don't match")); } TestCommon.AssertRoundTrip(o1); TestCommon.AssertRoundTrip(o2); }
private static void AddSubCompare(CBORObject o1, CBORObject o2) { ExtendedDecimal cmpDecFrac = o1.AsExtendedDecimal().Add(o2.AsExtendedDecimal()); ExtendedDecimal cmpCobj = CBORObject.Addition(o1, o2).AsExtendedDecimal(); if (cmpDecFrac.CompareTo(cmpCobj) != 0) { Assert.AreEqual(0, cmpDecFrac.CompareTo(cmpCobj), ObjectMessages(o1, o2, "Add: Results don't match:\n" + cmpDecFrac + " vs\n" + cmpCobj)); } cmpDecFrac = o1.AsExtendedDecimal().Subtract(o2.AsExtendedDecimal()); cmpCobj = CBORObject.Subtract(o1, o2).AsExtendedDecimal(); if (cmpDecFrac.CompareTo(cmpCobj) != 0) { Assert.AreEqual(0, cmpDecFrac.CompareTo(cmpCobj), ObjectMessages(o1, o2, "Subtract: Results don't match:\n" + cmpDecFrac + " vs\n" + cmpCobj)); } CompareDecimals(o1, o2); }
public static string ToByteArrayString(CBORObject obj) { byte[] bytes = obj.EncodeToBytes(); StringBuilder sb = new StringBuilder(); string hex = "0123456789ABCDEF"; sb.Append("CBORObject.DecodeFromBytes(new byte[]{"); for (int i = 0; i < bytes.Length; i++) { if (i > 0) sb.Append(","); if ((bytes[i] & 0x80) != 0) sb.Append("(byte)0x"); else sb.Append("0x"); sb.Append(hex[(bytes[i] >> 4) & 0xF]); sb.Append(hex[(bytes[i]) & 0xF]); } sb.Append("})"); return sb.ToString(); }
private static byte[] EncodingToBytes(CBORObject b) { try { using (var s = new MemoryStream()) { BEncoding.Write(b, s); return s.ToArray(); } } catch (IOException ex) { throw new CBORException("", ex); } }
public static void AssertRoundTrip(CBORObject o) { CBORObject o2 = FromBytesTestAB(o.EncodeToBytes()); if (o2.Type == CBORType.Map && o.Type == CBORType.Map) { // Skip because key order may be different } else { if (!o.ToString().Equals(o2.ToString())) Assert.AreEqual(o.ToString(), o2.ToString(), "o2 is not equal to o"); } TestNumber(o); AssertEqualsHashCode(o, o2); }
public static void TestNumber(CBORObject o) { if(o.Type!= CBORType.Number){ return; } if(o.IsPositiveInfinity() || o.IsNegativeInfinity() || o.IsNaN()){ try { o.AsByte(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsInt16(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsInt32(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsInt64(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsSingle(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsDouble(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsBigInteger(); } catch(OverflowException){ } catch(Exception ex){ Assert.Fail("Object: "+o+", "+ex.ToString()); throw new InvalidOperationException("",ex); } return; } BigInteger df=o.AsExtendedDecimal().ToBigInteger(); try { o.AsBigInteger(); } catch(Exception ex){ Assert.Fail("Object: "+o+", int: "+df+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsSingle(); } catch(Exception ex){ Assert.Fail("Object: "+o+", int: "+df+", "+ex.ToString()); throw new InvalidOperationException("",ex); } try { o.AsDouble(); } catch(Exception ex){ Assert.Fail("Object: "+o+", int: "+df+", "+ex.ToString()); throw new InvalidOperationException("",ex); } }
public static void AssertSer(CBORObject o, String s) { if (!s.Equals(o.ToString())) Assert.AreEqual(s, o.ToString(), "o is not equal to s"); // Test round-tripping CBORObject o2 = FromBytesTestAB(o.EncodeToBytes()); if (!s.Equals(o2.ToString())) Assert.AreEqual(s, o2.ToString(), "o2 is not equal to s"); TestNumber(o); AssertEqualsHashCode(o, o2); }
public static void Write(CBORObject obj, Stream stream) { if (obj.Type == CBORType.Number) { stream.WriteByte(unchecked((byte)((byte)'i'))); writeUtf8(obj.AsBigInteger().ToString(), stream); stream.WriteByte(unchecked((byte)((byte)'e'))); } else if (obj.Type == CBORType.TextString) { string s = obj.AsString(); long length = DataUtilities.GetUtf8Length(s, false); if (length < 0) throw new CBORException("invalid string"); writeUtf8(Convert.ToString((long)length, CultureInfo.InvariantCulture), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(s, stream); } else if (obj.Type == CBORType.Map) { bool hasNonStringKeys = false; foreach (CBORObject key in obj.Keys) { if (key.Type != CBORType.TextString) { hasNonStringKeys = true; break; } } if (hasNonStringKeys) { var sMap = new Dictionary<String, CBORObject>(); // Copy to a map with String keys, since // some keys could be duplicates // when serialized to strings foreach (CBORObject key in obj.Keys) { CBORObject value = obj[key]; string str = (key.Type == CBORType.TextString) ? key.AsString() : key.ToJSONString(); sMap[str] = value; } stream.WriteByte(unchecked((byte)((byte)'d'))); foreach (KeyValuePair<string, CBORObject> entry in sMap) { string key = entry.Key; CBORObject value = entry.Value; long length = DataUtilities.GetUtf8Length(key, false); if (length < 0) throw new CBORException("invalid string"); writeUtf8(Convert.ToString((long)length, CultureInfo.InvariantCulture), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(key, stream); Write(value, stream); } stream.WriteByte(unchecked((byte)((byte)'e'))); } else { stream.WriteByte(unchecked((byte)((byte)'d'))); foreach (CBORObject key in obj.Keys) { string str = key.AsString(); long length = DataUtilities.GetUtf8Length(str, false); if (length < 0) throw new CBORException("invalid string"); writeUtf8(Convert.ToString((long)length, CultureInfo.InvariantCulture), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(str, stream); Write(obj[key], stream); } stream.WriteByte(unchecked((byte)((byte)'e'))); } } else if (obj.Type == CBORType.Array) { stream.WriteByte(unchecked((byte)((byte)'l'))); for (int i = 0; i < obj.Count; i++) { Write(obj[i], stream); } stream.WriteByte(unchecked((byte)((byte)'e'))); } else { string str = obj.ToJSONString(); long length = DataUtilities.GetUtf8Length(str, false); if (length < 0) throw new CBORException("invalid string"); writeUtf8(Convert.ToString((long)length, CultureInfo.InvariantCulture), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(str, stream); } }