Selaa lähdekoodia

初始化

初始化提交
genProto_V1
AICells 5 vuotta sitten
vanhempi
commit
d4b70d942c
14 muutettua tiedostoa jossa 1871 lisäystä ja 0 poistoa
  1. +9
    -0
      README.md
  2. +9
    -0
      ebin/genProto.app
  3. +24
    -0
      proto/0_test.msg
  4. +2
    -0
      rebar.config
  5. +13
    -0
      src/genProto.app.src
  6. +247
    -0
      src/protoCode.erl
  7. +91
    -0
      src/protoField.erl
  8. +365
    -0
      src/protoGen.erl
  9. +475
    -0
      src/protoParse.erl
  10. +1
    -0
      test/genProto.bat
  11. +285
    -0
      test/protoMsg.erl
  12. +28
    -0
      test/protoMsg.hrl
  13. +3
    -0
      test/remake.bat
  14. +319
    -0
      test/test.erl

+ 9
- 0
README.md Näytä tiedosto

@ -0,0 +1,9 @@
genProto
=====
An OTP library
Build
-----
$ rebar3 compile

+ 9
- 0
ebin/genProto.app Näytä tiedosto

@ -0,0 +1,9 @@
{application,genProto,
[{description,"An OTP library"},
{vsn,"0.1.0"},
{registered,[]},
{applications,[kernel,stdlib]},
{env,[]},
{modules,[protoCode,protoField,protoGen,protoParse]},
{licenses,["Apache 2.0"]},
{links,[]}]}.

+ 24
- 0
proto/0_test.msg Näytä tiedosto

@ -0,0 +1,24 @@
%% 测试协议 注释可以用 % 也可以用 //
test {
string aa;
}
// phoneNumber info
phoneNumber{
test number; //电话号码
int32 type; //类型
}
%% person info
person{
string name; %% 名字
int32 id; %% id
string email; //邮箱
list[phoneNumber] phone; // list of phoneNumber
}
%% addressBook info
addressBook {
list[person] person;
list[person] other;
}

+ 2
- 0
rebar.config Näytä tiedosto

@ -0,0 +1,2 @@
{erl_opts, [debug_info]}.
{deps, []}.

+ 13
- 0
src/genProto.app.src Näytä tiedosto

@ -0,0 +1,13 @@
{application, genProto,
[{description, "An OTP library"},
{vsn, "0.1.0"},
{registered, []},
{applications,
[kernel,
stdlib
]},
{env, []},
{modules, []},
{licenses, ["Apache 2.0"]},
{links, []}
]}.

+ 247
- 0
src/protoCode.erl Näytä tiedosto

@ -0,0 +1,247 @@
-module(protoCode).
-compile(nowarn_unused_function).
-export([encode/1, decode/1, encodeRec/1, decodeRec/2]).
-define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)).
-define(int8(V), <<V:8>>).
-define(uint8(V), <<V:8>>).
-define(int16(V), <<V:16/big>>).
-define(uint16(V), <<V:16/big>>).
-define(int32(V), <<V:32/big>>).
-define(uint32(V), <<V:32/big>>).
-define(int64(V), <<V:64/big>>).
-define(uint64(V), <<V:64/big>>).
-define(float(V), <<V:32/big-float>>).
-define(double(V), <<V:64/big-float>>).
-define(string(V), (string(V))).
-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_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]).
-define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]).
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].
encode(Record) ->
MsgBin = encodeRec(Record),
MsgId = getMsgId(element(1, Record)),
[<<MsgId:16/big>>, MsgBin].
decode(Bin) ->
<<MsgId:16/big, MsgBin/binary>> = Bin,
SchList = getMsgSchema(MsgId),
{<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]),
list_to_tuple(ResultList).
decodeRec(RecordName, Bin) ->
SchList = getMsgSchema(RecordName),
{LeftBin, Result} = decodeField(SchList, Bin, [RecordName]),
{LeftBin, list_to_tuple(Result)}.
decodeField([], LeftBin, Result) ->
{LeftBin, lists:reverse(Result)};
decodeField([Type | SchList], MsgBin, Result) ->
case Type of
int32 ->
<<Int:32/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint32 ->
<<Int:32/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
string ->
<<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [StrBin | Result]);
int16 ->
<<Int:16/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint16 ->
<<Int:16/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
int8 ->
<<Int:8/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint8 ->
<<Int:8/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
int64 ->
<<Int:64/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint64 ->
<<Int:64/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
bool ->
<<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin,
case Bool =:= 1 of
true ->
decodeField(SchList, LeftBin, [true | Result]);
_ ->
decodeField(SchList, LeftBin, [false | Result])
end;
falat ->
<<Float:32/big-float, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Float | Result]);
double ->
<<Float:64/big-float, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Float | Result]);
{list, int32} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt32List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint32} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint32List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int16} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt16List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint16} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint16List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int8} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt8List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint8} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint8List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, string} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deStringList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int64} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt64List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint64} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint64List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, bool} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deBoolList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, flat} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deFloatList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, double} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deDoubleList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, RecordName} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
RecordName ->
<<IsUndef:8, LeftBin/binary>> = MsgBin,
case IsUndef of
0 ->
decodeField(SchList, LeftBin, [undefined | Result]);
_ ->
SubSchList = getMsgSchema(RecordName),
{SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]),
decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result])
end
end.
deBoolList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) ->
case Bool =:= 1 of
true ->
deBoolList(N - 1, LeftBin, [true | RetList]);
_ ->
deBoolList(N - 1, LeftBin, [false | RetList])
end.
deInt8List(0, MsgBin, RetList) ->
{MsgBin, RetList};
deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) ->
deInt8List(N - 1, LeftBin, [Int | RetList]).
deUint8List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) ->
deUint8List(N - 1, LeftBin, [Int | RetList]).
deInt16List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) ->
deInt16List(N - 1, LeftBin, [Int | RetList]).
deUint16List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) ->
deUint16List(N - 1, LeftBin, [Int | RetList]).
deInt32List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) ->
deInt32List(N - 1, LeftBin, [Int | RetList]).
deUint32List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) ->
deUint32List(N - 1, LeftBin, [Int | RetList]).
deInt64List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) ->
deInt64List(N - 1, LeftBin, [Int | RetList]).
deUint64List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) ->
deUint64List(N - 1, LeftBin, [Int | RetList]).
deFloatList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) ->
deFloatList(N - 1, LeftBin, [Float | RetList]).
deDoubleList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) ->
deDoubleList(N - 1, LeftBin, [Float | RetList]).
deStringList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) ->
deStringList(N - 1, LeftBin, [StrBin | RetList]).
deRecordList(0, _RecordName, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deRecordList(N, RecordName, MsgBin, RetList) ->
{LeftBin, Tuple} = decodeRec(RecordName, MsgBin),
deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]).
%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
encodeRec(_) ->
ok.
getMsgId(_) ->
ok.
getMsgType(_) ->
ok.
getMsgSchema(_) ->
ok.

