///////////////////////////////////////////////////////////////////////
        #region Public Methods

        /// <summary>
        /// Reads a value of the specified type from the buffer.
        /// </summary>
        /// <param name="buffer">The buffer containing binary data to read.</param>
        /// <param name="dictionary">The type dictionary that contains a complex type identified with the type name.</param>
        /// <param name="typeName">The name of the type that describes the data.</param>
        /// <returns>A structured represenation of the data in the buffer.</returns>
        public TsCCpxComplexValue Read(byte[] buffer, TypeDictionary dictionary, string typeName)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (dictionary == null)
            {
                throw new ArgumentNullException("dictionary");
            }
            if (typeName == null)
            {
                throw new ArgumentNullException("typeName");
            }

            TsCCpxContext context = InitializeContext(buffer, dictionary, typeName);

            TsCCpxComplexValue complexValue = null;

            int bytesRead = ReadType(context, out complexValue);

            if (bytesRead == 0)
            {
                throw new TsCCpxInvalidSchemaException(String.Format("Type '{0}' not found in dictionary.", typeName));
            }

            return(complexValue);
        }
        /// <summary>
        /// Reads a complex type from the buffer.
        /// </summary>
        private int ReadField(TsCCpxContext context, TypeReference field, out object fieldValue)
        {
            fieldValue = null;

            foreach (TypeDescription type in context.Dictionary.TypeDescription)
            {
                if (type.TypeID == field.TypeID)
                {
                    context.Type = type;

                    if (type.DefaultBigEndianSpecified)
                    {
                        context.BigEndian = type.DefaultBigEndian;
                    }
                    if (type.DefaultCharWidthSpecified)
                    {
                        context.CharWidth = type.DefaultCharWidth;
                    }
                    if (type.DefaultStringEncoding != null)
                    {
                        context.StringEncoding = type.DefaultStringEncoding;
                    }
                    if (type.DefaultFloatFormat != null)
                    {
                        context.FloatFormat = type.DefaultFloatFormat;
                    }

                    break;
                }
            }

            if (context.Type == null)
            {
                throw new TsCCpxInvalidSchemaException(String.Format("Reference type '{0}' not found.", field.TypeID));
            }

            TsCCpxComplexValue complexValue = null;

            int bytesRead = ReadType(context, out complexValue);

            if (bytesRead == 0)
            {
                fieldValue = null;
            }
            else
            {
                fieldValue = complexValue;
            }
            return(bytesRead);
        }
Example #3
0
        /// <summary>
        /// Finds the integer value referenced by the field name.
        /// </summary>
        private void WriteReference(
            TsCCpxContext context,
            FieldType field,
            int fieldIndex,
            TsCCpxComplexValue[] fieldValues,
            string fieldName,
            int count
            )
        {
            TsCCpxComplexValue namedValue = null;

            if (fieldName.Length == 0)
            {
                if (fieldIndex > 0 && fieldIndex - 1 < fieldValues.Length)
                {
                    namedValue = (TsCCpxComplexValue)fieldValues[fieldIndex - 1];
                }
            }
            else
            {
                for (int ii = 0; ii < fieldIndex; ii++)
                {
                    namedValue = (TsCCpxComplexValue)fieldValues[ii];

                    if (namedValue.Name == fieldName)
                    {
                        break;
                    }

                    namedValue = null;
                }
            }

            if (namedValue == null)
            {
                throw new TsCCpxInvalidSchemaException(String.Format("Referenced field not found ({0}).", fieldName));
            }

            if (context.Buffer == null)
            {
                namedValue.Value = count;
            }

            if (!count.Equals(namedValue.Value))
            {
                throw new TsCCpxInvalidDataToWriteException("Reference field value and the actual array length are not equal.");
            }
        }
        /// <summary>
        /// Finds the integer value referenced by the field name.
        /// </summary>
        private int ReadReference(
            TsCCpxContext context,
            FieldType field,
            int fieldIndex,
            ArrayList fieldValues,
            string fieldName
            )
        {
            TsCCpxComplexValue complexValue = null;

            if (fieldName.Length == 0)
            {
                if (fieldIndex > 0 && fieldIndex - 1 < fieldValues.Count)
                {
                    complexValue = (TsCCpxComplexValue)fieldValues[fieldIndex - 1];
                }
            }
            else
            {
                for (int ii = 0; ii < fieldIndex; ii++)
                {
                    complexValue = (TsCCpxComplexValue)fieldValues[ii];

                    if (complexValue.Name == fieldName)
                    {
                        break;
                    }

                    complexValue = null;
                }
            }

            if (complexValue == null)
            {
                throw new TsCCpxInvalidSchemaException(String.Format("Referenced field not found ({0}).", fieldName));
            }

            return(System.Convert.ToInt32(complexValue.Value));
        }
