Program.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml;
  6. using System.IO;
  7. using System.Text.RegularExpressions;
  8. using System.Threading.Tasks;
  9. using System.Net.Http;
  10. using Newtonsoft.Json;
  11. namespace spgen
  12. {
  13. public enum ParamType
  14. {
  15. PT_BOOL,
  16. PT_SHORT,
  17. PT_USHORT,
  18. PT_CHAR,
  19. PT_UCHAR,
  20. PT_INT,
  21. PT_UINT,
  22. PT_INT64,
  23. PT_UINT64,
  24. PT_DOUBLE,
  25. PT_FLOAT,
  26. PT_STRING,
  27. PT_WSTRING,
  28. PT_BLOB,
  29. PT_ARRAY_BOOL,
  30. PT_ARRAY_SHORT,
  31. PT_ARRAY_USHORT,
  32. PT_ARRAY_CHAR,
  33. PT_ARRAY_UCHAR,
  34. PT_ARRAY_INT,
  35. PT_ARRAY_UINT,
  36. PT_ARRAY_INT64,
  37. PT_ARRAY_UINT64,
  38. PT_ARRAY_DOUBLE,
  39. PT_ARRAY_FLOAT,
  40. PT_ARRAY_STRING,
  41. PT_ARRAY_WSTRING,
  42. PT_ARRAY_BLOB,
  43. }
  44. public class Param
  45. {
  46. public string Name;
  47. public ParamType Type;
  48. }
  49. public class Method
  50. {
  51. public EntityClass ParentClass = new EntityClass();
  52. public string Name;
  53. public int Id;
  54. public int Signature;
  55. public bool Overlap;
  56. public bool user_define_id;
  57. public bool user_define_sig;
  58. public virtual int CalcSignature()
  59. {
  60. throw new NotImplementedException();
  61. //return 0;
  62. }
  63. }
  64. public class Oneway : Method
  65. {
  66. public List<Param> InfoParamList = new List<Param>();
  67. public override int CalcSignature()
  68. {
  69. StringBuilder sb = new StringBuilder();
  70. sb.Append(this.Name);
  71. foreach (Param i in InfoParamList)
  72. {
  73. sb.Append(i.Name);
  74. sb.Append(i.Type.ToString());
  75. }
  76. return sb.ToString().GetHashCode();
  77. }
  78. }
  79. public class Twoway : Method
  80. {
  81. public List<Param> ReqParamList = new List<Param>();
  82. public List<Param> ResParamList = new List<Param>();
  83. public override int CalcSignature()
  84. {
  85. StringBuilder sb = new StringBuilder();
  86. sb.Append(this.Name);
  87. foreach (Param i in ReqParamList)
  88. {
  89. sb.Append(i.Name);
  90. sb.Append(i.Type.ToString());
  91. }
  92. foreach (Param i in ResParamList)
  93. {
  94. sb.Append(i.Name);
  95. sb.Append(i.Type.ToString());
  96. }
  97. return sb.ToString().GetHashCode();
  98. }
  99. }
  100. public class Subscribe : Method
  101. {
  102. public Oneway Cancel;
  103. public List<Param> SubParamList = new List<Param>();
  104. public Oneway Message;
  105. public override int CalcSignature()
  106. {
  107. StringBuilder sb = new StringBuilder();
  108. sb.Append(Name);
  109. foreach (Param i in SubParamList)
  110. {
  111. sb.Append(i.Name);
  112. sb.Append(i.Type.ToString());
  113. }
  114. foreach (Param i in Cancel.InfoParamList)
  115. {
  116. sb.Append(i.Name);
  117. sb.Append(i.Type.ToString());
  118. }
  119. foreach (Param i in Message.InfoParamList)
  120. {
  121. sb.Append(i.Name);
  122. sb.Append(i.Type.ToString());
  123. }
  124. return sb.ToString().GetHashCode();
  125. }
  126. }
  127. public class EntityClass
  128. {
  129. public string Name;
  130. public bool Exclusive;
  131. public bool Overlap;
  132. public bool NativeOnly;
  133. public List<Method> MethodList = new List<Method>();
  134. }
  135. public class EntityMsg
  136. {
  137. public string Name;
  138. public List<Param> InfoParamList = new List<Param>();
  139. public int Signature;
  140. public int CalcSignature()
  141. {
  142. StringBuilder sb = new StringBuilder();
  143. sb.Append(Name);
  144. foreach (Param i in InfoParamList)
  145. {
  146. sb.Append(i.Name);
  147. sb.Append(i.Type.ToString());
  148. }
  149. return sb.ToString().GetHashCode();
  150. }
  151. }
  152. public class ConstItem
  153. {
  154. public string Name;
  155. public int Value;
  156. }
  157. public class Entity
  158. {
  159. public List<EntityClass> ClassList = new List<EntityClass>();
  160. public string Name;
  161. public List<EntityMsg> MsgList = new List<EntityMsg>();
  162. public List<ConstItem> ConstList = new List<ConstItem>();
  163. public Dictionary<string, string> defineDic = new Dictionary<string, string>();
  164. public static Dictionary<string, string> entityDic = new Dictionary<string, string>();
  165. public static void ReadEntityInfoFromShellIni(string shellIniPath)
  166. {
  167. List<string> allLines = new List<string>();
  168. if (File.Exists(shellIniPath))
  169. {
  170. string[] msgLines = File.ReadAllLines(shellIniPath, Encoding.GetEncoding("gb2312"));
  171. Regex reg = new Regex("^(.+)=.+0x(.+)$");
  172. foreach (string line in msgLines)
  173. {
  174. Match match = reg.Match(line);
  175. if (match.Success && !entityDic.ContainsKey(match.Groups[1].Value))
  176. entityDic.Add(match.Groups[1].Value, match.Groups[2].Value);
  177. }
  178. }
  179. }
  180. public static void ReadEntityInfoFromServer(List<String> InfoArr)
  181. {
  182. entityDic.Clear();
  183. Regex reg = new Regex("^(.+)=.+0x(.+)$");
  184. foreach (string line in InfoArr)
  185. {
  186. Match match = reg.Match(line);
  187. if (match.Success && !entityDic.ContainsKey(match.Groups[1].Value))
  188. entityDic.Add(match.Groups[1].Value, match.Groups[2].Value);
  189. }
  190. }
  191. public static Entity Load(string xmlfile)
  192. {
  193. Entity entity = new Entity();
  194. XmlDocument doc = new XmlDocument();
  195. doc.Load(xmlfile);
  196. XmlNode entitynode = doc.SelectSingleNode("/entity");
  197. entity.Name = entitynode.Attributes["name"].Value;
  198. if (entity.Name == null)
  199. throw new Exception("entity name cannot empty!");
  200. foreach (XmlNode i in entitynode.ChildNodes)
  201. {
  202. if (i.NodeType == XmlNodeType.Element)
  203. {
  204. if (i.Name == "class")
  205. {
  206. entity.ClassList.Add(LoadEntityClass(i));
  207. }
  208. else if (i.Name == "message")
  209. {
  210. entity.MsgList.Add(LoadEntityMsg(i));
  211. }
  212. else if (i.Name == "const")
  213. {
  214. entity.ConstList.Add(LoadConstItem(i));
  215. }
  216. else
  217. {
  218. throw new Exception("invalid /entity/node, must be class or message!");
  219. }
  220. }
  221. }
  222. int index = xmlfile.LastIndexOf('\\');
  223. string curPath = xmlfile.Remove(index, xmlfile.Length - index);
  224. string deffilename = Path.Combine(curPath, string.Format("{0}_def_g.h", entity.Name));
  225. string msgfile = Path.Combine(curPath, string.Format("{0}_msg_g.h", entity.Name));
  226. List<string> defineLines = new List<string>();
  227. if(File.Exists(deffilename))
  228. {
  229. string[] msgLines = File.ReadAllLines(deffilename, Encoding.GetEncoding("gb2312"));
  230. foreach (string line in msgLines)
  231. defineLines.Add(line);
  232. }
  233. if (File.Exists(msgfile))
  234. {
  235. string[] msgLines = File.ReadAllLines(msgfile, Encoding.GetEncoding("gb2312"));
  236. foreach (string line in msgLines)
  237. defineLines.Add(line);
  238. }
  239. foreach (string line in defineLines)
  240. {
  241. if (line.Contains("#define"))
  242. {
  243. string noTrimStr = line.Trim();
  244. string[] splitArr = noTrimStr.Split(' ');
  245. if (3 == splitArr.Length)
  246. {
  247. entity.defineDic.Add(splitArr[1], splitArr[2]);
  248. }
  249. }
  250. }
  251. return entity;
  252. }
  253. static ConstItem LoadConstItem(XmlNode itemNode)
  254. {
  255. ConstItem item = new ConstItem();
  256. item.Name = itemNode.Attributes["name"].Value;
  257. if (item.Name == null)
  258. throw new Exception("item name cannot empty!");
  259. item.Value = Int32.Parse(itemNode.Attributes["value"].Value);
  260. return item;
  261. }
  262. static EntityMsg LoadEntityMsg(XmlNode msgNode)
  263. {
  264. EntityMsg msg = new EntityMsg();
  265. msg.Name = msgNode.Attributes["name"].Value;
  266. if (msg.Name == null)
  267. throw new Exception("msg name cannot empty!");
  268. LoadParamList(msg.InfoParamList, msgNode);
  269. msg.Signature = msg.CalcSignature();
  270. return msg;
  271. }
  272. static EntityClass LoadEntityClass(XmlNode clsNode)
  273. {
  274. int seq = 0;
  275. EntityClass entitycls = new EntityClass();
  276. entitycls.Name = clsNode.Attributes["name"].Value;
  277. if (entitycls.Name == null)
  278. throw new Exception("entity name cannot empty!");
  279. entitycls.Exclusive = clsNode.Attributes["exclusive"].Value != null ? Boolean.Parse(clsNode.Attributes["exclusive"].Value) : false;
  280. entitycls.Overlap = clsNode.Attributes["exclusive"].Value != null ? Boolean.Parse(clsNode.Attributes["overlap"].Value) : true;
  281. if (clsNode.Attributes["native"] != null)
  282. {
  283. entitycls.NativeOnly = clsNode.Attributes["native"].Value != null ? Boolean.Parse(clsNode.Attributes["overlap"].Value) : false;
  284. }
  285. else
  286. {
  287. entitycls.NativeOnly = false;
  288. }
  289. foreach (XmlNode method in clsNode.ChildNodes)
  290. {
  291. if (method.NodeType == XmlNodeType.Element)
  292. {
  293. Method m = LoadMethod(method);
  294. if (!m.user_define_id)
  295. m.Id = seq++;
  296. if (!m.user_define_sig)
  297. m.Signature = m.CalcSignature();
  298. if (typeof(Subscribe).IsInstanceOfType(m))
  299. {
  300. Subscribe sub = m as Subscribe;
  301. sub.Cancel.Id = seq++;
  302. sub.Cancel.Signature = sub.Cancel.CalcSignature();
  303. sub.Message.Id = seq++;
  304. sub.Message.Signature = sub.Message.CalcSignature();
  305. }
  306. entitycls.MethodList.Add(m);
  307. }
  308. }
  309. return entitycls;
  310. }
  311. static Method LoadMethod(XmlNode method)
  312. {
  313. Method m;
  314. string name = method.Attributes["name"].Value;
  315. if (name == null)
  316. throw new Exception("method name cannot empty!");
  317. bool overlap = bool.Parse(method.Attributes["overlap"].Value);
  318. if (string.Compare(method.Name, "oneway", true) == 0)
  319. {
  320. m = LoadOneway(method);
  321. }
  322. else if (string.Compare(method.Name, "twoway", true) == 0)
  323. {
  324. m = LoadTwoway(method);
  325. }
  326. else if (string.Compare(method.Name, "subscribe", true) == 0)
  327. {
  328. m = LoadSubscribe(method);
  329. }
  330. else
  331. {
  332. throw new Exception("unknown method type!");
  333. }
  334. m.Name = name;
  335. m.Overlap = overlap;
  336. if (method.Attributes["method_id"] != null)
  337. {
  338. m.user_define_id = true;
  339. m.Id = Int32.Parse(method.Attributes["method_id"].Value);
  340. }
  341. else
  342. {
  343. m.user_define_id = false;
  344. }
  345. if (method.Attributes["method_sig"] != null)
  346. {
  347. m.user_define_sig = true;
  348. m.Signature = Int32.Parse(method.Attributes["method_sig"].Value);
  349. }
  350. else
  351. {
  352. m.user_define_sig = false;
  353. }
  354. return m;
  355. }
  356. static Method LoadOneway(XmlNode method)
  357. {
  358. Oneway oneway = new Oneway();
  359. LoadParamList(oneway.InfoParamList, method);
  360. return oneway;
  361. }
  362. static Method LoadTwoway(XmlNode method)
  363. {
  364. Twoway twoway = new Twoway();
  365. foreach (XmlNode i in method.ChildNodes)
  366. {
  367. if (i.NodeType == XmlNodeType.Element)
  368. {
  369. if (String.Compare(i.Name, "req", true) == 0)
  370. {
  371. if (twoway.ReqParamList.Count != 0)
  372. throw new Exception("duplicate load of req!");
  373. LoadParamList(twoway.ReqParamList, i);
  374. }
  375. else if (String.Compare(i.Name, "res", true) == 0)
  376. {
  377. if (twoway.ResParamList.Count != 0)
  378. throw new Exception("duplicate load of res!");
  379. LoadParamList(twoway.ResParamList, i);
  380. }
  381. else
  382. {
  383. throw new Exception("unsupported tag!");
  384. }
  385. }
  386. }
  387. return twoway;
  388. }
  389. static Method LoadSubscribe(XmlNode method)
  390. {
  391. Subscribe subscribe = new Subscribe();
  392. LoadParamList(subscribe.SubParamList, method);
  393. foreach (XmlNode i in method.ChildNodes)
  394. {
  395. if (i.NodeType == XmlNodeType.Element)
  396. {
  397. if (string.Compare(i.Name, "cancel") == 0)
  398. {
  399. if (subscribe.Cancel != null)
  400. throw new Exception("duplicate load of cancel");
  401. subscribe.Cancel = new Oneway();
  402. subscribe.Cancel.Name = i.Attributes["name"].Value;
  403. subscribe.Cancel.Overlap = true;
  404. LoadParamList(subscribe.Cancel.InfoParamList, i);
  405. }
  406. if (string.Compare(i.Name, "message") == 0)
  407. {
  408. if (subscribe.Message != null)
  409. throw new Exception("duplicate load of message");
  410. subscribe.Message = new Oneway();
  411. subscribe.Message.Name = i.Attributes["name"].Value;
  412. subscribe.Message.Overlap = true;
  413. LoadParamList(subscribe.Message.InfoParamList, i);
  414. }
  415. }
  416. }
  417. if (subscribe.Message == null)
  418. throw new Exception("Message cannot null");
  419. if (subscribe.Cancel == null)
  420. throw new Exception("Cancel cannot null");
  421. return subscribe;
  422. }
  423. static void LoadParamList(List<Param> ParamList, XmlNode parent)
  424. {
  425. foreach (XmlNode i in parent.ChildNodes)
  426. {
  427. if (i.NodeType == XmlNodeType.Element)
  428. {
  429. if (string.Compare(i.Name, "param", true) == 0)
  430. {
  431. string name = i.Attributes["name"].Value;
  432. if (name == null)
  433. throw new Exception("method name cannot empty!");
  434. string type = i.Attributes["type"].Value;
  435. if (type == null)
  436. throw new Exception("method type cannot empty!");
  437. Param p = new Param();
  438. p.Name = name;
  439. p.Type = ToParamType(type);
  440. ParamList.Add(p);
  441. }
  442. }
  443. }
  444. }
  445. public static ParamType ToParamType(string type)
  446. {
  447. switch (type)
  448. {
  449. case "bool":
  450. return ParamType.PT_BOOL;
  451. case "int":
  452. return ParamType.PT_INT;
  453. case "uint":
  454. return ParamType.PT_UINT;
  455. case "short":
  456. return ParamType.PT_SHORT;
  457. case "ushort":
  458. return ParamType.PT_USHORT;
  459. case "char":
  460. return ParamType.PT_CHAR;
  461. case "uchar":
  462. return ParamType.PT_UCHAR;
  463. case "string":
  464. return ParamType.PT_STRING;
  465. case "wstring":
  466. return ParamType.PT_WSTRING;
  467. case "float":
  468. return ParamType.PT_FLOAT;
  469. case "double":
  470. return ParamType.PT_DOUBLE;
  471. case "blob":
  472. return ParamType.PT_BLOB;
  473. case "int64":
  474. return ParamType.PT_INT64;
  475. case "uint64":
  476. return ParamType.PT_UINT64;
  477. case "array_bool":
  478. return ParamType.PT_ARRAY_BOOL;
  479. case "array_short":
  480. return ParamType.PT_ARRAY_SHORT;
  481. case "array_ushort":
  482. return ParamType.PT_ARRAY_USHORT;
  483. case "array_char":
  484. return ParamType.PT_ARRAY_CHAR;
  485. case "array_uchar":
  486. return ParamType.PT_ARRAY_UCHAR;
  487. case "array_int":
  488. return ParamType.PT_ARRAY_INT;
  489. case "array_uint":
  490. return ParamType.PT_ARRAY_UINT;
  491. case "array_int64":
  492. return ParamType.PT_ARRAY_INT64;
  493. case "array_uint64":
  494. return ParamType.PT_ARRAY_UINT64;
  495. case "array_double":
  496. return ParamType.PT_ARRAY_DOUBLE;
  497. case "array_float":
  498. return ParamType.PT_ARRAY_FLOAT;
  499. case "array_string":
  500. return ParamType.PT_ARRAY_STRING;
  501. case "array_wstring":
  502. return ParamType.PT_ARRAY_WSTRING;
  503. case "array_blob":
  504. return ParamType.PT_ARRAY_BLOB;
  505. default:
  506. throw new Exception("unsupported type!");
  507. }
  508. }
  509. }
  510. public abstract class GeneratorBase
  511. {
  512. public abstract void GenerateCode(string dir, Entity entity, bool inSourceDir);
  513. }
  514. class Program
  515. {
  516. static void Usage()
  517. {
  518. Console.WriteLine("\tUsage: spgen.exe <entity>.xml\n");
  519. }
  520. public class ShellInfo
  521. {
  522. public string module { get; set; }
  523. public string name { get; set; }
  524. public string value { get; set; }
  525. }
  526. static async Task PostRequestAsync()
  527. {
  528. try
  529. {
  530. // 构造请求数据
  531. var requestData = "{\"terminal_no\": \"7555980178\"}";
  532. var content = new StringContent(requestData, Encoding.UTF8, "application/json");
  533. // 创建 HttpClient 实例
  534. using (var httpClient = new HttpClient())
  535. {
  536. // 设置请求的 URL
  537. var requestUrl = "http://centerconfig.paasst.cmbchina.cn/api/unify/config/query";
  538. // 发送 POST 请求
  539. var response = await httpClient.PostAsync(requestUrl, content);
  540. // 检查响应是否成功
  541. if (response.IsSuccessStatusCode)
  542. {
  543. // 读取响应内容
  544. var responseContent = await response.Content.ReadAsStringAsync();
  545. dynamic jsonObject = JsonConvert.DeserializeObject(responseContent);
  546. dynamic dataObj = JsonConvert.DeserializeObject(jsonObject.data.ToString());
  547. dynamic shellObj = JsonConvert.DeserializeObject(dataObj.shell_config_dto.ToString());
  548. List<ShellInfo> infos = JsonConvert.DeserializeObject<List<ShellInfo>>(shellObj.config.ToString());
  549. List<String> entityArr = new List<string>();
  550. foreach (var it in infos)
  551. {
  552. if (it.module == "Entity")
  553. {
  554. String cur = it.name + "=" + it.value;
  555. entityArr.Insert(0, cur);
  556. }
  557. }
  558. entityArr.Insert(0, "VtmLoader=1,mod_VtmLoader,0x10F");
  559. Entity.ReadEntityInfoFromServer(entityArr);
  560. }
  561. else
  562. {
  563. Console.WriteLine($"Error: {response.StatusCode}");
  564. }
  565. }
  566. }
  567. catch (Exception ex)
  568. {
  569. Console.WriteLine($"Exception: {ex.ToString()}");
  570. }
  571. }
  572. // spgen.exe print_entity.xml
  573. static async Task Main(string[] args)
  574. {
  575. if (args.Length != 1 && args.Length != 2)
  576. {
  577. Usage();
  578. return;
  579. }
  580. try
  581. {
  582. await PostRequestAsync();
  583. string xmlfile = System.IO.Path.Combine(Environment.CurrentDirectory, args[0]);
  584. Entity entity = Entity.Load(xmlfile);
  585. int index = xmlfile.LastIndexOf('\\');
  586. string curPath = xmlfile.Remove(index, xmlfile.Length - index);
  587. CPPGenerator cppgen = new CPPGenerator();
  588. cppgen.GenerateCode(curPath, entity, true);
  589. CSGenerator csgen = new CSGenerator();
  590. csgen.GenerateCode(Environment.CurrentDirectory, entity, false);
  591. Console.WriteLine("generated ok!");
  592. }
  593. catch (Exception e)
  594. {
  595. Console.WriteLine(e);
  596. Usage();
  597. }
  598. }
  599. }
  600. }