Exemplo n.º 1
0
 def _add_has(e: UxsdElement):
     impl = ""
     if e.many:
         pname = utils.to_pascalcase(utils.pluralize(e.name))
     else:
         pname = utils.to_pascalcase(e.name)
     impl += "return reader.has{pname}();\n".format(pname=pname)
     _add_field("bool", "has", e.name, _gen_reader(t) + " &reader", impl)
Exemplo n.º 2
0
def _gen_write_complex_element(e: UxsdElement, parent: str) -> str:
    """Function to generate partial code which writes out an element with a complex type."""
    assert isinstance(e.type, UxsdComplex)
    out = ""

    def _gen_write_element_body(root: str) -> str:
        assert isinstance(e.type, UxsdComplex)
        ouv = ""
        if e.type.attrs:
            for a in e.type.attrs:
                ouv += _gen_write_attr(a, e.type.name, root, "child_context")
            if e.type.content:
                ouv += "write_{name}_capnp_type(in, {root}, child_context);\n".format(
                    root=root, name=e.type.name)
        else:
            if e.type.content:
                ouv += "write_{name}_capnp_type(in, {root}, child_context);\n".format(
                    root=root, name=e.type.name)

        return ouv

    name = cpp._gen_stub_suffix(e, parent)
    if e.many:
        plural_name = utils.pluralize(cpp._gen_stub_suffix(e, parent))
        out += "size_t num_{pname} = in.num_{name}(context);\n".format(
            name=name, pname=plural_name)
        out += "auto {name} = root.init{pname}(num_{name});\n".format(
            name=plural_name,
            pname=utils.pluralize(utils.to_pascalcase(e.name)))
        out += "for(size_t i = 0; i < num_{name}; i++) {{\n".format(
            name=plural_name)
        out += "\tauto {name} = {plural_name}[i];\n".format(
            name=name,
            plural_name=plural_name,
        )
        out += "\tauto child_context = in.get_%s(i, context);\n" % cpp._gen_stub_suffix(
            e, parent)
        out += utils.indent(_gen_write_element_body(name))
        out += "}\n"
    elif e.optional:
        out += "if(in.has_%s(context)){\n" % cpp._gen_stub_suffix(e, parent)
        out += "\tauto {name} = root.init{pname}();\n".format(
            name=name, pname=utils.to_pascalcase(e.name))
        out += "\tauto child_context = in.get_%s(context);\n" % cpp._gen_stub_suffix(
            e, parent)
        out += utils.indent(_gen_write_element_body(name))
        out += "}\n"
    else:
        out += "{\n"
        out += "\tauto child_context = in.get_%s(context);\n" % cpp._gen_stub_suffix(
            e, parent)
        out += "\tauto {name} = root.init{pname}();\n".format(
            name=name, pname=utils.to_pascalcase(e.name))
        out += utils.indent(_gen_write_element_body(name))
        out += "}\n"

    return out
Exemplo n.º 3
0
    def _add_add_complex(e: UxsdElement):
        assert isinstance(e.type, UxsdComplex)
        impl = ""
        impl += "auto {name} = capnp::Orphanage::getForMessageContaining(builder).newOrphan<ucap::{pname}>();\n".format(
            name=cpp.checked(e.name), pname=utils.to_pascalcase(e.type.name))
        impl += "{pname}_.emplace_back(std::move({name}));\n".format(
            name=cpp.checked(e.name), pname=utils.pluralize(e.type.name))
        impl += "auto child_builder = {pname}_.back().get();\n".format(
            name=e.type.name, pname=utils.pluralize(e.type.name))
        impl += _gen_set_required_attrs(e)
        impl += "return child_builder;\n"
        _add_field(
            _gen_builder(e.type), "add", e.name,
            cpp._gen_required_attribute_arg_list(_gen_builder(t),
                                                 e.type.attrs,
                                                 context="builder"), impl)

        impl = ""
        impl = "{pname}_.reserve(size);\n".format(
            pname=utils.pluralize(e.type.name))
        _add_field("void", "preallocate", e.name,
                   _gen_builder(t) + "&, size_t size", impl)

        _add_field("void", "finish", e.name,
                   _gen_builder(e.type) + " &builder", _gen_finish(e))
