Пример #1
0
/* 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;
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
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;
			
			
			
	}
	
	
}
Пример #5
0
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;
    }
}
Пример #6
0
	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++;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
int next_double(GEOSCommand *command, double *value) {
        return ei_decode_double(command->param_bytes, &command->index, value);
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
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;
}