예제 #1
0
    def _load_variant_member(self, variant: VariantAlias):
        var_type_enum = self._get_variant_type_enum()
        if var_type_enum:
            self.buffer.append(
                f"switch(static_cast<{var_type_enum.type_name}>(m.type))")
        else:
            self.buffer.append(f"switch(m.{variant.type_name}.index())")

        self.buffer.append('{')
        with IndentedBlock(self.buffer):
            for i, var_member in enumerate(variant.member_type_defs):
                self.buffer.append(
                    f'case {self._get_variant_case_type_member(i)}:')
                self.buffer.append('{')
                with IndentedBlock(self.buffer):
                    self._load_variant_member_case(variant, var_member)
                    self.buffer.append('break;')
                self.buffer.append('}')
            # default case
            self.buffer.append('default:')
            self.buffer.append('{')
            with IndentedBlock(self.buffer):
                self.buffer.append(
                    'throw std::runtime_error(std::string() + "Unsupported variant type: " + '
                    'std::to_string(m.content.index()));')
            self.buffer.append('}')
        self.buffer.append('}')
예제 #2
0
 def _write_body(self):
     self.buffer.append('nlohmann::json res {')
     with IndentedBlock(self.buffer):
         for member_def in self.container_struct.members:
             self.member_to_json(member_def)
     self.buffer.append('};')
     self.buffer.append('return res;')
예제 #3
0
 def write_function(self):
     self.buffer.append(
         f"void FromJson({self.container_struct.type_name}& m, nlohmann::json const& j)"
     )
     self.buffer.append("{")
     with IndentedBlock(self.buffer):
         self._write_body()
     self.buffer.append("}")
예제 #4
0
 def _write_body(self):
     self.buffer.append('nlohmann::json res {')
     with IndentedBlock(self.buffer):
         self.buffer.append('{ "type": m.index() },')
     self.buffer.append('};')
     self.buffer.append('auto& content = res["content"];')
     self.buffer.append('// TODO: load content')
     self.buffer.append('return res;')
예제 #5
0
 def write_function(self):
     self.buffer.append(
         f"nlohmann::json ToJson({self.container_struct.type_name} const& m)"
     )
     self.buffer.append("{")
     with IndentedBlock(self.buffer):
         self._write_body()
     self.buffer.append("}")
     self.buffer.new_line()
예제 #6
0
 def _write_body(self):
     self.buffer.append(
         f'switch(j.at("type").get<{self.container_struct.type_name}::Type>())'
     )
     self.buffer.append('{')
     with IndentedBlock(self.buffer):
         self.buffer.append('// TODO: add missing cases')
         self.buffer.append(
             'default: throw std::runtime_error(std::string() + "Unexpected member type: " + j.at("type"))'
         )
     self.buffer.append('}')
예제 #7
0
 def write_header(self, buffer: LineBuffer,
                  _type_registry: TypeRegistry) -> None:
     buffer.append(
         f"enum class {self.enum_name()} : {self.type_def.underlying_type}")
     buffer.append('{')
     with IndentedBlock(buffer):
         if self.type_def.members:
             enum_members = self.type_def.members
             for m, i in enum_members.items():
                 comment = f"  //{self.type_def.comments[m]}" if m in self.type_def.comments else ''
                 buffer.append(f"{m} = {i},{comment}")
     buffer.append('};')
예제 #8
0
    def write_source(self, buffer: LineBuffer, type_registry: TypeRegistry):
        if self.type_def.namespaces:
            buffer.append('namespace ' + '::'.join(self.type_def.namespaces))
            buffer.append('{')
            buffer.indent_up()

        # internal namespace
        buffer.append(f"namespace internal")
        buffer.append("{")
        with IndentedBlock(buffer):
            # internal ToJson
            tjw = ToJsonWriter(buffer, type_registry, self.type_def)
            tjw.write_function()

            # internal FromJson
            fjw = FromJsonWriter(buffer, type_registry, self.type_def)
            fjw.write_function()

        buffer.append("}")
        buffer.new_line()

        # public ToJson
        buffer.append(f"std::string {self.type_def.type_name}::ToJson() const")
        buffer.append("{")
        with IndentedBlock(buffer):
            buffer.append('return internal::ToJson(*this).dump();')
        buffer.append("}")
        buffer.new_line()

        # public FromJson
        buffer.append(f"void {self.type_def.type_name}::FromJson(std::string const& js)")
        buffer.append("{")
        with IndentedBlock(buffer):
            buffer.append('internal::FromJson(*this, nlohmann::json::parse(js));')
        buffer.append("}")

        if self.type_def.namespaces:
            buffer.indent_down()
            buffer.append('}  // namespace ' + '::'.join(self.type_def.namespaces))
