#include #include #include #include #include #include #include #include #include #include namespace saw { namespace schema { using CVar = Struct< Member, Member, Member, Member, Member, Member >; using CStruct = Struct< Member, Member, Member, Member, "members"> >; using CFunction = Struct< Member, Member, Member, Member, "params">, Member >; using CIface = Struct< Member, Member, Member,"structs">, Member,"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, "a"> Member, "b"> >; Needs to be flattened to template using FlattenedSchemaElement = Struct< Member, "path">, Member >; // Illegal, but doable with more lines of code // Just use typename... T and // "T..." for // "Member,Names>...>" // and specialize somewhere else template using FlattenedSchema = Struct< Member, Member, Names>... >; } */ template struct schema_flattener { static_assert(always_false, "Not supported"); }; template struct schema_flattener,schema::Member...>, Res> { }; /** * Helper to determine if we are dealing with primitive types */ template struct c_is_primitive { static constexpr bool value = false; }; template struct c_is_primitive> { static constexpr bool value = true; }; template struct c_primitive_string { static_assert(always_false, "Not supported"); }; template<> struct c_primitive_string { static constexpr string_literal name = "int8"; static constexpr string_literal value = "int8_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "int16"; static constexpr string_literal value = "int16_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "int32"; static constexpr string_literal value = "int32_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "int64"; static constexpr string_literal value = "int64_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "uint8"; static constexpr string_literal value = "uint8_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "uint16"; static constexpr string_literal value = "uint16_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "uint32"; static constexpr string_literal value = "uint32_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "uint64"; static constexpr string_literal value = "uint64_t"; }; template<> struct c_primitive_string { static constexpr string_literal name = "float32"; static constexpr string_literal value = "float"; }; template<> struct c_primitive_string { static constexpr string_literal name = "float64"; static constexpr string_literal value = "double"; }; error_or> c_interface_find_struct_by_crc32(const data& state, const data& 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{i}; } } return make_error(); } error_or c_interface_add_struct(data& state, data&& 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& 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; } template struct c_data_translater { static_assert(always_false, "Not supported"); }; template struct c_data_translater> { using Schema = schema::Primitive; static constexpr string_literal c_type_name = c_primitive_string::name; static constexpr string_literal c_type = c_primitive_string::value; static error_or generate(data& state, data& prim){ try{ std::stringstream iss; schema_stringify::apply(iss); prim.template get<"schema">().set(iss.str()); prim.template get<"crc32">().set(schema_hash::apply()); prim.template get<"is_primitive">().set(1); prim.template get<"type">().set(std::string{c_primitive_string::value.view()}); }catch(const std::exception&){ return make_error(); } return void_t{}; } }; template struct c_data_translater> { static_assert(N==1, "Doesn't support more than one dimension currently"); using Schema = schema::Array; static constexpr string_literal c_type_name = "array_"_sl + c_data_translater::c_type_name + "_1d"_sl; static constexpr string_literal c_type = c_type_name + "_t"_sl; static error_or generate(data& state, data& arr){ try{ { std::stringstream iss; schema_stringify::apply(iss); arr.template get<"schema">().set(iss.str()); arr.template get<"crc32">().set(schema_hash::apply()); arr.template get<"is_primitive">().set(0); } /// @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()); } data 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 c_var; std::stringstream iss; schema_stringify::apply(iss); c_var.template get<"schema">().set(iss.str()); c_var.template get<"crc32">().set(schema_hash::apply()); if constexpr (is_primitive::value){ c_var.template get<"type">().set(std::string{c_primitive_string::value.view()} + "*"); c_var.template get<"name">().set(std::string{"data"}); c_var.template get<"is_primitive">().set(1); }else{ return make_error(); } auto eov_add = membs.add(std::move(c_var)); if(eov_add.is_error()){ return std::move(eov_add.get_error()); } } { data c_var; std::stringstream iss; schema_stringify::apply(iss); c_var.template get<"schema">().set(iss.str()); c_var.template get<"crc32">().set(schema_hash::apply()); if constexpr (is_primitive::value){ c_var.template get<"type">().set(std::string{c_primitive_string::value.view()}); c_var.template get<"name">().set(std::string{"size"}); c_var.template get<"is_primitive">().set(1); }else{ return make_error(); } auto eov_add = membs.add(std::move(c_var)); if(eov_add.is_error()){ return std::move(eov_add.get_error()); } } /** * 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()); } } } } arr.template get<"type">().set(std::string{c_type.view()}); }catch(const std::exception&){ return make_error(); } return void_t{}; } }; /* template struct c_data_translater> { using Schema = schema::Struct; static error_or generate(data& state){ return void_t{}; } }; */ template struct c_parameter_translater { static_assert(always_false, "Type not supported"); }; template struct c_parameter_translater...>> { template static error_or generate_ele(data& state, data>& params){ using Type = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; { auto c_var = data{}; c_var.template get<"name">().set(std::string{Literal.view()}); { auto eov = c_data_translater::generate(state,c_var); if(eov.is_error()){ return eov; } } { auto eov = params.add(std::move(c_var)); if(eov.is_error()){ return eov; } } } if constexpr ( (i+1) < sizeof...(V) ) { return generate_ele(state, params); } return void_t{}; } static error_or generate(data& state, data>& params){ if constexpr ( sizeof...(V) > 0){ return generate_ele<0>(state, params); } return void_t{}; } }; template struct c_data_translater> { using Schema = schema::Function; static error_or generate_struct_params(data& state, data>& params){ return c_parameter_translater::generate(state, params); } static error_or generate(data& state, const std::string_view& func_name){ if(c_interface_function_exists(state, func_name)){ return make_error("Function already exists"); } auto& funcs = state.template get<"functions">(); data function; function.template get<"name">().set(std::string{func_name}); try{ std::stringstream iss; schema_stringify::apply(iss); function.template get<"schema">().set(iss.str()); function.template get<"crc32">().set(schema_hash::apply()); }catch(const std::exception&){ return make_error(); } // Return value { auto& c_var = function.template get<"return">(); c_var.template get<"name">().set("ret_val"); auto eov = c_data_translater::generate(state, c_var); if(eov.is_error()){ return eov; } } // Request values auto& params = function.template get<"params">(); if constexpr (is_primitive::value){ auto c_var = data{}; c_var.template get<"name">().set("req_val"); { auto eov = c_data_translater::generate(state, c_var); if(eov.is_error()){ return eov; } } { auto eov = params.add(std::move(c_var)); if(eov.is_error()){ return eov; } } } else { auto eov = generate_struct_params(state, params); if(eov.is_error()){ return eov; } } { auto eov = funcs.add(std::move(function)); if(eov.is_error()){ return eov; } } return void_t{}; } }; template struct c_data_translater...>> { using Schema = schema::Interface...>; template static error_or generate_ele(data& state){ using InnerSchema = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; { auto eov = c_data_translater::generate(state, Literal.view()); if(eov.is_error()){ return eov; } } /** * Continue if elements remain or finish */ if constexpr ( (i+1) < sizeof...(Funcs) ){ return generate_ele(state); } return void_t{}; } static error_or generate(data& state){ try{ std::stringstream iss; schema_stringify::apply(iss); state.template get<"schema">().set(iss.str()); state.template get<"crc32">().set(schema_hash::apply()); }catch(const std::exception&){ return make_error(); } if constexpr (sizeof...(Funcs) > 0){ return generate_ele<0>(state); } return void_t{}; } }; template error_or generate_c_interface(data& state){ auto eov = c_data_translater::generate(state); return eov; } }