void ParseItem(object obj, string objName, HashSet <object> seenObjects) { if (obj == null) { return; } Type type = obj.GetType(); if (type.IsPointer) { return; // again, a pointer cast to whatever the fieldtype is, shoo. } if (type == typeof(string)) { // string needs special handling int strSize = 3 * IntPtr.Size + 2; strSize += ((string)(obj)).Length * sizeof(char); int pad = strSize % IntPtr.Size; if (pad != 0) { strSize += IntPtr.Size - pad; } Size += strSize; return; } // obj is not null, and a primitive/enum/array/struct/class TypeData fieldTypeData = TypeData.Get(type); if (type.IsClass || type.IsArray || fieldTypeData.DynamicSizedFields != null) { // class, array, or struct with pointers if (!(type.IsPrimitive || type.IsValueType || type.IsEnum)) { if (!seenObjects.Add(obj)) { return; } } StructOrClass child = new StructOrClass(objName, obj, fieldTypeData, seenObjects); Size += child.Size; Children.Add(child); return; } else { // primitive, enum, or a struct without pointers, embed it in parent Size += fieldTypeData.Size; } }
/// <summary> /// Parse field objects; only called for arrays, references and structs with references in them /// </summary> StructOrClass(string name, object root, TypeData rootTypeData, HashSet <object> seenObjects) { Identifier = name; ParsedType = root.GetType(); Size = rootTypeData.Size; if (ParsedType.IsArray) { int i = 0; ArraySize = GetTotalLength((Array)root); Type elementType = ParsedType.GetElementType(); TypeData elementTypeData = TypeData.Get(elementType); if (elementType.IsValueType || elementType.IsPrimitive || elementType.IsEnum) { if (elementTypeData.DynamicSizedFields == null) { Size += elementTypeData.Size * ArraySize; return; } foreach (var item in (Array)root) { StructOrClass child = new StructOrClass((i++).ToString(), item, elementTypeData, seenObjects); Size += child.Size; Children.Add(child); } } else { Size += IntPtr.Size * ArraySize; foreach (var item in (Array)root) { ParseItem(item, (i++).ToString(), seenObjects); } } } else { if (rootTypeData.DynamicSizedFields != null) { foreach (var fieldInfo in rootTypeData.DynamicSizedFields) { ParseField(fieldInfo, root, seenObjects); } } } }