Example #5
0
        ///////////////////////////////////////////////////////////////////////
        #region Public Methods

        /// <summary>
        /// Writes a complex value to a buffer.
        /// </summary>
        /// <param name="namedValue">The structured value to write to the buffer.</param>
        /// <param name="dictionary">The type dictionary that contains a complex type identified with the type name.</param>
        /// <param name="typeName">The name of the type that describes the data.</param>
        /// <returns>A buffer containing the binary form of the complex type.</returns>
        public byte[] Write(TsCCpxComplexValue namedValue, TypeDictionary dictionary, string typeName)
        {
            if (namedValue == null)
            {
                throw new ArgumentNullException(nameof(namedValue));
            }
            if (dictionary == null)
            {
                throw new ArgumentNullException(nameof(dictionary));
            }
            if (typeName == null)
            {
                throw new ArgumentNullException(nameof(typeName));
            }

            TsCCpxContext context = InitializeContext(null, dictionary, typeName);

            // determine the size of buffer required.
            int bytesRequired = WriteType(context, namedValue);

            if (bytesRequired == 0)
            {
                throw new TsCCpxInvalidDataToWriteException("Could not write value into buffer.");
            }

            // allocate buffer.
            context.Buffer = new byte[bytesRequired];

            // write data into buffer.
            int bytesWritten = WriteType(context, namedValue);

            if (bytesWritten != bytesRequired)
            {
                throw new TsCCpxInvalidDataToWriteException("Could not write value into buffer.");
            }

            return(context.Buffer);
        }
        ///////////////////////////////////////////////////////////////////////
        #region Private Methods

        /// <summary>
        /// Reads an instance of a type from the buffer,
        /// </summary>
        private int ReadType(TsCCpxContext context, out TsCCpxComplexValue complexValue)
        {
            complexValue = null;

            TypeDescription type       = context.Type;
            int             startIndex = context.Index;

            byte bitOffset = 0;

            ArrayList fieldValues = new ArrayList();

            for (int ii = 0; ii < type.Field.Length; ii++)
            {
                FieldType field = type.Field[ii];

                TsCCpxComplexValue fieldValue = new TsCCpxComplexValue {
                    Name = (field.Name != null && field.Name.Length != 0) ? field.Name : String.Format("[{0}]", ii), Type = null, Value = null
                };

                // check if additional padding is required after the end of a bit field.
                if (bitOffset != 0)
                {
                    if (field.GetType() != typeof(BitString))
                    {
                        context.Index++;
                        bitOffset = 0;
                    }
                }

                int bytesRead = 0;

                if (IsArrayField(field))
                {
                    bytesRead = ReadArrayField(context, field, ii, fieldValues, out fieldValue.Value);
                }
                else if (field.GetType() == typeof(TypeReference))
                {
                    object typeValue = null;

                    bytesRead = ReadField(context, (TypeReference)field, out typeValue);

                    // assign a name appropriate for the current context.
                    fieldValue.Name  = field.Name;
                    fieldValue.Type  = ((TsCCpxComplexValue)typeValue).Type;
                    fieldValue.Value = ((TsCCpxComplexValue)typeValue).Value;
                }
                else
                {
                    bytesRead = ReadField(context, field, ii, fieldValues, out fieldValue.Value, ref bitOffset);
                }

                if (bytesRead == 0 && bitOffset == 0)
                {
                    throw new TsCCpxInvalidDataInBufferException(String.Format("Could not read field '{0}' in type '{1}'.", field.Name, type.TypeID));
                }

                context.Index += bytesRead;

                // assign a value for field type.
                if (fieldValue.Type == null)
                {
                    fieldValue.Type = Technosoftware.DaAeHdaClient.OpcConvert.ToString(fieldValue.Value.GetType());
                }

                fieldValues.Add(fieldValue);
            }

            // skip padding bits at the end of a type.
            if (bitOffset != 0)
            {
                context.Index++;
            }

            complexValue = new TsCCpxComplexValue();

            complexValue.Name  = type.TypeID;
            complexValue.Type  = type.TypeID;
            complexValue.Value = (TsCCpxComplexValue[])fieldValues.ToArray(typeof(TsCCpxComplexValue));

            return(context.Index - startIndex);
        }
Example #7
0
        ///////////////////////////////////////////////////////////////////////
        #region Private Methods

        /// <summary>
        /// Writes an instance of a type to the buffer.
        /// </summary>
        private int WriteType(TsCCpxContext context, TsCCpxComplexValue namedValue)
        {
            TypeDescription type       = context.Type;
            int             startIndex = context.Index;

            TsCCpxComplexValue[] fieldValues = null;

            if (namedValue.Value == null || namedValue.Value.GetType() != typeof(TsCCpxComplexValue[]))
            {
                throw new TsCCpxInvalidDataToWriteException("Type instance does not contain field values.");
            }

            fieldValues = (TsCCpxComplexValue[])namedValue.Value;

            if (fieldValues.Length != type.Field.Length)
            {
                throw new TsCCpxInvalidDataToWriteException("Type instance does not contain the correct number of fields.");
            }

            byte bitOffset = 0;

            for (int ii = 0; ii < type.Field.Length; ii++)
            {
                FieldType          field      = type.Field[ii];
                TsCCpxComplexValue fieldValue = fieldValues[ii];

                if (bitOffset != 0)
                {
                    if (field.GetType() != typeof(BitString))
                    {
                        context.Index++;
                        bitOffset = 0;
                    }
                }

                int bytesWritten = 0;

                if (IsArrayField(field))
                {
                    bytesWritten = WriteArrayField(context, field, ii, fieldValues, fieldValue.Value);
                }
                else if (field.GetType() == typeof(TypeReference))
                {
                    bytesWritten = WriteField(context, (TypeReference)field, fieldValue);
                }
                else
                {
                    bytesWritten = WriteField(context, field, ii, fieldValues, fieldValue.Value, ref bitOffset);
                }

                if (bytesWritten == 0 && bitOffset == 0)
                {
                    throw new TsCCpxInvalidDataToWriteException(String.Format("Could not write field '{0}' in type '{1}'.", field.Name, type.TypeID));
                }

                context.Index += bytesWritten;
            }

            if (bitOffset != 0)
            {
                context.Index++;
            }

            return(context.Index - startIndex);
        }