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; }
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; }
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; }
/** 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_); }
/** 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_); }