erlang自定义二进制协议
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

746 line
31 KiB

  1. -module(protoGen).
  2. -export([
  3. convertFile/1
  4. , convert/1
  5. , convertDir/0
  6. , convertDir/1
  7. , convertDir/3
  8. ]).
  9. protoHrlHeader() ->
  10. "-opaque int8() :: -128..127.
  11. -opaque int16() :: -32768..32767.
  12. -opaque int32() :: -2147483648..2147483647.
  13. -opaque int64() :: -9223372036854775808..9223372036854775807.
  14. -opaque uint8() :: 0..255.
  15. -opaque uint16() :: 0..65536.
  16. -opaque uint32() :: 0..4294967295.
  17. -opaque uint64() :: 0..18446744073709551615.
  18. -opaque double() :: float().\n\n".
  19. protoErlHeader() ->
  20. "-module(protoMsg).\n\n
  21. -compile([nowarn_unused_vars]).
  22. -export([encode/1, decode/1, encodeRec/1, decodeBin/2]).
  23. -define(min8, -128).
  24. -define(max8, 127).
  25. -define(min16, -32768).
  26. -define(max16, 32767).
  27. -define(min32, -2147483648).
  28. -define(max32, 2147483647).
  29. -define(min64, -9223372036854775808).
  30. -define(max64, 9223372036854775807).
  31. -define(minF32, -3.4E+38).
  32. -define(maxF32, 3.4E+38).
  33. -define(minF64, -1.797E-308).
  34. -define(maxF64, 1.797E+308).
  35. -define(int8(V), <<V:8>>).
  36. -define(uint8(V), <<V:8>>).
  37. -define(int16(V), <<V:16/big>>).
  38. -define(uint16(V), <<V:16/big>>).
  39. -define(int32(V), <<V:32/big>>).
  40. -define(uint32(V), <<V:32/big>>).
  41. -define(int64(V), <<V:64/big>>).
  42. -define(uint64(V), <<V:64/big>>).
  43. -define(integer(V), (integer(V))).
  44. -define(number(V), (number(V))).
  45. -define(string(V), (string(V))).
  46. -define(float(V), <<V:32/big-float>>).
  47. -define(double(V), <<V:64/big-float>>).
  48. -define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)).
  49. -define(record(V), (case V of undefined -> [<<0:8>>]; V -> [<<1:8>>, encodeRec(V)] end)).
  50. -define(list_bool(List), [<<(length(List)):16/big>>, [?bool(V) || V <- List]]).
  51. -define(list_int8(List), [<<(length(List)):16/big>>, [?int8(V) || V <- List]]).
  52. -define(list_uint8(List), [<<(length(List)):16/big>>, [?uint8(V) || V <- List]]).
  53. -define(list_int16(List), [<<(length(List)):16/big>>, [?int16(V) || V <- List]]).
  54. -define(list_uint16(List), [<<(length(List)):16/big>>, [?uint16(V) || V <- List]]).
  55. -define(list_int32(List), [<<(length(List)):16/big>>, [?int32(V) || V <- List]]).
  56. -define(list_uint32(List), [<<(length(List)):16/big>>, [?uint32(V) || V <- List]]).
  57. -define(list_int64(List), [<<(length(List)):16/big>>, [?int64(V) || V <- List]]).
  58. -define(list_uint64(List), [<<(length(List)):16/big>>, [?uint64(V) || V <- List]]).
  59. -define(list_float(List), [<<(length(List)):16/big>>, [?float(V) || V <- List]]).
  60. -define(list_double(List), [<<(length(List)):16/big>>, [?double(V) || V <- List]]).
  61. -define(list_integer(List), [<<(length(List)):16/big>>, [integer(V) || V <- List]]).
  62. -define(list_number(List), [<<(length(List)):16/big>>, [number(V) || V <- List]]).
  63. -define(list_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]).
  64. -define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]).
  65. integer(V) ->
  66. if
  67. V >= ?min8 andalso V =< ?max8 ->
  68. <<8:8, <<V:8>>/binary>>;
  69. V >= ?min16 andalso V =< ?max16 ->
  70. <<16:8, <<V:16/big>>/binary>>;
  71. V >= ?min32 andalso V =< ?max32 ->
  72. <<32:8, <<V:32/big>>/binary>>;
  73. V >= ?min64 andalso V =< ?max64 ->
  74. <<64:8, <<V:64/big>>/binary>>;
  75. true ->
  76. throw(exceeded_the_integer)
  77. end.
  78. number(V) ->
  79. if
  80. erlang:is_integer(V) ->
  81. if
  82. V >= ?min8 andalso V =< ?max8 ->
  83. <<8:8, <<V:8>>/binary>>;
  84. V >= ?min16 andalso V =< ?max16 ->
  85. <<16:8, <<V:16/big>>/binary>>;
  86. V >= ?min32 andalso V =< ?max32 ->
  87. <<32:8, <<V:32/big>>/binary>>;
  88. V >= ?min64 andalso V =< ?max64 ->
  89. <<64:8, <<V:64/big>>/binary>>;
  90. true ->
  91. throw(exceeded_the_integer)
  92. end;
  93. erlang:is_float(V) ->
  94. if
  95. V >= ?minF32 andalso V =< ?maxF32 ->
  96. <<33:8, <<V:32/big-float>>/binary>>;
  97. V >= ?minF64 andalso V =< ?maxF64 ->
  98. <<65:8, <<V:64/big-float>>/binary>>;
  99. true ->
  100. throw(exceeded_the_float)
  101. end;
  102. true ->
  103. throw(is_not_number)
  104. end.
  105. string(Str) when is_binary(Str) ->
  106. [<<(byte_size(Str)):16/big>>, Str];
  107. string(Str) ->
  108. Str2 = unicode:characters_to_binary(Str, utf8),
  109. [<<(byte_size(Str2)):16/big>>, Str2].
  110. decode(Bin) ->
  111. <<MsgId:16/big, MsgBin/binary>> = Bin,
  112. decodeBin(MsgId, MsgBin).
  113. deBoolList(0, MsgBin, RetList) ->
  114. {lists:reverse(RetList), MsgBin};
  115. deBoolList(N, MsgBin, RetList) ->
  116. <<Bool:8, LeftBin/binary>> = MsgBin,
  117. case Bool =:= 1 of
  118. true ->
  119. deBoolList(N - 1, LeftBin, [true | RetList]);
  120. _ ->
  121. deBoolList(N - 1, LeftBin, [false | RetList])
  122. end.
  123. deInt8List(0, MsgBin, RetList) ->
  124. {RetList, MsgBin};
  125. deInt8List(N, MsgBin, RetList) ->
  126. <<Int:8/big-signed, LeftBin/binary>> = MsgBin,
  127. deInt8List(N - 1, LeftBin, [Int | RetList]).
  128. deUint8List(0, MsgBin, RetList) ->
  129. {lists:reverse(RetList), MsgBin};
  130. deUint8List(N, MsgBin, RetList) ->
  131. <<Int:8/big-unsigned, LeftBin/binary>> = MsgBin,
  132. deUint8List(N - 1, LeftBin, [Int | RetList]).
  133. deInt16List(0, MsgBin, RetList) ->
  134. {lists:reverse(RetList), MsgBin};
  135. deInt16List(N, MsgBin, RetList) ->
  136. <<Int:16/big-signed, LeftBin/binary>> = MsgBin,
  137. deInt16List(N - 1, LeftBin, [Int | RetList]).
  138. deUint16List(0, MsgBin, RetList) ->
  139. {lists:reverse(RetList), MsgBin};
  140. deUint16List(N, MsgBin, RetList) ->
  141. <<Int:16/big-unsigned, LeftBin/binary>> = MsgBin,
  142. deUint16List(N - 1, LeftBin, [Int | RetList]).
  143. deInt32List(0, MsgBin, RetList) ->
  144. {lists:reverse(RetList), MsgBin};
  145. deInt32List(N, MsgBin, RetList) ->
  146. <<Int:32/big-signed, LeftBin/binary>> = MsgBin,
  147. deInt32List(N - 1, LeftBin, [Int | RetList]).
  148. deUint32List(0, MsgBin, RetList) ->
  149. {lists:reverse(RetList), MsgBin};
  150. deUint32List(N, MsgBin, RetList) ->
  151. <<Int:32/big-unsigned, LeftBin/binary>> = MsgBin,
  152. deUint32List(N - 1, LeftBin, [Int | RetList]).
  153. deInt64List(0, MsgBin, RetList) ->
  154. {lists:reverse(RetList), MsgBin};
  155. deInt64List(N, MsgBin, RetList) ->
  156. <<Int:64/big-signed, LeftBin/binary>> = MsgBin,
  157. deInt64List(N - 1, LeftBin, [Int | RetList]).
  158. deUint64List(0, MsgBin, RetList) ->
  159. {lists:reverse(RetList), MsgBin};
  160. deUint64List(N, MsgBin, RetList) ->
  161. <<Int:64/big-unsigned, LeftBin/binary>> = MsgBin,
  162. deUint64List(N - 1, LeftBin, [Int | RetList]).
  163. deIntegerList(0, MsgBin, RetList) ->
  164. {lists:reverse(RetList), MsgBin};
  165. deIntegerList(N, MsgBin, RetList) ->
  166. <<IntBits:8, Int:IntBits/big-signed, LeftBin/binary>> = MsgBin,
  167. deIntegerList(N - 1, LeftBin, [Int | RetList]).
  168. deNumberList(0, MsgBin, RetList) ->
  169. {lists:reverse(RetList), MsgBin};
  170. deNumberList(N, MsgBin, RetList) ->
  171. <<NumBits:8, NumBin/binary>> = MsgBin,
  172. case NumBits of
  173. 33 ->
  174. <<Float:32/big-float, LeftBin/binary>> = NumBin,
  175. deNumberList(N - 1, LeftBin, [Float | RetList]);
  176. 65 ->
  177. <<Float:64/big-float, LeftBin/binary>> = NumBin,
  178. deNumberList(N - 1, LeftBin, [Float | RetList]);
  179. _ ->
  180. <<Int:NumBits/big-signed, LeftBin/binary>> = NumBin,
  181. deNumberList(N - 1, LeftBin, [Int | RetList])
  182. end.
  183. deFloatList(0, MsgBin, RetList) ->
  184. {lists:reverse(RetList), MsgBin};
  185. deFloatList(N, MsgBin, RetList) ->
  186. <<Float:32/big-float, LeftBin/binary>> = MsgBin,
  187. deFloatList(N - 1, LeftBin, [Float | RetList]).
  188. deDoubleList(0, MsgBin, RetList) ->
  189. {lists:reverse(RetList), MsgBin};
  190. deDoubleList(N, MsgBin, RetList) ->
  191. <<Float:64/big-float, LeftBin/binary>> = MsgBin,
  192. deDoubleList(N - 1, LeftBin, [Float | RetList]).
  193. deStringList(0, MsgBin, RetList) ->
  194. {lists:reverse(RetList), MsgBin};
  195. deStringList(N, MsgBin, RetList) ->
  196. <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>> = MsgBin,
  197. deStringList(N - 1, LeftBin, [StrBin | RetList]).
  198. deRecordList(0, _MsgId, MsgBin, RetList) ->
  199. {lists:reverse(RetList), MsgBin};
  200. deRecordList(N, MsgId, MsgBin, RetList) ->
  201. {Tuple, LeftBin} = decodeRec(MsgId, MsgBin),
  202. deRecordList(N - 1, MsgId, LeftBin, [Tuple | RetList]).\n\n".
  203. genMsgHrl(FieldInfo, {Index, Len, AccList}) ->
  204. TemStr =
  205. case Index of
  206. 1 ->
  207. "";
  208. _ ->
  209. ", "
  210. end,
  211. RecStr = TemStr ++ protoField:builtRecStr(FieldInfo) ++ (case Index == Len of true -> ""; _ -> "\t" end),
  212. {Index - 1, Len, [RecStr | AccList]}.
  213. genErrCodeHrl({ErrName, ErrCodeId, ComDesc}, AccList) ->
  214. Str = "-define(" ++ ErrName ++ ", " ++ integer_to_list(ErrCodeId) ++ ").\t\t%% " ++ ComDesc ++ "\n",
  215. [Str | AccList].
  216. genEncodeRec({MsgName, MsgId, FieldList}, IsForBin) ->
  217. FieldLen = length(FieldList),
  218. FunHead =
  219. fun(_, {Index, StrAcc}) ->
  220. {Index - 1, ", V" ++ integer_to_list(Index) ++ StrAcc}
  221. end,
  222. {_, TemStr} = lists:foldr(FunHead, {FieldLen, "}) ->\n\t"}, FieldList),
  223. HeadStr =
  224. case IsForBin of
  225. true ->
  226. "encode({" ++ MsgName ++ TemStr;
  227. _ ->
  228. "encodeRec({" ++ MsgName ++ TemStr
  229. end,
  230. FunBody =
  231. fun({FieldType, _FieldName}, {Index, PStrAcc}) ->
  232. TemV = "V" ++ integer_to_list(Index),
  233. PackStr = protoField:builtPackStr(FieldType) ++ TemV ++ ")",
  234. case Index == 1 of
  235. true ->
  236. {Index - 1, PackStr ++ PStrAcc};
  237. _ ->
  238. {Index - 1, ", " ++ PackStr ++ PStrAcc}
  239. end
  240. end,
  241. {_, BodyStr} = lists:foldr(FunBody, {FieldLen, ""}, FieldList),
  242. case IsForBin of
  243. true ->
  244. case FieldLen > 0 of
  245. true ->
  246. HeadStr ++ "[<<" ++ integer_to_list(MsgId) ++ ":16/big-unsigned>>, " ++ BodyStr ++ "];\n";
  247. _ ->
  248. HeadStr ++ "[<<" ++ integer_to_list(MsgId) ++ ":16/big-unsigned>>];\n"
  249. end;
  250. _ ->
  251. case FieldLen > 0 of
  252. true ->
  253. HeadStr ++ "[" ++ BodyStr ++ "];\n";
  254. _ ->
  255. HeadStr ++ "[];\n"
  256. end
  257. end.
  258. resetPd() ->
  259. erlang:put(pd_v, 0),
  260. erlang:put(pd_len, 0),
  261. erlang:put(pd_bool, 0),
  262. erlang:put(pd_leftBin, 0),
  263. erlang:put(pd_intBits, 0),
  264. erlang:put(pd_numBits, 0),
  265. erlang:put(pd_isUndef, 0).
  266. getIndexStr(Type) ->
  267. Index = erlang:get(Type),
  268. erlang:integer_to_list(Index).
  269. useIndexStr(Type) ->
  270. Index = erlang:get(Type) + 1,
  271. erlang:put(Type, Index),
  272. erlang:integer_to_list(Index).
  273. initSubRec() ->
  274. erlang:put(pd_subRec, []).
  275. getSubRec() ->
  276. erlang:get(pd_subRec).
  277. addSubRec({MsgName, _MsgId, _FieldList} = Info, IsForBin) when IsForBin ->
  278. OldList = erlang:get(pd_subRec),
  279. case lists:keyfind(MsgName, 1, OldList) of
  280. false ->
  281. erlang:put(pd_subRec, [Info | OldList]);
  282. _ ->
  283. ignore
  284. end;
  285. addSubRec(_Info, _IsForBin) ->
  286. ignore.
  287. genDecodeBin({MsgName, MsgId, FieldList}, SortedSProtoList, IsForBin) ->
  288. FieldLen = length(FieldList),
  289. case IsForBin of
  290. true ->
  291. HeadStr = "decodeBin(" ++ integer_to_list(MsgId) ++ ", LeftBin" ++ getIndexStr(pd_leftBin) ++ ") ->\n";
  292. _ ->
  293. HeadStr = "decodeRec(" ++ integer_to_list(MsgId) ++ ", LeftBin" ++ getIndexStr(pd_leftBin) ++ ") ->\n"
  294. end,
  295. FunBody =
  296. fun({FieldType, _FieldName}, {IsSimple, StrAcc}) ->
  297. case FieldType of
  298. "bool" ->
  299. TemStr =
  300. case IsSimple of
  301. true ->
  302. GetLeftBinStr1 = getIndexStr(pd_leftBin),
  303. UseLeftBinStr1 = useIndexStr(pd_leftBin),
  304. "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n";
  305. _ ->
  306. ""
  307. end,
  308. UseBoolStr = useIndexStr(pd_bool),
  309. GetLeftBinStr2 = getIndexStr(pd_leftBin),
  310. UseLeftBinStr2 = useIndexStr(pd_leftBin),
  311. BoolStr = "\t<<Bool" ++ UseBoolStr ++ ":8/big-unsigned, LeftBin" ++ UseLeftBinStr2 ++ "/binary>> = LeftBin" ++ GetLeftBinStr2 ++ ",\n",
  312. UseVStr = useIndexStr(pd_v),
  313. VStr = "\tcase Bool" ++ UseBoolStr ++ " =:= 1 of\n\t\ttrue ->\n\t\t\tV" ++ UseVStr ++" = true;\n\t\t_ ->\n\t\t\tV" ++ UseVStr ++" = false\n\tend,\n",
  314. {false, StrAcc ++ TemStr ++ BoolStr ++ VStr};
  315. "int8" ->
  316. TemStr =
  317. case IsSimple of
  318. true ->
  319. UseVStr = useIndexStr(pd_v),
  320. "V" ++ UseVStr ++ ":8/big-signed, ";
  321. _ ->
  322. UseVStr = useIndexStr(pd_v),
  323. "\t<<V" ++ UseVStr ++ ":8/big-signed, "
  324. end,
  325. {true, StrAcc ++ TemStr};
  326. "uint8" ->
  327. TemStr =
  328. case IsSimple of
  329. true ->
  330. UseVStr = useIndexStr(pd_v),
  331. "V" ++ UseVStr ++ ":8/big-unsigned, ";
  332. _ ->
  333. UseVStr = useIndexStr(pd_v),
  334. "\t<<V" ++ UseVStr ++ ":8/big-unsigned, "
  335. end,
  336. {true, StrAcc ++ TemStr};
  337. "int16" ->
  338. TemStr =
  339. case IsSimple of
  340. true ->
  341. UseVStr = useIndexStr(pd_v),
  342. "V" ++ UseVStr ++ ":16/big-signed, ";
  343. _ ->
  344. UseVStr = useIndexStr(pd_v),
  345. "\t<<V" ++ UseVStr ++ ":16/big-signed, "
  346. end,
  347. {true, StrAcc ++ TemStr};
  348. "uint16" ->
  349. TemStr =
  350. case IsSimple of
  351. true ->
  352. UseVStr = useIndexStr(pd_v),
  353. "V" ++ UseVStr ++ ":16/big-unsigned, ";
  354. _ ->
  355. UseVStr = useIndexStr(pd_v),
  356. "\t<<V" ++ UseVStr ++ ":16/big-unsigned, "
  357. end,
  358. {true, StrAcc ++ TemStr};
  359. "int32" ->
  360. TemStr =
  361. case IsSimple of
  362. true ->
  363. UseVStr = useIndexStr(pd_v),
  364. "V" ++ UseVStr ++ ":32/big-signed, ";
  365. _ ->
  366. UseVStr = useIndexStr(pd_v),
  367. "\t<<V" ++ UseVStr ++ ":32/big-signed, "
  368. end,
  369. {true, StrAcc ++ TemStr};
  370. "uint32" ->
  371. TemStr =
  372. case IsSimple of
  373. true ->
  374. UseVStr = useIndexStr(pd_v),
  375. "V" ++ UseVStr ++ ":32/big-unsigned, ";
  376. _ ->
  377. UseVStr = useIndexStr(pd_v),
  378. "\t<<V" ++ UseVStr ++ ":32/big-unsigned, "
  379. end,
  380. {true, StrAcc ++ TemStr};
  381. "int64" ->
  382. TemStr =
  383. case IsSimple of
  384. true ->
  385. UseVStr = useIndexStr(pd_v),
  386. "V" ++ UseVStr ++ ":64/big-signed, ";
  387. _ ->
  388. UseVStr = useIndexStr(pd_v),
  389. "\t<<V" ++ UseVStr ++ ":64/big-signed, "
  390. end,
  391. {true, StrAcc ++ TemStr};
  392. "uint64" ->
  393. TemStr =
  394. case IsSimple of
  395. true ->
  396. UseVStr = useIndexStr(pd_v),
  397. "V" ++ UseVStr ++ ":64/big-unsigned, ";
  398. _ ->
  399. UseVStr = useIndexStr(pd_v),
  400. "\t<<V" ++ UseVStr ++ ":64/big-unsigned, "
  401. end,
  402. {true, StrAcc ++ TemStr};
  403. "float" ->
  404. TemStr =
  405. case IsSimple of
  406. true ->
  407. UseVStr = useIndexStr(pd_v),
  408. "V" ++ UseVStr ++ ":32/big-float, ";
  409. _ ->
  410. UseVStr = useIndexStr(pd_v),
  411. "\t<<V" ++ UseVStr ++ ":32/big-float, "
  412. end,
  413. {true, StrAcc ++ TemStr};
  414. "double" ->
  415. TemStr =
  416. case IsSimple of
  417. true ->
  418. UseVStr = useIndexStr(pd_v),
  419. "V" ++ UseVStr ++ ":64/big-float, ";
  420. _ ->
  421. UseVStr = useIndexStr(pd_v),
  422. "\t<<V" ++ UseVStr ++ ":64/big-float, "
  423. end,
  424. {true, StrAcc ++ TemStr};
  425. "string" ->
  426. TemStr =
  427. case IsSimple of
  428. true ->
  429. GetLeftBinStr1 = getIndexStr(pd_leftBin),
  430. UseLeftBinStr1 = useIndexStr(pd_leftBin),
  431. "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n";
  432. _ ->
  433. ""
  434. end,
  435. UseLenStr = useIndexStr(pd_len),
  436. GetLeftBinStr2 = getIndexStr(pd_leftBin),
  437. UseLeftBinStr2 = useIndexStr(pd_leftBin),
  438. UseVStr = useIndexStr(pd_v),
  439. StrStr = "\t<<Len" ++ UseLenStr ++ ":16/big-unsigned, V" ++ UseVStr ++ ":Len" ++ UseLenStr ++ "/binary, LeftBin" ++ UseLeftBinStr2 ++ "/binary>> = LeftBin" ++ GetLeftBinStr2 ++ ",\n",
  440. {false, StrAcc ++ TemStr ++ StrStr};
  441. "integer" ->
  442. TemStr =
  443. case IsSimple of
  444. true ->
  445. UseVStr = useIndexStr(pd_v),
  446. UseIntBitsStr = useIndexStr(pd_intBits),
  447. "IntBits" ++ UseIntBitsStr ++ ":8, " ++ "V" ++ UseVStr ++ ":IntBits" ++ UseIntBitsStr ++ "/big-signed, ";
  448. _ ->
  449. UseVStr = useIndexStr(pd_v),
  450. UseIntBitsStr = useIndexStr(pd_intBits),
  451. "\t<<IntBits" ++ UseIntBitsStr ++ ":8, " ++ "V" ++ UseVStr ++ ":IntBits" ++ UseIntBitsStr ++ "/big-signed, "
  452. end,
  453. {true, StrAcc ++ TemStr};
  454. "number" ->
  455. TemStr =
  456. case IsSimple of
  457. true ->
  458. GetLeftBinStr1 = getIndexStr(pd_leftBin),
  459. UseLeftBinStr1 = useIndexStr(pd_leftBin),
  460. "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n";
  461. _ ->
  462. ""
  463. end,
  464. UseNumBitsStr = useIndexStr(pd_numBits),
  465. GetLeftBinStr2 = getIndexStr(pd_leftBin),
  466. UseLeftBinStr2 = useIndexStr(pd_leftBin),
  467. NumStr = "\t<<NumBits" ++ UseNumBitsStr ++ ":8, LeftBin" ++ UseLeftBinStr2 ++ "/binary>> = LeftBin" ++ GetLeftBinStr2 ++ ",\n",
  468. UseVStr = useIndexStr(pd_v),
  469. UseLeftBinStr3 = useIndexStr(pd_leftBin),
  470. VStr =
  471. "\tcase NumBits" ++ UseNumBitsStr ++ " of\n\t\t33-> \n\t\t\t<<V" ++ UseVStr ++ ":32/big-float, LeftBin" ++ UseLeftBinStr3 ++ "/binary>> = LeftBin" ++ UseLeftBinStr2 ++
  472. ";\n\t\t65 ->\n\t\t\t<<V" ++ UseVStr ++ ":64/big-float, LeftBin" ++ UseLeftBinStr3 ++ "/binary>> = LeftBin" ++ UseLeftBinStr2 ++
  473. ";\n\t\t_ ->\n\t\t\t<<V" ++ UseVStr ++ ":NumBits" ++ UseNumBitsStr ++ "/big-signed, LeftBin" ++ UseLeftBinStr3 ++ "/binary>> = LeftBin" ++ UseLeftBinStr2 ++ "\n\tend,\n",
  474. {false, StrAcc ++ TemStr ++ NumStr ++ VStr};
  475. "list[" ++ LeftStr ->
  476. [SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]),
  477. TemStr =
  478. case IsSimple of
  479. true ->
  480. GetLeftBinStr1 = getIndexStr(pd_leftBin),
  481. UseLeftBinStr1 = useIndexStr(pd_leftBin),
  482. "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n";
  483. _ ->
  484. ""
  485. end,
  486. UseLenStr = useIndexStr(pd_len),
  487. GetLeftBinStr2 = getIndexStr(pd_leftBin),
  488. UseLeftBinStr2 = useIndexStr(pd_leftBin),
  489. UseVStr = useIndexStr(pd_v),
  490. UseLeftBinStr3 = useIndexStr(pd_leftBin),
  491. LenStr = "\t<<Len" ++ UseLenStr ++ ":16/big-unsigned, LeftBin" ++ UseLeftBinStr2 ++ "/binary>> = LeftBin" ++ GetLeftBinStr2 ++ ",\n",
  492. DeListStr =
  493. case SubTypeStr of
  494. "bool" ->
  495. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deBoolList(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  496. "int8" ->
  497. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deInt8List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  498. "uint8" ->
  499. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deUint8List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  500. "int16" ->
  501. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deInt16List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  502. "uint16" ->
  503. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deUint16List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  504. "int32" ->
  505. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deInt32List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  506. "uint32" ->
  507. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deUint32List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  508. "int64" ->
  509. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deInt64List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  510. "uint64" ->
  511. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deUint64List(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  512. "integer" ->
  513. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deIntegerList(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  514. "number" ->
  515. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deNumberList(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  516. "float" ->
  517. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deFloatList(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  518. "double" ->
  519. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deDoubleList(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  520. "string" ->
  521. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deStringList(Len" ++ UseLenStr ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  522. ListRecord ->
  523. case lists:keyfind(ListRecord, 1, SortedSProtoList) of
  524. {ListRecord, ListMsgId, _} = RecordInfo ->
  525. addSubRec(RecordInfo, IsForBin),
  526. "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deRecordList(Len" ++ UseLenStr ++ ", " ++ integer_to_list(ListMsgId) ++ ", LeftBin" ++ UseLeftBinStr2 ++ ", []),\n";
  527. _ ->
  528. io:format("this an Record undefined :~p~n", [ListRecord]),
  529. throw(record_undefined)
  530. end
  531. end,
  532. {false, StrAcc ++ TemStr ++ LenStr ++ DeListStr};
  533. OtherRecord ->
  534. TemStr =
  535. case IsSimple of
  536. true ->
  537. GetLeftBinStr1 = getIndexStr(pd_leftBin),
  538. UseLeftBinStr1 = useIndexStr(pd_leftBin),
  539. "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n";
  540. _ ->
  541. ""
  542. end,
  543. UseIsUndefStr = useIndexStr(pd_isUndef),
  544. GetLeftBinStr2 = getIndexStr(pd_leftBin),
  545. UseLeftBinStr2 = useIndexStr(pd_leftBin),
  546. IsStr = "\t<<IsUndef" ++ UseIsUndefStr ++ ":8/big-unsigned, LeftBin" ++ UseLeftBinStr2 ++ "/binary>> = LeftBin" ++ GetLeftBinStr2 ++ ",\n",
  547. UseVStr = useIndexStr(pd_v),
  548. UseLeftBinStr3 = useIndexStr(pd_leftBin),
  549. case lists:keyfind(OtherRecord, 1, SortedSProtoList) of
  550. {OtherRecord, OtherMsgId, _} = RecordInfo ->
  551. addSubRec(RecordInfo, IsForBin),
  552. VStr = "\tcase IsUndef" ++ UseIsUndefStr ++ " of\n\t\t0 ->\n\t\t\tV" ++ UseVStr ++ " = undefined,\n\t\t\tLeftBin" ++ UseLeftBinStr3 ++ " = LeftBin" ++ UseLeftBinStr2 ++
  553. " ;\n\t\t_ ->\n\t\t\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = " ++ "decodeRec(" ++ integer_to_list(OtherMsgId) ++ ", LeftBin" ++ UseLeftBinStr2 ++ ")\n\tend,\n",
  554. {false, StrAcc ++ TemStr ++ IsStr ++ VStr};
  555. _ ->
  556. io:format("this an Record undefined :~p~n", [OtherRecord]),
  557. throw(record_undefined)
  558. end
  559. end
  560. end,
  561. {LIsSimple, BodyStr} = lists:foldl(FunBody, {false, ""}, FieldList),
  562. LBodyStr =
  563. case LIsSimple of
  564. true ->
  565. LGetLeftBinStr = getIndexStr(pd_leftBin),
  566. LUseLeftBinStr = useIndexStr(pd_leftBin),
  567. BodyStr ++ "LeftBin" ++ LUseLeftBinStr ++ "/binary>> = LeftBin" ++ LGetLeftBinStr ++ ",\n";
  568. _ ->
  569. BodyStr
  570. end,
  571. RetStr =
  572. case IsForBin of
  573. true ->
  574. case FieldLen > 0 of
  575. true ->
  576. FunRec =
  577. fun(N, Acc) ->
  578. ", V" ++ integer_to_list(N) ++ Acc
  579. end,
  580. RecStr = lists:foldr(FunRec, "", lists:seq(1, FieldLen)),
  581. "\t{" ++ MsgName ++ RecStr ++ "};\n";
  582. _ ->
  583. "\t{" + MsgName ++ "};\n"
  584. end;
  585. _ ->
  586. case FieldLen > 0 of
  587. true ->
  588. FunRec =
  589. fun(N, Acc) ->
  590. ", V" ++ integer_to_list(N) ++ Acc
  591. end,
  592. RecStr = lists:foldr(FunRec, "", lists:seq(1, FieldLen)),
  593. "\tMsgRec = {" ++ MsgName ++ RecStr ++ "},\n"
  594. "\t{MsgRec, LeftBin" ++ getIndexStr(pd_leftBin) ++ "};\n";
  595. _ ->
  596. "\t{{" + MsgName ++ "}, " ++ "<<>>};\n"
  597. end
  598. end,
  599. HeadStr ++ LBodyStr ++ RetStr.
  600. convertFile(File) ->
  601. protoParse:parseFile(File).
  602. convert([ProtoDir, HrlDir, ErlDir]) ->
  603. convertDir(atom_to_list(ProtoDir), atom_to_list(HrlDir), atom_to_list(ErlDir)).
  604. convertDir() ->
  605. convertDir("./", "./", "./").
  606. convertDir(ProtoDir) ->
  607. convertDir(ProtoDir, "./", "./").
  608. convertDir(ProtoDir, HrlDir, ErlDir) ->
  609. erlang:put(pd_errlist, []),
  610. FunRead =
  611. fun(File, ProAcc) ->
  612. case filename:extension(File) == ".mpdf" of
  613. true ->
  614. io:format("Convert proto msg file: ~s ~n", [File]),
  615. BaseName = filename:basename(File, ".mpdf"),
  616. [ModIndex | _ModName] = re:split(BaseName, "_"),
  617. Index = binary_to_integer(ModIndex),
  618. erlang:put(pd_messageid, Index * 1000 + 1),
  619. erlang:put(pd_errcodeid, Index * 1000 + 1),
  620. SProto = protoParse:parseFile(File),
  621. ErrCode = erlang:get(pd_errlist),
  622. erlang:erase(),
  623. erlang:put(pd_errlist, ErrCode),
  624. [SProto | ProAcc];
  625. _ ->
  626. ProAcc
  627. end
  628. end,
  629. %% 下面文件帅选并不能准确的帅选出文件名为.mpdf结尾的文件 在FunRead函数中纠正处理一下
  630. SProtoListOfList = filelib:fold_files(ProtoDir, "\\.mpdf", true, FunRead, []),
  631. SProtoList = lists:append(SProtoListOfList),
  632. ErrCodeList = erlang:get(pd_errlist),
  633. initSubRec(),
  634. SortedSProtoList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) ->
  635. MessageId1 > MessageId2 end, SProtoList),
  636. FunSpell =
  637. fun({MsgName, _MsgId, FieldList} = MsgInfo, {MsgHrlAcc, _MsgIdAcc, MsgEncodeAcc, MsgDecodeAcc}) ->
  638. %% gen hrl str
  639. Len = erlang:length(FieldList),
  640. {_, Len, LastFieldStr} = lists:foldr(fun genMsgHrl/2, {Len, Len, ""}, FieldList),
  641. HrlStr = "-record(" ++ MsgName ++ " ,{\n\t" ++ LastFieldStr ++ "}).\n",
  642. %% gen getMsgId getMsgType str
  643. %% TypeStr = "getMsgType(" ++ integer_to_list(MsgId) ++ ")-> " ++ MsgName ++ ";\n",
  644. %% IdStr = "getMsgId(" ++ MsgName ++ ")-> " ++ integer_to_list(MsgId) ++ ";\n",
  645. %% gen encodeRec Str
  646. EncodeStr = genEncodeRec(MsgInfo, true),
  647. %% gen decodeBin str
  648. resetPd(),
  649. DecodeStr = genDecodeBin(MsgInfo, SortedSProtoList, true),
  650. {[HrlStr | MsgHrlAcc], ["Unuse"], [EncodeStr | MsgEncodeAcc], [DecodeStr | MsgDecodeAcc]}
  651. end,
  652. {MsgHrlStr, _MsgIdStr, MsgEncodeStr, MsgDecodeStr} = lists:foldl(FunSpell, {[], ["getMsgId(_) -> 0.\n\n"], ["encode(_) ->\n\t[].\n\n"], ["decodeBin(_, _) ->\n\t{{}, <<>>}.\n\n"]}, SortedSProtoList),
  653. SortedErrList = lists:sort(fun({_ErrName1, ErrCodeId1, _Desc1}, {_ErrName2, ErrCodeId2, _Desc2}) ->
  654. ErrCodeId1 > ErrCodeId2 end, ErrCodeList),
  655. ErrCodeStr = lists:foldl(fun genErrCodeHrl/2, [], SortedErrList) ++ "\n\n",
  656. %% gen decodeRec str
  657. SubRecList = getSubRec(),
  658. SortedSubRecList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) ->
  659. MessageId1 > MessageId2 end, SubRecList),
  660. FunSubRec =
  661. fun(MsgInfo, {SubEncodeAcc, SubDecodeAcc}) ->
  662. EncodeStr = genEncodeRec(MsgInfo, false),
  663. resetPd(),
  664. DecodeStr = genDecodeBin(MsgInfo, SortedSProtoList, false),
  665. {[EncodeStr |SubEncodeAcc], [DecodeStr | SubDecodeAcc]}
  666. end,
  667. {MsgEncodeRecStr, MsgDecodeRecStr} = lists:foldl(FunSubRec, {["encodeRec(_) ->\n\t[].\n\n"], ["decodeRec(_, _) ->\n\t{{}, <<>>}.\n\n"]}, SortedSubRecList),
  668. ErlHeaderStr = protoErlHeader(),
  669. OutputStr = ErlHeaderStr ++ MsgEncodeRecStr ++ MsgEncodeStr ++ MsgDecodeRecStr ++ MsgDecodeStr,
  670. HrlFilename = do_write_hrl(HrlDir, protoMsg, protoHrlHeader() ++ ErrCodeStr ++ MsgHrlStr),
  671. ErlFilename = do_write_erl(ErlDir, protoMsg, OutputStr),
  672. io:format("protoConvert hrl dir : ~s ~n", [HrlDir]),
  673. io:format("protoConvert erl dir : ~s ~n", [ErlDir]),
  674. io:format("protoConvert to hrl file ~s succ.~n", [HrlFilename]),
  675. io:format("protoConvert to erl file ~s succ.~n", [ErlFilename]),
  676. ok.
  677. do_write_hrl(OutDir, Mod, Str) when is_list(OutDir) ->
  678. Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".hrl"]),
  679. ok = file:write_file(Filename, Str),
  680. Filename.
  681. do_write_erl(OutDir, Mod, Str) when is_list(OutDir) ->
  682. Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".erl"]),
  683. ok = file:write_file(Filename, Str),
  684. Filename.