/* decode an object and insert it into the table */ static int mn_decode_insert(ei_reg *reg, const char *msgbuf, int *index, char *key) { long keylen; long objlen; long objtype; void *objbuf = NULL; long i; double f; if (ei_decode_long(msgbuf,index,&keylen) || ei_decode_long(msgbuf,index,&objlen) || ei_decode_long(msgbuf,index,&objtype)) return -1; /* decode key */ if (ei_decode_string(msgbuf,index,key)) { if (objbuf) free(objbuf); return -1; } /* finally! decode object and insert in table */ /* don't forget to fix attributes (dirty bit for example) */ /* FIXME: added cast but 64 bit trouble I think */ switch ((int)objtype & EI_REG_TYPEMASK) { case EI_INT: if (ei_decode_long(msgbuf,index,&i)) return -1; ei_reg_setival(reg,key,i); break; case EI_FLT: if (ei_decode_double(msgbuf,index,&f)) return -1; ei_reg_setfval(reg,key,f); break; case EI_STR: objbuf = NULL; if (objlen > 0) { if (!(objbuf = malloc(objlen))) return -1; if (ei_decode_string(msgbuf,index,objbuf)) { free(objbuf); return -1; } ei_reg_setsval(reg,key,objbuf); } else { /* just a pointer to nothing */ if (ei_decode_long(msgbuf,index,&i)) return -1; ei_reg_setsval(reg,key,NULL); } break; case EI_BIN: objbuf = NULL; if (objlen > 0) { if (!(objbuf = malloc(objlen))) return -1; if (ei_decode_binary(msgbuf,index,objbuf,&i)) { free(objbuf); return -1; } /* assert(i == objlen) */ ei_reg_setpval(reg,key,objbuf,objlen); } else { /* just a pointer to nothing */ if (ei_decode_long(msgbuf,index,&i)) return -1; ei_reg_setpval(reg,key,(void *)i,0); } break; default: /* unknown type */ if (objbuf) free(objbuf); return -1; } /* switch */ return 0; }
static int print_term(FILE* fp, ei_x_buff* x, const char* buf, int* index) { int i, doquote, n, m, ty, r; char a[MAXATOMLEN], *p; int ch_written = 0; /* counter of written chars */ erlang_pid pid; erlang_port port; erlang_ref ref; double d; long l; int tindex = *index; /* use temporary index for multiple (and failable) decodes */ if (fp == NULL && x == NULL) return -1; doquote = 0; ei_get_type_internal(buf, index, &ty, &n); switch (ty) { case ERL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_EXT: case ERL_SMALL_ATOM_UTF8_EXT: if (ei_decode_atom(buf, index, a) < 0) goto err; doquote = !islower((int)a[0]); for (p = a; !doquote && *p != '\0'; ++p) doquote = !(isalnum((int)*p) || *p == '_' || *p == '@'); if (doquote) { xputc('\'', fp, x); ++ch_written; } xputs(a, fp, x); ch_written += strlen(a); if (doquote) { xputc('\'', fp, x); ++ch_written; } break; case ERL_PID_EXT: case ERL_NEW_PID_EXT: if (ei_decode_pid(buf, index, &pid) < 0) goto err; ch_written += xprintf(fp, x, "<%s.%d.%d>", pid.node, pid.num, pid.serial); break; case ERL_PORT_EXT: case ERL_NEW_PORT_EXT: if (ei_decode_port(buf, index, &port) < 0) goto err; ch_written += xprintf(fp, x, "#Port<%d.%d>", port.id, port.creation); break; case ERL_NEW_REFERENCE_EXT: case ERL_NEWER_REFERENCE_EXT: case ERL_REFERENCE_EXT: if (ei_decode_ref(buf, index, &ref) < 0) goto err; ch_written += xprintf(fp, x, "#Ref<"); for (i = 0; i < ref.len; ++i) { ch_written += xprintf(fp, x, "%d", ref.n[i]); if (i < ref.len - 1) { xputc('.', fp, x); ++ch_written; } } xputc('>', fp, x); ++ch_written; break; case ERL_NIL_EXT: if (ei_decode_list_header(buf, index, &n) < 0) goto err; ch_written += xprintf(fp, x, "[]"); break; case ERL_LIST_EXT: if (ei_decode_list_header(buf, &tindex, &n) < 0) goto err; xputc('[', fp, x); ch_written++; for (i = 0; i < n; ++i) { r = print_term(fp, x, buf, &tindex); if (r < 0) goto err; ch_written += r; if (i < n - 1) { xputs(", ", fp, x); ch_written += 2; } } if (ei_get_type_internal(buf, &tindex, &ty, &n) < 0) goto err; if (ty != ERL_NIL_EXT) { xputs(" | ", fp, x); ch_written += 3; r = print_term(fp, x, buf, &tindex); if (r < 0) goto err; ch_written += r; } else { if (ei_decode_list_header(buf, &tindex, &n) < 0) goto err; } xputc(']', fp, x); ch_written++; *index = tindex; break; case ERL_STRING_EXT: p = ei_malloc(n+1); if (p == NULL) goto err; if (ei_decode_string(buf, index, p) < 0) { ei_free(p); goto err; } ch_written += print_string(fp, x, p, n); ei_free(p); break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: if (ei_decode_tuple_header(buf, &tindex, &n) < 0) goto err; xputc('{', fp, x); ch_written++; for (i = 0; i < n; ++i) { r = print_term(fp, x, buf, &tindex); if (r < 0) goto err; ch_written += r; if (i < n-1) { xputs(", ", fp, x); ch_written += 2; } } *index = tindex; xputc('}', fp, x); ch_written++; break; case ERL_BINARY_EXT: p = ei_malloc(n); if (p == NULL) goto err; if (ei_decode_binary(buf, index, p, &l) < 0) { ei_free(p); goto err; } ch_written += xprintf(fp, x, "#Bin<"); if (l > BINPRINTSIZE) m = BINPRINTSIZE; else m = l; --m; for (i = 0; i < m; ++i) { ch_written += xprintf(fp, x, "%d,", p[i]); } ch_written += xprintf(fp, x, "%d", p[i]); if (l > BINPRINTSIZE) ch_written += xprintf(fp, x, ",..."); xputc('>', fp, x); ++ch_written; ei_free(p); break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (ei_decode_long(buf, index, &l) < 0) goto err; ch_written += xprintf(fp, x, "%ld", l); break; case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: { erlang_big *b; char *ds; if ( (b = ei_alloc_big(n)) == NULL) goto err; if (ei_decode_big(buf, index, b) < 0) { ei_free_big(b); goto err; } if ( (ds = ei_big_to_str(b)) == NULL ) { ei_free_big(b); goto err; } ch_written += xprintf(fp, x, ds); free(ds); ei_free_big(b); } break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, &d) < 0) goto err; ch_written += xprintf(fp, x, "%f", d); break; default: goto err; } return ch_written; err: return -1; }
int ei_skip_term(const char* buf, int* index) { int i, n, ty; /* ASSERT(ep != NULL); */ ei_get_type_internal(buf, index, &ty, &n); switch (ty) { case ERL_ATOM_EXT: /* FIXME: what if some weird locale is in use? */ if (ei_decode_atom_as(buf, index, NULL, MAXATOMLEN_UTF8, (ERLANG_LATIN1|ERLANG_UTF8), NULL, NULL) < 0) return -1; break; case ERL_PID_EXT: if (ei_decode_pid(buf, index, NULL) < 0) return -1; break; case ERL_PORT_EXT: if (ei_decode_port(buf, index, NULL) < 0) return -1; break; case ERL_NEW_REFERENCE_EXT: case ERL_REFERENCE_EXT: if (ei_decode_ref(buf, index, NULL) < 0) return -1; break; case ERL_NIL_EXT: if (ei_decode_list_header(buf, index, &n) < 0) return -1; break; case ERL_LIST_EXT: if (ei_decode_list_header(buf, index, &n) < 0) return -1; for (i = 0; i < n; ++i) ei_skip_term(buf, index); if (ei_get_type_internal(buf, index, &ty, &n) < 0) return -1; if (ty != ERL_NIL_EXT) ei_skip_term(buf, index); else if (ei_decode_list_header(buf, index, &n) < 0) return -1; break; case ERL_STRING_EXT: if (ei_decode_string(buf, index, NULL) < 0) return -1; break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: if (ei_decode_tuple_header(buf, index, &n) < 0) return -1; for (i = 0; i < n; ++i) ei_skip_term(buf, index); break; case ERL_BINARY_EXT: if (ei_decode_binary(buf, index, NULL, NULL) < 0) return -1; break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (ei_decode_long(buf, index, NULL) < 0) return -1; break; case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: if (ei_decode_big(buf, index, NULL) < 0) return -1; break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, NULL) < 0) return -1; break; case ERL_FUN_EXT: case ERL_NEW_FUN_EXT: if (ei_decode_fun(buf, index, NULL) < 0) return -1; break; default: return -1; } return 0; }
void dump_eterm(ei_x_buff *x) { int etype, esize, arity; long long num; char *atom; int i; char *binary; long bin_size; double fnum; ei_get_type(x->buff, &x->index, &etype, &esize); uwsgi_log("etype: %d/%c esize: %d\n", etype, etype, esize); switch(etype) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: ei_decode_longlong(x->buff, &x->index, &num); uwsgi_log("num: %lu\n", num); break; case ERL_FLOAT_EXT: ei_decode_double(x->buff, &x->index, &fnum); uwsgi_log("float: %f\n", fnum); break; case ERL_STRING_EXT: atom = uwsgi_malloc(esize+1); ei_decode_string(x->buff, &x->index, atom); uwsgi_log("string: %s\n", atom); free(atom); break; case ERL_ATOM_EXT: atom = uwsgi_malloc(esize+1); ei_decode_atom(x->buff, &x->index, atom); uwsgi_log("atom: %s\n", atom); free(atom); break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: ei_decode_tuple_header(x->buff, &x->index, &arity); for(i=0;i<arity;i++) { dump_eterm(x); } break; case ERL_LIST_EXT: case ERL_NIL_EXT: ei_decode_list_header(x->buff, &x->index, &arity); if (arity == 0) { uwsgi_log("nil value\n"); break; } for(i=0;i<arity+1;i++) { dump_eterm(x); } break; case ERL_BINARY_EXT: binary = uwsgi_malloc(esize); ei_decode_binary(x->buff, &x->index, binary, &bin_size); uwsgi_log("binary data of %d bytes\n", bin_size); free(binary); break; default: uwsgi_log("ignored...\n"); ei_skip_term(x->buff, &x->index); break; } }
static void show_term(const char *termbuf, int *index, FILE *stream) { int type; char smallbuf[EISHOWBUF]; int version; long num; double fnum; erlang_pid pid; erlang_port port; erlang_ref ref; int i, len; char *s; ei_get_type_internal(termbuf,index,&type,&len); switch (type) { case ERL_VERSION_MAGIC: /* just skip past this */ ei_decode_version(termbuf,index,&version); show_term(termbuf,index,stream); break; case ERL_ATOM_EXT: ei_decode_atom(termbuf,index,smallbuf); fprintf(stream,"%s",smallbuf); break; case ERL_STRING_EXT: /* strings can be much longer than EISHOWBUF */ if (len < EISHOWBUF) s = smallbuf; else if (!(s = malloc(len+1))) break; /* FIXME just break if can't? */ ei_decode_string(termbuf,index,s); if (printable_list_p((uint8 *)s,len)) { /* just show it as it is */ fprintf(stream,"\"%s\"",s); } else { /* show it as a list instead */ fprintf(stream,"["); for (i=0; i<len; i++) { if (i > 0) fprintf(stream,", "); fprintf(stream,"%d",s[i]); } fprintf(stream,"]"); } /* did we allocate anything? */ if (s && (s != smallbuf)) free(s); break; /* FIXME add case using ei_decode_longlong */ case ERL_SMALL_BIG_EXT: case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (ei_decode_long(termbuf,index,&num) == 0) { fprintf(stream,"%ld",num); } else { ei_decode_skip_bignum(termbuf,index,NULL); fprintf(stream,"#Bignum"); } break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: ei_decode_double(termbuf,index,&fnum); fprintf(stream,"%f",fnum); break; case ERL_PID_EXT: ei_decode_pid(termbuf,index,&pid); show_pid(stream,&pid); break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: ei_decode_tuple_header(termbuf,index,&len); fprintf(stream,"{"); for (i=0; i<len; i++) { if (i > 0) fprintf(stream,", "); show_term(termbuf,index,stream); } fprintf(stream,"}"); break; case ERL_LIST_EXT: ei_decode_list_header(termbuf,index,&len); fprintf(stream,"["); for (i=0; i<len; i++) { if (i > 0) fprintf(stream,", "); show_term(termbuf,index,stream); } /* get the empty list at the end */ ei_decode_list_header(termbuf,index,&len); fprintf(stream,"]"); break; case ERL_NIL_EXT: ei_decode_list_header(termbuf,index,&len); fprintf(stream,"[]"); break; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: ei_decode_ref(termbuf,index,&ref); fprintf(stream,"#Ref<%s",ref.node); for (i = 0; i < ref.len; i++) { fprintf(stream,".%u",ref.n[i]); } fprintf(stream,".%u>",ref.creation); break; case ERL_PORT_EXT: ei_decode_port(termbuf,index,&port); fprintf(stream,"#Port<%s.%u.%u>",port.node,port.id,port.creation); break; case ERL_BINARY_EXT: ei_decode_binary(termbuf,index,NULL,&num); fprintf(stream,"#Bin<%ld>",num); break; case ERL_LARGE_BIG_EXT: /* doesn't actually decode - just skip over it */ /* FIXME if GMP, what to do here?? */ ei_decode_skip_bignum(termbuf,index,NULL); fprintf(stream,"#Bignum"); break; case ERL_FUN_EXT: { char atom[MAXATOMLEN]; long idx; long uniq; const char* s = termbuf + *index, * s0 = s; int n_free; ++s; n_free = get32be(s); *index += s - s0; ei_decode_pid(termbuf, index, NULL); /* skip pid */ ei_decode_atom(termbuf, index, atom); /* get module, index, uniq */ ei_decode_long(termbuf, index, &idx); ei_decode_long(termbuf, index, &uniq); fprintf(stream,"#Fun<%s.%ld.%ld>", atom, idx, uniq); for (i = 0; i < n_free; ++i) { /* FIXME how to report error ?! */ if (ei_skip_term(termbuf, index) != 0) fprintf(stderr,"<ERROR> show_msg: unknown type of term !"); } break; } default: fprintf(stream,"#Unknown<%d.%d>",type,len); /* unfortunately we don't know how to skip over this type in * the buffer if we don't even know what it is, so we return. */ return; break; } }
double toDouble() const { int idx = _index; double p; ei_decode_double(_buf, &idx, &p); return p; }
/*! * Take an arbitrary mixed list of integers and floats and add all numbers, * returning the resulting sum. * * \param[in] req Request * \param[in,out] res Result * \param[in,out] drv_state Driver state * \param[in,out] trd_state Thread state */ static void handle_sum(gd_req_t *req, gd_res_t *res, gdt_drv_t *drv, gdt_trd_t *trd) { int type, size; /* Determine type and size */ if (ei_get_type(req->buf, &req->index, &type, &size) || size <= 0) return error_set(res, GDE_ERR_TYPE); /* Allocate memory for numbers */ double *values, sum = 0; if (!(values = driver_alloc(sizeof(double) * size))) return error_set(res, GDE_ERR_MEMORY); /* Decode list */ switch (type) { /* Decode integer list interpreted as string */ case ERL_STRING_EXT: { char value[size]; if (ei_decode_string(req->buf, &req->index, (char *)&value)) return error_set(res, GDE_ERR_DECODE); for (int v = 0; v < size; v++) values[v] = (double)value[v]; break; } /* Decode ordinary integer/double list */ case ERL_LIST_EXT: { if (ei_decode_list_header(req->buf, &req->index, &size)) return error_set(res, GDE_ERR_DECODE); for (int v = 0, temp; v < size; v++) { ei_get_type(req->buf, &req->index, &type, &temp); switch (type) { /* Decode integer */ case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: { long value; if (ei_decode_long(req->buf, &req->index, &value)) return error_set(res, GDE_ERR_DECODE); values[v] = (double)value; break; } /* Decode double */ case ERL_FLOAT_EXT: { double value; if (ei_decode_double(req->buf, &req->index, &value)) return error_set(res, GDE_ERR_DECODE); values[v] = (double)value; break; } /* Unsupported type */ default: return error_set(res, GDE_ERR_TYPE); } } /* A list always contains an empty list at the end */ if (ei_decode_list_header(req->buf, &req->index, NULL)) return error_set(res, GDE_ERR_DECODE); break; } /* Unsupported type */ default: return error_set(res, GDE_ERR_TYPE); } /* Sum up values */ for (int v = 0; v < size; v++) sum += values[v]; /* Free allocated memory */ driver_free(values); /* Encode resulting sum and return tuple */ ei_encode_tuple_header(res->buf, &res->index, 2); ei_encode_atom(res->buf, &res->index, "ok"); ei_encode_double(res->buf, &res->index, sum); /* Update counters */ drv->count++; trd->count++; }
int ei_decode_term(const char *buf, int *index, void *t) { const char *s = buf + *index; const char *s0 = s; if (t) { ETERM *tmp; /* this decodes and advances s */ if (!(tmp = erl_decode_buf((unsigned char **)&s))) return -1; *(ETERM **)t = tmp; *index += s - s0; return 0; } else { int tmpindex = *index; long ttype; int arity; int i; /* these are all the external types */ switch ((ttype = get8(s))) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: case ERL_SMALL_BIG_EXT: return ei_decode_long(buf,index,NULL); case ERL_FLOAT_EXT: return ei_decode_double(buf,index,NULL); case ERL_ATOM_EXT: return ei_decode_atom(buf,index,NULL); case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: return ei_decode_ref(buf,index,NULL); case ERL_PORT_EXT: return ei_decode_port(buf,index,NULL); case ERL_PID_EXT: return ei_decode_pid(buf,index,NULL); case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: if (ei_decode_tuple_header(buf,index,&arity) < 0) return -1; for (i=0; i<arity; i++) { if (ei_decode_term(buf,index,NULL)) { /* restore possibly changed index before returning */ *index = tmpindex; return -1; } } return 0; case ERL_STRING_EXT: return ei_decode_string(buf,index,NULL); case ERL_LIST_EXT: case ERL_NIL_EXT: if (ei_decode_list_header(buf,index,&arity) < 0) return -1; if (arity) { for (i=0; i<arity; i++) { if (ei_decode_term(buf,index,NULL) < 0) { /* restore possibly changed index before returning */ *index = tmpindex; return -1; } } if (ei_decode_list_header(buf,index,&arity) < 0) { *index = tmpindex; return -1; } } return 0; case ERL_BINARY_EXT: return ei_decode_binary(buf,index,NULL,NULL); case ERL_LARGE_BIG_EXT: default: break; } } return -1; }
int ei_decode_ei_term(const char* buf, int* index, ei_term* term) { const char* s = buf + *index, * s0 = s; int i, n, sign; char c; if (term == NULL) return -1; c = term->ei_type = get8(s); switch (c) { case ERL_SMALL_INTEGER_EXT: term->value.i_val = get8(s); break; case ERL_INTEGER_EXT: term->value.i_val = get32be(s); break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: return ei_decode_double(buf, index, &term->value.d_val); case ERL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_EXT: case ERL_SMALL_ATOM_UTF8_EXT: return ei_decode_atom(buf, index, term->value.atom_name); case ERL_REFERENCE_EXT: /* first the nodename */ if (get_atom(&s, term->value.ref.node, &term->value.ref.node_org_enc) < 0) return -1; /* now the numbers: num (4), creation (1) */ term->value.ref.n[0] = get32be(s); term->value.ref.len = 1; term->value.ref.creation = get8(s) & 0x03; break; case ERL_NEW_REFERENCE_EXT: /* first the integer count */ term->value.ref.len = get16be(s); /* then the nodename */ if (get_atom(&s, term->value.ref.node, &term->value.ref.node_org_enc) < 0) return -1; /* creation */ term->value.ref.creation = get8(s) & 0x03; /* finally the id integers */ for (i = 0; (i<term->value.ref.len) && (i<3); i++) { term->value.ref.n[i] = get32be(s); } if (term->value.ref.len > 3) { s += 4 * (term->value.ref.len - 3); } break; case ERL_PORT_EXT: if (get_atom(&s, term->value.port.node, &term->value.port.node_org_enc) < 0) return -1; term->value.port.id = get32be(s) & 0x0fffffff; /* 28 bits */; term->value.port.creation = get8(s) & 0x03; break; case ERL_PID_EXT: if (get_atom(&s, term->value.pid.node, &term->value.port.node_org_enc) < 0) return -1; /* now the numbers: num (4), serial (4), creation (1) */ term->value.pid.num = get32be(s) & 0x7fff; /* 15 bits */ term->value.pid.serial = get32be(s) & 0x1fff; /* 13 bits */ term->value.pid.creation = get8(s) & 0x03; /* 2 bits */ break; case ERL_SMALL_TUPLE_EXT: term->arity = get8(s); break; case ERL_LARGE_TUPLE_EXT: term->arity = get32be(s); break; case ERL_NIL_EXT: term->arity = 0; break; case ERL_STRING_EXT: term->size = get16be(s); return 0; case ERL_LIST_EXT: term->arity = get32be(s); break; case ERL_BINARY_EXT: term->size = get32be(s); return 0; case ERL_SMALL_BIG_EXT: if ((term->arity = get8(s)) != 4) return -1; sign = get8(s); /* Little Endian, and n always positive, except for LONG_MIN */ n = get32le(s); if (sign) { /* check for overflow */ if ((n - 1) < 0) return -1; n = -n; } else { /* check for overflow */ if (n < 0) return -1; } break; case ERL_LARGE_BIG_EXT: return 0; case ERL_PASS_THROUGH: return 0; case ERL_NEW_CACHE: return -1; case ERL_CACHED_ATOM: return -1; default: return -1; } *index += s-s0; return 1; }
int next_double(GEOSCommand *command, double *value) { return ei_decode_double(command->param_bytes, &command->index, value); }
int ei_decode_ei_term(const char* buf, int* index, ei_term* term) { const char* s = buf + *index, * s0 = s; int n, sign; char c; if (term == NULL) return -1; c = term->ei_type = get8(s); switch (c) { case ERL_SMALL_INTEGER_EXT: term->value.i_val = get8(s); break; case ERL_INTEGER_EXT: term->value.i_val = get32be(s); break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: return (ei_decode_double(buf, index, &term->value.d_val) < 0 ? -1 : 1); case ERL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_EXT: case ERL_SMALL_ATOM_UTF8_EXT: return (ei_decode_atom(buf, index, term->value.atom_name) < 0 ? -1 : 1); case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: case ERL_NEWER_REFERENCE_EXT: return (ei_decode_ref(buf, index, &term->value.ref) < 0 ? -1 : 1); case ERL_PORT_EXT: case ERL_NEW_PORT_EXT: return (ei_decode_port(buf, index, &term->value.port) < 0 ? -1 : 1); case ERL_PID_EXT: case ERL_NEW_PID_EXT: return (ei_decode_pid(buf, index, &term->value.pid) < 0 ? -1 : 1); case ERL_SMALL_TUPLE_EXT: term->arity = get8(s); break; case ERL_LARGE_TUPLE_EXT: term->arity = get32be(s); break; case ERL_NIL_EXT: term->arity = 0; break; case ERL_STRING_EXT: term->size = get16be(s); return 0; case ERL_LIST_EXT: case ERL_MAP_EXT: term->arity = get32be(s); break; case ERL_BINARY_EXT: term->size = get32be(s); return 0; case ERL_SMALL_BIG_EXT: if ((term->arity = get8(s)) != 4) return -1; sign = get8(s); /* Little Endian, and n always positive, except for LONG_MIN */ n = get32le(s); if (sign) { /* check for overflow */ if ((n - 1) < 0) return -1; n = -n; } else { /* check for overflow */ if (n < 0) return -1; } break; case ERL_LARGE_BIG_EXT: return 0; case ERL_PASS_THROUGH: return 0; case ERL_NEW_CACHE: return -1; case ERL_CACHED_ATOM: return -1; default: return -1; } *index += s-s0; return 1; }
static int get_str(str *str_ptr, erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; double d; long n; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_FLOAT_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } p=(char*)pkg_malloc(MAX_DIGITS); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } str_ptr->len=snprintf(p, MAX_DIGITS, "%f", d); str_ptr->s = p; break; case ERL_STRING_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } if(ei_decode_strorbin(ctx->request->buff,&ctx->request_index,size+1,p)) { erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads); return -1; } str_ptr->s=p; str_ptr->len=size; break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_long(ctx->request->buff,&ctx->request_index,&n)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } p=(char*)pkg_malloc(MAX_DIGITS); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } str_ptr->len=snprintf(p, MAX_DIGITS, "%ld", n); str_ptr->s = p; break; default: erl_rpc_fault(ctx,400,"Can't convert to string parameter #%d.",reads); return -1; } LM_ERR("parameter #%d:<%.*s>\n",reads,STR_FMT(str_ptr)); return 0; }
static int get_double(double *double_prt,erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; char *endptr; long n; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)){ erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_FLOAT_EXT: if (ei_decode_double(ctx->request->buff,&ctx->request_index,double_prt)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } break; case ERL_STRING_EXT: case ERL_LIST_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } ei_decode_string(ctx->request->buff, &ctx->request_index, p); *double_prt = strtod(p,&endptr); if (p == endptr) { erl_rpc_fault(ctx,400,"Unable to convert %s into double, parameter at position #%d",p,reads); pkg_free(p); return -1; } pkg_free(p); break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if(ei_decode_long(ctx->request->buff, &ctx->request_index, &n)) { erl_rpc_fault(ctx,400,"Can't read parameter #%d",reads); return -1; } *double_prt=n; break; default: erl_rpc_fault(ctx,400,"Can't convert to double parameter #%d.",reads); return -1; } return 0; }
/* * Get int parameter */ static int get_int(int *int_ptr,erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; char *endptr; double d; long l; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { if(ctx->optional) return 0; erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if(ei_decode_long(ctx->request->buff, &ctx->request_index, &l)) { erl_rpc_fault(ctx,400,"Bad value of parameter #%d.",reads); return -1; } *int_ptr = (int)l; break; case ERL_STRING_EXT: case ERL_LIST_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } ei_decode_string(ctx->request->buff, &ctx->request_index, p); *int_ptr = strtol(p,&endptr,10); if (p == endptr) { erl_rpc_fault(ctx,400,"Unable to convert %s into integer for parameter at position %d",p,reads); pkg_free(p); return -1; } pkg_free(p); break; case ERL_FLOAT_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d)) { erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads); return -1; } *int_ptr=(int)d; break; default: LM_ERR("Unsupported type ('%c') for conversion into integer parameter #%d.\n",type,reads); erl_rpc_fault(ctx,400,"Unsupported type ('%c') for conversion into integer parameter #%d.",type,reads); return -1; } return 0; }
static inline int decode_and_bind_param( sqlite3_drv_t *drv, char *buffer, int *p_index, sqlite3_stmt *statement, int param_index, int *p_type, int *p_size) { int result; sqlite3_int64 int64_val; double double_val; char* char_buf_val; long bin_size; ei_get_type(buffer, p_index, p_type, p_size); switch (*p_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: ei_decode_longlong(buffer, p_index, &int64_val); result = sqlite3_bind_int64(statement, param_index, int64_val); break; case ERL_FLOAT_EXT: #ifdef NEW_FLOAT_EXT case NEW_FLOAT_EXT: // what's the difference? #endif ei_decode_double(buffer, p_index, &double_val); result = sqlite3_bind_double(statement, param_index, double_val); break; case ERL_ATOM_EXT: // include space for null separator char_buf_val = driver_alloc((*p_size + 1) * sizeof(char)); ei_decode_atom(buffer, p_index, char_buf_val); if (strncmp(char_buf_val, "null", 5) == 0) { result = sqlite3_bind_null(statement, param_index); } else { output_error(drv, SQLITE_MISUSE, "Non-null atom as parameter"); return 1; } break; case ERL_STRING_EXT: // include space for null separator char_buf_val = driver_alloc((*p_size + 1) * sizeof(char)); ei_decode_string(buffer, p_index, char_buf_val); result = sqlite3_bind_text(statement, param_index, char_buf_val, *p_size, &driver_free_fun); break; case ERL_BINARY_EXT: char_buf_val = driver_alloc(*p_size * sizeof(char)); ei_decode_binary(buffer, p_index, char_buf_val, &bin_size); result = sqlite3_bind_text(statement, param_index, char_buf_val, *p_size, &driver_free_fun); break; case ERL_SMALL_TUPLE_EXT: // assume this is {blob, Blob} ei_get_type(buffer, p_index, p_type, p_size); ei_decode_tuple_header(buffer, p_index, p_size); if (*p_size != 2) { output_error(drv, SQLITE_MISUSE, "bad parameter type"); return 1; } ei_skip_term(buffer, p_index); // skipped the atom 'blob' ei_get_type(buffer, p_index, p_type, p_size); if (*p_type != ERL_BINARY_EXT) { output_error(drv, SQLITE_MISUSE, "bad parameter type"); return 1; } char_buf_val = driver_alloc(*p_size * sizeof(char)); ei_decode_binary(buffer, p_index, char_buf_val, &bin_size); result = sqlite3_bind_blob(statement, param_index, char_buf_val, *p_size, &driver_free_fun); break; default: output_error(drv, SQLITE_MISUSE, "bad parameter type"); return 1; } if (result != SQLITE_OK) { output_db_error(drv); return result; } return SQLITE_OK; }
/** * Query a table for specified rows. * \param _h structure representing database connection * \param _k key names * \param _op operators *\param _v values of the keys that must match * \param _c column names to return * \param _n number of key=values pairs to compare * \param _nc number of columns to return * \param _o order by the specified column * \param _r pointer to a structure representing the result * \return zero on success, negative value on failure */ int erlang_srdb1_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op, const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc, const db_key_t _o, db1_res_t** _r) { ei_x_buff argbuf,retbuf; int retcode,i,j,x; int n_cols,n_rows,len; db1_res_t *res; db_row_t *rows = NULL, *row; db_val_t *val; char atom[MAXATOMLEN], *p; ei_term term; int ei_type,size; str *sname; if (!_h || !_r) { LM_ERR("invalid parameter value\n"); return -1; } *_r=NULL; LM_DBG("erlang_srdb1_query table %.*s\n",CON_TABLE(_h)->len, CON_TABLE(_h)->s); ei_x_new(&argbuf); //encode tuple {db_op, table, [cols], [params]} ei_x_encode_tuple_header(&argbuf, 5); ei_x_encode_atom(&argbuf,"select"); ei_x_encode_atom_len(&argbuf,CON_TABLE(_h)->s,CON_TABLE(_h)->len); srdb1_encode_c(_c, _nc, &argbuf); srdb1_encode_k(_k, _op, _v, _n, &argbuf); // ei_x_encode_atom_len(&argbuf,_o->s,_o->len); ei_x_encode_list_header(&argbuf, 0); retcode=erl_bind.do_erlang_call(&(CON_ERLANG(_h)->con),&(CON_ERLANG(_h)->regname), &argbuf, &retbuf); ei_x_free(&argbuf); if (retcode<0) { if(retbuf.buff) shm_free(retbuf.buff); return retcode; } // we have a tuple there: ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &i); x=retbuf.index; ei_skip_term(retbuf.buff, &x); LM_DBG("erlang_srdb1_query: position of end of field list should be %d\n",x); //first is list of 5-element tuples containing name and type of field ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_cols); LM_DBG("erlang_srdb1_query: length -f field_list is %d\n",n_cols); res=db_new_result(); if (db_allocate_columns(res, n_cols) != 0) { LM_ERR("erlang_srdb1_query: db_allocate_columns failed\n"); goto error; } RES_COL_N(res) = n_cols; for(i=0; i < n_cols; i++) { x=retbuf.index; ei_skip_term(retbuf.buff, &x); LM_DBG("erlang_srdb1_query: position of end of this field should be %d\n",x); ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j); if( j!=5) LM_ERR("erlang_srdb1_query name&type list element tuple is not 5\n"); ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //1 name len=strlen(atom); sname = (str*)pkg_malloc(sizeof(str)+len+1); if (!sname) { LM_ERR("no private memory left\n"); goto error; } sname->len = len; sname->s = (char*)sname + sizeof(str); memcpy(sname->s, atom, len); sname->s[len] = '\0'; RES_NAMES(res)[i] = sname; LM_DBG("decoded header %d, fieled 1: %s\n",i,atom); ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //2 type atom if(strcmp("int",atom)==0) { RES_TYPES(res)[i]=DB1_INT; } if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_STRING; } if(strcmp("float",atom)==0) { RES_TYPES(res)[i]=DB1_DOUBLE; } if(strcmp("datetime",atom)==0) { RES_TYPES(res)[i]=DB1_DATETIME; } // if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_BLOB; } ei_skip_term(retbuf.buff, &(retbuf.index)); //3 size (ignored) ei_skip_term(retbuf.buff, &(retbuf.index)); //4 default value (ignored) ei_skip_term(retbuf.buff, &(retbuf.index)); //3 null status (ignored) LM_DBG("end of %d record: %d\n",i,retbuf.index); } ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail, LM_DBG("erlang_srdb1_query: position after scanning is %d\n",retbuf.index); //now rows, list of tuples ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_rows); LM_DBG("erlang_srdb1_query values list size is %d\n",n_rows); if (n_rows<=0) { LM_DBG("erlang_srdb1_query no rows returned\n"); RES_ROWS(res) = NULL; RES_NUM_ROWS(res)=0; *_r=res; return 0; } RES_NUM_ROWS(res)=n_rows; rows = pkg_realloc(rows, sizeof(db_row_t) * n_rows); if (rows == NULL) { LM_ERR("erlang_srdb1_query: pkg_realloc rows failed\n"); goto error; } RES_ROWS(res) = rows; for(i=0; i < n_rows; i++) { RES_ROW_N(res)=i+1; row = &RES_ROWS(res)[i]; if (db_allocate_row(res, row) != 0) { LM_ERR("erlang_srdb1_query: db_allocate_row failed for row %d\n",i); goto error; } ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j); if(j!=n_cols) { LM_ERR("erlang_srdb1_query: mismatch:values list element tuple size is %d n_cols from header was %d\n",j, n_cols); } for (j = 0, val = ROW_VALUES(row); j < RES_COL_N(res); j++, val++) { VAL_TYPE(val) = RES_TYPES(res)[j]; VAL_NULL(val) = 0; VAL_FREE(val) = 0; retcode=ei_get_type_internal(retbuf.buff, &(retbuf.index), &ei_type, &size); if (retcode < 0) { LM_ERR("erlang_srdb1_query: error getting type for element %d %d\n",i,j); goto error; } LM_DBG("erlang_srdb1_query: element %d %d ei_type=%d size=%d\n",i,j,ei_type, size); switch(ei_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: retcode=ei_decode_long(retbuf.buff, &(retbuf.index), &VAL_INT(val)); if(retcode < 0) goto error; LM_DBG("decoded interger %d\n",VAL_INT(val)); break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: retcode=ei_decode_double(retbuf.buff, &(retbuf.index), &VAL_DOUBLE(val)); if(retcode < 0) goto error; LM_DBG("decoded float %f\n",VAL_DOUBLE(val)); break; case ERL_ATOM_EXT: case ERL_SMALL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_UTF8_EXT: p=pkg_malloc(size+1); if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; } retcode=ei_decode_atom(retbuf.buff, &(retbuf.index), p); if(retcode < 0) { pkg_free(p); goto error; } LM_DBG("decoded small_atom_utf %s\n",p); VAL_STRING(val)=p; VAL_FREE(val)=1; break; case ERL_STRING_EXT: p=pkg_malloc(size+1); if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; } retcode=ei_decode_string(retbuf.buff, &(retbuf.index), p); if(retcode < 0) { pkg_free(p); goto error; } LM_DBG("decoded string %s\n",p); VAL_STRING(val)=p; VAL_FREE(val)=1; break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: LM_DBG("got tuple)\n"); if (VAL_TYPE(val)==DB1_DATETIME) { struct tm tm; LM_DBG("and col type is datetime\n"); retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_year);tm.tm_year -=1900; if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mon); tm.tm_mon -=1; if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mday); if(retcode < 0) goto error; retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_hour); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_min); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_sec); if(retcode < 0) goto error; VAL_TIME(val)=mktime(&tm); break; } LM_ERR("erlang_srdb1_query: got tuple but valtype is not datetime element %d in row %d in response\n",j,i); break; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: case ERL_PORT_EXT: case ERL_PID_EXT: case ERL_NIL_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: case ERL_NEW_FUN_EXT: case ERL_FUN_EXT: default: LM_ERR("erlang_srdb1_query: don't know how to handle element %d in row %d in response\n",j,i); } } } ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail, *_r=res; return 0; error: if (res) db_free_result(res); LM_ERR("erlang_srdb1_query: Failed\n"); return -1; }