Ejemplo n.º 1
0
    int ObjectBlueprint::decodePropList( const char* data, 
                                         int* idx, 
                                         PropList* output )
    {
        int count = 0;

        if( !data || !idx || ei_decode_list_header(data, idx, &count) ){
            return -EINVAL;
        }   
   
        //Walk the list of given properties
        for( int i = 0; i < count; i++ ){
            int arity = 0;
            std::string prop = "";
            boost::any val;
    
            //Every prop must be of the form {name:string, prop:varies}
            if( ei_decode_tuple_header(data, idx, &arity) ||
                (arity != 2) ||
                Ymir::decodeString(data, idx, &prop) )
            {
                Core::getSingletonPtr()->logCritical("Failed to decode property name!");
                return -EINVAL;
            }
 

            //Lookup the prop in the blueprint's map
            Blueprint::iterator it;

            if( ((it = mBlueprint.find(prop)) == mBlueprint.end()) ||
                !(it->second.first) )
            {
                Core::getSingletonPtr()->logCritical("No decoding function specified for prop: " + prop);
                return -EINVAL;
            }

            //If the entry and its decode function are defined 
            //then call the decodeFP. Otherwise, error.
            if( it->second.first(data, idx, &val) ){

                Core::getSingletonPtr()->logCritical("Failed to decode property: " + prop);
                return -EINVAL;
            }
            
            //Add the entry to the output
            output->insert(PropListEntry(prop, val));
        }
    
        //Decode end of list
        if( count && ei_decode_list_header(data, idx, &count) ){
            return -EINVAL;
        }

        return 0;
    }
Ejemplo n.º 2
0
int find_first_gteq(char* buf, int pos, void* key, compare_info* lu, int at_least)
{
    int list_arity, inner_arity;
    int list_pos = 0, cmp_val;
    off_t pair_pos = 0;
    if(ei_decode_list_header(buf, &pos, &list_arity) < 0)
    {
        return ERROR_PARSE;
    }
    while(list_pos < list_arity)
    {
        //{<<"key", some other term}
        pair_pos = pos; //Save pos of kv/kp pair tuple

        if(ei_decode_tuple_header(buf, &pos, &inner_arity) < 0)
        {
            return ERROR_PARSE;
        }

        lu->last_cmp_key = (*lu->from_ext)(lu, buf,pos);
        cmp_val = (*lu->compare) (lu->last_cmp_key, key);
        lu->last_cmp_val = cmp_val;
        lu->list_pos = list_pos;
        if(cmp_val >= 0 && list_pos >= at_least)
        {
            break;
        }
        ei_skip_term(buf, &pos); //skip over the key
        ei_skip_term(buf, &pos); //skip over the value
        list_pos++;
    }
    return pair_pos;
}
Ejemplo n.º 3
0
static int
update_list(struct exmpp_hashtable *kl, const char *buf, int *index)
{
	int nb_items, i, type, item_len;
	char item[MAXATOMLEN];

	/* We check that we have a real list. */
	if (ei_decode_list_header(buf, index, &nb_items) != 0)
		return (-1);

	if (nb_items < 0)
		return (0);

	for (i = 0; i < nb_items; ++i) {
		/* Decode the item. */
		if (ei_get_type(buf, index, &type, &item_len) != 0)
			return (-1);
		if (ei_decode_atom(buf, index, item) != 0)
			return (-1);

		/* Add it to the list. */
		if (!exmpp_ht_exists(kl, item, item_len))
			exmpp_ht_store(kl, item, item_len, &DUMMY);
	}

	return (0);
}
Ejemplo n.º 4
0
int mr_push_kv_range(char* buf, int pos, int bound, int end, couchfile_modify_result *dst)
{
    int current = 0;
    int term_begin_pos;
    ei_decode_list_header(buf, &pos, NULL);
    int errcode = 0;
    while(current < end && errcode == 0)
    {
        term_begin_pos = pos;
        ei_skip_term(buf, &pos);
        if(current >= bound)
        { //Parse KV pair into a leaf_value
            couchfile_leaf_value *lv = malloc(sizeof(couchfile_leaf_value));

            lv->term.buf = buf+term_begin_pos;
            lv->term.size = pos-term_begin_pos;

            nodelist* n = make_nodelist();
            dst->values_end->next = n;
            dst->values_end = n;
            n->value.leaf = lv;

            dst->node_len += lv->term.size;
            dst->count++;
            errcode = maybe_flush(dst);
        }
        current++;
    }
    return errcode;
}
Ejemplo n.º 5
0
int my_decode_list_header(const char *buf, int *index, struct my_obj* obj)
{
    int ret = ei_decode_list_header(buf, index, &obj->u.arity);
    if (ret == 0 && obj) {
        obj->nterms = obj->u.arity + 1;
    }
    return ret;
}
Ejemplo n.º 6
0
void terms_to_coordseq(GEOSCommand *command) {
        char *buffer = command->param_bytes;
        int *index = &command->index;
        int size;
	GEOSCoordSequence *coordSeq = NULL;
	
	GEOSContextHandle_t handle = command->driver_data->handle;
        
	if(ei_decode_list_header(buffer, index, &size)) {
          	erl_send_error(command, "notalist");
		return;
	}

	unsigned int i;
	for(i = 0; i < size; i++) {
		//for each element
		int digitc;
		double x,y,z;

		if(ei_decode_tuple_header(buffer, index, &digitc)) {
          		erl_send_error(command, "invalidlist");
			if(coordSeq!=NULL) GEOSCoordSeq_destroy_r(handle, coordSeq);
			return;
        	}
		
		if(coordSeq == NULL) {
			coordSeq = GEOSCoordSeq_create_r(handle, size, digitc);
			if(coordSeq == NULL) {
				erl_send_error(command, "create");
				return;
			}
		}
		
		if(next_number(command, &x) || GEOSCoordSeq_setX_r(handle, coordSeq, i, x)==0) {
			erl_send_error(command, "setx");
			GEOSCoordSeq_destroy_r(handle, coordSeq);
			return;

		}	
		if(next_number(command, &y) || GEOSCoordSeq_setY_r(handle, coordSeq, i, y)==0) {
			erl_send_error(command, "sety");
			GEOSCoordSeq_destroy_r(handle, coordSeq);
			return;

		}
		if(digitc == 3) {
			if(next_number(command, &z) || GEOSCoordSeq_setZ_r(handle, coordSeq, i, z)==0) {
				erl_send_error(command, "setz");
				GEOSCoordSeq_destroy_r(handle, coordSeq);
				return;

			}
		}
	}
	ERL_WRITE_PTR_GEOSCOORDSEQUENCE(command, coordSeq);
}
Ejemplo n.º 7
0
static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf)
{
	char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
	int headerlength;

	if (ei_decode_string_or_binary(buf->buff, &buf->index, SWITCH_UUID_FORMATTED_LENGTH, uuid) ||
		ei_decode_list_header(buf->buff, &buf->index, &headerlength)) {
		ei_x_encode_tuple_header(rbuf, 2);
		ei_x_encode_atom(rbuf, "error");
		ei_x_encode_atom(rbuf, "badarg");
	} else {
		switch_core_session_t *session;
		if (!zstr_buf(uuid) && (session = switch_core_session_locate(uuid))) {
			switch_event_t *event;
			if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) {

				char key[1024];
				char value[1024];
				int i = 0;
				switch_bool_t fail = SWITCH_FALSE;
				while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) {
					i++;
					if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) {
						fail = SWITCH_TRUE;
						break;
					}
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value);
				}

				if (headerlength != i || fail) {
					ei_x_encode_tuple_header(rbuf, 2);
					ei_x_encode_atom(rbuf, "error");
					ei_x_encode_atom(rbuf, "badarg");
				} else {
					if (switch_core_session_queue_private_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
						ei_x_encode_atom(rbuf, "ok");
					} else {
						ei_x_encode_tuple_header(rbuf, 2);
						ei_x_encode_atom(rbuf, "error");
						ei_x_encode_atom(rbuf, "badmem");
					}

				}
			}
			/* release the lock returned by session locate */
			switch_core_session_rwunlock(session);

		} else {
			ei_x_encode_tuple_header(rbuf, 2);
			ei_x_encode_atom(rbuf, "error");
			ei_x_encode_atom(rbuf, "nosession");
		}
	}
	return SWITCH_STATUS_SUCCESS;
}
Ejemplo n.º 8
0
    int
