Represents a reader that provides the means to read BER-encoded input, as specified in "X.690"X.690.
Only the subset defined in the "Ember+ Specification"Ember+ Specification is supported.
Inheritance: IDisposable
Example #1
0
        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 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));
        }
Example #3
0
        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>Reads the EmBER-encoded data in <paramref name="buffer"/> and writes an equivalent XML
 /// representation with <paramref name="writer"/>.</summary>
 /// <exception cref="ArgumentNullException"><paramref name="buffer"/> and/or <paramref name="writer"/> equal
 /// <c>null</c>.</exception>
 /// <exception cref="EmberException">The EmBER-encoded data is invalid, see <see cref="Exception.Message"/> for
 /// details.</exception>
 public void ToXml(byte[] buffer, XmlWriter writer)
 {
     using (var stream = new MemoryStream(buffer))
         using (var reader = new EmberReader(stream))
         {
             this.ToXml(reader, writer);
         }
 }
Example #5
0
 public void EmptyTest()
 {
     using (var stream = new MemoryStream())
         using (var reader = new EmberReader(stream, 1))
         {
             Assert.IsFalse(reader.Read());
         }
 }
        /// <summary>Reads EmBER data with <paramref name="reader"/> and writes an equivalent XML representation with
        /// <paramref name="writer"/>.</summary>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> and/or <paramref name="writer"/> equal
        /// <c>null</c>.</exception>
        /// <exception cref="EmberException">The EmBER-encoded data is invalid, see <see cref="Exception.Message"/> for
        /// details.</exception>
        public void ToXml(EmberReader reader, XmlWriter writer)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            this.ToXmlCore(reader, writer, default(FieldPath <int, EmberId>), EmberGlobal.InnerNumber);
        }
Example #7
0
        public void ExceptionTest()
        {
            AssertThrow <ArgumentNullException>(
                () => new EmberType(null).Ignore(),
                () => new EmberTypeBag(null).Ignore(),
                () => new EmberConverter(null).Ignore());

            AssertThrow <ArgumentException>(() => new EmberType().Ignore());

            using (var stream = new MemoryStream())
                using (var reader = new EmberReader(stream))
                    using (var writer = XmlWriter.Create(new StringBuilder()))
                    {
                        var converter = new EmberConverter();
                        AssertThrow <ArgumentNullException>(
                            () => converter.ToXml((byte[])null, writer),
                            () => converter.ToXml(new byte[0], null),
                            () => converter.ToXml((EmberReader)null, writer),
                            () => converter.ToXml(reader, null));
                    }

            using (var stringReader = new StringReader(string.Empty))
                using (var reader = XmlReader.Create(stringReader))
                    using (var stream = new MemoryStream())
                        using (var writer = new EmberWriter(stream))
                        {
                            var converter = new EmberConverter();
                            AssertThrow <ArgumentNullException>(
                                () => converter.FromXml(null),
                                () => converter.FromXml(null, writer),
                                () => converter.FromXml(reader, null));
                        }

            AssertXmlException("<whatever type=\"A-11\"></whatever>", "Unknown field path: whatever.");
            AssertXmlException(
                "<A-0 type=\"Sequence\"><whatever type=\"Set\" /></A-0>", "Unknown field path: A-0.whatever.");
            AssertXmlException("<A-0 type=\"C-11\"></A-0>", "Unknown type: C-11.");
            AssertXmlException(
                "<A-0 type=\"A-11\" whatever=\"\"></A-0>",
                "Unexpected Attribute Count: Each element must have exactly one type attribute.");
            AssertXmlException(
                "<A-0 type=\"A-11\"><![CDATA[Whatever]]></A-0>",
                "Unexpected Node Type: Encountered CDATA while looking for Element.");
            AssertXmlException("<A-0 type=\"Boolean\" />", "Unexpected empty element for a field of type Boolean.");
        }
        public void ExceptionTest()
        {
            AssertThrow<ArgumentNullException>(
                () => new EmberType(null).Ignore(),
                () => new EmberTypeBag(null).Ignore(),
                () => new EmberConverter(null).Ignore());

            AssertThrow<ArgumentException>(() => new EmberType().Ignore());

            using (var stream = new MemoryStream())
            using (var reader = new EmberReader(stream))
            using (var writer = XmlWriter.Create(new StringBuilder()))
            {
                var converter = new EmberConverter();
                AssertThrow<ArgumentNullException>(
                    () => converter.ToXml((byte[])null, writer),
                    () => converter.ToXml(new byte[0], null),
                    () => converter.ToXml((EmberReader)null, writer),
                    () => converter.ToXml(reader, null));
            }

            using (var stringReader = new StringReader(string.Empty))
            using (var reader = XmlReader.Create(stringReader))
            using (var stream = new MemoryStream())
            using (var writer = new EmberWriter(stream))
            {
                var converter = new EmberConverter();
                AssertThrow<ArgumentNullException>(
                    () => converter.FromXml(null),
                    () => converter.FromXml(null, writer),
                    () => converter.FromXml(reader, null));
            }

            AssertXmlException("<whatever type=\"A-11\"></whatever>", "Unknown field path: whatever.");
            AssertXmlException(
                "<A-0 type=\"Sequence\"><whatever type=\"Set\" /></A-0>", "Unknown field path: A-0.whatever.");
            AssertXmlException("<A-0 type=\"C-11\"></A-0>", "Unknown type: C-11.");
            AssertXmlException(
                "<A-0 type=\"A-11\" whatever=\"\"></A-0>",
                "Unexpected Attribute Count: Each element must have exactly one type attribute.");
            AssertXmlException(
                "<A-0 type=\"A-11\"><![CDATA[Whatever]]></A-0>",
                "Unexpected Node Type: Encountered CDATA while looking for Element.");
            AssertXmlException("<A-0 type=\"Boolean\" />", "Unexpected empty element for a field of type Boolean.");
        }
