-module(gCsGen). -include("genDef.hrl"). -export([ genCs/4 ]). protoHeader() -> <<"using System; using System.Collections; using System.Collections.Generic; using System.IO; namespace ProtoMsg { public static class Protocol { public enum BasicTypeEnum { Boolean = 0x01, Int8 = 0x02, UInt8 = 0x03, UInt16 = 0x04, Int16 = 0x05, Int32 = 0x06, UInt32 = 0x07, Int64 = 0x08, UInt64 = 0x09, Float = 0x10, Double = 0x11, String = 0x12, } public static BasicTypeEnum JudgeType(T value) { return value switch { bool => BasicTypeEnum.Boolean, byte => BasicTypeEnum.Int8, sbyte => BasicTypeEnum.UInt8, ushort => BasicTypeEnum.UInt16, short => BasicTypeEnum.Int16, int => BasicTypeEnum.Int32, uint => BasicTypeEnum.UInt32, long => BasicTypeEnum.Int64, ulong => BasicTypeEnum.UInt64, float => BasicTypeEnum.Float, double => BasicTypeEnum.Double, string => BasicTypeEnum.String, _ => throw new InvalidOperationException($\"unexpect type: {value.GetType().FullName}\") }; } public static void WriteValue(this BinaryWriter binaryWriter, T value) { switch (value) { case bool boolValue: binaryWriter.Write(boolValue); break; case byte byteValue: binaryWriter.Write(byteValue); break; case sbyte sbyteValue: binaryWriter.Write(sbyteValue); break; case ushort ushortValue: binaryWriter.Write(ushortValue); break; case short shortValue: binaryWriter.Write(shortValue); break; case int intValue: binaryWriter.Write(intValue); break; case uint uintValue: binaryWriter.Write(uintValue); break; case long longValue: binaryWriter.Write(longValue); break; case ulong ulongValue: binaryWriter.Write(ulongValue); break; case float floatValue: binaryWriter.Write(floatValue); break; case double doubleValue: binaryWriter.Write(doubleValue); break; case string stringValue: binaryWriter.Write(stringValue); break; default: throw new InvalidOperationException($\"unexpect type: {value.GetType().FullName}\"); } } public static void WriteList(this BinaryWriter binaryWriter, IList list) { var length = (ushort) (list?.Count ?? 0); binaryWriter.Write(length); if (list == null) return; for (var idx = 0; idx < length; idx++) { var value = list[idx]; if (idx == 0) { var basicType = JudgeType(value); binaryWriter.Write((byte) basicType); } binaryWriter.WriteValue(value); } } public static void ReadList(this BinaryReader binaryReader, out IList list) { var length = binaryReader.ReadUInt16(); if (length <= 0) { list = default; return; } list = default; var basicTypeEnum = (BasicTypeEnum) binaryReader.ReadByte(); for (int idx = 0; idx < length; idx++) { switch (basicTypeEnum) { case BasicTypeEnum.Boolean: list ??= new List(length); var boolValue = binaryReader.ReadBoolean(); list.Add(boolValue); break; case BasicTypeEnum.Int8: list ??= new List(length); var sbyteValue = binaryReader.ReadSByte(); list.Add(sbyteValue); break; case BasicTypeEnum.UInt8: list ??= new List(length); var byteValue = binaryReader.ReadByte(); list.Add(byteValue); break; case BasicTypeEnum.UInt16: list ??= new List(length); var ushortValue = binaryReader.ReadUInt16(); list.Add(ushortValue); break; case BasicTypeEnum.Int16: list ??= new List(length); var shortValue = binaryReader.ReadInt16(); list.Add(shortValue); break; case BasicTypeEnum.Int32: list ??= new List(length); var intValue = binaryReader.ReadInt32(); list.Add(intValue); break; case BasicTypeEnum.UInt32: list ??= new List(length); var uintValue = binaryReader.ReadUInt32(); list.Add(uintValue); break; case BasicTypeEnum.Int64: list ??= new List(length); var longValue = binaryReader.ReadInt64(); list.Add(longValue); break; case BasicTypeEnum.UInt64: list ??= new List(length); var ulongValue = binaryReader.ReadUInt64(); list.Add(ulongValue); break; case BasicTypeEnum.Float: list ??= new List(length); var singleValue = binaryReader.ReadSingle(); list.Add(singleValue); break; case BasicTypeEnum.Double: list ??= new List(length); var doubleValue = binaryReader.ReadDouble(); list.Add(doubleValue); break; case BasicTypeEnum.String: list ??= new List(length); var stringValue = binaryReader.ReadString(); list.Add(stringValue); break; default: throw new ArgumentOutOfRangeException(); } } } }">>. protoEnd() -> <<"}">>. genMsgHrl([], _Index, _Len, HrlBinStr) -> HrlBinStr; genMsgHrl([FieldInfo | FieldList], Index, Len, HrlBinStr) -> TemStr = case Index of Len -> <<"">>; _ -> <<", ">> end, RecStr = < <<"">>; _ -> <<"\t">> end)/binary>>, genMsgHrl(FieldList, Index - 1, Len, <>). spellHead([], _Index, HeadBinStr) -> HeadBinStr; spellHead([_FieldInfo | FieldList], Index, HeadBinStr) -> spellHead(FieldList, Index + 1, <>). spellBody([], _Index, BodyBinStr) -> BodyBinStr; spellBody([{FieldType, _FieldName}], Index, BodyBinStr) -> TemV = <<"V", (integer_to_binary(Index))/binary>>, <>; spellBody([{FieldType, _FieldName} | FieldList], Index, BodyBinStr) -> TemV = <<"V", (integer_to_binary(Index))/binary>>, NewBodyBinStr = <>, spellBody(FieldList, Index + 1, NewBodyBinStr). spellErrCodeHrl([], ErrBinStr) -> ErrBinStr; spellErrCodeHrl([{ErrName, ErrCodeId, ComDesc} | SortedErrList], ErrBinStr) -> ErrStr = <<"-define(", ErrName/binary, ", ", (integer_to_binary(ErrCodeId))/binary, ").\t\t%% ", ComDesc/binary, "\n">>, spellErrCodeHrl(SortedErrList, <>). genEncodeRec({MsgName, MsgId, FieldList}, IsForBin) -> FieldLen = length(FieldList), TemStr = spellHead(FieldList, 1, <<"">>), HeadStr = case IsForBin of true -> <<"encodeIol(", MsgName/binary, ", {_", TemStr/binary, "}) ->\n\t">>; _ -> <<"subEncode(", MsgName/binary, ", {_", TemStr/binary, "}) ->\n\t">> end, BodyStr = spellBody(FieldList, 1, <<"">>), case IsForBin of true -> case FieldLen > 0 of true -> <>, ", BodyStr/binary, "];\n">>; _ -> <>];\n">> end; _ -> case FieldLen > 0 of true -> <>; _ -> <> 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), integer_to_binary(Index). useIndexStr(Type) -> Index = erlang:get(Type) + 1, erlang:put(Type, Index), integer_to_binary(Index). isCalcRefSize() -> erlang:get(pd_isCalcRefSize) > 0. initSubRec() -> erlang:put(pd_subRec, []). getSubRec() -> erlang:get(pd_subRec). initSubSubRec() -> erlang:put(pd_subSubRec, []). getSubSubRec() -> erlang:get(pd_subSubRec). 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({MsgName, _MsgId, _FieldList} = Info, _IsForBin) -> OldAllList = erlang:get(pd_subRec), case lists:keyfind(MsgName, 1, OldAllList) of false -> erlang:put(pd_subRec, [Info | OldAllList]), OldSubList = erlang:get(pd_subSubRec), case lists:keyfind(MsgName, 1, OldSubList) of false -> erlang:put(pd_subSubRec, [Info | OldSubList]); _ -> ignore end; _ -> ignore end. genDecodeBin({MsgName, MsgId, FieldList}, SortedSProtoList, IsForBin) -> FieldLen = length(FieldList), case IsForBin of true -> HeadStr = <<"decodeBin(", (integer_to_binary(MsgId))/binary, ", LeftBin", (getIndexStr(pd_leftBin))/binary, ") ->\n">>; _ -> HeadStr = <<"decodeRec(", (integer_to_binary(MsgId))/binary, ", LeftBin", (getIndexStr(pd_leftBin))/binary, ") ->\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, "/binary>> = LeftBin", GetLeftBinStr1/binary, ",\n">>; _ -> <<"">> end, UseBoolStr = useIndexStr(pd_bool), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), BoolStr = <<"\t<> = LeftBin", GetLeftBinStr2/binary, ",\n">>, UseVStr = useIndexStr(pd_v), VStr = <<"\tV", UseVStr/binary, " = Bool", UseBoolStr/binary, " =:= 1,\n">>, {false, <>}; <<"int8">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":8/big-signed, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"uint8">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":8/big-unsigned, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"int16">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":16/big-signed, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"uint16">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":16/big-unsigned, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"int32">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":32/big-signed, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"uint32">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":32/big-unsigned, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"int64">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":64/big-signed, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"uint64">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":64/big-unsigned, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"float">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":32/big-float, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"double">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), <<"V", UseVStr/binary, ":64/big-float, ">>; _ -> UseVStr = useIndexStr(pd_v), <<"\t<> end, {true, <>}; <<"string">> -> TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), <<"LeftBin", UseLeftBinStr1/binary, "/binary>> = LeftBin", GetLeftBinStr1/binary, ",\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/binary, ",\n">>, VStr = <<"\tcase Len", UseLenStr/binary, " < ?BinaryShareSize of\n\t\t", "true ->\n\t\t\tV", UseVStr/binary, " = TemStrV", UseVStr/binary, ";\n\t\t", "_ ->\n\t\t\tcase RefSize / Len", UseLenStr/binary, " > ?BinaryCopyRatio of\n\t\t\t\t", "true ->\n\t\t\t\t\tV", UseVStr/binary, " = binary:copy(TemStrV", UseVStr/binary, ");\n\t\t\t\t", "_ ->\n\t\t\t\t\tV", UseVStr/binary, " = TemStrV", UseVStr/binary, "\n\t\t\tend\n\tend,\n">>, {false, <>}; <<"integer">> -> TemStr = case IsSimple of true -> UseVStr = useIndexStr(pd_v), UseIntBitsStr = useIndexStr(pd_intBits), <<"IntBits", UseIntBitsStr/binary, ":8, V", UseVStr/binary, ":IntBits", UseIntBitsStr/binary, "/big-signed, ">>; _ -> UseVStr = useIndexStr(pd_v), UseIntBitsStr = useIndexStr(pd_intBits), <<"\t<> end, {true, <>}; <<"number">> -> TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), <<"LeftBin", UseLeftBinStr1/binary, "/binary>> = LeftBin", GetLeftBinStr1/binary, ",\n">>; _ -> <<"">> end, UseNumBitsStr = useIndexStr(pd_numBits), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), NumStr = <<"\t<> = LeftBin", GetLeftBinStr2/binary, ",\n">>, UseVStr = useIndexStr(pd_v), UseLeftBinStr3 = useIndexStr(pd_leftBin), VStr = <<"\tcase NumBits", UseNumBitsStr/binary, " of\n\t\t33-> \n\t\t\t<> = LeftBin", UseLeftBinStr2/binary, ";\n\t\t65 ->\n\t\t\t<> = LeftBin", UseLeftBinStr2/binary, ";\n\t\t_ ->\n\t\t\t<> = LeftBin", UseLeftBinStr2/binary, "\n\tend,\n">>, {false, <>}; <<"list[", LeftStr/binary>> -> [SubTypeStr | _] = re:split(LeftStr, <<"\\]">>, [{return, binary}]), TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), <<"LeftBin", UseLeftBinStr1/binary, "/binary>> = LeftBin", GetLeftBinStr1/binary, ",\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/binary, ",\n">>, DeListStr = case SubTypeStr of <<"bool">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV =:= 1 || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"int8">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"uint8">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"int16">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"uint16">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"int32">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"uint32">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"int64">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"uint64">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"integer">> -> <<"\t{V", UseVStr/binary, ", LeftBin", UseLeftBinStr3/binary, "} = deIntegerList(Len", UseLenStr/binary, ", LeftBin", GetLeftBinStr3/binary, ", []),\n">>; <<"number">> -> <<"\t{V", UseVStr/binary, ", LeftBin", UseLeftBinStr3/binary, "} = deNumberList(Len", UseLenStr/binary, ", LeftBin", GetLeftBinStr3/binary, ", []),\n">>; <<"float">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"double">> -> ListBinStr = <<"\t<> = LeftBin", GetLeftBinStr3/binary, ",\n">>, VStr = <<"\tV", UseVStr/binary, " = [TemV || <> <= ListBin", UseListBinStr/binary, "],\n">>, <>; <<"string">> -> case isCalcRefSize() of true -> <<"\t{V", UseVStr/binary, ", LeftBin", UseLeftBinStr3/binary, "} = deStringList(Len", UseLenStr/binary, ", LeftBin", GetLeftBinStr3/binary, ", RefSize, []),\n">>; _ -> useIndexStr(pd_isCalcRefSize), RefSizeStr = <<"\tRefSize = binary:referenced_byte_size(LeftBin0),\n">>, VStr = <<"\t{V", UseVStr/binary, ", LeftBin", UseLeftBinStr3/binary, "} = deStringList(Len", UseLenStr/binary, ", LeftBin", GetLeftBinStr3/binary, ", RefSize, []),\n">>, <> end; ListRecord -> case lists:keyfind(ListRecord, 1, SortedSProtoList) of {ListRecord, ListMsgId, _} = RecordInfo -> addSubRec(RecordInfo, IsForBin), <<"\t{V", UseVStr/binary, ", LeftBin", UseLeftBinStr3/binary, "} = deRecordList(Len", UseLenStr/binary, ", ", (integer_to_binary(ListMsgId))/binary, ", LeftBin", GetLeftBinStr3/binary, ", []),\n">>; _ -> io:format("this an Record undefined :~p~n", [ListRecord]), throw(record_undefined) end end, {false, <>}; OtherRecord -> TemStr = case IsSimple of true -> GetLeftBinStr1 = getIndexStr(pd_leftBin), UseLeftBinStr1 = useIndexStr(pd_leftBin), <<"LeftBin", UseLeftBinStr1/binary, "/binary>> = LeftBin", GetLeftBinStr1/binary, ",\n">>; _ -> <<"">> end, UseIsUndefStr = useIndexStr(pd_isUndef), GetLeftBinStr2 = getIndexStr(pd_leftBin), UseLeftBinStr2 = useIndexStr(pd_leftBin), IsStr = <<"\t<> = LeftBin", GetLeftBinStr2/binary, ",\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/binary, " of\n\t\t0 ->\n\t\t\tV", UseVStr/binary, " = undefined,\n\t\t\tLeftBin", UseLeftBinStr3/binary, " = LeftBin", UseLeftBinStr2/binary, " ;\n\t\t_ ->\n\t\t\t{V", UseVStr/binary, ", LeftBin", UseLeftBinStr3/binary, "} = ", "decodeRec(", (integer_to_binary(OtherMsgId))/binary, ", LeftBin", UseLeftBinStr2/binary, ")\n\tend,\n">>, {false, <>}; _ -> 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), <> = LeftBin", LGetLeftBinStr/binary, ",\n">>; _ -> BodyStr end, RetStr = case IsForBin of true -> MsgIndex = MsgId div ?MsgIdSegSize, Handler = erlang:get(pd_handler), {MsgIndex, ModName} = lists:keyfind(MsgIndex, 1, Handler), HandleName = <>, case FieldLen > 0 of true -> FunRec = fun(N, Acc) -> <> end, RecStr = lists:foldl(FunRec, <<"">>, lists:seq(1, FieldLen)), <<"\t{", HandleName/binary, ", ", MsgName/binary, ", {", MsgName/binary, RecStr/binary, "}};\n">>; _ -> <<"\t{", HandleName/binary, ", ", MsgName/binary, ", {", MsgName/binary, "}};\n">> end; _ -> case FieldLen > 0 of true -> FunRec = fun(N, Acc) -> <> end, RecStr = lists:foldl(FunRec, <<"">>, lists:seq(1, FieldLen)), <<"\tMsgRec = {", MsgName/binary, RecStr/binary, "},\n\t{MsgRec, LeftBin", (getIndexStr(pd_leftBin))/binary, "};\n">>; _ -> <<"\t{{", MsgName/binary, "}, ", "<<>>};\n">> end end, <>. genCs(SortedSProtoList, SortedErrList, HrlDir, ErlDir) -> initSubRec(), FunSpell = fun({MsgName, MsgId, FieldList} = MsgInfo, {MsgHrlAcc, MsgEncodeAcc, MsgDecodeAcc, MsgIdAcc, MsgNameAcc}) -> %% gen hrl str Len = erlang:length(FieldList), LastFieldStr = genMsgHrl(FieldList, Len, Len, <<"">>), HrlStr = <<"-record(", MsgName/binary, ", {\n\t", LastFieldStr/binary, "}).\n">>, %% gen getMsgId getMsgType str IdStr = <<"getMsgId(", MsgName/binary, ")-> ", (integer_to_binary(MsgId))/binary, ";\n">>, NameStr = <<"getMsgName(", (integer_to_binary(MsgId))/binary, ")-> ", MsgName/binary, ";\n">>, %% gen encodeRec Str EncodeStr = genEncodeRec(MsgInfo, true), %% gen decodeBin str resetPd(), DecodeStr = genDecodeBin(MsgInfo, SortedSProtoList, true), {<>, <>, <>, <>, <>} end, {MsgHrlStr, TMsgEncodeStr, TMsgDecodeStr, _TMsgIdStr, _TMsgNameStr} = lists:foldl(FunSpell, {<<>>, <<>>, <<>>, <<>>, <<>>}, SortedSProtoList), MsgEncodeStr = <\n\t[].\n\n">>, MsgDecodeStr = <\n\t{undefinedHer, undefined, {}}.\n\n">>, _MsgIdStr = <<_TMsgIdStr/binary, "getMsgId(_) -> 0.\n\n">>, _MsgNameStr = <<_TMsgNameStr/binary, "getMsgName(_) -> undefiend.\n\n">>, ErrCodeStr = spellErrCodeHrl(SortedErrList, <<>>), %% gen decodeRec str SubRecList = getSubRec(), initSubSubRec(), SortedSubRecList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) -> MessageId1 < MessageId2 end, SubRecList), {MsgEncodeRecStr, MsgDecodeRecStr} = dealSubRec(SortedSubRecList, SortedSProtoList, <<"">>, <<"">>), ErlHeaderStr = protoErlHeader(), HrlHeaderStr = protoHrlHeader(), OutputErlStr = <>, OutputHrlStr = <>, HrlFilename = do_write_hrl(HrlDir, protoMsg, OutputHrlStr), ErlFilename = do_write_erl(ErlDir, protoMsg, OutputErlStr), 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. dealSubRec([], SortedSProtoList, SubEncodeAcc, SubDecodeAcc) -> case getSubSubRec() of [] -> {<\n\t[].\n\n">>, <\n\t{{}, <<>>}.\n\n">>}; NewAddList -> initSubSubRec(), SortedSubRecList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) -> MessageId1 < MessageId2 end, NewAddList), dealSubRec(SortedSubRecList, SortedSProtoList, SubEncodeAcc, SubDecodeAcc) end; dealSubRec([MsgInfo | SubRecList], SortedSProtoList, SubEncodeAcc, SubDecodeAcc) -> EncodeStr = genEncodeRec(MsgInfo, false), resetPd(), DecodeStr = genDecodeBin(MsgInfo, SortedSProtoList, false), dealSubRec(SubRecList, SortedSProtoList, <>, <>). do_write_hrl(OutDir, Mod, BinStr) -> Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".hrl"]), ok = file:write_file(Filename, BinStr), Filename. do_write_erl(OutDir, Mod, BinStr) -> Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".erl"]), case file:write_file(Filename, BinStr) of ok -> ok; _Ret -> io:format("write to erl file error:~p ~n", [_Ret]) end, Filename.