using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Net.Http; using Newtonsoft.Json; namespace spgen { public enum ParamType { PT_BOOL, PT_SHORT, PT_USHORT, PT_CHAR, PT_UCHAR, PT_INT, PT_UINT, PT_INT64, PT_UINT64, PT_DOUBLE, PT_FLOAT, PT_STRING, PT_WSTRING, PT_BLOB, PT_ARRAY_BOOL, PT_ARRAY_SHORT, PT_ARRAY_USHORT, PT_ARRAY_CHAR, PT_ARRAY_UCHAR, PT_ARRAY_INT, PT_ARRAY_UINT, PT_ARRAY_INT64, PT_ARRAY_UINT64, PT_ARRAY_DOUBLE, PT_ARRAY_FLOAT, PT_ARRAY_STRING, PT_ARRAY_WSTRING, PT_ARRAY_BLOB, } public class Param { public string Name; public ParamType Type; } public class Method { public EntityClass ParentClass = new EntityClass(); public string Name; public int Id; public int Signature; public bool Overlap; public bool user_define_id; public bool user_define_sig; public virtual int CalcSignature() { throw new NotImplementedException(); //return 0; } } public class Oneway : Method { public List InfoParamList = new List(); public override int CalcSignature() { StringBuilder sb = new StringBuilder(); sb.Append(this.Name); foreach (Param i in InfoParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } return sb.ToString().GetHashCode(); } } public class Twoway : Method { public List ReqParamList = new List(); public List ResParamList = new List(); public override int CalcSignature() { StringBuilder sb = new StringBuilder(); sb.Append(this.Name); foreach (Param i in ReqParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } foreach (Param i in ResParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } return sb.ToString().GetHashCode(); } } public class Subscribe : Method { public Oneway Cancel; public List SubParamList = new List(); public Oneway Message; public override int CalcSignature() { StringBuilder sb = new StringBuilder(); sb.Append(Name); foreach (Param i in SubParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } foreach (Param i in Cancel.InfoParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } foreach (Param i in Message.InfoParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } return sb.ToString().GetHashCode(); } } public class EntityClass { public string Name; public bool Exclusive; public bool Overlap; public bool NativeOnly; public List MethodList = new List(); } public class EntityMsg { public string Name; public List InfoParamList = new List(); public int Signature; public int CalcSignature() { StringBuilder sb = new StringBuilder(); sb.Append(Name); foreach (Param i in InfoParamList) { sb.Append(i.Name); sb.Append(i.Type.ToString()); } return sb.ToString().GetHashCode(); } } public class ConstItem { public string Name; public int Value; } public class Entity { public List ClassList = new List(); public string Name; public List MsgList = new List(); public List ConstList = new List(); public Dictionary defineDic = new Dictionary(); public static Dictionary entityDic = new Dictionary(); public static void ReadEntityInfoFromShellIni(string shellIniPath) { List allLines = new List(); if (File.Exists(shellIniPath)) { string[] msgLines = File.ReadAllLines(shellIniPath, Encoding.GetEncoding("gb2312")); Regex reg = new Regex("^(.+)=.+0x(.+)$"); foreach (string line in msgLines) { Match match = reg.Match(line); if (match.Success && !entityDic.ContainsKey(match.Groups[1].Value)) entityDic.Add(match.Groups[1].Value, match.Groups[2].Value); } } } public static void ReadEntityInfoFromServer(List InfoArr) { entityDic.Clear(); Regex reg = new Regex("^(.+)=.+0x(.+)$"); foreach (string line in InfoArr) { Match match = reg.Match(line); if (match.Success && !entityDic.ContainsKey(match.Groups[1].Value)) entityDic.Add(match.Groups[1].Value, match.Groups[2].Value); } } public static Entity Load(string xmlfile) { Entity entity = new Entity(); XmlDocument doc = new XmlDocument(); doc.Load(xmlfile); XmlNode entitynode = doc.SelectSingleNode("/entity"); entity.Name = entitynode.Attributes["name"].Value; if (entity.Name == null) throw new Exception("entity name cannot empty!"); foreach (XmlNode i in entitynode.ChildNodes) { if (i.NodeType == XmlNodeType.Element) { if (i.Name == "class") { entity.ClassList.Add(LoadEntityClass(i)); } else if (i.Name == "message") { entity.MsgList.Add(LoadEntityMsg(i)); } else if (i.Name == "const") { entity.ConstList.Add(LoadConstItem(i)); } else { throw new Exception("invalid /entity/node, must be class or message!"); } } } int index = xmlfile.LastIndexOf('\\'); string curPath = xmlfile.Remove(index, xmlfile.Length - index); string deffilename = Path.Combine(curPath, string.Format("{0}_def_g.h", entity.Name)); string msgfile = Path.Combine(curPath, string.Format("{0}_msg_g.h", entity.Name)); List defineLines = new List(); if(File.Exists(deffilename)) { string[] msgLines = File.ReadAllLines(deffilename, Encoding.GetEncoding("gb2312")); foreach (string line in msgLines) defineLines.Add(line); } if (File.Exists(msgfile)) { string[] msgLines = File.ReadAllLines(msgfile, Encoding.GetEncoding("gb2312")); foreach (string line in msgLines) defineLines.Add(line); } foreach (string line in defineLines) { if (line.Contains("#define")) { string noTrimStr = line.Trim(); string[] splitArr = noTrimStr.Split(' '); if (3 == splitArr.Length) { entity.defineDic.Add(splitArr[1], splitArr[2]); } } } return entity; } static ConstItem LoadConstItem(XmlNode itemNode) { ConstItem item = new ConstItem(); item.Name = itemNode.Attributes["name"].Value; if (item.Name == null) throw new Exception("item name cannot empty!"); item.Value = Int32.Parse(itemNode.Attributes["value"].Value); return item; } static EntityMsg LoadEntityMsg(XmlNode msgNode) { EntityMsg msg = new EntityMsg(); msg.Name = msgNode.Attributes["name"].Value; if (msg.Name == null) throw new Exception("msg name cannot empty!"); LoadParamList(msg.InfoParamList, msgNode); msg.Signature = msg.CalcSignature(); return msg; } static EntityClass LoadEntityClass(XmlNode clsNode) { int seq = 0; EntityClass entitycls = new EntityClass(); entitycls.Name = clsNode.Attributes["name"].Value; if (entitycls.Name == null) throw new Exception("entity name cannot empty!"); entitycls.Exclusive = clsNode.Attributes["exclusive"].Value != null ? Boolean.Parse(clsNode.Attributes["exclusive"].Value) : false; entitycls.Overlap = clsNode.Attributes["exclusive"].Value != null ? Boolean.Parse(clsNode.Attributes["overlap"].Value) : true; if (clsNode.Attributes["native"] != null) { entitycls.NativeOnly = clsNode.Attributes["native"].Value != null ? Boolean.Parse(clsNode.Attributes["overlap"].Value) : false; } else { entitycls.NativeOnly = false; } foreach (XmlNode method in clsNode.ChildNodes) { if (method.NodeType == XmlNodeType.Element) { Method m = LoadMethod(method); if (!m.user_define_id) m.Id = seq++; if (!m.user_define_sig) m.Signature = m.CalcSignature(); if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe sub = m as Subscribe; sub.Cancel.Id = seq++; sub.Cancel.Signature = sub.Cancel.CalcSignature(); sub.Message.Id = seq++; sub.Message.Signature = sub.Message.CalcSignature(); } entitycls.MethodList.Add(m); } } return entitycls; } static Method LoadMethod(XmlNode method) { Method m; string name = method.Attributes["name"].Value; if (name == null) throw new Exception("method name cannot empty!"); bool overlap = bool.Parse(method.Attributes["overlap"].Value); if (string.Compare(method.Name, "oneway", true) == 0) { m = LoadOneway(method); } else if (string.Compare(method.Name, "twoway", true) == 0) { m = LoadTwoway(method); } else if (string.Compare(method.Name, "subscribe", true) == 0) { m = LoadSubscribe(method); } else { throw new Exception("unknown method type!"); } m.Name = name; m.Overlap = overlap; if (method.Attributes["method_id"] != null) { m.user_define_id = true; m.Id = Int32.Parse(method.Attributes["method_id"].Value); } else { m.user_define_id = false; } if (method.Attributes["method_sig"] != null) { m.user_define_sig = true; m.Signature = Int32.Parse(method.Attributes["method_sig"].Value); } else { m.user_define_sig = false; } return m; } static Method LoadOneway(XmlNode method) { Oneway oneway = new Oneway(); LoadParamList(oneway.InfoParamList, method); return oneway; } static Method LoadTwoway(XmlNode method) { Twoway twoway = new Twoway(); foreach (XmlNode i in method.ChildNodes) { if (i.NodeType == XmlNodeType.Element) { if (String.Compare(i.Name, "req", true) == 0) { if (twoway.ReqParamList.Count != 0) throw new Exception("duplicate load of req!"); LoadParamList(twoway.ReqParamList, i); } else if (String.Compare(i.Name, "res", true) == 0) { if (twoway.ResParamList.Count != 0) throw new Exception("duplicate load of res!"); LoadParamList(twoway.ResParamList, i); } else { throw new Exception("unsupported tag!"); } } } return twoway; } static Method LoadSubscribe(XmlNode method) { Subscribe subscribe = new Subscribe(); LoadParamList(subscribe.SubParamList, method); foreach (XmlNode i in method.ChildNodes) { if (i.NodeType == XmlNodeType.Element) { if (string.Compare(i.Name, "cancel") == 0) { if (subscribe.Cancel != null) throw new Exception("duplicate load of cancel"); subscribe.Cancel = new Oneway(); subscribe.Cancel.Name = i.Attributes["name"].Value; subscribe.Cancel.Overlap = true; LoadParamList(subscribe.Cancel.InfoParamList, i); } if (string.Compare(i.Name, "message") == 0) { if (subscribe.Message != null) throw new Exception("duplicate load of message"); subscribe.Message = new Oneway(); subscribe.Message.Name = i.Attributes["name"].Value; subscribe.Message.Overlap = true; LoadParamList(subscribe.Message.InfoParamList, i); } } } if (subscribe.Message == null) throw new Exception("Message cannot null"); if (subscribe.Cancel == null) throw new Exception("Cancel cannot null"); return subscribe; } static void LoadParamList(List ParamList, XmlNode parent) { foreach (XmlNode i in parent.ChildNodes) { if (i.NodeType == XmlNodeType.Element) { if (string.Compare(i.Name, "param", true) == 0) { string name = i.Attributes["name"].Value; if (name == null) throw new Exception("method name cannot empty!"); string type = i.Attributes["type"].Value; if (type == null) throw new Exception("method type cannot empty!"); Param p = new Param(); p.Name = name; p.Type = ToParamType(type); ParamList.Add(p); } } } } public static ParamType ToParamType(string type) { switch (type) { case "bool": return ParamType.PT_BOOL; case "int": return ParamType.PT_INT; case "uint": return ParamType.PT_UINT; case "short": return ParamType.PT_SHORT; case "ushort": return ParamType.PT_USHORT; case "char": return ParamType.PT_CHAR; case "uchar": return ParamType.PT_UCHAR; case "string": return ParamType.PT_STRING; case "wstring": return ParamType.PT_WSTRING; case "float": return ParamType.PT_FLOAT; case "double": return ParamType.PT_DOUBLE; case "blob": return ParamType.PT_BLOB; case "int64": return ParamType.PT_INT64; case "uint64": return ParamType.PT_UINT64; case "array_bool": return ParamType.PT_ARRAY_BOOL; case "array_short": return ParamType.PT_ARRAY_SHORT; case "array_ushort": return ParamType.PT_ARRAY_USHORT; case "array_char": return ParamType.PT_ARRAY_CHAR; case "array_uchar": return ParamType.PT_ARRAY_UCHAR; case "array_int": return ParamType.PT_ARRAY_INT; case "array_uint": return ParamType.PT_ARRAY_UINT; case "array_int64": return ParamType.PT_ARRAY_INT64; case "array_uint64": return ParamType.PT_ARRAY_UINT64; case "array_double": return ParamType.PT_ARRAY_DOUBLE; case "array_float": return ParamType.PT_ARRAY_FLOAT; case "array_string": return ParamType.PT_ARRAY_STRING; case "array_wstring": return ParamType.PT_ARRAY_WSTRING; case "array_blob": return ParamType.PT_ARRAY_BLOB; default: throw new Exception("unsupported type!"); } } } public abstract class GeneratorBase { public abstract void GenerateCode(string dir, Entity entity, bool inSourceDir); } class Program { static void Usage() { Console.WriteLine("\tUsage: spgen.exe .xml\n"); } public class ShellInfo { public string module { get; set; } public string name { get; set; } public string value { get; set; } } static async Task PostRequestAsync() { try { // 构造请求数据 var requestData = "{\"terminal_no\": \"7555980178\"}"; var content = new StringContent(requestData, Encoding.UTF8, "application/json"); // 创建 HttpClient 实例 using (var httpClient = new HttpClient()) { // 设置请求的 URL var requestUrl = "http://centerconfig.paasst.cmbchina.cn/api/unify/config/query"; // 发送 POST 请求 var response = await httpClient.PostAsync(requestUrl, content); // 检查响应是否成功 if (response.IsSuccessStatusCode) { // 读取响应内容 var responseContent = await response.Content.ReadAsStringAsync(); dynamic jsonObject = JsonConvert.DeserializeObject(responseContent); dynamic dataObj = JsonConvert.DeserializeObject(jsonObject.data.ToString()); dynamic shellObj = JsonConvert.DeserializeObject(dataObj.shell_config_dto.ToString()); List infos = JsonConvert.DeserializeObject>(shellObj.config.ToString()); List entityArr = new List(); foreach (var it in infos) { if (it.module == "Entity") { String cur = it.name + "=" + it.value; entityArr.Insert(0, cur); } } entityArr.Insert(0, "VtmLoader=1,mod_VtmLoader,0x10F"); Entity.ReadEntityInfoFromServer(entityArr); } else { Console.WriteLine($"Error: {response.StatusCode}"); } } } catch (Exception ex) { Console.WriteLine($"Exception: {ex.ToString()}"); } } // spgen.exe print_entity.xml static async Task Main(string[] args) { if (args.Length != 1 && args.Length != 2) { Usage(); return; } try { await PostRequestAsync(); string xmlfile = System.IO.Path.Combine(Environment.CurrentDirectory, args[0]); Entity entity = Entity.Load(xmlfile); int index = xmlfile.LastIndexOf('\\'); string curPath = xmlfile.Remove(index, xmlfile.Length - index); CPPGenerator cppgen = new CPPGenerator(); cppgen.GenerateCode(curPath, entity, true); CSGenerator csgen = new CSGenerator(); csgen.GenerateCode(Environment.CurrentDirectory, entity, false); Console.WriteLine("generated ok!"); } catch (Exception e) { Console.WriteLine(e); Usage(); } } } }