Example #9
0
        public void PerformanceTest()
        {
            byte[] payload;

            using (var memoryStream = new MemoryStream())
            {
                using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
                           typeof(EmberPayloads), "BigPayload.ember"))
                {
                    resourceStream.CopyTo(memoryStream);
                }

                payload = memoryStream.ToArray();
            }

            var stopwatch = new Stopwatch();
            var converter = new EmberConverter(GlowTypes.Instance);

            GC.Collect();
            GC.WaitForPendingFinalizers();

            for (int index = 0; index < 100; ++index)
            {
                using (var writer = XmlWriter.Create(TextWriter.Null))
                {
                    stopwatch.Start();

                    using (var stream = new MemoryStream(payload))
                        using (var reader = new EmberReader(stream))
                        {
                            converter.ToXml(reader, writer);
                        }

                    stopwatch.Stop();
                }
            }

            stopwatch.Start();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            stopwatch.Stop();

            Console.WriteLine(stopwatch.ElapsedMilliseconds);
        }
Example #10
0
        private static void ReadAll(params byte[] input)
        {
            using (var stream = new MemoryStream(input))
                using (var reader = new EmberReader(stream, 1))
                {
                    while (reader.Read())
                    {
                        switch (reader.InnerNumber)
                        {
                        case InnerNumber.EndContainer:
                            AssertThrow <InvalidOperationException>(() => reader.OuterId.Ignore());
                            Assert.IsFalse(reader.CanReadContents);
                            AssertThrow <InvalidOperationException>(() => reader.ReadContentsAsObject());
                            break;

                        case InnerNumber.Sequence:
                        case InnerNumber.Set:
                            reader.OuterId.Ignore();
                            Assert.IsFalse(reader.CanReadContents);
                            AssertThrow <InvalidOperationException>(() => reader.ReadContentsAsObject());
                            break;

                        case InnerNumber.Boolean:
                        case InnerNumber.Integer:
                        case InnerNumber.Octetstring:
                        case InnerNumber.Real:
                        case InnerNumber.Utf8String:
                        case InnerNumber.RelativeObjectIdentifier:
                            reader.OuterId.Ignore();
                            Assert.IsTrue(reader.CanReadContents);
                            reader.ReadContentsAsObject();
                            break;

                        default:
                            Assert.IsTrue(reader.InnerNumber >= InnerNumber.FirstApplication);
                            reader.OuterId.Ignore();
                            Assert.IsFalse(reader.CanReadContents);
                            AssertThrow <InvalidOperationException>(() => reader.ReadContentsAsObject());
                            break;
                        }
                    }
                }
        }
Example #11
0
        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));
                }
        }
