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));
        }
Example #3
0
        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());
            }
        }
Example #4
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>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());
            }
        }
Example #19
0
        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;
            }
        }
Example #21
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));
        }
Example #23
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));
                }
        }
        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);
        }
Example #25
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());
                }
        }
        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();