static PType() { ttype = new PTypeUnion(); ttype.variants = new NamedType[] { new NamedType("none", new PType(PTypeEnumeration.none)), new NamedType("boolean", new PType(PTypeEnumeration.none)), new NamedType("character", new PType(PTypeEnumeration.none)), new NamedType("integer", new PType(PTypeEnumeration.none)), new NamedType("longinteger", new PType(PTypeEnumeration.none)), new NamedType("real", new PType(PTypeEnumeration.none)), new NamedType("fstring", new PType(PTypeEnumeration.integer)), new NamedType("sstring", new PType(PTypeEnumeration.none)), new NamedType("record", new PTypeSequence( new PTypeRecord( new NamedType("Name", new PType(PTypeEnumeration.sstring)), new NamedType("Type", ttype)))), //new NamedType("sequence", ttype), new NamedType("sequence", new PTypeRecord( new NamedType("growing", new PType(PTypeEnumeration.boolean)), new NamedType("Type", ttype))), new NamedType("union", new PTypeSequence( new PTypeRecord( new NamedType("Name", new PType(PTypeEnumeration.sstring)), new NamedType("Type", ttype)))), new NamedType("byte", new PType(PTypeEnumeration.@byte)) //, //new NamedType("objpair", new PTypeRecord( // )), // Нет объектной пары }; }
public static object Deserialize(BinaryReader br, PType tp) { switch (tp.Vid) { case PTypeEnumeration.none: { return(null); } case PTypeEnumeration.boolean: { return(br.ReadBoolean()); } case PTypeEnumeration.@byte: { return(br.ReadByte()); } case PTypeEnumeration.character: { return(br.ReadChar()); } case PTypeEnumeration.integer: { return(br.ReadInt32()); } case PTypeEnumeration.longinteger: { return(br.ReadInt64()); } case PTypeEnumeration.real: { return(br.ReadDouble()); } case PTypeEnumeration.sstring: { return(br.ReadString()); } case PTypeEnumeration.record: { PTypeRecord tp_rec = (PTypeRecord)tp; object[] rec = new object[tp_rec.Fields.Length]; for (int i = 0; i < rec.Length; i++) { object v = Deserialize(br, tp_rec.Fields[i].Type); rec[i] = v; } return(rec); } case PTypeEnumeration.sequence: { PType tp_element = ((PTypeSequence)tp).ElementType; long nelements = br.ReadInt64(); if (nelements < 0 || nelements > Int32.MaxValue) { throw new Exception($"Err in Deserialize: sequense has too many ({nelements}) elements"); } object[] elements = new object[nelements]; for (int i = 0; i < nelements; i++) { elements[i] = Deserialize(br, tp_element); } return(elements); } case PTypeEnumeration.union: { PTypeUnion tp_uni = (PTypeUnion)tp; // тег - 1 байт int tag = br.ReadByte(); object subval = Deserialize(br, tp_uni.Variants[tag].Type); return(new object[] { tag, subval }); } default: { throw new Exception($"Err in Deserialize: unknown type variant {tp.Vid}"); } } }
//TODO: Добавление уровня - неправильный путь борьбы с рекурсивными типами, но пока ... //TODO: А еще я похоже "напортачил" с вариантом (растущих) последовательностей ... public object ToPObject(int level) { if (level < 0) { return(null); } switch (this.vid) { case PTypeEnumeration.fstring: { return(new object[] { PType.ToInt(this.vid), ((PTypeFString)this).Size }); } case PTypeEnumeration.record: { PTypeRecord ptr = (PTypeRecord)this; var query = ptr.Fields.Select(pair => new object[] { pair.Name, pair.Type.ToPObject(level - 1) }).ToArray(); return(new object[] { PType.ToInt(this.vid), query }); } case PTypeEnumeration.sequence: { PTypeSequence pts = (PTypeSequence)this; return(new object[] { PType.ToInt(this.vid), new object[] { new object[] { "growing", new object[] { PType.ToInt(PTypeEnumeration.boolean), null } }, new object[] { "Type", pts.ElementType.ToPObject(level - 1) } } }); } case PTypeEnumeration.union: { PTypeUnion ptu = (PTypeUnion)this; var query = ptu.Variants.Select(pair => new object[] { pair.Name, pair.Type.ToPObject(level - 1) }).ToArray(); return(new object[] { PType.ToInt(this.vid), query }); } default: return(new object[] { PType.ToInt(this.vid), null }); } }
public string Interpret(object v, bool withfieldnames = false) { switch (this.vid) { case PTypeEnumeration.none: return(""); case PTypeEnumeration.boolean: return(((bool)v).ToString()); case PTypeEnumeration.character: return("'" + ((char)v).ToString() + "'"); // Нужно учесть специальные символы case PTypeEnumeration.integer: return(((int)v).ToString()); case PTypeEnumeration.longinteger: return(((long)v).ToString()); case PTypeEnumeration.real: return(((double)v).ToString("G", CultureInfo.InvariantCulture)); case PTypeEnumeration.fstring: return("\"" + ((string)v).Replace("\"", "\\\"") + "\""); case PTypeEnumeration.sstring: return("\"" + ((string)v).Replace("\"", "\\\"") + "\""); case PTypeEnumeration.record: { PTypeRecord ptr = (PTypeRecord)this; object[] arr = (object[])v; StringBuilder sb = new StringBuilder(); sb.Append('{'); for (int i = 0; i < ptr.Fields.Length; i++) { if (i > 0) { sb.Append(','); } if (withfieldnames) { sb.Append(ptr.Fields[i].Name); sb.Append(':'); } sb.Append(ptr.Fields[i].Type.Interpret(arr[i])); } sb.Append('}'); return(sb.ToString()); } case PTypeEnumeration.sequence: { PTypeSequence pts = (PTypeSequence)this; PType tel = pts.ElementType; object[] arr = (object[])v; StringBuilder sb = new StringBuilder(); sb.Append('['); for (int i = 0; i < arr.Length; i++) { if (i > 0) { sb.Append(','); } sb.Append(tel.Interpret(arr[i])); } sb.Append(']'); return(sb.ToString()); } case PTypeEnumeration.union: { PTypeUnion ptu = (PTypeUnion)this; object[] arr = (object[])v; if (arr.Length != 2) { throw new Exception("incorrect data for union"); } int tag = (int)arr[0]; if (tag < 0 || tag >= ptu.Variants.Length) { throw new Exception("incorrect data for union"); } NamedType nt = ptu.Variants[tag]; return(nt.Name + "^" + nt.Type.Interpret(arr[1])); } case PTypeEnumeration.@byte: return(((byte)v).ToString()); // не реализован вариант объектной парыЫ default: throw new Exception("Can't interpret value by type"); } }
private object Des(PType tp) { switch (tp.Vid) { case PTypeEnumeration.none: { return(null); } case PTypeEnumeration.boolean: { return(ReadBoolean()); } case PTypeEnumeration.@byte: { return(ReadByte()); } case PTypeEnumeration.character: { return(ReadChar()); } case PTypeEnumeration.integer: { return(ReadInt32()); } case PTypeEnumeration.longinteger: { return(ReadInt64()); } case PTypeEnumeration.real: { return(ReadDouble()); } case PTypeEnumeration.sstring: { return(ReadString()); } case PTypeEnumeration.record: { PTypeRecord tp_rec = (PTypeRecord)tp; object[] rec = new object[tp_rec.Fields.Length]; char c = (char)tr.Read(); if (c != '{') { throw new Exception("Polar syntax error 19327"); } for (int i = 0; i < rec.Length; i++) { Skip(); object v = Des(tp_rec.Fields[i].Type); rec[i] = v; if (i < rec.Length - 1) { Skip(); c = (char)tr.Read(); if (c != ',') { throw new Exception("Polar syntax error 19329"); } } Skip(); } c = (char)tr.Read(); if (c != '}') { throw new Exception("Polar syntax error 19328"); } return(rec); } case PTypeEnumeration.sequence: { PType tp_element = ((PTypeSequence)tp).ElementType; List <object> lsequ = new List <object>(); char c = (char)tr.Read(); if (c != '[') { throw new Exception("Polar syntax error 19331"); } bool firsttime = true; while (true) { Skip(); //TODO: неудачно, что дважды проверяю и выхожу по закрывающей скобке if (firsttime && tr.Peek() == ']') { c = (char)tr.Read(); break; } firsttime = false; lsequ.Add(Des(tp_element)); Skip(); c = (char)tr.Read(); if (c == ']') { break; } else if (c == ',') { continue; } throw new Exception("Polar syntax error 19333"); } if (c != ']') { throw new Exception("Polar syntax error 19332"); } object[] elements = lsequ.ToArray(); return(elements); } case PTypeEnumeration.union: { PTypeUnion tp_uni = (PTypeUnion)tp; // тег - 1 байт int tag = ReadInt32(); Skip(); int c = tr.Read(); if (c != '^') { throw new Exception("Polar syntax error 19335"); } Skip(); object subval = Des(tp_uni.Variants[tag].Type); return(new object[] { tag, subval }); } default: { throw new Exception($"Err in Deserialize: unknown type variant {tp.Vid}"); } } }
public static void SerializeFormatted(TextWriter tw, object v, PType tp, int level) { Intend(tw, level * intend); switch (tp.Vid) { case PTypeEnumeration.none: { return; } case PTypeEnumeration.boolean: { tw.Write((bool)v ? 't' : 'f'); return; } case PTypeEnumeration.@byte: { tw.Write(((byte)v).ToString()); return; } case PTypeEnumeration.character: { tw.Write((char)v); return; } case PTypeEnumeration.integer: { tw.Write((int)v); return; } case PTypeEnumeration.longinteger: { tw.Write((long)v); return; } case PTypeEnumeration.real: { tw.Write(((double)v).ToString("G", System.Globalization.CultureInfo.InvariantCulture)); return; } case PTypeEnumeration.sstring: { tw.Write('\"'); tw.Write(((string)v).Replace("\\", "\\\\").Replace("\"", "\\\"")); tw.Write('\"'); return; } case PTypeEnumeration.record: { object[] rec = (object[])v; PTypeRecord tp_rec = (PTypeRecord)tp; if (rec.Length != tp_rec.Fields.Length) { throw new Exception("Err in Serialize: wrong record field number"); } bool simple = IsSimple(tp); if (simple) { Serialize(tw, v, tp); return; } tw.Write('{'); for (int i = 0; i < rec.Length; i++) { if (i != 0) { tw.Write(','); } SerializeFormatted(tw, rec[i], tp_rec.Fields[i].Type, level + 1); } Intend(tw, level * intend); tw.Write('}'); return; } case PTypeEnumeration.sequence: { PType tp_element = ((PTypeSequence)tp).ElementType; object[] elements = (object[])v; tw.Write('['); bool isfirst = true; foreach (object el in elements) { if (!isfirst) { tw.Write(','); } isfirst = false; SerializeFormatted(tw, el, tp_element, level + 1); } Intend(tw, level * intend); tw.Write(']'); return; } case PTypeEnumeration.union: { PTypeUnion tp_uni = (PTypeUnion)tp; // тег - 1 байт int tag = (int)((object[])v)[0]; object subval = ((object[])v)[1]; if (tag < 0 || tag >= tp_uni.Variants.Length) { throw new Exception("Err in Serialize: wrong union tag"); } tw.Write(tag); tw.Write('^'); if (IsSimple(tp_uni.Variants[tag].Type)) { Serialize(tw, subval, tp_uni.Variants[tag].Type); return; } SerializeFormatted(tw, subval, tp_uni.Variants[tag].Type, level + 1); return; } } }
public static void Serialize(BinaryWriter bw, object v, PType tp) { switch (tp.Vid) { case PTypeEnumeration.none: { return; } case PTypeEnumeration.boolean: { bw.Write((bool)v); return; } case PTypeEnumeration.@byte: { bw.Write((byte)v); return; } case PTypeEnumeration.character: { bw.Write((char)v); return; } case PTypeEnumeration.integer: { bw.Write((int)v); return; } case PTypeEnumeration.longinteger: { bw.Write((long)v); return; } case PTypeEnumeration.real: { bw.Write((double)v); return; } case PTypeEnumeration.sstring: { bw.Write((string)v); return; } case PTypeEnumeration.record: { object[] rec = (object[])v; PTypeRecord tp_rec = (PTypeRecord)tp; if (rec.Length != tp_rec.Fields.Length) { throw new Exception("Err in Serialize: wrong record field number"); } for (int i = 0; i < rec.Length; i++) { Serialize(bw, rec[i], tp_rec.Fields[i].Type); } return; } case PTypeEnumeration.sequence: { PType tp_element = ((PTypeSequence)tp).ElementType; object[] elements = (object[])v; bw.Write((long)elements.Length); foreach (object el in elements) { Serialize(bw, el, tp_element); } return; } case PTypeEnumeration.union: { PTypeUnion tp_uni = (PTypeUnion)tp; // тег - 1 байт int tag = (int)((object[])v)[0]; object subval = ((object[])v)[1]; if (tag < 0 || tag >= tp_uni.Variants.Length) { throw new Exception("Err in Serialize: wrong union tag"); } bw.Write((byte)tag); Serialize(bw, subval, tp_uni.Variants[tag].Type); return; } } }