alcove_decode_list_header(const char *buf, size_t len, int *index, int *size)
{
    int type = 0;
    int arity = 0;

    if (alcove_get_type(buf, len, index, &type, &arity) < 0)
        return -1;

    return ei_decode_list_header(buf, index, size);
}
Ejemplo n.º 9
0
static int
decode_list(ei_x_buff *eip, int *index)
{
    int err;
    int arity;

    err = ei_decode_list_header(eip->buff, index, &arity);
    if (err < 0) {
        msg_warn("cannot decode response list");
        return err;
    }
    return arity;
}
Ejemplo n.º 10
0
bool decodeDBString (char* erlBuf, int* pIndex, unsigned char* outBuf, int bufLen, long* outLen)
{
    int type, size;
    long long integerValue;

    if (ei_decode_list_header(erlBuf, pIndex, &size) == 0 && size < bufLen /2) {
        for (int i = 0; i < size; ++i) {
            if (decodeInteger(erlBuf, pIndex, &integerValue)) {
                outBuf[i * 2] = ((unsigned short)integerValue) >> 8;
                outBuf[i * 2 + 1] = ((unsigned short)integerValue) & 0x00ff;
            } else {
                return false;
            }
        }
Ejemplo n.º 11
0
static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf)
{
	char ename[MAXATOMLEN + 1];
	char esname[MAXATOMLEN + 1];
	int headerlength;

	memset(esname, 0, MAXATOMLEN);

	if (ei_decode_atom(buf->buff, &buf->index, ename) ||
		(!strncasecmp(ename, "CUSTOM", MAXATOMLEN) &&
		 ei_decode_atom(buf->buff, &buf->index, esname)) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) {
		ei_x_encode_tuple_header(rbuf, 2);
		ei_x_encode_atom(rbuf, "error");
		ei_x_encode_atom(rbuf, "badarg");
	} else {
		switch_event_types_t etype;
		if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) {
			switch_event_t *event;
			if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) ||
				switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) {
				char key[1024];
				char value[1024];
				int i = 0;
				switch_bool_t fail = SWITCH_FALSE;

				while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) {
					i++;
					if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) {
						fail = SWITCH_TRUE;
						break;
					}

					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value);
				}

				if (headerlength != i || fail) {
					ei_x_encode_tuple_header(rbuf, 2);
					ei_x_encode_atom(rbuf, "error");
					ei_x_encode_atom(rbuf, "badarg");
				} else {
					switch_event_fire(&event);
					ei_x_encode_atom(rbuf, "ok");
				}
			}
		}
	}
	return SWITCH_STATUS_SUCCESS;
}
Ejemplo n.º 12
0
void mr_push_kp_range(char* buf, int pos, int bound, int end, couchfile_modify_result *dst)
{
    DBG("Moving items %d - %d into result.\r\n", bound, end);
    int current = 0;
    ei_decode_list_header(buf, &pos, NULL);
    while(current < end)
    {
        if(current >= bound)
        {
            DBG("   .... %d\r\n", current);
            mr_push_pointerinfo(read_pointer(buf,pos), dst);
        }
        ei_skip_term(buf, &pos);
        current++;
    }
}
Ejemplo n.º 13
0
void do_call(char *pid, int index, char *buf) {
  char m[MAXATOMLEN];
  char f[MAXATOMLEN];
  long a;
  int arity;

  if(ei_decode_tuple_header(buf, &index, &arity) || (arity != 3))
    return;
  if(ei_decode_atom(buf, &index, m))
    return;
  if(ei_decode_atom(buf, &index, f))
    return;
  
  if(ei_decode_long(buf, &index, &a)) {
    if(ei_decode_list_header(buf, &index, &arity))
      return;
    a = arity;
  }

  erts_printf("%s call %s/%s/%d\n", pid, m, f, a);
}
Ejemplo n.º 14
0
static gboolean make_reply(ei_x_buff *xbuf, char *buff, int *index) {
  int k;
  gint arity;
  gchar cmd[MAXATOMLEN+1];
  gboolean (*funcp)(int, ei_x_buff *, char *, int *);
  
  if ( ! ((arity = gn_get_tuple(xbuf, buff, index)) > -1) ||
       ! gn_check_arity(xbuf,2,arity)  ||
       ! gn_get_arg_gchar_fix(xbuf, buff, index, cmd) ||
       ! ((arity = gn_get_list(xbuf, buff, index)) > -1) )
    return FALSE;
  
  if ( get_fpointer(cmd, xbuf, (gpointer *)&funcp) &&
       (*funcp)(arity, xbuf, buff, index) ) {
    g_assert( ei_decode_list_header(buff,index,&k) == 0 );
    g_assert( k == 0 );
    return TRUE;
  }
  
  return FALSE;
}
Ejemplo n.º 15
0
int ei_decode_alloc_string(char *buff, int *index, unsigned char **str, int *len) {
    int type = 0;
    EI(ei_get_type(buff, index, &type, len));
    if(type == ERL_STRING_EXT) {
        *str = genq_alloc((sizeof(unsigned char))*(*len+1));
        EIC(ei_decode_string_safe(buff, index, *str), free_alloc_string(str, len));
        return 0;
    } else if(type == ERL_LIST_EXT ||
            type == ERL_NIL_EXT) {
        // String larger than 65535
        int arity = 0;
        EI(ei_decode_list_header(buff, index, &arity));
        *str = genq_alloc((sizeof(unsigned char))*(*len+1));
        int i;
        for(i=0; i < *len; ++i) {
            EIC(ei_decode_char_safe(buff, index, &(*str)[i]), free_alloc_string(str, len));
        }
        (*str)[*len] = '\0';
        if(arity > 0) {
            EIC(ei_skip_term(buff, index), free_alloc_string(str, len)); // skip tail
        }

        return 0;
    } else if(type == ERL_ATOM_EXT) {
        *str = genq_alloc(sizeof(unsigned char)*(*len+1));
        (*str)[*len] = '\0';
        EIC(ei_decode_atom_safe(buff, index, *str), free_alloc_string(str, len));
        return 0;
    } else if(type == ERL_BINARY_EXT) {
        *str = genq_alloc(sizeof(unsigned char)*(*len+1));
        (*str)[*len] = '\0';
        long llen = 0;
        EIC(ei_decode_binary(buff, index, *str, &llen), free_alloc_string(str, len));
        return 0;
    } else {
        LOG("ERROR unknown type %d\n", type);
        *len = -1;
        return -1;
    }
}
Ejemplo n.º 16
0
int next_geometry_list(GEOSCommand *command, GEOSGeometry*** geom) {
	int geoc;
	int i;

	
	if(ei_decode_list_header(command->param_bytes,&command->index, &geoc)) {
		return -1;
	}

	GEOSGeometry** geomlist = (GEOSGeometry **) malloc(geoc * sizeof(GEOSGeometry*));

	if(*geom == NULL) return -1;
	for(i = 0; i < geoc; i++) {
		if(next_geometry(command, &geomlist[i])) {
			free(geomlist);
			return -1;
		}
	}
	*geom = geomlist;

	return 0;
}
Ejemplo n.º 17
0
static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command,
                            char *buf, ErlDrvSizeT, char **rbuf, ErlDrvSizeT) {

  driver_data_t *data = (driver_data_t *)drv_data;

  ei_x_buff x;

  ei_x_new_with_version(&x);

  switch ((TPCE::eCommand)command) {
  case TPCE::CMD_ALL_INIT:
    {
      int index = 0, version, arity;
      char atom[MAXATOMLEN+1];
      bool found = true;

      ei_decode_version(buf, &index, &version);
      ei_decode_list_header(buf, &index, &arity);

      for (int size = arity, i = 0; found && i < size; i++) {

        ei_decode_tuple_header(buf, &index, &arity);

        if (2 == arity) {

          ei_term term;

          ei_decode_atom(buf, &index, atom);
          ei_decode_ei_term(buf, &index, &term);

          if (0 == strcmp(atom, "id")) {
            data->id = term.value.i_val;
          } else if (0 == strcmp(atom, "path") && ERL_STRING_EXT == term.ei_type) {
            char v[term.size+1];
            ei_decode_string(buf, &index, v);
            strncpy(data->path, v, sizeof(data->path));
          } else if (0 == strcmp(atom, "path") && ERL_BINARY_EXT == term.ei_type) {
            char v[term.size+1];
            long l = term.size;
            ei_decode_binary(buf, &index, v, &l); v[l] = '\0';
            strncpy(data->path, v, sizeof(data->path));
          } else if (0 == strcmp(atom, "configured_customer_count")) {
            data->configured_customer_count = term.value.i_val;
          } else if (0 == strcmp(atom, "active_customer_count")) {
            data->active_customer_count = term.value.i_val;
          } else if (0 == strcmp(atom, "scale_factor")) {
            data->scale_factor = term.value.i_val;
          } else if (0 == strcmp(atom, "days_of_initial_trades")) {
            data->days_of_initial_trades = term.value.i_val;
          } else {
            found = false;
          }
        }
      }

      if (found) {
        ei_x_encode_atom(&x, "ok");
      } else {
        ergen_drv_encode_error1(&x, "badmatch", atom);
      }
    }
    break;
  case TPCE::CMD_ALL_CONFIG:
    {
      ei_x_encode_atom(&x, "ok");
    }
    break;
  case TPCE::CMD_ALL_ALLOC:
    {
      void *ptr = ergen_driver_new(data);

      if (NULL != ptr) {

        data->driver = ptr;

        ei_x_encode_atom(&x, "ok");

      } else {
        ergen_drv_encode_error0(&x, "nomem");
      }
    }
    break;
  case TPCE::CMD_ALL_FREE:
    {
      void *ptr = data->driver;

      if (NULL != ptr) {
        ergen_driver_delete(ptr);
        data->driver = NULL;
      }

      ei_x_encode_atom(&x, "ok");
    }
    break;
  default:
    {
      ergen_drv_encode_error0(&x, "badarg");
    }
    break;
  }

  ErlDrvSizeT result = x.index;
  *rbuf = (char *)ergen_drv_bindup(x.buff, result);

  ei_x_free(&x);

  return result;
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
0
int modify_node(couchfile_modify_request *rq, couchfile_pointer_info *nptr,
                int start, int end, couchfile_modify_result *dst)
{
    eterm_buf current_node;
    int curnode_pos = 0;
    int read_size = 0;
    int list_start_pos = 0;
    int node_len = 0;
    int node_bound = 0;
    int errcode = 0;
    int kpos = 0;

    char node_type[MAXATOMLEN + 1];
    node_type[0] = 0;

    DBG("Enter modify_node. %d - %d\r\n", start, end);

    if(start == end)
    {
        return 0;
    }

    if(nptr == NULL)
    {
        current_node = empty_root;
    }
    else
    {
        if((read_size = pread_bin(rq->fd, nptr->pointer, &current_node.buf)) < 0)
        {
            return ERROR_READ_FILE;
        }
        current_node.size = read_size;
        DBG("... read node from %d\r\n", nptr->pointer);
        curnode_pos++; //Skip over 131.
    }

    couchfile_modify_result *local_result = make_modres(rq);

    ei_decode_tuple_header(current_node.buf, &curnode_pos, NULL);
    if(ei_decode_atom(current_node.buf, &curnode_pos, node_type) < 0)
    {
        errcode = ERROR_PARSE;
        goto cleanup;
    }
    list_start_pos = curnode_pos;
    if(ei_decode_list_header(current_node.buf, &curnode_pos, &node_len) < 0)
    {
        errcode = ERROR_PARSE;
        goto cleanup;
    }

    if(strcmp("kv_node", node_type) == 0)
    {
        local_result->node_type = KV_NODE;
        while(start < end)
        {
            DBG("act on kvnode item\r\n");
            if(node_bound >= node_len)
            { //We're at the end of a leaf node.
                DBG("   ... exec action at end!\r\n");
                switch(rq->actions[start].type)
                {
                    case ACTION_INSERT:
                        local_result->modified = 1;
                        mr_push_action(&rq->actions[start], local_result);
                    break;

                    case ACTION_REMOVE:
                        local_result->modified = 1;
                    break;

                    case ACTION_FETCH:
                        if(rq->fetch_callback)
                        {
                            //not found
                            (*rq->fetch_callback)(rq, rq->actions[start].key, NULL);
                        }
                    break;
                }
                start++;
            }
            else
            {
                kpos = find_first_gteq(current_node.buf, list_start_pos,
                        rq->actions[start].cmp_key,
                        &rq->cmp, node_bound);

                if(kpos < 0)
                {
                    errcode = ERROR_PARSE;
                    goto cleanup;
                }

                //Add items from node_bound up to but not including the current
                mr_push_kv_range(current_node.buf, list_start_pos, node_bound,
                        rq->cmp.list_pos, local_result);

                if(rq->cmp.last_cmp_val > 0) // Node key > action key
                {
                    DBG("   Inserting action before\r\n");
                    switch(rq->actions[start].type)
                    {
                        case ACTION_INSERT:
                            local_result->modified = 1;
                            mr_push_action(&rq->actions[start], local_result);
                        break;

                        case ACTION_REMOVE:
                            local_result->modified = 1;
                        break;

                        case ACTION_FETCH:
                            if(rq->fetch_callback)
                            {
                                //not found
                                (*rq->fetch_callback)(rq, rq->actions[start].key, NULL);
                            }
                        break;
                    }

                    start++;
                    node_bound = rq->cmp.list_pos;
                }
                else if(rq->cmp.last_cmp_val < 0) // Node key < action key
                {
                    DBG("   -- Continue with this action\r\n");
                    node_bound = rq->cmp.list_pos + 1;
                    mr_push_kv_range(current_node.buf, list_start_pos, node_bound - 1,
                            node_bound, local_result);
                }
                else //Node key == action key
                {
                    DBG("   Replacing value with action\r\n");
                    switch(rq->actions[start].type)
                    {
                        case ACTION_INSERT:
                            local_result->modified = 1;
                            mr_push_action(&rq->actions[start], local_result);
                            node_bound = rq->cmp.list_pos + 1;
                        break;

                        case ACTION_REMOVE:
                            local_result->modified = 1;
                            node_bound = rq->cmp.list_pos + 1;
                        break;

                        case ACTION_FETCH:
                            if(rq->fetch_callback)
                            {
                                eterm_buf cb_tmp;
                                int cb_vpos = kpos;
                                ei_decode_tuple_header(current_node.buf, &cb_vpos, NULL);
                                ei_skip_term(current_node.buf, &cb_vpos);
                                cb_tmp.buf = current_node.buf + cb_vpos;
                                cb_tmp.size = cb_vpos;
                                ei_skip_term(current_node.buf, &cb_vpos);
                                cb_tmp.size = cb_vpos - cb_tmp.size;
                                (*rq->fetch_callback)(rq, rq->actions[start].key, &cb_tmp);
                            }
                            node_bound = rq->cmp.list_pos;
                        break;
                    }
                    start++;
                }
            }
        }
        //Push any items past the end of what we dealt with onto result.
        if(node_bound < node_len)
        {
            mr_push_kv_range(current_node.buf, list_start_pos, node_bound,
                    node_len, local_result);
        }
    }
    else if(strcmp("kp_node", node_type) == 0)
    {
        local_result->node_type = KP_NODE;
        while(start < end)
        {
            kpos = find_first_gteq(current_node.buf, list_start_pos,
                    rq->actions[start].cmp_key,
                    &rq->cmp, node_bound);

            if(kpos < 0)
            {
                errcode = ERROR_PARSE;
                goto cleanup;
            }

            if(rq->cmp.list_pos == (node_len - 1)) //got last item in kp_node
            {
                //Push all items in node onto mr
                mr_push_kp_range(current_node.buf, list_start_pos, node_bound,
                        rq->cmp.list_pos, local_result);
                DBG("  ...descending into final item of kpnode\r\n");
                couchfile_pointer_info *desc = read_pointer(current_node.buf, kpos);
                errcode = modify_node(rq, desc, start, end, local_result);
                if(local_result->values_end->value.pointer != desc)
                {
                        free(desc);
                }

                if(errcode < 0)
                {
                    goto cleanup;
                }
                node_bound = node_len;
                break;
            }
            else
            {
                //Get all actions with key <= the key of the current item in the
                //kp_node

                //Push items in node up to but not including current onto mr
                mr_push_kp_range(current_node.buf, list_start_pos, node_bound,
                        rq->cmp.list_pos - 1, local_result);
                int range_end = start;
                while(range_end < end &&
                      ((*rq->cmp.compare)(rq->actions[range_end].cmp_key, rq->cmp.last_cmp_key) <= 0))
                {
                    range_end++;
                }

                DBG("  ...descending into item %d of kpnode\r\n", rq->cmp.list_pos);
                node_bound = rq->cmp.list_pos + 1;
                couchfile_pointer_info *desc = read_pointer(current_node.buf, kpos);
                errcode = modify_node(rq, desc, start, range_end, local_result);
                if(local_result->values_end->value.pointer != desc)
                {
                        free(desc);
                }
                if(errcode < 0)
                {
                    goto cleanup;
                }
                start = range_end;
            }
        }
        DBG(".. Finished kp node, up to %d\r\n", node_bound);
        if(node_bound < node_len)
        {
            //Processed all the actions but haven't exhausted this kpnode.
            //push the rest of it onto the mr.
            mr_push_kp_range(current_node.buf, list_start_pos, node_bound, node_len,
                    local_result);
        }
    }
    else
    {
        errcode = ERROR_PARSE;
        goto cleanup;
    }
    //If we've done modifications, write out the last leaf node.
    errcode = flush_mr(local_result);
    if(errcode == 0)
    {
        if(!local_result->modified && nptr != NULL)
        {
            //If we didn't do anything, give back the pointer to the original
            mr_push_pointerinfo(nptr, dst);
        }
        else
        {
            //Otherwise, give back the pointers to the nodes we've created.
            dst->modified = 1;
            errcode = mr_move_pointers(local_result, dst);
        }
    }
cleanup:
    free_modres(local_result);

    if(current_node.buf != empty_root.buf)
    {
        free(current_node.buf);
    }

    return errcode;
}
Ejemplo n.º 20
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;
    }
}
Ejemplo n.º 21
0
/* Scratch function */
int oe_ei_decode_wstring(const char *buf, int *index, CORBA_wchar *p) {

  int length,error_code,type,tmp=0;
  char * tmp_space = NULL;


  if ((error_code = ei_get_type(buf, index, &type, &length)) < 0)
    return error_code;
  
  switch(type) {
    
  case ERL_LIST_EXT: /* A list */
  case ERL_NIL_EXT: /* An empty list */
    
    if (p) { /* Decoding part */

      if ((error_code = ei_decode_list_header(buf, index, &length)) < 0) 
	return error_code;
      
      if (length != 0) {
	for(tmp = 0; tmp < length; tmp++) 
	  if ((error_code = oe_ei_decode_wchar(buf, index, &(p[tmp]))) < 0)
	    return error_code;

	/* Read list tail also */
	if ((error_code = ei_decode_list_header(buf, index, &length)) < 0) 
	  return error_code;
      }
      
      p[tmp] = 0;   /* Wide NULL */
	
    } else { /* Allocation counting part */

      if ((error_code = ei_decode_list_header(buf, index, &length)) < 0) 
	return error_code;
      
      if (length != 0) {
	for(tmp = 0; tmp < length; tmp++) 
	  if ((error_code = oe_ei_decode_wchar(buf, index, 0)) < 0)
	    return error_code;

	/* Read list tail also */
	if ((error_code = ei_decode_list_header(buf, index, &length)) < 0) 
	  return error_code;
      }
    }
    
    break;

  case ERL_STRING_EXT: /* A string */

    if (p) { /* Decoding part */
      
      /* Allocate temporary string */
      tmp_space = (char*) malloc(length*(__OE_WCHARSZ__+1));

      if ((error_code = ei_decode_string(buf, index, tmp_space)) < 0)
	return error_code;
      
      /* Assign characters to wide characters */
      for(tmp = 0; tmp < length; tmp++)
	p[tmp] = tmp_space[tmp];
      
      p[tmp] = 0; /* Wide NULL */
      
      /* Free temporary string */
      CORBA_free(tmp_space);

    } else { /* Allocation counting part */
      
      if ((error_code = ei_decode_string(buf, index, 0)) < 0)
	return error_code;

    }
    break;

  default: /* Bad header */
    return -1; 
  }

  return 0;
}
Ejemplo n.º 22
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;
			
			
			
	}
	
	
}
Ejemplo n.º 23
0
static bool
decode_proplist(void *port, PropList **plist, int *szalloc,
                const char *buf, int *index) {
    int type, size;
    long item_type;
    bool succeess = false;
    PropList *list_head = (*plist = plist_alloc(port, szalloc));
    if (DECODED(ei_get_type(buf, index, &type, &size))) {
        int list_arity = 0;
        if (DECODED(ei_decode_list_header(buf, index, &list_arity))) {
            ASSERT(size == list_arity);
            if (list_arity < 1) {
                succeess = false;
            } else {
                for (int i = 0; i < list_arity; i++) {
                    if (!DECODED(ei_decode_tuple_header(buf, index, &size))) {
                        return false;
                    }
                    if ((list_head->next = plist_alloc(port, szalloc)) != NULL) {
                        *plist = (list_head = list_head->next);
                        list_head->type = EDBC_OCI_DRV_TYPE_UNASSIGNED;
                        char *pkey = safe_driver_alloc(port, sizeof(char) * MAXATOMLEN);
                        
                        if (!DECODED(ei_decode_atom(buf, index, pkey))) {
                            return false;
                        } 
                        
                        list_head->name = pkey;
                        
                        if (!DECODED(ei_decode_long(buf, index, &item_type))) {
                            return false;
                        }
                        list_head->type = item_type;
                        
                        switch (item_type) {
                        case EDBC_OCI_DRV_TYPE_STRING: {
                            if(!DECODED(ei_get_type(buf, index, &type, &size))) {
                                return false;
                            }
                            ASSERT(type == ERL_STRING_EXT);
                            TextBuffer *ptxt = zalloc(port, sizeof(TextBuffer));
                            char *pval = safe_driver_alloc(port, sizeof(char) * ptxt->size);

                            ptxt->size = size + 1;
                            ptxt->data = pval;
                            list_head->value.buffer = ptxt;
                            if (!DECODED(ei_decode_string(buf, index, pval))) {
                                return false;
                            }
                            break;
                        }
                        case EDBC_OCI_DRV_TYPE_LONG: {
                            long num;
                            if (!DECODED(ei_decode_long(buf, index, &num))) {
                                return false;
                            }
                            list_head->value.number = num;
                            break;
                        }
                        default:
                            // make error?
                            break;
                        }
                    }
                }
            }
        }
    }
    return false;
};
Ejemplo n.º 24
0
static int control(ErlDrvData handle, unsigned int command, char* buf, int count, char** res, int res_size) {
  tcbdb_drv_t *driver = (tcbdb_drv_t*)handle;
  TCBDB *bdb = driver->bdb;

  int index = 1, tp, sz, version;
  char key[MAX_KEY_SIZE], value[MAX_VALUE_SIZE];
  long key_size, value_size;
  long long long_tmp;
  bool rs;
  const char *value_tmp = NULL;

  ei_x_buff x;
  ei_x_new_with_version(&x);
  if (bdb == NULL && command != OPEN)
    return ei_error(&x, "database_not_opened", res, res_size);

  ei_decode_version(buf, &index, &version);

  switch (command) {
    case OPEN:
      // open(Filepath::string())
      if (bdb == NULL) {
        ei_get_type(buf, &index, &tp, &sz);
        if (tp != ERL_STRING_EXT)
          return ei_error(&x, "invalid_argument", res, res_size);

        TCBDB *bdb = tcbdbnew();
        tcbdbsetmutex(bdb);
        tcbdbsetcache(bdb, 104800, 51200);
        tcbdbsetxmsiz(bdb, 1048576);
        tcbdbtune(bdb, 0, 0, 0, 7, -1, BDBTLARGE);

        char *file = driver_alloc(sz + 1);
        ei_decode_string(buf, &index, file);
        rs = tcbdbopen(bdb, file, BDBOWRITER | BDBOCREAT);
        driver_free(file);
        if (!rs)
          return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
        driver->bdb = bdb;
        ei_x_encode_atom(&x, "ok");
      } else
        return ei_error(&x, "database already opened", res, res_size);
      break;

    case CLOSE:
      tcbdbclose(bdb);
      tcbdbdel(bdb);
      driver->bdb = NULL;
      ei_x_encode_atom(&x, "ok");
      break;

    case PUT:
    case PUTDUP:
    case PUTCAT:
    case PUTKEEP:
      // put({Key::binary(), Value::binary()})
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_SMALL_TUPLE_EXT || sz != 2)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_tuple_header(buf, &index, &sz);

      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_binary(buf, &index, &key[0], &key_size);
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT)
        return ei_error(&x, "invalid_argument", res, res_size);
      if (sz <= MAX_VALUE_SIZE) {
        ei_decode_binary(buf, &index, &value[0], &value_size);
        switch (command) {
          case PUT: rs = tcbdbput(bdb, &key[0], key_size, &value[0], value_size); break;
          case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, &value[0], value_size); break;
          case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, &value[0], value_size); break;
          default: rs = tcbdbputkeep(bdb, &key[0], key_size, &value[0], value_size);
        }
      } else {
        void *p = driver_alloc(sz);
        if (p) {
          ei_decode_binary(buf, &index, p, &value_size);
          switch (command) {
            case PUT: rs = tcbdbput(bdb, &key[0], key_size, p, value_size); break;
            case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, p, value_size); break;
            case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, p, value_size); break;
            default: rs = tcbdbputkeep(bdb, &key[0], key_size, p, value_size);
          }
          driver_free(p);
        } else
          return ei_error(&x, "too long value", res, res_size);
      };
      if (!rs)
        return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      ei_x_encode_atom(&x, "ok");
      break;

    case GET:
      // get(Key::binary()) -> {ok, Value} | {error, not_found}
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_binary(buf, &index, &key[0], &key_size);

      value_tmp = tcbdbget3(bdb, &key[0], key_size, &sz);
      ei_x_encode_tuple_header(&x, 2);
      if (value_tmp != NULL) {
        ei_x_encode_atom(&x, "ok");
        ei_x_encode_binary(&x, value_tmp, sz);
      } else {
        ei_x_encode_atom(&x, "error");
        ei_x_encode_atom(&x, "not_found");
      }
      break;

    case GETDUP:
      // get(Key::binary()) -> {ok, Values}
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_binary(buf, &index, &key[0], &key_size);

      TCLIST *vals = tcbdbget4(bdb, key, key_size);
      if (vals) {
        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");
        int j;
        for (j=0; j<tclistnum(vals); j++) {
          value_tmp = tclistval(vals, j, &sz);
          ei_x_encode_list_header(&x, 1);
          ei_x_encode_binary(&x, value_tmp, sz);
        }
        tclistdel(vals);
        ei_x_encode_empty_list(&x);
      } else {
        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");
        ei_x_encode_empty_list(&x);
      }
      break;

    case REMOVE:
      // remove(Keys::list())
      // remove(Key::binary())
      // remove({Key::binary(), Value::binary()})
      ei_get_type(buf, &index, &tp, &sz);
      if (tp == ERL_LIST_EXT) {
        int count, j;
        ei_decode_list_header(buf, &index, &count);
        for (j=0; j<count; j++) {
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_binary(buf, &index, &key[0], &key_size);
          if (!tcbdbout3(bdb, &key[0], key_size))
            return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
        }
        ei_x_encode_atom(&x, "ok");
      } else if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) {
        ei_decode_binary(buf, &index, &key[0], &key_size);
        tcbdbout3(bdb, &key[0], key_size);
        ei_x_encode_atom(&x, "ok");
      } else if (tp == ERL_SMALL_TUPLE_EXT && sz == 2) {
        ei_decode_tuple_header(buf, &index, &sz);
        // get key
        ei_get_type(buf, &index, &tp, &sz);
        if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
          return ei_error(&x, "invalid_argument", res, res_size);
        ei_decode_binary(buf, &index, &key[0], &key_size);
        // get value
        ei_get_type(buf, &index, &tp, &sz);
        if (tp != ERL_BINARY_EXT || sz > MAX_VALUE_SIZE)
          return ei_error(&x, "invalid_argument", res, res_size);
        ei_decode_binary(buf, &index, &value[0], &value_size);
        // remove by key&value
        BDBCUR *cur = tcbdbcurnew(bdb);
        if (!tcbdbcurjump(cur, &key[0], key_size))
          return ei_error(&x, "record_not_found", res, res_size);
        
        bool removed = false, not_found = false;
        while (!removed && !not_found) {
          int cur_key_size, cur_val_size;
          const void *curkey = tcbdbcurkey3(cur, &cur_key_size);
          if (cur_key_size == key_size && memcmp(curkey, key, key_size) == 0) {
            const void *curval = tcbdbcurval3(cur, &cur_val_size);
            if (cur_val_size == value_size && memcmp(curval, value, value_size) == 0) {
              tcbdbcurout(cur);
              removed = true;
            } else
              if (!tcbdbcurnext(cur))
                not_found = true;
          } else not_found = true;
        }
        if (not_found) ei_x_encode_atom(&x, "not_found");
        else ei_x_encode_atom(&x, "ok");
        
      } else
        return ei_error(&x, "invalid_argument", res, res_size);
      break;

    case RANGE:
      /*
       * range({Prefix::binary(), limit:integer()})
       * range({StartKey::binary(), BeginInclusion::boolean(), EndKey::binary(), EndInclusion::binary(), limit:integer()})
       */
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_SMALL_TUPLE_EXT || sz < 2)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_tuple_header(buf, &index, &sz);

      ei_get_type(buf, &index, &tp, &sz);
      if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) {
        char keys[MAX_KEY_SIZE], keyf[MAX_KEY_SIZE];
        long keys_size, keyf_size;
        int keys_inc, keyf_inc;
        long max = -1;
        TCLIST *range;

        ei_decode_binary(buf, &index, &keys[0], &keys_size);
        ei_get_type(buf, &index, &tp, &sz);
        if (tp == ERL_ATOM_EXT) {
          // range
          ei_decode_boolean(buf, &index, &keys_inc);
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_binary(buf, &index, &keyf[0], &keyf_size);
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_ATOM_EXT)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_boolean(buf, &index, &keyf_inc);

          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_INTEGER_EXT)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_long(buf, &index, &max);

          range = tcbdbrange(bdb, &keys[0], keys_size, keys_inc == 1, &keyf[0], keyf_size, keyf_inc == 1, max);
        } else if (tp == ERL_INTEGER_EXT) {
          // prefix
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_INTEGER_EXT)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_long(buf, &index, &max);

          range = tcbdbfwmkeys(bdb, &keys[0], keys_size, max);
        } else
          return ei_error(&x, "invalid_argument", res, res_size);

        const char *key;
        int key_size, value_size;
        int idx, cnt = 0, rcount = tclistnum(range);

        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");

        BDBCUR *cur = tcbdbcurnew(bdb);
        for (idx=0; idx<rcount; idx++) {
          key = tclistval(range, idx, &key_size);
          TCLIST *vals = tcbdbget4(bdb, key, key_size);
          if (vals) {
            int j;
            for (j=0; j<tclistnum(vals); j++) {
              ei_x_encode_list_header(&x, 1);
              value_tmp = tclistval(vals, j, &value_size);
              ei_x_encode_binary(&x, value_tmp, value_size);
              if (max >= 0 && ++cnt >= max) break;
            }
            tclistdel(vals);
          }
          idx++;
        }
        tcbdbcurdel(cur);
        tclistdel(range);
        ei_x_encode_empty_list(&x);

      } else
        return ei_error(&x, "invalid_argument", res, res_size);
      break;

    case SYNC:
      // sync()
      if (!tcbdbsync(bdb))
        return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      ei_x_encode_atom(&x, "ok");
      break;

    case INFO:
      // info()
      ei_x_encode_tuple_header(&x, 3);
      ei_x_encode_atom(&x, "ok");
      long_tmp = tcbdbrnum(bdb);
      ei_x_encode_longlong(&x, long_tmp);
      long_tmp = tcbdbfsiz(bdb);
      ei_x_encode_longlong(&x, long_tmp);
      break;

    case ITERATE:
      // Read(none) -> {ok, Key} | {error, not_found}
      // Read(Key::binary()) -> {ok, Key} | {error, not_found}
      ei_get_type(buf, &index, &tp, &sz);
      BDBCUR *cur = tcbdbcurnew(bdb);
      if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) {
        ei_decode_binary(buf, &index, &key[0], &key_size);
        rs = tcbdbcurjump(cur, &key[0], key_size) && tcbdbcurnext(cur);
      } else
        rs = tcbdbcurfirst(cur);
      if (rs) {
        int key_size;
        const char *key = tcbdbcurkey3(cur, &key_size);

        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");
        ei_x_encode_binary(&x, key, key_size);
        tcbdbcurdel(cur);
      } else {
        tcbdbcurdel(cur);
        return ei_error(&x, "not_found", res, res_size);
      }
      break;

    case VANISH:
      // vanish() -> ok
      if (!tcbdbvanish(bdb))
        return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      ei_x_encode_atom(&x, "ok");
      break;

    case BACKUP:
      // backup(path::string()) -> ok | {error, Reason}
      ei_get_type(buf, &index, &tp, &sz);
      if (tp == ERL_STRING_EXT) {
        char *file = driver_alloc(sz + 1);
        ei_decode_string(buf, &index, file);
        if (tcbdbcopy(driver->bdb, file))
          ei_x_encode_atom(&x, "ok");
        else
          return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      } else
        return ei_error(&x, "invalid_argument", res, res_size);
      break;

    default:
      return ei_error(&x, "invalid_command", res, res_size);
  }

  if (res_size < x.index)
    (*res) = (char *)driver_alloc(x.index);
  int n = x.index;
  memcpy(*res, x.buff, x.index);
  ei_x_free(&x);
  return n;
};
Ejemplo n.º 25
0
int main(void)
#endif
{
  ErlConnect conp;
  Erl_IpAddr thisipaddr = (Erl_IpAddr)0;
  FILE *fp = (FILE *)0;
  char* charp = "foo";
  double *doublep = NULL;
  double doublex = 0.0;
  ei_cnode xec;
  ei_reg *ei_regp = NULL;
  ei_term eterm;
  ei_x_buff eix;
  erlang_big *bigp = NULL;
  erlang_fun efun;
  erlang_msg *msgp = NULL;
  erlang_msg emsg;
  erlang_pid *pidp = NULL;
  erlang_pid epid;
  erlang_port eport;
  erlang_ref eref;
  erlang_trace etrace;
  int *intp = NULL;
  int intx = 0;
  long *longp = NULL;
  long longx = 0;
  short creation = 0;
  struct ei_reg_stat *ei_reg_statp = NULL;
  struct ei_reg_tabstat *ei_reg_tabstatp = NULL;
  struct hostent *hostp = NULL;
  unsigned char * ucharp = (unsigned char *)"foo";
  unsigned long *ulongp = NULL;
  unsigned long ulongx = 0;
  void *voidp = NULL;
#ifndef VXWORKS
  EI_LONGLONG *longlongp = (EI_LONGLONG*)NULL;
  EI_LONGLONG longlongx = 0;
  EI_ULONGLONG *ulonglongp = (EI_ULONGLONG*)NULL;
  EI_ULONGLONG ulonglongx = 0;
#endif
  enum erlang_char_encoding enc;

  intx = erl_errno;

  ei_connect_init(&xec, charp, charp, creation);
  ei_connect_xinit (&xec, charp, charp, charp, thisipaddr, charp, creation);

  ei_connect(&xec, charp);
  ei_xconnect (&xec, thisipaddr, charp);

  ei_receive(intx, ucharp, intx);
  ei_receive_msg(intx, &emsg, &eix);
  ei_xreceive_msg(intx, &emsg, &eix);

  ei_send(intx, &epid, charp, intx);
  ei_reg_send(&xec, intx, charp, charp, intx);

  ei_rpc(&xec, intx, charp, charp, charp, intx, &eix);
  ei_rpc_to(&xec, intx, charp, charp, charp, intx);
  ei_rpc_from(&xec, intx, intx, &emsg, &eix);

  ei_publish(&xec, intx);
  ei_accept(&xec, intx, &conp);
  ei_unpublish(&xec);

  ei_thisnodename(&xec);
  ei_thishostname(&xec);
  ei_thisalivename(&xec);

  ei_self(&xec);

  ei_gethostbyname(charp);
  ei_gethostbyaddr(charp, intx, intx);
  ei_gethostbyname_r(charp, hostp, charp, intx, intp);
  ei_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp);

  ei_encode_version(charp, intp);
  ei_x_encode_version(&eix);
  ei_encode_long(charp, intp, longx);
  ei_x_encode_long(&eix, longx);
  ei_encode_ulong(charp, intp, ulongx);
  ei_x_encode_ulong(&eix, ulongx);
  ei_encode_double(charp, intp, doublex);
  ei_x_encode_double(&eix, doublex);
  ei_encode_boolean(charp, intp, intx);
  ei_x_encode_boolean(&eix, intx);
  ei_encode_char(charp, intp, 'a');
  ei_x_encode_char(&eix, 'a');
  ei_encode_string(charp, intp, charp);
  ei_encode_string_len(charp, intp, charp, intx);
  ei_x_encode_string(&eix, charp);
  ei_x_encode_string_len(&eix, charp, intx);
  ei_encode_atom(charp, intp, charp);
  ei_encode_atom_as(charp, intp, charp, ERLANG_LATIN1, ERLANG_UTF8);
  ei_encode_atom_len(charp, intp, charp, intx);
  ei_encode_atom_len_as(charp, intp, charp, intx, ERLANG_ASCII, ERLANG_LATIN1);
  ei_x_encode_atom(&eix, charp);
  ei_x_encode_atom_as(&eix, charp, ERLANG_LATIN1, ERLANG_UTF8);
  ei_x_encode_atom_len(&eix, charp, intx);
  ei_x_encode_atom_len_as(&eix, charp, intx, ERLANG_LATIN1, ERLANG_UTF8);
  ei_encode_binary(charp, intp, (void *)0, longx);
  ei_x_encode_binary(&eix, (void*)0, intx);
  ei_encode_pid(charp, intp, &epid);
  ei_x_encode_pid(&eix, &epid);
  ei_encode_fun(charp, intp, &efun);
  ei_x_encode_fun(&eix, &efun);
  ei_encode_port(charp, intp, &eport);
  ei_x_encode_port(&eix, &eport);
  ei_encode_ref(charp, intp, &eref);
  ei_x_encode_ref(&eix, &eref);
  ei_encode_trace(charp, intp, &etrace);
  ei_x_encode_trace(&eix, &etrace);
  ei_encode_tuple_header(charp, intp, intx);
  ei_x_encode_tuple_header(&eix, longx);
  ei_encode_list_header(charp, intp, intx);
  ei_x_encode_list_header(&eix, longx);
