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();
}
}
}
}