void WriteBody(Element elem) { Writer.Write(elem.Count); foreach (var attr in elem) { StringDict.WriteString(attr.Key); var attr_type = attr.Value == null ? typeof(Element) : attr.Value.GetType(); Writer.Write(TypeToId(attr_type, EncodingVersion)); if (attr.Value == null || !Datamodel.IsDatamodelArrayType(attr.Value.GetType())) { WriteAttribute(attr.Value, false); } else { var array = (System.Collections.IList)attr.Value; Writer.Write(array.Count); attr_type = Datamodel.GetArrayInnerType(array.GetType()); foreach (var item in array) { WriteAttribute(item, true); } } } }
static byte TypeToId(Type type, int version) { bool array = Datamodel.IsDatamodelArrayType(type); var search_type = array ? Datamodel.GetArrayInnerType(type) : type; if (array && search_type == typeof(byte) && !SupportedAttributes[version].Contains(typeof(byte))) { search_type = typeof(byte[]); // Recent version of DMX support both "binary" and "uint8_array" attributes. These are the same thing! array = false; } var type_list = SupportedAttributes[version]; byte i = 0; foreach (var list_type in type_list) { if (list_type == search_type) { break; } else { i++; } } if (i == type_list.Length) { throw new CodecException(String.Format("\"{0}\" is not supported in encoding binary {1}", type.Name, version)); } if (array) { i += (byte)(type_list.Length * (version >= 9 ? 2 : 1)); } return(++i); }
object DecodeAttribute(Datamodel dm, bool prefix) { var type = IdToType(Reader.ReadByte()); if (!Datamodel.IsDatamodelArrayType(type)) { return(ReadValue(dm, type, EncodingVersion < 4 || prefix)); } else { var count = Reader.ReadInt32(); var inner_type = Datamodel.GetArrayInnerType(type); var array = CodecUtilities.MakeList(inner_type, count); foreach (var x in Enumerable.Range(0, count)) { array.Add(ReadValue(dm, inner_type, true)); } return(array); } }
void SkipAttribte() { var type = IdToType(Reader.ReadByte()); int count = 1; bool array = false; if (Datamodel.IsDatamodelArrayType(type)) { array = true; count = Reader.ReadInt32(); type = Datamodel.GetArrayInnerType(type); } if (type == typeof(Element)) { foreach (int i in Enumerable.Range(0, count)) { if (Reader.ReadInt32() == -2) { Reader.BaseStream.Seek(37, SeekOrigin.Current); // skip GUID + null terminator if a stub } } return; } int length; if (type == typeof(TimeSpan)) { length = sizeof(int); } else if (type == typeof(System.Drawing.Color)) { length = 4; } else if (type == typeof(bool)) { length = 1; } else if (type == typeof(byte[])) { foreach (var i in Enumerable.Range(0, count)) { Reader.BaseStream.Seek(Reader.ReadInt32(), SeekOrigin.Current); } return; } else if (type == typeof(string)) { if (!StringDict.Dummy && !array && EncodingVersion >= 4) { length = StringDict.IndiceSize; } else { foreach (var i in Enumerable.Range(0, count)) { byte b; do { b = Reader.ReadByte(); } while (b != 0); } return; } } else if (type == typeof(Vector2)) { length = sizeof(float) * 2; } else if (type == typeof(Vector3)) { length = sizeof(float) * 3; } else if (type == typeof(Vector4) || type == typeof(Quaternion)) { length = sizeof(float) * 4; } else if (type == typeof(Matrix4x4)) { length = sizeof(float) * 4 * 4; } else { length = System.Runtime.InteropServices.Marshal.SizeOf(type); } Reader.BaseStream.Seek(length * count, SeekOrigin.Current); }
void WriteAttribute(string name, Type type, object value, bool in_array) { bool is_element = type == typeof(Element); Type inner_type = null; if (!in_array) { inner_type = Datamodel.GetArrayInnerType(type); if (inner_type == typeof(byte) && !ValidAttributes[EncodingVersion].Contains(typeof(byte))) { inner_type = null; // fall back on the "binary" type in older KV2 versions } } if (!ValidAttributes[EncodingVersion].Contains(inner_type ?? type)) { throw new CodecException(type.Name + " is not valid in KeyValues2 " + EncodingVersion); } if (inner_type != null) { is_element = inner_type == typeof(Element); Writer.WriteTokenLine(name, TypeNames[inner_type] + "_array"); if (((System.Collections.IList)value).Count == 0) { Writer.Write(" [ ]"); return; } if (is_element) { Writer.WriteLine("["); } else { Writer.Write(" ["); } Writer.Indent++; foreach (var array_value in (System.Collections.IList)value) { WriteAttribute(null, inner_type, array_value, true); } Writer.Indent--; Writer.TrimEnd(1); // remove trailing comma if (inner_type == typeof(Element)) { Writer.WriteLine("]"); } else { Writer.Write(" ]"); } return; } if (is_element) { var elem = value as Element; var id = elem == null ? "" : elem.ID.ToString(); if (in_array) { if (elem != null && Users[elem] == 1) { Writer.WriteLine(); WriteElement(elem); } else { Writer.WriteTokenLine("element", id); } Writer.Write(","); } else { if (elem != null && Users.ContainsKey(elem) && Users[elem] == 1) { Writer.WriteLine(String.Format("\"{0}\" ", name)); WriteElement(elem); } else { Writer.WriteTokenLine(name, "element", id); } } } else { if (type == typeof(bool)) { value = (bool)value ? 1 : 0; } else if (type == typeof(float)) { value = (float)value; } else if (type == typeof(byte[])) { value = BitConverter.ToString((byte[])value).Replace("-", String.Empty); } else if (type == typeof(TimeSpan)) { value = ((TimeSpan)value).TotalSeconds; } else if (type == typeof(System.Drawing.Color)) { var c = (System.Drawing.Color)value; value = String.Join(" ", new int[] { c.R, c.G, c.B, c.A }); } else if (type == typeof(UInt64)) { value = ((UInt64)value).ToString("X"); } else if (type == typeof(Vector2)) { var arr = new float[2]; ((Vector2)value).CopyTo(arr); value = string.Join(" ", arr); } else if (type == typeof(Vector3)) { var arr = new float[3]; ((Vector3)value).CopyTo(arr); value = string.Join(" ", arr); } else if (type == typeof(Vector4)) { var arr = new float[4]; ((Vector4)value).CopyTo(arr); value = string.Join(" ", arr); } else if (type == typeof(Quaternion)) { var arr = new float[4]; var q = (Quaternion)value; value = string.Join(" ", q.X, q.Y, q.Z, q.W); } else if (type == typeof(Matrix4x4)) { var arr = new float[4 * 4]; var m = (Matrix4x4)value; value = string.Join(" ", m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.M41, m.M42, m.M43, m.M44); } if (in_array) { Writer.Write(String.Format(" \"{0}\",", value.ToString())); } else { Writer.WriteTokenLine(name, TypeNames[type], value.ToString()); } } }