/////////////////////////////////////////////////////////////////////// private int WriteChild(BinaryWriter bw, CType child) { int len = 0; // name is agnostic var namestr = new StringStore(); namestr.Value = child.Name; namestr.Write(bw); len += namestr.WriteSize; switch (child.CoreType) { case CInternalType.Undefined: throw new Exception("All wrong."); case CInternalType.Empty: bw.Write((byte)Types.Empty); len += sizeof(byte); break; case CInternalType.String: bw.Write((byte)Types.String); len += sizeof(byte); var s_val = new StringStore(); s_val.Value = (child as CTypeString).SValue; s_val.Write(bw); len += s_val.WriteSize; break; case CInternalType.Number: bw.Write((byte)Types.Number); len += sizeof(byte); if ((child as CTypeNumber).HasValue) { var n_val = new NumberStore(); n_val.Value = (child as CTypeNumber).IValue; n_val.Write(bw); len += sizeof(int); } break; case CInternalType.StringList: bw.Write((byte)Types.StringList); len += sizeof(byte); foreach (string str in (child as CTypeStringList).SValues) { var stmp_val = new StringStore(); stmp_val.Value = str; stmp_val.Write(bw); len += stmp_val.WriteSize; } break; case CInternalType.Enum: bw.Write((byte)Types.Enum); len += sizeof(byte); var e_string = new StringStore(); e_string.Value = (child as CTypeEnum).SValue; e_string.Write(bw); len += e_string.WriteSize; var e_number = new NumberStore(); e_number.Value = (child as CTypeEnum).IValue; e_number.Write(bw); len += sizeof(int); break; case CInternalType.List: bw.Write((byte)Types.List); len += sizeof(byte); // nastier. var child_node = child as CTypeChild; int count = child_node.Children.Count; bw.Write((byte)(count & 0xFF)); len += sizeof(byte); if (count > 0) { if (count > 1) { int hdr_offset = (int)bw.BaseStream.Length; // we need to revisit this.. int real_count = count - 1; for (int i = 0; i < real_count; ++i) { bw.Write((int)0xF0F0F0F); } len += real_count * sizeof(int); var child_lengths = new List <int>(); // this is no longer the 'real count' for (int i = 0; i < real_count; ++i) { int child_length = WriteChild(bw, child_node.Children[i]); child_lengths.Add(child_length); len += child_length; } // revist all data length int tail_offset = (int)bw.BaseStream.Length; bw.Seek(hdr_offset, SeekOrigin.Begin); int sum = 0; foreach (int cl in child_lengths) { sum += cl; bw.Write(sum); } bw.Seek(tail_offset, SeekOrigin.Begin); } len += WriteChild(bw, child_node.Children.Last()); } break; } // type agnostic foreach (int tail in child.Tail) { bw.Write(tail); len += 4; } return(len); }
/////////////////////////////////////////////////////////////////////// int ScanChild(BinaryReader br, int max_len, ref CTypeChild root) { int cur_len = 0; string name; using (StringStore tmp = new StringStore().Read(br)) { name = tmp.Value; cur_len += tmp.ReadSize; } CType last_node = new CType(); if (cur_len < max_len) { Types type = (Types)br.ReadByte(); cur_len += 1; switch (type) { case Types.Empty: { CTypeEmpty me = new CTypeEmpty(name); last_node = me; break; } case Types.Enum: { string val; using (StringStore tmp = new StringStore().Read(br)) { val = tmp.Value; cur_len += tmp.ReadSize; } int ival; using (NumberStore tmp = new NumberStore().Read(br)) { ival = tmp.Value; cur_len += sizeof(int); } CTypeEnum me = new CTypeEnum(name); me.SValue = val; me.IValue = ival; last_node = me; break; } case Types.String: { string val; using (StringStore tmp = new StringStore().Read(br)) { val = tmp.Value; cur_len += tmp.ReadSize; } CTypeString me = new CTypeString(name); me.SValue = val; last_node = me; break; } case Types.Number: { CTypeNumber me = new CTypeNumber(name); // required. some number nodes end before they have any data. yup. if (cur_len != max_len) { int ival; using (NumberStore tmp = new NumberStore().Read(br)) { ival = tmp.Value; cur_len += sizeof(int); } me.HasValue = true; me.IValue = ival; } last_node = me; break; } case Types.StringList: { CTypeStringList me = new CTypeStringList(name); string val; using (StringStore tmp = new StringStore().Read(br)) { val = tmp.Value; me.SValues.Add(val); cur_len += tmp.ReadSize; } using (StringStore tmp = new StringStore().Read(br)) { val = tmp.Value; me.SValues.Add(val); cur_len += tmp.ReadSize; } // are there any more? last_node = me; break; } case Types.List: { byte Count = br.ReadByte(); cur_len += sizeof(byte); CTypeChild me = new CTypeChild(name); if (Count > 0) { // multiple child nodes have a list of lengths if (Count > 1) { int real_count = Count - 1; var items = new List <int>(); for (int i = 0; i < real_count; ++i) { items.Add(br.ReadInt32()); } cur_len += real_count * sizeof(int); int last = 0; for (int i = 0; i < real_count; ++i) { int child_len = ScanChild(br, items[i] - last, ref me); cur_len += child_len; last = items[i]; } } int ret_len = ScanChild(br, max_len - cur_len, ref me); cur_len += ret_len; } last_node = me; break; } default: { throw new Exception("Unknown node type. Please report this file"); } } } // oh, there is also random tail data // we store this as 'tail' data, but in xml this is 'metadata' int tail_length = max_len - cur_len; if (tail_length != 0) { if ((tail_length & 3) != 0) { throw new Exception("Unexpected tail"); } int tail_count = tail_length / sizeof(int); for (int i = 0; i < tail_count; ++i) { int ival = br.ReadInt32(); // swap the endian if (runtimeOptions.ExportForConsole) { EndianHelper.Swap(ref ival); } last_node.Tail.Add(ival); } cur_len = max_len; } root.Children.Add(last_node); return(cur_len); }