/// <summary>
        /// Reads a char string value from the buffer.
        /// </summary>
        private int ReadField(
            TsCCpxContext context,
            CharString field,
            int fieldIndex,
            ArrayList fieldValues,
            out object fieldValue
            )
        {
            fieldValue = null;

            byte[] buffer = context.Buffer;

            // initialize serialization parameters.
            int charWidth = (field.CharWidthSpecified) ? (int)field.CharWidth : (int)context.CharWidth;
            int charCount = (field.LengthSpecified) ? (int)field.Length : -1;

            // apply defaults for built in types.
            if (field.GetType() == typeof(Ascii))
            {
                charWidth = 1;
            }
            else if (field.GetType() == typeof(Unicode))
            {
                charWidth = 2;
            }

            if (field.CharCountRef != null)
            {
                charCount = ReadReference(context, field, fieldIndex, fieldValues, field.CharCountRef);
            }

            // find null terminator
            if (charCount == -1)
            {
                charCount = 0;

                for (int ii = context.Index; ii < context.Buffer.Length - charWidth + 1; ii += charWidth)
                {
                    charCount++;

                    bool isNull = true;

                    for (int jj = 0; jj < charWidth; jj++)
                    {
                        if (context.Buffer[ii + jj] != 0)
                        {
                            isNull = false;
                            break;
                        }
                    }

                    if (isNull)
                    {
                        break;
                    }
                }
            }

            // check if there is enough data left.
            if (buffer.Length - context.Index < charWidth * charCount)
            {
                throw new TsCCpxInvalidDataInBufferException("Unexpected end of buffer.");
            }

            if (charWidth > 2)
            {
                // copy bytes.
                byte[] bytes = new byte[charCount * charWidth];

                for (int ii = 0; ii < charCount * charWidth; ii++)
                {
                    bytes[ii] = buffer[context.Index + ii];
                }

                // swap bytes.
                if (context.BigEndian)
                {
                    for (int ii = 0; ii < bytes.Length; ii += charWidth)
                    {
                        SwapBytes(bytes, 0, charWidth);
                    }
                }

                fieldValue = bytes;
            }
            else
            {
                // copy characters.
                char[] chars = new char[charCount];

                for (int ii = 0; ii < charCount; ii++)
                {
                    if (charWidth == 1)
                    {
                        chars[ii] = System.Convert.ToChar(buffer[context.Index + ii]);
                    }
                    else
                    {
                        byte[] charBytes = new byte[]
                        {
                            buffer[context.Index + 2 * ii],
                            buffer[context.Index + 2 * ii + 1]
                        };

                        if (context.BigEndian)
                        {
                            SwapBytes(charBytes, 0, 2);
                        }

                        chars[ii] = BitConverter.ToChar(charBytes, 0);
                    }
                }

                fieldValue = new string(chars).TrimEnd(new char[] { '\0' });
            }

            return(charCount * charWidth);
        }
Esempio n. 2
0
        /// <summary>
        /// Writes a char string value to the buffer.
        /// </summary>
        private int WriteField(
            TsCCpxContext context,
            CharString field,
            int fieldIndex,
            TsCCpxComplexValue[] fieldValues,
            object fieldValue
            )
        {
            byte[] buffer = context.Buffer;

            // initialize serialization parameters.
            int charWidth = (field.CharWidthSpecified) ? (int)field.CharWidth : (int)context.CharWidth;
            int charCount = (field.LengthSpecified) ? (int)field.Length : -1;

            // apply defaults for built in types.
            if (field.GetType() == typeof(Ascii))
            {
                charWidth = 1;
            }
            else if (field.GetType() == typeof(Unicode))
            {
                charWidth = 2;
            }

            byte[] bytes = null;

            if (charCount == -1)
            {
                // extra wide characters stored as byte arrays
                if (charWidth > 2)
                {
                    if (fieldValue.GetType() != typeof(byte[]))
                    {
                        throw new TsCCpxInvalidDataToWriteException("Field value is not a byte array.");
                    }

                    bytes     = (byte[])fieldValue;
                    charCount = bytes.Length / charWidth;
                }

                // convert string to byte array.
                else
                {
                    if (fieldValue.GetType() != typeof(string))
                    {
                        throw new TsCCpxInvalidDataToWriteException("Field value is not a string.");
                    }

                    string stringValue = (string)fieldValue;

                    charCount = stringValue.Length + 1;

                    // calculate length of ascii string by forcing pure unicode characters to two ascii chars.
                    if (charWidth == 1)
                    {
                        charCount = 1;

                        foreach (char unicodeChar in stringValue)
                        {
                            charCount++;

                            byte[] charBytes = BitConverter.GetBytes(unicodeChar);

                            if (charBytes[1] != 0)
                            {
                                charCount++;
                            }
                        }
                    }
                }
            }

            // update the char count reference.
            if (field.CharCountRef != null)
            {
                WriteReference(context, field, fieldIndex, fieldValues, field.CharCountRef, charCount);
            }

            if (buffer != null)
            {
                // copy string to buffer.
                if (bytes == null)
                {
                    string stringValue = (string)fieldValue;

                    bytes = new byte[charWidth * charCount];

                    int index = 0;

                    for (int ii = 0; ii < stringValue.Length; ii++)
                    {
                        if (index >= bytes.Length)
                        {
                            break;
                        }

                        byte[] charBytes = BitConverter.GetBytes(stringValue[ii]);

                        bytes[index++] = charBytes[0];

                        if (charWidth == 2 || charBytes[1] != 0)
                        {
                            bytes[index++] = charBytes[1];
                        }
                    }
                }

                // check if there is enough data left.
                if (buffer.Length - context.Index < bytes.Length)
                {
                    throw new TsCCpxInvalidDataToWriteException("Unexpected end of buffer.");
                }

                // write bytes to buffer.
                for (int ii = 0; ii < bytes.Length; ii++)
                {
                    buffer[context.Index + ii] = bytes[ii];
                }

                // swap bytes.
                if (context.BigEndian && charWidth > 1)
                {
                    for (int ii = 0; ii < bytes.Length; ii += charWidth)
                    {
                        SwapBytes(buffer, context.Index + ii, charWidth);
                    }
                }
            }

            return(charCount * charWidth);
        }