Skip to content

Instantly share code, notes, and snippets.

@Xitsa
Created September 7, 2020 11:41
Show Gist options
  • Select an option

  • Save Xitsa/0cb6939c7a4ef9d729798398548f16bf to your computer and use it in GitHub Desktop.

Select an option

Save Xitsa/0cb6939c7a4ef9d729798398548f16bf to your computer and use it in GitHub Desktop.
Генератор RPC-вызовов на gsl.
<?xml version = "1.0"?>
<rpc
script = "typedefines.gsl"
module = "Trafficd"
>
<types>
<type kind="enum" name="ServiceId">
<doc>Сервисы</doc>
<elem name="telnet"/>
<elem name="ssh"/>
<elem name="tacacs"/>
<elem name="snmp"/>
<elem name="snmp_trap"/>
<elem name="tftp"/>
<elem name="icmp"/>
<elem name="tcp"/>
<elem name="traceroute"/>
<elem name="ipsla"/>
<elem name="igmp"/>
<elem name="ospf"/>
<elem name="bgp"/>
<elem name="bfd"/>
<elem name="rip"/>
<elem name="vrrp"/>
<elem name="pim"/>
<elem name="ntp"/>
<elem name="dhcp_client"/>
<elem name="dhcp_server"/>
<elem name="dns"/>
<elem name="ftp_client"/>
<elem name="syslog"/>
</type>
<type kind="struct" name="IPv4Address">
<doc>Описатель IP–адреса (аналог MRN::Networking:IPv4::Address)</doc>
<param name="ip" type="string">
<doc>IPv4–адрес в формате xx.xx.xx.xx</doc>
</param>
</type>
<type kind="oneof" name="IPv4Interface">
<doc>Описатель IP–интерфейсов, на адреса которых производится воздействие</doc>
<param name="vlan" type="int32"/>
<param name="loopback" type="int32"/>
</type>
<type kind="array" name="IPv4Interfaces" elemtype="IPv4Interface"/>
<type kind="array" name="Categories" elemtype="int32">
<doc>
Список уникальных мандатных меток со значениями от 0 до 63.
Передача списком была выбрана из-за того, что у Lua есть проблема с
представлением целых беззнаковых 64–битных значений.
</doc>
</type>
<type kind="struct" name="MandateLabel">
<doc>Мандатная метка</doc>
<param name="level" type="int32">
<doc>Уровень доступа, должен быть в диапазоне 0...3</doc>
</param>
<param name="mask" type="Categories">
<doc>Список категорий</doc>
</param>
</type>
<type kind="struct" name="ServiceMandateSettings">
<doc>Настройки КСЗ для сервиса</doc>
<param name="label" type="MandateLabel">
<doc>Мандатная метка</doc>
</param>
<param name="check_exact" type="bool">
<doc>Необходимо ли полное совпадение метки (проверка на запись)</doc>
</param>
</type>
<type kind="struct" name="NamedServiceMandateSettings">
<doc>Настройки КСЗ для сервиса</doc>
<param name="service_id" type="ServiceId">
<doc>Идентификатор сетевой службы</doc>
</param>
<param name="settings" type="ServiceMandateSettings">
<doc>Настройки КСЗ для сетевой службы</doc>
</param>
</type>
<type kind="array" name="ServicesMandateSettings" elemtype="NamedServiceMandateSettings"/>
<type kind="struct" name="InterfaceMandateSettings">
<doc>Настройки мандатных меток на IP–интерфейсах</doc>
<param name="iface" type="IPv4Interface">
<doc>IP–интерфейс</doc>
</param>
<param name="enabled_mode" type="bool">
<doc>Включен или выключен контроль мандатных меток</doc>
</param>
<param name="services_settings" type="ServicesMandateSettings">
<doc>Настройки КСЗ для служб на этом интерфейсе</doc>
</param>
</type>
<type kind="array" name="InterfacesMandateSettings" elemtype="InterfaceMandateSettings"/>
<type kind="struct" name="PacketCounter">
<doc>
Счётчик пакетов.
Тип double пришлось взять из-за ограничений Lua на числа.
</doc>
<param name="frames" type="double">
<doc>Количество пакетов</doc>
</param>
<param name="bytes" type="double">
<doc>Количество байт</doc>
</param>
</type>
<type kind="struct" name="MandateCounters">
<doc>Счётчики трафика через КСЗ</doc>
<param name="permitted" type="PacketCounter">
<doc>Количество разрешённых входящих пакетов с мандатной меткой</doc>
</param>
<param name="outbound" type="PacketCounter">
<doc>Количество выходящих пакетов</doc>
</param>
<param name="denied" type="PacketCounter">
<doc>Количество входящих пакетов с мандатной меткой с неверным доступом</doc>
</param>
<param name="dropped" type="PacketCounter">
<doc>Количество входящих пакетов без мандатной метки</doc>
</param>
</type>
<type kind="struct" name="IPv4MandateCounters">
<doc>Счётчики трафика через КСЗ для конкретного адреса</doc>
<param name="ipv4_address" type="IPv4Address">
<doc>Адрес, к которому подсоединена служба</doc>
</param>
<param name="counters" type="MandateCounters">
<doc>Счётчики трафика для службы на этом адресе</doc>
</param>
</type>
<type kind="array" name="IPv4sMandateCounters" elemtype="IPv4MandateCounters"/>
<type kind="struct" name="ServiceMandateCounters">
<doc>Счётчики трафика через КСЗ для конкретной сетевой службы</doc>
<param name="service_id" type="ServiceId">
<doc>Идентификатор сетевой службы</doc>
</param>
<param name="ipv4_counters" type="IPv4sMandateCounters">
<doc>Счётчики трафика для службы</doc>
</param>
</type>
<type kind="array" name="ServicesMandateCounters" elemtype="ServiceMandateCounters"/>
<type kind="struct" name="InterfaceMandateCounters">
<doc>Счётчики трафика через КСЗ для конкретного IP–интерфейса</doc>
<param name="iface" type="IPv4Interface">
<doc>IP–интерфейс</doc>
</param>
<param name="services_counters" type="ServicesMandateCounters">
<doc>Счётчики трафика для служб на этом интерфейсе</doc>
</param>
<param name="total_counters" type="MandateCounters">
<doc>Общие счётчики трафика на этом интерфейсе</doc>
</param>
</type>
<type kind="array" name="InterfacesMandateCounters" elemtype="InterfaceMandateCounters"/>
<type kind="struct" name="ServiceOverallMandateInfo">
<doc>Информаця о КСЗ для конкретной службы</doc>
<param name="service_id" type="ServiceId">
<doc>Идентификатор сетевой службы</doc>
</param>
<param name="settings" type="ServiceMandateSettings">
<doc>Настройки КСЗ для сетевой службы</doc>
</param>
<param name="ipv4_counters" type="IPv4sMandateCounters">
<doc>Счётчики трафика для служб на этом интерфейсе</doc>
</param>
</type>
<type kind="array" name="ServicesOverallMandateInfo" elemtype="ServiceOverallMandateInfo"/>
<type kind="struct" name="InterfaceOverallMandateInfo">
<doc>Информация о КСЗ для конкретного IP–интерфейса</doc>
<param name="iface" type="IPv4Interface">
<doc>IP–интерфейс</doc>
</param>
<param name="enabled_mode" type="bool">
<doc>Включен или выключен контроль мандатных меток</doc>
</param>
<param name="services_info" type="ServicesOverallMandateInfo">
<doc>Информция о КСЗ по службам на этом интерфейсе</doc>
</param>
<param name="total_counters" type="MandateCounters">
<doc>Общие счётчики трафика на этом интерфейсе</doc>
</param>
</type>
<type kind="array" name="InterfacesOverallMandateInfo" elemtype="InterfaceOverallMandateInfo"/>
<type kind="args" name="ServicesIfacesFilter">
<doc>
Фильтр по службе и интерфейсам.
Если служба не указана, то для всех.
Если не указаны интерфейсы, то для всех.
Если указаны и служба и интерфейсы, то по службам на указанных интерфейсах.
Если не указаны ни служба, ни интерфейсы, то по всем.
</doc>
<param name="service_id" type="ServiceId" optional="yes">
<doc>Идентификатор сетевой службы</doc>
</param>
<param name="ifaces" type="IPv4Interfaces" optional="yes">
<doc>Список IP–интерфейсов</doc>
</param>
</type>
<type kind="args" name="SetMandateLabelMode">
<param name="ifaces" type="IPv4Interfaces">
<doc>Список IP–интерфейсов</doc>
</param>
<param name="enable" type="bool">
<doc>Включить или выключить контроль мандатных меток</doc>
</param>
</type>
<type kind="args" name="SetMandateLabel">
<param name="service_id" type="ServiceId">
<doc>Идентификатор сетевой службы</doc>
</param>
<param name="ifaces" type="IPv4Interfaces">
<doc>Список IP–интерфейсов</doc>
</param>
<param name="label" type="MandateLabel">
<doc>Мандатная метка</doc>
</param>
</type>
<type kind="args" name="RemoveMandateLabel">
<param name="service_id" type="ServiceId">
<doc>Идентификатор сетевой службы</doc>
</param>
<param name="ifaces" type="IPv4Interfaces">
<doc>Список IP–интерфейсов</doc>
</param>
</type>
<type kind="values" name="GetMandateInfo">
<param name="settings" type="InterfacesMandateSettings">
<doc>Настройки</doc>
</param>
</type>
<type kind="values" name="GetMandateCounters">
<param name="counters" type="InterfacesMandateCounters">
<doc>Счётчики</doc>
</param>
</type>
<type kind="values" name="GetMandateOverallInfo">
<param name="overall_info" type="InterfacesOverallMandateInfo">
<doc>Счётчики</doc>
</param>
</type>
</types>
<procedures>
<procedure
name="set mandate label mode"
args="SetMandateLabelMode"
>
<doc>Включить или выключить контроль мандатных меток на интерфейсах</doc>
</procedure>
<procedure
name="set mandate label"
args="SetMandateLabel"
>
<doc>Назначить параметры мандатной метки на службу</doc>
</procedure>
<procedure
name="remove mandate label"
args="RemoveMandateLabel"
>
<doc>Снять мандатную метку со службы</doc>
</procedure>
<procedure
name="get mandate info"
args="ServicesIfacesFilter"
values="GetMandateInfo"
>
<doc>Запросить настройки мандатного доступа по службе и интерфейсам</doc>
</procedure>
<procedure
name="get mandate counters"
args="ServicesIfacesFilter"
values="GetMandateCounters"
>
<doc>Запросить счётчики трафика по службе и интерфейсам</doc>
</procedure>
<procedure
name="get mandate overall info"
args="ServicesIfacesFilter"
values="GetMandateOverallInfo"
>
<doc>Запросить всё информацию о мандатном доступе по службе и интерфейсам</doc>
</procedure>
<procedure
name="reset mandate counters"
args="ServicesIfacesFilter"
>
<doc>Сбросить счётчики трафика по службе и интерфейсам</doc>
</procedure>
</procedures>
</rpc>
.template 0
.ignorecase = 0
function get_type_ref(typename)
scope rpc->types
if count(types.type, other_type.name = my.typename, other_type) = 0
abort "get_type_ref: cannot find $(my.typename)"
endif
my.type_ref = types->type(other_type.name = my.typename, other_type)
endscope types
return my.type_ref
endfunction
function get_args_ref(typename)
scope rpc->types
if count(types.type, other_type.name = my.typename & other_type.kind = "args", other_type) = 0
abort "get_args_ref: cannot find $(my.typename)"
endif
my.type_ref = types->type(other_type.name = my.typename & other_type.kind = "args", other_type)
endscope types
return my.type_ref
endfunction
function get_values_ref(typename)
scope rpc->types
if count(types.type, other_type.name = my.typename & other_type.kind = "values", other_type) = 0
abort "get_values_ref: cannot find $(my.typename)"
endif
my.type_ref = types->type(other_type.name = my.typename & other_type.kind = "values", other_type)
endscope types
return my.type_ref
endfunction
function is_enum_type_present()
my.res = 1
scope rpc->types
if count(types.type, other_type.kind = "enum", other_type) = 0
my.res = 0
endif
endscope types
return my.res
endfunction
function is_type_scalar(typename)
if my.typename = "string"
return 1
elsif my.typename = "int64"
return 1
elsif my.typename = "int32"
return 1
elsif my.typename = "int16"
return 1
elsif my.typename = "int8"
return 1
elsif my.typename = "bool"
return 1
elsif my.typename = "double"
return 1
endif
return 0
endfunction
function get_rf_type(typename)
if my.typename = "string"
return "std::string"
elsif my.typename = "int64"
return "int64_t"
elsif my.typename = "int32"
return "int32_t"
elsif my.typename = "int16"
return "int16_t"
elsif my.typename = "int8"
return "int8_t"
elsif my.typename = "bool"
return "bool"
elsif my.typename = "double"
return "double"
else
my.type_ref = get_type_ref(my.typename)
if defined(my.type_ref)
if my.type_ref.kind = "enum"
return my.type_ref.cxx_enum_type_name
endif
return my.type_ref.cxx_type_name
endif
endif
return "UNDEFINED TYPE"
endfunction
# Тип для условноотсутствующего значения, используется в определениях полей и переменных
function get_optional_rf_type(typename)
if my.typename = "UNDEFINED TYPE"
return "UNDEFINED TYPE"
elsif my.typename = "std::string"
return "MRN::Meta::OptionalStdString"
elsif my.typename = "int64_t"
return "MRN::Meta::OptionalInt64"
elsif my.typename = "int32_t"
return "MRN::Meta::OptionalInt32"
elsif my.typename = "int16_t"
return "MRN::Meta::OptionalInt16"
elsif my.typename = "int8_t"
return "MRN::Meta::OptionalInt8"
elsif my.typename = "bool"
return "MRN::Meta::OptionalBool"
elsif my.typename = "double"
return "MRN::Meta::OptionalDouble"
endif
return "MRN::Meta::InitialUnsetOptionalObject<$(my.typename)>"
endfunction
# Тип условноотсутствующих значений, которые возвращают blobreader’ы
function get_blobreader_scalar_optional_type(typename)
if my.typename = "UNDEFINED TYPE"
return "UNDEFINED TYPE"
elsif my.typename = "string"
return "MRN::Meta::OptionalCString"
elsif my.typename = "int64_t"
return "MRN::Meta::OptionalInt64"
elsif my.typename = "int32"
return "MRN::Meta::OptionalInt32"
elsif my.typename = "int16"
return "MRN::Meta::OptionalInt16"
elsif my.typename = "int8"
return "MRN::Meta::OptionalInt8"
elsif my.typename = "bool"
return "MRN::Meta::OptionalBool"
elsif my.typename = "double"
return "MRN::Meta::OptionalDouble"
endif
abort "get_blobreader_scalar_optional_type: unknown scalar type $(my.typename)"
endfunction
function get_blob_object_reader_scalar_accessor(typename)
if my.typename = "string"
return "GetString"
elsif my.typename = "int64"
return "GetInt64"
elsif my.typename = "int32"
return "GetInt32"
elsif my.typename = "int16"
return "GetInt16"
elsif my.typename = "int8"
return "GetInt8"
elsif my.typename = "bool"
return "GetBool"
elsif my.typename = "double"
return "GetDouble"
endif
abort "get_blob_object_reader_scalar_accessor: unknown scalar type $(my.typename)"
endfunction
function get_blob_object_writer_scalar_setter(typename)
if my.typename = "string"
return "AddString"
elsif my.typename = "int64"
return "AddInt64"
elsif my.typename = "int32"
return "AddInt32"
elsif my.typename = "int16"
return "AddInt16"
elsif my.typename = "int8"
return "AddInt8"
elsif my.typename = "bool"
return "AddBool"
elsif my.typename = "double"
return "AddDouble"
endif
abort "get_blob_object_writer_scalar_setter: unknown scalar type $(my.typename)"
endfunction
function get_blob_array_writer_scalar_setter(typename)
# Имена методов совпадают с методами записи в структуру
return get_blob_object_writer_scalar_setter(my.typename)
endfunction
function get_rpc_paramater_type_register(typename)
if my.typename = "string"
return "ParameterString"
elsif my.typename = "int64"
return "ParameterInt64"
elsif my.typename = "int32"
return "ParameterInt32"
elsif my.typename = "int16"
return "ParameterInt16"
elsif my.typename = "int8"
return "ParameterInt8"
elsif my.typename = "bool"
return "ParameterBool"
elsif my.typename = "double"
return "ParameterDouble"
endif
abort "get_rpc_paramater_type_register: unknown scalar type $(my.typename)"
endfunction
function mark_types_recursive(typenode, attrname)
if defined(my.typenode.$(my.attrname))
return
endif
define my.typenode.$(my.attrname) = "yes"
if my.typenode.kind = "array"
if is_type_scalar(my.typenode.elemtype)
return
endif
my.rf_type = get_type_ref(my.typenode.elemtype)
mark_types_recursive(my.rf_type, my.attrname)
else
for my.typenode.param
if !is_type_scalar(param.type)
my.rf_type = get_type_ref(param.type)
mark_types_recursive(my.rf_type, my.attrname)
endif
endfor
endif
endfunction
function get_non_scalar_params_count(typenode)
my.non_scalar_params_count = count(my.typenode.param, param->typeinfo.is_scalar_type <> "1")
return my.non_scalar_params_count
endfunction
function make_rf_type(node, typename, optional)
new my.node.typeinfo
my.rf_type = get_rf_type(my.typename)
if my.optional
my.rf_type = get_optional_rf_type(my.rf_type)
endif
my.is_scalar_type = is_type_scalar(my.typename)
if my.is_scalar_type <> "1"
my.ref_type = get_type_ref(my.typename)
copy my.ref_type to my.node as ref_type
endif
define typeinfo.rf_type = my.rf_type
define typeinfo.is_scalar_type = my.is_scalar_type
endnew
endfunction
function make_procs_ref_types(proc_node)
if defined(my.proc_node.args)
my.ref_type = get_args_ref(my.proc_node.args)
copy my.ref_type to my.proc_node as args_ref_type
endif
if defined(my.proc_node.values)
my.ref_type = get_values_ref(my.proc_node.values)
copy my.ref_type to my.proc_node as values_ref_type
endif
endfunction
# Запомним полные пространства имён для будущей справки
define rpc.cxx_messages_namespace = "$(rpc.module)::UbusMessages"
# Пометим типы, которые надо распаковывать
for types
for type where kind = "args"
mark_types_recursive(type, "decode")
endfor
endfor
# Пометим типы, которые надо запаковывать
for types
for type where kind = "values"
mark_types_recursive(type, "encode")
endfor
endfor
for types
for type
# cxx_name неквалифицированное имя, изменённое под требования проекта
if kind = "struct"
type.cxx_name = "$(name)"
elsif kind = "array"
type.cxx_name = "$(name)"
elsif kind = "oneof"
type.cxx_name = "$(name)"
elsif kind = "enum"
type.cxx_name = "$(name)"
elsif kind = "args"
type.cxx_name = "$(name)_args"
elsif kind = "values"
type.cxx_name = "$(name)_values"
endif
type.cxx_namespaced_name = "$(rpc.module)::UbusMessages::$(cxx_name)"
if kind = "array"
type.cxx_type_name = "$(cxx_name)"
type.cxx_namespaced_type_name = "$(cxx_namespaced_name)"
elsif kind = "enum"
type.cxx_type_name = "struct $(cxx_name)"
type.cxx_namespaced_type_name = "struct $(cxx_namespaced_name)"
type.cxx_enum_type_name = "enum $(cxx_name)::CASE"
type.cxx_namespaced_enum_type_name = "enum $(cxx_namespaced_name)::CASE"
else
type.cxx_type_name = "struct $(cxx_name)"
type.cxx_namespaced_type_name = "struct $(cxx_namespaced_name)"
endif
type.encode_func_name = "$(cxx_name)_encode"
type.decode_func_name = "$(cxx_name)_decode"
endfor
endfor
for types
for type
for param
make_rf_type(param, .[type], type.kind = "oneof" | (defined(param.optional) & param.optional = "yes"))
endfor
endfor
endfor
for types
for type where kind = "array"
make_rf_type(type, .[elemtype], 0)
endfor
endfor
for types
for type where kind = "oneof"
for param
define param.cxx_enum_value = "$(name:upper)_CASE"
endfor
endfor
endfor
for types
for type where kind = "enum"
for elem
define elem.cxx_enum_value = "$(name:upper)_CASE"
endfor
endfor
endfor
# Подготовим процедуры
for procedures
for procedure
make_procs_ref_types(procedure)
if !defined(procedure.ubus_name)
define procedure.ubus_name = "$(name:c)"
endif
define procedure.cxx_callback_name = "$(name:pascal)"
define procedure.cxx_event_name = "On$(name:pascal)"
endfor
endfor
save root
.endtemplate
.#
.#############################################################################
.# Rpc.Messages.hxx #
.#############################################################################
.#
.output "../include/platform/Rpc.Messages.hxx"
.#
.macro dividing_empty_line ()
. if !last()
. endif
.endmacro
.#
.macro generate_struct_params ()
. for param
. for param.doc
// $(doc:block)
. endfor
$(param->typeinfo.rf_type) $(name);
. endfor
.endmacro
.#
.macro generate_oneof_enum ()
enum CASE {
UNSET_CASE = 0,
. for param
. my.comma = last()?? ""? ","
$(param.cxx_enum_value)$(my.comma)
. endfor
} selected;
.endmacro
.#
.macro generate_enum_values ()
enum CASE {
. for elem
. my.comma = last()?? ""? ","
$(elem.cxx_enum_value)$(my.comma)
. endfor
};
.endmacro
#ifndef $(rpc.module:upper)_UBUS_RPC_MESSAGES_HXX
#define $(rpc.module:upper)_UBUS_RPC_MESSAGES_HXX
namespace $(rpc.module)
{
namespace UbusMessages
{
.for types
. for type
. for type.doc
/*
* $(name)
* $(doc:block)
*/
. endfor
. if kind = "struct"
$(cxx_type_name) {
. generate_struct_params ()
};
. elsif kind = "args"
$(cxx_type_name) {
. generate_struct_params ()
static void register_args(MRN::System::Ubus::LocalProcedure* rpc);
static MRN::Result decode(const MRN::System::Ubus::Blob::BlobObjectReader& bor, $(cxx_type_name)& args);
};
. elsif kind = "values"
$(cxx_type_name) {
. generate_struct_params ()
static MRN::Result encode(MRN::System::Ubus::LocalProcedureReply& lpr, const char* field_name, const $(cxx_type_name)& values);
};
. elsif kind = "array"
typedef std::vector<$(->typeinfo.rf_type)> $(cxx_type_name);
. elsif kind = "oneof"
$(cxx_type_name) {
. generate_oneof_enum ()
. generate_struct_params ()
};
. elsif kind = "enum"
$(cxx_type_name) {
. generate_enum_values ()
};
. endif
. dividing_empty_line()
. endfor
.endfor
}
}
#endif /*$(rpc.module:upper)_UBUS_RPC_MESSAGES_HXX*/
.#
.#############################################################################
.# Rpc.Messages.cxx #
.#############################################################################
.#
.output "../src/platform/Rpc.Messages.cxx"
.#
.macro generate_hash_comparer()
#include <unordered_map>
namespace
{
struct ConstCharHashComparer {
std::size_t operator()(const char* str) const noexcept
{
return MRN::Utils::Hash::hash<const char*>(str);
}
bool operator()(const char* lhs, const char* rhs) const noexcept
{
return 0 == strcmp(lhs, rhs);
}
};
}
.endmacro
.#
.macro generate_enum_map(typenode)
const std::unordered_map<const char*, $(my.typenode.cxx_enum_type_name), ConstCharHashComparer, ConstCharHashComparer> $(my.typenode.cxx_name)_map = {
. for my.typenode.elem
. my.comma = last()?? ""? ","
. my.key = '{ "$(elem.name)",'
$(my.key%-30s) $(my.typenode.cxx_name)::$(elem.cxx_enum_value) }$(my.comma)
.# { "$(elem.name)", $(my.typenode.cxx_name)::$(elem.cxx_enum_value) }$(my.comma)
. endfor
};
.endmacro
.#
.macro generate_struct_decoder(typenode)
MRN::Result $(my.typenode.decode_func_name)(const MRN::System::Ubus::Blob::BlobObjectReader& bor, $(my.typenode.cxx_type_name)& obj)
{
. if get_non_scalar_params_count(my.typenode) <> 0
MRN::Result oResult;
. endif
if (!bor.IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name)");
}
. for my.typenode.param
//.$(param.name)
. if defined(param.optional) & param.optional = "yes"
bool has_$(param.name) = true;
. if param->typeinfo.is_scalar_type = "1"
$(get_blobreader_scalar_optional_type(param.type)) tmp_$(param.name) = bor.$(get_blob_object_reader_scalar_accessor(param.type))("$(param.name)");
if (!tmp_$(param.name).IsSet()) {
has_$(param.name) = false;
}
. elsif param->ref_type.kind = "enum"
$(param->ref_type.cxx_enum_type_name) tmp_$(param.name);
$(get_blobreader_scalar_optional_type("string")) str_$(param.name) = bor.$(get_blob_object_reader_scalar_accessor("string"))("$(param.name)");
if (!str_$(param.name).IsSet()) {
has_$(param.name) = false;
} else {
oResult = $(param->ref_type.decode_func_name)(str_$(param.name).Value(), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
}
. else
$(param->ref_type.cxx_type_name) tmp_$(param.name);
. if param->ref_type.kind = "array"
. my.blob_reader_name = "bar_$(param.name)"
const MRN::System::Ubus::Blob::BlobArrayReader& $(my.blob_reader_name) = bor.GetArray("$(param.name)");
if ($(my.blob_reader_name).IsValid()) {
oResult = $(param->ref_type.decode_func_name)($(my.blob_reader_name), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
} else {
// lua вместо пустого массива отправляет пустую таблицу
const MRN::System::Ubus::Blob::BlobObjectReader& bor_empty_array_check = bor.GetObject("$(param.name)");
if (!bor_empty_array_check.IsValid()) {
has_$(param.name) = false;
} else {
if (bor_empty_array_check.Length() != 0) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' is not an array");
}
}
// Пустой массив, ОК
}
. else
. my.blob_reader_name = "bor_$(param.name)"
const MRN::System::Ubus::Blob::BlobObjectReader& $(my.blob_reader_name) = bor.GetObject("$(param.name)");
if (!$(my.blob_reader_name).IsValid()) {
has_$(param.name) = false;
} else {
oResult = $(param->ref_type.decode_func_name)($(my.blob_reader_name), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
}
. endif
. endif
. else
. if param->typeinfo.is_scalar_type = "1"
$(get_blobreader_scalar_optional_type(param.type)) tmp_$(param.name) = bor.$(get_blob_object_reader_scalar_accessor(param.type))("$(param.name)");
if (!tmp_$(param.name).IsSet()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' doesn't exist");
}
. elsif param->ref_type.kind = "enum"
$(param->typeinfo.rf_type) tmp_$(param.name);
$(get_blobreader_scalar_optional_type("string")) str_$(param.name) = bor.$(get_blob_object_reader_scalar_accessor("string"))("$(param.name)");
if (!str_$(param.name).IsSet()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' doesn't exist");
}
oResult = $(param->ref_type.decode_func_name)(str_$(param.name).Value(), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
. else
$(param->typeinfo.rf_type) tmp_$(param.name);
. if param->ref_type.kind = "array"
. my.blob_reader_name = "bar_$(param.name)"
const MRN::System::Ubus::Blob::BlobArrayReader& $(my.blob_reader_name) = bor.GetArray("$(param.name)");
if ($(my.blob_reader_name).IsValid()) {
oResult = $(param->ref_type.decode_func_name)($(my.blob_reader_name), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
} else {
// lua вместо пустого массива отправляет пустую таблицу
const MRN::System::Ubus::Blob::BlobObjectReader& bor_empty_array_check = bor.GetObject("$(param.name)");
if (!bor_empty_array_check.IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' doesn't exist");
} else {
if (bor_empty_array_check.Length() != 0) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' is not an array");
}
}
// Пустой массив, ОК
}
. else
. my.blob_reader_name = "bor_$(param.name)"
const MRN::System::Ubus::Blob::BlobObjectReader& $(my.blob_reader_name) = bor.GetObject("$(param.name)");
if (!$(my.blob_reader_name).IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' doesn't exist");
}
oResult = $(param->ref_type.decode_func_name)($(my.blob_reader_name), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
. endif
. endif
. endif
. endfor
. for my.typenode.param
. if defined(param.optional) & param.optional = "yes"
if (has_$(param.name)) {
. if param->typeinfo.is_scalar_type = "1"
. if param.type = "string"
obj.$(param.name).Value(std::string(tmp_$(param.name).Value()));
. else
obj.$(param.name).Value(tmp_$(param.name).Value());
. endif
. else
obj.$(param.name).Value(tmp_$(param.name));
. endif
}
. else
. if param->typeinfo.is_scalar_type = "1"
. if param.type = "string"
obj.$(param.name) = std::string(tmp_$(param.name).Value());
. else
obj.$(param.name) = tmp_$(param.name).Value();
. endif
. else
. if param->ref_type.kind = "array"
obj.$(param.name).swap(tmp_$(param.name));
. else
obj.$(param.name) = tmp_$(param.name);
. endif
. endif
. endif
. endfor
return MRN::Result(true);
}
.endmacro
.#
.macro generate_array_decoder(typenode)
MRN::Result $(my.typenode.decode_func_name)(const MRN::System::Ubus::Blob::BlobArrayReader& bar, $(my.typenode.cxx_type_name)& arr)
{
. if my.typenode->typeinfo.is_scalar_type <> "1"
MRN::Result oResult;
. endif
if (!bar.IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name)");
}
$(my.typenode.cxx_type_name) tmp_arr;
tmp_arr.reserve(bar.Length());
for (size_t f = 0; f < bar.Length(); ++f) {
. if my.typenode->typeinfo.is_scalar_type = "1"
$(get_blobreader_scalar_optional_type(my.typenode.elemtype)) tmp_elem = bar.$(get_blob_object_reader_scalar_accessor(my.typenode.elemtype))(f);
if (!tmp_elem.IsSet()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): elem with index %u is not a $(my.typenode.elemtype)", (unsigned int)f);
}
. if my.typenode.elemtype = "string"
tmp_arr.push_back(std::string(tmp_elem.Value()));
. else
tmp_arr.push_back(tmp_elem.Value());
. endif
. elsif my.typenode->ref_type.kind = "enum"
$(my.typenode->typeinfo.rf_type) tmp_elem;
$(get_blobreader_scalar_optional_type("string")) str_elem = bar.$(get_blob_object_reader_scalar_accessor("string"))(f);
if (!str_elem.IsSet()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): elem with index %u is not a string", (unsigned int)f);
}
oResult = $(my.typenode->ref_type.decode_func_name)(str_elem.Value(), tmp_elem);
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name)[%u]: %s", (unsigned int)f, oResult.Message());
}
tmp_arr.push_back(tmp_elem);
. else
$(my.typenode->typeinfo.rf_type) tmp_elem;
. if my.typenode->ref_type.kind = "array"
. my.elem_reader_name = "bar_elem"
const MRN::System::Ubus::Blob::BlobArrayReader& $(my.elem_reader_name) = bar.GetArray(f);
if ($(my.elem_reader_name).IsValid()) {
oResult = $(my.typenode->ref_type.decode_func_name)($(my.elem_reader_name), tmp_elem);
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name)[%u]: %s", (unsigned int)f, oResult.Message());
}
} else {
// lua вместо пустого массива отправляет пустую таблицу
const MRN::System::Ubus::Blob::BlobObjectReader& bor_empty_array_check = bar.GetObject(f);
if (!bor_empty_array_check.IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): elem with index %u is not an array", (unsigned int)f);
} else {
if (bor_empty_array_check.Length() != 0) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): elem with index %u is not an array", (unsigned int)f);
}
}
// Пустой массив, ОК
}
. else
. my.elem_reader_name = "bor_elem"
const MRN::System::Ubus::Blob::BlobObjectReader& $(my.elem_reader_name) = bar.GetObject(f);
if (!$(my.elem_reader_name).IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): elem with index %u is not an object", (unsigned int)f);
}
oResult = $(my.typenode->ref_type.decode_func_name)($(my.elem_reader_name), tmp_elem);
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name)[%u]: %s", (unsigned int)f, oResult.Message());
}
. endif
tmp_arr.push_back(tmp_elem);
. endif
}
arr.swap(tmp_arr);
return MRN::Result(true);
}
.endmacro
.#
.macro generate_oneof_decoder(typenode)
MRN::Result $(my.typenode.decode_func_name)(const MRN::System::Ubus::Blob::BlobObjectReader& bor, $(my.typenode.cxx_type_name)& obj)
{
. if get_non_scalar_params_count(my.typenode) <> 0
MRN::Result oResult;
. endif
if (!bor.IsValid()) {
return MRN::Result(false, "Cannot decode $(my.typenode.name)");
}
. for my.typenode.param
//.$(param.name)
. if param->typeinfo.is_scalar_type = "1"
$(get_blobreader_scalar_optional_type(param.type)) tmp_$(param.name) = bor.$(get_blob_object_reader_scalar_accessor(param.type))("$(param.name)");
if (tmp_$(param.name).IsSet()) {
obj.selected = $(my.typenode.cxx_name)::$(param.cxx_enum_value);
. if param.type = "string"
obj.$(param.name).Value(std::string(tmp_$(param.name).Value()));
. else
obj.$(param.name) = tmp_$(param.name);
. endif
return MRN::Result(true);
}
. elsif param->ref_type.kind = "enum"
$(param->ref_type.cxx_enum_type_name) tmp_$(param.name);
$(get_blobreader_scalar_optional_type("string")) str_$(param.name) = bor.$(get_blob_object_reader_scalar_accessor("string"))("$(param.name)");
if (str_$(param.name).IsSet()) {
oResult = $(param->ref_type.decode_func_name)(str_$(param.name).Value(), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
obj.selected = $(my.typenode.cxx_name)::$(param.cxx_enum_value);
obj.$(param.name).Value(tmp_$(param.name));
return MRN::Result(true);
}
. else
$(param->ref_type.cxx_type_name) tmp_$(param.name);
. if param->ref_type.kind = "array"
. my.blob_reader_name = "bar_$(param.name)"
const MRN::System::Ubus::Blob::BlobArrayReader& $(my.blob_reader_name) = bor.GetArray("$(param.name)");
if ($(my.blob_reader_name).IsValid()) {
oResult = $(param->ref_type.decode_func_name)($(my.blob_reader_name), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
obj.selected = $(my.typenode.cxx_name)::$(param.cxx_enum_value);
obj.$(param.name).Value(tmp_$(param.name));
return MRN::Result(true);
} else {
// lua вместо пустого массива отправляет пустую таблицу
const MRN::System::Ubus::Blob::BlobObjectReader& bor_empty_array_check = bor.GetObject("$(param.name)");
if (bor_empty_array_check.IsValid()) {
if (bor_empty_array_check.Length() != 0) {
return MRN::Result(false, "Cannot decode $(my.typenode.name): field '$(param.name)' is not an array");
}
// Пустой массив, ОК
obj.selected = $(my.typenode.cxx_name)::$(param.cxx_enum_value);
obj.$(param.name).Value(tmp_$(param.name));
return MRN::Result(true);
}
}
. else
. my.blob_reader_name = "bor_$(param.name)"
const MRN::System::Ubus::Blob::BlobObjectReader& $(my.blob_reader_name) = bor.GetObject("$(param.name)");
if ($(my.blob_reader_name).IsValid()) {
oResult = $(param->ref_type.decode_func_name)($(my.blob_reader_name), tmp_$(param.name));
if (!oResult) {
return MRN::Result(false, "Cannot decode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
obj.selected = $(my.typenode.cxx_name)::$(param.cxx_enum_value);
obj.$(param.name).Value(tmp_$(param.name));
return MRN::Result(true);
}
. endif
. endif
. endfor
return MRN::Result(false, "Cannot decode $(my.typenode.name): no variant is present");
}
.endmacro
.#
.macro generate_enum_decoder(typenode)
MRN::Result $(my.typenode.decode_func_name)(const char* str, $(my.typenode.cxx_enum_type_name)& value)
{
auto found = $(my.typenode.cxx_name)_map.find(str);
if (found == $(my.typenode.cxx_name)_map.end()) {
return MRN::Result(false, "Cannot decode enum value of $(my.typenode.name) '%s'", str);
}
value = found->second;
return MRN::Result(true);
}
.endmacro
.#
.macro generate_struct_encoder(typenode)
template<typename T>
MRN::Result $(my.typenode.encode_func_name)(MRN::System::Ubus::Blob::BlobObjectWriter<T>& bow, const $(my.typenode.cxx_type_name)& obj)
{
. if get_non_scalar_params_count(my.typenode) <> 0
MRN::Result oResult;
. endif
. for my.typenode.param
//.$(param.name)
. if defined(param.optional) & param.optional = "yes"
if (obj.$(param.name).IsSet()) {
. if param->typeinfo.is_scalar_type = "1"
. if param.type = "string"
bow.$(get_blob_object_writer_scalar_setter(param.type))("$(param.name)", obj.$(param.name).Value().c_str());
. else
bow.$(get_blob_object_writer_scalar_setter(param.type))("$(param.name)", obj.$(param.name).Value());
. endif
. elsif param->ref_type.kind = "enum"
const char* str_$(param.name);
oResult = $(param->ref_type.encode_func_name)(obj.$(param.name).Value(), str_$(param.name));
if (!oResult) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
bow.$(get_blob_object_writer_scalar_setter("string"))("$(param.name)", str_$(param.name));
. else
. if param->ref_type.kind = "array"
. my.blob_writer_name = "baw_$(param.name)"
auto $(my.blob_writer_name) = bow.AddArray("$(param.name)");
. else
. my.blob_writer_name = "bow_$(param.name)"
auto $(my.blob_writer_name) = bow.AddObject("$(param.name)");
. endif
oResult = $(param->ref_type.encode_func_name)($(my.blob_writer_name), obj.$(param.name).Value());
if (!oResult) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
. endif
}
. else
. if param->typeinfo.is_scalar_type = "1"
. if param.type = "string"
bow.$(get_blob_object_writer_scalar_setter(param.type))("$(param.name)", obj.$(param.name).c_str());
. else
bow.$(get_blob_object_writer_scalar_setter(param.type))("$(param.name)", obj.$(param.name));
. endif
. elsif param->ref_type.kind = "enum"
const char* str_$(param.name);
oResult = $(param->ref_type.encode_func_name)(obj.$(param.name), str_$(param.name));
if (!oResult) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
bow.AddString("$(param.name)", str_$(param.name));
. else
. if param->ref_type.kind = "array"
. my.blob_writer_name = "baw_$(param.name)"
auto $(my.blob_writer_name) = bow.AddArray("$(param.name)");
. else
. my.blob_writer_name = "bow_$(param.name)"
auto $(my.blob_writer_name) = bow.AddObject("$(param.name)");
. endif
oResult = $(param->ref_type.encode_func_name)($(my.blob_writer_name), obj.$(param.name));
if (!oResult) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
. endif
. endif
. endfor
bow.Close();
return MRN::Result(true);
}
.endmacro
.#
.macro generate_array_encoder(typenode)
template<typename T>
MRN::Result $(my.typenode.encode_func_name)(MRN::System::Ubus::Blob::BlobArrayWriter<T>& baw, const $(my.typenode.cxx_type_name)& arr)
{
. if my.typenode->typeinfo.is_scalar_type <> "1"
MRN::Result oResult;
. endif
for (const $(my.typenode->typeinfo.rf_type)& v : arr) {
. if my.typenode->typeinfo.is_scalar_type = "1"
. if my.typenode.elemtype = "string"
baw.$(get_blob_array_writer_scalar_setter(my.typenode.elemtype))(v.c_str());
. else
baw.$(get_blob_array_writer_scalar_setter(my.typenode.elemtype))(v);
. endif
. elsif my.typenode->ref_type.kind = "enum"
const char* str_elem;
oResult = $(my.typenode->ref_type.encode_func_name)(v, str_elem);
if (!oResult) {
baw.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name): %s", oResult.Message());
}
baw.$(get_blob_array_writer_scalar_setter("string"))(str_elem);
. else
. if my.typenode->ref_type.kind = "array"
. my.elem_writer_name = "baw_elem"
auto $(my.elem_writer_name) = baw.AddArray();
. else
. my.elem_writer_name = "bow_elem"
auto $(my.elem_writer_name) = baw.AddObject();
. endif
oResult = $(my.typenode->ref_type.encode_func_name)($(my.elem_writer_name), v);
if (!oResult) {
baw.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name): %s", oResult.Message());
}
. endif
}
baw.Close();
return MRN::Result(true);
}
.endmacro
.#
.macro generate_oneof_encoder(typenode)
template<typename T>
MRN::Result $(my.typenode.encode_func_name)(MRN::System::Ubus::Blob::BlobObjectWriter<T>& bow, const $(my.typenode.cxx_type_name)& obj)
{
. if get_non_scalar_params_count(my.typenode) <> 0
MRN::Result oResult;
. endif
switch (obj.selected) {
. for my.typenode.param
case $(my.typenode.cxx_name)::$(param.cxx_enum_value):
if (!obj.$(param.name).IsSet()) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name): $(param.name) is selected but not set");
}
. if param->typeinfo.is_scalar_type = "1"
. if param.type = "string"
bow.$(get_blob_object_writer_scalar_setter(param.type))("$(param.name)", obj.$(param.name).Value().c_str());
. else
bow.$(get_blob_object_writer_scalar_setter(param.type))("$(param.name)", obj.$(param.name).Value());
. endif
. elsif param->ref_type.kind = "enum"
{
const char* str_$(param.name);
oResult = $(param->ref_type.encode_func_name)(obj.$(param.name).Value(), str_$(param.name));
if (!oResult) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
bow.$(get_blob_object_writer_scalar_setter("string"))("$(param.name)", str_$(param.name));
}
. else
{
. if param->ref_type.kind = "array"
. my.blob_writer_name = "baw_$(param.name)"
auto $(my.blob_writer_name) = bow.AddArray("$(param.name)");
. else
. my.blob_writer_name = "bow_$(param.name)"
auto $(my.blob_writer_name) = bow.AddObject("$(param.name)");
. endif
oResult = $(param->ref_type.encode_func_name)($(my.blob_writer_name), obj.$(param.name).Value());
if (!oResult) {
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name).$(param.name): %s", oResult.Message());
}
}
. endif
break;
. endfor
default:
bow.Close();
return MRN::Result(false, "Cannot encode $(my.typenode.name): no variant is set");
}
bow.Close();
return MRN::Result(true);
}
.endmacro
.#
.macro generate_enum_encoder(typenode)
MRN::Result $(my.typenode.encode_func_name)($(my.typenode.cxx_enum_type_name) value, const char*& str)
{
switch (value) {
. for my.typenode.elem
case $(my.typenode.cxx_name)::$(elem.cxx_enum_value):
str = "$(elem.name)";
return MRN::Result(true);
. endfor
}
return MRN::Result(false, "Unknown enum value of $(my.typenode.name) '%u'", static_cast<unsigned int>(value));
}
.endmacro
.#
.macro generate_decoder(typenode)
. if my.typenode.kind = "array"
. generate_array_decoder(my.typenode)
. elsif my.typenode.kind = "oneof"
. generate_oneof_decoder(my.typenode)
. elsif my.typenode.kind = "enum"
. generate_enum_decoder(my.typenode)
. else
. generate_struct_decoder(my.typenode)
. endif
.endmacro
.#
.macro generate_encoder(typenode)
. if my.typenode.kind = "array"
. generate_array_encoder(my.typenode)
. elsif my.typenode.kind = "oneof"
. generate_oneof_encoder(my.typenode)
. elsif my.typenode.kind = "enum"
. generate_enum_encoder(my.typenode)
. else
. generate_struct_encoder(my.typenode)
. endif
.endmacro
.#
.macro generate_register_args(typenode)
void $(my.typenode.cxx_name)::register_args(MRN::System::Ubus::LocalProcedure* rpc)
{
. for my.typenode.param where !defined(param.optional) | param.optional <> "yes"
. if param->typeinfo.is_scalar_type = "1"
. my.register = get_rpc_paramater_type_register(param.type)
. elsif param->ref_type.kind = "enum"
. my.register = get_rpc_paramater_type_register("string")
. elsif param->ref_type.kind = "array"
. my.register = "ParameterArray"
. else
. my.register = "ParameterObject"
. endif
rpc = rpc->$(my.register)("$(param.name)");
. endfor
}
.endmacro
.#
.macro generate_decode_args(typenode)
MRN::Result $(my.typenode.cxx_name)::decode(const MRN::System::Ubus::Blob::BlobObjectReader& bor, $(my.typenode.cxx_type_name)& args)
{
return $(my.typenode.decode_func_name)(bor, args);
}
.endmacro
.#
.macro generate_encode_values(typenode)
MRN::Result $(my.typenode.cxx_name)::encode(MRN::System::Ubus::LocalProcedureReply& lpr, const char* field_name, const $(my.typenode.cxx_type_name)& values)
{
MRN::Result oResult;
auto bow = lpr.Values().AddObject(field_name);
oResult = $(my.typenode.encode_func_name)(bow, values);
if (!oResult) {
lpr.ResetValues();
}
return oResult;
}
.endmacro
.#
.#
.#
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <mrn/MRN.hxx>
#include "platform/Rpc.Messages.hxx"
.if is_enum_type_present()
. generate_hash_comparer()
.endif
namespace $(rpc.module)
{
namespace UbusMessages
{
namespace
{
.for types
. for type
. if (defined(type.decode) & type.decode = "yes") | (defined(type.encode) & type.encode = "yes")
/*
* $(type.cxx_name)
*/
. endif
. if defined(type.decode) & type.decode = "yes"
. if type.kind = "enum"
. generate_enum_map(type)
. endif
. generate_decoder(type)
. endif
. if defined(type.encode) & type.encode = "yes"
. generate_encoder(type)
. endif
. dividing_empty_line()
. endfor
.endfor
}
.for types
. for type
. if type.kind = "args"
/*
* $(type.cxx_name)
*/
. generate_register_args(type)
. generate_decode_args(type)
. dividing_empty_line()
. elsif type.kind = "values"
/*
* $(type.cxx_name)
*/
. generate_encode_values(type)
. dividing_empty_line()
. endif
. endfor
.endfor
}
}
.#
.#############################################################################
.# Rpc.Procedures.hxx #
.#############################################################################
.#
.output "../include/platform/Rpc.Procedures.hxx"
.#
.macro generate_ubus_callback_procedure_prototype(proc_node)
. my.params = "const $(my.proc_node->args_ref_type.cxx_namespaced_type_name)& args"
. if defined(my.proc_node.values)
. my.params = my.params + ", $(my.proc_node->values_ref_type.cxx_namespaced_type_name)& values"
. endif
// $(my.proc_node->doc:block)
// ubus–метод ‘$(my.proc_node.ubus_name)’
virtual MRN::Result $(my.proc_node.cxx_callback_name)($(my.params)) = 0;
.endmacro
.#
.macro generate_ubus_event_for_procedure(proc_node)
void $(my.proc_node.cxx_event_name)(MRN::System::Ubus::LocalProcedureCall& oCall);
.endmacro
.#
#ifndef $(rpc.module:upper)_UBUS_RPC_PROCEDURES_HXX
#define $(rpc.module:upper)_UBUS_RPC_PROCEDURES_HXX
namespace $(rpc.module)
{
class UbusRpcProcedures
{
.for procedures
. for procedure
. if first()
private:
. endif
. generate_ubus_callback_procedure_prototype(procedure)
. endfor
.endfor
.for procedures
. for procedure
. if first()
private:
. endif
. generate_ubus_event_for_procedure(procedure)
. endfor
.endfor
protected:
MRN::Result RegisterProcedures(MRN::System::Ubus::Namespace& ubus_namespace);
MRN::Result UnregisterProcedures(MRN::System::Ubus::Namespace& ubus_namespace);
};
}
#endif /*$(rpc.module:upper)_UBUS_RPC_PROCEDURES_HXX*/
.#
.#############################################################################
.# Rpc.Procedures.cxx #
.#############################################################################
.#
.output "../src/platform/Rpc.Procedures.cxx"
.#
.macro generate_ubus_register_procedure(proc_node)
{
//$(my.proc_node.ubus_name)
MRN::System::Ubus::LocalProcedure* rpc = ubus_namespace.AddProcedure("$(my.proc_node.ubus_name)");
$(my.proc_node->args_ref_type.cxx_namespaced_name)::register_args(rpc);
rpc->OnExecute().Bind(*this, &UbusRpcProcedures::$(my.proc_node.cxx_event_name));
}
.endmacro
.#
.macro generate_ubus_unregister_procedure(proc_node)
//$(my.proc_node.ubus_name)
ubus_namespace.GetProcedure("$(my.proc_node.ubus_name)")->OnExecute().Unbind(*this, &UbusRpcProcedures::$(my.proc_node.cxx_event_name));
.endmacro
.#
.macro generate_ubus_event_procedure_body(proc_node)
void UbusRpcProcedures::$(my.proc_node.cxx_event_name)(MRN::System::Ubus::LocalProcedureCall& oCall)
{
MRN::Result oResult(true);
$(my.proc_node->args_ref_type.cxx_namespaced_type_name) args;
oResult = $(my.proc_node->args_ref_type.cxx_namespaced_name)::decode(oCall.Arguments(), args);
if (!oResult) {
oCall.Result().InvalidArgument();
oCall.Reply().SendResult(oResult);
return;
}
. if defined(my.proc_node.values)
$(my.proc_node->values_ref_type.cxx_namespaced_type_name) values;
oResult = this->$(my.proc_node.cxx_callback_name)(args, values);
if (!oResult) {
oCall.Result().Ok();
oCall.Reply().SendResult(oResult);
return;
}
oResult = $(my.proc_node->values_ref_type.cxx_namespaced_name)::encode(oCall.Reply(), "ret_value", values);
. else
oResult = this->$(my.proc_node.cxx_callback_name)(args);
. endif
oCall.Result().Ok();
oCall.Reply().SendResult(oResult);
}
.endmacro
.#
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <mrn/MRN.hxx>
#include "platform/Rpc.Messages.hxx"
#include "platform/Rpc.Procedures.hxx"
namespace $(rpc.module)
{
MRN::Result UbusRpcProcedures::RegisterProcedures(MRN::System::Ubus::Namespace& ubus_namespace)
{
/* Registering of procedures */
.for procedures
. for procedure
. generate_ubus_register_procedure(procedure)
. endfor
.endfor
return MRN::Result(true);
}
MRN::Result UbusRpcProcedures::UnregisterProcedures(MRN::System::Ubus::Namespace& ubus_namespace)
{
/* Unregistering of procedures */
.for procedures
. for procedure
. generate_ubus_unregister_procedure(procedure)
. endfor
.endfor
return MRN::Result(true);
}
.for procedures
. for procedure
. generate_ubus_event_procedure_body(procedure)
. endfor
.endfor
}
.close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment