-module(protoGen). -export([ convertFile/1 , convert/1 , convertDir/0 , convertDir/1 , convertDir/3 ]). protoHrlHeader() -> "-opaque int8() :: -128..127. -opaque int16() :: -32768..32767. -opaque int32() :: -2147483648..2147483647. -opaque int64() :: -9223372036854775808..9223372036854775807. -opaque uint8() :: 0..255. -opaque uint16() :: 0..65536. -opaque uint32() :: 0..4294967295. -opaque uint64() :: 0..18446744073709551615. -opaque double() :: float().\n\n". protoErlHeader() -> "-module(protoMsg).\n\n -compile([nowarn_unused_vars]). -export([encode/1, decode/1, encodeRec/1, decodeBin/2]). -define(min8, -128). -define(max8, 127). -define(min16, -32768). -define(max16, 32767). -define(min32, -2147483648). -define(max32, 2147483647). -define(min64, -9223372036854775808). -define(max64, 9223372036854775807). -define(minF32, -3.4E+38). -define(maxF32, 3.4E+38). -define(minF64, -1.797E-308). -define(maxF64, 1.797E+308). -define(int8(V), <>). -define(uint8(V), <>). -define(int16(V), <>). -define(uint16(V), <>). -define(int32(V), <>). -define(uint32(V), <>). -define(int64(V), <>). -define(uint64(V), <>). -define(integer(V), (integer(V))). -define(number(V), (number(V))). -define(string(V), (string(V))). -define(float(V), <>). -define(double(V), <>). -define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)). -define(record(V), (case V of undefined -> [<<0:8>>]; V -> [<<1:8>>, encodeRec(V)] end)). -define(list_bool(List), [<<(length(List)):16/big>>, [?bool(V) || V <- List]]). -define(list_int8(List), [<<(length(List)):16/big>>, [?int8(V) || V <- List]]). -define(list_uint8(List), [<<(length(List)):16/big>>, [?uint8(V) || V <- List]]). -define(list_int16(List), [<<(length(List)):16/big>>, [?int16(V) || V <- List]]). -define(list_uint16(List), [<<(length(List)):16/big>>, [?uint16(V) || V <- List]]). -define(list_int32(List), [<<(length(List)):16/big>>, [?int32(V) || V <- List]]). -define(list_uint32(List), [<<(length(List)):16/big>>, [?uint32(V) || V <- List]]). -define(list_int64(List), [<<(length(List)):16/big>>, [?int64(V) || V <- List]]). -define(list_uint64(List), [<<(length(List)):16/big>>, [?uint64(V) || V <- List]]). -define(list_float(List), [<<(length(List)):16/big>>, [?float(V) || V <- List]]). -define(list_double(List), [<<(length(List)):16/big>>, [?double(V) || V <- List]]). -define(list_integer(List), [<<(length(List)):16/big>>, [integer(V) || V <- List]]). -define(list_number(List), [<<(length(List)):16/big>>, [number(V) || V <- List]]). -define(list_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]). -define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]). -define(BinaryShareSize, 65). -define(BinaryCopyRatio, 1.2). integer(V) -> if V >= ?min8 andalso V =< ?max8 -> <<8:8, <>/binary>>; V >= ?min16 andalso V =< ?max16 -> <<16:8, <>/binary>>; V >= ?min32 andalso V =< ?max32 -> <<32:8, <>/binary>>; V >= ?min64 andalso V =< ?max64 -> <<64:8, <>/binary>>; true -> throw(exceeded_the_integer) end. number(V) -> if erlang:is_integer(V) -> if V >= ?min8 andalso V =< ?max8 -> <<8:8, <>/binary>>; V >= ?min16 andalso V =< ?max16 -> <<16:8, <>/binary>>; V >= ?min32 andalso V =< ?max32 -> <<32:8, <>/binary>>; V >= ?min64 andalso V =< ?max64 -> <<64:8, <>/binary>>; true -> throw(exceeded_the_integer) end; erlang:is_float(V) -> if V >= ?minF32 andalso V =< ?maxF32 -> <<33:8, <>/binary>>; V >= ?minF64 andalso V =< ?maxF64 -> <<65:8, <>/binary>>; true -> throw(exceeded_the_float) end; true -> throw(is_not_number) end. string(Str) when is_binary(Str) -> [<<(byte_size(Str)):16/big>>, Str]; string(Str) -> Str2 = unicode:characters_to_binary(Str, utf8), [<<(byte_size(Str2)):16/big>>, Str2]. decode(Bin) -> <> = Bin, decodeBin(MsgId, MsgBin). deIntegerList(0, MsgBin, RetList) -> {lists:reverse(RetList), MsgBin}; deIntegerList(N, MsgBin, RetList) -> <> = MsgBin, deIntegerList(N - 1, LeftBin, [Int | RetList]). deNumberList(0, MsgBin, RetList) -> {lists:reverse(RetList), MsgBin}; deNumberList(N, MsgBin, RetList) -> <> = MsgBin, case NumBits of 33 -> <> = NumBin, deNumberList(N - 1, LeftBin, [Float | RetList]); 65 -> <> = NumBin, deNumberList(N - 1, LeftBin, [Float | RetList]); _ -> <> = NumBin, deNumberList(N - 1, LeftBin, [Int | RetList]) end. deStringList(0, MsgBin, _RefSize, RetList) -> {lists:reverse(RetList), MsgBin}; deStringList(N, MsgBin, RefSize, RetList) -> <> = MsgBin, case Len < ?BinaryShareSize of true -> deStringList(N - 1, LeftBin, RefSize, [StrBin | RetList]); _ -> case RefSize / Len > ?BinaryCopyRatio of true -> StrBinCopy = binary:copy(StrBin), deStringList(N - 1, LeftBin, RefSize, [StrBinCopy | RetList]); _ -> deStringList(N - 1, LeftBin, RefSize, [StrBin | RetList]) end end. deRecordList(0, _MsgId, MsgBin, RetList) -> {lists:reverse(RetList), MsgBin}; deRecordList(N, MsgId, MsgBin, RetList) -> {Tuple, LeftBin} = decodeRec(MsgId, MsgBin), deRecordList(N - 1, MsgId, LeftBin, [Tuple | RetList]).\n\n". genMsgHrl(FieldInfo, {Index, Len, AccList}) -> TemStr = case Index of 1 -> ""; _ -> ", " end, RecStr = TemStr ++ protoField:builtRecStr(FieldInfo) ++ (case Index == Len of true -> ""; _ -> "\t" end), {Index - 1, Len, [RecStr | AccList]}. genErrCodeHrl({ErrName, ErrCodeId, ComDesc}, AccList) -> Str = "-define(" ++ ErrName ++ ", " ++ integer_to_list(ErrCodeId) ++ ").\t\t%% " ++ ComDesc ++ "\n", [Str | AccList]. genEncodeRec({MsgName, MsgId, FieldList}, IsForBin) -> FieldLen = length(FieldList), FunHead = fun(_, {Index, StrAcc}) -> {Index - 1, ", V" ++ integer_to_list(Index) ++ StrAcc} end, {_, TemStr} = lists:foldr(FunHead, {FieldLen, "}) ->\n\t"}, FieldList), HeadStr = case IsForBin of true -> "encode({" ++ MsgName ++ TemStr; _ -> "encodeRec({" ++ MsgName ++ TemStr end, FunBody = fun({FieldType, _FieldName}, {Index, PStrAcc}) -> TemV = "V" ++ integer_to_list(Index), PackStr = protoField:builtPackStr(FieldType) ++ TemV ++ ")", case Index == 1 of true -> {Index - 1, PackStr ++ PStrAcc}; _ -> {Index - 1, ", " ++ PackStr ++ PStrAcc} end end, {_, BodyStr} = lists:foldr(FunBody, {FieldLen, ""}, FieldList), case IsForBin of true -> case FieldLen > 0 of true -> HeadStr ++ "[<<" ++ integer_to_list(MsgId) ++ ":16/big-unsigned>>, " ++ BodyStr ++ "];\n"; _ -> HeadStr ++ "[<<" ++ integer_to_list(MsgId) ++ ":16/big-unsigned>>];\n" end; _ -> case FieldLen > 0 of true -> HeadStr ++ "[" ++ BodyStr ++ "];\n"; _ -> HeadStr ++ "[];\n" end end. resetPd() -> erlang:put(pd_v, 0), erlang:put(pd_len, 0), erlang:put(pd_bool, 0), erlang:put(pd_leftBin, 0), erlang:put(pd_intBits, 0), erlang:put(pd_numBits, 0), erlang:put(pd_listBin, 0), erlang:put(pd_isUndef, 0), erlang:put(pd_isCalcRefSize, 0). getIndexStr(Type) -> Index = erlang:get(Type), erlang:integer_to_list(Index). useIndexStr(Type) -> Index = erlang:get(Type) + 1, erlang:put(Type, Index), erlang:integer_to_list(Index). isCalcRefSize() -> erlang:get(pd_isCalcRefSize) > 0. initSubRec() -> erlang:put(pd_subRec, []). getSubRec() -> erlang:get(pd_subRec). addSubRec({MsgName, _MsgId, _FieldList} = Info, IsForBin) when IsForBin -> OldList = erlang:get(pd_subRec), case lists:keyfind(MsgName, 1, OldList) of false -> erlang:put(pd_subRec, [Info | OldList]); _ -> ignore end; addSubRec(_Info, _IsForBin) -> ignore. genDecodeBin({MsgName, MsgId, FieldList}, SortedSProtoList, IsForBin) -> FieldLen = length(FieldList), case IsForBin of true -> HeadStr = "decodeBin(" ++ integer_to_list(MsgId) ++ ", LeftBin" ++ getIndexStr(pd_leftBin) ++ ") ->\n"; _ -> HeadStr = "decodeRec(" ++ integer_to_list(MsgId) ++ ", LeftBin" ++ getIndexStr(pd_leftBin) ++ ") ->\n" end, FunBody = fun({FieldType, _FieldName}, {IsSimple, StrAcc}) -> case FieldType of "bool" -> TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n"; _ -> "" end, UseBoolStr = useIndexStr(pd_bool), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), BoolStr = "\t<> = LeftBin" ++ GetLeftBinStr2 ++ ",\n", UseVStr = useIndexStr(pd_v), VStr = "\tV" ++ UseVStr ++ " = Bool" ++ UseBoolStr ++ " =:= 1,\n", {false, StrAcc ++ TemStr ++ BoolStr ++ VStr}; "int8" -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":8/big-signed, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":8/big-unsigned, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":16/big-signed, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":16/big-unsigned, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":32/big-signed, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":32/big-unsigned, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":64/big-signed, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":64/big-unsigned, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":32/big-float, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), "V" ++ UseVStr ++ ":64/big-float, "; _ -> UseVStr = useIndexStr(pd_v), "\t< TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n"; _ -> "" end, UseLenStr = useIndexStr(pd_len), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), UseVStr = useIndexStr(pd_v), RefSizeStr = case isCalcRefSize() of false -> useIndexStr(pd_isCalcRefSize), "\tRefSize = binary:referenced_byte_size(LeftBin0),\n"; _ -> "" end, StrStr = "\t<> = LeftBin" ++ GetLeftBinStr2 ++ ",\n", VStr = "\tcase Len" ++ UseLenStr ++ " < ?BinaryShareSize of\n\t\t" ++ "true ->\n\t\t\tV" ++ UseVStr ++ " = TemStrV" ++ UseVStr ++ ";\n\t\t" ++ "_ ->\n\t\t\tcase RefSize / Len" ++ UseLenStr ++ " > ?BinaryCopyRatio of\n\t\t\t\t" ++ "true ->\n\t\t\t\t\tV" ++ UseVStr ++ " = binary:copy(TemStrV" ++ UseVStr ++ ");\n\t\t\t\t" ++ "_ ->\n\t\t\t\t\tV" ++ UseVStr ++ " = TemStrV" ++ UseVStr ++ "\n\t\t\tend\n\tend,\n", {false, StrAcc ++ TemStr ++ RefSizeStr ++ StrStr ++ VStr}; "integer" -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), UseIntBitsStr = useIndexStr(pd_intBits), "IntBits" ++ UseIntBitsStr ++ ":8, " ++ "V" ++ UseVStr ++ ":IntBits" ++ UseIntBitsStr ++ "/big-signed, "; _ -> UseVStr = useIndexStr(pd_v), UseIntBitsStr = useIndexStr(pd_intBits), "\t< TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n"; _ -> "" end, UseNumBitsStr = useIndexStr(pd_numBits), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), NumStr = "\t<> = LeftBin" ++ GetLeftBinStr2 ++ ",\n", UseVStr = useIndexStr(pd_v), UseLeftBinStr3 = useIndexStr(pd_leftBin), VStr = "\tcase NumBits" ++ UseNumBitsStr ++ " of\n\t\t33-> \n\t\t\t<> = LeftBin" ++ UseLeftBinStr2 ++ ";\n\t\t65 ->\n\t\t\t<> = LeftBin" ++ UseLeftBinStr2 ++ ";\n\t\t_ ->\n\t\t\t<> = LeftBin" ++ UseLeftBinStr2 ++ "\n\tend,\n", {false, StrAcc ++ TemStr ++ NumStr ++ VStr}; "list[" ++ LeftStr -> [SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]), TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n"; _ -> "" end, UseLenStr = useIndexStr(pd_len), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), UseVStr = useIndexStr(pd_v), UseListBinStr = useIndexStr(pd_listBin), GetLeftBinStr3 = getIndexStr(pd_leftBin), UseLeftBinStr3 = useIndexStr(pd_leftBin), LenStr = "\t<> = LeftBin" ++ GetLeftBinStr2 ++ ",\n", DeListStr = case SubTypeStr of "bool" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV =:= 1 || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "int8" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "uint8" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "int16" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "uint16" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "int32" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "uint32" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "int64" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "uint64" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "integer" -> "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deIntegerList(Len" ++ UseLenStr ++ ", LeftBin" ++ GetLeftBinStr3 ++ ", []),\n"; "number" -> "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deNumberList(Len" ++ UseLenStr ++ ", LeftBin" ++ GetLeftBinStr3 ++ ", []),\n"; "float" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "double" -> ListBinStr = "\t<> = LeftBin" ++ GetLeftBinStr3 ++ ",\n", VStr = "\tV" ++ UseVStr ++ " = [TemV || <> <= ListBin" ++ UseListBinStr ++ "],\n", ListBinStr ++ VStr; "string" -> case isCalcRefSize() of true -> "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deStringList(Len" ++ UseLenStr ++ ", LeftBin" ++ GetLeftBinStr3 ++ ", RefSize, []),\n"; _ -> useIndexStr(pd_isCalcRefSize), RefSizeStr = "\tRefSize = binary:referenced_byte_size(LeftBin0),\n", VStr = "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deStringList(Len" ++ UseLenStr ++ ", LeftBin" ++ GetLeftBinStr3 ++ ", RefSize, []),\n", RefSizeStr ++ VStr end; ListRecord -> case lists:keyfind(ListRecord, 1, SortedSProtoList) of {ListRecord, ListMsgId, _} = RecordInfo -> addSubRec(RecordInfo, IsForBin), "\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = deRecordList(Len" ++ UseLenStr ++ ", " ++ integer_to_list(ListMsgId) ++ ", LeftBin" ++ GetLeftBinStr3 ++ ", []),\n"; _ -> io:format("this an Record undefined :~p~n", [ListRecord]), throw(record_undefined) end end, {false, StrAcc ++ TemStr ++ LenStr ++ DeListStr}; OtherRecord -> TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), "LeftBin" ++ UseLeftBinStr1 ++ "/binary>> = LeftBin" ++ GetLeftBinStr1 ++ ",\n"; _ -> "" end, UseIsUndefStr = useIndexStr(pd_isUndef), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), IsStr = "\t<> = LeftBin" ++ GetLeftBinStr2 ++ ",\n", UseVStr = useIndexStr(pd_v), UseLeftBinStr3 = useIndexStr(pd_leftBin), case lists:keyfind(OtherRecord, 1, SortedSProtoList) of {OtherRecord, OtherMsgId, _} = RecordInfo -> addSubRec(RecordInfo, IsForBin), VStr = "\tcase IsUndef" ++ UseIsUndefStr ++ " of\n\t\t0 ->\n\t\t\tV" ++ UseVStr ++ " = undefined,\n\t\t\tLeftBin" ++ UseLeftBinStr3 ++ " = LeftBin" ++ UseLeftBinStr2 ++ " ;\n\t\t_ ->\n\t\t\t{V" ++ UseVStr ++ ", LeftBin" ++ UseLeftBinStr3 ++ "} = " ++ "decodeRec(" ++ integer_to_list(OtherMsgId) ++ ", LeftBin" ++ UseLeftBinStr2 ++ ")\n\tend,\n", {false, StrAcc ++ TemStr ++ IsStr ++ VStr}; _ -> io:format("this an Record undefined :~p~n", [OtherRecord]), throw(record_undefined) end end end, {LIsSimple, BodyStr} = lists:foldl(FunBody, {false, ""}, FieldList), LBodyStr = case LIsSimple of true -> LGetLeftBinStr = getIndexStr(pd_leftBin), LUseLeftBinStr = useIndexStr(pd_leftBin), BodyStr ++ "LeftBin" ++ LUseLeftBinStr ++ "/binary>> = LeftBin" ++ LGetLeftBinStr ++ ",\n"; _ -> BodyStr end, RetStr = case IsForBin of true -> case FieldLen > 0 of true -> FunRec = fun(N, Acc) -> ", V" ++ integer_to_list(N) ++ Acc end, RecStr = lists:foldr(FunRec, "", lists:seq(1, FieldLen)), "\t{" ++ MsgName ++ RecStr ++ "};\n"; _ -> "\t{" + MsgName ++ "};\n" end; _ -> case FieldLen > 0 of true -> FunRec = fun(N, Acc) -> ", V" ++ integer_to_list(N) ++ Acc end, RecStr = lists:foldr(FunRec, "", lists:seq(1, FieldLen)), "\tMsgRec = {" ++ MsgName ++ RecStr ++ "},\n" "\t{MsgRec, LeftBin" ++ getIndexStr(pd_leftBin) ++ "};\n"; _ -> "\t{{" + MsgName ++ "}, " ++ "<<>>};\n" end end, HeadStr ++ LBodyStr ++ RetStr. convertFile(File) -> protoParse:parseFile(File). convert([ProtoDir, HrlDir, ErlDir]) -> convertDir(atom_to_list(ProtoDir), atom_to_list(HrlDir), atom_to_list(ErlDir)). convertDir() -> convertDir("./", "./", "./"). convertDir(ProtoDir) -> convertDir(ProtoDir, "./", "./"). convertDir(ProtoDir, HrlDir, ErlDir) -> erlang:put(pd_errlist, []), FunRead = fun(File, ProAcc) -> case filename:extension(File) == ".mpdf" of true -> io:format("Convert proto msg file: ~s ~n", [File]), BaseName = filename:basename(File, ".mpdf"), [ModIndex | _ModName] = re:split(BaseName, "_"), Index = binary_to_integer(ModIndex), erlang:put(pd_messageid, Index * 1000 + 1), erlang:put(pd_errcodeid, Index * 1000 + 1), SProto = protoParse:parseFile(File), ErrCode = erlang:get(pd_errlist), erlang:erase(), erlang:put(pd_errlist, ErrCode), [SProto | ProAcc]; _ -> ProAcc end end, %% 下面文件帅选并不能准确的帅选出文件名为.mpdf结尾的文件 在FunRead函数中纠正处理一下 SProtoListOfList = filelib:fold_files(ProtoDir, "\\.mpdf$", true, FunRead, []), SProtoList = lists:append(SProtoListOfList), ErrCodeList = erlang:get(pd_errlist), initSubRec(), SortedSProtoList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) -> MessageId1 > MessageId2 end, SProtoList), FunSpell = fun({MsgName, _MsgId, FieldList} = MsgInfo, {MsgHrlAcc, _MsgIdAcc, MsgEncodeAcc, MsgDecodeAcc}) -> %% gen hrl str Len = erlang:length(FieldList), {_, Len, LastFieldStr} = lists:foldr(fun genMsgHrl/2, {Len, Len, ""}, FieldList), HrlStr = "-record(" ++ MsgName ++ ", {\n\t" ++ LastFieldStr ++ "}).\n", %% gen getMsgId getMsgType str %% TypeStr = "getMsgType(" ++ integer_to_list(MsgId) ++ ")-> " ++ MsgName ++ ";\n", %% IdStr = "getMsgId(" ++ MsgName ++ ")-> " ++ integer_to_list(MsgId) ++ ";\n", %% gen encodeRec Str EncodeStr = genEncodeRec(MsgInfo, true), %% gen decodeBin str resetPd(), DecodeStr = genDecodeBin(MsgInfo, SortedSProtoList, true), {[HrlStr | MsgHrlAcc], ["Unuse"], [EncodeStr | MsgEncodeAcc], [DecodeStr | MsgDecodeAcc]} end, {MsgHrlStr, _MsgIdStr, MsgEncodeStr, MsgDecodeStr} = lists:foldl(FunSpell, {[], ["getMsgId(_) -> 0.\n\n"], ["encode(_) ->\n\t[].\n\n"], ["decodeBin(_, _) ->\n\t{{}, <<>>}.\n\n"]}, SortedSProtoList), SortedErrList = lists:sort(fun({_ErrName1, ErrCodeId1, _Desc1}, {_ErrName2, ErrCodeId2, _Desc2}) -> ErrCodeId1 > ErrCodeId2 end, ErrCodeList), ErrCodeStr = lists:foldl(fun genErrCodeHrl/2, [], SortedErrList) ++ "\n\n", %% gen decodeRec str SubRecList = getSubRec(), SortedSubRecList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) -> MessageId1 > MessageId2 end, SubRecList), FunSubRec = fun(MsgInfo, {SubEncodeAcc, SubDecodeAcc}) -> EncodeStr = genEncodeRec(MsgInfo, false), resetPd(), DecodeStr = genDecodeBin(MsgInfo, SortedSProtoList, false), {[EncodeStr | SubEncodeAcc], [DecodeStr | SubDecodeAcc]} end, {MsgEncodeRecStr, MsgDecodeRecStr} = lists:foldl(FunSubRec, {["encodeRec(_) ->\n\t[].\n\n"], ["decodeRec(_, _) ->\n\t{{}, <<>>}.\n\n"]}, SortedSubRecList), ErlHeaderStr = protoErlHeader(), OutputStr = ErlHeaderStr ++ MsgEncodeRecStr ++ MsgEncodeStr ++ MsgDecodeRecStr ++ MsgDecodeStr, HrlFilename = do_write_hrl(HrlDir, protoMsg, protoHrlHeader() ++ ErrCodeStr ++ MsgHrlStr), ErlFilename = do_write_erl(ErlDir, protoMsg, OutputStr), io:format("protoConvert hrl dir : ~s ~n", [HrlDir]), io:format("protoConvert erl dir : ~s ~n", [ErlDir]), io:format("protoConvert to hrl file ~s succ.~n", [HrlFilename]), io:format("protoConvert to erl file ~s succ.~n", [ErlFilename]), ok. do_write_hrl(OutDir, Mod, Str) when is_list(OutDir) -> Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".hrl"]), ok = file:write_file(Filename, Str), Filename. do_write_erl(OutDir, Mod, Str) when is_list(OutDir) -> Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".erl"]), ok = file:write_file(Filename, Str), Filename.