static void emit_encode_nohash(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char* sn = ls->structname->shortname; if(0 == g_ptr_array_size(ls->members)) { emit(0, "int %s::_encodeNoHash(void *, int, int) const", sn); emit(0, "{"); emit(1, "return 0;"); emit(0, "}"); emit(0, ""); return; } emit(0, "int %s::_encodeNoHash(void *buf, int offset, int maxlen) const", sn); emit(0, "{"); emit(1, "int pos = 0, tlen;"); 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); int num_dims = g_ptr_array_size(lm->dimensions); if (0 == num_dims) { if (lcm_is_primitive_type(lm->type->lctypename)) { if(!strcmp(lm->type->lctypename, "string")) { emit(1, "char* %s_cstr = (char*) this->%s.c_str();", lm->membername, lm->membername); emit(1, "tlen = __string_encode_array(buf, offset + pos, maxlen - pos, &%s_cstr, 1);", lm->membername); } else { emit(1, "tlen = __%s_encode_array(buf, offset + pos, maxlen - pos, &this->%s, 1);", lm->type->lctypename, lm->membername); } emit(1, "if(tlen < 0) return tlen; else pos += tlen;"); } else { _encode_recursive(lcm, f, lm, 0, 0); } } else { lcm_dimension_t *last_dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, num_dims - 1); // for non-string primitive types with variable size final // dimension, add an optimization to only call the primitive encode // functions only if the final dimension size is non-zero. if(lcm_is_primitive_type(lm->type->lctypename) && strcmp(lm->type->lctypename, "string") && !is_dim_size_fixed(last_dim->size)) { emit(1, "if(%s%s > 0) {", dim_size_prefix(last_dim->size), last_dim->size); _encode_recursive(lcm, f, lm, 0, 1); emit(1, "}"); } else { _encode_recursive(lcm, f, lm, 0, 0); } } emit(0,""); } emit(1, "return pos;"); emit(0,"}"); emit(0,""); }
static void emit_python_dependencies (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { GHashTable *dependencies = g_hash_table_new (g_str_hash, g_str_equal); for (unsigned int m=0; m<ls->members->len; m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index (ls->members, m); if (! lcm_is_primitive_type (lm->type->lctypename)) { if (strlen (lm->type->package) && ! is_same_package (ls->structname, lm->type)) { if (! g_hash_table_lookup (dependencies, lm->type->lctypename)) { g_hash_table_insert (dependencies, lm->type->lctypename, lm->type->lctypename); } } else if (! g_hash_table_lookup (dependencies, lm->type->shortname)){ g_hash_table_insert (dependencies, lm->type->shortname, lm->type->shortname); } } } GPtrArray *deps = _hash_table_get_vals (dependencies); for (int i=0; i<deps->len; i++) { const char *package = (char *) g_ptr_array_index (deps, i); emit (0, "import %s\n", package); } g_ptr_array_free (deps, TRUE); g_hash_table_destroy (dependencies); }
static void emit_lua_dependencies (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { GHashTable *dependencies = g_hash_table_new (g_str_hash, g_str_equal); for (unsigned int m=0; m<ls->members->len; m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index (ls->members, m); if (! lcm_is_primitive_type (lm->type->lctypename)) { if (!g_hash_table_lookup (dependencies, lm->type->lctypename) && strcmp(lm->type->lctypename, ls->structname->lctypename)) { g_hash_table_insert (dependencies, lm->type->lctypename, lm->type->lctypename); } } } GPtrArray *deps = _hash_table_get_vals (dependencies); for (int i=0; i<deps->len; i++) { const char *package = (char *) g_ptr_array_index (deps, i); char *variablename = escape_typename_to_variablename(package); emit (0, "local %s = require('%s')", variablename, package); g_free(variablename); } if(deps->len) emit (0, ""); g_ptr_array_free (deps, TRUE); g_hash_table_destroy (dependencies); }
static void emit_python_fingerprint (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit (1, "_hash = None"); emit (1, "def _get_hash_recursive(parents):"); emit (2, "if %s in parents: return 0", sn); for (unsigned int m = 0; m < ls->members->len; m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); if (! lcm_is_primitive_type (lm->type->lctypename)) { emit (2, "newparents = parents + [%s]", sn); break; } } emit_start (2, "tmphash = (0x%"PRIx64, ls->hash); for (unsigned int m = 0; m < ls->members->len; m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); const char *msn = lm->type->shortname; if (! lcm_is_primitive_type (lm->type->lctypename)) { const char *ghr = "_get_hash_recursive(newparents)"; if (is_same_type (lm->type, ls->structname)) { emit_continue ("+ %s.%s", msn, ghr); } else if (is_same_package (lm->type, ls->structname)) { emit_continue ("+ %s.%s.%s", msn, msn, ghr); } else { emit_continue ("+ %s.%s", lm->type->lctypename, ghr); } } } emit_end (") & 0xffffffffffffffff"); emit (2, "tmphash = (((tmphash<<1)&0xffffffffffffffff) + " "(tmphash>>63)) & 0xffffffffffffffff"); emit (2, "return tmphash"); emit (1, "_get_hash_recursive = staticmethod(_get_hash_recursive)"); emit (1, "_packed_fingerprint = None"); emit (0, ""); emit (1, "def _get_packed_fingerprint():"); emit (2, "if %s._packed_fingerprint is None:", sn); emit (3, "%s._packed_fingerprint = struct.pack(\">Q\", " "%s._get_hash_recursive([]))", sn, sn); emit (2, "return %s._packed_fingerprint", sn); emit (1, "_get_packed_fingerprint = staticmethod(_get_packed_fingerprint)"); fprintf (f, "\n"); }
static void emit_compute_hash(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; int last_complex_member = -1; 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); if(!lcm_is_primitive_type(lm->type->lctypename)) last_complex_member = m; } if(last_complex_member >= 0) { emit(0, "uint64_t %s::_computeHash(const __lcm_hash_ptr *p)", sn); emit(0, "{"); emit(1, "const __lcm_hash_ptr *fp;"); emit(1, "for(fp = p; fp != NULL; fp = fp->parent)"); emit(2, "if(fp->v == %s::getHash)", sn); emit(3, "return 0;"); if(g_ptr_array_size(ls->members)) { emit(1, "const __lcm_hash_ptr cp = { p, (void*)%s::getHash };", sn); } emit(0, ""); emit(1, "uint64_t hash = 0x%016"PRIx64"LL +", ls->hash); for (unsigned int m = 0; m <= last_complex_member; 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); if(!lcm_is_primitive_type(lm->type->lctypename)) { emit(2, " %s::_computeHash(&cp)%s", lm_tnc, (m == last_complex_member) ? ";" : " +"); } free(lm_tnc); } emit(0, ""); } else { emit(0, "uint64_t %s::_computeHash(const __lcm_hash_ptr *)", sn); emit(0, "{"); emit(1, "uint64_t hash = 0x%016"PRIx64"LL;", ls->hash); } emit(1, "return (hash<<1) + ((hash>>63)&1);"); emit(0, "}"); emit(0, ""); }
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 void emit_encoded_size_nohash(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "int %s::_getEncodedSizeNoHash() const", sn); emit(0, "{"); if(0 == g_ptr_array_size(ls->members)) { emit(1, "return 0;"); emit(0,"}"); emit(0,""); return; } emit(1, "int enc_size = 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); int ndim = g_ptr_array_size(lm->dimensions); if(lcm_is_primitive_type(lm->type->lctypename) && strcmp(lm->type->lctypename, "string")) { emit_start(1, "enc_size += "); for(int n=0; n < ndim - 1; n++) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, n); emit_continue("%s%s * ", dim_size_prefix(dim->size), dim->size); } if(ndim > 0) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, ndim - 1); emit_end("__%s_encoded_array_size(NULL, %s%s);", lm->type->lctypename, dim_size_prefix(dim->size), dim->size); } else { emit_end("__%s_encoded_array_size(NULL, 1);", lm->type->lctypename); } } else { for(int n=0; n < ndim; n++) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, n); emit(1+n, "for (int a%d = 0; a%d < %s%s; a%d++) {", n, n, dim_size_prefix(dim->size), dim->size, n); } emit_start(ndim + 1, "enc_size += this->%s", lm->membername); for(int i=0; i<ndim; i++) emit_continue("[a%d]", i); if(!strcmp(lm->type->lctypename, "string")) { emit_end(".size() + 4 + 1;"); } else { emit_end("._getEncodedSizeNoHash();"); } for(int n=ndim-1; n >= 0; n--) { emit(1 + n, "}"); } } } emit(1, "return enc_size;"); emit(0,"}"); emit(0,""); }
static void _encode_recursive(lcmgen_t* lcm, FILE* f, lcm_member_t* lm, int depth, int extra_indent) { int indent = extra_indent + 1 + depth; // primitive array if (depth+1 == g_ptr_array_size(lm->dimensions) && lcm_is_primitive_type(lm->type->lctypename) && strcmp(lm->type->lctypename, "string")) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit_start(indent, "tlen = __%s_encode_array(buf, offset + pos, maxlen - pos, &this->%s", lm->type->lctypename, lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end("[0], %s%s);", dim_size_prefix(dim->size), dim->size); emit(indent, "if(tlen < 0) return tlen; else pos += tlen;"); return; } // if(depth == g_ptr_array_size(lm->dimensions)) { if(!strcmp(lm->type->lctypename, "string")) { emit_start(indent, "char* __cstr = (char*) this->%s", lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end(".c_str();"); emit(indent, "tlen = __string_encode_array(buf, offset + pos, maxlen - pos, &__cstr, 1);"); } else { emit_start(indent, "tlen = this->%s", lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end("._encodeNoHash(buf, offset + pos, maxlen - pos);"); } emit(indent, "if(tlen < 0) return tlen; else pos += tlen;"); return; } lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit(indent, "for (int a%d = 0; a%d < %s%s; a%d++) {", depth, depth, dim_size_prefix(dim->size), dim->size, depth); _encode_recursive(lcm, f, lm, depth+1, extra_indent); emit(indent, "}"); }
static int emit_compute_hash(lcmgen_t *lcm, lcm_struct_t *ls) { start_file("_computeHash"); emit(0, "function hash = %s_computeHash(parents)", sn); emit(1, "parents_len = length(parents);"); emit(1, "parents = [parents, %zu, '%s'];", strlen(sn), sn); emit(0, ""); emit(1, "hash = hex2int64('%016"PRIx64"');", ls->hash); 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); if(!lcm_is_primitive_type(lm->type->lctypename)) { char* lm_tnc = dots_to_double_colons(lm->type->lctypename); emit(1, "visit = true;"); emit(1, "ix = uint32(1);"); emit(1, "while ix < parents_len"); emit(2, "p_len = uint32(parents(ix));"); emit(2, "if %zu == p_len && strcmp(parents(ix + 1: ix + p_len), '%s')", strlen(lm_tnc), lm_tnc); emit(3, "visit = false;"); emit(3, "break"); emit(2, "end"); emit(2, "ix = ix + p_len + 1;"); emit(1, "end"); emit(1, "if visit"); emit(2, "hash = add_overflow(hash, %s_computeHash(parents));", lm_tnc); emit(1, "end"); emit(0, ""); free(lm_tnc); } } emit(1, "%%wrap around shift"); emit(1, "overflowbit = bitshift(hash(2), -31);"); emit(1, "bigendbit = bitshift(hash(1), -31);"); emit(1, "hash = bitshift(hash, 1);"); emit(1, "hash(1) = bitor(hash(1), overflowbit);"); emit(1, "hash(2) = bitor(hash(2), bigendbit);"); emit(0, "%%endfunction"); emit(0, ""); end_file(); }
static void emit_lua_fingerprint (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "function %s._get_hash_recursive(parents)", sn); emit(0, ""); emit(0, " local newparents = {}"); emit(0, ""); emit(0, " for _, v in ipairs(parents) do"); emit(0, " if v == %s then return lcm._hash.new('0x0') end", sn); emit(0, " table.insert(newparents, v)"); emit(0, " end"); emit(0, ""); emit(0, " table.insert(newparents, %s)", sn); emit(0, ""); emit(0, " local hash = lcm._hash.new('0x%"PRIx64"')", ls->hash); // add all substruct hashes for (unsigned int m = 0; m < ls->members->len; m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); const char *msn = lm->type->shortname; if (! lcm_is_primitive_type(lm->type->lctypename)) { const char *ghr = "_get_hash_recursive(newparents)"; // XXX this might need a touch up, not sure about intra-module names if (is_same_type(lm->type, ls->structname)) { emit(0, " + %s.%s", msn, ghr); } else { char *variablename = escape_typename_to_variablename(lm->type->lctypename); emit(0, " + %s.%s", variablename, ghr); g_free(variablename); } } } emit(0, " hash:rotate(1)"); emit(0, ""); emit(0, " return hash"); emit(0, "end"); emit(0, ""); emit(0, "%s._packed_fingerprint = lcm._pack.pack('>X', %s._get_hash_recursive({}))", sn, sn); emit(0, ""); }
static void emit_decode_nohash(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char* sn = ls->structname->shortname; if(0 == g_ptr_array_size(ls->members)) { emit(0, "int %s::_decodeNoHash(const void *, int, int)", sn); emit(0, "{"); emit(1, "return 0;"); emit(0, "}"); emit(0, ""); return; } emit(0, "int %s::_decodeNoHash(const void *buf, int offset, int maxlen)", sn); emit(0, "{"); emit(1, "int pos = 0, tlen;"); 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); if (0 == g_ptr_array_size(lm->dimensions) && lcm_is_primitive_type(lm->type->lctypename)) { if(!strcmp(lm->type->lctypename, "string")) { emit(1, "int32_t __%s_len__;", lm->membername); emit(1, "tlen = __int32_t_decode_array(buf, offset + pos, maxlen - pos, &__%s_len__, 1);", lm->membername); emit(1, "if(tlen < 0) return tlen; else pos += tlen;"); emit(1, "if(__%s_len__ > maxlen - pos) return -1;", lm->membername); emit(1, "this->%s.assign(((const char*)buf) + offset + pos, __%s_len__ - 1);", lm->membername, lm->membername); emit(1, "pos += __%s_len__;", lm->membername); } else { emit(1, "tlen = __%s_decode_array(buf, offset + pos, maxlen - pos, &this->%s, 1);", lm->type->lctypename, lm->membername); emit(1, "if(tlen < 0) return tlen; else pos += tlen;"); } } else { _decode_recursive(lcm, f, lm, 0); } emit(0,""); } emit(1, "return pos;"); emit(0, "}"); emit(0, ""); }
static void emit_lua_encode_one (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { emit(0, "function %s:_encode_one()", ls->structname->shortname); // check for no members if(!g_ptr_array_size(ls->members)){ emit(0, ""); emit(0, " -- nothing to do"); emit(0, "end"); return; } emit(0, ""); emit(0, " local buf_table = {}"); emit(0, ""); GQueue *struct_fmt = g_queue_new (); GQueue *struct_members = g_queue_new (); 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 fmt = _struct_format (lm); if (! lm->dimensions->len) { // XXX not an array if (fmt) { // XXX is a primitive g_queue_push_tail (struct_fmt, GINT_TO_POINTER ((int)fmt)); g_queue_push_tail (struct_members, lm); } else { // XXX not a primitive _flush_write_struct_fmt (f, struct_fmt, struct_members); char *accessor = g_strdup_printf("self.%s", lm->membername); _emit_encode_one (lcm, f, ls, lm, accessor, 1); g_free(accessor); } } else { // XXX this is an array _flush_write_struct_fmt (f, struct_fmt, struct_members); GString *accessor = g_string_new (""); g_string_append_printf (accessor, "self.%s", lm->membername); int n; for (n=0; n<lm->dimensions->len - 1; n++) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index (lm->dimensions, n); g_string_append_printf (accessor, "[i%d]", n); if (dim->mode == LCM_CONST) { emit (1+n, "for i%d = 1, %s do", n, dim->size); } else { emit (1+n, "for i%d = 1, self.%s do", n, dim->size); } } // last dimension. lcm_dimension_t *last_dim = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, lm->dimensions->len - 1); int last_dim_fixed_len = last_dim->mode == LCM_CONST; if(lcm_is_primitive_type(lm->type->lctypename) && 0 != strcmp(lm->type->lctypename, "string")) { _emit_encode_list(lcm, f, ls, lm, accessor->str, 1+n, last_dim->size, last_dim_fixed_len); } else { if (last_dim_fixed_len) { emit (1+n, "for i%d = 1, %s do", n, last_dim->size); } else { emit (1+n, "for i%d = 1, self.%s do", n, last_dim->size); } g_string_append_printf (accessor, "[i%d]", n); _emit_encode_one (lcm, f, ls, lm, accessor->str, n+2); emit (1+n, "end"); } g_string_free (accessor, TRUE); while ( --n >= 0 ) { emit (1+n, "end"); } } } _flush_write_struct_fmt (f, struct_fmt, struct_members); g_queue_free (struct_fmt); g_queue_free (struct_members); emit(0, ""); emit(0, " return table.concat(buf_table)"); emit(0, "end"); emit(0, ""); }
static void emit_lua_decode_one (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { emit(0, "function %s._decode_one(data)", ls->structname->shortname); emit(0, ""); emit(0, " if not data.read then"); emit(0, " data = _buffer_helper:new(data)"); emit(0, " end"); emit(0, ""); emit(0, " local obj = %s:new()", ls->structname->shortname); emit(0, ""); GQueue *struct_fmt = g_queue_new (); GQueue *struct_members = g_queue_new (); 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 fmt = _struct_format (lm); if (! lm->dimensions->len) { if (fmt) { g_queue_push_tail (struct_fmt, GINT_TO_POINTER ((int)fmt)); g_queue_push_tail (struct_members, lm); } else { _flush_read_struct_fmt (lcm, f, struct_fmt, struct_members); char *accessor = g_strdup_printf("obj.%s", lm->membername); _emit_decode_one (lcm, f, ls, lm, accessor, 1); g_free(accessor); } } else { _flush_read_struct_fmt (lcm, f, struct_fmt, struct_members); GString *accessor = g_string_new (""); g_string_append_printf (accessor, "obj.%s", lm->membername); // iterate through the dimensions of the member, building up // an accessor string, and emitting for loops int n; for (n=0; n<lm->dimensions->len - 1; n++) { lcm_dimension_t *dim = (lcm_dimension_t *) g_ptr_array_index (lm->dimensions, n); emit (1+n, "%s = {}", accessor->str); if (dim->mode == LCM_CONST) { emit (1+n, "for i%d = 1, %s do", n, dim->size); } else { emit (1+n, "for i%d = 1, obj.%s do", n, dim->size); } g_string_append_printf(accessor, "[i%d]", n); } // last dimension. lcm_dimension_t *last_dim = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, lm->dimensions->len - 1); int last_dim_fixed_len = last_dim->mode == LCM_CONST; if(lcm_is_primitive_type(lm->type->lctypename) && 0 != strcmp(lm->type->lctypename, "string")) { // member is a primitive non-string type. Emit code to // decode a full array in one call to struct.unpack _emit_decode_list(lcm, f, ls, lm, accessor->str, 1+n, last_dim->size, last_dim_fixed_len); } else { // member is either a string type or an inner LCM type. Each // array element must be decoded individually emit (1+n, "%s = {}", accessor->str); if (last_dim_fixed_len) { emit (1+n, "for i%d = 1, %s do", n, last_dim->size); } else { emit (1+n, "for i%d = 1, obj.%s do", n, last_dim->size); } g_string_append_printf (accessor, "[i%d]", n); _emit_decode_one (lcm, f, ls, lm, accessor->str, n+2); emit (1+n, "end"); } g_string_free (accessor, TRUE); while ( --n >= 0 ) { emit (1+n, "end"); } } } _flush_read_struct_fmt (lcm, f, struct_fmt, struct_members); g_queue_free (struct_fmt); g_queue_free (struct_members); emit(0, ""); emit(0, " return obj"); emit(0, "end"); emit(0, ""); }
/** 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); }
static void emit_compare_test(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "bool %s::compareTestObject(%s const & other) const", sn, sn); emit(0, "{"); if(0 == g_ptr_array_size(ls->members)) { emit(1, "return true;"); emit(0,"}"); emit(0,""); return; } // For each member uint8_t firstVar = 1; emit_start(1, "bool equal = true;"); 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); int numDim = g_ptr_array_size(lm->dimensions); uint8_t isFloat = (0==strcmp(lm->type->lctypename,"float")) || (0==strcmp(lm->type->lctypename,"double")); emit_end(""); if (firstVar) { emit_start(1, "equal = "); firstVar = 0; } else { emit_start(2, "&& "); } if (0==numDim) { if (isFloat) { emit_continue("( (std::fabs(%s - other.%s) < 1e-5) )", lm->membername, lm->membername); } else if ( ! lcm_is_primitive_type(lm->type->lctypename) ) { emit_continue("(%s.compareTestObject(other.%s))", lm->membername, lm->membername); } else { emit_continue("(%s == other.%s)", lm->membername, lm->membername); } } 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 < numDim; ++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) { // Compare first component in array char * dimStr = g_strdup_printf(""); for (uint8_t dim = 0; dim < numDim; ++dim) { char * tmpStr = g_strdup_printf("%s", dimStr); g_free(dimStr); dimStr = g_strdup_printf("%s[0]", tmpStr); g_free(tmpStr); } if (isFloat) { emit_continue("( (std::fabs(%s%s - other.%s%s) < 1e-5) )", lm->membername, dimStr, lm->membername, dimStr); } else if ( ! lcm_is_primitive_type(lm->type->lctypename) ) { emit_continue("(%s%s.compareTestObject(other.%s%s))", lm->membername, dimStr, lm->membername, dimStr); } else { emit_continue("(%s%s == other.%s%s)", lm->membername, dimStr, lm->membername, dimStr); } g_free(dimStr); dimStr = g_strdup_printf(""); // Compare last component in array for (uint8_t dim = 0; dim < numDim; ++dim) { lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim); char * tmpStr = g_strdup_printf("%s", dimStr); g_free(dimStr); dimStr = g_strdup_printf("%s[%i]", tmpStr, atoi(ld->size)-1); g_free(tmpStr); } if (isFloat) { emit_continue(" && ( (std::fabs(%s%s - other.%s%s) < 1e-5) )", lm->membername, dimStr, lm->membername, dimStr); } else if ( ! lcm_is_primitive_type(lm->type->lctypename) ) { emit_continue(" && (%s%s.compareTestObject(other.%s%s))", lm->membername, dimStr, lm->membername, dimStr); } else { emit_continue(" && (%s%s == other.%s%s)", lm->membername, dimStr, lm->membername, dimStr); } g_free(dimStr); } else { emit_end("// %s is a dynamic array", lm->membername); } } } emit_end(";"); emit(0,""); emit(1, "return equal;"); emit(0,"}"); emit(0,""); }
static void emit_inc_test(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "bool %s::incTestObject()", 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 * valueAssignment; // For non-primitive types, simply call object's increment function if ( ! lcm_is_primitive_type(lm->type->lctypename) ) { valueAssignment = strdup(".incTestObject()"); } else if (!strcmp(lm->type->lctypename,"string")) { valueAssignment = g_strdup_printf(" = std::to_string(std::stol(%s", lm->membername); } else { valueAssignment = strdup("++"); } int ndim = g_ptr_array_size(lm->dimensions); if (0==ndim) { emit_start(1, "%s%s", lm->membername, valueAssignment); if (!strcmp(lm->type->lctypename,"string")) { emit_continue(")+1)"); } emit_end(";"); } 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) { // Inc first component in array emit_start(1, "%s", lm->membername); for (int dim=0; dim < ndim; ++dim) { emit_continue("[0]"); } emit_continue("%s", valueAssignment); if (!strcmp(lm->type->lctypename,"string")) { // This is not pretty but is the simplest way to avoid mem allocation for (int dim=0; dim < ndim; ++dim) { emit_continue("[0]"); } emit_continue(")+1)"); } emit_end(";"); // Inc 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_continue("%s", valueAssignment); if (!strcmp(lm->type->lctypename,"string")) { // This is not pretty but is the simplest way to avoid mem allocation 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_continue(")+1)"); } emit_end(";"); } else { emit(1, "//%s is a dynamic array", lm->membername); } g_free (valueAssignment); } } emit(0, ""); emit(1, "return true;"); emit(0,"}"); emit(0,""); }
static void emit_c_get_field(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { char *tn = ls->structname->lctypename; char *tn_ = dots_to_underscores(tn); emit(0,"int %s_get_field(const %s *p, int i, lcm_field_t *f)", tn_, tn_); emit(0,"{"); emit(1,"if (0 > i || i >= %s_num_fields())", tn_); emit(2,"return 1;"); emit(1,""); emit(1,"switch (i) {"); emit(1,""); int num_fields = g_ptr_array_size(ls->members); for(int i = 0; i < num_fields; i++) { emit(2,"case %d: {", i); lcm_member_t *m = (lcm_member_t *)g_ptr_array_index(ls->members, i); const char *type_val = NULL; if(lcm_is_primitive_type(m->type->shortname)) { type_val = str_toupper(g_strdup_printf("LCM_FIELD_%s", m->type->shortname)); } else { emit(3,"/* %s */", m->type->shortname); type_val = "LCM_FIELD_USER_TYPE"; } emit(3,"f->name = \"%s\";", m->membername); emit(3,"f->type = %s;", type_val); emit(3,"f->typestr = \"%s\";", m->type->shortname); int num_dim = g_ptr_array_size(m->dimensions); emit(3,"f->num_dim = %d;", num_dim); if(num_dim != 0) { for(int j = 0; j < num_dim; j++) { lcm_dimension_t *d = (lcm_dimension_t*) g_ptr_array_index(m->dimensions, j); if(d->mode == LCM_VAR) emit(3,"f->dim_size[%d] = p->%s;", j, d->size); else emit(3,"f->dim_size[%d] = %s;", j, d->size); } for(int j = 0; j < num_dim; j++) { lcm_dimension_t *d = (lcm_dimension_t*) g_ptr_array_index(m->dimensions, j); emit(3,"f->dim_is_variable[%d] = %d;", j, d->mode == LCM_VAR); } } emit(3, "f->data = (void *) &p->%s;", m->membername); emit(3, "return 0;"); emit(2,"}"); emit(2,""); } emit(2,"default:"); emit(3,"return 1;"); emit(1,"}"); emit(0,"}"); emit(0,""); }
static void emit_python_decode_one (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { emit(1, "def _decode_one(buf):"); emit (2, "self = %s()", ls->structname->shortname); GQueue *struct_fmt = g_queue_new (); GQueue *struct_members = g_queue_new (); 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 fmt = _struct_format (lm); if (! lm->dimensions->len) { if (fmt && strcmp(lm->type->lctypename, "boolean")) { g_queue_push_tail (struct_fmt, GINT_TO_POINTER ((int)fmt)); g_queue_push_tail (struct_members, lm); } else { _flush_read_struct_fmt (lcm, f, struct_fmt, struct_members); char *accessor = g_strdup_printf("self.%s = ", lm->membername); _emit_decode_one (lcm, f, ls, lm, accessor, 2, ""); g_free(accessor); } } else { _flush_read_struct_fmt (lcm, f, struct_fmt, struct_members); GString *accessor = g_string_new (""); g_string_append_printf (accessor, "self.%s", lm->membername); // iterate through the dimensions of the member, building up // an accessor string, and emitting for loops unsigned int n; for (n=0; n<lm->dimensions->len-1; n++) { lcm_dimension_t *dim = (lcm_dimension_t *) g_ptr_array_index (lm->dimensions, n); if(n == 0) { emit (2, "%s = []", accessor->str); } else { emit (2+n, "%s.append([])", accessor->str); } if (dim->mode == LCM_CONST) { emit (2+n, "for i%d in range(%s):", n, dim->size); } else { emit (2+n, "for i%d in range(self.%s):", n, dim->size); } if(n > 0 && n < lm->dimensions->len-1) { g_string_append_printf(accessor, "[i%d]", n-1); } } // last dimension. lcm_dimension_t *last_dim = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, lm->dimensions->len - 1); int last_dim_fixed_len = last_dim->mode == LCM_CONST; if(lcm_is_primitive_type(lm->type->lctypename) && 0 != strcmp(lm->type->lctypename, "string")) { // member is a primitive non-string type. Emit code to // decode a full array in one call to struct.unpack if(n == 0) { g_string_append_printf (accessor, " = "); } else { g_string_append_printf (accessor, ".append("); } _emit_decode_list(lcm, f, ls, lm, accessor->str, 2+n, n==0, last_dim->size, last_dim_fixed_len); } else { // member is either a string type or an inner LCM type. Each // array element must be decoded individually if(n == 0) { emit (2, "%s = []", accessor->str); } else { emit (2+n, "%s.append ([])", accessor->str); g_string_append_printf (accessor, "[i%d]", n-1); } if (last_dim_fixed_len) { emit (2+n, "for i%d in range(%s):", n, last_dim->size); } else { emit (2+n, "for i%d in range(self.%s):", n, last_dim->size); } g_string_append_printf (accessor, ".append("); _emit_decode_one (lcm, f, ls, lm, accessor->str, n+3, ")"); } g_string_free (accessor, TRUE); } } _flush_read_struct_fmt (lcm, f, struct_fmt, struct_members); emit (2, "return self"); g_queue_free (struct_fmt); g_queue_free (struct_members); emit (1, "_decode_one = staticmethod(_decode_one)"); fprintf (f, "\n"); }
/** 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_); }
static void _decode_recursive(lcmgen_t* lcm, FILE* f, lcm_member_t* lm, int depth) { // primitive array if (depth+1 == g_ptr_array_size(lm->dimensions) && lcm_is_primitive_type(lm->type->lctypename) && strcmp(lm->type->lctypename, "string")) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); int decode_indent = 1 + depth; if(!lcm_is_constant_size_array(lm)) { emit(1 + depth, "if(%s%s) {", dim_size_prefix(dim->size), dim->size); emit_start(2 + depth, "this->%s", lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end(".resize(%s%s);", dim_size_prefix(dim->size), dim->size); decode_indent++; } emit_start(decode_indent, "tlen = __%s_decode_array(buf, offset + pos, maxlen - pos, &this->%s", lm->type->lctypename, lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end("[0], %s%s);", dim_size_prefix(dim->size), dim->size); emit(decode_indent, "if(tlen < 0) return tlen; else pos += tlen;"); if(!lcm_is_constant_size_array(lm)) { emit(1 + depth, "}"); } } else if(depth == g_ptr_array_size(lm->dimensions)) { if(!strcmp(lm->type->lctypename, "string")) { emit(1 + depth, "int32_t __elem_len;"); emit(1 + depth, "tlen = __int32_t_decode_array(buf, offset + pos, maxlen - pos, &__elem_len, 1);"); emit(1 + depth, "if(tlen < 0) return tlen; else pos += tlen;"); emit(1 + depth, "if(__elem_len > maxlen - pos) return -1;"); emit_start(1 + depth, "this->%s", lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end(".assign(((const char*)buf) + offset + pos, __elem_len - 1);"); emit(1 + depth, "pos += __elem_len;"); } else { emit_start(1 + depth, "tlen = this->%s", lm->membername); for(int i=0; i<depth; i++) emit_continue("[a%d]", i); emit_end("._decodeNoHash(buf, offset + pos, maxlen - pos);"); emit(1 + depth, "if(tlen < 0) return tlen; else pos += tlen;"); } } else { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); if(!lcm_is_constant_size_array(lm)) { emit_start(1+depth, "this->%s", lm->membername); for(int i=0; i<depth; i++) { emit_continue("[a%d]", i); } emit_end(".resize(%s%s);", dim_size_prefix(dim->size), dim->size); } emit(1+depth, "for (int a%d = 0; a%d < %s%s; a%d++) {", depth, depth, dim_size_prefix(dim->size), dim->size, depth); _decode_recursive(lcm, f, lm, depth+1); emit(1+depth, "}"); } }
static void emit_print(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "std::string %s::toDebugStr(std::string const & layout) const", sn); emit(0, "{"); if(0 == g_ptr_array_size(ls->members)) { emit(1, "return \"\";"); emit(0,"}"); emit(0,""); return; } emit(1, "std::stringstream ss(\"\");"); // 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); uint8_t isString = (0==strcmp(lm->type->lctypename,"string")); int ndim = g_ptr_array_size(lm->dimensions); char * valueAssignment; char * valueAssignment2; // Needs to be split for possibly adding array index if (isString) { valueAssignment = g_strdup_printf("= '\" << %s << \"'\"", lm->membername); valueAssignment2 = g_strdup_printf(" << std::endl;"); } else if ( lcm_is_primitive_type(lm->type->lctypename) ) { valueAssignment = g_strdup_printf("= \" << std::to_string(%s", lm->membername); valueAssignment2 = g_strdup_printf(") << std::endl;"); } else { valueAssignment = g_strdup_printf("\" << std::endl << %s", lm->membername); if (0==ndim) { valueAssignment2 = g_strdup_printf(".toDebugStr(\" \"+layout);"); } else { valueAssignment2 = g_strdup_printf(".toDebugStr(\" \"+layout);"); } } emit_start(1, "ss << layout << \"%s ", lm->membername); if (0==ndim) { emit_end("%s%s", valueAssignment, valueAssignment2); } 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) { // End previous line so that each element is on a new line emit_end("\" << std::endl;"); // Print first component in array emit_start(1, "ss << \" \" << layout << \""); for (int dim=0; dim < ndim; ++dim) { emit_continue("[0]"); } emit_continue("%s", valueAssignment); for (int dim=0; dim < ndim; ++dim) { // Copy-paste is not pretty but is the simplest way to avoid mem allocation emit_continue("[0]"); } emit_end("%s", valueAssignment2); // Print last component in array emit_start(1, "ss << \" \" << layout << \""); 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_continue("%s", valueAssignment); for (int dim=0; dim < ndim; ++dim) { // Copy-paste is not pretty but is the simplest way to avoid mem allocation lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim); emit_continue("[%i]", atoi(ld->size)-1); } emit_end("%s", valueAssignment2); } else { emit_end("is a dynamic array\" << std::endl;"); } } g_free (valueAssignment); } emit(0, ""); emit(1, "return ss.str();"); emit(0,"}"); emit(0,""); }
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,""); }
static void emit_python_encode_one (const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { emit(1, "def _encode_one(self, buf):"); if(!g_ptr_array_size(ls->members)) emit(2, "pass"); GQueue *struct_fmt = g_queue_new (); GQueue *struct_members = g_queue_new (); 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 fmt = _struct_format (lm); if (! lm->dimensions->len) { if (fmt) { g_queue_push_tail (struct_fmt, GINT_TO_POINTER ((int)fmt)); g_queue_push_tail (struct_members, lm); } else { _flush_write_struct_fmt (f, struct_fmt, struct_members); char *accessor = g_strdup_printf("self.%s", lm->membername); _emit_encode_one (lcm, f, ls, lm, accessor, 2); g_free(accessor); } } else { _flush_write_struct_fmt (f, struct_fmt, struct_members); GString *accessor = g_string_new (""); g_string_append_printf (accessor, "self.%s", lm->membername); unsigned int n; for (n=0; n<lm->dimensions->len - 1; n++) { lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index (lm->dimensions, n); g_string_append_printf (accessor, "[i%d]", n); if (dim->mode == LCM_CONST) { emit (2+n, "for i%d in range(%s):", n, dim->size); } else { emit (2+n, "for i%d in range(self.%s):", n, dim->size); } } // last dimension. lcm_dimension_t *last_dim = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, lm->dimensions->len - 1); int last_dim_fixed_len = last_dim->mode == LCM_CONST; if(lcm_is_primitive_type(lm->type->lctypename) && 0 != strcmp(lm->type->lctypename, "string")) { _emit_encode_list(lcm, f, ls, lm, accessor->str, 2+n, last_dim->size, last_dim_fixed_len); } else { if (last_dim_fixed_len) { emit (2+n, "for i%d in range(%s):", n, last_dim->size); } else { emit (2+n, "for i%d in range(self.%s):", n, last_dim->size); } g_string_append_printf (accessor, "[i%d]", n); _emit_encode_one (lcm, f, ls, lm, accessor->str, n+3); } g_string_free (accessor, TRUE); } } _flush_write_struct_fmt (f, struct_fmt, struct_members); g_queue_free (struct_fmt); g_queue_free (struct_members); fprintf (f, "\n"); }
/** 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_); }