static void emit_member_initializer(const lcmgen_t* lcm, FILE *f, lcm_member_t* lm, int dim_num) { if(dim_num == lm->dimensions->len) { emit_end("%s", nil_initializer_string(lm->type)); return; } lcm_dimension_t *dim = (lcm_dimension_t *) g_ptr_array_index (lm->dimensions, dim_num); if(dim->mode == LCM_VAR) { emit_end("{}"); } else { emit_end("{}"); emit(dim_num + 1, "for d%d = 1, %s do", dim_num, dim->size); emit_start(dim_num + 2, "obj.%s", lm->membername); for(int i = 0; i < dim_num + 1; i++){ emit_continue("[d%d]", i); } emit_continue(" = "); emit_member_initializer(lcm, f, lm, dim_num + 1); emit(dim_num + 1, "end"); } }
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_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 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 _flush_read_struct_fmt (const lcmgen_t *lcm, FILE *f, GQueue *formats, GQueue *members) { int nfmts = g_queue_get_length(formats); assert (nfmts == g_queue_get_length (members)); if(nfmts == 0) return; emit_start(1, ""); // for indent int fmtsize = 0; while (! g_queue_is_empty (members)) { lcm_member_t *lm = (lcm_member_t*) g_queue_pop_head (members); emit_continue ("obj.%s", lm->membername); if (! g_queue_is_empty (members)) { emit_continue (", "); } fmtsize += _primitive_type_size (lm->type->lctypename); } emit_continue (" = lcm._pack.unpack('>"); while (! g_queue_is_empty (formats)) { emit_continue ("%c", GPOINTER_TO_INT (g_queue_pop_head (formats))); } emit_end ("', data:read(%d))", fmtsize); }
void Prepreprocess::exact_quote(const std::string &line) { int end=line.length(); state=START; for (int pos=0; pos<end; ++pos) emit_char(line[pos]); emit_end(); }
static void _flush_read_struct_fmt (const lcmgen_t *lcm, FILE *f, GQueue *formats, GQueue *members) { int nfmts = g_queue_get_length(formats); assert (nfmts == g_queue_get_length (members)); if(nfmts == 0) return; fprintf (f, " "); int fmtsize = 0; while (! g_queue_is_empty (members)) { lcm_member_t *lm = (lcm_member_t*) g_queue_pop_head (members); emit_continue ("self.%s", lm->membername); if (! g_queue_is_empty (members)) { emit_continue (", "); } fmtsize += _primitive_type_size (lm->type->lctypename); } emit_continue (" = struct.unpack(\">"); while (! g_queue_is_empty (formats)) { emit_continue ("%c", GPOINTER_TO_INT (g_queue_pop_head (formats))); } emit_end ("\", buf.read(%d))%s", fmtsize, nfmts == 1 ? "[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_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(); }
int dec64_to_string( dec64_string_state state, dec64 number, dec64_string_char string[] ) { /* dec64_to_string converts a dec64 number into a string. The caller provides the memory in which to deposit the string. The string must have sufficient capacity to hold 32 characters. If NULL is passed in as the string, then no characters will be deposited, but a character count will be returned. dec64_to_string returns the number of characters actually deposited in the string (not including the trailing \0). If the number is nan, then it returns 0 indicating an empty string. In standard mode, the number will be formatted conventionally unless it would require more than 17 digits, which would be due to excessive trailing zeros or zeros immediately after the decimal point. In that case scientific notation will be used instead. */ if (state == NULL || state->valid != confirmed) { return 0; } state->length = 0; state->string = string; if (dec64_is_any_nan(number) != DEC64_TRUE) { if (dec64_is_zero(number) == DEC64_TRUE) { emit(state, '0'); } else { if (number != state->number) { state->number = number; digitize(state); } if (number < 0) { emit(state, '-'); } switch (state->mode) { case engineering_mode: engineering(state); break; case scientific_mode: scientific(state); break; case standard_mode: standard(state); break; } } } emit_end(state); state->string = NULL; return state->length; }
void encode_recursive(zcmgen_t *zcm, zcm_member_t *lm, FILE *f, primitive_info_t *pinfo, char *accessor, int depth) { // base case: primitive array if (depth+1 == g_ptr_array_size(lm->dimensions) && pinfo != NULL) { char accessor_array[1024]; make_accessor_array(lm, "", accessor_array); if (!strcmp(pinfo->storage, "byte")) { zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); if (dim->mode == ZCM_VAR) { emit(2+depth, "if (this.%s > 0)", dim->size); emit(3+depth, "outs.write(this.%s, 0, %s);", accessor_array, dim->size); } else { emit(2+depth, "outs.write(this.%s, 0, %s);", accessor_array, dim->size); } return; } // some other kind of primitive array. // This seems to be slower than the default (and is untested for correctness), hence it is disabled. if (0 && !strcmp(pinfo->storage, "float")) { zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit(2+depth, "{ ByteBuffer bbuf = ByteBuffer.allocate(%s%s*4); bbuf.order(ByteOrder.BIG_ENDIAN); ", dim_size_prefix(dim->size), dim->size); emit(2+depth, " bbuf.asFloatBuffer().put(this.%s);", accessor_array); emit(2+depth, " outs.write(bbuf.array()); }"); return; } } // base case: generic if (depth == g_ptr_array_size(lm->dimensions)) { emit_start(2 + g_ptr_array_size(lm->dimensions),""); if (pinfo != NULL) freplace(f, pinfo->encode, accessor); else freplace(f, "#._encodeRecursive(outs);", accessor); emit_end(" "); return; } zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit(2+depth, "for (int %c = 0; %c < %s%s; %c++) {", 'a'+depth, 'a'+depth, dim_size_prefix(dim->size), dim->size, 'a'+depth); encode_recursive(zcm, lm, f, pinfo, accessor, depth+1); emit(2+depth, "}"); }
void decode_recursive(zcmgen_t *zcm, zcm_member_t *lm, FILE *f, primitive_info_t *pinfo, char *accessor, int depth) { // base case: primitive array if (depth+1 == g_ptr_array_size(lm->dimensions) && pinfo != NULL) { char accessor_array[1024]; make_accessor_array(lm, "", accessor_array); // byte array if (!strcmp(pinfo->storage, "byte")) { zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit_start(2+depth, "ins.readFully(this.%s, 0, %s);", accessor_array, dim->size); return; } // some other kind of primitive array. // This seems to be slower than the default (and is untested for correctness), hence it is disabled. if (0 && !strcmp(pinfo->storage, "float")) { zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit(2+depth, "{ byte bb[] = new byte[%s%s*4]; ins.readFully(bb); ByteBuffer bbuf = ByteBuffer.wrap(bb); bbuf.order(ByteOrder.BIG_ENDIAN); ", dim_size_prefix(dim->size), dim->size); emit(2+depth, " bbuf.asFloatBuffer().get(this.%s); }", accessor_array); return; } } // base case: generic if (depth == g_ptr_array_size(lm->dimensions)) { emit_start(2 + g_ptr_array_size(lm->dimensions),""); if (pinfo != NULL) freplace(f, pinfo->decode, accessor); else { emit_continue("%s = %s._decodeRecursiveFactory(ins);", accessor, make_fqn(zcm, lm->type->lctypename)); } emit_end(""); return; } zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit(2+depth, "for (int %c = 0; %c < %s%s; %c++) {", 'a'+depth, 'a'+depth, dim_size_prefix(dim->size), dim->size, 'a'+depth); decode_recursive(zcm, lm, f, pinfo, accessor, depth+1); emit(2+depth, "}"); }
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 _flush_write_struct_fmt (FILE *f, GQueue *formats, GQueue *members) { assert (g_queue_get_length (formats) == g_queue_get_length (members)); if (g_queue_is_empty (formats)) return; emit_start (2, "buf.write(struct.pack(\">"); while (! g_queue_is_empty (formats)) { emit_continue ("%c", GPOINTER_TO_INT (g_queue_pop_head (formats))); } emit_continue ("\", "); while (! g_queue_is_empty (members)) { lcm_member_t *lm = (lcm_member_t*) g_queue_pop_head (members); emit_continue ("self.%s", lm->membername); if (! g_queue_is_empty (members)) { emit_continue (", "); } } emit_end ("))"); }
void Prepreprocess::magic_quote(const std::string &line) { int end=line.length(); bool use_suffix=true; state=START; for (int pos=0; pos<end; ++pos) { if (line[pos]=='$') { if (pos == end-1) { use_suffix=false; break; } else { if (id0(line[pos+1])) { ++pos; int begin=pos; while (pos < end && id1(line[pos])) ++pos; emit_expression(line.substr(begin,(pos-begin))); --pos; continue; } if (line[pos+1] == '(') { ++pos; int begin=pos; int parens=0; while (pos < end) { if (line[pos]=='(') ++parens; if (line[pos]==')') {--parens; if (parens==0) { ++pos; break; } } ++pos; } emit_expression(line.substr(begin,(pos-begin))); --pos; continue; } if (line[pos+1]=='$') { ++pos; } } } emit_char(line[pos]); } emit_end(use_suffix); }
static void _flush_write_struct_fmt (FILE *f, GQueue *formats, GQueue *members) { // XXX encode primitive members in one line assert (g_queue_get_length (formats) == g_queue_get_length (members)); if (g_queue_is_empty (formats)) return; emit_start (1, "table.insert(buf_table, lcm._pack.pack('>"); while (! g_queue_is_empty (formats)) { emit_continue ("%c", GPOINTER_TO_INT (g_queue_pop_head (formats))); } emit_continue ("', "); while (! g_queue_is_empty (members)) { lcm_member_t *lm = (lcm_member_t*) g_queue_pop_head (members); emit_continue ("self.%s", lm->membername); if (! g_queue_is_empty (members)) { emit_continue (", "); } } emit_end ("))"); }
/** 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_); }
/** 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 _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, "}"); } }
/** 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_); }
bool multiget_ascii_downstream(downstream *d, conn *uc, int (*emit_start)(conn *c, char *cmd, int cmd_len), int (*emit_skey)(conn *c, char *skey, int skey_len), int (*emit_end)(conn *c), mcache *front_cache) { assert(d != NULL); assert(d->downstream_conns != NULL); assert(d->multiget == NULL); assert(uc != NULL); assert(uc->noreply == false); proxy_td *ptd = d->ptd; assert(ptd != NULL); proxy_stats_cmd *psc_get = &ptd->stats.stats_cmd[STATS_CMD_TYPE_REGULAR][STATS_CMD_GET]; proxy_stats_cmd *psc_get_key = &ptd->stats.stats_cmd[STATS_CMD_TYPE_REGULAR][STATS_CMD_GET_KEY]; int nwrite = 0; int nconns = mcs_server_count(&d->mst); for (int i = 0; i < nconns; i++) { if (d->downstream_conns[i] != NULL && cproxy_prep_conn_for_write(d->downstream_conns[i]) == false) { d->ptd->stats.stats.err_downstream_write_prep++; cproxy_close_conn(d->downstream_conns[i]); return false; } } if (uc->next != NULL) { // More than one upstream conn, so we need a hashtable // to track keys for de-deplication. // d->multiget = genhash_init(128, skeyhash_ops); if (settings.verbose > 1) { fprintf(stderr, "cproxy multiget hash table new\n"); } } // Snapshot the volatile only once. // uint32_t msec_current_time_snapshot = msec_current_time; int uc_num = 0; conn *uc_cur = uc; while (uc_cur != NULL) { assert(uc_cur->cmd == -1); assert(uc_cur->item == NULL); assert(uc_cur->state == conn_pause); assert(IS_ASCII(uc_cur->protocol)); assert(IS_PROXY(uc_cur->protocol)); char *command = uc_cur->cmd_start; assert(command != NULL); char *space = strchr(command, ' '); assert(space > command); int cmd_len = space - command; assert(cmd_len == 3 || cmd_len == 4); // Either get or gets. int cas_emit = (command[3] == 's'); if (settings.verbose > 1) { fprintf(stderr, "forward multiget %s (%d %d)\n", command, cmd_len, uc_num); } while (space != NULL) { char *key = space + 1; char *next_space = strchr(key, ' '); int key_len; if (next_space != NULL) { key_len = next_space - key; } else { key_len = strlen(key); // We've reached the last key. // psc_get->read_bytes += (key - command + key_len); } // This key_len check helps skip consecutive spaces. // if (key_len > 0) { ptd->stats.stats.tot_multiget_keys++; psc_get_key->seen++; psc_get_key->read_bytes += key_len; // Update key-based statistics. // bool do_key_stats = matcher_check(&ptd->key_stats_matcher, key, key_len, true) == true && matcher_check(&ptd->key_stats_unmatcher, key, key_len, false) == false; if (do_key_stats) { touch_key_stats(ptd, key, key_len, msec_current_time_snapshot, STATS_CMD_TYPE_REGULAR, STATS_CMD_GET_KEY, 1, 0, 0, key_len, 0); } // Handle a front cache hit by queuing response. // // Note, front cache stats are part of mcache. // if (!cas_emit) { item *it = mcache_get(front_cache, key, key_len, msec_current_time_snapshot); if (it != NULL) { assert(it->nkey == key_len); assert(strncmp(ITEM_key(it), key, it->nkey) == 0); cproxy_upstream_ascii_item_response(it, uc_cur, 0); psc_get_key->hits++; psc_get_key->write_bytes += it->nbytes; if (do_key_stats) { touch_key_stats(ptd, key, key_len, msec_current_time_snapshot, STATS_CMD_TYPE_REGULAR, STATS_CMD_GET_KEY, 0, 1, 0, 0, it->nbytes); } // The refcount was inc'ed by mcache_get() for us. // item_remove(it); goto loop_next; } } bool self = false; conn *c = cproxy_find_downstream_conn(d, key, key_len, &self); if (c != NULL) { if (self) { // Optimization for talking with ourselves, // to avoid extra network hop. // ptd->stats.stats.tot_optimize_self++; item *it = item_get(key, key_len); if (it != NULL) { cproxy_upstream_ascii_item_response(it, uc_cur, cas_emit); psc_get_key->hits++; psc_get_key->write_bytes += it->nbytes; if (do_key_stats) { touch_key_stats(ptd, key, key_len, msec_current_time_snapshot, STATS_CMD_TYPE_REGULAR, STATS_CMD_GET_KEY, 0, 1, 0, 0, it->nbytes); } // The refcount was inc'ed by item_get() for us. // item_remove(it); if (settings.verbose > 1) { fprintf(stderr, "optimize self multiget hit: %s\n", key); } } else { psc_get_key->misses++; if (do_key_stats) { touch_key_stats(ptd, key, key_len, msec_current_time_snapshot, STATS_CMD_TYPE_REGULAR, STATS_CMD_GET_KEY, 0, 0, 1, 0, 0); } if (settings.verbose > 1) { fprintf(stderr, "optimize self multiget miss: %s\n", key); } } goto loop_next; } // See if we've already requested this key via // the multiget hash table, in order to // de-deplicate repeated keys. // bool first_request = true; if (d->multiget != NULL) { // TODO: Use Trond's allocator here. // multiget_entry *entry = calloc(1, sizeof(multiget_entry)); if (entry != NULL) { entry->upstream_conn = uc_cur; entry->opaque = 0; entry->hits = 0; entry->next = genhash_find(d->multiget, key); genhash_update(d->multiget, key, entry); if (entry->next != NULL) { first_request = false; } } else { // TODO: Handle out of multiget entry memory. } } if (first_request) { assert(c->item == NULL); assert(c->state == conn_pause); assert(IS_PROXY(c->protocol)); assert(c->ilist != NULL); assert(c->isize > 0); if (c->msgused <= 1 && c->msgbytes <= 0) { emit_start(c, command, cmd_len); } // Provide the preceding space as optimization // for ascii-to-ascii configuration. // emit_skey(c, key - 1, key_len + 1); } else { ptd->stats.stats.tot_multiget_keys_dedupe++; if (settings.verbose > 1) { char buf[KEY_MAX_LENGTH + 10]; memcpy(buf, key, key_len); buf[key_len] = '\0'; fprintf(stderr, "%d cproxy multiget dedpue: %s\n", uc_cur->sfd, buf); } } } else { // TODO: Handle when downstream conn is down. } } loop_next: space = next_space; } uc_num++; uc_cur = uc_cur->next; } for (int i = 0; i < nconns; i++) { conn *c = d->downstream_conns[i]; if (c != NULL && (c->msgused > 1 || c->msgbytes > 0)) { emit_end(c); conn_set_state(c, conn_mwrite); c->write_and_go = conn_new_cmd; if (update_event(c, EV_WRITE | EV_PERSIST)) { nwrite++; if (uc->noreply) { c->write_and_go = conn_pause; } } else { if (settings.verbose > 1) { fprintf(stderr, "Couldn't update cproxy write event\n"); } d->ptd->stats.stats.err_oom++; cproxy_close_conn(c); } } } if (settings.verbose > 1) { fprintf(stderr, "forward multiget nwrite %d out of %d\n", nwrite, nconns); } d->downstream_used_start = nwrite; d->downstream_used = nwrite; if (cproxy_dettach_if_noreply(d, uc) == false) { d->upstream_suffix = "END\r\n"; cproxy_start_downstream_timeout(d, NULL); } return nwrite > 0; }
static void emit_compare(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) { const char *sn = ls->structname->shortname; emit(0, "/// Deep compare. FIXME floats and doubles are compared to 1e-5"); emit(0, "bool %s::operator==(%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 (non-array) uint8_t firstNonArray = 1; uint8_t arraysExist = 0; 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); uint8_t isFloat = (0==strcmp(lm->type->lctypename,"float")) || (0==strcmp(lm->type->lctypename,"double")); // Deal with arrays afterwards if (0 != g_ptr_array_size(lm->dimensions)) { arraysExist = 1; continue; } emit_end(""); if (firstNonArray) { if (isFloat) { emit_start(1, "equal = ( (std::fabs(%s - other.%s) < 1e-5) )", lm->membername, lm->membername); } else { emit_start(1, "equal = (%s == other.%s)", lm->membername, lm->membername); } firstNonArray = 0; } else { if (isFloat) { emit_start(2, "&& ( (std::fabs(%s - other.%s) < 1e-5) )", lm->membername, lm->membername); } else { emit_start(2, "&& (%s == other.%s)", lm->membername, lm->membername); } } } emit_end(";"); emit(0,""); if (arraysExist) { emit(1, "if (!equal) {"); emit(2, "return false;"); emit(1, "}"); emit(0,""); // For each array 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); int numDim = g_ptr_array_size(lm->dimensions); if (0 == numDim) { continue; } uint8_t isFloat = (0==strcmp(lm->type->lctypename,"float")) || (0==strcmp(lm->type->lctypename,"double")); char * dimStr = g_strdup_printf(""); for (uint8_t dim = 0; dim < numDim; ++dim) { lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim); emit(1+dim, "for ( uint dim%i = 0; dim%i < %i; ++dim%i)", dim, dim, atoi(ld->size) , dim); char * tmpStr = g_strdup_printf("%s", dimStr); g_free(dimStr); dimStr = g_strdup_printf("%s[dim%i]", tmpStr, dim); g_free(tmpStr); } emit (numDim, "{"); if (isFloat) { emit (numDim+1, "if ( (std::fabs(%s - other.%s) > 1e-5) )", lm->membername, lm->membername); } else { emit (numDim+1, "if (!(%s%s == other.%s%s))", lm->membername, dimStr, lm->membername, dimStr); } emit (numDim+1, "{"); emit (numDim+2, "return false;"); emit (numDim+1, "}"); emit (numDim, "}"); emit(0,""); g_free(dimStr); } } emit(1, "return equal;"); emit(0,"}"); emit(0,""); }
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,""); }
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; }
void copy_recursive(zcmgen_t *zcm, zcm_member_t *lm, FILE *f, primitive_info_t *pinfo, char *accessor, int depth) { // base case: primitive array if (depth+1 == g_ptr_array_size(lm->dimensions) && pinfo != NULL) { char accessor_array[1024]; make_accessor_array(lm, "", accessor_array); // one method works for all primitive types, yay! zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); if (dim->mode == ZCM_VAR) { emit(2+depth, "if (this.%s > 0)", dim->size); emit_start(3+depth, "System.arraycopy(this.%s, 0, outobj.%s, 0, %s%s);", accessor_array, accessor_array, dim_size_prefix(dim->size), dim->size); } else { emit_start(2+depth, "System.arraycopy(this.%s, 0, outobj.%s, 0, %s%s);", accessor_array, accessor_array, dim_size_prefix(dim->size), dim->size); } return; } // base case: generic if (depth == g_ptr_array_size(lm->dimensions)) { if (pinfo != NULL) { emit_start(2+g_ptr_array_size(lm->dimensions), "outobj.%s", lm->membername); for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions); i++) { emit_continue("[%c]", 'a'+i); } emit_continue(" = this.%s", lm->membername); for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions); i++) { emit_continue("[%c]", 'a'+i); } emit_end(";"); } else { emit(2+depth, "outobj.%s = this.%s.copy();", accessor, accessor); } return; } zcm_dimension_t *dim = (zcm_dimension_t*) g_ptr_array_index(lm->dimensions, depth); emit(2+depth, "for (int %c = 0; %c < %s%s; %c++) {", 'a'+depth, 'a'+depth, dim_size_prefix(dim->size), dim->size, 'a'+depth); copy_recursive(zcm, lm, f, pinfo, accessor, depth+1); emit(2+depth, "}"); }
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_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_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,""); }