Example #1
0
int emit_cpp(lcmgen_t *lcmgen)
{
    // iterate through all defined message types
    for (unsigned int i = 0; i < g_ptr_array_size(lcmgen->structs); i++) {
        lcm_struct_t *lr = (lcm_struct_t *) g_ptr_array_index(lcmgen->structs, i);

        const char *tn = lr->structname->lctypename;
        char *tn_ = dots_to_slashes(tn);

        // compute the target filename
        char *header_name = g_strdup_printf("%s%s%s.hpp",
                                            getopt_get_string(lcmgen->gopt, "cpp-hpath"),
                                            strlen(getopt_get_string(lcmgen->gopt, "cpp-hpath")) > 0 ? G_DIR_SEPARATOR_S : "",
                                            tn_);

        // generate code if needed
        if (lcm_needs_generation(lcmgen, lr->lcmfile, header_name)) {
            make_dirs_for_file(header_name);

            FILE *f = fopen(header_name, "w");
            if (f == NULL)
                return -1;

            emit_header_start(lcmgen, f, lr);
            emit_encode(lcmgen, f, lr);
            emit_decode(lcmgen, f, lr);
            emit_encoded_size(lcmgen, f, lr);
            emit_get_hash(lcmgen, f, lr);
            emit(0, "const char* %s::getTypeName()", lr->structname->shortname);
            emit(0, "{");
            emit(1,     "return \"%s\";", lr->structname->shortname);
            emit(0, "}");
            emit(0, "");

            emit_encode_nohash(lcmgen, f, lr);
            emit_decode_nohash(lcmgen, f, lr);
            emit_encoded_size_nohash(lcmgen, f, lr);
            emit_compute_hash(lcmgen, f, lr);

            emit_compare(lcmgen, f, lr);
            emit(0, "/// Testing (ignores dynamic arrays & affects only first and last elements of static arrays)");
            emit(0, "/// {");
            emit_print(lcmgen, f, lr);
            emit_init_test(lcmgen, f, lr);
            emit_inc_test(lcmgen, f, lr);
            emit_compare_test(lcmgen, f, lr);
            emit(0, "/// }");

            emit_package_namespace_close(lcmgen, f, lr);
            emit(0, "#endif");

            fclose(f);
        }
        g_free(header_name);
        free(tn_);
    }

    return 0;
}
Example #2
0
File: emit_m.c Project: cd127/lcm-1
static char * get_file_name(lcmgen_t * lcmgen, lcm_struct_t const * lr, char const * func)
{
	char const * tn = lr->structname->lctypename;
	char * tn_ = dots_to_slashes(tn);

    // compute the target filename
	char * file_name = g_strdup_printf("%s%s%s%s.m",
            getopt_get_string(lcmgen->gopt, "mpath"),
            strlen(getopt_get_string(lcmgen->gopt, "mpath")) > 0 ? G_DIR_SEPARATOR_S : "",
            tn_,
			func);
	free(tn_);
	return file_name;
}
Example #3
0
int emit_java(zcmgen_t *zcm)
{
    GHashTable *type_table = g_hash_table_new(g_str_hash, g_str_equal);

    g_hash_table_insert(type_table, "byte",   prim("byte",
                                             "# = ins.readByte();",
                                             "outs.writeByte(#);"));
    g_hash_table_insert(type_table, "int8_t",   prim("byte",
                                               "# = ins.readByte();",
                                               "outs.writeByte(#);"));
    g_hash_table_insert(type_table, "int16_t",  prim("short",
                                               "# = ins.readShort();",
                                               "outs.writeShort(#);"));
    g_hash_table_insert(type_table, "int32_t",  prim("int",
                                               "# = ins.readInt();",
                                               "outs.writeInt(#);"));
    g_hash_table_insert(type_table, "int64_t",  prim("long",
                                               "# = ins.readLong();",
                                               "outs.writeLong(#);"));

    g_hash_table_insert(type_table, "string",   prim("String",
                                                     "__strbuf = new char[ins.readInt()-1]; for (int _i = 0; _i < __strbuf.length; _i++) __strbuf[_i] = (char) (ins.readByte()&0xff); ins.readByte(); # = new String(__strbuf);",
                                                     "__strbuf = new char[#.length()]; #.getChars(0, #.length(), __strbuf, 0); outs.writeInt(__strbuf.length+1); for (int _i = 0; _i < __strbuf.length; _i++) outs.write(__strbuf[_i]); outs.writeByte(0);"));

//    g_hash_table_insert(type_table, "string",   prim("String",
//                                               "__strbuf = new byte[ins.readInt()-1]; ins.readFully(__strbuf); ins.readByte(); # = new String(__strbuf, \"UTF-8\");",
//                                               "__strbuf = #.getBytes(\"UTF-8\"); outs.writeInt(__strbuf.length+1); outs.write(__strbuf, 0, __strbuf.length); outs.writeByte(0);"));

    g_hash_table_insert(type_table, "boolean",  prim("boolean",
                                               "# = ins.readByte()!=0;",
                                               "outs.writeByte( # ? 1 : 0);"));
    g_hash_table_insert(type_table, "float",    prim("float",
                                               "# = ins.readFloat();",
                                               "outs.writeFloat(#);"));
    g_hash_table_insert(type_table, "double",   prim("double",
                                               "# = ins.readDouble();",
                                               "outs.writeDouble(#);"));

    //////////////////////////////////////////////////////////////
    // ENUMS
    for (unsigned int en = 0; en < g_ptr_array_size(zcm->enums); en++) {
        zcm_enum_t *le = (zcm_enum_t *) g_ptr_array_index(zcm->enums, en);

        const char *classname = make_fqn(zcm, le->enumname->lctypename);
        char *path = g_strdup_printf("%s%s%s.java",
                                  getopt_get_string(zcm->gopt, "jpath"),
                                  strlen(getopt_get_string(zcm->gopt, "jpath")) > 0 ? G_DIR_SEPARATOR_S : "",
                                  dots_to_slashes(classname));

        if (!zcm_needs_generation(zcm, le->zcmfile, path))
            continue;

        if (getopt_get_bool(zcm->gopt, "jmkdir"))
            make_dirs_for_file(path);

        FILE *f = fopen(path, "w");
        if (f==NULL)
            return -1;

        if (strlen(le->enumname->package) > 0)
            emit(0, "package %s;", le->enumname->package);
        else
            emit(0, "package %s;", getopt_get_string(zcm->gopt, "jdefaultpkg"));

        emit(0, " ");
        emit(0, "import java.io.*;");
        emit(0, "import java.util.*;");
        emit(0, " ");

        emit(0, "public final class %s %s", le->enumname->shortname, getopt_get_string(zcm->gopt, "jdecl"));

        emit(0, "{");
        emit(1, "public int value;");
        emit(0, " ");

        for (unsigned int v = 0; v < g_ptr_array_size(le->values); v++) {
            zcm_enum_value_t *lev = (zcm_enum_value_t *) g_ptr_array_index(le->values, v);
            emit(1, "public static final int %-16s = %i;",
                    lev->valuename, lev->value);
        }
        emit(0," ");

        emit(1,"public %s(int value) { this.value = value; }",
                le->enumname->shortname);
        emit(0," ");

        emit(1,"public int getValue() { return value; }");
        emit(0," ");

        emit(1,"public void _encodeRecursive(DataOutput outs) throws IOException");
        emit(1,"{");
        emit(2,"outs.writeInt(this.value);");
        emit(1,"}");
        emit(0," ");

        emit(1,"public void encode(DataOutput outs) throws IOException");
        emit(1,"{");
        emit(2,"outs.writeLong(ZCM_FINGERPRINT);");
        emit(2,"_encodeRecursive(outs);");
        emit(1,"}");
        emit(0," ");

        emit(1,"public static %s _decodeRecursiveFactory(DataInput ins) throws IOException", make_fqn(zcm, le->enumname->lctypename));
        emit(1,"{");
        emit(2,"%s o = new %s(0);", make_fqn(zcm, le->enumname->lctypename), make_fqn(zcm, le->enumname->lctypename));
        emit(2,"o._decodeRecursive(ins);");
        emit(2,"return o;");
        emit(1,"}");
        emit(0," ");

        emit(1,"public void _decodeRecursive(DataInput ins) throws IOException");
        emit(1,"{");
        emit(2,"this.value = ins.readInt();");
        emit(1,"}");
        emit(0," ");

        emit(1,"public %s(DataInput ins) throws IOException", le->enumname->shortname);
        emit(1,"{");
        emit(2,"long hash = ins.readLong();");
        emit(2,"if (hash != ZCM_FINGERPRINT)");
        emit(3,     "throw new IOException(\"ZCM Decode error: bad fingerprint\");");
        emit(2,"_decodeRecursive(ins);");
        emit(1,"}");
        emit(0," ");

        emit(1,"public %s copy()", classname);
        emit(1,"{");
        emit(2,"return new %s(this.value);", classname);
        emit(1,"}");
        emit(0," ");

        emit(1,"public static final long _hashRecursive(ArrayList<Class<?>> clss)");
        emit(1,"{");
        emit(2,"return ZCM_FINGERPRINT;");
        emit(1,"}");
        emit(0," ");
        emit(1, "public static final long ZCM_FINGERPRINT = 0x%016"PRIx64"L;", le->hash);
        emit(0, "}");
        fclose(f);
    }

    for (unsigned int st = 0; st < g_ptr_array_size(zcm->structs); st++) {
        zcm_struct_t *lr = (zcm_struct_t *) g_ptr_array_index(zcm->structs, st);

        const char *classname = make_fqn(zcm, lr->structname->lctypename);
        char *path = g_strdup_printf("%s%s%s.java",
                                  getopt_get_string(zcm->gopt, "jpath"),
                                  strlen(getopt_get_string(zcm->gopt, "jpath")) > 0 ? G_DIR_SEPARATOR_S : "",
                                  dots_to_slashes(classname));

        if (!zcm_needs_generation(zcm, lr->zcmfile, path))
            continue;

        if (getopt_get_bool(zcm->gopt, "jmkdir"))
            make_dirs_for_file(path);

        FILE *f = fopen(path, "w");
        if (f==NULL)
            return -1;

        emit(0, "/* ZCM type definition class file\n"
                " * This file was automatically generated by zcm-gen\n"
                " * DO NOT MODIFY BY HAND!!!!\n"
                " */\n");

        if (strlen(lr->structname->package) > 0)
            emit(0, "package %s;", lr->structname->package);
        else
            emit(0, "package %s;", getopt_get_string(zcm->gopt, "jdefaultpkg"));

        emit(0, " ");
        emit(0, "import java.io.*;");

        if (0) {
            // Determine if we even need the java.nio.* package.
            int usenio = 0;
            for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
                zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
                primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);
                if (pinfo!=NULL && !strcmp(pinfo->storage, "float")) {
                    usenio = 1;
                    break;
                }
            }
            if (usenio)
                emit(0, "import java.nio.*;");
        }

        emit(0, "import java.util.*;");
        emit(0, "import zcm.zcm.*;");
        emit(0, " ");
        emit(0, "public final class %s %s", lr->structname->shortname, getopt_get_string(zcm->gopt, "jdecl"));
        emit(0, "{");

        for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
            zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
            primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);

            emit_start(1, "public ");

            if (pinfo==NULL)  {
                emit_continue("%s", make_fqn(zcm, lm->type->lctypename));
            } else {
                emit_continue("%s", pinfo->storage);
            }

            emit_continue(" %s", lm->membername);
            for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions); i++)
                emit_continue("[]");
            emit_end(";");
        }
        emit(0," ");

        // public constructor
        emit(1,"public %s()", lr->structname->shortname);
        emit(1,"{");

        // pre-allocate any fixed-size arrays.
        for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
            zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
            primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);

            if (g_ptr_array_size(lm->dimensions)==0 || !zcm_is_constant_size_array(lm))
                continue;

            emit_start(2, "%s = new ", lm->membername);
            if (pinfo != NULL)
                emit_continue("%s", pinfo->storage);
            else
                emit_continue("%s", make_fqn(zcm, lm->type->lctypename));

            for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions); i++) {
                zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, i);
                emit_continue("[%s]", dim->size);
            }
            emit_end(";");
        }
        emit(1,"}");
        emit(0," ");

        emit(1, "public static final long ZCM_FINGERPRINT;");
        emit(1, "public static final long ZCM_FINGERPRINT_BASE = 0x%016"PRIx64"L;", lr->hash);
        emit(0," ");

        //////////////////////////////////////////////////////////////
        // CONSTANTS
        for (unsigned int cn = 0; cn < g_ptr_array_size(lr->constants); cn++) {
            zcm_constant_t *lc = (zcm_constant_t *) g_ptr_array_index(lr->constants, cn);
            assert(zcm_is_legal_const_type(lc->lctypename));

            if (!strcmp(lc->lctypename, "int8_t")) {
                emit(1, "public static final byte %s = (byte) %s;", lc->membername, lc->val_str);
            } else if (!strcmp(lc->lctypename, "int16_t")) {
                emit(1, "public static final short %s = (short) %s;", lc->membername, lc->val_str);
            } else if (!strcmp(lc->lctypename, "int32_t")) {
                emit(1, "public static final int %s = %s;", lc->membername, lc->val_str);
            } else if (!strcmp(lc->lctypename, "int64_t")) {
                emit(1, "public static final long %s = %sL;", lc->membername, lc->val_str);
            } else if (!strcmp(lc->lctypename, "float")) {
                emit(1, "public static final float %s = %sf;", lc->membername, lc->val_str);
            } else if (!strcmp(lc->lctypename, "double")) {
                emit(1, "public static final double %s = %s;", lc->membername, lc->val_str);
            } else {
                assert(0);
            }
        }
        if (g_ptr_array_size(lr->constants) > 0)
            emit(0, "");

        ///////////////// compute fingerprint //////////////////
        emit(1, "static {");
        emit(2, "ZCM_FINGERPRINT = _hashRecursive(new ArrayList<Class<?>>());");
        emit(1, "}");
        emit(0, " ");

        emit(1, "public static long _hashRecursive(ArrayList<Class<?>> classes)");
        emit(1, "{");
        emit(2, "if (classes.contains(%s.class))", make_fqn(zcm, lr->structname->lctypename));
        emit(3,     "return 0L;");
        emit(0, " ");
        emit(2, "classes.add(%s.class);", make_fqn(zcm, lr->structname->lctypename));

        emit(2, "long hash = ZCM_FINGERPRINT_BASE");
        for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
            zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
            primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);

            if (pinfo)
                continue;

            emit(3, " + %s._hashRecursive(classes)", make_fqn(zcm, lm->type->lctypename));
        }
        emit(3,";");

        emit(2, "classes.remove(classes.size() - 1);");
        emit(2, "return (hash<<1) + ((hash>>63)&1);");

        emit(1, "}");
        emit(0, " ");

        ///////////////// encode //////////////////

        emit(1,"public void encode(DataOutput outs) throws IOException");
        emit(1,"{");
        emit(2,"outs.writeLong(ZCM_FINGERPRINT);");
        emit(2,"_encodeRecursive(outs);");
        emit(1,"}");
        emit(0," ");

        emit(1,"public void _encodeRecursive(DataOutput outs) throws IOException");
        emit(1,"{");
        if(struct_has_string_member(lr))
            emit(2, "char[] __strbuf = null;");
        char accessor[1024];

        for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
            zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
            primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);
            make_accessor(lm, "this", accessor);

            encode_recursive(zcm, lm, f, pinfo, accessor, 0);
            emit(0," ");
        }
        emit(1,"}");
        emit(0," ");

        ///////////////// decode //////////////////

        // decoding constructors
        emit(1, "public %s(byte[] data) throws IOException", lr->structname->shortname);
        emit(1, "{");
        emit(2, "this(new ZCMDataInputStream(data));");
        emit(1, "}");
        emit(0, " ");

        emit(1,"public %s(DataInput ins) throws IOException", lr->structname->shortname);
        emit(1,"{");
        emit(2,"if (ins.readLong() != ZCM_FINGERPRINT)");
        emit(3,     "throw new IOException(\"ZCM Decode error: bad fingerprint\");");
        emit(0," ");
        emit(2,"_decodeRecursive(ins);");
        emit(1,"}");
        emit(0," ");

        emit(1,"public static %s _decodeRecursiveFactory(DataInput ins) throws IOException", make_fqn(zcm, lr->structname->lctypename));
        emit(1,"{");
        emit(2,"%s o = new %s();", make_fqn(zcm, lr->structname->lctypename), make_fqn(zcm, lr->structname->lctypename));
        emit(2,"o._decodeRecursive(ins);");
        emit(2,"return o;");
        emit(1,"}");
        emit(0," ");

        emit(1,"public void _decodeRecursive(DataInput ins) throws IOException");
        emit(1,"{");
        if(struct_has_string_member(lr))
            emit(2, "char[] __strbuf = null;");
        for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
            zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
            primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);

            make_accessor(lm, "this", accessor);

            // allocate an array if necessary
            if (g_ptr_array_size(lm->dimensions) > 0) {

                emit_start(2, "this.%s = new ", lm->membername);

                if (pinfo != NULL)
                    emit_continue("%s", pinfo->storage);
                else
                    emit_continue("%s", make_fqn(zcm, lm->type->lctypename));

                for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions); i++) {
                    zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, i);
                    emit_continue("[(int) %s]", dim->size);
                }
                emit_end(";");
            }

            decode_recursive(zcm, lm, f, pinfo, accessor, 0);
            emit(0," ");
        }

        emit(1,"}");
        emit(0," ");


        ///////////////// copy //////////////////

        emit(1,"public %s copy()", classname);
        emit(1,"{");
        emit(2,"%s outobj = new %s();", classname, classname);

        for (unsigned int member = 0; member < g_ptr_array_size(lr->members); member++) {
            zcm_member_t *lm = (zcm_member_t *) g_ptr_array_index(lr->members, member);
            primitive_info_t *pinfo = (primitive_info_t*) g_hash_table_lookup(type_table, lm->type->lctypename);
            make_accessor(lm, "", accessor);

            // allocate an array if necessary
            if (g_ptr_array_size(lm->dimensions) > 0) {

                emit_start(2, "outobj.%s = new ", lm->membername);

                if (pinfo != NULL)
                    emit_continue("%s", pinfo->storage);
                else
                    emit_continue("%s", make_fqn(zcm, lm->type->lctypename));

                for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions); i++) {
                    zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, i);
                    emit_continue("[(int) %s]", dim->size);
                }
                emit_end(";");
            }

            copy_recursive(zcm, lm, f, pinfo, accessor, 0);
            emit(0," ");
        }

        emit(2,"return outobj;");
        emit(1,"}");
        emit(0," ");

        ////////
        emit(0, "}\n");
        fclose(f);
    }

