Created
September 7, 2020 11:41
-
-
Save Xitsa/0cb6939c7a4ef9d729798398548f16bf to your computer and use it in GitHub Desktop.
Генератор RPC-вызовов на gsl.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .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