Exemplo n.º 4
0
 def _add_get_complex_many(e: UxsdElement):
     impl = ""
     impl += "return reader.get{pname}()[n];\n".format(
         name=e.type.name,
         pname=utils.to_pascalcase(utils.pluralize(e.name)))
     _add_field(_gen_reader(e.type), "get", e.name,
                "int n, {} &reader".format(_gen_reader(t)), impl)
Exemplo n.º 5
0
    def _add_get_simple(e: Union[UxsdElement, UxsdAttribute]):
        impl = ""
        impl += "return {value};\n".format(value=_gen_load_simple(
            e.type, "reader.get{pname}()".format(
                pname=utils.to_pascalcase(e.name))))

        _add_field(e.type.cpp, "get", e.name,
                   _gen_reader(t) + " &reader", impl)
Exemplo n.º 6
0
 def _gen_set_required_attrs(e: UxsdElement):
     impl = ""
     for attr in sorted(e.type.attrs, key=lambda attr: attr.name):
         if cpp.pass_at_init(attr):
             impl += 'child_builder.set{pname}({value});\n'.format(
                 pname=utils.to_pascalcase(attr.name),
                 value=_gen_set_simple(attr.type, attr.name))
     return impl
Exemplo n.º 7
0
 def _add_set(e: Union[UxsdElement, UxsdAttribute]):
     impl = ""
     impl += "builder.set{pname}({value});\n".format(
         pname=utils.to_pascalcase(e.name),
         value=_gen_set_simple(e.type, e.name))
     _add_field(
         "void", "set",
         e.name, "{}, {} &builder".format(cpp._gen_attribute_arg(e),
                                          _gen_builder(t)), impl)
Exemplo n.º 8
0
def _gen_write_attr(a: UxsdAttribute,
                    parent: str,
                    root: str = "root",
                    context: str = "context") -> str:
    """Function to generate partial code which writes out a single XML attribute."""
    out = ""
    if not a.optional or a.default_value:
        # root.set{pname}(in.get_{}(context);
        out += "{root}.set{pname}({value});\n".format(
            root=root,
            pname=utils.to_pascalcase(a.name),
            value=_gen_write_simple(a, parent, context))
    else:
        out += "if((bool)%s)\n" % _gen_check_simple(a, parent, context)
        out += "\t{root}.set{pname}({value});\n".format(
            root=root,
            pname=utils.to_pascalcase(a.name),
            value=_gen_write_simple(a, parent, context))

    return out
Exemplo n.º 9
0
    def _gen_finish(e: UxsdElement):
        any_many = False
        if not isinstance(e.type, UxsdComplex):
            return ""

        if isinstance(e.type.content, (UxsdDfa, UxsdAll)):
            for el in e.type.content.children:
                if el.many:
                    any_many = True
                    break

        if not any_many:
            return ""

        impl = ""
        for el in e.type.content.children:
            if el.many:
                impl += "auto {cname} = builder.init{pname}({name}_.size());\n".format(
                    cname=cpp.checked(el.name),
                    name=utils.pluralize(el.type.name),
                    pname=utils.to_pascalcase(utils.pluralize(el.name)))
                impl += "for(size_t i = 0; i < {name}_.size(); ++i) {{\n".format(
                    name=utils.pluralize(el.type.name))
                impl += "\t{cname}.adoptWithCaveats(i, std::move({name}_[i]));\n".format(
                    cname=cpp.checked(el.name),
                    name=utils.pluralize(el.type.name))
                impl += "}\n"
                impl += "{name}_.clear();\n".format(
                    name=utils.pluralize(el.type.name))
        return impl

        any_many = False
        for e2 in e.content.children:
            if isinstance(e2.type, UxsdComplex):
                if e2.many:
                    any_many = True
                    break
            elif isinstance(e2.type, UxsdSimple):
                if e2.many:
                    any_many = True
                    break
            else:
                raise TypeError(e2)

        if not any_many:
            return ""

        impl = ""

        return impl