예제 #9
0
    def get_type_header_buffer(self, namespaces: List[str]) -> LineBuffer:
        ns_key = self._make_ns_key(namespaces)
        if ns_key not in self.include_headers:
            raise NameError(f"No namespace type info: {ns_key}")

        buffer = LineBuffer(0)
        if self.include_headers[ns_key]:
            buffer.new_line()
            for include in self.include_headers[ns_key]:
                buffer.append(f"#include <{include}>")
        buffer.new_line()
        ns_str = "::".join(namespaces)
        buffer.append(f'namespace {ns_str}')
        buffer.append('{')
        with IndentedBlock(buffer):
            for buf in self.buffers[ns_key]:
                buffer.append_buffer(buf)
        buffer.append(f'}} // {ns_str}')

        return buffer
예제 #10
0
    def write_source(self, buffer: LineBuffer, type_registry: TypeRegistry):
        if self.type_def.namespaces:
            buffer.append('namespace ' + '::'.join(self.type_def.namespaces))
            buffer.append('{')
            buffer.indent_up()

        # internal namespace
        buffer.append(f"namespace internal")
        buffer.append("{")
        with IndentedBlock(buffer):
            fjw = FromJsonWriter(buffer, type_registry, self.type_def)
            fjw.write_function()

            tjw = ToJsonWriter(buffer, type_registry, self.type_def)
            tjw.write_function()

        buffer.append("}")
        buffer.new_line()

        if self.type_def.namespaces:
            buffer.indent_down()
            buffer.append('}  // namespace ' + '::'.join(self.type_def.namespaces))
예제 #11
0
    def write_header(self, buffer: LineBuffer, type_registry: TypeRegistry) -> None:
        var_buffer = LineBuffer(0)
        type_buffer = LineBuffer(0)
        for type_def in self.type_def.members:
            if isinstance(type_def, SimpleAlias):
                cpp_alias = CppSimpleAlias(type_def)
                var_buffer.append(f"{cpp_alias.actual_type()} {type_def.type_name};")
                self.header_includes.update(cpp_alias.get_include_headers(type_registry))
            elif isinstance(type_def, ArrayAlias):
                cpp_array = CppArrayAlias(type_def)
                var_buffer.append(f"{cpp_array.actual_type(type_registry)} {type_def.type_name};")
                self.header_includes.update(cpp_array.get_include_headers(type_registry))
            elif isinstance(type_def, VariantAlias):
                cpp_variant = CppVariantAlias(type_def)
                var_buffer.append(f"{cpp_variant.actual_type(type_registry)} {type_def.type_name};")
                self.header_includes.update(cpp_variant.get_include_headers(type_registry))
            elif isinstance(type_def, EnumType):
                cpp_enum = CppEnum(type_def)
                cpp_enum.write_header(type_buffer, type_registry)
                type_buffer.new_line()
            elif isinstance(type_def, StructType):
                cpp_struct = CppStruct(type_def)
                cpp_struct.write_header(type_buffer, type_registry)
                type_buffer.new_line()
                self.header_includes.update(cpp_struct.header_includes)
            elif isinstance(type_def, ExtendedVariant):
                cpp_struct = CppExtendedVariant(type_def)
                cpp_struct.write_header(type_buffer, type_registry)
                type_buffer.new_line()
                self.header_includes.update(cpp_struct.header_includes)
            elif isinstance(type_def, RefType):
                cpp_ref_alias = CppRefAlias(type_def)
                var_buffer.append(f"{cpp_ref_alias.target_type(type_registry)} {type_def.type_name};")
            else:
                raise TypeError(f"Unsupported struct member type: [{type_def}]")

        # generate struct
        if self.type_def.namespaces:
            buffer.append('namespace ' + '::'.join(self.type_def.namespaces))
            buffer.append('{')
            buffer.indent_up()

        if self.base_classes:
            suffix = ' : ' + ', '.join(self.base_classes)
        else:
            suffix = ''
        buffer.append(f"struct {self.type_def.type_name}{suffix}")
        buffer.append("{")

        if type_buffer:
            with IndentedBlock(buffer):
                buffer.append_buffer(type_buffer)

        if var_buffer:
            with IndentedBlock(buffer):
                buffer.append_buffer(var_buffer)
            buffer.new_line()

        # pre-defined methods
        with IndentedBlock(buffer):
            if self.member_methods:
                for method in self.member_methods:
                    buffer.append(method)
            else:
                buffer.pop()

        buffer.append('};')
        if self.type_def.namespaces:
            buffer.indent_down()
            buffer.append('}  // namespace ' + '::'.join(self.type_def.namespaces))
