erlang自定义二进制协议
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

772 Zeilen
36 KiB

-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>(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<T>(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<T>(this BinaryWriter binaryWriter, IList<T> 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<bool>(length);
var boolValue = binaryReader.ReadBoolean();
list.Add(boolValue);
break;
case BasicTypeEnum.Int8:
list ??= new List<sbyte>(length);
var sbyteValue = binaryReader.ReadSByte();
list.Add(sbyteValue);
break;
case BasicTypeEnum.UInt8:
list ??= new List<byte>(length);
var byteValue = binaryReader.ReadByte();
list.Add(byteValue);
break;
case BasicTypeEnum.UInt16:
list ??= new List<ushort>(length);
var ushortValue = binaryReader.ReadUInt16();
list.Add(ushortValue);
break;
case BasicTypeEnum.Int16:
list ??= new List<short>(length);
var shortValue = binaryReader.ReadInt16();
list.Add(shortValue);
break;
case BasicTypeEnum.Int32:
list ??= new List<int>(length);
var intValue = binaryReader.ReadInt32();
list.Add(intValue);
break;
case BasicTypeEnum.UInt32:
list ??= new List<uint>(length);
var uintValue = binaryReader.ReadUInt32();
list.Add(uintValue);
break;
case BasicTypeEnum.Int64:
list ??= new List<long>(length);
var longValue = binaryReader.ReadInt64();
list.Add(longValue);
break;
case BasicTypeEnum.UInt64:
list ??= new List<ulong>(length);
var ulongValue = binaryReader.ReadUInt64();
list.Add(ulongValue);
break;
case BasicTypeEnum.Float:
list ??= new List<float>(length);
var singleValue = binaryReader.ReadSingle();
list.Add(singleValue);
break;
case BasicTypeEnum.Double:
list ??= new List<double>(length);
var doubleValue = binaryReader.ReadDouble();
list.Add(doubleValue);
break;
case BasicTypeEnum.String:
list ??= new List<string>(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 = <<TemStr/binary, (gErlField:builtRecStr(FieldInfo))/binary, (case Index == 1 of true -> <<"">>; _ -> <<"\t">> end)/binary>>,
genMsgHrl(FieldList, Index - 1, Len, <<HrlBinStr/binary, RecStr/binary>>).
spellHead([], _Index, HeadBinStr) ->
HeadBinStr;
spellHead([_FieldInfo | FieldList], Index, HeadBinStr) ->
spellHead(FieldList, Index + 1, <<HeadBinStr/binary, ", V", (integer_to_binary(Index))/binary>>).
spellBody([], _Index, BodyBinStr) ->
BodyBinStr;
spellBody([{FieldType, _FieldName}], Index, BodyBinStr) ->
TemV = <<"V", (integer_to_binary(Index))/binary>>,
<<BodyBinStr/binary, (gErlField:builtPackStr(FieldType))/binary, TemV/binary, ")">>;
spellBody([{FieldType, _FieldName} | FieldList], Index, BodyBinStr) ->
TemV = <<"V", (integer_to_binary(Index))/binary>>,
NewBodyBinStr = <<BodyBinStr/binary, (gErlField:builtPackStr(FieldType))/binary, TemV/binary, "), ">>,
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, <<ErrBinStr/binary, ErrStr/binary>>).
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 ->
<<HeadStr/binary, "[<<", (integer_to_binary(MsgId))/binary, ":16/big-unsigned>>, ", BodyStr/binary, "];\n">>;
_ ->
<<HeadStr/binary, "[<<", (integer_to_binary(MsgId))/binary, ":16/big-unsigned>>];\n">>
end;
_ ->
case FieldLen > 0 of
true ->
<<HeadStr/binary, "[", BodyStr/binary, "];\n">>;
_ ->
<<HeadStr/binary, "[];\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),
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<<Bool", UseBoolStr/binary, ":8/big-unsigned, LeftBin", UseLeftBinStr2/binary, "/binary>> = LeftBin", GetLeftBinStr2/binary, ",\n">>,
UseVStr = useIndexStr(pd_v),
VStr = <<"\tV", UseVStr/binary, " = Bool", UseBoolStr/binary, " =:= 1,\n">>,
{false, <<StrAcc/binary, TemStr/binary, BoolStr/binary, VStr/binary>>};
<<"int8">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":8/big-signed, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":8/big-signed, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"uint8">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":8/big-unsigned, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":8/big-unsigned, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"int16">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":16/big-signed, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":16/big-signed, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"uint16">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":16/big-unsigned, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":16/big-unsigned, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"int32">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":32/big-signed, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":32/big-signed, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"uint32">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":32/big-unsigned, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":32/big-unsigned, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"int64">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":64/big-signed, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":64/big-signed, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"uint64">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":64/big-unsigned, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":64/big-unsigned, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"float">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":32/big-float, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":32/big-float, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"double">> ->
TemStr =
case IsSimple of
true ->
UseVStr = useIndexStr(pd_v),
<<"V", UseVStr/binary, ":64/big-float, ">>;
_ ->
UseVStr = useIndexStr(pd_v),
<<"\t<<V", UseVStr/binary, ":64/big-float, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"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<<Len", UseLenStr/binary, ":16/big-unsigned, TemStrV", UseVStr/binary, ":Len", UseLenStr/binary, "/binary, LeftBin", UseLeftBinStr2/binary, "/binary>> = 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, <<StrAcc/binary, TemStr/binary, RefSizeStr/binary, StrStr/binary, VStr/binary>>};
<<"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<<IntBits", UseIntBitsStr/binary, ":8, V", UseVStr/binary, ":IntBits", UseIntBitsStr/binary, "/big-signed, ">>
end,
{true, <<StrAcc/binary, TemStr/binary>>};
<<"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<<NumBits", UseNumBitsStr/binary, ":8, LeftBin", UseLeftBinStr2/binary, "/binary>> = 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<<V", UseVStr/binary, ":32/big-float, LeftBin", UseLeftBinStr3/binary,
"/binary>> = LeftBin", UseLeftBinStr2/binary, ";\n\t\t65 ->\n\t\t\t<<V", UseVStr/binary, ":64/big-float, LeftBin", UseLeftBinStr3/binary,
"/binary>> = LeftBin", UseLeftBinStr2/binary, ";\n\t\t_ ->\n\t\t\t<<V", UseVStr/binary, ":NumBits", UseNumBitsStr/binary, "/big-signed, LeftBin", UseLeftBinStr3/binary,
"/binary>> = LeftBin", UseLeftBinStr2/binary, "\n\tend,\n">>,
{false, <<StrAcc/binary, TemStr/binary, NumStr/binary, VStr/binary>>};
<<"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<<Len", UseLenStr/binary, ":16/big-unsigned, LeftBin", UseLeftBinStr2/binary, "/binary>> = LeftBin", GetLeftBinStr2/binary, ",\n">>,
DeListStr =
case SubTypeStr of
<<"bool">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:8, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV =:= 1 || <<TemV:8/big-unsigned>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"int8">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:8, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:8/big-signed>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"uint8">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:8, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:8/big-unsigned>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"int16">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:16, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:16/big-signed>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"uint16">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:16, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:16/big-unsigned>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"int32">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:32, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:32/big-signed>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"uint32">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:32, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:32/big-unsigned>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"int64">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:64, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:64/big-signed>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"uint64">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:64, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:64/big-unsigned>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"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<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:32, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:32/big-float>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"double">> ->
ListBinStr = <<"\t<<ListBin", UseListBinStr/binary, ":Len", UseLenStr/binary, "/big-binary-unit:64, LeftBin", UseLeftBinStr3/binary, "/binary>> = LeftBin", GetLeftBinStr3/binary, ",\n">>,
VStr = <<"\tV", UseVStr/binary, " = [TemV || <<TemV:64/big-float>> <= ListBin", UseListBinStr/binary, "],\n">>,
<<ListBinStr/binary, VStr/binary>>;
<<"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">>,
<<RefSizeStr/binary, VStr/binary>>
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, <<StrAcc/binary, TemStr/binary, LenStr/binary, DeListStr/binary>>};
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<<IsUndef", UseIsUndefStr/binary, ":8/big-unsigned, LeftBin", UseLeftBinStr2/binary, "/binary>> = 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, <<StrAcc/binary, TemStr/binary, IsStr/binary, VStr/binary>>};
_ ->
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/binary, "LeftBin", LUseLeftBinStr/binary, "/binary>> = 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 = <<ModName/binary, "Her">>,
case FieldLen > 0 of
true ->
FunRec =
fun(N, Acc) ->
<<Acc/binary, ", V", (integer_to_binary(N))/binary>>
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) ->
<<Acc/binary, ", V", (integer_to_binary(N))/binary>>
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,
<<HeadStr/binary, LBodyStr/binary, RetStr/binary>>.
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),
{<<MsgHrlAcc/binary, HrlStr/binary>>, <<MsgEncodeAcc/binary, EncodeStr/binary>>, <<MsgDecodeAcc/binary, DecodeStr/binary>>, <<MsgIdAcc/binary, IdStr/binary>>, <<MsgNameAcc/binary, NameStr/binary>>}
end,
{MsgHrlStr, TMsgEncodeStr, TMsgDecodeStr, _TMsgIdStr, _TMsgNameStr} = lists:foldl(FunSpell, {<<>>, <<>>, <<>>, <<>>, <<>>}, SortedSProtoList),
MsgEncodeStr = <<TMsgEncodeStr/binary, "encodeIol(_, _) ->\n\t[].\n\n">>,
MsgDecodeStr = <<TMsgDecodeStr/binary, "decodeBin(_, _) ->\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 = <<ErlHeaderStr/binary, MsgEncodeRecStr/binary, MsgEncodeStr/binary, MsgDecodeRecStr/binary, MsgDecodeStr/binary>>,
OutputHrlStr = <<HrlHeaderStr/binary, ErrCodeStr/binary, "\n\n", MsgHrlStr/binary>>,
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
[] ->
{<<SubEncodeAcc/binary, "subEncode(_, _) ->\n\t[].\n\n">>, <<SubDecodeAcc/binary, "decodeRec(_, _) ->\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, <<SubEncodeAcc/binary, EncodeStr/binary>>, <<SubDecodeAcc/binary, DecodeStr/binary>>).
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.