/* XXX deallocate our storage. unfinished since memory leaks are non-critical for zcm-gen.

    hashtable_iterator_t *hit = hashtable_iterator_create(type_table);
    hashtable_entry_t *entry;
    while ((entry = hashtable_iterator_next(hit)) != NULL) {
        free((char*) entry->value);
    }
    hashtable_iterator_destroy(hit);

    hashtable_destroy(type_table);
*/
    return 0;
}
Example #4
0
/** Emit header file **/
static void emit_header_start(lcmgen_t *lcmgen, FILE *f, lcm_struct_t *ls)
{
    char *tn = ls->structname->lctypename;
    char *sn = ls->structname->shortname;
    char *tn_ = dots_to_underscores(tn);

    emit_auto_generated_warning(f);

    fprintf(f, "#include <lcm/lcm_coretypes.h>\n");
    fprintf(f, "\n");
    fprintf(f, "#ifndef __%s_hpp__\n", tn_);
    fprintf(f, "#define __%s_hpp__\n", tn_);
    fprintf(f, "\n");

    // do we need to #include <vector> ?
    int emit_include_vector = 0;
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *)g_ptr_array_index(ls->members, mind);
        if (g_ptr_array_size(lm->dimensions) != 0 &&
                !lcm_is_constant_size_array(lm) && !emit_include_vector) {
            emit(0, "#include <vector>");
            emit_include_vector = 1;
        }
    }

    emit(0, "#include <cmath>\t// For fabs to compare floats");
    emit(0, "#include <string>\t// For return type of toStr()");
    emit(0, "#include <sstream>\t// For stringstream in toStr()");

    // include header files for other LCM types
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

        if (!lcm_is_primitive_type(lm->type->lctypename) &&
                strcmp(lm->type->lctypename, ls->structname->lctypename)) {
            char *other_tn = dots_to_slashes (lm->type->lctypename);
            emit(0, "#include \"%s%s%s.hpp\"",
                 getopt_get_string(lcmgen->gopt, "cpp-include"),
                 strlen(getopt_get_string(lcmgen->gopt, "cpp-include"))>0 ? G_DIR_SEPARATOR_S : "",
                 other_tn);
            free(other_tn);
        }
    }

    fprintf(f, "\n");
    emit_package_namespace_start(lcmgen, f, ls);

    // define the class
    emit(0, "");
    emit_comment(f, 0, ls->comment);
    emit(0, "class %s", sn);
    emit(0, "{");

    // data members
    if(g_ptr_array_size(ls->members)) {
        emit(1, "public:");
        for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
            lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

            emit_comment(f, 2, lm->comment);
            char const* mapped_typename = map_type_name(lm->type->lctypename);
            int ndim = g_ptr_array_size(lm->dimensions);
            if (ndim == 0) {
                emit(2, "%-10s %s;", mapped_typename, lm->membername);
            } else {
                if (lcm_is_constant_size_array(lm)) {
                    emit_start(2, "%-10s %s", mapped_typename, lm->membername);
                    for (unsigned int d = 0; d < ndim; d++) {
                        lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, d);
                        emit_continue("[%s]", ld->size);
                    }
                    emit_end(";");
                } else {
                    emit_start(2, "");
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue("std::vector< ");
                    emit_continue("%s", mapped_typename);
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue(" >");
                    emit_end(" %s;", lm->membername);
                }
            }
            if (mind < g_ptr_array_size(ls->members) - 1) {
                emit(0, "");
            }
        }
        emit(0, "");
    }

    // constants
    if (g_ptr_array_size(ls->constants) > 0) {
        emit(1, "public:");
        for (unsigned int i = 0; i < g_ptr_array_size(ls->constants); i++) {
            lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, i);
            assert(lcm_is_legal_const_type(lc->lctypename));

            emit_comment(f, 2, lc->comment);
            // For int32_t only, we emit enums instead of static const
            // values because the former can be passed by reference while
            // the latter cannot.
            if (!strcmp(lc->lctypename, "int32_t")) {
                emit(2, "enum { %s = %s };", lc->membername, lc->val_str);
            } else {
                const char *suffix = "";
                if (!strcmp(lc->lctypename, "int64_t"))
                    suffix = "LL";
                char const* mapped_typename = map_type_name(lc->lctypename);
                char *cpp_std = getopt_get_string(lcmgen->gopt, "cpp-std");
                if(strcmp("c++98",cpp_std) && strcmp("c++11",cpp_std)) {
                    printf("%s is not a valid cpp_std. Use --cpp-std=c++98 or --cpp-std=c++11 instead\n\n", cpp_std);
                    fflush(stdout);
                    _exit(1);
                }

                if(!strcmp (cpp_std, "c++11")) {
                    emit(2, "static constexpr %-8s %s = %s%s;", mapped_typename,
                         lc->membername, lc->val_str, suffix);
                } else {
                    emit(2, "// If you're using C++11 and are getting compiler errors saying things like");
                    emit(2, "// ‘constexpr’ needed for in-class initialization of static data member");
                    emit(2, "// then re-run lcm-gen with '--cpp-std=c++11' to generate code that is");
                    emit(2, "// compliant with C++11");
                    emit(2, "static const %-8s %s = %s%s;", mapped_typename,
                         lc->membername, lc->val_str, suffix);
                }
            }
        }
        emit(0, "");
    }

    emit(1, "public:");
    emit(2, "/**");
    emit(2, " * Encode a message into binary form.");
    emit(2, " *");
    emit(2, " * @param buf The output buffer.");
    emit(2, " * @param offset Encoding starts at thie byte offset into @p buf.");
    emit(2, " * @param maxlen Maximum number of bytes to write.  This should generally be");
    emit(2, " *  equal to getEncodedSize().");
    emit(2, " * @return The number of bytes encoded, or <0 on error.");
    emit(2, " */");
    emit(2, "inline int encode(void *buf, int offset, int maxlen) const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Check how many bytes are required to encode this message.");
    emit(2, " */");
    emit(2, "inline int getEncodedSize() const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Decode a message from binary form into this instance.");
    emit(2, " *");
    emit(2, " * @param buf The buffer containing the encoded message.");
    emit(2, " * @param offset The byte offset into @p buf where the encoded message starts.");
    emit(2, " * @param maxlen The maximum number of bytes to reqad while decoding.");
    emit(2, " * @return The number of bytes decoded, or <0 if an error occured.");
    emit(2, " */");
    emit(2, "inline int decode(const void *buf, int offset, int maxlen);");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Compare two instances of the same type.");
    emit(2, " *");
    emit(2, " * @param[in] other The object to compare.");
    emit(2, " * @return true if all elements are equal, false otherwise.");
    emit(2, " */");
    emit(2, "inline bool operator==(%s const & other) const;", sn);
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Construct a string from the object for debugging purposes.");
    emit(2, " * Note that arrays are cropped for readability. Only the first and last elements are shown.");
    emit(2, " *");
    emit(2, " * @param[in] layout A placeholder for the tree structure.");
    emit(2, " */");
    emit(2, "inline std::string toDebugStr(std::string const & layout=\"|-\") const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Initialize all values of a test object to pre-defined values.");
    emit(2, " * The values used are much more informative than using 0 because");
    emit(2, " * they are type-dependant. This way, the user knows directly whether");
    emit(2, " * the type is correct or not. Typically the default values are the");
    emit(2, " * maximum value allowed by the type minus 5, and 1.0 for float and double.");
    emit(2, " * Note that for arrays only the first and last elements are considered.");
    emit(2, " *");
    emit(2, " * @return success.");
    emit(2, " */");
    emit(2, "inline bool initTestObject();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Increment every variable in the object.");
    emit(2, " * Works well with initTestObject() and compareTestObject().");
    emit(2, " * Note that for arrays only the first and last elements are considered.");
    emit(2, " *");
    emit(2, " * @return success.");
    emit(2, " */");
    emit(2, "inline bool incTestObject();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Compare two instances of the same type.");
    emit(2, " * Works well with initTestObject() and incTestObject().");
    emit(2, " * Note that for arrays only the first and last elements are considered.");
    emit(2, " *");
    emit(2, " * @param[in] other The object to compare.");
    emit(2, " * @return true if all elements are equal, false otherwise.");
    emit(2, " */");
    emit(2, "inline bool compareTestObject(%s const & other) const;", sn);
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Retrieve the 64-bit fingerprint identifying the structure of the message.");
    emit(2, " * Note that the fingerprint is the same for all instances of the same");
    emit(2, " * message type, and is a fingerprint on the message type definition, not on");
    emit(2, " * the message contents.");
    emit(2, " */");
    emit(2, "inline static int64_t getHash();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Returns \"%s\"", ls->structname->shortname);
    emit(2, " */");
    emit(2, "inline static const char* getTypeName();");

    emit(0, "");
    emit(2, "// LCM support functions. Users should not call these");
    emit(2, "inline int _encodeNoHash(void *buf, int offset, int maxlen) const;");
    emit(2, "inline int _getEncodedSizeNoHash() const;");
    emit(2, "inline int _decodeNoHash(const void *buf, int offset, int maxlen);");
    emit(2, "inline static uint64_t _computeHash(const __lcm_hash_ptr *p);");
    emit(0, "};");
    emit(0, "");

    free(tn_);
}
Example #5
0
File: emit_cpp.c Project: ahans/lcm
/** Emit header file **/
static void emit_header_start(lcmgen_t *lcmgen, FILE *f, lcm_struct_t *ls)
{
    char *tn = ls->structname->lctypename;
    char *sn = ls->structname->shortname;
    char *tn_ = dots_to_underscores(tn);

    emit_auto_generated_warning(f);

    fprintf(f, "#include <lcm/lcm_coretypes.h>\n");
    fprintf(f, "\n");
    fprintf(f, "#ifndef __%s_hpp__\n", tn_);
    fprintf(f, "#define __%s_hpp__\n", tn_);
    fprintf(f, "\n");

    // do we need to #include <vector> and/or <string>?
    int emit_include_vector = 0;
    int emit_include_string = 0;
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *)g_ptr_array_index(ls->members, mind);
        if (g_ptr_array_size(lm->dimensions) != 0 &&
            !lcm_is_constant_size_array(lm) && !emit_include_vector) {
            emit(0, "#include <vector>");
            emit_include_vector = 1;
        }
        if(!emit_include_string &&
            !strcmp(lm->type->lctypename, "string")) {
            emit(0, "#include <string>");
            emit_include_string = 1;
        }
    }

    // include header files for other LCM types
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

        if (!lcm_is_primitive_type(lm->type->lctypename) &&
            strcmp(lm->type->lctypename, ls->structname->lctypename)) {
            char *other_tn = dots_to_slashes (lm->type->lctypename);
            emit(0, "#include \"%s%s%s.hpp\"",
                    getopt_get_string(lcmgen->gopt, "cpp-include"),
                    strlen(getopt_get_string(lcmgen->gopt, "cpp-include"))>0 ? G_DIR_SEPARATOR_S : "",
                    other_tn);
            free(other_tn);
        }
    }

    fprintf(f, "\n");
    emit_package_namespace_start(lcmgen, f, ls);

    // define the class
    emit(0, "");
    emit_comment(f, 0, ls->comment);
    emit(0, "class %s", sn);
    emit(0, "{");

    // data members
    if(g_ptr_array_size(ls->members)) {
        emit(1, "public:");
        for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
            lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

            emit_comment(f, 2, lm->comment);
            char* mapped_typename = map_type_name(lm->type->lctypename);
            int ndim = g_ptr_array_size(lm->dimensions);
            if (ndim == 0) {
                emit(2, "%-10s %s;", mapped_typename, lm->membername);
            } else {
                if (lcm_is_constant_size_array(lm)) {
                    emit_start(2, "%-10s %s", mapped_typename, lm->membername);
                    for (unsigned int d = 0; d < ndim; d++) {
                        lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, d);
                        emit_continue("[%s]", ld->size);
                    }
                    emit_end(";");
                } else {
                    emit_start(2, "");
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue("std::vector< ");
                    emit_continue("%s", mapped_typename);
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue(" >");
                    emit_end(" %s;", lm->membername);
                }
            }
            free(mapped_typename);
            if (mind < g_ptr_array_size(ls->members) - 1) {
                emit(0, "");
            }
        }
        emit(0, "");
    }

    // constants
    if (g_ptr_array_size(ls->constants) > 0) {
        emit(1, "public:");
        for (unsigned int i = 0; i < g_ptr_array_size(ls->constants); i++) {
            lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, i);
            assert(lcm_is_legal_const_type(lc->lctypename));

            emit_comment(f, 2, lc->comment);
            // For int32_t only, we emit enums instead of static const
            // values because the former can be passed by reference while
            // the latter cannot.
            if (!strcmp(lc->lctypename, "int32_t")) {
              emit(2, "enum { %s = %s };", lc->membername, lc->val_str);
            } else {
              const char *suffix = "";
              if (!strcmp(lc->lctypename, "int64_t"))
                suffix = "LL";
              char* mapped_typename = map_type_name(lc->lctypename);
              emit(2, "static const %-8s %s = %s%s;", mapped_typename,
                  lc->membername, lc->val_str, suffix);
              free(mapped_typename);
            }
        }
        emit(0, "");
    }

    emit(1, "public:");
    emit(2, "/**");
    emit(2, " * Encode a message into binary form.");
    emit(2, " *");
    emit(2, " * @param buf The output buffer.");
    emit(2, " * @param offset Encoding starts at thie byte offset into @p buf.");
    emit(2, " * @param maxlen Maximum number of bytes to write.  This should generally be");
    emit(2, " *  equal to getEncodedSize().");
    emit(2, " * @return The number of bytes encoded, or <0 on error.");
    emit(2, " */");
    emit(2, "inline int encode(void *buf, int offset, int maxlen) const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Check how many bytes are required to encode this message.");
    emit(2, " */");
    emit(2, "inline int getEncodedSize() const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Decode a message from binary form into this instance.");
    emit(2, " *");
    emit(2, " * @param buf The buffer containing the encoded message.");
    emit(2, " * @param offset The byte offset into @p buf where the encoded message starts.");
    emit(2, " * @param maxlen The maximum number of bytes to reqad while decoding.");
    emit(2, " * @return The number of bytes decoded, or <0 if an error occured.");
    emit(2, " */");
    emit(2, "inline int decode(const void *buf, int offset, int maxlen);");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Retrieve the 64-bit fingerprint identifying the structure of the message.");
    emit(2, " * Note that the fingerprint is the same for all instances of the same");
    emit(2, " * message type, and is a fingerprint on the message type definition, not on");
    emit(2, " * the message contents.");
    emit(2, " */");
    emit(2, "inline static int64_t getHash();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Returns \"%s\"", ls->structname->shortname);
    emit(2, " */");
    emit(2, "inline static const char* getTypeName();");

    emit(0, "");
    emit(2, "// LCM support functions. Users should not call these");
    emit(2, "inline int _encodeNoHash(void *buf, int offset, int maxlen) const;");
    emit(2, "inline int _getEncodedSizeNoHash() const;");
    emit(2, "inline int _decodeNoHash(const void *buf, int offset, int maxlen);");
    emit(2, "inline static int64_t _computeHash(const __lcm_hash_ptr *p);");
    emit(0, "};");
    emit(0, "");

    free(tn_);
}