예제 #12
0
    def write_header(self, buffer: LineBuffer, type_registry: TypeRegistry) -> None:
        # generate extended struct
        if self.type_def.namespaces:
            buffer.append('namespace ' + '::'.join(self.type_def.namespaces))
            buffer.append('{')
            buffer.indent_up()

        if self.base_classes:
            suffix = ' : ' + ', '.join(self.base_classes)
        else:
            suffix = ''
        variant_members = ['std::monostate']
        for member_type_def in self.type_def.content_variant.member_type_defs:
            if isinstance(member_type_def, SimpleAlias):
                cpp_alias = CppSimpleAlias(member_type_def)
                variant_members.append(cpp_alias.actual_type())
            elif isinstance(member_type_def, ArrayAlias):
                cpp_array = CppArrayAlias(member_type_def)
                variant_members.append(cpp_array.actual_type(type_registry))
            elif isinstance(member_type_def, StructType):
                #     cpp_struct = CppStruct(member_type_def)
                #     variant_members.append(cpp_struct.type_def.type_name)
                pass
            elif isinstance(member_type_def, RefType):
                #     target_type = type_registry.get_ref_target(member_type_def.target_uri)
                #     variant_members.append(target_type.type_name)
                pass
            else:
                raise TypeError(f"Unsupported struct member type: [{member_type_def}]")

        buffer.append(f"struct {self.type_def.type_name}{suffix} : std::variant<{','.join(variant_members)}>")
        buffer.append("{")

        with IndentedBlock(buffer):
            # write type enum
            cpp_enum = CppEnum(self.type_def.type_enum)
            cpp_enum.type_def.type_name = cpp_enum.type_def.type_name.capitalize()
            cpp_enum.write_header(buffer, type_registry)
            buffer.append('')

            cast_expr = f'static_cast<{self.type_def.type_enum.underlying_type}>(MemberType)'
            # write setter
            buffer.append('template <Type MemberType, typename T>')
            buffer.append(f'void SetAs(T value) ')
            buffer.extend_last('{ ')
            buffer.extend_last(f'emplace<{cast_expr}>(value);')
            buffer.extend_last(' }')
            buffer.new_line()

            # write non-const getter
            buffer.append('template <Type MemberType>')
            buffer.append(f'[[nodiscard]] auto& GetAs() ')
            buffer.extend_last('{ ')
            buffer.extend_last(f'return std::get<{cast_expr}>(*this);')
            buffer.extend_last(' }')
            buffer.new_line()

            # write const getter
            buffer.append('template <Type MemberType>')
            buffer.append(f'[[nodiscard]] auto const& GetAs() const ')
            buffer.extend_last('{ ')
            buffer.extend_last(f'return std::get<{cast_expr}>(*this);')
            buffer.extend_last(' }')

            # pre-defined methods
            with IndentedBlock(buffer):
                if self.member_methods:
                    for method in self.member_methods:
                        buffer.append(method)

        buffer.append('};')
        if self.type_def.namespaces:
            buffer.indent_down()
            buffer.append('}  // namespace ' + '::'.join(self.type_def.namespaces))