+ 91
- 0
src/protoField.erl Näytä tiedosto

@ -0,0 +1,91 @@
-module(protoField).
-compile([export_all, nowarn_export_all]).
-define(TypeList, [
"bool",
"int8",
"uint8",
"int16",
"uint16",
"int32",
"uint32",
"int64",
"uint64",
"float",
"double",
"string"
]).
-define(TypeValue, [
{"bool", "false", "boolean"},
{"int8", "0", "int8()"},
{"uint8", "0", "uint8()"},
{"int16", "0", "int16()"},
{"uint16", "0", "uint16()"},
{"int32", "0", "int32()"},
{"uint32", "0", "uint32()"},
{"int64", "0", "int64()"},
{"uint64", "0", "uint64()"},
{"float", "0.0", "float()"},
{"double", "0.0", "flaot"},
{"string", "\"\"", "string()"}
]).
getSchemaInfo(TypeStr) ->
case lists:member(TypeStr, ?TypeList) of
true ->
erlang:list_to_atom(TypeStr);
_ ->
case TypeStr of
"list[" ++ LeftStr ->
[SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]),
{list, erlang:list_to_atom(SubTypeStr)};
_ ->
erlang:list_to_atom(TypeStr)
end
end.
builtRecStr({TypeStr, NameStr}) ->
case lists:keyfind(TypeStr, 1, ?TypeValue) of
{TypeStr, DefValueStr, DefTypeStr} ->
NameStr ++ " = " ++ DefValueStr ++ " :: " ++ DefTypeStr ++ "\n\t";
_ ->
case TypeStr of
"list[" ++ LeftStr ->
[SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]),
case lists:keyfind(SubTypeStr, 1, ?TypeValue) of
{SubTypeStr, _DefSubValueStr, DefSubTypeStr} ->
NameStr ++ " = [] " ++ " :: [" ++ DefSubTypeStr ++ "]\n\t";
_ ->
NameStr ++ " = [] " ++ " :: [#" ++ SubTypeStr ++ "{}]\n\t"
end;
_ ->
NameStr ++ " = undefined " ++ " :: #" ++ TypeStr ++ "{}\n\t"
end
end.
builtPackStr(TypeStr) ->
case lists:member(TypeStr, ?TypeList) of
true ->
"?" ++ TypeStr ++ "(";
_ ->
case TypeStr of
"list[" ++ LeftStr ->
[SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]),
SubStr =
case lists:member(SubTypeStr, ?TypeList) of
true ->
SubTypeStr;
_ ->
"record"
end,
"?list_" ++ SubStr ++ "(";
_ ->
"?record("
end
end.

+ 365
- 0
src/protoGen.erl Näytä tiedosto

