diff options
Diffstat (limited to 'modules/tools')
-rw-r--r-- | modules/tools/c++/c_gen_iface.hpp | 474 | ||||
-rwxr-xr-x | modules/tools/python/c_generate_iface.py | 24 | ||||
-rw-r--r-- | modules/tools/tests/c_iface.cpp | 20 |
3 files changed, 150 insertions, 368 deletions
diff --git a/modules/tools/c++/c_gen_iface.hpp b/modules/tools/c++/c_gen_iface.hpp index b55816c..2dfa36f 100644 --- a/modules/tools/c++/c_gen_iface.hpp +++ b/modules/tools/c++/c_gen_iface.hpp @@ -12,81 +12,9 @@ #include <iostream> namespace saw { - -namespace schema { - -using CVar = Struct< - Member<schema::String, "schema">, - Member<schema::UInt32, "crc32">, - Member<schema::String, "type">, - Member<schema::String, "type_name">, - Member<schema::String, "name">, - Member<schema::Int8, "is_primitive"> ->; - -using CStruct = Struct< - Member<schema::String, "schema">, - Member<schema::UInt32, "crc32">, - Member<schema::String, "type">, - Member<Array<CVar>, "members"> ->; - -using CFunction = Struct< - Member<schema::String, "schema">, - Member<schema::UInt32, "crc32">, - Member<schema::String, "name">, - Member<Array<CVar>, "params">, - Member<CVar, "return"> ->; - -using CIface = Struct< - Member<schema::String, "schema">, - Member<schema::UInt32, "crc32">, - Member<Array<CStruct>,"structs">, - Member<Array<CFunction>,"functions"> ->; -} -/** - * Type meant to provide future help if I decide to introduce more maps - */ -/** -namespace schema { -using namespace saw::schema; -Pseudo flattened -using Foo = Struct< - Member<Array<Int32>, "a"> - Member<Array<Float32>, "b"> ->; - -Needs to be flattened to - -template<typename InnerSchema> -using FlattenedSchemaElement = Struct< - Member<Array<String>, "path">, - Member<InnerSchema, "inner_schema"> ->; - -// Illegal, but doable with more lines of code -// Just use typename... T and -// "T..." for -// "Member<FlattenedSchemaElement<Ele>,Names>...>" -// and specialize somewhere else -template<typename... Ele, string_literal... Names> -using FlattenedSchema = Struct< - Member<String, "top_schema">, - Member<FlattenedSchemaElement<Ele>, Names>... ->; +namespace binding { +struct C {}; } -*/ - -template<typename T, typename Res> -struct schema_flattener { - static_assert(always_false<T>, "Not supported"); -}; - -template<typename T0, string_literal Name0, typename... T, string_literal... Names, typename Res> -struct schema_flattener<schema::Struct<schema::Member<T0,Name0>,schema::Member<T,Names>...>, Res> { -}; /** * Helper to determine if we are dealing with primitive types @@ -166,336 +94,222 @@ struct c_primitive_string<schema::Float64> { static constexpr string_literal value = "double"; }; -error_or<data<schema::UInt64>> c_interface_find_struct_by_crc32(const data<schema::CIface>& state, const data<schema::UInt32>& id){ - const auto& strs = state.template get<"structs">(); - for(uint64_t i = 0; i < strs.size(); ++i){ - const auto& str = strs.at(i); - if(str.template get<"crc32">() == id){ - return data<schema::UInt64>{i}; - } - } - return make_error<err::not_found>(); -} - -error_or<void> c_interface_add_struct(data<schema::CIface>& state, data<schema::CStruct>&& val){ - auto& strs = state.template get<"structs">(); - auto eov = strs.add(std::move(val)); - if(eov.is_error()){ - return std::move(eov.get_error()); - } - return void_t{}; -} - -bool c_interface_function_exists(data<schema::CIface>& state, const std::string_view& name){ - auto& funcs = state.template get<"functions">(); - for(uint64_t i = 0; i < funcs.size(); ++i){ - if(funcs.at(i).get<"name">() == name){ - return true; - } - } - return false; -} +struct language_binding_config { + std::string prefix; +}; -template<typename Schema> -struct c_data_translater { +namespace impl { +template<typename Schema, typename Lang> +struct lang_bind { static_assert(always_false<Schema>, "Not supported"); }; -template<typename T, uint64_t N> -struct c_data_translater<schema::Primitive<T,N>> { - using Schema = schema::Primitive<T,N>; - static constexpr string_literal c_type_name = c_primitive_string<Schema>::name; - static constexpr string_literal c_type = c_primitive_string<Schema>::value; - - static error_or<void> generate(data<schema::CIface>& state, data<schema::CVar>& prim){ - try{ - std::stringstream iss; - schema_stringify<Schema>::apply(iss); - prim.template get<"schema">().set(iss.str()); - prim.template get<"crc32">().set(schema_hash<Schema>::apply()); - prim.template get<"is_primitive">().set(1); - prim.template get<"type">().set(std::string{c_primitive_string<Schema>::value.view()}); - }catch(const std::exception&){ - return make_error<err::out_of_memory>(); +struct language_binding_state { + struct info { + std::string type; + }; + std::map<uint32_t, language_binding_state::info> hashes; +}; + +struct lang_bind_helper { + static error_or<void> append_string(buffer& buff, const std::string_view& str){ + for(uint64_t i = 0; i < str.size(); ++i){ + auto err = buff.push(static_cast<uint8_t>(str[i])); + if(!err.template is_type<err::no_error>()){ + return err; + } } + return void_t{}; + } + static error_or<void> append_hashed_type(buffer& buff, const std::string_view& prefix, uint32_t hash){ + { + auto eov = append_string(buff, prefix); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = append_string(buff, "_"); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = append_string(buff, std::to_string(hash)); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = append_string(buff, "_t"); + if(eov.is_error()){ + return eov; + } + } return void_t{}; } }; -template<typename T, uint64_t N> -struct c_data_translater<schema::Array<T,N>> { - static_assert(N==1, "Doesn't support more than one dimension currently"); - - using Schema = schema::Array<T,N>; - static constexpr string_literal c_type_name = "array_"_sl + c_data_translater<T>::c_type_name + "_1d"_sl; - static constexpr string_literal c_type = c_type_name + "_t"_sl; - - static error_or<void> generate(data<schema::CIface>& state, data<schema::CVar>& arr){ - try{ - { - std::stringstream iss; - schema_stringify<Schema>::apply(iss); - arr.template get<"schema">().set(iss.str()); - arr.template get<"crc32">().set(schema_hash<Schema>::apply()); - arr.template get<"is_primitive">().set(0); - } +template<typename T, uint64_t L> +struct lang_bind<schema::Primitive<T,L>, binding::C> { + using Schema = schema::Primitive<T,L>; - /// @todo change this !!!!! - { - auto eov = c_interface_find_struct_by_crc32(state, arr.template get<"crc32">()); - if(eov.is_error()){ - if(false){ - return std::move(eov.get_error()); + static error_or<void> generate(buffer& buff, const language_binding_config& cfg, language_binding_state& state){ + constexpr uint64_t hash = schema_hash<Schema>::apply(); + + { + std::string hash_type_str = cfg.prefix + "_" + std::to_string(hash) + "_t"; + auto emp = state.hashes.emplace(std::make_pair(hash, hash_type_str)); + if(emp.second){ + { + auto eov = lang_bind_helper::append_string(buff, "typedef "); + if(eov.is_error()){ + return eov; } - data<schema::CStruct> str; - str.template get<"schema">() = arr.template get<"schema">(); - str.template get<"crc32">() = arr.template get<"crc32">(); - str.template get<"type">().set(std::string{c_type.view()}); - auto& membs = str.template get<"members">(); - { - data<schema::CVar> c_var; - std::stringstream iss; - schema_stringify<T>::apply(iss); - c_var.template get<"schema">().set(iss.str()); - c_var.template get<"crc32">().set(schema_hash<T>::apply()); - if constexpr (is_primitive<T>::value){ - c_var.template get<"type">().set(std::string{c_primitive_string<T>::value.view()} + "*"); - c_var.template get<"name">().set(std::string{"data"}); - c_var.template get<"is_primitive">().set(1); - }else{ - return make_error<err::not_implemented>(); - } - - auto eov_add = membs.add(std::move(c_var)); - if(eov_add.is_error()){ - return std::move(eov_add.get_error()); - } + } + { + auto eov = lang_bind_helper::append_string(buff, c_primitive_string<Schema>::value.view()); + if(eov.is_error()){ + return eov; } - { - data<schema::CVar> c_var; - std::stringstream iss; - schema_stringify<schema::UInt64>::apply(iss); - c_var.template get<"schema">().set(iss.str()); - c_var.template get<"crc32">().set(schema_hash<schema::UInt64>::apply()); - if constexpr (is_primitive<T>::value){ - c_var.template get<"type">().set(std::string{c_primitive_string<schema::UInt64>::value.view()}); - c_var.template get<"name">().set(std::string{"size"}); - c_var.template get<"is_primitive">().set(1); - }else{ - return make_error<err::not_implemented>(); - } - - auto eov_add = membs.add(std::move(c_var)); - if(eov_add.is_error()){ - return std::move(eov_add.get_error()); - } + } + { + auto eov = lang_bind_helper::append_string(buff, " "); + if(eov.is_error()){ + return eov; } - - /** - * Add the struct to the struct array - */ - { - auto eov_add = c_interface_add_struct(state, std::move(str)); - if(eov_add.is_error()){ - return std::move(eov_add.get_error()); - } + } + { + auto eov = lang_bind_helper::append_string(buff, hash_type_str); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = lang_bind_helper::append_string(buff, ";\n"); + if(eov.is_error()){ + return eov; } } } - arr.template get<"type">().set(std::string{c_type.view()}); - }catch(const std::exception&){ - return make_error<err::out_of_memory>(); } return void_t{}; } }; -/* -template<typename... Members> -struct c_data_translater<schema::Struct<Members...>> { - using Schema = schema::Struct<Members...>; - - static error_or<void> generate(data<schema::CIface>& state){ - return void_t{}; - } -}; -*/ - -template<typename Str> -struct c_parameter_translater { - static_assert(always_false<Str>, "Type not supported"); -}; - -template<typename... V, string_literal... K> -struct c_parameter_translater<schema::Struct<schema::Member<V,K>...>> { - template<uint64_t i> - static error_or<void> generate_ele(data<schema::CIface>& state, data<schema::Array<schema::CVar>>& params){ - using Type = typename parameter_pack_type<i, V...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i,K...>::literal; +template<typename Input, typename Output> +struct lang_bind<schema::Function<Input, Output>, binding::C> { + static error_or<void> generate(buffer& buff, const language_binding_config& cfg, language_binding_state& state){ + constexpr uint64_t input_hash = schema_hash<Input>::apply(); + constexpr uint64_t output_hash = schema_hash<Output>::apply(); { - auto c_var = data<schema::CVar>{}; - c_var.template get<"name">().set(std::string{Literal.view()}); - { - auto eov = c_data_translater<Type>::generate(state,c_var); + auto eov = lang_bind<Input, binding::C>::generate(buff, cfg, state); if(eov.is_error()){ return eov; } - } - { - auto eov = params.add(std::move(c_var)); + } + { + auto eov = lang_bind<Output, binding::C>::generate(buff, cfg, state); if(eov.is_error()){ return eov; } - } } - if constexpr ( (i+1) < sizeof...(V) ) { - return generate_ele<i+1>(state, params); - } - return void_t{}; - } - - static error_or<void> generate(data<schema::CIface>& state, data<schema::Array<schema::CVar>>& params){ - if constexpr ( sizeof...(V) > 0){ - return generate_ele<0>(state, params); - } return void_t{}; } }; -template<typename Req, typename Ret> -struct c_data_translater<schema::Function<Req,Ret>> { - using Schema = schema::Function<Req,Ret>; - - static error_or<void> generate_struct_params(data<schema::CIface>& state, data<schema::Array<schema::CVar>>& params){ - return c_parameter_translater<Req>::generate(state, params); - } +template<typename... M> +struct lang_bind<schema::Interface<M...>, binding::C> { + template<uint64_t i> + static error_or<void> generate_element(buffer& buff, const language_binding_config& cfg, language_binding_state& state){ + using Member = typename parameter_pack_type<i, M...>::type; + using MValue = typename Member::ValueType; + static constexpr string_literal MKey = Member::KeyLiteral; - static error_or<void> generate(data<schema::CIface>& state, const std::string_view& func_name){ - if(c_interface_function_exists(state, func_name)){ - return make_error<err::invalid_state>("Function already exists"); + { + auto eov = lang_bind<MValue, binding::C>::generate(buff, cfg, state); + if(eov.is_error()){ + return eov; + } } - auto& funcs = state.template get<"functions">(); - data<schema::CFunction> function; - function.template get<"name">().set(std::string{func_name}); - - try{ - std::stringstream iss; - schema_stringify<Schema>::apply(iss); - function.template get<"schema">().set(iss.str()); - function.template get<"crc32">().set(schema_hash<Schema>::apply()); - }catch(const std::exception&){ - return make_error<err::out_of_memory>(); + { + auto eov = lang_bind_helper::append_string(buff, cfg.prefix); + if(eov.is_error()){ + return eov; + } } - - // Return value { - auto& c_var = function.template get<"return">(); - c_var.template get<"name">().set("ret_val"); - auto eov = c_data_translater<Ret>::generate(state, c_var); + auto eov = lang_bind_helper::append_string(buff, "_"); if(eov.is_error()){ return eov; } } - - // Request values - auto& params = function.template get<"params">(); - if constexpr (is_primitive<Req>::value){ - auto c_var = data<schema::CVar>{}; - c_var.template get<"name">().set("req_val"); - { - auto eov = c_data_translater<Req>::generate(state, c_var); - if(eov.is_error()){ - return eov; - } + { + auto eov = lang_bind_helper::append_string(buff, MKey.view()); + if(eov.is_error()){ + return eov; } - { - auto eov = params.add(std::move(c_var)); - if(eov.is_error()){ - return eov; - } + } + { + auto eov = lang_bind_helper::append_string(buff, "("); + if(eov.is_error()){ + return eov; } - } else { - auto eov = generate_struct_params(state, params); + } + { + auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, schema_hash<Member>::apply()); if(eov.is_error()){ return eov; } } - { - auto eov = funcs.add(std::move(function)); + auto eov = lang_bind_helper::append_string(buff, ","); if(eov.is_error()){ return eov; } } - - return void_t{}; - } -}; - -template<typename... Funcs, string_literal... Names> -struct c_data_translater<schema::Interface<schema::Member<Funcs,Names>...>> { - using Schema = schema::Interface<schema::Member<Funcs, Names>...>; - - template<std::size_t i> - static error_or<void> generate_ele(data<schema::CIface>& state){ - using InnerSchema = typename parameter_pack_type<i, Funcs...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Names...>::literal; { - auto eov = c_data_translater<InnerSchema>::generate(state, Literal.view()); + auto eov = lang_bind_helper::append_string(buff, ");"); if(eov.is_error()){ return eov; } } - /** - * Continue if elements remain or finish - */ - if constexpr ( (i+1) < sizeof...(Funcs) ){ - return generate_ele<i+1>(state); + if constexpr ((i+1) < sizeof...(M) ){ + return generate_element<i+1>(buff, cfg, state); } return void_t{}; } - static error_or<void> generate(data<schema::CIface>& state){ - try{ - std::stringstream iss; - schema_stringify<Schema>::apply(iss); - state.template get<"schema">().set(iss.str()); - state.template get<"crc32">().set(schema_hash<Schema>::apply()); - }catch(const std::exception&){ - return make_error<err::out_of_memory>(); + static error_or<void> generate(buffer& buff, const language_binding_config& cfg){ + if(cfg.prefix.size() == 0){ + return make_error<err::invalid_state>("C interfaces need a prefix."); } - - if constexpr (sizeof...(Funcs) > 0){ - return generate_ele<0>(state); + language_binding_state state; + + if constexpr (sizeof...(M) > 0){ + return generate_element<0>(buff, cfg, state); } + return void_t{}; } }; - -template<typename Interface> -error_or<void> generate_c_interface(data<schema::CIface>& state){ - auto eov = c_data_translater<Interface>::generate(state); - return eov; -} -/* -namespace lang { -struct C {}; } -template<typename Iface, typename T> -class binding; +template<typename IfaceSchema, typename Binding> +struct language_binding { + static_assert(always_false<IfaceSchema, Binding>, "Case not supported."); +}; -template<typename Iface> -class binding<Iface, lang::C> { -public: - static constexpr string_literal header; - static constexpr string_literal source; +template<typename IfaceSchema> +struct language_binding<IfaceSchema, binding::C> { + static error_or<void> generate(buffer& buff, const language_binding_config& cfg){ + return impl::lang_bind<IfaceSchema, binding::C>::generate(buff, cfg); + } }; -*/ } diff --git a/modules/tools/python/c_generate_iface.py b/modules/tools/python/c_generate_iface.py deleted file mode 100755 index d234482..0000000 --- a/modules/tools/python/c_generate_iface.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 - -import argparse; -import jinja2; - - -def parse_args(): - parser = argparse.ArgumentParser( - description = "Generates bindings for the Interface schema" - ); - parser.add_argument( - '-t', '--template', - required=True, - help = "Path to the template directory" - ); - - return parser.parse_args(); - -def main(): - return 0; - -if __name__ == "__main__": - rc = main(); - exit(rc); diff --git a/modules/tools/tests/c_iface.cpp b/modules/tools/tests/c_iface.cpp index 4f1b744..79d2344 100644 --- a/modules/tools/tests/c_iface.cpp +++ b/modules/tools/tests/c_iface.cpp @@ -41,23 +41,14 @@ template<typename Schema> void test_generate(std::string& res){ using namespace saw; - data<schema::CIface> c_iface; - { - auto eov = generate_c_interface<Schema>(c_iface); - SAW_EXPECT(eov.is_value(), "Couldn't generate interface info"); - } - - data<schema::CIface, encode::Json> j_data; - codec_config<encode::Json> j_config; - j_config.pretty = true; - codec<schema::CIface, encode::Json> j_codec{j_config}; + ring_buffer r_buff{4u * 1024u * 1024u}; { - auto eov = j_codec.encode(c_iface, j_data); - SAW_EXPECT(eov.is_value(), "Couldn't encode data"); + auto eov = language_binding<Schema, binding::C>::generate(r_buff, {"kel"}); + SAW_EXPECT(eov.is_value(), std::string{"Couldn't generate interface info: "} + std::string{eov.get_error().get_message()}); } - res = convert_to_string(j_data.get_buffer()); + res = convert_to_string(r_buff); } SAW_TEST("CIface Empty Interface"){ @@ -76,7 +67,7 @@ SAW_TEST("CIface One Function Interface"){ test_generate<schema::TestOneFunctionInterface>(res); std::cout<<"\n"<<res<<"\n"<<std::endl; } - +/* SAW_TEST("CIface Struct Function Interface"){ using namespace saw; @@ -92,4 +83,5 @@ SAW_TEST("CIface Array Function Interface"){ test_generate<schema::TestArrayFunctionInterface>(res); std::cout<<"\n"<<res<<"\n"<<std::endl; } +*/ } |