Example #1
0
            /// <summary>
            /// Examines the specified type and calculates necessary information
            /// about the layout of the structure.
            /// </summary>
            private static void LoadData()
            {
                data = new List <SortedFieldInfo>();

                Type sortingType = typeof(T);

                // insert sort
                foreach (FieldInfo fi in sortingType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    SortedFieldInfo info = new SortedFieldInfo();
                    info.field  = fi;
                    info.offset = OffsetOf(fi);

                    int insertIndex = data.Count;
                    while (insertIndex > 0 && info.offset <= data[insertIndex - 1].offset)
                    {
                        insertIndex--;
                    }
                    data.Insert(insertIndex, info);
                }

                // Adjust reference type size to zero (arrays, lists, strings)
                int omittedBytes = 0;

                for (int i = 0; i < data.Count; i++)
                {
                    SortedFieldInfo dat            = data[i];
                    int             originalOffset = dat.offset;
                    dat.offset -= omittedBytes;
                    data[i]     = dat;

                    Type type = dat.field.FieldType;
                    if (typeof(IHandle).IsAssignableFrom(type))   // Handle
                    // Handle is 4 bytes
                    {
                        omittedBytes += (Marshal.SizeOf(type) - 4);
                    }
                    else if (type.IsSubclassOf(typeof(ValueType)) && !type.IsSubclassOf(typeof(System.Enum)) && !type.IsPrimitive)
                    {
                        // Struct could have any # of omitted bytes
                        omittedBytes += getOmittedBytesFor_Dynamic(dat.field.FieldType);
                    }
                    else if (!data[i].field.FieldType.IsValueType)
                    {
                        // Ref is 4 bytes
                        if (i < data.Count - 1)
                        {
                            // just in case of alignment issues
                            omittedBytes += data[i + 1].offset - originalOffset;
                        }
                        else
                        {
                            omittedBytes += 4;
                        }
                    }
                }
                compactSize = Marshal.SizeOf(typeof(T)) - omittedBytes;
                SortedFieldData <T> .omittedBytes = omittedBytes;
            }
Example #2
0
        /// <summary>
        /// Creates a byte array contianing a structure with array references expanded to their contents. See remarks.
        /// </summary>
        /// <param name="t">The type of the structure.</param>
        /// <returns>The binary data of the structure.</returns>
        /// <remarks>
        /// <para>Valid Types: The specified object must be a structure. The only valid reference types
        /// (including contents of arrays and their subfields, recursively)
        /// are strings, string builders, arrays and generic IList objects. ILists and
        /// StringBuilders will be treated as arrays and strings, respectively.</para>
        ///
        /// <para>Encoding: Strings will be written as ASNI strings unless
        /// the field name ends with an encoding specifier (_UTF, _UTF7, _UTF8, _UTF32). Chars will
        /// always be ANSI. Store chars in a 1-char string field to specify encoding. Arrays of
        /// strings will always be ANSI. Concatenate string arrays into a single-string composite
        /// field to specify encoding).</para>
        ///
        /// Strings and arrays
        /// will not be prefixed with their length. Invalid objects may be silently omitted.
        /// IHandle objects will be treated as IntPtrs.</remarks>
        public static Byte[] ExpandArraysInStruct <T>(T obj, out int insertedByteCount) where T : struct
        {
            Type type = typeof(T);
            IList <SortedFieldInfo> fields       = SortedFieldData <T> .Data;
            MemoryStream            result       = new MemoryStream(1);
            BinaryWriter            resultWriter = new BinaryWriter(result);
            int offsetAdjustment = 0;

            for (int i = 0; i < fields.Count; i++)
            {
                // Get data
                SortedFieldInfo field        = fields[i];
                int             targetOffset = field.offset + offsetAdjustment;
                object          value        = fields[i].field.GetValue(obj);

                // Seek to output offset
                while (result.Capacity < targetOffset)
                {
                    result.Capacity *= 2;
                }
                result.Seek(targetOffset, SeekOrigin.Begin);

                // Write
                if (value is StringBuilder)
                {
                    value = value.ToString();
                }
                if (value is System.Enum)
                {
                    value = GetEnumValue(value);
                }

                if (canWriteDirect(value))
                {
                    outputField(resultWriter, value);
                }
                else if (fields[i].field.FieldType.IsArray)
                {
                    offsetAdjustment += outputList(resultWriter, fields[i].field.FieldType.GetElementType(), (System.Collections.IList)value);
                }
                else if (value is string || value is StringBuilder)
                {
                    if (field.field.Name.EndsWith("_UTF"))
                    {
                        offsetAdjustment += WriteStringUTF(resultWriter, value);
                    }
                    else if (field.field.Name.EndsWith("_UTF7"))
                    {
                        offsetAdjustment += WriteStringUTF7(resultWriter, value);
                    }
                    else if (field.field.Name.EndsWith("_UTF8"))
                    {
                        offsetAdjustment += WriteStringUTF8(resultWriter, value);
                    }
                    else if (field.field.Name.EndsWith("_UTF32"))
                    {
                        offsetAdjustment += WriteStringUTF32(resultWriter, value);
                    }
                    else
                    {
                        offsetAdjustment += WriteString(resultWriter, value);
                    }
                }
                else if (objectImplementsGenerigIList(value))
                {
                    offsetAdjustment += outputList(resultWriter, value.GetType().GetGenericArguments()[0], (System.Collections.IList)value);
                }
                else if (value is ValueType)
                {
                    int    extraBytes;
                    byte[] structData = ExpandArraysInStruct_Dynamic(value, out extraBytes);
                    result.Write(structData, 0, structData.Length);
                    offsetAdjustment += extraBytes;
                }
            }

            insertedByteCount = offsetAdjustment;
            result.Capacity   = (int)result.Length;
            return(result.GetBuffer());
        }