Exemplo n.º 10
0
def _gen_required_attribute_arg_list(t: UxsdComplex, input: str) -> str:
    required_attrs = []

    for attr in sorted(t.type.attrs, key=lambda attr: attr.name):
        if cpp.pass_at_init(attr):
            required_attrs.append(
                _gen_load_simple(attr.type,
                                 input='{input}.get{pname}()'.format(
                                     input=input,
                                     pname=utils.to_pascalcase(attr.name))))

    if len(required_attrs) == 0:
        return ""
    else:
        return ', ' + ', '.join(required_attrs)
Exemplo n.º 11
0
    def _add_init(e: UxsdElement):
        assert isinstance(e.type, UxsdComplex)
        impl = ""
        impl += "auto child_builder = builder.init{pname}();\n".format(
            pname=utils.to_pascalcase(e.name))
        impl += _gen_set_required_attrs(e)
        impl += "return child_builder;\n"
        _add_field(
            _gen_builder(e.type), "init", e.name,
            cpp._gen_required_attribute_arg_list(_gen_builder(t),
                                                 e.type.attrs,
                                                 context="builder"), impl)

        _add_field("void", "finish", e.name,
                   _gen_builder(e.type) + " &builder", _gen_finish(e))
Exemplo n.º 12
0
def write_fn_from_complex_type(t: UxsdComplex) -> str:
    assert isinstance(t.content, (UxsdDfa, UxsdAll, UxsdLeaf))
    out = ""
    out += "template<class T, typename Context>\n"
    out += "inline void write_{name}_capnp_type(T &in, ucap::{cname}::Builder &root, Context &context) {{\n".format(
        name=t.name, cname=utils.to_pascalcase(t.name))
    out += "\t(void)in;\n"
    out += "\t(void)root;\n"
    if isinstance(t.content, (UxsdDfa, UxsdAll)):
        for e in t.content.children:
            out += utils.indent(_gen_write_element(e, t.name))
    elif isinstance(t.content, UxsdLeaf):
        out += "\troot.setValue(in.get_%s_value(context));\n" % t.name
    else:
        out += "\treturn;\n"

    out += "}\n"
    return out
Exemplo n.º 13
0
def write_fn_from_root_element(e: UxsdElement) -> str:
    assert isinstance(e.type, UxsdComplex)
    out = ""
    out += "template <class T, typename Context>\n"
    out += "inline void write_{name}_capnp(T &in, Context &context, ucap::{cname}::Builder &root) {{\n".format(
        name=e.name, cname=utils.to_pascalcase(e.name))

    out += "\tin.start_write();\n"

    if e.type.attrs:
        for a in e.type.attrs:
            out += utils.indent(_gen_write_attr(a, e.name))
    out += "\twrite_{name}_capnp_type(in, root, context);\n".format(
        name=e.name)

    out += "\tin.finish_write();\n"

    out += "}\n"
    return out
Exemplo n.º 14
0
def _gen_conv_enum(t: UxsdEnum) -> str:
    pname = utils.to_pascalcase(t.name)
    out = ""
    out += "inline enum_{name} conv_enum_{name}(ucap::{pname} e, const std::function<void(const char *)> * report_error) {{\n".format(
        name=t.name, pname=pname)
    out += "\tswitch(e) {\n"
    out += "\tcase ucap::{pname}::{e}:\n".format(pname=pname, e='UXSD_INVALID')
    out += "\t\treturn enum_{name}::{e};\n".format(name=t.name,
                                                   e='UXSD_INVALID')
    for e in t.enumeration:
        out += "\tcase ucap::{pname}::{e}:\n".format(pname=pname, e=e.upper())
        out += "\t\treturn enum_{name}::{e};\n".format(name=t.name,
                                                       e=e.upper())
    out += "\tdefault:\n"
    out += '\t\t(*report_error)("Unknown enum_{name}");\n'.format(name=t.name)
    out += "\t\tthrow std::runtime_error(\"Unreachable!\");\n"
    out += "\t}\n"
    out += "}\n"
    out += "\n"
    out += "inline ucap::{pname} conv_to_enum_{name}(enum_{name} e) {{\n".format(
        name=t.name, pname=pname)
    out += "\tswitch(e) {\n"
    out += "\tcase enum_{name}::{e}:\n".format(name=t.name, e='UXSD_INVALID')
    out += "\t\treturn ucap::{pname}::{e};\n".format(pname=pname,
                                                     e='UXSD_INVALID')
    for e in t.enumeration:
        out += "\tcase enum_{name}::{e}:\n".format(name=t.name, e=e.upper())
        out += "\t\treturn ucap::{pname}::{e};\n".format(pname=pname,
                                                         e=e.upper())
    out += "\tdefault:\n"
    out += '\t\tthrow std::runtime_error("Unknown enum_{name}");\n'.format(
        name=t.name)
    out += "\t}\n"
    out += "}\n"

    return out
