private string check_type(string ptype, string fieldtype) { if (SprotoHelper.IsBuildInType(fieldtype)) { return(fieldtype); } string fullname = ptype + "." + fieldtype; if (this.GetType(fullname) != null) { return(fullname); } // backtrace find List <string> list = new List <string>(ptype.Split('.')); list.RemoveAt(list.Count - 1); if (list.Count > 0) { string pptype = String.Join(".", list.ToArray()); return(this.check_type(pptype, fieldtype)); } else if (this.GetType(fieldtype) != null) { return(fieldtype); } else { return(null); } }
private static SprotoField parse_field(Lexer lexer, SprotoType type) { SprotoField field = new SprotoField(); Token token = expect(lexer, "word", "space"); field.name = token.val; // allow colon follow by tag,eg: field tag: type token = expect(lexer, "tag"); ignore(lexer, "space"); field.tag = Convert.ToUInt16(token.val); if (field.tag >= SprotoParser.MAX_FIELD_TAG) { SprotoHelper.Error(lexer.error_pos(token.line, token.column, type) + "{0} field's tag {1} >= {2}", field.name, field.tag, SprotoParser.MAX_FIELD_TAG); } expect(lexer, "colon", "space"); token = optional(lexer, "star"); if (token != null) { field.is_array = true; } token = expect(lexer, "word"); field.type = token.val; string fieldtype = field.type; token = optional(lexer, "key_start"); if (token != null) { // allow field tag : type(space+key+space) ignore(lexer, "space"); token = expect(lexer, "word|tag"); if ("tag" == token.type) { if (fieldtype != "integer") { SprotoHelper.Error(lexer.error_pos(token.line, token.column, type) + "decimal index expect 'integer' got '{0}'", fieldtype); } field.digit = Convert.ToUInt16(token.val); if (field.digit > SprotoParser.MAX_DECIMAL) { SprotoHelper.Error(lexer.error_pos(token.line, token.column, type) + "decimal index {0} > {1}", field.digit, SprotoParser.MAX_DECIMAL); } } else { if (SprotoHelper.IsBuildInType(fieldtype)) { SprotoHelper.Error(lexer.error_pos(token.line, token.column, type) + "map index expect 'usertype' got '{0}'", fieldtype); } field.key = token.val; } ignore(lexer, "space"); expect(lexer, "key_end", "space"); } else { expect(lexer, "space"); ignore(lexer, "space"); } return(field); }
public SprotoObject Decode(SprotoMgr sprotomgr, string typename, SprotoStream reader) { if (SprotoHelper.IsBuildInType(typename)) { SprotoHelper.Error("[SprotoCodec.Decode] expect a 'non-buildin-type' got '{0}'", typename); } SprotoType type = sprotomgr.GetType(typename); if (null == type) { SprotoHelper.Error("[SprotoCodec.Decode] occur a unknow-type '{0}'", typename); } SprotoObject obj = this.DecodeSprotoObject(sprotomgr, type, reader); return(obj); }
private void check_type() { foreach (var type in this.Types.Values) { foreach (var field in type.fields.Values) { if (!SprotoHelper.IsBuildInType(field.type) && (null == this.GetType(field.type))) { SprotoHelper.Error("undefined type '{0}' in field '{1}.{2}'", field.type, type.name, field.name); } if (field.key != null) { SprotoType fieldtype = this.GetType(field.type); if (null == fieldtype.GetField(field.key)) { SprotoHelper.Error("map index '{0}' cann't found in type '{1}'", field.key, field.type); } } } } }
public SprotoStream Encode(SprotoMgr sprotomgr, SprotoObject obj, SprotoStream writer = null) { if (null == writer) { writer = new SprotoStream(); } string typename = obj.type; if (SprotoHelper.IsBuildInType(typename)) { SprotoHelper.Error("[SprotoCodec.Encode] expect a 'non-buildin-type sprotoobj' got '{0}'", typename); } SprotoType type = sprotomgr.GetType(typename); if (null == type) { SprotoHelper.Error("[SprotoCodec.Encode] occur a unknow-type '{0}'", typename); } this.EncodeSprotoObject(sprotomgr, type, obj, writer); return(writer); }
private UInt32 EncodeSprotoObject(SprotoMgr sprotomgr, SprotoType type, SprotoObject obj, SprotoStream writer) { // encode header part List <UInt16> tags = new List <UInt16>(type.tagfields.Keys); tags.Sort(); UInt16 fieldnum = 0; Int16 lasttag = -1; int fieldnum_pos = writer.Position; writer.Seek(SprotoCodec.SIZEOF_FIELD, SprotoStream.SEEK_CUR); List <UInt16> data_tags = new List <UInt16>(); for (int i = 0; i < tags.Count; i++) { UInt16 tag = tags[i]; SprotoField field = type.GetField(tag); SprotoObject fieldobj = obj.Get(field.name); if (fieldobj != null) { UInt16 skiptag = (UInt16)(tag - lasttag); //Console.WriteLine("skiptag: tag={0},lasttag={1},skiptag={2}",tag,lasttag,skiptag); lasttag = (Int16)tag; if (skiptag > 1) { skiptag = (UInt16)((skiptag - 1) * 2 - 1); this.WriteTag(writer, skiptag); fieldnum++; } fieldnum++; bool encode_in_header = false; if (!field.is_array) { if (field.type == "integer") { Int64 integer; if (field.digit == 0) { integer = (Int64)fieldobj.val; } else { integer = (Int64)(Math.Round((double)fieldobj.val * MathPow(10, field.digit))); } if (this.IsSmallInteger(integer)) { encode_in_header = true; UInt16 number = (UInt16)((integer + 1) * 2); this.WriteTag(writer, number); } } else if (field.type == "boolean") { encode_in_header = true; bool ok = (bool)fieldobj.val; UInt16 integer = (UInt16)(ok ? 1 : 0); UInt16 number = (UInt16)((integer + 1) * 2); this.WriteTag(writer, number); } } if (!encode_in_header) { this.WriteTag(writer, 0); data_tags.Add(tag); } else { } } } this.FillFieldNum(writer, fieldnum_pos, fieldnum); UInt32 size = SprotoCodec.SIZEOF_FIELD + fieldnum * SprotoCodec.SIZEOF_FIELD; // encode data part foreach (UInt16 tag in data_tags) { SprotoField field = type.GetField(tag); SprotoType fieldtype = sprotomgr.GetType(field.type); SprotoObject fieldobj = obj.Get(field.name); int fieldsize_pos = writer.Position; UInt32 fieldsize = 0; writer.Seek(SprotoCodec.SIZEOF_LENGTH, SprotoStream.SEEK_CUR); if (SprotoHelper.IsBuildInType(field.type)) { fieldsize = this.EncodeBuildInType(field, fieldobj, writer); } else { if (field.is_array) { if (field.key != null) { string keytype = fieldtype.GetField(field.key).type; if (keytype == "integer") { Dictionary <Int64, SprotoObject> dict = fieldobj.val as Dictionary <Int64, SprotoObject>; fieldsize = this.EncodeSprotoObjectDict <Int64>(sprotomgr, dict, field, writer); } else if (keytype == "string") { Dictionary <string, SprotoObject> dict = fieldobj.val as Dictionary <string, SprotoObject>; fieldsize = this.EncodeSprotoObjectDict <string>(sprotomgr, dict, field, writer); } else if (keytype == "boolean") { Dictionary <bool, SprotoObject> dict = fieldobj.val as Dictionary <bool, SprotoObject>; fieldsize = this.EncodeSprotoObjectDict <bool>(sprotomgr, dict, field, writer); } else { SprotoHelper.Error("[SprotoCodec.EncodeSprotoObject] keytype expect 'integer/boolean/string' got '{0}'", keytype); } } else { List <SprotoObject> list = fieldobj.val as List <SprotoObject>; fieldsize = this.EncodeSprotoObjectList(sprotomgr, list, writer); } } else { fieldsize = this.EncodeSprotoObject(sprotomgr, fieldtype, fieldobj, writer); } } this.FillSize(writer, fieldsize_pos, fieldsize); size += (fieldsize + SprotoCodec.SIZEOF_LENGTH); } return(size); }
private SprotoObject DecodeSprotoObject(SprotoMgr sprotomgr, SprotoType type, SprotoStream reader) { SprotoObject obj = sprotomgr.NewSprotoObject(type.name); // decode header part UInt16 fieldnum = this.ReadUInt16(reader); List <UInt16> data_tags = new List <UInt16>(); UInt16 curtag = 0; for (UInt16 i = 0; i < fieldnum; i++) { UInt16 tag = this.ReadUInt16(reader); if (tag == 0) { data_tags.Add(curtag); curtag++; } else if (0 == (tag & 1)) // even { UInt16 val = (UInt16)((tag / 2) - 1); SprotoField field = type.GetField(curtag); if (field != null) // for protocol version compatibility { if (field.type == "integer") { if (0 == field.digit) { Int64 number = (Int64)(val); obj.Set(field.name, number); } else { double number = (double)val / MathPow(10, field.digit); obj.Set(field.name, number); } } else if (field.type == "boolean") { if (!(val == 0 || val == 1)) { SprotoHelper.Error("[SprotoCodec.DecodeSprotoObject] type={0},field={1},boolean type expect value '0/1' got '{2}'", type.name, curtag, val); } bool ok = (val == 0) ? false : true; obj.Set(field.name, ok); } else { SprotoHelper.Error("[SprotoCodec.DecodeSprotoObject] type={0},field={1},expect type 'integer/boolean' got '{2}'", type.name, curtag, field.type); } } curtag++; } else // odd { curtag += (UInt16)((tag + 1) / 2); } } // decode data part foreach (UInt16 tag in data_tags) { SprotoField field = type.GetField(tag); if (field != null) { object fieldobj = null; if (SprotoHelper.IsBuildInType(field.type)) { fieldobj = this.DecodeBuildInType(field, reader); } else { SprotoType fieldtype = sprotomgr.GetType(field.type); if (field.is_array) { if (field.key != null) { string keytype = fieldtype.GetField(field.key).type; if (keytype == "integer") { fieldobj = this.DecodeSprotoObjectDict <Int64>(sprotomgr, fieldtype, field, reader); } else if (keytype == "string") { fieldobj = this.DecodeSprotoObjectDict <string>(sprotomgr, fieldtype, field, reader); } else if (keytype == "boolean") { fieldobj = this.DecodeSprotoObjectDict <bool>(sprotomgr, fieldtype, field, reader); } else { SprotoHelper.Error("[SprotoCodec.DecodeSprotoObject] keytype expect 'integer/boolean/string' got '{0}'", keytype); } } else { fieldobj = this.DecodeSprotoObjectList(sprotomgr, fieldtype, reader); } } else { this.ReadUInt32(reader); fieldobj = this.DecodeSprotoObject(sprotomgr, fieldtype, reader); } } obj.Set(field.name, fieldobj); } else { // for protocol version compatibility UInt32 fieldsize = this.ReadUInt32(reader); this.IgnoreByte(reader, fieldsize); } } return(obj); }