@ -0,0 +1,365 @@
-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 single() :: float().
-opaque double() :: float().\n\n".
protoErlHeader() ->
"-module(protoMsg).\n\n
-export([encode/1, decode/1, encodeRec/1, decodeRec/2]).
-define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)).
-define(int8(V), <<V:8>>).
-define(uint8(V), <<V:8>>).
-define(int16(V), <<V:16/big>>).
-define(uint16(V), <<V:16/big>>).
-define(int32(V), <<V:32/big>>).
-define(uint32(V), <<V:32/big>>).
-define(int64(V), <<V:64/big>>).
-define(uint64(V), <<V:64/big>>).
-define(float(V), <<V:32/big-float>>).
-define(double(V), <<V:64/big-float>>).
-define(string(V), (string(V))).
-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_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]).
-define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]).
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].
encode(Record) ->
MsgBin = encodeRec(Record),
MsgId = getMsgId(element(1, Record)),
[<<MsgId:16/big>>, MsgBin].
decode(Bin) ->
<<MsgId:16/big, MsgBin/binary>> = Bin,
SchList = getMsgSchema(MsgId),
{<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]),
list_to_tuple(ResultList).
decodeRec(RecordName, Bin) ->
SchList = getMsgSchema(RecordName),
{LeftBin, Result} = decodeField(SchList, Bin, [RecordName]),
{LeftBin, list_to_tuple(Result)}.
decodeField([], LeftBin, Result) ->
{LeftBin, lists:reverse(Result)};
decodeField([Type | SchList], MsgBin, Result) ->
case Type of
int32 ->
<<Int:32/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint32 ->
<<Int:32/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
string ->
<<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [StrBin | Result]);
int16 ->
<<Int:16/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint16 ->
<<Int:16/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
int8 ->
<<Int:8/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint8 ->
<<Int:8/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
int64 ->
<<Int:64/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint64 ->
<<Int:64/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
bool ->
<<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin,
case Bool =:= 1 of
true ->
decodeField(SchList, LeftBin, [true | Result]);
_ ->
decodeField(SchList, LeftBin, [false | Result])
end;
falat ->
<<Float:32/big-float, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Float | Result]);
double ->
<<Float:64/big-float, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Float | Result]);
{list, int32} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt32List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint32} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint32List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int16} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt16List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint16} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint16List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int8} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt8List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint8} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint8List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, string} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deStringList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int64} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt64List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint64} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint64List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, bool} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deBoolList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, flat} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deFloatList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, double} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deDoubleList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, RecordName} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
RecordName ->
<<IsUndef:8, LeftBin/binary>> = MsgBin,
case IsUndef of
0 ->
decodeField(SchList, LeftBin, [undefined | Result]);
_ ->
SubSchList = getMsgSchema(RecordName),
{SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]),
decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result])
end
end.
deBoolList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) ->
case Bool =:= 1 of
true ->
deBoolList(N - 1, LeftBin, [true | RetList]);
_ ->
deBoolList(N - 1, LeftBin, [false | RetList])
end.
deInt8List(0, MsgBin, RetList) ->
{MsgBin, RetList};
deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) ->
deInt8List(N - 1, LeftBin, [Int | RetList]).
deUint8List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) ->
deUint8List(N - 1, LeftBin, [Int | RetList]).
deInt16List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) ->
deInt16List(N - 1, LeftBin, [Int | RetList]).
deUint16List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) ->
deUint16List(N - 1, LeftBin, [Int | RetList]).
deInt32List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) ->
deInt32List(N - 1, LeftBin, [Int | RetList]).
deUint32List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) ->
deUint32List(N - 1, LeftBin, [Int | RetList]).
deInt64List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) ->
deInt64List(N - 1, LeftBin, [Int | RetList]).
deUint64List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) ->
deUint64List(N - 1, LeftBin, [Int | RetList]).
deFloatList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) ->
deFloatList(N - 1, LeftBin, [Float | RetList]).
deDoubleList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) ->
deDoubleList(N - 1, LeftBin, [Float | RetList]).
deStringList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) ->
deStringList(N - 1, LeftBin, [StrBin | RetList]).
deRecordList(0, _RecordName, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deRecordList(N, RecordName, MsgBin, RetList) ->
{LeftBin, Tuple} = decodeRec(RecordName, MsgBin),
deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]).\n\n".
genSchema({FieldType, _FieldName}, AccList) ->
SchemaStr = protoField:getSchemaInfo(FieldType),
[SchemaStr | AccList].
genMsgHrl(FieldInfo, {Index, AccList}) ->
TemStr =
case Index of
1 ->
"";
_ ->
","
end,
RecStr = TemStr ++ protoField:builtRecStr(FieldInfo),
{Index - 1, [RecStr | AccList]}.
genEncodeRec({MsgName, _MsgId, FieldList}) ->
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 = "encodeRec({" ++ MsgName ++ TemStr,
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,
{_, LastStr} = lists:foldr(FunBody, {FieldLen, ""}, FieldList),
case FieldLen > 0 of
true ->
HeadStr ++ "[" ++ LastStr ++ "];\n";
_ ->
HeadStr ++ "[];\n"
end.
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) ->
FunRead =
fun(File, Acc) ->
case filename:extension(File) == ".msg" of
true ->
io:format("Convert proto msg file: ~s ~n", [File]),
BaseName = filename:basename(File, ".msg"),
[ModIndex | _ModName] = re:split(BaseName, "_"),
Index = binary_to_integer(ModIndex),
put(messageid, Index * 1000 + 1),
SProto = protoParse:parseFile(File),
[SProto | Acc];
_ ->
Acc
end
end,
%% .msg结尾的文件 FunRead函数中纠正处理一下
SProtoListOfList = filelib:fold_files(ProtoDir, "\\.msg", true, FunRead, []),
SProtoList = lists:append(SProtoListOfList),
SortedSProtoList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) ->
MessageId1 > MessageId2 end, SProtoList),
FunSpell =
fun({MsgName, MsgId, FieldList} = MsgInfo, {MsgHrlAcc, MsgTypeAcc, MsgIdAcc, MsgEndStr, MsgSchemaAcc}) ->
TypeStr = "getMsgType(" ++ integer_to_list(MsgId) ++ ")->\n\t" ++ MsgName ++ ";\n",
IdStr = "getMsgId(" ++ MsgName ++ ")->\n\t" ++ integer_to_list(MsgId) ++ ";\n",
EncodeStr = genEncodeRec(MsgInfo),
Len = erlang:length(FieldList),
SchemaList = lists:foldr(fun genSchema/2, [], FieldList),
SchemaStr = "getMsgSchema(" ++ MsgName ++ ")->\n\t" ++ "getMsgSchema(" ++ integer_to_list(MsgId) ++ ");\n" ++
"getMsgSchema(" ++ integer_to_list(MsgId) ++ ")->\n\t" ++ io_lib:format("~p", [SchemaList]) ++ ";\n",
{_, LastFieldStr} = lists:foldr(fun genMsgHrl/2, {Len, ""}, FieldList),
HrlStr = "-record(" ++ MsgName ++ " ,{\n\t" ++ LastFieldStr ++ "}).\n",
{[HrlStr | MsgHrlAcc], [TypeStr | MsgTypeAcc], [IdStr | MsgIdAcc], [EncodeStr | MsgEndStr], [SchemaStr | MsgSchemaAcc]}
end,
{MsgHrlStr, MsgTypeStr, MsgIdStr, MsgEndStr, MsgSchemaStr} = lists:foldl(FunSpell, {[], ["getMsgType(_) ->\n\tundefined.\n\n"], ["getMsgId(_) ->\n\t0.\n\n"], ["encodeRec(_) ->\n\t[].\n\n"], ["getMsgSchema(_) ->\n\t[].\n\n"]}, SortedSProtoList),
ModStr = protoErlHeader(),
OutputStr = ModStr ++ MsgTypeStr ++ MsgIdStr ++ MsgEndStr ++ MsgSchemaStr,
HrlFilename = do_write_hrl(HrlDir, protoMsg, protoHrlHeader() ++ 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.

+ 475
- 0
src/protoParse.erl Näytä tiedosto

@ -0,0 +1,475 @@
-module(protoParse).
-compile(nowarn_unused_function).
-export([
parseParse/1
, parseFile/1
]).
-define(p_anything, true).
-define(p_charclass, true).
-define(p_choose, true).
-define(p_label, true).
-define(p_not, true).
-define(p_one_or_more, true).
-define(p_optional, true).
-define(p_scan, true).
-define(p_seq, true).
-define(p_string, true).
-define(p_zero_or_more, true).
-spec parseFile(file:name()) -> any().
parseFile(Filename) ->
case file:read_file(Filename) of
{ok, Bin} ->
parseParse(Bin);
Err -> Err
end.
-spec parseParse(binary() | list()) -> any().
parseParse(List) when is_list(List) ->
parseParse(unicode:characters_to_binary(List));
parseParse(Input) when is_binary(Input) ->
Result =
case 'all'(Input, {{line, 1}, {column, 1}}) of
{AST, <<>>, _Index} ->
AST;
Any ->
Any
end,
release_memo(),
Result.
-spec 'all'(input(), index()) -> parse_result().
'all'(Input, Index) ->
p(Input, Index, 'all',
fun(I, D) ->
(p_seq([fun 'blank0'/2, p_zero_or_more(p_seq([fun 'protocol'/2, fun 'blank0'/2]))]))(I, D)
end,
fun(Node, _Idx) ->
[_ | [T]] = Node, DataList = [H || [H | _] <- T], DataList
end).
-spec 'protocol'(input(), index()) -> parse_result().
'protocol'(Input, Index) ->
p(Input, Index, 'protocol',
fun(I, D) ->
(p_seq([p_label('name', fun 'name'/2), fun 'blank0'/2, p_label('structural', fun 'structural'/2)]))(I, D)
end,
fun(Node, _Idx) ->
Name = binary_to_list(iolist_to_binary(proplists:get_value(name, Node))),
Structural = proplists:get_value(structural, Node),
MsgId = get(messageid),
put(messageid, MsgId + 1),
{Name, MsgId, Structural}
end).
-spec 'structural'(input(), index()) -> parse_result().
'structural'(Input, Index) ->
p(Input, Index, 'structural',
fun(I, D) ->
(p_seq([p_string(<<"{">>), fun 'blank0'/2, p_zero_or_more(p_seq([fun 'field'/2, fun 'blank0'/2])), p_string(<<"}">>)]))(I, D)
end,
fun(Node, _Idx) ->
[_, _, List, _] = Node, [H || [H | _] <- List]
end).
-spec 'field'(input(), index()) -> parse_result().
'field'(Input, Index) ->
p(Input, Index, 'field',
fun(I, D) ->
(p_seq([p_label('datatype', fun 'typename'/2), fun 'blanks'/2, p_label('name', fun 'name'/2), fun 'blank0'/2, p_string(<<";">>)]))(I, D)
end,
fun(Node, _Idx) ->
DataType = binary_to_list(iolist_to_binary(proplists:get_value(datatype, Node))),
Name = binary_to_list(iolist_to_binary(proplists:get_value(name, Node))),
{DataType, Name}
end).
-spec 'eof'(input(), index()) -> parse_result().
'eof'(Input, Index) ->
p(Input, Index, 'eof',
fun(I, D) ->
(p_not(p_string(<<".">>)))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'newline'(input(), index()) -> parse_result().
'newline'(Input, Index) ->
p(Input, Index, 'newline',
fun(I, D) ->
(p_seq([p_optional(p_charclass(<<"[\r]">>)), p_charclass(<<"[\n]">>)]))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'line_comment'(input(), index()) -> parse_result().
'line_comment'(Input, Index) ->
p(Input, Index, 'line_comment',
fun(I, D) ->
(p_seq([p_choose([p_string(<<"//">>), p_string(<<"%">>)]), p_zero_or_more(p_seq([p_not(fun 'newline'/2), p_anything()])), p_choose([fun 'newline'/2, fun 'eof'/2])]))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'blank'(input(), index()) -> parse_result().
'blank'(Input, Index) ->
p(Input, Index, 'blank',
fun(I, D) ->
(p_choose([p_charclass(<<"[\s\t]">>), fun 'newline'/2, fun 'line_comment'/2]))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'blank0'(input(), index()) -> parse_result().
'blank0'(Input, Index) ->
p(Input, Index, 'blank0',
fun(I, D) ->
(p_zero_or_more(fun 'blank'/2))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'blanks'(input(), index()) -> parse_result().
'blanks'(Input, Index) ->
p(Input, Index, 'blanks',
fun(I, D) -> (p_one_or_more(fun 'blank'/2))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'alpha'(input(), index()) -> parse_result().
'alpha'(Input, Index) ->
p(Input, Index, 'alpha',
fun(I, D) ->
(p_choose([p_charclass(<<"[a-z]">>), p_charclass(<<"[A-Z]">>), p_string(<<"_">>), p_string(<<"[">>), p_string(<<"]">>)]))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'alnum'(input(), index()) -> parse_result().
'alnum'(Input, Index) ->
p(Input, Index, 'alnum',
fun(I, D) ->
(p_choose([fun 'alpha'/2, p_charclass(<<"[0-9]">>)]))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'word'(input(), index()) -> parse_result().
'word'(Input, Index) ->
p(Input, Index, 'word',
fun(I, D) ->
(p_seq([fun 'alpha'/2, p_zero_or_more(fun 'alnum'/2)]))(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'name'(input(), index()) -> parse_result().
'name'(Input, Index) ->
p(Input, Index, 'name',
fun(I, D) ->
(fun 'word'/2)(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-spec 'typename'(input(), index()) -> parse_result().
'typename'(Input, Index) ->
p(Input, Index, 'typename',
fun(I, D) ->
(fun 'word'/2)(I, D)
end,
fun(Node, _Idx) ->
Node
end).
-file("peg_includes.hrl", 1).
-type index() :: {{line, pos_integer()}, {column, pos_integer()}}.
-type input() :: binary().
-type parse_failure() :: {fail, term()}.
-type parse_success() :: {term(), input(), index()}.
-type parse_result() :: parse_failure() | parse_success().
-type parse_fun() :: fun((input(), index()) -> parse_result()).
-type xform_fun() :: fun((input(), index()) -> term()).
-spec p(input(), index(), atom(), parse_fun(), xform_fun()) -> parse_result().
p(Inp, StartIndex, Name, ParseFun, TransformFun) ->
case get_memo(StartIndex, Name) of % See if the current reduction is memoized
{ok, Memo} -> % If it is, return the stored result
Memo;
_ -> % If not, attempt to parse
Result =
case ParseFun(Inp, StartIndex) of
{fail, _} = Failure -> % If it fails, memoize the failure
Failure;
{Match, InpRem, NewIndex} -> % If it passes, transform and memoize the result.
Transformed = TransformFun(Match, StartIndex),
{Transformed, InpRem, NewIndex}
end,
memoize(StartIndex, Name, Result),
Result
end.
-spec setup_memo() -> list().
setup_memo() ->
erase().
-spec release_memo() -> list().
release_memo() ->
erase().
-spec memoize(index(), atom(), parse_result()) -> any().
memoize(Index, Name, Result) ->
case get(Index) of
undefined ->
put(Index, [{Name, Result}]);
[] ->
put(Index, [{Name, Result}]);
Plist ->
put(Index, [{Name, Result} | Plist])
end.
-spec get_memo(index(), atom()) -> {ok, term()} | {error, not_found}.
get_memo(Index, Name) ->
case get(Index) of
undefined ->
{error, not_found};
[] ->
{error, not_found};
Plist ->
case proplists:lookup(Name, Plist) of
{Name, Result} ->
{ok, Result};
_ ->
{error, not_found}
end
end.
-ifdef(p_eof).
-spec p_eof() -> parse_fun().
p_eof() ->
fun(<<>>, Index) ->
{eof, [], Index};
(_, Index) ->
{fail, {expected, eof, Index}} end.
-endif.
-ifdef(p_optional).
-spec p_optional(parse_fun()) -> parse_fun().
p_optional(P) ->
fun(Input, Index) ->
case P(Input, Index) of
{fail, _} ->
{[], Input, Index};
{_, _, _} = Success ->
Success
end
end.
-endif.
-ifdef(p_not).
-spec p_not(parse_fun()) -> parse_fun().
p_not(P) ->
fun(Input, Index) ->
case P(Input, Index) of
{fail, _} ->
{[], Input, Index};
{Result, _, _} ->
{fail, {expected, {no_match, Result}, Index}}
end
end.
-endif.
-ifdef(p_assert).
-spec p_assert(parse_fun()) -> parse_fun().
p_assert(P) ->
fun(Input, Index) ->
case P(Input, Index) of
{fail, _} = Failure ->
Failure;
_ ->
{[], Input, Index}
end
end.
-endif.
-ifdef(p_seq).
-spec p_seq([parse_fun()]) -> parse_fun().
p_seq(P) ->
fun(Input, Index) ->
p_all(P, Input, Index, [])
end.
-spec p_all([parse_fun()], input(), index(), [term()]) -> parse_result().
p_all([], Inp, Index, Accum) ->
{lists:reverse(Accum), Inp, Index};
p_all([P | Parsers], Inp, Index, Accum) ->
case P(Inp, Index) of
{fail, _} = Failure ->
Failure;
{Result, InpRem, NewIndex} ->
p_all(Parsers, InpRem, NewIndex, [Result | Accum])
end.
-endif.
-ifdef(p_choose).
-spec p_choose([parse_fun()]) -> parse_fun().
p_choose(Parsers) ->
fun(Input, Index) ->
p_attempt(Parsers, Input, Index, none)
end.
-spec p_attempt([parse_fun()], input(), index(), none | parse_failure()) -> parse_result().
p_attempt([], _Input, _Index, Failure) -> Failure;
p_attempt([P | Parsers], Input, Index, FirstFailure) ->
case P(Input, Index) of
{fail, _} = Failure ->
case FirstFailure of
none ->
p_attempt(Parsers, Input, Index, Failure);
_ ->
p_attempt(Parsers, Input, Index, FirstFailure)
end;
Result ->
Result
end.
-endif.
-ifdef(p_zero_or_more).
-spec p_zero_or_more(parse_fun()) -> parse_fun().
p_zero_or_more(P) ->
fun(Input, Index) ->
p_scan(P, Input, Index, [])
end.
-endif.
-ifdef(p_one_or_more).
-spec p_one_or_more(parse_fun()) -> parse_fun().
p_one_or_more(P) ->
fun(Input, Index) ->
Result = p_scan(P, Input, Index, []),
case Result of
{[_ | _], _, _} ->
Result;
_ ->
{fail, {expected, Failure, _}} = P(Input, Index),
{fail, {expected, {at_least_one, Failure}, Index}}
end
end.
-endif.
-ifdef(p_label).
-spec p_label(atom(), parse_fun()) -> parse_fun().
p_label(Tag, P) ->
fun(Input, Index) ->
case P(Input, Index) of
{fail, _} = Failure ->
Failure;
{Result, InpRem, NewIndex} ->
{{Tag, Result}, InpRem, NewIndex}
end
end.
-endif.
-ifdef(p_scan).
-spec p_scan(parse_fun(), input(), index(), [term()]) -> {[term()], input(), index()}.
p_scan(_, <<>>, Index, Accum) ->
{lists:reverse(Accum), <<>>, Index};
p_scan(P, Inp, Index, Accum) ->
case P(Inp, Index) of
{fail, _} ->
{lists:reverse(Accum), Inp, Index};
{Result, InpRem, NewIndex} ->
p_scan(P, InpRem, NewIndex, [Result | Accum])
end.
-endif.
-ifdef(p_string).
-spec p_string(binary()) -> parse_fun().
p_string(S) ->
Length = erlang:byte_size(S),
fun(Input, Index) ->
try
<<S:Length/binary, Rest/binary>> = Input,
{S, Rest, p_advance_index(S, Index)}
catch
error:{badmatch, _} ->
{fail, {expected, {string, S}, Index}}
end
end.
-endif.
-ifdef(p_anything).
-spec p_anything() -> parse_fun().
p_anything() ->
fun(<<>>, Index) ->
{fail, {expected, any_character, Index}};
(Input, Index) when is_binary(Input) ->
<<C/utf8, Rest/binary>> = Input,
{<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)}
end.
-endif.
-ifdef(p_charclass).
-spec p_charclass(string() | binary()) -> parse_fun().
p_charclass(Class) ->
{ok, RE} = re:compile(Class, [unicode, dotall]),
fun(Inp, Index) ->
case re:run(Inp, RE, [anchored]) of
{match, [{0, Length} | _]} ->
{Head, Tail} = erlang:split_binary(Inp, Length),
{Head, Tail, p_advance_index(Head, Index)};
_ ->
{fail, {expected, {character_class, binary_to_list(Class)}, Index}}
end
end.
-endif.
-ifdef(p_regexp).
-spec p_regexp(binary()) -> parse_fun().
p_regexp(Regexp) ->
{ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]),
fun(Inp, Index) ->
case re:run(Inp, RE) of
{match, [{0, Length} | _]} ->
{Head, Tail} = erlang:split_binary(Inp, Length),
{Head, Tail, p_advance_index(Head, Index)};
_ ->
{fail, {expected, {regexp, binary_to_list(Regexp)}, Index}}
end
end.
-endif.
-ifdef(line).
-spec line(index() | term()) -> pos_integer() | undefined.
line({{line, L}, _}) -> L;
line(_) -> undefined.
-endif.
-ifdef(column).
-spec column(index() | term()) -> pos_integer() | undefined.
column({_, {column, C}}) -> C;
column(_) -> undefined.
-endif.
-spec p_advance_index(input() | unicode:charlist() | pos_integer(), index()) -> index().
p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput) -> % strings
lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput));
p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters
{{line, Line}, {column, Col}} = Index,
case MatchedInput of
$\n -> {{line, Line + 1}, {column, 1}};
_ -> {{line, Line}, {column, Col + 1}}
end.

+ 1
- 0
test/genProto.bat Näytä tiedosto

@ -0,0 +1 @@
erl -pa ../ebin -s protoGen convertDir ../proto ./ ./

+ 285
- 0
test/protoMsg.erl Näytä tiedosto

@ -0,0 +1,285 @@
-module(protoMsg).
-export([encode/1, decode/1, encodeRec/1, decodeRec/2]).
-define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)).
-define(int8(V), <<V:8>>).
-define(uint8(V), <<V:8>>).
-define(int16(V), <<V:16/big>>).
-define(uint16(V), <<V:16/big>>).
-define(int32(V), <<V:32/big>>).
-define(uint32(V), <<V:32/big>>).
-define(int64(V), <<V:64/big>>).
-define(uint64(V), <<V:64/big>>).
-define(float(V), <<V:32/big-float>>).
-define(double(V), <<V:64/big-float>>).
-define(string(V), (string(V))).
-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_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]).
-define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]).
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].
encode(Record) ->
MsgBin = encodeRec(Record),
MsgId = getMsgId(element(1, Record)),
[<<MsgId:16/big>>, MsgBin].
decode(Bin) ->
<<MsgId:16/big, MsgBin/binary>> = Bin,
SchList = getMsgSchema(MsgId),
{<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]),
list_to_tuple(ResultList).
decodeRec(RecordName, Bin) ->
SchList = getMsgSchema(RecordName),
{LeftBin, Result} = decodeField(SchList, Bin, [RecordName]),
{LeftBin, list_to_tuple(Result)}.
decodeField([], LeftBin, Result) ->
{LeftBin, lists:reverse(Result)};
decodeField([Type | SchList], MsgBin, Result) ->
case Type of
int32 ->
<<Int:32/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint32 ->
<<Int:32/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
string ->
<<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [StrBin | Result]);
int16 ->
<<Int:16/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint16 ->
<<Int:16/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
int8 ->
<<Int:8/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint8 ->
<<Int:8/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
int64 ->
<<Int:64/big-signed, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
uint64 ->
<<Int:64/big-unsigned, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Int | Result]);
bool ->
<<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin,
case Bool =:= 1 of
true ->
decodeField(SchList, LeftBin, [true | Result]);
_ ->
decodeField(SchList, LeftBin, [false | Result])
end;
falat ->
<<Float:32/big-float, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Float | Result]);
double ->
<<Float:64/big-float, LeftBin/binary>> = MsgBin,
decodeField(SchList, LeftBin, [Float | Result]);
{list, int32} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt32List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint32} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint32List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int16} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt16List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint16} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint16List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int8} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt8List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint8} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint8List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, string} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deStringList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, int64} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deInt64List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, uint64} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deUint64List(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, bool} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deBoolList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, flat} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deFloatList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, double} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deDoubleList(Len, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
{list, RecordName} ->
<<Len:16/big, LeftListBin/binary>> = MsgBin,
{LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []),
decodeField(SchList, LeftBin, [RetList | Result]);
RecordName ->
<<IsUndef:8, LeftBin/binary>> = MsgBin,
case IsUndef of
0 ->
decodeField(SchList, LeftBin, [undefined | Result]);
_ ->
SubSchList = getMsgSchema(RecordName),
{SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]),
decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result])
end
end.
deBoolList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) ->
case Bool =:= 1 of
true ->
deBoolList(N - 1, LeftBin, [true | RetList]);
_ ->
deBoolList(N - 1, LeftBin, [false | RetList])
end.
deInt8List(0, MsgBin, RetList) ->
{MsgBin, RetList};
deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) ->
deInt8List(N - 1, LeftBin, [Int | RetList]).
deUint8List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) ->
deUint8List(N - 1, LeftBin, [Int | RetList]).
deInt16List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) ->
deInt16List(N - 1, LeftBin, [Int | RetList]).
deUint16List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) ->
deUint16List(N - 1, LeftBin, [Int | RetList]).
deInt32List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) ->
deInt32List(N - 1, LeftBin, [Int | RetList]).
deUint32List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) ->
deUint32List(N - 1, LeftBin, [Int | RetList]).
deInt64List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) ->
deInt64List(N - 1, LeftBin, [Int | RetList]).
deUint64List(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) ->
deUint64List(N - 1, LeftBin, [Int | RetList]).
deFloatList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) ->
deFloatList(N - 1, LeftBin, [Float | RetList]).
deDoubleList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) ->
deDoubleList(N - 1, LeftBin, [Float | RetList]).
deStringList(0, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) ->
deStringList(N - 1, LeftBin, [StrBin | RetList]).
deRecordList(0, _RecordName, MsgBin, RetList) ->
{MsgBin, lists:reverse(RetList)};
deRecordList(N, RecordName, MsgBin, RetList) ->
{LeftBin, Tuple} = decodeRec(RecordName, MsgBin),
deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]).
getMsgType(1)->
test;
getMsgType(2)->
phoneNumber;
getMsgType(3)->
person;
getMsgType(4)->
addressBook;
getMsgType(_) ->
undefined.
getMsgId(test)->
1;
getMsgId(phoneNumber)->
2;
getMsgId(person)->
3;
getMsgId(addressBook)->
4;
getMsgId(_) ->
0.
encodeRec({test, V1}) ->
[?string(V1)];
encodeRec({phoneNumber, V1, V2}) ->
[?record(V1), ?int32(V2)];
encodeRec({person, V1, V2, V3, V4}) ->
[?string(V1), ?int32(V2), ?string(V3), ?list_record(V4)];
encodeRec({addressBook, V1, V2}) ->
[?list_record(V1), ?list_record(V2)];
encodeRec(_) ->
[].
getMsgSchema(test)->
getMsgSchema(1);
getMsgSchema(1)->
[string];
getMsgSchema(phoneNumber)->
getMsgSchema(2);
getMsgSchema(2)->
[test,int32];
getMsgSchema(person)->
getMsgSchema(3);
getMsgSchema(3)->
[string,int32,string,{list,phoneNumber}];
getMsgSchema(addressBook)->
getMsgSchema(4);
getMsgSchema(4)->
[{list,person},{list,person}];
getMsgSchema(_) ->
[].