Exemplo n.º 15
0
def render_impl_header_file(schema: UxsdSchema, cmdline: str,
                            capnp_file_name: str, interface_file_name: str,
                            input_file: str) -> str:
    out = ""
    x = {
        "version": __version__,
        "cmdline": cmdline,
        "input_file": input_file,
        "md5": utils.md5(input_file)
    }
    out += cpp_templates.header_comment.substitute(x)
    out += '#include <stdexcept>\n'
    out += '#include <vector>\n'
    out += '#include "capnp/serialize.h"\n'
    out += '#include "{}.h"\n'.format(capnp_file_name)
    out += '#include "{}"\n'.format(interface_file_name)
    out += "\n/* All uxsdcxx functions and structs live in this namespace. */\n"
    out += "namespace uxsd {\n"

    if schema.enums:
        enum_converters = [_gen_conv_enum(t) for t in schema.enums]
        out += "\n\n/* Enum conversions from uxsd to ucap */\n"
        out += "\n".join(enum_converters)

    pname = utils.to_pascalcase(schema.root_element.name)
    out += "struct Capnp{pname}ContextTypes : public Default{pname}ContextTypes {{\n\t".format(
        pname=pname)
    out += "\n\t".join(
        "using {pname}ReadContext = ucap::{pname}::Reader;".format(
            pname=utils.to_pascalcase(t.name)) for t in schema.complex_types)
    out += "\n\t"
    out += "\n\t".join(
        "using {pname}WriteContext = ucap::{pname}::Builder;".format(
            pname=utils.to_pascalcase(t.name)) for t in schema.complex_types)
    out += "\n};\n"
    out += "\n"

    out += "class Capnp{pname} : public {pname}Base<Capnp{pname}ContextTypes> {{\n\t".format(
        pname=pname)
    out += "public:\n"
    out += "\tCapnp{pname}() {{}}\n\n".format(pname=pname)

    out += "\tvoid start_load(const std::function<void(const char *)> *report_error_in) override {\n"
    out += "\t\treport_error = report_error_in;\n"
    out += "\t}\n"
    out += "\tvoid finish_load() override {}\n"
    out += "\tvoid start_write() override {}\n"
    out += "\tvoid finish_write() override {}\n"
    out += "\tvoid error_encountered(const char * file, int line, const char *message) override {\n"
    out += "\t\tstd::stringstream msg;"
    out += "\t\tmsg << message << \" occured at file: \" << file << \" line: \" << line;\n"
    out += "\t\tthrow std::runtime_error(msg.str());\n"
    out += "\t}\n"

    for t in schema.complex_types:
        out += utils.indent(
            _gen_capnp_impl(t, t.name == schema.root_element.name))
    out += "private:\n"
    out += "\tconst std::function<void(const char *)> *report_error;\n"

    for t in schema.complex_types:
        if isinstance(t.content, (UxsdDfa, UxsdAll)):
            for el in t.content.children:
                if el.many:
                    out += "\tstd::vector<capnp::Orphan<ucap::{pname}>> {name}_;\n".format(
                        pname=utils.to_pascalcase(el.type.name),
                        name=utils.pluralize(el.type.name))
    out += "};\n"

    out += "\n\n} /* namespace uxsd */\n"
    return out
