static int emit_header(lcmgen_t *lcm, lcm_struct_t *ls) { start_file("_new"); // define the class emit(0, "function S = %s_new()", sn); emit(1, "S = struct(..."); // data members int const members = g_ptr_array_size(ls->members); for (unsigned int mx = 0; mx < members; mx++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mx); char* lm_tnc = dots_to_double_colons(lm->type->lctypename); emit_start(2, "'%s', ", lm->membername); int const dimensions = g_ptr_array_size(lm->dimensions); int const primitive = lcm_is_primitive_type(lm->type->lctypename); if (0 == dimensions) { emit_continue("%s%s", map_type_name(lm_tnc) , primitive ? "(0)" : "_new()"); } else { emit_continue("repmat( %s%s, [", map_type_name(lm_tnc), primitive ? "(0)" : "_new()"); for (int dx = 0; dx < dimensions - 1; ++dx) { lcm_dimension_t *dim = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dx); emit_continue("%s, ", dim->size); } lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dimensions - 1); emit_continue("%s%s] )", dim->size, dimensions == 1 ? ", 1" : ""); } emit_end("%s", (members == mx + 1 ? " );" : ",...")); } emit(0, "%%endfunction"); emit(0, ""); // // constants TODO // 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)); // // const char *suffix = ""; // if (!strcmp(lc->lctypename, "int64_t")) // suffix = "LL"; // char const * 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(9, "};"); // // free(tn_); end_file(); }
static int emit_encoded_size_nohash(lcmgen_t *lcm, lcm_struct_t *ls) { start_file("_encodedSize_nohash"); emit(0, "function s = %s_encodedSize_nohash(S)", sn); emit(1, "s = uint32(0);"); for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); char* lm_tnc = dots_to_double_colons(lm->type->lctypename); int const encsize = encoded_size(lm_tnc); int const dimensions = g_ptr_array_size(lm->dimensions); if (encsize > -1) {//known constant size emit_start(1, "s = s + %d", encsize); for (int dx = 0; dx < dimensions; ++dx) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dx); emit_continue(" * %s", dim->size); } emit_end(";"); } else { if (0 == dimensions) { emit(1, "s = s + %s_encodedSize_nohash(S.%s);", map_type_name(lm_tnc), lm->membername); } else { //emit: for each dimension for (int dx = 0; dx < dimensions; ++dx) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dx); emit(1 + dx, "for dx%d = 1:%s", dx, dim->size); } {//do emit_start(1 + dimensions, "s = s + %s_encodedSize_nohash(S.%s(", map_type_name(lm_tnc), lm->membername); for (int dx = 0; dx < dimensions - 1; ++dx) { emit_continue("dx%d,", dx); } emit_end("dx%d));", dimensions - 1); } //end for (int dx = dimensions; dx > 0; --dx) { emit(dx, "end"); } } } free(lm_tnc); } emit(0, "%%endfunction"); emit(0, ""); end_file(); }
static void emit_c_array_loops_start(lcmgen_t *lcm, FILE *f, lcm_member_t *lm, const char *n, int flags) { if (g_ptr_array_size(lm->dimensions) == 0) return; for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions) - 1; i++) { char var = 'a' + i; if (flags & FLAG_EMIT_MALLOCS) { char stars[1000]; for (unsigned int s = 0; s < g_ptr_array_size(lm->dimensions) - 1 - i; s++) { stars[s] = '*'; stars[s+1] = 0; } emit(2+i, "%s = (%s%s*) lcm_malloc(sizeof(%s%s) * %s);", make_accessor(lm, n, i), map_type_name(lm->type->lctypename), stars, map_type_name(lm->type->lctypename), stars, make_array_size(lm, n, i)); } emit(2+i, "{ int %c;", var); emit(2+i, "for (%c = 0; %c < %s; %c++) {", var, var, make_array_size(lm, "p", i), var); } if (flags & FLAG_EMIT_MALLOCS) { emit(2 + g_ptr_array_size(lm->dimensions) - 1, "%s = (%s*) lcm_malloc(sizeof(%s) * %s);", make_accessor(lm, n, g_ptr_array_size(lm->dimensions) - 1), map_type_name(lm->type->lctypename), map_type_name(lm->type->lctypename), make_array_size(lm, n, g_ptr_array_size(lm->dimensions) - 1)); } }
static int emit_decode_nohash(lcmgen_t *lcm, lcm_struct_t *ls) { start_file("_decode_nohash"); emit(0, "function [pos, S] = %s_decode_nohash(buf, pos, maxlen, S, elems)", sn); emit(1, "for ix = 1:elems"); for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); char* lm_tnc = dots_to_double_colons(lm->type->lctypename); int const dimensions = g_ptr_array_size(lm->dimensions); if (0 == dimensions) { emit(2, "[pos, t] = %s_decode_nohash(buf, pos, maxlen, S(ix).%s, 1);", map_type_name(lm_tnc), lm->membername); emit(2, "S(ix).%s = t(1);", lm->membername); } else { //emit: for each dimension for (int dx = 0; dx < dimensions - 1; ++dx) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dx); emit(2 + dx, "for dx%d = 1:%s", dx, dim->size); } {//do emit_start(1 + (dimensions > 1 ? dimensions : 1), "[pos, t] = %s_decode_nohash(buf, pos, maxlen, S(ix).%s(", map_type_name(lm_tnc), lm->membername); for (int dx = 0; dx < dimensions - 1; ++dx) { emit_continue("dx%d,", dx); } lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dimensions - 1); emit_end(":), %s);", dim->size); emit_start(1 + (dimensions > 1 ? dimensions : 1), "S(ix).%s(", lm->membername); for (int dx = 0; dx < dimensions - 1; ++dx) { emit_continue("dx%d,", dx); } emit_end(":) = t(1:%s);", dim->size); } //end for (int dx = dimensions - 1; dx > 0; --dx) { emit(1 + dx, "end"); } } free(lm_tnc); } emit(1, "end"); emit(0, "%%endfunction"); end_file(); }
static void emit_init_test(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "bool %s::initTestObject()", sn); emit(0, "{"); if(0 == g_ptr_array_size(ls->members)) { emit(1, "return true;"); emit(0,"}"); emit(0,""); return; } // For each member 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); char const* mapped_typename = map_type_name(lm->type->lctypename); char const* typeInitValue = init_test_value(mapped_typename); char * valueAssignment; // For non-primitive types, simply call object's init function if ( ! lcm_is_primitive_type(lm->type->lctypename) ) { valueAssignment = strdup(".initTestObject();"); } else { valueAssignment = g_strdup_printf(" = %s;", typeInitValue); } int ndim = g_ptr_array_size(lm->dimensions); if (0==ndim) { emit(1, "%s%s", lm->membername, valueAssignment); free (valueAssignment); } else { // Check if it's a dynamic array, in which case we ignore it at the moment. uint8_t isDynamic=0; for (int dim=0; dim < ndim; ++dim) { lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim); if (!is_dim_size_fixed(ld->size)) { isDynamic=1; break; } } if (!isDynamic) { // Set first component in array emit_start(1, "%s", lm->membername); for (int dim=0; dim < ndim; ++dim) { emit_continue("[0]"); } emit_end("%s", valueAssignment); // Set last component in array emit_start(1, "%s", lm->membername); for (int dim=0; dim < ndim; ++dim) { lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim); emit_continue("[%i]", atoi(ld->size)-1); } emit_end("%s", valueAssignment); } else { emit(1, "//%s is a dynamic array", lm->membername); } g_free (valueAssignment); free((char*)mapped_typename); free((char*)typeInitValue); } } emit(0, ""); emit(1, "return true;"); emit(0,"}"); emit(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 output specific to a particular type of struct. **/ static void emit_header_struct(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { char *tn = ls->structname->lctypename; char *tn_ = dots_to_underscores(tn); char *tn_upper = g_utf8_strup(tn_, -1); // include header files required by members for (unsigned int i = 0; i < g_ptr_array_size(ls->members); i++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, i); if (!lcm_is_primitive_type(lm->type->lctypename) && strcmp(lm->type->lctypename, ls->structname->lctypename)) { char *other_tn = dots_to_underscores (lm->type->lctypename); fprintf(f, "#include \"%s%s%s.h\"\n", getopt_get_string(lcm->gopt, "cinclude"), strlen(getopt_get_string(lcm->gopt, "cinclude"))>0 ? "/" : "", other_tn); free (other_tn); } } // output constants 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)); const char *suffix = ""; if (!strcmp(lc->lctypename, "int64_t")) { suffix = "LL"; } emit_comment(f, 0, lc->comment); emit(0, "#define %s_%s %s%s", tn_upper, lc->membername, lc->val_str, suffix); } if (g_ptr_array_size(ls->constants) > 0) { emit(0, ""); } // define the struct emit_comment(f, 0, ls->comment); emit(0, "typedef struct _%s %s;", tn_, tn_); emit(0, "struct _%s", tn_); emit(0, "{"); for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); emit_comment(f, 1, lm->comment); int ndim = g_ptr_array_size(lm->dimensions); if (ndim == 0) { emit(1, "%-10s %s;", map_type_name(lm->type->lctypename), lm->membername); } else { if (lcm_is_constant_size_array(lm)) { emit_start(1, "%-10s %s", map_type_name(lm->type->lctypename), 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(1, "%-10s ", map_type_name(lm->type->lctypename)); for (unsigned int d = 0; d < ndim; d++) emit_continue("*"); emit_end("%s;", lm->membername); } } } emit(0, "};"); emit(0, ""); free(tn_); g_free(tn_upper); }
/** 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_); }