internal int?ParseRecord(SerialObject parentObject) { int?serialObjectReferenceID = null; if (PendingNullCounter == 0) { long startPosition = reader.BaseStream.Position; SerialObject si = null; RecordTypeEnumeration nextRecordType = (RecordTypeEnumeration)reader.ReadByte(); switch (nextRecordType) { case RecordTypeEnumeration.SerializedStreamHeader: //header is 4 values that I wouldn't know what to do with (what type of message, what version, etc) - trash. reader.ReadBytes(16); break; case RecordTypeEnumeration.ClassWithID: //just two ints, read directly si = new ClassInfo(); si.ObjectID = reader.ReadInt32(); ((ClassInfo)si).ReferencedObject = reader.ReadInt32(); //Use the referenced object definition for data retrieval rules // -> this will overwrite the original values in the referenced object, but who cares - the values are trash anyway (for now). ((ClassInfo)serialObjects[((ClassInfo)si).ReferencedObject.Value]).ReadValueInfo(this); break; case RecordTypeEnumeration.SystemClassWithMembers: //single structure, read in constructor si = new ClassInfo(this); //also values. si.ReadValueInfo(this); break; case RecordTypeEnumeration.ClassWithMembers: //single structure, read in constructor si = new ClassInfo(this); //also library ID, read into place. ((ClassInfo)si).LibraryID = reader.ReadInt32(); //also values. si.ReadValueInfo(this); break; case RecordTypeEnumeration.SystemClassWithMembersAndTypes: //single structure, read in constructor si = new ClassInfo(this); //also member type info, read into place. ((ClassInfo)si).ReadTypeInfo(this); //also values. si.ReadValueInfo(this); break; case RecordTypeEnumeration.ClassWithMembersAndTypes: //single structure, read in constructor si = new ClassInfo(this); //also member type info, read into place. ((ClassInfo)si).ReadTypeInfo(this); //also library ID, read into place. ((ClassInfo)si).LibraryID = reader.ReadInt32(); //also values. si.ReadValueInfo(this); break; case RecordTypeEnumeration.BinaryObjectString: //simple structure, just an ID and a string si = new ObjectString(); si.ObjectID = reader.ReadInt32(); ((ObjectString)si).String = reader.ReadString(); break; case RecordTypeEnumeration.BinaryArray: //complex process, read in constructor. si = new BinaryArray(this); //also values. si.ReadValueInfo(this); break; case RecordTypeEnumeration.MemberReference: //just return the ID that was referenced. serialObjectReferenceID = reader.ReadInt32(); break; case RecordTypeEnumeration.ObjectNull: //a single null; do nothing, as null is the default return value. break; case RecordTypeEnumeration.MessageEnd: //do nothing, quit. Wasn't that fun? endRecordReached = true; break; case RecordTypeEnumeration.BinaryLibrary: int newLibraryID = reader.ReadInt32(); libraries.Add(newLibraryID, new BinaryLibrary()); libraries[newLibraryID].LibraryID = newLibraryID; libraries[newLibraryID].Name = reader.ReadString(); libraries[newLibraryID].recordLength = reader.BaseStream.Position - startPosition; break; case RecordTypeEnumeration.ObjectNullMultiple256: //a sequence of nulls; return null, and start a counter to continue returning N nulls over the next calls. PendingNullCounter = reader.ReadByte() - 1; break; case RecordTypeEnumeration.ObjectNullMultiple: //a sequence of nulls; return null, and start a counter to continue returning N nulls over the next calls. PendingNullCounter = reader.ReadInt32() - 1; #if (DEBUG) //not yet tested: if it happens, take a look around. System.Diagnostics.Debugger.Break(); #endif break; case RecordTypeEnumeration.ArraySinglePrimitive: //This one's pretty easy to build, do locally. si = new BinaryArray(); si.ObjectID = reader.ReadInt32(); ((BinaryArray)si).ArrayType = BinaryArrayTypeEnumeration.Single; ((BinaryArray)si).BinaryType = BinaryTypeEnumeration.Primitive; ((BinaryArray)si).Rank = 1; ((BinaryArray)si).Lengths = new List <int>(); ((BinaryArray)si).Lengths.Add(reader.ReadInt32()); ((BinaryArray)si).PrimitiveType = (PrimitiveTypeEnumeration)reader.ReadByte(); //and then read the values. si.ReadValueInfo(this); break; case RecordTypeEnumeration.ArraySingleObject: //This should be pretty easy to build, do locally. si = new BinaryArray(); si.ObjectID = reader.ReadInt32(); ((BinaryArray)si).ArrayType = BinaryArrayTypeEnumeration.Single; ((BinaryArray)si).BinaryType = BinaryTypeEnumeration.Object; ((BinaryArray)si).Rank = 1; ((BinaryArray)si).Lengths = new List <int>(); ((BinaryArray)si).Lengths.Add(reader.ReadInt32()); //and then read the values. si.ReadValueInfo(this); #if (DEBUG) //not yet tested: if it happens, take a look around. System.Diagnostics.Debugger.Break(); #endif break; case RecordTypeEnumeration.ArraySingleString: //This should be pretty easy to build, do locally. si = new BinaryArray(); si.ObjectID = reader.ReadInt32(); ((BinaryArray)si).ArrayType = BinaryArrayTypeEnumeration.Single; ((BinaryArray)si).BinaryType = BinaryTypeEnumeration.String; ((BinaryArray)si).Rank = 1; ((BinaryArray)si).Lengths = new List <int>(); ((BinaryArray)si).Lengths.Add(reader.ReadInt32()); //and then read the values. si.ReadValueInfo(this); #if (DEBUG) //not yet tested: if it happens, take a look around. System.Diagnostics.Debugger.Break(); #endif break; case RecordTypeEnumeration.MemberPrimitiveTyped: #if (DEBUG) //not yet tested: if it happens, take a look around. System.Diagnostics.Debugger.Break(); #endif break; case RecordTypeEnumeration.MethodCall: #if (DEBUG) //not yet tested: if it happens, take a look around. System.Diagnostics.Debugger.Break(); #endif break; case RecordTypeEnumeration.MethodReturn: #if (DEBUG) //not yet tested: if it happens, take a look around. System.Diagnostics.Debugger.Break(); #endif break; default: throw new Exception("Parsing appears to have failed dramatically. Unknown record type, we must be lost in the bytestream!"); } //standard: if this was a serial object, add to list and record its length. if (si != null) { serialObjects.Add(si.ObjectID, si); serialObjects[si.ObjectID].recordLength = reader.BaseStream.Position - startPosition; if (parentObject != null) { serialObjects[si.ObjectID].ParentObjectID = parentObject.ObjectID; } return(si.ObjectID); } } else { PendingNullCounter--; } return(serialObjectReferenceID); }
public string Analyze() { int classCount = 0; int arrayCount = 0; int stringCount = 0; long classLength = 0; long arrayLength = 0; long stringLength = 0; Dictionary <string, int> ObjectCounts = new Dictionary <string, int>(); Dictionary <string, long> ObjectLengths = new Dictionary <string, long>(); //we are only interested in top-level objects, not nested ones (otherwise would double-count lengths!). foreach (SerialObject someObject in serialObjects.Values) { if (someObject.ParentObjectID == null) { if (someObject.GetType() == typeof(ClassInfo)) { classCount++; classLength += someObject.recordLength; ClassInfo interestingClass = (ClassInfo)someObject; if (interestingClass.ReferencedObject != null) { interestingClass = (ClassInfo)serialObjects[interestingClass.ReferencedObject.Value]; } if (!ObjectCounts.ContainsKey(interestingClass.Name)) { ObjectCounts.Add(interestingClass.Name, 0); ObjectLengths.Add(interestingClass.Name, 0); } ObjectCounts[interestingClass.Name]++; ObjectLengths[interestingClass.Name] += someObject.recordLength; } else if (someObject.GetType() == typeof(BinaryArray)) { arrayCount++; arrayLength += someObject.recordLength; } else if (someObject.GetType() == typeof(ObjectString)) { stringCount++; stringLength += someObject.recordLength; } } } StringBuilder sb = new StringBuilder(); sb.AppendLine(string.Format("Total Objects: {0}", serialObjects.Count)); sb.AppendLine(string.Format("Total Top-Level Objects: {0}", classCount + arrayCount + stringCount)); sb.AppendLine(string.Format("Total Top-Level Length: {0}", classLength + arrayLength + stringLength)); sb.AppendLine(); sb.AppendLine(string.Format("Top-Level Class Count: {0}", classCount)); sb.AppendLine(string.Format("Top-Level Class Length: {0}", classLength)); sb.AppendLine(); sb.AppendLine(string.Format("Top-Level Array Count: {0}", arrayCount)); sb.AppendLine(string.Format("Top-Level Array Length: {0}", arrayLength)); sb.AppendLine(); sb.AppendLine(string.Format("Top-Level String Count: {0}", stringCount)); sb.AppendLine(string.Format("Top-Level String Length: {0}", stringLength)); sb.AppendLine(); sb.AppendLine("Top-Level Object Counts by Name:"); foreach (string ClassName in ObjectCounts.Keys) { sb.AppendLine(string.Format("{0}: {1}", ClassName, ObjectCounts[ClassName])); } sb.AppendLine(); sb.AppendLine("Top-Level Object Lengths by Name:"); foreach (string ClassName in ObjectLengths.Keys) { sb.AppendLine(string.Format("{0}: {1}", ClassName, ObjectLengths[ClassName])); } return(sb.ToString()); }