Exemplo n.º 16
0
def to_type(t: UxsdType) -> str:
    """For determining type in fields only."""
    if isinstance(t, UxsdAtomic):
        return tpl.atomic_builtins[t.name]
    else:
        return utils.to_pascalcase(t.name)
Exemplo n.º 17
0
 def _add_num(e: UxsdElement):
     impl = ""
     impl += "return reader.get{pname}().size();\n".format(
         pname=utils.to_pascalcase(utils.pluralize(e.name)))
     _add_field("size_t", "num", e.name, _gen_reader(t) + " &reader", impl)
Exemplo n.º 18
0
 def _add_get_complex(e: UxsdElement):
     impl = ""
     impl += "return reader.get{pname}();\n".format(
         name=e.type.name, pname=utils.to_pascalcase(e.name))
     _add_field(_gen_reader(e.type), "get", e.name,
                _gen_reader(t) + " &reader", impl)
Exemplo n.º 19
0
def render_header_file(schema: UxsdSchema, cmdline: str, capnp_file_name: str,
                       interface_file_name: str, input_file: str) -> str:
    """Render a C++ header file to a string."""
    out = ""
    x = {
        "version": __version__,
        "cmdline": cmdline,
        "input_file": input_file,
        "md5": utils.md5(input_file)
    }
    out += cpp_templates.header_comment.substitute(x)
    out += '#include <stdexcept>\n'
    out += '#include <tuple>\n'
    out += '#include <vector>\n'
    out += '#include <sstream>\n'
    out += '#include <limits>\n'
    out += '#include "capnp/serialize.h"\n'
    out += '#include "{}.h"\n'.format(capnp_file_name)
    out += '#include "{}"\n'.format(interface_file_name)
    out += "\n/* All uxsdcxx functions and structs live in this namespace. */\n"
    out += "namespace uxsd {"

    out += "\n/* Declarations for internal load functions for the complex types. */\n"
    load_fn_decls = []
    for t in schema.complex_types:
        load_fn_decls.append("template <class T, typename Context>")
        load_fn_decls.append(
            "void load_{name}_capnp_type(const ucap::{cname}::Reader &root, T &out, Context &context, const std::function<void(const char*)> * report_error, std::vector<std::pair<const char *, size_t>> * stack);"
            .format(name=t.name, cname=utils.to_pascalcase(t.name)))
    out += "\n".join(load_fn_decls)

    out += "\n\n/* Declarations for internal write functions for the complex types. */\n"
    write_fn_decls = []
    for t in schema.complex_types:
        if t.content is None:
            continue
        write_fn_decls.append("template <class T, typename Context>")
        write_fn_decls.append(
            "inline void write_{name}_capnp_type(T &in, ucap::{cname}::Builder &root, Context &context);"
            .format(name=t.name, cname=utils.to_pascalcase(t.name)))
    out += "\n".join(write_fn_decls)

    if schema.enums:
        enum_converters = [_gen_conv_enum(t) for t in schema.enums]
        out += "\n\n/* Enum conversions from uxsd to ucap */\n"
        out += "\n".join(enum_converters)

    out += "\n\n/* Load function for the root element. */\n"
    out += load_fn_from_element(schema.root_element)
    out += "\n/* Write function for the root element. */\n"
    out += write_fn_from_root_element(schema.root_element)

    complex_type_loaders = [
        load_fn_from_complex_type(t) for t in schema.complex_types
    ]

    out += "\n\n/* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */\n"
    out += "\n".join(complex_type_loaders)

    complex_type_writers = [
        write_fn_from_complex_type(t) for t in schema.complex_types
        if t.content is not None
    ]
    out += "\n\n/* Internal writing functions, which uxsdcxx uses to write out a class. */\n"
    out += "\n".join(complex_type_writers)

    out += "\n\n} /* namespace uxsd */\n"
    return out
Exemplo n.º 20
0
def _gen_builder(e: UxsdComplex):
    return 'ucap::{}::Builder'.format(utils.to_pascalcase(e.name))
