erlang自定义二进制协议
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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