+ 28
- 0
test/protoMsg.hrl Näytä tiedosto

@ -0,0 +1,28 @@
-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 single() :: float().
-opaque double() :: float().
-record(test ,{
aa = "" :: string()
}).
-record(phoneNumber ,{
number = undefined :: #test{}
,type = 0 :: int32()
}).
-record(person ,{
name = "" :: string()
,id = 0 :: int32()
,email = "" :: string()
,phone = [] :: [#phoneNumber{}]
}).
-record(addressBook ,{
person = [] :: [#person{}]
,other = [] :: [#person{}]
}).

+ 3
- 0
test/remake.bat Näytä tiedosto

@ -0,0 +1,3 @@
#if not exist ebin md ebin
FOR %%f in (*.erl) DO erlc -W0 -o . %%f
pause

+ 319
- 0
test/test.erl Näytä tiedosto

@ -0,0 +1,319 @@
-module(test).
-include("protoMsg.hrl").
-compile(export_all).
hh1(0) ->
ok;
hh1(N) ->
A = [tt1,tt2,tt3,tt4,{tet,tt1},{tet, tt2},{tet,tt3}, yyy],
test(A),
hh1(N -1).
hh2(0) ->
ok;
hh2(N) ->
A = [tt1,tt2,tt3,tt4,{tet,tt1},{tet, tt2},{tet,tt3}, yyy],
tet(A),
hh2(N -1).
test([]) ->
ok;
test([A | T]) ->
case A of
tt1 ->
ok;
tt2 ->
ok;
tt3 ->
ok;
tt4 ->
ok;
{tet, tt1} ->
ok;
{tet, tt2} ->
ok;
{tet, tt3} ->
ok;
_ ->
ok
end,
test(T).
tet([]) ->
ok;
tet([tt1 | T]) ->
ok,
tet(T);
tet([tt2 | T]) ->
ok,
tet(T);
tet([tt3 | T]) ->
ok,
tet(T);
tet([tt4 | T]) ->
ok,
tet(T);
tet([{tet, tt1} | T]) ->
ok,
tet(T);
tet([{tet, tt2} | T]) ->
ok,
tet(T);
tet([{tet, tt3} | T]) ->
ok,
tet(T);
tet([YY | T]) ->
ok,
tet(T).
tt1(0)->
AddressBook = #addressBook{
person = [
#person{
name = "Alice",
id = 10000,
phone = [
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 },
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 }
]
},
#person{
name = "Bob",
id = 20000,
phone = [
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 }
]
}
]
},
Bin = protoMsg:encode(AddressBook);
tt1(N) ->
tt1(),
tt1(N- 1).
tt1() ->
AddressBook = #addressBook{
person = [
#person{
name = "Alice",
id = 10000,
phone = [
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 },
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 }
]
},
#person{
name = "Bob",
id = 20000,
phone = [
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 }
]
}
]
},
%"others" => [
% #{
% "name" => "Carol",
% "id" => 30000,
% "phone" => [
% #{ "number" => #{"aa" => "9876543210"} }
% ]
% }
%]
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] },
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 },
Bin = protoMsg:encode(AddressBook).
%ok = file:write_file("fff.bin", Bin),
%print_bin(Bin),
%Bin = protoCode:encode(AddressBook),
%ok = file:write_file("fff.bin", Bin),
%print_bin(Bin),
%MsgId = protoMsg:getMsgId(element(1, AddressBook)),
%<<MsgId:16/little, Bin/binary>>.
tt(N) ->
AddressBook = #addressBook{
person = [
#person{
name = "Alice",
id = 10000,
phone = [
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 },
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 }
]
},
#person{
name = "Bob",
id = 20000,
phone = [
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 }
]
}
]
},
%"others" => [
% #{
% "name" => "Carol",
% "id" => 30000,
% "phone" => [
% #{ "number" => #{"aa" => "9876543210"} }
% ]
% }
%]
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] },
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 },
Bin = protoMsg:encode(AddressBook),
%ok = file:write_file("fff.bin", Bin),
%print_bin(Bin),
tt(N, iolist_to_binary(Bin)).
tt(0, Bin) ->
protoMsg:decode(Bin);
tt(N, Bin) ->
protoMsg:decode(Bin),
tt(N-1, Bin).
%{Len, List, RestBin} = protoMsg("AddressBook", Bin),
%io:format("Len:~p, RestBin:~p~n", [Len, RestBin]),
%io:format("List:~p~n", [List]),
%{Map, _, _} = sproto:decode2("AddressBook", Bin),
%Map.
ttt1(0)->
AddressBook = #addressBook{
person = [
#person{
name = "Alice",
id = 10000,
phone = [
#phoneNumber{ number = #test{aa = "你好啊 嘿嘿"} , type = 1 },
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 }
]
},
#person{
name = "Bob",
id = 20000,
phone = [
#phoneNumber{number = #test{aa = "范德萨地方范德萨发"} , type = 3 }
]
}
]
},
term_to_binary(AddressBook);
ttt1(N) ->
ttt1(),
ttt1(N- 1).
ttt1() ->
AddressBook = #addressBook{
person = [
#person{
name = "Alice",
id = 10000,
phone = [
#phoneNumber{ number = #test{aa = "你好啊 嘿嘿"} , type = 1 },
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 }
]
},
#person{
name = "Bob",
id = 20000,
phone = [
#phoneNumber{number = #test{aa = "范德萨地方范德萨发"} , type = 3 }
]
}
]
},
%"others" => [
% #{
% "name" => "Carol",
% "id" => 30000,
% "phone" => [
% #{ "number" => #{"aa" => "9876543210"} }
% ]
% }
%]
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] },
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 },
Bin = term_to_binary(AddressBook).
%ok = file:write_file("fff.bin", Bin),
%print_bin(Bin),
%Bin = protoCode:encode(AddressBook),
%ok = file:write_file("fff.bin", Bin),
%print_bin(Bin),
%MsgId = protoMsg:getMsgId(element(1, AddressBook)),
%<<MsgId:16/little, Bin/binary>>.
ttt(N) ->
AddressBook = #addressBook{
person = [
#person{
name = "Alice",
id = 10000,
phone = [
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 },
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 }
]
},
#person{
name = "Bob",
id = 20000,
phone = [
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 }
]
}
]
},
%"others" => [
% #{
% "name" => "Carol",
% "id" => 30000,
% "phone" => [
% #{ "number" => #{"aa" => "9876543210"} }
% ]
% }
%]
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] },
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 },
%ok = file:write_file("fff.bin", Bin),
%print_bin(Bin),
ttt(N, term_to_binary(AddressBook)).
ttt(0, Bin) ->
binary_to_term(Bin);
ttt(N, Bin) ->
binary_to_term(Bin),
ttt(N-1, Bin).
print_bin(Bin) ->
ByteList = lists:reverse(bin_to_hex(Bin, [])),
Fun = fun(Byte, Acc) ->
io:format("~2.16.0b ", [Byte]),
case Acc rem 8 =:= 0 of
true -> io:format("~n", []);
false -> ok
end,
Acc + 1
end,
lists:foldl(Fun, 1, ByteList),
io:format("bytes:~p~n", [byte_size(Bin)]).
bin_to_hex(<<>>, Acc) ->
Acc;
bin_to_hex(Bin, Acc) ->
<<A:8, Bin2/binary>> = Bin,
bin_to_hex(Bin2, [A|Acc]).

Ladataan…
Peruuta
Tallenna