Exemplo n.º 21
0
def load_fn_from_complex_type(t: UxsdComplex) -> str:
    """Generate a full C++ function load_foo(&root, &out)
	which can load an XSD complex type from DOM &root into C++ object out.
	"""
    out = ""
    out += "template<class T, typename Context>\n"
    out += "inline void load_{name}_capnp_type(const ucap::{cname}::Reader &root, T &out, Context &context, const std::function<void(const char*)> * report_error, std::vector<std::pair<const char *, size_t>> * stack){{\n".format(
        name=t.name, cname=utils.to_pascalcase(t.name))

    out += "\t(void)root;\n"
    out += "\t(void)out;\n"
    out += "\t(void)context;\n"
    out += "\t(void)report_error;\n"
    out += "\t(void)stack;\n"
    out += "\n"
    for attr in t.attrs:
        if cpp.pass_at_init(attr):
            continue

        out += "\tout.set_{suffix}({data}, context);\n".format(
            suffix=cpp._gen_stub_suffix(attr, t.name),
            data=_gen_load_simple(
                attr.type, 'root.get{pname}()'.format(
                    pname=utils.to_pascalcase(attr.name))))

    if isinstance(t.content, (UxsdDfa, UxsdAll)):
        for el in t.content.children:
            name = utils.to_pascalcase(el.name)
            out += "\tstack->push_back(std::make_pair(\"get{}\", 0));\n".format(
                name)
            if el.many:
                out += "\t{\n"
                suffix = cpp._gen_stub_suffix(el, t.name)
                out += "\t\tauto data = root.get{pname}();\n".format(
                    pname=utils.pluralize(name))
                out += "\t\tout.preallocate_{suffix}(context, data.size());\n".format(
                    suffix=suffix)

                out += "\t\tfor(const auto & el : data) {\n"
                if isinstance(el.type, UxsdComplex):
                    out += "\t\t\tauto child_context = out.add_{suffix}(context{required_attrs});\n".format(
                        suffix=suffix,
                        required_attrs=_gen_required_attribute_arg_list(
                            el, 'el'))
                    out += "\t\t\tload_{suffix}_capnp_type(el, out, child_context, report_error, stack);\n".format(
                        suffix=el.type.name)
                    out += "\t\t\tout.finish_{suffix}(child_context);\n".format(
                        suffix=suffix)
                else:
                    out += "\t\t\tout.add_{suffix}({data}, context);\n".format(
                        suffix=suffix,
                        data=_gen_load_simple(el, 'el.get{}()'.format(name)))
                out += "\t\t\tstack->back().second += 1;\n"
                out += "\t\t}\n"
                out += "\t}\n"
            else:
                out += "\tif (root.has{pname}()) {{\n".format(pname=name)
                if isinstance(el.type, UxsdComplex):
                    out += "\t\tauto child_el = root.get{pname}();\n".format(
                        pname=name)
                    access = 'child_el'
                    out += "\t\tauto child_context = out.init_{suffix}(context{required_attrs});\n".format(
                        suffix=cpp._gen_stub_suffix(el, t.name),
                        required_attrs=_gen_required_attribute_arg_list(
                            el, access))
                    out += "\t\tload_{suffix}_capnp_type({access}, out, child_context, report_error, stack);\n".format(
                        access=access, suffix=el.type.name, pname=name)
                    out += "\t\tout.finish_{suffix}(child_context);\n".format(
                        suffix=cpp._gen_stub_suffix(el, t.name))
                else:
                    out += "\t\tout.init_{suffix}({data}, context);\n".format(
                        suffix=cpp._gen_stub_suffix(el, t.name),
                        data=_gen_load_simple(el,
                                              'root.get{name}()'.format(name)))
                out += "\t}\n"

            out += "\tstack->pop_back();\n"
    elif isinstance(t.content, UxsdLeaf):
        out += "\tstack->push_back(std::make_pair(\"getValue\", 0));\n"
        out += "\tout.set_{name}_value(root.getValue().cStr(), context);\n".format(
            name=t.name)
        out += "\tstack->pop_back();\n"

    out += "}\n"
    return out