731 lines
30 KiB
Erlang
731 lines
30 KiB
Erlang
|
|
%%----------------------------------------------------
|
||
|
|
%% 协议生成工具
|
||
|
|
%% @author yeahoo2000@gmail.com
|
||
|
|
%% @end
|
||
|
|
%%----------------------------------------------------
|
||
|
|
-module(main).
|
||
|
|
-export([
|
||
|
|
compile/1
|
||
|
|
,compile/2
|
||
|
|
]
|
||
|
|
).
|
||
|
|
-include("common.hrl").
|
||
|
|
-include("protocol.hrl").
|
||
|
|
-include("condition.hrl").
|
||
|
|
-define(SRV_PATH, "../../server/src/proto/").
|
||
|
|
-define(CLI_PATH, "./cli/").
|
||
|
|
%% -define(SRV_PATH, "./out/").
|
||
|
|
|
||
|
|
compile(all) ->
|
||
|
|
compile(all, release).
|
||
|
|
compile(all, CType) ->
|
||
|
|
io:setopts([{encoding,unicode}]),
|
||
|
|
?P("---------------------------------~n"),
|
||
|
|
?P("> 正在生成协议...~n"),
|
||
|
|
?P("---------------------------------~n"),
|
||
|
|
List = cfg_file(),
|
||
|
|
put(rpc, []),
|
||
|
|
put(desc_fun, []),
|
||
|
|
put(log_title, []),
|
||
|
|
put(log_data, []),
|
||
|
|
put(lua_send, []),
|
||
|
|
put(lua_recv, []),
|
||
|
|
put(js_send, []),
|
||
|
|
put(js_recv, []),
|
||
|
|
all(List, CType),
|
||
|
|
gen_rpc_cfg(),
|
||
|
|
gen_lua(),
|
||
|
|
gen_js(),
|
||
|
|
?P("> 所有协议已生成~n"),
|
||
|
|
ok;
|
||
|
|
compile(Name, CType) ->
|
||
|
|
?P("===========~s~n", [Name]),
|
||
|
|
put(compile_type, CType),
|
||
|
|
Mod = list_to_atom(Name),
|
||
|
|
Info = Mod:info(),
|
||
|
|
L = Mod:cfg(),
|
||
|
|
[gen_js_pack(Rpc) || Rpc <- L],
|
||
|
|
[gen_js_unpack(Rpc) || Rpc <- L],
|
||
|
|
[gen_lua_pack(Rpc) || Rpc <- L],
|
||
|
|
[gen_lua_unpack(Rpc) || Rpc <- L],
|
||
|
|
%% spawn_link(fun() -> gen_as_cmd(L) end),
|
||
|
|
gen_srv_proto(Mod, Info, L),
|
||
|
|
rpc_cfg(L),
|
||
|
|
ok.
|
||
|
|
|
||
|
|
%% 处理所有命令
|
||
|
|
all([], _CType) -> ok;
|
||
|
|
all([H | T], CType) ->
|
||
|
|
compile(H, CType),
|
||
|
|
all(T, CType).
|
||
|
|
|
||
|
|
gen_srv_proto(Mod, {Description, IncFiles}, L) ->
|
||
|
|
Inc = ["\n-include(\"" ++ X ++ "\")." || X <- IncFiles],
|
||
|
|
Pack = lists:concat([gen_erl_pack(cli, Code, ReqFields) ++ gen_erl_pack(srv, Code, ReplyFields) || #rpc{code = Code, req = ReqFields, reply = ReplyFields} <- L]),
|
||
|
|
Unpack = lists:concat([gen_erl_unpack(srv, Code, ReqFields) ++ gen_erl_unpack(cli, Code, ReplyFields) || #rpc{code = Code, req = ReqFields, reply = ReplyFields} <- L]),
|
||
|
|
PackMate = lists:concat([gen_erl_pack_mate(Code, ReplyFields) || #rpc{code = Code, reply = ReplyFields = [_ | _]} <- L, lists:member(Code, [20000, 20002, 20004, 20020, 20027])]),
|
||
|
|
ConvertData = lists:concat([gen_erl_convert_data(Code, ReplyFields) || #rpc{code = Code, reply = ReplyFields} <- L, lists:member(Code, [20000,20002,20004, 20020,20027])]),
|
||
|
|
Vars = [
|
||
|
|
{description, Description}
|
||
|
|
,{include_file, Inc}
|
||
|
|
,{mod_name, Mod}
|
||
|
|
,{pack_fun, Pack}
|
||
|
|
,{unpack_fun, Unpack}
|
||
|
|
,{pack_mate_fun, unicode:characters_to_binary(PackMate)}
|
||
|
|
,{convert_data, ConvertData}
|
||
|
|
],
|
||
|
|
Text = cn_str(util:template("./tpl/server.tpl.erl", cn_vars(Vars))),
|
||
|
|
case file:write_file(lists:concat([?SRV_PATH, Mod, ".erl"]), Text) of
|
||
|
|
ok -> ok; %% ?P("> ~ts.erl~n", [Mod]);
|
||
|
|
Err -> ?P("生成协议[~ts]时发生异常: ~w~n", [Mod, Err])
|
||
|
|
end.
|
||
|
|
|
||
|
|
%% 保存rpc_cfg内容
|
||
|
|
gen_rpc_cfg() ->
|
||
|
|
Vars = [{rpc, lists:reverse(get(rpc))}, {desc_fun, lists:reverse(get(desc_fun))}, {log_title, lists:reverse(get(log_title))}, {log_data, lists:reverse(get(log_data))}],
|
||
|
|
Text = cn_str(util:template("./tpl/rpc_cfg.tpl.erl", cn_vars(Vars))),
|
||
|
|
case file:write_file(lists:concat([?SRV_PATH, "rpc_cfg.erl"]), Text) of
|
||
|
|
ok -> ?P("> rpc_cfg.erl~n");
|
||
|
|
Err -> ?P("生成rpc_cfg.erl时发生异常: ~w~n", [Err])
|
||
|
|
end.
|
||
|
|
|
||
|
|
%% 保存lua文件
|
||
|
|
gen_lua() ->
|
||
|
|
Vars = [
|
||
|
|
{lua_send, string:join(lists:reverse(get(lua_send)), ",\n")}
|
||
|
|
,{lua_recv, string:join(lists:reverse(get(lua_recv)), ",\n")}
|
||
|
|
],
|
||
|
|
Text = cn_str(util:template("./tpl/client.tpl.lua", cn_vars(Vars))),
|
||
|
|
case file:write_file(lists:concat([?CLI_PATH, "proto_mate.lua"]), Text) of
|
||
|
|
ok -> ?P("> proto_mate.lua~n");
|
||
|
|
Err -> ?P("生成proto_mate.lua时发生异常: ~w~n", [Err])
|
||
|
|
end.
|
||
|
|
|
||
|
|
%% 保存js文件
|
||
|
|
gen_js() ->
|
||
|
|
Vars = [
|
||
|
|
{js_send, string:join(lists:reverse(get(js_send)), ",\n")}
|
||
|
|
,{js_recv, string:join(lists:reverse(get(js_recv)), ",\n")}
|
||
|
|
],
|
||
|
|
Text = cn_str(util:template("./tpl/client.tpl.js", cn_vars(Vars))),
|
||
|
|
case file:write_file(lists:concat([?CLI_PATH, "proto_mate.js"]), Text) of
|
||
|
|
ok -> ?P("> proto_mate.js~n");
|
||
|
|
Err -> ?P("生成proto_mate.js时发生异常: ~w~n", [Err])
|
||
|
|
end.
|
||
|
|
|
||
|
|
cn_vars(Vars) ->
|
||
|
|
[{K, unicode:characters_to_binary(util:to_list(V))} || {K, V} <- Vars].
|
||
|
|
|
||
|
|
cn_str(Str) ->
|
||
|
|
unicode:characters_to_binary(unicode:characters_to_list(list_to_bitstring(Str))).
|
||
|
|
|
||
|
|
%% 生成rpc配置内容
|
||
|
|
rpc_cfg([]) -> ok;
|
||
|
|
rpc_cfg([H | T]) ->
|
||
|
|
do_rpc_cfg(H),
|
||
|
|
rpc_cfg(T).
|
||
|
|
do_rpc_cfg(Rpc = #rpc{log_title = LogTitle, code = Code, req = ReqFields, req_desc = ReqDesc, reply = ReplyFields, reply_desc = ReplyDesc}) ->
|
||
|
|
put(code, Code),
|
||
|
|
R = Rpc#rpc{
|
||
|
|
req_desc = {rpc_cfg, desc_fun, {req, Code}}
|
||
|
|
,log_title = undefined
|
||
|
|
,req = undefined
|
||
|
|
,reply_desc = {rpc_cfg, desc_fun, {reply, Code}}
|
||
|
|
,reply = undefined
|
||
|
|
},
|
||
|
|
case is_list(ReqFields) of
|
||
|
|
true when LogTitle =:= undefined orelse LogTitle =:= "" ->
|
||
|
|
%% ?P("协议号[~w]允许请求但日志标题[log_title]为空,请填写日志标题[log_title]~n", [Code]);
|
||
|
|
ok;
|
||
|
|
true ->
|
||
|
|
case put({log_title, LogTitle}, 1) of
|
||
|
|
undefined -> skip;
|
||
|
|
_ -> ?P("协议号[~w]日志标题[log_title]出现重复值: ~ts~n", [Code, LogTitle])
|
||
|
|
end;
|
||
|
|
_ -> skip
|
||
|
|
end,
|
||
|
|
S = lists:concat(["get(", Code, ") ->\n", s(1), util:to_string(R), ";\n\n"]),
|
||
|
|
put(rpc, [S | get(rpc)]),
|
||
|
|
case ReqDesc of
|
||
|
|
[_ | _] ->
|
||
|
|
F1 = lists:concat(["desc_fun({req, ", Code, "}, _Data)-> ", cdesc(ReqDesc, ReqFields), ";\n"]),
|
||
|
|
put(desc_fun, [F1 | get(desc_fun)]);
|
||
|
|
_ -> skip
|
||
|
|
end,
|
||
|
|
case ReplyDesc of
|
||
|
|
[_ | _] ->
|
||
|
|
F2 = lists:concat(["desc_fun({reply, ", Code, "}, _Data)-> ", cdesc(ReplyDesc, ReplyFields), ";\n"]),
|
||
|
|
put(desc_fun, [F2 | get(desc_fun)]);
|
||
|
|
_ -> skip
|
||
|
|
end,
|
||
|
|
case LogTitle of
|
||
|
|
[_ | _] ->
|
||
|
|
LTitle = lists:concat(["log_title(", Code, ", _Data)-> ", cdesc(LogTitle, []), ";\n"]),
|
||
|
|
put(log_title, [LTitle | get(log_title)]);
|
||
|
|
_ -> skip
|
||
|
|
end,
|
||
|
|
case gen_log_data(ReqFields, 1, "", "", false) of
|
||
|
|
{ok, D1, D2} ->
|
||
|
|
LData = lists:concat(["log_data(", Code, ", ", D1, ") -> ", D2, ";\n"]),
|
||
|
|
put(log_data, [LData | get(log_data)]);
|
||
|
|
_ -> skip
|
||
|
|
end.
|
||
|
|
gen_log_data([], _N, DL1, DL2, true) ->
|
||
|
|
{ok, "{" ++ string:join(lists:reverse(DL1), ", ") ++ "}", "{" ++ string:join(lists:reverse(DL2), ", ") ++ "}"};
|
||
|
|
gen_log_data([{string, _, _} | T], N, DL1, DL2, _Flag) ->
|
||
|
|
V = lists:concat(["_V", N]),
|
||
|
|
gen_log_data(T, N + 1, [V | DL1], DL2, true);
|
||
|
|
gen_log_data([_ | T], N, DL1, DL2, Flag) ->
|
||
|
|
V = lists:concat(["V", N]),
|
||
|
|
gen_log_data(T, N + 1, [V | DL1], [V | DL2], Flag);
|
||
|
|
gen_log_data(_, _N, _DL1, _DL2, _Flag) ->
|
||
|
|
false.
|
||
|
|
|
||
|
|
%% record_to_string(L, Rec) ->
|
||
|
|
%% S = r2s(L, []),
|
||
|
|
%% lists:concat(["#", Rec, "{", S, "}"]).
|
||
|
|
%%
|
||
|
|
%% r2s([], Str) -> t(lists:concat(lists:reverse(Str)));
|
||
|
|
%% r2s([{K, V} | T], Str) ->
|
||
|
|
%% S = lists:concat([K, " = ", V, ", "]),
|
||
|
|
%% r2s(T, [S | Str]).
|
||
|
|
|
||
|
|
%% 生成日志格式化代码
|
||
|
|
cdesc(undefined, _) -> "\"\"";
|
||
|
|
cdesc({Desc, Vars}, Fields) ->
|
||
|
|
V = vals(Vars, Fields, []),
|
||
|
|
lists:concat(["io_lib:format(\"", Desc, "\", [", V, "])"]);
|
||
|
|
cdesc(Desc, _) ->
|
||
|
|
lists:concat(["\"", Desc, "\""]).
|
||
|
|
|
||
|
|
%% 生成取值代码
|
||
|
|
vals([], _F, L) -> string:join(lists:reverse(L), ", ");
|
||
|
|
vals([N | T], F, L) ->
|
||
|
|
P = pos(F, 1, N),
|
||
|
|
vals(T, F, [?S("element(~w, _Data)", [P]) | L]).
|
||
|
|
|
||
|
|
%% 定位某项在list中的位置
|
||
|
|
pos([], _P, N) ->
|
||
|
|
?ERR("[Code: ~w]的desc项配置有误,没有找到对应的项[~ts]", [get(code), N]),
|
||
|
|
exit(error);
|
||
|
|
pos([{_, N, _} | _T], P, N) -> P;
|
||
|
|
pos([{_, N, _, _} | _T], P, N) -> P;
|
||
|
|
pos([{_, _, N, _, _} | _T], P, N) -> P;
|
||
|
|
pos([_ | T], P, N) -> pos(T, P + 1, N).
|
||
|
|
|
||
|
|
%% 生成打包函数
|
||
|
|
gen_erl_pack(_Type, _Code, undefined) -> %% 不支持请求的协议
|
||
|
|
"";
|
||
|
|
gen_erl_pack(Type, Code, []) ->
|
||
|
|
lists:concat(["\n\npack(", Code, ", ", Type, ", {}) ->\n", s(1), "{ok, <<2:32, ", Code, ":16>>};"]);
|
||
|
|
gen_erl_pack(Type, Code, {RecordName, Fields}) ->
|
||
|
|
put(code, Code),
|
||
|
|
Vars = lists:concat(["#", RecordName, "{", vr(Fields, 0), "}"]),
|
||
|
|
reset_var(0),
|
||
|
|
Txt = erl_pack(Fields, 0, []),
|
||
|
|
lists:concat(["\n\npack(", Code, ", ", Type, ", ", Vars, ") ->\n", s(1), "D_a_t_a = ", Txt, ",\n", s(1),"{ok, <<(byte_size(D_a_t_a) + 2):32, ", Code, ":16, D_a_t_a/binary>>};"]);
|
||
|
|
gen_erl_pack(Type, Code, Fields) ->
|
||
|
|
put(code, Code),
|
||
|
|
reset_var(0),
|
||
|
|
Txt = erl_pack(Fields, 0, []),
|
||
|
|
Vars = "{" ++ v(Fields, 0) ++ "}",
|
||
|
|
lists:concat(["\n\npack(", Code, ", ", Type, ", ", Vars, ") ->\n", s(1), "D_a_t_a = ", Txt, ",\n", s(1),"{ok, <<(byte_size(D_a_t_a) + 2):32, ", Code, ":16, D_a_t_a/binary>>};"]).
|
||
|
|
|
||
|
|
%% 处理record项
|
||
|
|
erl_pack([], _Deep, Vars) ->
|
||
|
|
V = t(lists:concat(lists:reverse(Vars))),
|
||
|
|
"<<" ++ V ++ ">>";
|
||
|
|
erl_pack([{int8, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ":8/signed, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{uint8, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ":8, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{int16, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ":16/signed, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{uint16, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ":16, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{int32, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ":32/signed, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{uint32, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ":32, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{float, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
V = lists:concat(["V", Deep, "_", N, "/float, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{binary, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
V = lists:concat(["(protocol:pack(binary, ", X, "))/binary, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{string, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
V = lists:concat(["(protocol:pack(string, ", X, "))/binary, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{byte, N, _} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
V = lists:concat(["(protocol:pack(byte, ", X, "))/binary, "]),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{tuple, _N, Fields} | T], Deep, Vars) ->
|
||
|
|
%% @wpf 增加单个tuple元素的解析方法
|
||
|
|
A = t(erl_pack(Fields, Deep, [])),
|
||
|
|
A1 = lists:reverse(t(lists:reverse(A))),
|
||
|
|
A2 = lists:concat([A1, ", "]),
|
||
|
|
erl_pack(T, Deep, [A2 | Vars]);
|
||
|
|
erl_pack([{array, Type, _N1, N2, Desc, Fields} | T], Deep, Vars) ->
|
||
|
|
erl_pack([{array, Type, N2, Desc, Fields} | T], Deep, Vars);
|
||
|
|
erl_pack([{array, tuple, N, _, Fields} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
S = "{" ++ v(Fields, Deep + 1) ++ "}",
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
reset_var(Deep + 1),
|
||
|
|
A = erl_pack(Fields, Deep + 1, []),
|
||
|
|
V = pack_erl_array(A, S, X),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{array, list, N, _, Fields} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
S = "[" ++ v(Fields, Deep + 1) ++ "]",
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
reset_var(Deep + 1),
|
||
|
|
A = erl_pack(Fields, Deep + 1, []),
|
||
|
|
V = pack_erl_array(A, S, X),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{array, single, N, _, Fields} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
S = v(Fields, Deep + 1),
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
reset_var(Deep + 1),
|
||
|
|
A = erl_pack(Fields, Deep + 1, []),
|
||
|
|
V = pack_erl_array(A, S, X),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{array, new_map, N, _, Fields} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
S = lists:concat(["#{", vmap(Fields, Deep + 1), "}"]),
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
reset_var(Deep + 1),
|
||
|
|
A = erl_pack(Fields, Deep + 1, []),
|
||
|
|
V = pack_erl_array(A, S, X),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{array, RecordName, N, _, Fields} | T], Deep, Vars) ->
|
||
|
|
add_var(Deep, N),
|
||
|
|
S = lists:concat(["#", RecordName, "{", vr(Fields, Deep + 1), "}"]),
|
||
|
|
X = lists:concat(["V", Deep, "_", N]),
|
||
|
|
reset_var(Deep + 1),
|
||
|
|
A = erl_pack(Fields, Deep + 1, []),
|
||
|
|
V = pack_erl_array(A, S, X),
|
||
|
|
erl_pack(T, Deep, [V | Vars]);
|
||
|
|
erl_pack([{rec, _N, _RecN, Fields} | T], Deep, Vars) ->
|
||
|
|
erl_pack(Fields ++ T, Deep, Vars);
|
||
|
|
erl_pack([{Type, _N, N, Desc} | T], Deep, Vars) ->
|
||
|
|
erl_pack([{Type, N, Desc} | T], Deep, Vars);
|
||
|
|
erl_pack([{_, N, _} | _T], _Deep, _Vars) ->
|
||
|
|
?ERR("[code: ~w]的[~w]项配置有误", [get(code), N]),
|
||
|
|
exit(error);
|
||
|
|
erl_pack([{_, _, N, _, _} | _T], _Deep, _Vars) ->
|
||
|
|
?ERR("[code: ~w]的[~w]项配置有误", [get(code), N]),
|
||
|
|
exit(error).
|
||
|
|
pack_erl_array(A, S, X) ->
|
||
|
|
case get(compile_type) of
|
||
|
|
debug -> lists:concat(["(length(", X, ")):16, (list_to_binary(lists:map(fun(", S, ") -> ", A, " end, ", X, ")))/binary, "]);
|
||
|
|
_ -> lists:concat(["(length(", X, ")):16, (list_to_binary([", A, " || ", S, " <- ", X, "]))/binary, "])
|
||
|
|
end.
|
||
|
|
|
||
|
|
%% 获取变量名字串
|
||
|
|
v(Fields, Deep) ->
|
||
|
|
v(Fields, Deep, []).
|
||
|
|
v([], _Deep, Vars) -> t(lists:concat(lists:reverse(Vars)));
|
||
|
|
v([{tuple, _Name, Fields} | T], Deep, Vars) ->
|
||
|
|
V = "{" ++ v(Fields, Deep) ++ "}, ",
|
||
|
|
v(T, Deep, [V | Vars]);
|
||
|
|
v([{array, Type, _N1, N2, Desc, Fields} | T], Deep, Vars) ->
|
||
|
|
v([{array, Type, N2, Desc, Fields} | T], Deep, Vars);
|
||
|
|
v([{array, _, N, _, _} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ", "]),
|
||
|
|
v(T, Deep, [V | Vars]);
|
||
|
|
v([{rec, _N, new_map, Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat(["#{", vmap(Fields, Deep), "}, "]),
|
||
|
|
v(T, Deep, [V | Vars]);
|
||
|
|
v([{rec, _N, RecN, Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat(["#", RecN, "{", vr(Fields, Deep), "}, "]),
|
||
|
|
v(T, Deep, [V | Vars]);
|
||
|
|
v([{Type, Name, Desc} | T], Deep, Vars) ->
|
||
|
|
v([{Type, Name, Name, Desc} | T], Deep, Vars);
|
||
|
|
v([{_, _, N, _} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat(["V", Deep, "_", N, ", "]),
|
||
|
|
v(T, Deep, [V | Vars]).
|
||
|
|
|
||
|
|
%% 获取记录名字串
|
||
|
|
vr(Fields, Deep) ->
|
||
|
|
vr(Fields, Deep, []).
|
||
|
|
vr([], _Deep, Vars) -> t(lists:concat(lists:reverse(Vars)));
|
||
|
|
vr([{tuple, N, L} | T], Deep, Vars) ->
|
||
|
|
%% @wpf 增加记录中的单个元素是tuple类型的数据解析
|
||
|
|
V = lists:concat([N, " = {", v(L, Deep), "}, "]),
|
||
|
|
vr(T, Deep, [V | Vars]);
|
||
|
|
vr([{array, _Type, N1, N2, _Desc, _Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N1, " = V", Deep, "_", N2, ", "]),
|
||
|
|
vr(T, Deep, [V | Vars]);
|
||
|
|
vr([{array, _, N, _, _} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N, " = V", Deep, "_", N, ", "]),
|
||
|
|
vr(T, Deep, [V | Vars]);
|
||
|
|
vr([{rec, N, new_map, Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N , " = #{", vmap(Fields, Deep), "}, "]),
|
||
|
|
vr(T, Deep, [V | Vars]);
|
||
|
|
vr([{rec, N, RecN, Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N , " = #", RecN, "{", vr(Fields, Deep), "}, "]),
|
||
|
|
vr(T, Deep, [V | Vars]);
|
||
|
|
vr([{Type, Name, Desc} | T], Deep, Vars) ->
|
||
|
|
vr([{Type, Name, Name, Desc} | T], Deep, Vars);
|
||
|
|
vr([{_, N1, N2, _} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N1, " = V", Deep, "_", N2, ", "]),
|
||
|
|
vr(T, Deep, [V | Vars]).
|
||
|
|
|
||
|
|
%% 获取记录名字串
|
||
|
|
vmap(Fields, Deep) ->
|
||
|
|
vmap(Fields, Deep, []).
|
||
|
|
vmap([], _Deep, Vars) -> t(lists:concat(lists:reverse(Vars)));
|
||
|
|
vmap([{tuple, N, L} | T], Deep, Vars) ->
|
||
|
|
%% @wpf 增加记录中的单个元素是tuple类型的数据解析
|
||
|
|
V = lists:concat([N, " := {", v(L, Deep), "}, "]),
|
||
|
|
vmap(T, Deep, [V | Vars]);
|
||
|
|
vmap([{array, _Type, N1, N2, _Desc, _Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N1, " := V", Deep, "_", N2, ", "]),
|
||
|
|
vmap(T, Deep, [V | Vars]);
|
||
|
|
vmap([{array, _, N, _, _} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N, " := V", Deep, "_", N, ", "]),
|
||
|
|
vmap(T, Deep, [V | Vars]);
|
||
|
|
vmap([{rec, N, new_map, Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N , " := #{", vmap(Fields, Deep), "}, "]),
|
||
|
|
vmap(T, Deep, [V | Vars]);
|
||
|
|
vmap([{rec, N, RecN, Fields} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N , " := #", RecN, "{", vr(Fields, Deep), "}, "]),
|
||
|
|
vmap(T, Deep, [V | Vars]);
|
||
|
|
vmap([{Type, Name, Desc} | T], Deep, Vars) ->
|
||
|
|
vmap([{Type, Name, Name, Desc} | T], Deep, Vars);
|
||
|
|
vmap([{_, N1, N2, _} | T], Deep, Vars) ->
|
||
|
|
V = lists:concat([N1, " := V", Deep, "_", N2, ", "]),
|
||
|
|
vmap(T, Deep, [V | Vars]).
|
||
|
|
|
||
|
|
%% 生成解包函数
|
||
|
|
gen_erl_unpack(_Type, _Code, undefined) ->
|
||
|
|
"";
|
||
|
|
gen_erl_unpack(Type, Code, []) ->
|
||
|
|
lists:concat(["\n\nunpack(", Code, ", ", Type, ", _B0) ->\n", s(1), "{ok, {}};"]);
|
||
|
|
gen_erl_unpack(Type, Code, {_RecordName, Fields}) ->
|
||
|
|
gen_erl_unpack(Type, Code, Fields);
|
||
|
|
gen_erl_unpack(Type, Code, Fields) ->
|
||
|
|
{_Idx, _Deep, Txt} = erl_unpack(Fields, 0, 1, [], []),
|
||
|
|
lists:concat(["\n\nunpack(", Code, ", ", Type, ", _B0) ->\n", Txt, ";"]).
|
||
|
|
erl_unpack([], Idx, Deep, Vars, Str) ->
|
||
|
|
V = case Deep =:= 1 of
|
||
|
|
true ->
|
||
|
|
lists:concat([s(1), "{ok, {", t(lists:concat([N ++ ", " || N <- lists:reverse(Vars)])), "}}"]);
|
||
|
|
false ->
|
||
|
|
case erase(array_type) of
|
||
|
|
single ->
|
||
|
|
lists:concat([s(Deep), "{", t(lists:concat([N ++ ", " || N <- lists:reverse(Vars)])), ", _B", Idx, "}"]);
|
||
|
|
_ ->
|
||
|
|
lists:concat([s(Deep), "{{", t(lists:concat([N ++ ", " || N <- lists:reverse(Vars)])), "}, _B", Idx, "}"])
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
S = lists:concat(lists:reverse(Str)),
|
||
|
|
{Idx + 1, Deep, S ++ V};
|
||
|
|
erl_unpack([{array, Type, _Name1, Name2, Desc, Fields} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
erl_unpack([{array, Type, Name2, Desc, Fields} | T], Idx, Deep, Vars, Str);
|
||
|
|
erl_unpack([{array, _Type, Name, _Desc, Fields} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
V = lists:concat(["V", Deep, "_", Name]),
|
||
|
|
X = s(Deep),
|
||
|
|
put(array_type, _Type),
|
||
|
|
{Idx1, Deep1, Txt} = erl_unpack(Fields, Idx + 1, Deep + 1, [], []),
|
||
|
|
S = lists:concat([X, "{", V, ", _B", Idx1 + 1, "} = protocol:array(_B", Idx, ", fun(_B", Idx +1, ") ->\n", Txt, "\n", X, "end),\n"]),
|
||
|
|
erl_unpack(T, Idx1 + 1, Deep1 - 1, [V | Vars], [S | Str]);
|
||
|
|
erl_unpack([{tuple, _Name, Fields} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
%% @wpf 增加记录中的单个元素是tuple类型的数据解析
|
||
|
|
{NewIdx, NewV, NewS} = erl_unpack_tuple(Fields, Idx, Deep, Vars, Str),
|
||
|
|
erl_unpack(T, NewIdx, Deep, NewV, NewS);
|
||
|
|
erl_unpack([{rec, _N, _RecN, Fields} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
erl_unpack(Fields ++ T, Idx, Deep, Vars, Str);
|
||
|
|
erl_unpack([{Type, Name, Desc} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
erl_unpack([{Type, Name, Name, Desc} | T], Idx, Deep, Vars, Str);
|
||
|
|
erl_unpack([{Type, _, Name, _Desc} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
V = lists:concat(["V", Deep, "_", Name]),
|
||
|
|
X = s(Deep),
|
||
|
|
S = lists:concat([X, "{", V, ", _B", Idx + 1, "} = protocol:", Type, "(_B", Idx, "),\n"]),
|
||
|
|
erl_unpack(T, Idx + 1, Deep, [V | Vars], [S | Str]).
|
||
|
|
%% 添加的tuple组合
|
||
|
|
%% @wpf 增加记录中的单个元素是tuple类型的数据解析
|
||
|
|
erl_unpack_tuple([], Idx, _Deep, Vars, Str) ->
|
||
|
|
{Idx, Vars, Str};
|
||
|
|
erl_unpack_tuple([{array, Type, _Name1, Name2, Desc, Fields} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
erl_unpack_tuple([{array, Type, Name2, Desc, Fields} | T], Idx, Deep, Vars, Str);
|
||
|
|
erl_unpack_tuple([{array, _Type, Name, _Desc, Fields} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
V = lists:concat(["V", Deep, "_", Name]),
|
||
|
|
X = s(Deep),
|
||
|
|
{Idx1, _Deep1, Txt} = erl_unpack_tuple(Fields, Idx + 1, Deep + 1, [], []),
|
||
|
|
S = lists:concat([X, "{", V, ", _B", Idx1 + 1, "} = protocol:array(_B", Idx, ", fun(_B", Idx +1, ") ->\n", Txt, "\n", X, "end),\n"]),
|
||
|
|
erl_unpack_tuple(T, Idx1 + 1, Deep + 1, [V | Vars], [S | Str]);
|
||
|
|
erl_unpack_tuple([{Type, Name, Desc} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
erl_unpack_tuple([{Type, Name, Name, Desc} | T], Idx, Deep, Vars, Str);
|
||
|
|
erl_unpack_tuple([{Type, _N, Name, _Desc} | T], Idx, Deep, Vars, Str) ->
|
||
|
|
V = lists:concat(["V", Deep, "_", Name]),
|
||
|
|
X = s(Deep),
|
||
|
|
S = lists:concat([X, "{", V, ", _B", Idx + 1, "} = protocol:", Type, "(_B", Idx, "),\n"]),
|
||
|
|
erl_unpack_tuple(T, Idx + 1, Deep, [V | Vars], [S | Str]).
|
||
|
|
|
||
|
|
%% 打包协议描述
|
||
|
|
gen_erl_pack_mate(Code, L) ->
|
||
|
|
Bin = gen_erl_pack_mate_(L, <<(length(L)):8>>),
|
||
|
|
lists:concat(["\pack_mate(", Code, ") -> ", ?S("~w", [Bin]) , ";\n"]).
|
||
|
|
gen_erl_pack_mate_([], Bin) ->
|
||
|
|
Bin;
|
||
|
|
gen_erl_pack_mate_([{int8, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_int8:8>>);
|
||
|
|
gen_erl_pack_mate_([{uint8, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_uint8:8>>);
|
||
|
|
gen_erl_pack_mate_([{int16, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_int16:8>>);
|
||
|
|
gen_erl_pack_mate_([{uint16, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_uint16:8>>);
|
||
|
|
gen_erl_pack_mate_([{int32, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_int32:8>>);
|
||
|
|
gen_erl_pack_mate_([{uint32, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_uint32:8>>);
|
||
|
|
gen_erl_pack_mate_([{string, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_string:8>>);
|
||
|
|
gen_erl_pack_mate_([{byte, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_byte:8>>);
|
||
|
|
gen_erl_pack_mate_([{array, _, _, _, Fields} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(Fields ++ T, <<Bin/binary, ?proto_array:8, (length(Fields)):8>>);
|
||
|
|
gen_erl_pack_mate_([{array_map, _, _, Fields} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(Fields ++ T, <<Bin/binary, ?proto_array:8, (length(Fields)):8>>);
|
||
|
|
gen_erl_pack_mate_([{float, _, _} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(T, <<Bin/binary, ?proto_float:8>>);
|
||
|
|
gen_erl_pack_mate_([{tuple, _, Fields} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(Fields ++ T, Bin);
|
||
|
|
gen_erl_pack_mate_([{rec, _, _, Fields} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_(Fields ++ T, Bin);
|
||
|
|
gen_erl_pack_mate_([{Type, _N1, N2, N3} | T], Bin) ->
|
||
|
|
gen_erl_pack_mate_([{Type, N2, N3} | T], Bin).
|
||
|
|
|
||
|
|
%% 生成版本数据转换
|
||
|
|
gen_erl_convert_data(Code, List) ->
|
||
|
|
Txt = convert_data_tuple(List, undefined, 1, 1, "Data", []),
|
||
|
|
lists:concat(["convert_data(", Code, ", Data) ->\n ", Txt, ";\n\n"]).
|
||
|
|
convert_data_tuple([], undefined, _Pos, _Deep, _Data, L) ->
|
||
|
|
lists:concat(["#{", string:join(lists:reverse(L), ", "), "}"]);
|
||
|
|
convert_data_tuple([], RecName, _Pos, _Deep, _Data, L) ->
|
||
|
|
lists:concat(["#", RecName, "{", string:join(lists:reverse(L), ", "), "}"]);
|
||
|
|
convert_data_tuple([{Type, Name, _Desc} | T], RecName, Pos, Deep, Data, L)
|
||
|
|
when Type =:= int8
|
||
|
|
orelse Type =:= uint8
|
||
|
|
orelse Type =:= int16
|
||
|
|
orelse Type =:= uint16
|
||
|
|
orelse Type =:= int32
|
||
|
|
orelse Type =:= uint32
|
||
|
|
->
|
||
|
|
S = convert_data_pos(Data, RecName, Pos, Name, int),
|
||
|
|
convert_data_tuple(T, RecName, Pos + 1, Deep, Data, [S | L]);
|
||
|
|
convert_data_tuple([{Type, Name, _Desc} | T], RecName, Pos, Deep, Data, L)
|
||
|
|
when Type =:= string
|
||
|
|
orelse Type =:= binary
|
||
|
|
orelse Type =:= byte
|
||
|
|
->
|
||
|
|
S = convert_data_pos(Data, RecName, Pos, Name, str),
|
||
|
|
convert_data_tuple(T, RecName, Pos + 1, Deep, Data, [S | L]);
|
||
|
|
convert_data_tuple([{tuple, Name, Fields} | T], RecName, Pos, Deep, Data, L) ->
|
||
|
|
Data1 = ?S("V~w_~w", [Deep, Name]),
|
||
|
|
S = case RecName of
|
||
|
|
undefined ->
|
||
|
|
?S("~w=>begin ~s=?pcd(~s,~w,tuple),~s end", [Name, Data1, Data, Pos, convert_data_tuple(Fields, undefined, 1, Deep + 1, Data1, [])]);
|
||
|
|
_ ->
|
||
|
|
?S("~w=begin ~s=?pcd(~s,~w,tuple),~s end", [Name, Data1, Data, Pos, convert_data_tuple(Fields, undefined, 1, Deep + 1, Data1, [])])
|
||
|
|
end,
|
||
|
|
convert_data_tuple(T, RecName, Pos + 1, Deep, Data, [S | L]);
|
||
|
|
convert_data_tuple([{array, tuple, Name, _Desc, Fields} | T], RecName, Pos, Deep, Data, L) ->
|
||
|
|
Data1 = ?S("V~w_~w", [Deep, Name]),
|
||
|
|
S = case RecName of
|
||
|
|
undefined ->
|
||
|
|
?S("~w=>begin ~s=?pcd(~s,~w,list), [~s||~s_I<-~s] end", [Name, Data1, Data, Pos, convert_data_tuple(Fields, undefined, 1, Deep + 1, Data1++"_I", []), Data1, Data1]);
|
||
|
|
_ ->
|
||
|
|
?S("~w=begin ~s=?pcd(~s,~w,list), [~s||~s_I<-~s] end", [Name, Data1, Data, Pos, convert_data_tuple(Fields, undefined, 1, Deep + 1, Data1++"_I", []), Data1, Data1])
|
||
|
|
end,
|
||
|
|
convert_data_tuple(T, RecName, Pos + 1, Deep, Data, [S | L]);
|
||
|
|
convert_data_tuple([{array, single, Name, _Desc, _Fields} | T], RecName, Pos, Deep, Data, L) ->
|
||
|
|
S = case RecName of
|
||
|
|
undefined ->
|
||
|
|
?S("~w=>?pcd(~s,~w,list)", [Name, Data, Pos]);
|
||
|
|
_ ->
|
||
|
|
?S("~w=?pcd(~s,~w,list)", [Name, Data, Pos])
|
||
|
|
end,
|
||
|
|
convert_data_tuple(T, RecName, Pos + 1, Deep, Data, [S | L]);
|
||
|
|
convert_data_tuple([{array, NewRecName, Name, _Desc, Fields} | T], RecName, Pos, Deep, Data, L) ->
|
||
|
|
Data1 = ?S("V~w_~w", [Deep, Name]),
|
||
|
|
S = case RecName of
|
||
|
|
undefined ->
|
||
|
|
?S("~w=>begin ~s=?pcd(~s,~w,list), [~s||~s_I<-~s] end", [Name, Data1, Data, Pos, convert_data_tuple(Fields, NewRecName, 1, Deep + 1, Data1++"_I", []), Data1, Data1]);
|
||
|
|
_ ->
|
||
|
|
?S("~w=begin ~s=?pcd(~s,~w,list), [~s||~s_I<-~s] end", [Name, Data1, Data, Pos, convert_data_tuple(Fields, NewRecName, 1, Deep + 1, Data1++"_I", []), Data1, Data1])
|
||
|
|
end,
|
||
|
|
convert_data_tuple(T, RecName, Pos + 1, Deep, Data, [S | L]);
|
||
|
|
convert_data_tuple([{Type, Name, _Name2, Desc} | T], RecName, Pos, Deep, Data, L) ->
|
||
|
|
convert_data_tuple([{Type, Name, Desc} | T], RecName, Pos, Deep, Data, L).
|
||
|
|
|
||
|
|
convert_data_pos(Data, undefined, Pos, Name, Type) -> ?S("~w=>?pcd(~s,~w,~w)", [Name, Data, Pos, Type]);
|
||
|
|
convert_data_pos(Data, _RecName, Pos, Name, Type) -> ?S("~w=?pcd(~s,~w,~w)", [Name, Data,Pos, Type]).
|
||
|
|
|
||
|
|
%% 缩进处理
|
||
|
|
s(N) -> s(N, "").
|
||
|
|
s(0, S) -> S;
|
||
|
|
s(N, S) -> s(N - 1, S ++ " ").
|
||
|
|
|
||
|
|
%% 尾部处理
|
||
|
|
t(S) ->
|
||
|
|
[_ | [_ | R]] = lists:reverse(S),
|
||
|
|
lists:reverse(R).
|
||
|
|
|
||
|
|
%% lua打包发送
|
||
|
|
gen_lua_pack(#rpc{req = undefined}) -> ok;
|
||
|
|
gen_lua_pack(#rpc{code = Code, req = Req}) ->
|
||
|
|
LuaFields = gen_lua_fields(Req, " ", []),
|
||
|
|
P = ?S(" [~w] = {\n~ts }", [Code, LuaFields]),
|
||
|
|
put(lua_send, [P | get(lua_send)]).
|
||
|
|
|
||
|
|
%% lua解包接收
|
||
|
|
gen_lua_unpack(#rpc{reply = undefined}) -> ok;
|
||
|
|
gen_lua_unpack(#rpc{code = Code, reply = Reply}) ->
|
||
|
|
LuaFields = gen_lua_fields(Reply, " ", []),
|
||
|
|
P = ?S(" [~w] = {\n~ts }", [Code, LuaFields]),
|
||
|
|
put(lua_recv, [P | get(lua_recv)]).
|
||
|
|
gen_lua_fields([], _Space, []) ->
|
||
|
|
"";
|
||
|
|
gen_lua_fields([], _Space, L) ->
|
||
|
|
string:join(lists:reverse(L), ",\n") ++ "\n";
|
||
|
|
gen_lua_fields({_RecName, Fields}, Space, L) ->
|
||
|
|
gen_lua_fields(Fields, Space, L);
|
||
|
|
gen_lua_fields([{rec, _, _, Fields} | T], Space, L) ->
|
||
|
|
gen_lua_fields(Fields ++ T, Space, L);
|
||
|
|
gen_lua_fields([{tuple, _, Fields} | T], Space, L) ->
|
||
|
|
gen_lua_fields(Fields ++ T, Space, L);
|
||
|
|
gen_lua_fields([{array, Type, _Name1, Name2, _Desc, SubFields} | T], Space, L) ->
|
||
|
|
gen_lua_fields([{array, Type, Name2, _Desc, SubFields} | T], Space, L);
|
||
|
|
gen_lua_fields([{array, _, Name, _Desc, SubFields} | T], Space, L) ->
|
||
|
|
SubS = gen_lua_fields(SubFields, Space ++ " ", []),
|
||
|
|
S = ?S("~ts{name='~ts', type='array', fields={\n~ts~ts}}", [Space, Name, SubS, Space]),
|
||
|
|
gen_lua_fields(T, Space, [S | L]);
|
||
|
|
gen_lua_fields([{Type, _Name1, Name2, _Desc} | T], Space, L) ->
|
||
|
|
gen_lua_fields([{Type, Name2, _Desc} | T], Space, L);
|
||
|
|
gen_lua_fields([{binary, Name, Desc} | T], Space, L) ->
|
||
|
|
gen_lua_fields([{string, Name, Desc} | T], Space, L);
|
||
|
|
gen_lua_fields([{Type, Name, _Desc} | T], Space, L) when
|
||
|
|
Type =:= int8
|
||
|
|
orelse Type =:= uint8
|
||
|
|
orelse Type =:= int16
|
||
|
|
orelse Type =:= uint16
|
||
|
|
orelse Type =:= int32
|
||
|
|
orelse Type =:= uint32
|
||
|
|
orelse Type =:= string
|
||
|
|
orelse Type =:= byte
|
||
|
|
->
|
||
|
|
S = ?S("~ts{name='~w', type='~w'}", [Space, Name, Type]),
|
||
|
|
gen_lua_fields(T, Space, [S | L]).
|
||
|
|
|
||
|
|
%% js打包发送
|
||
|
|
gen_js_pack(#rpc{req = undefined}) -> ok;
|
||
|
|
gen_js_pack(#rpc{code = Code, req = Req}) ->
|
||
|
|
JsFields = gen_js_fields(Req, " ", []),
|
||
|
|
P = ?S(" ~w : [\n~ts ]", [Code, JsFields]),
|
||
|
|
put(js_send, [P | get(js_send)]).
|
||
|
|
|
||
|
|
%% lua解包接收
|
||
|
|
gen_js_unpack(#rpc{reply = undefined}) -> ok;
|
||
|
|
gen_js_unpack(#rpc{code = Code, reply = Reply}) ->
|
||
|
|
LuaFields = gen_js_fields(Reply, " ", []),
|
||
|
|
P = ?S(" ~w : [\n~ts ]", [Code, LuaFields]),
|
||
|
|
put(js_recv, [P | get(js_recv)]).
|
||
|
|
|
||
|
|
gen_js_fields([], _Space, []) ->
|
||
|
|
"";
|
||
|
|
gen_js_fields([], _Space, L) ->
|
||
|
|
string:join(lists:reverse(L), ",\n") ++ "\n";
|
||
|
|
gen_js_fields({_RecName, Fields}, Space, L) ->
|
||
|
|
gen_js_fields(Fields, Space, L);
|
||
|
|
gen_js_fields([{rec, _, _, Fields} | T], Space, L) ->
|
||
|
|
gen_js_fields(Fields ++ T, Space, L);
|
||
|
|
gen_js_fields([{tuple, _, Fields} | T], Space, L) ->
|
||
|
|
gen_js_fields(Fields ++ T, Space, L);
|
||
|
|
gen_js_fields([{array, Type, _Name1, Name2, _Desc, SubFields} | T], Space, L) ->
|
||
|
|
gen_js_fields([{array, Type, Name2, _Desc, SubFields} | T], Space, L);
|
||
|
|
gen_js_fields([{array, _, Name, _Desc, SubFields} | T], Space, L) ->
|
||
|
|
SubS = gen_js_fields(SubFields, Space ++ " ", []),
|
||
|
|
S = ?S("~ts{s:'~ts', t:~w, f:[\n~ts~ts]}", [Space, Name, js_type(array), SubS, Space]),
|
||
|
|
gen_js_fields(T, Space, [S | L]);
|
||
|
|
gen_js_fields([{Type, _Name1, Name2, _Desc} | T], Space, L) ->
|
||
|
|
gen_js_fields([{Type, Name2, _Desc} | T], Space, L);
|
||
|
|
gen_js_fields([{binary, Name, Desc} | T], Space, L) ->
|
||
|
|
gen_js_fields([{string, Name, Desc} | T], Space, L);
|
||
|
|
gen_js_fields([{Type, Name, _Desc} | T], Space, L) when
|
||
|
|
Type =:= int8
|
||
|
|
orelse Type =:= uint8
|
||
|
|
orelse Type =:= int16
|
||
|
|
orelse Type =:= uint16
|
||
|
|
orelse Type =:= int32
|
||
|
|
orelse Type =:= uint32
|
||
|
|
orelse Type =:= string
|
||
|
|
orelse Type =:= byte
|
||
|
|
->
|
||
|
|
S = ?S("~ts{s:'~w', t:~w}", [Space, Name, js_type(Type)]),
|
||
|
|
gen_js_fields(T, Space, [S | L]).
|
||
|
|
js_type(int8) -> 1;
|
||
|
|
js_type(uint8) -> 2;
|
||
|
|
js_type(int16) -> 3;
|
||
|
|
js_type(uint16) -> 4;
|
||
|
|
js_type(int32) -> 5;
|
||
|
|
js_type(uint32) -> 6;
|
||
|
|
js_type(string) -> 7;
|
||
|
|
js_type(byte) -> 8;
|
||
|
|
js_type(array) -> 9.
|
||
|
|
|
||
|
|
%% 清空变量
|
||
|
|
reset_var(N) ->
|
||
|
|
put({var_list, N}, []).
|
||
|
|
|
||
|
|
%% 增加变量
|
||
|
|
add_var(N, Var) ->
|
||
|
|
case lists:member(Var, get({var_list, N})) of
|
||
|
|
true -> ?P("~w==字段重复==>deep:~w ~w~n", [get(code), N, Var]);
|
||
|
|
_ -> put({var_list, N}, [Var | get({var_list, N})])
|
||
|
|
end.
|
||
|
|
|
||
|
|
%% 获取所有的配置文件
|
||
|
|
cfg_file() ->
|
||
|
|
%% ?DEBUG("配置目录:~ts", [env:get(code_path) ++ "/src/proto"]),
|
||
|
|
case file:list_dir("./cfg") of
|
||
|
|
{ok, L} -> do_cfg_file(L, []);
|
||
|
|
{error, Why} ->
|
||
|
|
?P("获取RPC配置文件时发生异常: ~w~n", [Why]),
|
||
|
|
[]
|
||
|
|
end.
|
||
|
|
|
||
|
|
%% 返回所有的配置文件
|
||
|
|
do_cfg_file([], List) -> lists:sort(List);
|
||
|
|
do_cfg_file([F | T], List) ->
|
||
|
|
L = case filename:extension(F) =:= ".erl" of
|
||
|
|
true ->
|
||
|
|
M = filename:basename(filename:rootname(F)),
|
||
|
|
[M | List];
|
||
|
|
_ -> List
|
||
|
|
end,
|
||
|
|
do_cfg_file(T, L).
|