internal PositionInfo(EmberId emberId, bool isInner, long lengthPosition, long?endPosition) { this.EmberId = emberId; this.IsInner = isInner; this.LengthPosition = lengthPosition; this.EndPosition = endPosition; }
public void MainTest() { var u1 = default(EmberId); var n1 = this.Random.Next(); var n2 = n1 + 1; var a1 = EmberId.CreateApplication(n1); var a2 = EmberId.CreateApplication(n2); var c1 = EmberId.CreateContextSpecific(n1); EmberId p1; using (var stream = new MemoryStream(new byte[] { 0xE0, 0x03, 0x01, 0x01, 0xFF })) using (var reader = new EmberReader(stream, 1)) { reader.Read(); p1 = reader.OuterId; } TestStructEquality(a1, a2, (l, r) => l == r, (l, r) => l != r); TestStructEquality(a1, c1, (l, r) => l == r, (l, r) => l != r); TestParse(u1); TestParse(a1); TestParse(c1); TestParse(p1); EmberId dummy; Assert.IsFalse(EmberId.TryParse("S-234", out dummy)); Assert.IsFalse(EmberId.TryParse("U+234", out dummy)); Assert.IsFalse(EmberId.TryParse("P--234", out dummy)); Assert.IsFalse(EmberId.TryParse("A-89345734579385749354", out dummy)); }
public void ExceptionTest() { AssertThrow <ArgumentNullException>(() => new EmberWriter(null, 1).Dispose()); AssertThrow <ArgumentException>(() => new EmberWriter(new MemoryStream(), 0).Dispose()); using (var writer = new EmberWriter(new MemoryStream(), 1)) { var outer = EmberId.CreateApplication(0); AssertThrow <ArgumentNullException>( () => writer.WriteValue(outer, (byte[])null), () => writer.WriteValue(outer, (int[])null), () => writer.WriteValue(outer, (string)null)); AssertThrow <ArgumentOutOfRangeException>( () => writer.WriteStartApplicationDefinedType(outer, InnerNumber.FirstApplication - 1)); writer.Dispose(); AssertThrow <ObjectDisposedException>( () => writer.WriteValue(outer, true), () => writer.WriteValue(outer, 0), () => writer.WriteValue(outer, new byte[] { }), () => writer.WriteValue(outer, 0.0), () => writer.WriteValue(outer, string.Empty), () => writer.WriteValue(outer, new int[] { }), () => writer.WriteStartSequence(outer), () => writer.WriteStartSet(outer), () => writer.WriteStartApplicationDefinedType(outer, InnerNumber.FirstApplication), () => writer.WriteEndContainer()); } }
private static void AssertDecode(int expectedInnerNumber, Action <EmberReader> assertEqual, params byte[] input) { using (var stream = new MemoryStream(input)) using (var reader = new EmberReader(stream, 1)) { AssertThrow <InvalidOperationException>(() => reader.InnerNumber.GetHashCode().Ignore()); AssertThrow <InvalidOperationException>(() => reader.OuterId.Ignore()); AssertThrow <InvalidOperationException>(() => reader.ReadContentsAsObject()); Assert.IsFalse(reader.CanReadContents); Assert.IsTrue(reader.Read()); Assert.AreEqual(EmberId.CreateApplication(0), reader.OuterId); Assert.AreEqual(expectedInnerNumber, reader.InnerNumber); assertEqual(reader); AssertThrow <InvalidOperationException>(() => reader.ReadContentsAsObject()); Assert.IsFalse(reader.Read()); reader.Dispose(); Assert.IsFalse(reader.CanReadContents); AssertThrow <ObjectDisposedException>(() => reader.InnerNumber.Ignore()); AssertThrow <ObjectDisposedException>(() => reader.OuterId.Ignore()); AssertThrow <ObjectDisposedException>(() => reader.ReadContentsAsObject()); } using (var writer = XmlWriter.Create(Console.Out, new XmlWriterSettings() { Indent = true })) { new EmberConverter(GlowTypes.Instance).ToXml(input, writer); Console.WriteLine(); Console.WriteLine(); } }
/// <summary>Writes <paramref name="outer"/> with definite length followed by <paramref name="value"/> as /// Boolean.</summary> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteValue(EmberId outer, bool value) { this.AssertNotDisposed(); this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength + 1); this.WriteIdentifiersAndLengths(outer, Boolean, 1); Write8Bit(this.writeBuffer, value ? Constants.AllBitsSetLong : 0, 0); // AllBitsSet is encoded as 0xFF }
private bool ProcessOuter(EmberId id, long idPosition) { if (id == EndContainer) { if (ReadLength(this.readBuffer) != 0) { throw CreateEmberException( "Unexpected length for End-of-contents identifier at position {0}.", idPosition); } if (this.endPositions.Count == 0) { throw CreateEmberException( "Unexpected excess End-of-contents identifier at position {0}.", idPosition); } var endPosition = this.endPositions.Pop(); if (endPosition.EndPosition.HasValue) { throw CreateEmberException( "Unexpected End-of-contents identifier at position {0} for definite length at position {1}.", idPosition, endPosition.LengthPosition); } return(IsContainer(endPosition)); } else { this.ReadAndProcessLength(id, false); return(true); } }
private static byte GetLeadingOctet(EmberId emberId, int bits) { const int PrimitiveFlag = 0x00; const int ConstructedFlag = 0x20; return((byte)((int)emberId.Class | (emberId.IsConstructed ? ConstructedFlag : PrimitiveFlag) | bits)); }
private void ReadAndProcessLength(EmberId id, bool isInner) { var lengthPosition = this.readBuffer.Position; var length = ReadLength(this.readBuffer); this.endPositions.Push(new PositionInfo(id, isInner, lengthPosition, this.readBuffer.Position + length)); }
/// <summary>Writes <paramref name="outer"/> with definite length followed by <paramref name="value"/> as /// Relative object identifier.</summary> /// <exception cref="ArgumentNullException"><paramref name="value"/> equals <c>null</c>.</exception> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteValue(EmberId outer, int[] value) { this.AssertNotDisposed(); if (value == null) { throw new ArgumentNullException(nameof(value)); } // For byte[] values, the buffer size does not matter this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength); this.tempBuffer.Reserve(SubidentifierMaxLength * value.Length); try { // See http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf, chapter 8.20.2. foreach (int number in value) { Write7Bit(this.tempBuffer, number, Get7BitStartShift(number)); } this.WriteIdentifiersAndLengths(outer, RelativeObjectIdentifier, this.tempBuffer.Count); this.tempBuffer.Flush(); } finally { // Make sure that tempBuffer is empty if anything goes wrong this.tempBuffer.Count = 0; } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// private static void TestParse(EmberId emberId) { EmberId parsed; Assert.IsTrue(EmberId.TryParse(emberId.ToString(), out parsed)); Assert.AreEqual(emberId, parsed); Console.WriteLine(emberId); }
/// <summary>Writes <paramref name="outer"/> with definite length followed by <paramref name="value"/> as /// Integer.</summary> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteValue(EmberId outer, long value) { this.AssertNotDisposed(); this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength + Constants.BytesPerLong); var shift = Get8BitStartShift(value, true); this.WriteIdentifiersAndLengths(outer, Integer, GetLengthFromShift8Bit(shift)); Write8Bit(this.writeBuffer, value, shift); }
/// <summary>See <i>"X.690"</i><cite>X.690</cite>, chapter 8.1.2.</summary> private static void WriteIdentifier(WriteBuffer writeBuffer, EmberId emberId) { if (emberId.Number <= 30) { writeBuffer[writeBuffer.Count++] = GetLeadingOctet(emberId, emberId.Number); } else { writeBuffer[writeBuffer.Count++] = GetLeadingOctet(emberId, 0x1F); Write7Bit(writeBuffer, emberId.Number, Get7BitStartShift(emberId.Number)); } }
private EmberId GetFieldId(FieldPath <string, string> fieldPath) { EmberId emberId; if (this.fieldIds.TryGetValue(fieldPath, out emberId) || EmberId.TryParse(fieldPath.Tail.GetValueOrDefault().FieldId, out emberId)) { return(emberId); } throw new XmlException(string.Format(InvariantCulture, "Unknown field path: {0}.", fieldPath)); }
/// <summary>Writes <paramref name="outer"/> with indefinite length followed by the start of an /// application-defined type with indefinite length.</summary> /// <exception cref="ArgumentOutOfRangeException"><paramref name="innerNumber"/> is smaller than /// <see cref="InnerNumber.FirstApplication"/>.</exception> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteStartApplicationDefinedType(EmberId outer, int innerNumber) { this.AssertNotDisposed(); if (innerNumber < InnerNumber.FirstApplication) { throw new ArgumentOutOfRangeException( nameof(innerNumber), "Must be greater than or equal to InnerNumber.StartFirstApplication"); } this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength); this.WriteIdentifiersAndLengths(outer, EmberId.FromInnerNumber(innerNumber), null); }
/// <summary>Writes <paramref name="outer"/> with definite length followed by <paramref name="value"/> as /// Octetstring.</summary> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteValue(EmberId outer, byte[] value) { this.AssertNotDisposed(); if (value == null) { throw new ArgumentNullException(nameof(value)); } // For byte[] values, the buffer size does not matter this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength); this.WriteIdentifiersAndLengths(outer, Octetstring, value.Length); this.writeBuffer.Write(value, 0, value.Length); }
private void WriteIdentifiersAndLengths(EmberId outer, EmberId inner, int?innerLength) { // The outer length is the inner length + the length of the inner length field + the length of the inner // token (for definite lengths the inner token is always universal and therefore one byte). int innerShift; var innerLengthLength = GetLengthLength(innerLength, out innerShift); var outerLength = innerLength + innerLengthLength + 1; int outerShift; var outerLengthLength = GetLengthLength(outerLength, out outerShift); WriteIdentifier(this.writeBuffer, outer); WriteLength(this.writeBuffer, outerLength, outerShift, outerLengthLength); WriteIdentifier(this.writeBuffer, inner); WriteLength(this.writeBuffer, innerLength, innerShift, innerLengthLength); }
/// <summary>Writes <paramref name="outer"/> with definite length followed by <paramref name="value"/> as /// UTF8String.</summary> /// <exception cref="ArgumentNullException"><paramref name="value"/> equals <c>null</c>.</exception> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteValue(EmberId outer, string value) { this.AssertNotDisposed(); if (value == null) { throw new ArgumentNullException(nameof(value)); } var byteCount = Encoding.UTF8.GetByteCount(value); this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength + byteCount); this.WriteIdentifiersAndLengths(outer, Utf8String, byteCount); this.writeBuffer.WriteAsUtf8(value, byteCount); }
private static void WriteOctetstring(XmlReader reader, EmberWriter writer, EmberId fieldId) { var buffer = new byte[1024]; using (var stream = new MemoryStream()) { var read = ReadValue(reader, r => (int?)r.ReadContentAsBinHex(buffer, 0, buffer.Length), 0); while (read > 0) { stream.Write(buffer, 0, read.Value); read = reader.ReadContentAsBinHex(buffer, 0, buffer.Length); } writer.WriteValue(fieldId, stream.ToArray()); } }
public void MainTest() { AssertEncode( writer => writer.WriteValue(EmberId.CreateApplication(0), true), 0x60, 0x03, 0x01, 0x01, 0xFF); AssertEncode( writer => writer.WriteValue(EmberId.CreateContextSpecific(1), 0x80), 0xA1, 0x04, 0x02, 0x02, 0x00, 0x80); AssertEncode( writer => writer.WriteValue(EmberId.CreateApplication(2), new byte[] { 0x42 }), 0x62, 0x03, 0x04, 0x01, 0x42); AssertEncode(writer => writer.WriteValue(EmberId.CreateContextSpecific(3), 0.0), 0xA3, 0x02, 0x09, 0x00); AssertEncode(writer => writer.WriteValue(EmberId.CreateContextSpecific(3), double.PositiveInfinity), 0xA3, 0x03, 0x09, 0x01, 0x40); AssertEncode(writer => writer.WriteValue(EmberId.CreateContextSpecific(3), double.NegativeInfinity), 0xA3, 0x03, 0x09, 0x01, 0x41); AssertEncode(writer => writer.WriteValue(EmberId.CreateContextSpecific(3), double.NaN), 0xA3, 0x03, 0x09, 0x01, 0x42); AssertEncode(writer => writer.WriteValue(EmberId.CreateContextSpecific(3), -0.0), 0xA3, 0x03, 0x09, 0x01, 0x43); AssertEncode(writer => writer.WriteValue(EmberId.CreateContextSpecific(3), -1.0), 0xA3, 0x05, 0x09, 0x03, 0xC0, 0x00, 0x01); AssertEncode( writer => writer.WriteValue(EmberId.CreateApplication(4), "A"), 0x64, 0x03, 0x0C, 0x01, 0x41); AssertEncode( writer => writer.WriteValue(EmberId.CreateContextSpecific(5), new[] { 15 }), 0xA5, 0x03, 0x0D, 0x01, 0x0F); AssertEncode( writer => writer.WriteStartSequence(EmberId.CreateApplication(6)), 0x66, 0x80, 0x30, 0x80); AssertEncode( writer => writer.WriteStartSet(EmberId.CreateContextSpecific(7)), 0xA7, 0x80, 0x31, 0x80); AssertEncode( writer => writer.WriteStartApplicationDefinedType( EmberId.CreateContextSpecific(7), InnerNumber.FirstApplication), 0xA7, 0x80, 0x60, 0x80); AssertEncode( writer => writer.WriteEndContainer(), 0x00, 0x00, 0x00, 0x00); }
/// <summary>Writes <paramref name="outer"/> with definite length followed by <paramref name="value"/> as /// Real.</summary> /// <exception cref="NotSupportedException">This method is called on a big endian CPU, which is currently not /// supported.</exception> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteValue(EmberId outer, double value) { this.AssertNotDisposed(); this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength); this.tempBuffer.Reserve(10); // 1st byte followed by max. 2 exponent bytes, followed by max 7 mantissa bytes try { WriteReal(this.tempBuffer, value); this.WriteIdentifiersAndLengths(outer, Real, this.tempBuffer.Count); this.tempBuffer.Flush(); } finally { this.tempBuffer.Count = 0; } }
public void InvalidXmlCharactersTest() { using (var stream = new MemoryStream()) { using (var writer = new EmberWriter(stream)) { writer.WriteValue(EmberId.CreateContextSpecific(0), "\0"); } var builder = new StringBuilder(); using (var xmlWriter = XmlWriter.Create(builder)) { var converter = new EmberConverter(); converter.ToXml(stream.ToArray(), xmlWriter); } } }
private int GetInnerNumber(string type) { int innerNumber; if (this.innerNumbers.TryGetValue(type, out innerNumber)) { return(innerNumber); } EmberId id; int? innerNumberCandidate; if (EmberId.TryParse(type, out id) && (innerNumberCandidate = id.ToInnerNumber()).HasValue) { return(innerNumberCandidate.Value); } throw new XmlException(string.Format(InvariantCulture, "Unknown type: {0}.", type)); }
private void AssertEqual <T>( Action <EmberLib.EmberWriter, BerTag, T> write, Func <EmberReader, T> read, T value, Action <T, T> assertEqual) { var number = this.Random.Next(); var outerId = EmberId.CreateApplication(number); var tag = new BerTag(BerClass.Application, (uint)number); var output = new BerMemoryOutput(); var writer = new EmberLib.EmberWriter(output); write(writer, tag, value); using (var input = new MemoryStream(output.ToArray())) using (var reader = new EmberReader(input, 1)) { Assert.IsTrue(reader.Read()); Assert.AreEqual(outerId, reader.OuterId); assertEqual(value, read(reader)); } }
private int ValidateIdentifierAndLength(EmberId innerIdentifier, long innerIdentifierPosition) { if (innerIdentifier.IsConstructed) { throw CreateEmberException( "Unexpected constructed encoding at position {0}.", innerIdentifierPosition); } innerIdentifier.Ignore(); var length = this.ContentsLength; if (!length.HasValue) { throw CreateEmberException( "Unexpected indefinite length for primitive data value at position {0}.", innerIdentifierPosition); } this.CanReadContents = true; return(length.Value); }
public void SkipContentsTest() { using (var stream = new MemoryStream(new byte[] { 0x60, 0x03, 0x01, 0x01, 0xFF, 0x60, 0x03, 0x01, 0x01, 0x00 })) using (var reader = new EmberReader(stream, 1)) { Assert.IsTrue(reader.Read()); Assert.IsTrue(reader.Read()); Assert.IsFalse(reader.ReadContentsAsBoolean()); } var original = new byte[64]; this.Random.NextBytes(original); byte[] encoded; using (var stream = new MemoryStream()) { using (var writer = new EmberWriter(stream)) { writer.WriteValue(EmberId.CreateApplication(0), original); writer.WriteValue(EmberId.CreateApplication(1), true); } encoded = stream.ToArray(); } using (var stream = new MemoryStream(encoded)) using (var reader = new EmberReader(stream, 1)) { Assert.IsTrue(reader.Read()); Assert.AreEqual(InnerNumber.Octetstring, reader.InnerNumber); Assert.IsTrue(reader.Read()); Assert.AreEqual(InnerNumber.Boolean, reader.InnerNumber); Assert.AreEqual(true, reader.ReadContentsAsBoolean()); Assert.IsFalse(reader.Read()); } }
private static void WriteRelativeObjectIdentifier(XmlReader reader, EmberWriter writer, EmberId fieldId) { var pathElements = ReadValue(reader, r => r.ReadContentAsString()).Split('.'); var value = (pathElements.Length == 1) && string.IsNullOrEmpty(pathElements[0]) ? new int[0] : pathElements.Select(s => int.Parse(s, InvariantCulture)).ToArray(); writer.WriteValue(fieldId, value); }
/// <summary>Writes <paramref name="outer"/> with indefinite length followed by the start of a set with /// indefinite length.</summary> /// <exception cref="ObjectDisposedException"><see cref="Dispose"/> has been called.</exception> public void WriteStartSet(EmberId outer) { this.AssertNotDisposed(); this.writeBuffer.Reserve(IdentifiersAndLengthsMaxLength); this.WriteIdentifiersAndLengths(outer, Set, null); }
public void ExceptionTest() => AssertThrow <ArgumentOutOfRangeException>( () => EmberId.CreateApplication(-1), () => EmberId.CreateContextSpecific(-1));
private static string GetFallbackName(int innerNumber) => EmberId.FromInnerNumber(innerNumber).ToString();