/* #define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0) */
  ei_x_encode_empty_list(&eix);

  ei_get_type(charp, intp, intp, intp);
  ei_get_type_internal(charp, intp, intp, intp);

  ei_decode_version(charp, intp, intp);
  ei_decode_long(charp, intp, longp);
  ei_decode_ulong(charp, intp, ulongp);
  ei_decode_double(charp, intp, doublep);
  ei_decode_boolean(charp, intp, intp);
  ei_decode_char(charp, intp, charp);
  ei_decode_string(charp, intp, charp);
  ei_decode_atom(charp, intp, charp);
  ei_decode_atom_as(charp, intp, charp, MAXATOMLEN_UTF8, ERLANG_WHATEVER, &enc, &enc);
  ei_decode_binary(charp, intp, (void *)0, longp);
  ei_decode_fun(charp, intp, &efun);
  free_fun(&efun);
  ei_decode_pid(charp, intp, &epid);
  ei_decode_port(charp, intp, &eport);
  ei_decode_ref(charp, intp, &eref);
  ei_decode_trace(charp, intp, &etrace);
  ei_decode_tuple_header(charp, intp, intp);
  ei_decode_list_header(charp, intp, intp);

  ei_decode_ei_term(charp, intp, &eterm);

  ei_print_term(fp, charp, intp);
  ei_s_print_term(&charp, charp, intp);

  ei_x_format(&eix, charp);
  ei_x_format_wo_ver(&eix, charp);

  ei_x_new(&eix);
  ei_x_new_with_version(&eix);
  ei_x_free(&eix);
  ei_x_append(&eix, &eix);
  ei_x_append_buf(&eix, charp, intx);
  ei_skip_term(charp, intp);

  ei_reg_open(intx);
  ei_reg_resize(ei_regp, intx);
  ei_reg_close(ei_regp);

  ei_reg_setival(ei_regp, charp, longx);
  ei_reg_setfval(ei_regp, charp, doublex);
  ei_reg_setsval(ei_regp, charp, charp);
  ei_reg_setpval(ei_regp, charp, voidp, intx);

  ei_reg_setval(ei_regp, charp, intx);

  ei_reg_getival(ei_regp, charp);
  ei_reg_getfval(ei_regp, charp);
  ei_reg_getsval(ei_regp, charp);
  ei_reg_getpval(ei_regp, charp, intp);

  ei_reg_getval(ei_regp, charp, intx);

  ei_reg_markdirty(ei_regp, charp);

  ei_reg_delete(ei_regp, charp);

  ei_reg_stat(ei_regp, charp, ei_reg_statp);

  ei_reg_tabstat(ei_regp, ei_reg_tabstatp);

  ei_reg_dump(intx, ei_regp, charp, intx);
  ei_reg_restore(intx, ei_regp, charp);
  ei_reg_purge(ei_regp);