Example #12
0
        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());
                }
        }
 /// <summary>Reads EmBER data with <paramref name="reader"/> and writes an equivalent XML representation with
 /// <paramref name="writer"/>.</summary>
 /// <exception cref="ArgumentNullException"><paramref name="reader"/> and/or <paramref name="writer"/> equal
 /// <c>null</c>.</exception>
 /// <exception cref="EmberException">The EmBER-encoded data is invalid, see <see cref="Exception.Message"/> for
 /// details.</exception>
 public void ToXml(EmberReader reader, XmlWriter writer) => this.ToXmlCore(
Example #14
0
        public void ExceptionTest()
        {
            TestStandardExceptionConstructors <EmberException>();

            AssertThrow <ArgumentNullException>(() => new EmberReader(null, 1).Dispose());
            AssertEmberException("Incorrect length at position 3.", 0x60, 0x03, 0x0D, 0x01, 0xFF, 0x00);

            using (var stream = new MemoryStream(new byte[] { 0x60, 0x03, 0x01, 0x01, 0xFF }))
                using (var reader = new EmberReader(stream, 1))
                {
                    reader.Read();
                    AssertThrow <InvalidOperationException>(() => reader.ReadContentsAsString());
                    reader.ReadContentsAsBoolean();
                }

            AssertEmberException(
                "Unexpected Universal class for outer identifier at position 0.", 0x01, 0x03, 0x01, 0x01, 0xFF);

            AssertEmberException("Unexpected end of stream.", 0x60);

            AssertEmberException("Unexpected end of stream.", 0x60, 0x05, 0x04, 0x03, 0xFF, 0xFE);

            AssertEmberException(
                "Unexpected end of stream at position 9.", 0x60, 0x08, 0x30, 0x06, 0x60, 0x03, 0x01, 0x01, 0xFF);

            AssertEmberException("Unexpected End-of-contents identifier at position 2.", 0x60, 0x02, 0x00, 0x00);

            AssertEmberException("Unexpected number in universal identifier at position 2.", 0x60, 0x03, 0x03, 0x01, 0xFF);

            AssertEmberException("Unexpected context-specific or private identifier at position 2.", 0x60, 0x03, 0x83, 0x01, 0xFF);
            AssertEmberException("Unexpected context-specific or private identifier at position 2.", 0x60, 0x03, 0xC3, 0x01, 0xFF);

            AssertEmberException("Unexpected length for End-of-contents identifier at position 0.", 0x00, 0x01);

            AssertEmberException("Unexpected excess End-of-contents identifier at position 0.", 0x00, 0x00);

            AssertEmberException(
                "Unexpected End-of-contents identifier at position 6 for definite length at position 1.",
                0x60, 0x06, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00);

            AssertEmberException("Unexpected constructed encoding at position 2.", 0x60, 0x03, 0x21, 0x01, 0xFF);

            AssertEmberException(
                "Unexpected indefinite length for primitive data value at position 2.", 0x60, 0x03, 0x01, 0x80, 0xFF);

            AssertEmberException("Unexpected encoding for Real at position 4.", 0x60, 0x03, 0x09, 0x01, 0x00);

            AssertEmberException("Incorrect length for Real at position 4.", 0x60, 0x04, 0x09, 0x02, 0x80, 0x00);

            AssertEmberException(
                "The exponent of the Real at position 4 exceeds the expected range.",
                0x60, 0x06, 0x09, 0x04, 0x81, 0x04, 0x01, 0x01);

            AssertEmberException(
                "The exponent of the Real at position 4 exceeds the expected range.",
                0x60, 0x06, 0x09, 0x04, 0x81, 0xFC, 0x01, 0x01);

            AssertEmberException(
                "The mantissa of the Real at position 4 is zero.", 0x60, 0x05, 0x09, 0x03, 0x80, 0x00, 0x00);

            AssertEmberException(
                "The length at position 1 exceeds the expected range.", 0x60, 0x84, 0x80, 0x00, 0x00, 0x00);

            AssertEmberException("Unexpected zero length for integer.", 0x60, 0x02, 0x02, 0x00);

            ReadAll(0x60, 0x0A, 0x02, 0x08, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
            AssertEmberException(
                "The integer, length or exponent at position 4 exceeds the expected range.",
                0x60, 0x0B, 0x02, 0x09, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);

            ReadAll(0x60, 0x0A, 0x02, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
            AssertEmberException(
                "The integer, length or exponent at position 4 exceeds the expected range.",
                0x60, 0x0B, 0x02, 0x09, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

            ReadAll(0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x03, 0x01, 0x01, 0xFF);
            AssertEmberException(
                "The identifier number or subidentifier at position 1 exceeds the expected range.",
                0x7F, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F, 0x03, 0x01, 0x01, 0xFF);
        }
        private void ToXmlCore(
            EmberReader reader, XmlWriter writer, FieldPath <int, EmberId> previousPath, int currentType)
        {
            while (reader.Read())
            {
                var nextType = reader.InnerNumber;

                if (nextType == InnerNumber.EndContainer)
                {
                    writer.WriteEndElement();
                    return;
                }

                var currentPath = Combine(previousPath, new Field <int, EmberId>(currentType, reader.OuterId));
                var fieldName   = this.GetFieldName(currentPath);

                switch (nextType)
                {
                case BerBoolean.InnerNumber:
                    var boolean = reader.ReadContentsAsBoolean();
                    WriteValue(writer, fieldName, BerBoolean.Name, boolean, (w, o) => w.WriteValue(o));
                    break;

                case BerInteger.InnerNumber:
                    var integer = reader.ReadContentsAsInt64();
                    WriteValue(writer, fieldName, BerInteger.Name, integer, (w, o) => w.WriteValue(o));
                    break;

                case BerReal.InnerNumber:
                    WriteValue(
                        writer, fieldName, BerReal.Name, reader.ReadContentsAsDouble(), (w, o) => w.WriteValue(o));
                    break;

                case BerUtf8String.InnerNumber:
                    string str;

                    try
                    {
                        str = XmlConvert.VerifyXmlChars(reader.ReadContentsAsString());
                    }
                    catch (XmlException)
                    {
                        str = "*** CONTAINS INVALID XML CHARACTERS ***";
                    }

                    switch (currentPath.ToString())
                    {
                    case "1073741825.C-1.C-6":
                    case "1073741825.C-1.C-7":
                    case "1073741825.C-1.C-17":
                    case "1073741833.C-1.C-6":
                    case "1073741833.C-1.C-7":
                    case "1073741833.C-1.C-17":
                    case "1073741827.C-1.C-4":
                    case "1073741834.C-1.C-4":
                    case "1073741837.C-1.C-11":
                    case "1073741841.C-1.C-11":
                        str = str.Replace("\n", Environment.NewLine);
                        break;

                    default:
                        // Intentionally do nothing
                        break;
                    }

                    WriteValue(writer, fieldName, BerUtf8String.Name, str, (w, o) => w.WriteValue(o));
                    break;

                case BerOctetstring.InnerNumber:
                    var bytes = reader.ReadContentsAsByteArray();
                    WriteValue(
                        writer, fieldName, BerOctetstring.Name, bytes, (w, o) => w.WriteBinHex(o, 0, o.Length));
                    break;

                case BerRelativeObjectIdentifier.InnerNumber:
                    var intOid = reader.ReadContentsAsInt32Array();
                    var oid    = string.Join(".", intOid.Select(e => e.ToString(InvariantCulture)));
                    WriteValue(writer, fieldName, BerRelativeObjectIdentifier.Name, oid, (w, o) => w.WriteValue(o));
                    break;

                case BerSequence.InnerNumber:
                    WriteStartContainer(writer, fieldName, BerSequence.Name);
                    this.ToXmlCore(reader, writer, currentPath, nextType);
                    break;

                case BerSet.InnerNumber:
                    WriteStartContainer(writer, fieldName, BerSet.Name);
                    this.ToXmlCore(reader, writer, currentPath, nextType);
                    break;

                default:
                    WriteStartContainer(writer, fieldName, this.GetTypeName(nextType));
                    this.ToXmlCore(reader, writer, currentPath, nextType);
                    break;
                }
            }
        }
        public void PerformanceTest()
        {
            byte[] payload;

            using (var memoryStream = new MemoryStream())
            {
                using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
                    typeof(EmberPayloads), "BigPayload.ember"))
                {
                    resourceStream.CopyTo(memoryStream);
                }

                payload = memoryStream.ToArray();
            }

            var stopwatch = new Stopwatch();
            var converter = new EmberConverter(GlowTypes.Instance);
            GC.Collect();
            GC.WaitForPendingFinalizers();

            for (int index = 0; index < 100; ++index)
            {
                using (var writer = XmlWriter.Create(TextWriter.Null))
                {
                    stopwatch.Start();

                    using (var stream = new MemoryStream(payload))
                    using (var reader = new EmberReader(stream))
                    {
                        converter.ToXml(reader, writer);
                    }

                    stopwatch.Stop();
                }
            }

            stopwatch.Start();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            stopwatch.Stop();

            Console.WriteLine(stopwatch.ElapsedMilliseconds);
        }