private static bool IsSimple(PType tp) { if (tp.IsAtom || tp.Vid == PTypeEnumeration.sstring) { return(true); } if (tp.Vid == PTypeEnumeration.record) { PTypeRecord rec = (PTypeRecord)tp; bool simple = true; for (int i = 0; i < rec.Fields.Length; i++) { var t = rec.Fields[i].Type; if (!(t.IsAtom || t.Vid == PTypeEnumeration.sstring)) { simple = false; break; } } if (simple) { return(true); } } return(false); }
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}"); } } }
public static PType FromPObject(object po) { object[] uni = (object[])po; int tg = (int)uni[0]; switch (tg) { case 0: return(new PType(PTypeEnumeration.none)); case 1: return(new PType(PTypeEnumeration.boolean)); case 2: return(new PType(PTypeEnumeration.character)); case 3: return(new PType(PTypeEnumeration.integer)); case 4: return(new PType(PTypeEnumeration.longinteger)); case 5: return(new PType(PTypeEnumeration.real)); case 6: return(new PType(PTypeEnumeration.fstring)); case 7: return(new PType(PTypeEnumeration.sstring)); case 8: { object[] fields_def = (object[])uni[1]; var query = fields_def.Select(fd => { object[] f = (object[])fd; return(new NamedType((string)f[0], FromPObject(f[1]))); }); PTypeRecord rec = new PTypeRecord(query.ToArray()); return(rec); } case 9: { object[] growing_type = (object[])uni[1]; return(new PTypeSequence(FromPObject(growing_type[1]), (bool)growing_type[0])); } // case 10: не реализован вариант объединения case 11: { return(new PType(PTypeEnumeration.@byte)); } // case 12: не реализован вариант объектной пары default: { throw new Exception("unknown tag for pobject"); } } }
//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; } } }