#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
  {
      mpz_t obj;
      ei_decode_bignum(charp, intp, obj);
      ei_encode_bignum(charp, intp, obj);
      ei_x_encode_bignum(&eix, obj);
  }
#endif /* HAVE_GMP_H && HAVE_LIBGMP */

#ifndef VXWORKS

  ei_decode_longlong(charp, intp, longlongp);
  ei_decode_ulonglong(charp, intp, ulonglongp);
  ei_encode_longlong(charp, intp, longlongx);
  ei_encode_ulonglong(charp, intp, ulonglongx);
  ei_x_encode_longlong(&eix, longlongx);
  ei_x_encode_ulonglong(&eix, ulonglongx);

#endif

#ifdef USE_EI_UNDOCUMENTED

  ei_decode_intlist(charp, intp, longp, intp);

  ei_receive_encoded(intx, &charp, intp, msgp, intp);
  ei_send_encoded(intx, pidp, charp, intx);
  ei_send_reg_encoded(intx, pidp, charp, charp, intx);

  ei_decode_big(charp, intp, bigp);
  ei_big_comp(bigp, bigp);
  ei_big_to_double(bigp, doublep);
  ei_small_to_big(intx, bigp);
  ei_alloc_big(intx);
  ei_free_big(bigp);

#endif /* USE_EI_UNDOCUMENTED */

  return
      BUFSIZ +
      EAGAIN +
      EHOSTUNREACH +
      EIO +
      EI_BIN +
      EI_DELET +
      EI_DIRTY +
      EI_FLT +
      EI_FORCE +
      EI_INT +
      EI_NOPURGE +
      EI_STR +
      EMSGSIZE +
      ENOMEM +
      ERL_ERROR +
      ERL_EXIT +
      ERL_LINK +
      ERL_MSG +
      ERL_NO_TIMEOUT +
      ERL_REG_SEND +
      ERL_SEND +
      ERL_TICK +
      ERL_TIMEOUT +
      ERL_UNLINK +
      ETIMEDOUT +
      MAXATOMLEN;
}
Ejemplo n.º 26
0
static int parse_option_list(const char *req, int *req_index, struct uart_config *config)
{
    int term_type;
    int option_count;
    if (ei_get_type(req, req_index, &term_type, &option_count) < 0 ||
            (term_type != ERL_LIST_EXT && term_type != ERL_NIL_EXT)) {
        debug("expecting option list");
        return -1;
    }

    if (term_type == ERL_NIL_EXT)
        option_count = 0;
    else
        ei_decode_list_header(req, req_index, &option_count);

    // Go through all of the options
    for (int i = 0; i < option_count; i++) {
        int term_size;
        if (ei_decode_tuple_header(req, req_index, &term_size) < 0 ||
                term_size != 2) {
            debug("expecting kv tuple for options");
            return -1;
        }

        char key[16];
        if (ei_decode_atom(req, req_index, key) < 0) {
            debug("expecting atoms for option keys");
            return -1;
        }

        if (strcmp(key, "active") == 0) {
            int val;
            if (ei_decode_boolean(req, req_index, &val) < 0) {
                debug("active should be a bool");
                return -1;
            }
            config->active = (val != 0);
        } else if (strcmp(key, "speed") == 0) {
            long val;
            if (ei_decode_long(req, req_index, &val) < 0) {
                debug("speed should be an integer");
                return -1;
            }
            config->speed = val;
        } else if (strcmp(key, "data_bits") == 0) {
            long val;
            if (ei_decode_long(req, req_index, &val) < 0) {
                debug("data_bits should be an integer");
                return -1;
            }
            config->data_bits = val;
        } else if (strcmp(key, "stop_bits") == 0) {
            long val;
            if (ei_decode_long(req, req_index, &val) < 0) {
                debug("stop_bits should be an integer");
                return -1;
            }
            config->stop_bits = val;
        } else if (strcmp(key, "parity") == 0) {
            char parity[16];
            if (ei_decode_atom(req, req_index, parity) < 0) {
                debug("parity should be an atom");
                return -1;
            }
            if (strcmp(parity, "none") == 0) config->parity = UART_PARITY_NONE;
            else if (strcmp(parity, "even") == 0) config->parity = UART_PARITY_EVEN;
            else if (strcmp(parity, "odd") == 0) config->parity = UART_PARITY_ODD;
            else if (strcmp(parity, "space") == 0) config->parity = UART_PARITY_SPACE;
            else if (strcmp(parity, "mark") == 0) config->parity = UART_PARITY_MARK;
        } else if (strcmp(key, "flow_control") == 0) {
            char flow_control[16];
            if (ei_decode_atom(req, req_index, flow_control) < 0) {
                debug("flow_control should be an atom");
                return -1;
            }
            if (strcmp(flow_control, "none") == 0) config->flow_control = UART_FLOWCONTROL_NONE;
            else if (strcmp(flow_control, "hardware") == 0) config->flow_control = UART_FLOWCONTROL_HARDWARE;
            else if (strcmp(flow_control, "software") == 0) config->flow_control = UART_FLOWCONTROL_SOFTWARE;
        } else {
            // unknown term
            ei_skip_term(req, req_index);
        }
    }
    return 0;
}
Ejemplo n.º 27
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:
    case ERL_NEW_PID_EXT:
	if (ei_decode_pid(buf, index, NULL) < 0) return -1;
	break;
    case ERL_PORT_EXT:
    case ERL_NEW_PORT_EXT:
	if (ei_decode_port(buf, index, NULL) < 0) return -1;
	break;
    case ERL_NEW_REFERENCE_EXT:
    case ERL_NEWER_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_MAP_EXT:
	if (ei_decode_map_header(buf, index, &n) < 0) return -1;
	n *= 2;
	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;
}
/*!
 * 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++;
}
Ejemplo n.º 29
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:
        case NEW_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;
}
Ejemplo n.º 30
0
static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf)
{
	char ename[MAXATOMLEN + 1];
	char esname[MAXATOMLEN + 1];
	int headerlength;

	memset(esname, 0, MAXATOMLEN);

	if (ei_decode_atom(buf->buff, &buf->index, ename) ||
		(!strncasecmp(ename, "CUSTOM", MAXATOMLEN) &&
		 ei_decode_atom(buf->buff, &buf->index, esname)) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) {
		ei_x_encode_tuple_header(rbuf, 2);
		ei_x_encode_atom(rbuf, "error");
		ei_x_encode_atom(rbuf, "badarg");
	} else {
		switch_event_types_t etype;
		if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) {
			switch_event_t *event;
			if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) ||
				switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) {
				char key[1024];
				char *value;
                                int type;
                                int size;
				int i = 0;
				switch_bool_t fail = SWITCH_FALSE;

				while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) {
					i++;

					ei_get_type(buf->buff, &buf->index, &type, &size);

					if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) {
						fail = SWITCH_TRUE;
						break;
					}

					ei_get_type(buf->buff, &buf->index, &type, &size);
					value = malloc(size + 1);

					if (ei_decode_string(buf->buff, &buf->index, value)) {
       						fail = SWITCH_TRUE;
						break;
					}

					if (!fail && !strcmp(key, "body")) {
						switch_safe_free(event->body);
						event->body = value;
					} else if (!fail)  {
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value);
					}
					
					/* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */
				}

				if (headerlength != i || fail) {
					ei_x_encode_tuple_header(rbuf, 2);
					ei_x_encode_atom(rbuf, "error");
					ei_x_encode_atom(rbuf, "badarg");
				} else {
					switch_event_fire(&event);
					ei_x_encode_atom(rbuf, "ok");
				}
			}
			/* If the event wasn't successfully fired, or failed for any other reason, then make sure not to leak it. */
			if ( event ) {
				switch_event_destroy(&event);
			}
		}
	}
	return SWITCH_STATUS_SUCCESS;
}