public void TestBuilderAdd() { var builder1 = new BinaryCodeBuilder( new byte[] { 100, 255 } ); var builder2 = new BinaryCodeBuilder(); var bytes = new byte[] { 100, 255, 201 }; builder1.AppendBit(1); builder1.AppendBit(0); builder1.AppendBit(0); builder1.AppendBit(1); builder1.AppendBit(0); builder2.Append(builder1); builder2.AppendBit(0); builder2.AppendBit(1); builder2.AppendBit(1); var storedBytes2 = builder2.ToBytes(); for (int i = 0; i < bytes.Length; i++) { Assert.AreEqual(bytes[i], storedBytes2[i]); } }
public virtual BinaryCodeBuilder Encode(object o, ConverterCategory converterCategory = ConverterCategory.ANY, BinaryCodeBuilder builder = null) { if (builder == null) { builder = new BinaryCodeBuilder(); } BinaryEncoderData encoderData = GetSpecificEncoder(o, converterCategory); IEnumerable <byte> encodedObject = null; if (encoderData.ConverterType == ConverterType.NULL) { builder.AppendBit(0); builder.AppendBit(0); return(builder); } else if (encoderData.ConverterType == ConverterType.EXCLUSIVE) { encodedObject = encoderData.Encoder.Invoke(o); builder.AppendBit(0); builder.AppendBit(1); byte[] typeBytes = EncodeType(o.GetType()); builder.Append(EncodeLength((uint)typeBytes.Length)); builder.AppendBytes(typeBytes); } else { encodedObject = encoderData.Encoder.Invoke(o); builder.AppendBit(1); if (encoderData.ConverterType == ConverterType.INCLUSIVE_SERIALIZABLE) { // Inclusive serializable, no need to encode type builder.AppendBit(0); } else { // Inclusive primitive, no need to encode type builder.AppendBit(1); } } uint length = (uint)encodedObject.Count(); builder.Append(EncodeLength(length)); builder.AppendBytes(encodedObject); return(builder); }
protected BinaryCodeBuilder EncodeLength(uint length) { byte lengthSizeInBytes = GetNumberOfBytesToStoreLength(length); BinaryCodeBuilder builder = new BinaryCodeBuilder(); builder.AppendBit((byte)(lengthSizeInBytes % 2)); builder.AppendBit((byte)((lengthSizeInBytes / 2) % 2)); // Minimum length is 1 byte so we start counting that value with 0, meaning 0 represents 1, 1 represents 2 etc. byte[] lengthBytes = BitConverter.GetBytes(length); for (int i = 0; i <= lengthSizeInBytes; i++) { builder.AppendByte(lengthBytes[i]); } return(builder); }
static void Main(string[] args) { var storer = new BinaryCodeBuilder(); var a = new byte[] { 0, 1, 1, 0, 0 }; var b = new byte[] { 1, 1, 1, 0, 1 }; var c = new byte[] { 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1 }; storer.AppendBits(a); storer.AppendBits(b); storer.AppendBits(c); storer.Print(); }
public void TestBytesAdd() { var builder1 = new BinaryCodeBuilder(); var builder2 = new BinaryCodeBuilder(); var bytes = new byte[] { 100, 140, 255, 0, 24 }; for (int i = 0; i < bytes.Length; i++) { builder1.AppendByte(bytes[i]); } builder2.AppendBytes(bytes); var storedBytes1 = builder1.ToBytes(); var storedBytes2 = builder2.ToBytes(); for (int i = 0; i < bytes.Length; i++) { Assert.AreEqual(bytes[i], storedBytes1[i]); Assert.AreEqual(bytes[i], storedBytes2[i]); } }
protected virtual IEnumerable <byte> ComplexTypeEncoder(object o) { bool firstLevelEncoding = false; if (_encodedComplexObjects == null) { firstLevelEncoding = true; _encodedComplexObjects = new List <object>(); } if (_encodedComplexObjects.Contains(o)) { // Infinite encoding loop detected throw new InfiniteEncodingLoopException(o, "Infinite encoding loop detected"); } _encodedComplexObjects.Add(o); // Remember we already encoded this one object in particular List <byte> result = new List <byte>(); Type t = o.GetType(); // Original type accessable fields (all fields apart from private fields in base types as these are not inherited) var hierarchyFieldInfos = new List <FieldInfo[]>(); hierarchyFieldInfos.Add(t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)); Type inherited = t.BaseType; // Base types non-public fields (later restricted to private fields only) while (inherited != null && inherited != typeof(object)) { hierarchyFieldInfos.Add(inherited.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)); inherited = inherited.BaseType; } int hierarchyDescentCounter = 0; // How many times to go up the class parent hierarchy to get access to currently encoded private fields bool originalType = true; // whether we are currently encoding fields accessable from the object type, not parent types object currentlyEncodedObject; BinaryCodeBuilder encodedAsBuilder; BinaryCodeBuilder builder = new BinaryCodeBuilder(); foreach (var fieldArr in hierarchyFieldInfos) { foreach (var field in fieldArr) { if (field.IsPrivate || originalType) { if (hierarchyDescentCounter > 0) { for (int i = 0; i < hierarchyDescentCounter; i++) { builder.AppendBit(1); } hierarchyDescentCounter = 0; } builder.AppendBit(0); // 0 indicates end of going up the class hierarchy byte[] bytes = EncodeFieldName(field.Name); builder.Append(EncodeLength((uint)bytes.Length)); builder.AppendBytes(bytes); currentlyEncodedObject = field.GetValue(o); encodedAsBuilder = Encode(currentlyEncodedObject); builder.Append(encodedAsBuilder); } } hierarchyDescentCounter++; originalType = false; } if (firstLevelEncoding) { _encodedComplexObjects.Clear(); _encodedComplexObjects = null; } return(builder); }