private GFFObject[] ReadList(long offset) { long pos = file.Position; file.Position = lioffset + offset; //read the size of the list byte[] buffer = new byte[DWORD_SIZE]; file.Read(buffer, 0, buffer.Length); uint count = BitConverter.ToUInt32(buffer, 0); //read the elements of the list (each being 1 uint index into the struct array) buffer = new byte[DWORD_SIZE * count]; file.Read(buffer, 0, buffer.Length); file.Position = pos; GFFObject[] structs = new GFFObject[count]; for (int i = 0, j = 0; i < count; i++, j += DWORD_SIZE) { GFFStructDef def = ReadStruct(BitConverter.ToUInt32(buffer, j)); structs[i] = new GFFObject(null, GFFObject.FieldType.Struct, def.structValue, def.structID); } return(structs); }
public GFFLoader(Stream file) { this.file = file; //read the file type and version byte[] buffer = new byte[DWORD_SIZE * 14]; file.Read(buffer, 0, DWORD_SIZE * 14); string filetype = Encoding.ASCII.GetString(buffer, 0, 4); string filever = Encoding.ASCII.GetString(buffer, 4, 4); //get the offset to and number of structs in the file structoffset = BitConverter.ToUInt32(buffer, 8); structcount = BitConverter.ToInt32(buffer, 12); //get the offset to and number of fields in the file fieldoffset = BitConverter.ToUInt32(buffer, 16); fieldcount = BitConverter.ToInt32(buffer, 20); //get the offset to and number of labels in the file labeloffset = BitConverter.ToUInt32(buffer, 24); labelcount = BitConverter.ToInt32(buffer, 28); //get the offset to and number of field data in the file fdoffset = BitConverter.ToUInt32(buffer, 32); fdcount = BitConverter.ToInt32(buffer, 36); //get the offset to and number of field indices in the file fioffset = BitConverter.ToUInt32(buffer, 40); ficount = BitConverter.ToInt32(buffer, 44); //get the offset to and number of list indices in the file lioffset = BitConverter.ToUInt32(buffer, 48); licount = BitConverter.ToInt32(buffer, 52); //read the top level struct, recursively reading the file GFFStructDef def = ReadStruct(0); TopStruct = new GFFObject(null, GFFObject.FieldType.Struct, def.structValue, def.structID); }
public object Serialize <T>() { Type objectType = typeof(T); // Creates an instance of "T" from this GFFObject // Will throw an exception if a field does not match // the class we are serializing into switch (Type) { case GFFObject.FieldType.Struct: T return_obj = (T)Activator.CreateInstance(objectType); Dictionary <string, GFFObject> dict = (Dictionary <string, GFFObject>)Value; HashSet <string> found = new HashSet <string>(); foreach (FieldInfo p in objectType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { // Check that the dictionary has this property GFFAttribute attr = (GFFAttribute)p.GetCustomAttributes(typeof(GFFAttribute)).First(); string name = attr.name; if (!dict.ContainsKey(name)) { if (name == "structid") { p.SetValue(return_obj, StructID); continue; } else { //Debug.LogWarning("Key " + name + " not found"); continue; } } found.Add(name); // Create a generic serializer method based on the expected type of this field GFFObject obj = dict[name]; MethodInfo serializer = obj.GetType().GetMethod("Serialize").MakeGenericMethod(p.FieldType); // Invoke this serializer on the value dict[name] object serialized = serializer.Invoke(dict[name], null); // Set the value in the instance try { p.SetValue(return_obj, serialized); } catch (Exception e) { Debug.LogError("Failed to serialize value " + name + " of type " + serialized.GetType() + "; expected " + p.FieldType); throw e; } } //foreach (string k in dict.Keys) //{ // if (!found.Contains(k)) // { // Debug.LogWarning("Did not serialize value " + k + " with type " + dict[k].Value.GetType().ToString()); // } //} return(return_obj); case GFFObject.FieldType.List: // This is made easier because any list is guaranteed to be of type // List<GFFObject> (and the objects are always structs, but that's // not actually important). Type listType = objectType.GetGenericArguments()[0]; Type newListType = typeof(List <>).MakeGenericType(new[] { listType }); IList return_list = (IList)Activator.CreateInstance(newListType); GFFObject[] items = (GFFObject[])Value; foreach (GFFObject obj in items) { MethodInfo serializer = obj.GetType().GetMethod("Serialize").MakeGenericMethod(listType); object serialized = serializer.Invoke(obj, null); return_list.Add(serialized); } return(return_list); case GFFObject.FieldType.Byte: case GFFObject.FieldType.Char: case GFFObject.FieldType.Word: case GFFObject.FieldType.Short: case GFFObject.FieldType.DWord: case GFFObject.FieldType.Int: case GFFObject.FieldType.DWord64: case GFFObject.FieldType.Int64: case GFFObject.FieldType.Float: case GFFObject.FieldType.Double: case GFFObject.FieldType.CExoString: case GFFObject.FieldType.ResRef: case GFFObject.FieldType.CExoLocString: case GFFObject.FieldType.Void: case GFFObject.FieldType.Quaternion: case GFFObject.FieldType.Vector3: return(Value); default: throw new Exception("Could not serialize type " + Type.ToString()); } }