Beispiel #1
0
static inline int
match_atom(ErlNifEnv* env, ERL_NIF_TERM term, State *st){
  if(!enif_is_atom(env, term)){
    return 0;
  }
  
  if(enif_is_identical(term, st->priv->am_true)){
    b_puts(4, "true", st);
    return 1;
  }else if(enif_is_identical(term, st->priv->am_false)){
    b_puts(5, "false", st);
    return 1;
  }else if(enif_is_identical(term, st->priv->am_null)){
    b_puts(4, "null", st);
    return 1;
  }
  
  unsigned len, reserve;
  b_reserve(256 + 2, st);
  unsigned char *p = st->cur;
  if((len = enif_get_atom(env, term, (char*)p + 1, 256U, ERL_NIF_LATIN1))){
    *p = '"';
    if(!check_str_for_json((unsigned char*)p + 1, len-1, &reserve)){
      return 0;
    }
    if(reserve > 0){
      b_reserve(len + reserve + 2, st);
      extend_str_to_jstr((unsigned char*)p + 1, len-1, reserve);
    }
    st->cur += (len + reserve);
    b_putc('"', st);
    return 1;
  }
  return 0;
}
Beispiel #2
0
static ERL_NIF_TERM seek_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    Sint64 new_position, offset;
    enum efile_seek_t seek;

    ASSERT(argc == 2);
    if(!enif_get_int64(env, argv[1], &offset)) {
        return enif_make_badarg(env);
    }

    if(enif_is_identical(argv[0], am_bof)) {
        seek = EFILE_SEEK_BOF;
    } else if(enif_is_identical(argv[0], am_cur)) {
        seek = EFILE_SEEK_CUR;
    } else if(enif_is_identical(argv[0], am_eof)) {
        seek = EFILE_SEEK_EOF;
    } else {
        return enif_make_badarg(env);
    }

    if(!efile_seek(d, seek, offset, &new_position)) {
        return posix_error_to_tuple(env, d->posix_errno);
    }

    return enif_make_tuple2(env, am_ok, enif_make_uint64(env, new_position));
}
Beispiel #3
0
static inline int
match_tuple(ErlNifEnv* env, ERL_NIF_TERM term, State *st){ 
  const ERL_NIF_TERM *tuple;
  int arity;
  if(!enif_get_tuple(env, term, &arity, &tuple))
    return 0;
  if(arity > 0){ 
    if(enif_is_atom(env, tuple[0])){
      if(arity == 2){
	if(enif_is_identical(tuple[0], st->priv->am_struct)){
	  //struct
	  return match_proplist(env, tuple[1], st);
	}else   if(enif_is_identical(tuple[0], st->priv->am_json)){
	  //json
	  return  match_json(env, tuple[1], st);
	}
      }
      //records
      if(st->records){
	return match_record(env, arity, tuple, st);
      }
    }
    if(arity == 1){
      //eep18
      return (match_proplist(env, tuple[0], st));
    }
  }
  return 0;  
}
Beispiel #4
0
static ERL_NIF_TERM send_blob_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    union { void* vp; struct make_term_info* p; }mti;
    ERL_NIF_TERM copy;
    if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)
	|| !enif_get_local_pid(env,argv[1], &mti.p->to_pid)) {
	return enif_make_badarg(env);
    }
    copy = enif_make_copy(env, mti.p->blob);

    mti.p->send_it = enif_is_identical(argv[2],atom_join);
    if (enif_thread_create("nif_SUITE:send_from_thread", &mti.p->tid,
			   threaded_sender, mti.p, NULL) != 0) {
	return enif_make_badarg(env);
    }
    if (enif_is_identical(argv[2],atom_join)) {
	int err = enif_thread_join(mti.p->tid, NULL);
	assert(err == 0);
	return enif_make_tuple3(env, atom_ok, enif_make_int(env, mti.p->send_res), copy);
    }
    else {
	enif_keep_resource(mti.vp);
	return enif_make_tuple2(env, atom_ok, copy);
    }
}
Beispiel #5
0
static int whereis_type(ERL_NIF_TERM type)
{
    if (enif_is_identical(type, atom_pid))
        return WHEREIS_LOOKUP_PID;

    if (enif_is_identical(type, atom_port))
        return WHEREIS_LOOKUP_PORT;

    return WHEREIS_ERROR_TYPE;
}
Beispiel #6
0
// convert an erlang term to a python object
// return None if the type can't be converted
static PyObject* pynerl_term_to_obj(ErlNifEnv* env, ERL_NIF_TERM term) {
	int vint;
	Py_ssize_t arity, i;
	long int vlong;
	double vdouble;
	char buff[BUFF_SIZE];
	PyObject* obj;
	ERL_NIF_TERM list, head, tail;
	const ERL_NIF_TERM *terms;

	// TODO: add more types
	if (enif_get_long(env, term, &vlong)) {
		obj = PyLong_FromLong(vlong);
	}
	else if (enif_get_double(env, term, &vdouble)) {
		obj = PyFloat_FromDouble(vlong);
	}
	else if (enif_is_empty_list(env, term)) {
		obj = PyList_New(0);
	}
	else if (enif_get_tuple(env, term, &vint, &terms)) {
		arity = vint;
		obj = PyTuple_New(arity);

		for (i = 0; i < arity; i++) {
			PyTuple_SetItem(obj, i, pynerl_term_to_obj(env, terms[(int)i]));
		}
	}
	else if (enif_is_identical(term, enif_make_atom(env, "true"))) {
		obj = Py_True;
	}
	else if (enif_is_identical(term, enif_make_atom(env, "false"))) {
		obj = Py_False;
	}
	else if (enif_get_string(env, term, buff, BUFF_SIZE, ERL_NIF_LATIN1)) {
		obj = PyUnicode_FromString(buff);
	}
	else if (enif_get_list_cell(env, term, &head, &tail)) {
		obj = PyList_New(0);
		list = term;

		while (enif_get_list_cell(env, list, &head, &tail)) {
			PyList_Append(obj, pynerl_term_to_obj(env, head));
			list = tail;
		}
	}
	else {
		obj = Py_None;
	}

	return obj;
}
Beispiel #7
0
//
// Options = [ Option ]
// Option = caseless | {offset, non_neg_integer()}
//          | {capture,ValueSpec} | {capture,ValueSpec,Type}
// Type = index | binary
// ValueSpec = all | all_but_first | first | none | ValueList
// ValueList = [ ValueID ]
// ValueID = int() | string() | atom()
//
static bool parse_match_options(ErlNifEnv* env, const ERL_NIF_TERM list,
                                matchoptions& opts)
{
    if (enif_is_empty_list(env, list))
        return true;

    ERL_NIF_TERM L,H,T;

    for (L=list; enif_get_list_cell(env, L, &H, &T); L=T) {
        const ERL_NIF_TERM *tuple;
        int tuplearity = -1;

        if (enif_is_identical(H, a_caseless)) {

            // caseless

            opts.caseless = true;

        } else if (enif_get_tuple(env, H, &tuplearity, &tuple)) {

            if (tuplearity == 2 || tuplearity == 3) {

                // {offset,N} or {capture,ValueSpec}

                if (enif_is_identical(tuple[0], a_offset)) {

                    // {offset, int()}

                    int offset = 0;
                    if (enif_get_int(env, tuple[1], &offset)) {
                        opts.offset = offset;
                    } else {
                        return false;
                    }

                } else if (enif_is_identical(tuple[0], a_capture)) {

                    // {capture,ValueSpec,Type}
                    parse_match_capture_options(env, opts, tuple, tuplearity);

                }
            }
        } else {
            return false;
        }
    }

    return true;
}
Beispiel #8
0
int decode_flags(ErlNifEnv* env, ERL_NIF_TERM list, int *prot, int *flags, bool *direct, bool *lock)
{
  bool l = true;
  bool d = false;
  int f = MAP_FILE;
  int p = 0;
  ERL_NIF_TERM head;
  while (enif_get_list_cell(env, list, &head, &list)) {

    if (enif_is_identical(head, ATOM_READ)) {
      p |= PROT_READ;
    } else if (enif_is_identical(head, ATOM_DIRECT)) {
      d = true;
    } else if (enif_is_identical(head, ATOM_LOCK)) {
      l = true;
    } else if (enif_is_identical(head, ATOM_NOLOCK)) {
      l = false;
    } else if (enif_is_identical(head, ATOM_WRITE)) {
      p |= PROT_WRITE;
//    } else if (enif_is_identical(head, ATOM_NONE)) {
//    p |= PROT_NONE;

    } else if (enif_is_identical(head, ATOM_PRIVATE)) {
      f |= MAP_PRIVATE;
    } else if (enif_is_identical(head, ATOM_SHARED)) {
      f |= MAP_SHARED;
//  } else if (enif_is_identical(head, ATOM_ANON)) {
//    f |= MAP_ANON;
//  } else if (enif_is_identical(head, ATOM_FILE)) {
//    f |= MAP_FILE;
//  } else if (enif_is_identical(head, ATOM_FIXED)) {
//    f |= MAP_FIXED;
    } else if (enif_is_identical(head, ATOM_NOCACHE)) {
      f |= MAP_NOCACHE;

    } else {
      return 0;
    }
  }

  // direct cannot be write
  if (d & ((p & PROT_WRITE) != 0))
    return 0;

  // default to private
  if ((f & (MAP_SHARED|MAP_PRIVATE)) == 0)
    f |= MAP_PRIVATE;

  // default to read-only
  if ((p & (PROT_READ|PROT_WRITE)) == 0)
    p |= PROT_READ;

  *flags = f;
  *prot = p;
  *direct = d;
  *lock = l;

  return 1;
}
Beispiel #9
0
static ERL_NIF_TERM is_identical(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{    
    if (argc != 2) {
	return enif_make_badarg(env);
    }
    return enif_make_atom(env, (enif_is_identical(argv[0],argv[1]) ?
				"true" : "false"));
}
Beispiel #10
0
//
// Options = [ Option ]
// Option = caseless | {max_mem, int()}
//
static bool parse_compile_options(ErlNifEnv* env, const ERL_NIF_TERM list,
                                  re2::RE2::Options& opts)
{
    if (enif_is_empty_list(env, list))
        return true;

    ERL_NIF_TERM L,H,T;

    for (L=list; enif_get_list_cell(env, L, &H, &T); L=T) {
        const ERL_NIF_TERM *tuple;
        int tuplearity = -1;

        if (enif_is_identical(H, a_caseless)) {

            // caseless

            opts.set_case_sensitive(false);

        } else if (enif_get_tuple(env, H, &tuplearity, &tuple)) {

            if (tuplearity == 2) {

                if (enif_is_identical(tuple[0], a_max_mem)) {

                    // {max_mem, int()}

                    int max_mem = 0;
                    if (enif_get_int(env, tuple[1], &max_mem))
                        opts.set_max_mem(max_mem);
                    else
                        return false;

                }
            }
        } else {
            return false;
        }
    }

    return true;
}
static ERL_NIF_TERM
same_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    assert(argc == 2 && "same_term is a 2-arity function.");
    if(enif_is_identical(argv[0], argv[1]))
    {
        return mk_atom(env, "true");
    }
    else
    {
        return  mk_atom(env, "false");
    }
}
Beispiel #12
0
/* {resource_type, Ix|null, ErlNifResourceFlags in, "TypeName", dtor(A|B|null), ErlNifResourceFlags out}*/
static void open_resource_type(ErlNifEnv* env, const ERL_NIF_TERM* arr)
{
    NifModPrivData* data = priv_data(env);
    char rt_name[30];
    union { ErlNifResourceFlags e; int i; } flags, exp_res, got_res;
    unsigned ix;
    ErlNifResourceDtor* dtor;
    ErlNifResourceType* got_ptr;

    CHECK(enif_is_identical(arr[0], am_resource_type));
    CHECK(enif_get_int(env, arr[2], &flags.i));
    CHECK(enif_get_string(env, arr[3], rt_name, sizeof(rt_name), ERL_NIF_LATIN1) > 0);
    CHECK(enif_get_int(env, arr[5], &exp_res.i));
	
    if (enif_is_identical(arr[4], am_null)) {
	dtor = NULL;
    }
    else if (enif_is_identical(arr[4], am_resource_dtor_A)) {
	dtor = resource_dtor_A;
    }
    else {
	CHECK(enif_is_identical(arr[4], am_resource_dtor_B));
	dtor = resource_dtor_B;
    }

    got_ptr = enif_open_resource_type(env, NULL, rt_name, dtor,
				      flags.e, &got_res.e);

    if (enif_get_uint(env, arr[1], &ix) && ix < RT_MAX && got_ptr != NULL) {
	data->rt_arr[ix] = got_ptr;
    }
    else {
	CHECK(enif_is_identical(arr[1], am_null));
	CHECK(got_ptr == NULL);
    }
    CHECK(got_res.e == exp_res.e);
}
Beispiel #13
0
/*
 * argv[0] an atom
 * argv[1] a binary
 * argv[2] a ref
 * argv[3] 'ok'
 * argv[4] a fun
 * argv[5] a pid
 * argv[6] a port
 * argv[7] an empty list
 * argv[8] a non-empty list
 * argv[9] a tuple
 */
static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM ok_atom = enif_make_atom(env, "ok");

    if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env);
    if (!enif_is_binary(env, argv[1])) return enif_make_badarg(env);
    if (!enif_is_ref(env, argv[2])) return enif_make_badarg(env);
    if (!enif_is_identical(argv[3], ok_atom)) return enif_make_badarg(env);
    if (!enif_is_fun(env, argv[4])) return enif_make_badarg(env);
    if (!enif_is_pid(env, argv[5])) return enif_make_badarg(env);
    if (!enif_is_port(env, argv[6])) return enif_make_badarg(env);
    if (!enif_is_empty_list(env, argv[7])) return enif_make_badarg(env);
    if (!enif_is_list(env, argv[7])) return enif_make_badarg(env);
    if (!enif_is_list(env, argv[8])) return enif_make_badarg(env);
    if (!enif_is_tuple(env, argv[9])) return enif_make_badarg(env);

    return ok_atom;
}
Beispiel #14
0
//
// Options = [ Option ]
// Option = global
//
static bool parse_replace_options(ErlNifEnv* env, const ERL_NIF_TERM list,
                                  replaceoptions& opts)
{
    if (enif_is_empty_list(env, list))
        return true;

    ERL_NIF_TERM L,H,T;

    for (L=list; enif_get_list_cell(env, L, &H, &T); L=T) {

        if (enif_is_identical(H, a_global))
            opts.global = true;
        else
            return false;
    }

    return true;
}
Beispiel #15
0
static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary data_bin;
    union { ErlNifResourceType* t; long l; } type;
    union { void* p; long l; } data;

    type.t = NULL;
    if (enif_is_identical(argv[0], atom_binary_resource_type)) {
	type.t = binary_resource_type;
    }
    else {
	enif_get_long(env, argv[0], &type.l);
    }
    if (type.t == NULL 
	|| !enif_get_resource(env, argv[1], type.t, &data.p)) {
	return enif_make_badarg(env);
    }
    enif_alloc_binary(enif_sizeof_resource(data.p), &data_bin);    
    memcpy(data_bin.data, data.p, data_bin.size);
    return enif_make_tuple2(env, enif_make_long(env,data.l),
			    enif_make_binary(env, &data_bin));
}
Beispiel #16
0
static void parse_match_capture_options(ErlNifEnv* env, matchoptions& opts,
                                        const ERL_NIF_TERM* tuple,
                                        int tuplearity)
{
    bool vs_set = false;
    if (enif_is_atom(env, tuple[1])) {

        // ValueSpec = all | all_but_first | first | none

        if (enif_is_atom(env, tuple[1]) > 0) {

            if (enif_is_identical(tuple[1], a_all))
                opts.vs = matchoptions::VS_ALL;
            else if (enif_is_identical(tuple[1], a_all_but_first))
                opts.vs = matchoptions::VS_ALL_BUT_FIRST;
            else if (enif_is_identical(tuple[1], a_first))
                opts.vs = matchoptions::VS_FIRST;
            else if (enif_is_identical(tuple[1], a_none))
                opts.vs = matchoptions::VS_NONE;

            vs_set = true;
        }

    } else if (!enif_is_empty_list(env, tuple[1])) {

        // ValueSpec = ValueList
        // ValueList = [ ValueID ]
        // ValueID = int() | string() | atom()

        opts.vlist = tuple[1];
        vs_set = true;
        opts.vs = matchoptions::VS_VLIST;
    }

    // Type = index | binary

    if (tuplearity == 3 && vs_set) {

        if (enif_is_identical(tuple[2], a_index))
            opts.ct = matchoptions::CT_INDEX;
        else if (enif_is_identical(tuple[2], a_binary))
            opts.ct = matchoptions::CT_BINARY;
    }
}
Beispiel #17
0
static ERL_NIF_TERM advise_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    enum efile_advise_t advise;
    Sint64 offset, length;

    if(argc != 3 || !enif_is_number(env, argv[0])
                 || !enif_is_number(env, argv[1])) {
        return enif_make_badarg(env);
    }

    if(!enif_get_int64(env, argv[0], &offset) ||
       !enif_get_int64(env, argv[1], &length) ||
       (offset < 0 || length < 0)) {
        return posix_error_to_tuple(env, EINVAL);
    }

    if(enif_is_identical(argv[2], am_normal)) {
        advise = EFILE_ADVISE_NORMAL;
    } else if(enif_is_identical(argv[2], am_random)) {
        advise = EFILE_ADVISE_RANDOM;
    } else if(enif_is_identical(argv[2], am_sequential)) {
        advise = EFILE_ADVISE_SEQUENTIAL;
    } else if(enif_is_identical(argv[2], am_will_need)) {
        advise = EFILE_ADVISE_WILL_NEED;
    } else if(enif_is_identical(argv[2], am_dont_need)) {
        advise = EFILE_ADVISE_DONT_NEED;
    } else if(enif_is_identical(argv[2], am_no_reuse)) {
        advise = EFILE_ADVISE_NO_REUSE;
    } else {
        /* The tests check for EINVAL instead of badarg. Sigh. */
        return posix_error_to_tuple(env, EINVAL);
    }

    if(!efile_advise(d, offset, length, advise)) {
        return posix_error_to_tuple(env, d->posix_errno);
    }

    return am_ok;
}
Beispiel #18
0
static enum efile_modes_t efile_translate_modelist(ErlNifEnv *env, ERL_NIF_TERM list) {
    enum efile_modes_t modes;
    ERL_NIF_TERM head, tail;

    modes = 0;

    while(enif_get_list_cell(env, list, &head, &tail)) {
        if(enif_is_identical(head, am_read)) {
            modes |= EFILE_MODE_READ;
        } else if(enif_is_identical(head, am_write)) {
            modes |= EFILE_MODE_WRITE;
        } else if(enif_is_identical(head, am_exclusive)) {
            modes |= EFILE_MODE_EXCLUSIVE;
        } else if(enif_is_identical(head, am_append)) {
            modes |= EFILE_MODE_APPEND;
        } else if(enif_is_identical(head, am_sync)) {
            modes |= EFILE_MODE_SYNC;
        } else if(enif_is_identical(head, am_skip_type_check)) {
            modes |= EFILE_MODE_SKIP_TYPE_CHECK;
        } else {
            /* Modes like 'raw', 'ram', 'delayed_writes' etc are handled
             * further up the chain. */
        }

        list = tail;
    }

    if(modes & (EFILE_MODE_APPEND | EFILE_MODE_EXCLUSIVE)) {
        /* 'append' and 'exclusive' are documented as "open for writing." */
        modes |= EFILE_MODE_WRITE;
    } else if(!(modes & EFILE_MODE_READ_WRITE)) {
        /* Defaulting to read if !(W|R) is undocumented, but specifically
         * tested against in file_SUITE. */
        modes |= EFILE_MODE_READ;
    }

    return modes;
}
Beispiel #19
0
ERL_NIF_TERM
encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    Encoder enc;
    Encoder* e = &enc;

    ErlNifBinary bin;
    ERL_NIF_TERM ret;

    ERL_NIF_TERM stack;
    ERL_NIF_TERM curr;
    ERL_NIF_TERM item;
    const ERL_NIF_TERM* tuple;
    int arity;
    ErlNifSInt64 lval;
    double dval;

    if(argc != 2) {
        return enif_make_badarg(env);
    }

    if(!enc_init(e, env, argv[1], &bin)) {
        return enif_make_badarg(env);
    }

    stack = enif_make_list(env, 1, argv[0]);

    while(!enif_is_empty_list(env, stack)) {
        if(!enif_get_list_cell(env, stack, &curr, &stack)) {
            ret = enc_error(e, "internal_error");
            goto done;
        }
        if(enif_is_identical(curr, e->atoms->ref_object)) {
            if(!enif_get_list_cell(env, stack, &curr, &stack)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_object(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_tuple(env, item, &arity, &tuple)) {
                ret = enc_error(e, "invalid_object_pair");
                goto done;
            }
            if(arity != 2) {
                ret = enc_error(e, "invalid_object_pair");
                goto done;
            }
            if(!enc_comma(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enc_string(e, tuple[0])) {
                ret = enc_error(e, "invalid_object_key");
                goto done;
            }
            if(!enc_colon(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
            stack = enif_make_list_cell(env, tuple[1], stack);
        } else if(enif_is_identical(curr, e->atoms->ref_array)) {
            if(!enif_get_list_cell(env, stack, &curr, &stack)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_array(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enc_comma(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
            stack = enif_make_list_cell(env, item, stack);
        } else if(enif_compare(curr, e->atoms->atom_null) == 0) {
            if(!enc_literal(e, "null", 4)) {
                ret = enc_error(e, "null");
                goto done;
            }
        } else if(enif_compare(curr, e->atoms->atom_true) == 0) {
            if(!enc_literal(e, "true", 4)) {
                ret = enc_error(e, "true");
                goto done;
            }
        } else if(enif_compare(curr, e->atoms->atom_false) == 0) {
            if(!enc_literal(e, "false", 5)) {
                ret = enc_error(e, "false");
                goto done;
            }
        } else if(enif_is_binary(env, curr)) {
            if(!enc_string(e, curr)) {
                ret = enc_error(e, "invalid_string");
                goto done;
            }
        } else if(enif_is_atom(env, curr)) {
            if(!enc_string(e, curr)) {
                ret = enc_error(e, "invalid_string");
                goto done;
            }
        } else if(enif_get_int64(env, curr, &lval)) {
            if(!enc_long(e, lval)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        } else if(enif_get_double(env, curr, &dval)) {
            if(!enc_double(e, dval)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        } else if(enif_get_tuple(env, curr, &arity, &tuple)) {
            if(arity != 1) {
                ret = enc_error(e, "invalid_ejson");
                goto done;
            }
            if(!enif_is_list(env, tuple[0])) {
                ret = enc_error(e, "invalid_object");
                goto done;
            }
            if(!enc_start_object(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, tuple[0])) {
                if(!enc_end_object(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, tuple[0], &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_tuple(env, item, &arity, &tuple)) {
                ret = enc_error(e, "invalid_object_member");
                goto done;
            }
            if(arity != 2) {
                ret = enc_error(e, "invalid_object_member_arity");
                goto done;
            }
            if(!enc_string(e, tuple[0])) {
                ret = enc_error(e, "invalid_object_member_key");
                goto done;
            }
            if(!enc_colon(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
            stack = enif_make_list_cell(env, tuple[1], stack);
        } else if(enif_is_list(env, curr)) {
            if(!enc_start_array(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_array(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
            stack = enif_make_list_cell(env, item, stack);
        } else {
            if(!enc_unknown(e, curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        }
    }

    if(!enc_done(e, &item)) {
        ret = enc_error(e, "internal_error");
        goto done;
    }

    if(e->iolen == 0) {
        ret = item;
    } else {
        ret = enif_make_tuple2(env, e->atoms->atom_partial, item);
    }

done:
    enc_destroy(e);
    return ret;
}
Beispiel #20
0
ERL_NIF_TERM
encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    Encoder* e;
    jiffy_st* st = (jiffy_st*) enif_priv_data(env);

    ERL_NIF_TERM ret = 0;

    ERL_NIF_TERM stack;
    ERL_NIF_TERM curr;
    ERL_NIF_TERM item;
    const ERL_NIF_TERM* tuple;
    int arity;
    ErlNifSInt64 lval;
    double dval;

    size_t start;
    size_t processed;

    if(argc != 3) {
        return enif_make_badarg(env);
    } else if(!enif_get_resource(env, argv[0], st->res_enc, (void**) &e)) {
        return enif_make_badarg(env);
    } else if(!enif_is_list(env, argv[1])) {
        return enif_make_badarg(env);
    } else if(!enif_is_list(env, argv[2])) {
        return enif_make_badarg(env);
    }

    if(!enc_init(e, env)) {
        return enif_make_badarg(env);
    }

    stack = argv[1];
    e->iolist = argv[2];

    start = e->iosize + e->i;

    while(!enif_is_empty_list(env, stack)) {

        processed = (e->iosize + e->i) - start;
        if(should_yield(processed, e->bytes_per_iter)) {
            consume_timeslice(env, processed, e->bytes_per_iter);
            return enif_make_tuple4(
                    env,
                    st->atom_iter,
                    argv[0],
                    stack,
                    e->iolist
                );
        }

        if(!enif_get_list_cell(env, stack, &curr, &stack)) {
            ret = enc_error(e, "internal_error");
            goto done;
        }
        if(enif_is_identical(curr, e->atoms->ref_object)) {
            if(!enif_get_list_cell(env, stack, &curr, &stack)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_object(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_tuple(env, item, &arity, &tuple)) {
                ret = enc_obj_error(e, "invalid_object_member", item);
                goto done;
            }
            if(arity != 2) {
                ret = enc_obj_error(e, "invalid_object_member_arity", item);
                goto done;
            }
            if(!enc_comma(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enc_string(e, tuple[0])) {
                ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]);
                goto done;
            }
            if(!enc_colon(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
            stack = enif_make_list_cell(env, tuple[1], stack);
        } else if(enif_is_identical(curr, e->atoms->ref_array)) {
            if(!enif_get_list_cell(env, stack, &curr, &stack)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_array(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enc_comma(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
            stack = enif_make_list_cell(env, item, stack);
        } else if(enif_compare(curr, e->atoms->atom_null) == 0) {
            if(!enc_literal(e, "null", 4)) {
                ret = enc_error(e, "null");
                goto done;
            }
        } else if(e->use_nil && enif_compare(curr, e->atoms->atom_nil) == 0) {
            if(!enc_literal(e, "null", 4)) {
                ret = enc_error(e, "null");
                goto done;
            }
        } else if(enif_compare(curr, e->atoms->atom_true) == 0) {
            if(!enc_literal(e, "true", 4)) {
                ret = enc_error(e, "true");
                goto done;
            }
        } else if(enif_compare(curr, e->atoms->atom_false) == 0) {
            if(!enc_literal(e, "false", 5)) {
                ret = enc_error(e, "false");
                goto done;
            }
        } else if(enif_is_binary(env, curr)) {
            if(!enc_string(e, curr)) {
                ret = enc_obj_error(e, "invalid_string", curr);
                goto done;
            }
        } else if(enif_is_atom(env, curr)) {
            if(!enc_string(e, curr)) {
                ret = enc_obj_error(e, "invalid_string", curr);
                goto done;
            }
        } else if(enif_get_int64(env, curr, &lval)) {
            if(!enc_long(e, lval)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        } else if(enif_get_double(env, curr, &dval)) {
            if(!enc_double(e, dval)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        } else if(enif_get_tuple(env, curr, &arity, &tuple)) {
			ret = enc_obj_error(e, "invalid_ejson", curr);
			goto done;
#if MAP_TYPE_PRESENT
        } else if(enif_is_map(env, curr)) {
            if(!enc_map_to_ejson(env, curr, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
#endif
        } else if(enif_is_list(env, curr)) {
            if(enif_is_empty_list(env, curr)) {
                if(!enc_start_array(e) || !enc_end_array(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_tuple(env, item, &arity, &tuple)) {
				if(!enc_start_array(e)) {
					ret = enc_error(e, "internal_error");
					goto done;
				}
				stack = enif_make_list_cell(env, curr, stack);
				stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
				stack = enif_make_list_cell(env, item, stack);
            } else {
				if(!enc_start_object(e)) {
					ret = enc_error(e, "internal_error");
					goto done;
				}
				if(arity == 0) {
					if(!enc_end_object(e)) {
						ret = enc_error(e, "internal_error");
						goto done;
					}
					continue;
				} else if(arity != 2) {
					ret = enc_obj_error(e, "invalid_object_member_arity", item);
					goto done;
				}
				if(!enc_string(e, tuple[0])) {
					ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]);
					goto done;
				}
				if(!enc_colon(e)) {
					ret = enc_error(e, "internal_error");
					goto done;
				}
				stack = enif_make_list_cell(env, curr, stack);
				stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
				stack = enif_make_list_cell(env, tuple[1], stack);
			}
        } else {
            if(!enc_unknown(e, curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        }
    }

    if(!enc_done(e, &item)) {
        ret = enc_error(e, "internal_error");
        goto done;
    }

    if(e->iolen == 0) {
        ret = item;
    } else {
        ret = enif_make_tuple2(env, e->atoms->atom_partial, item);
    }

done:
    processed = (e->iosize + e->i) - start;
    consume_timeslice(env, processed, e->bytes_per_iter);

    return ret;
}
Beispiel #21
0
static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    int i;
    int sint;
    unsigned uint;
    long slong;
    unsigned long ulong;
    ErlNifSInt64 sint64;
    ErlNifUInt64 uint64;
    double d;
    ERL_NIF_TERM atom, ref1, ref2;

    sint = INT_MIN;
    do {
	if (!test_int(env,sint)) {
	    goto error;
	}
	sint += ~sint / 3 + 1;
    } while (sint < 0);
    sint = INT_MAX;
    do {
	if (!test_int(env,sint)) {
	    goto error;
	}
	sint -= sint / 3 + 1;
    } while (sint >= 0);

    slong = LONG_MIN;
    do {
	if (!test_long(env,slong)) {
	    goto error;
	}
	slong += ~slong / 3 + 1;
    } while (slong < 0);
    slong = LONG_MAX;
    do {
	if (!test_long(env,slong)) {
	    goto error;
	}
	slong -= slong / 3 + 1;
    } while (slong >= 0);

    sint64 = ((ErlNifSInt64)1 << 63); /* INT64_MIN */
    do {
	if (!test_int64(env,sint64)) {
	    goto error;
	}
	sint64 += ~sint64 / 3 + 1;
    } while (sint64 < 0);
    sint64 = ((ErlNifUInt64)1 << 63) - 1; /* INT64_MAX */
    do {
	if (!test_int64(env,sint64)) {
	    goto error;
	}
	sint64 -= sint64 / 3 + 1;
    } while (sint64 >= 0);

    uint = UINT_MAX;
    for (;;) {
	if (!test_uint(env,uint)) {
	    goto error;
	}
	if (uint == 0) break;
	uint -= uint / 3 + 1;
    }
    ulong = ULONG_MAX;
    for (;;) {
	if (!test_ulong(env,ulong)) {
	    goto error;
	}
	if (ulong == 0) break;
	ulong -= ulong / 3 + 1;
    }    
    uint64 = (ErlNifUInt64)-1; /* UINT64_MAX */
    for (;;) {
	if (!test_uint64(env,uint64)) {
	    goto error;
	}
	if (uint64 == 0) break;
	uint64 -= uint64 / 3 + 1;
    }    

    if (MAX_SMALL < INT_MAX) { /* 32-bit */
	for (i=-10 ; i <= 10; i++) {
	    if (!test_int(env,MAX_SMALL+i)) {
		goto error;
	    }
	}
	for (i=-10 ; i <= 10; i++) {
	    if (!test_int(env,MIN_SMALL+i)) {
		goto error;
	    }
	}
	for (i=-10 ; i <= 10; i++) {
	    if (!test_uint(env,MAX_SMALL+i)) {
		goto error;
	    }
	}
    }
    assert((MAX_SMALL < INT_MAX) == (MIN_SMALL > INT_MIN));

    for (i=-10 ; i < 10; i++) {
	if (!test_long(env,MAX_SMALL+i) || !test_ulong(env,MAX_SMALL+i) ||
	    !test_long(env,MIN_SMALL+i) ||
	    !test_int64(env,MAX_SMALL+i) || !test_uint64(env,MAX_SMALL+i) ||
	    !test_int64(env,MIN_SMALL+i)) {
	    goto error;
	}
	if (MAX_SMALL < INT_MAX) {
	    if (!test_int(env,MAX_SMALL+i) || !test_uint(env,MAX_SMALL+i) ||
		!test_int(env,MIN_SMALL+i)) {
		goto error;
	    }
	}
    }
    for (d=3.141592e-100 ; d < 1e100 ; d *= 9.97) {
	if (!test_double(env,d) || !test_double(env,-d)) {
	    goto error;
	}	
    }

    if (!enif_make_existing_atom(env,"nif_SUITE", &atom, ERL_NIF_LATIN1)
	|| !enif_is_identical(atom,enif_make_atom(env,"nif_SUITE"))) {
	fprintf(stderr, "nif_SUITE not an atom?\r\n");
	goto error;
    }
    for (i=2; i; i--) {
	if (enif_make_existing_atom(env,"nif_SUITE_pink_unicorn", &atom, ERL_NIF_LATIN1)) {
	    fprintf(stderr, "pink unicorn exist?\r\n");
	    goto error;
	}
    }
    ref1 = enif_make_ref(env);
    ref2 = enif_make_ref(env);
    if (!enif_is_ref(env,ref1) || !enif_is_ref(env,ref2) 
	|| enif_is_identical(ref1,ref2) || enif_compare(ref1,ref2)==0) {
	fprintf(stderr, "strange refs?\r\n");
	goto error;
    }
    return enif_make_atom(env,"ok");

error:
    return enif_make_atom(env,"error");
}
Beispiel #22
0
static ERL_NIF_TERM re2_match(ErlNifEnv* env, int argc,
                              const ERL_NIF_TERM argv[])
{
    ErlNifBinary sdata;

    if (enif_inspect_iolist_as_binary(env, argv[0], &sdata))
    {
        const re2::StringPiece s((const char*)sdata.data, sdata.size);
        autohandle<re2::RE2> re;
        union re2_handle_union handle;
        ErlNifBinary pdata;

        matchoptions opts(env);
        if (argc == 3 && !parse_match_options(env, argv[2], opts))
            return enif_make_badarg(env);

        if (enif_get_resource(env, argv[1], re2_resource_type, &handle.vp)
            && handle.p->re != NULL)
        {
            re.set(handle.p->re, true);

            if (opts.caseless) // caseless allowed either in compile or match
                return enif_make_badarg(env);
        }
        else if (enif_inspect_iolist_as_binary(env, argv[1], &pdata))
        {
            const re2::StringPiece p((const char*)pdata.data, pdata.size);
            re2::RE2::Options re2opts;
            re2opts.set_log_errors(false);
            if (opts.caseless)
                re2opts.set_case_sensitive(false);
            re2::RE2* re2 = (re2::RE2*)enif_alloc(sizeof(re2::RE2));
            if (re2 == NULL)
                return error(env, a_err_enif_alloc);
            re.set(new (re2) re2::RE2(p, re2opts)); // placement new
        }
        else
        {
            return enif_make_badarg(env);
        }

        if (!re->ok())
            return enif_make_badarg(env);

        int n = re->NumberOfCapturingGroups()+1;
        std::vector<re2::StringPiece> group;
        group.reserve(n);

        if (re->Match(s, opts.offset, s.size(),
                      re2::RE2::UNANCHORED, &group[0], n))
        {

            int start = 0;
            int arrsz = n;

            if (opts.vs == matchoptions::VS_NONE) {

                // return match atom only

                return a_match;

            } else if (opts.vs == matchoptions::VS_FIRST) {

                // return first match only

                ERL_NIF_TERM first = mres(env, s, group[0], opts.ct);
                if (enif_is_identical(first, a_err_alloc_binary)) {
                    return error(env, a_err_alloc_binary);
                } else {
                    return enif_make_tuple2(env, a_match,
                                            enif_make_list1(env, first));
                }

            } else if (opts.vs == matchoptions::VS_ALL_BUT_FIRST) {
                // skip first match
                start = 1;
                arrsz--;
            }

            if (opts.vs == matchoptions::VS_VLIST) {

                // return matched subpatterns as specified in ValueList

                return re2_match_ret_vlist(env, re, s, opts, group, n);

            } else {

                // return all or all_but_first matches

                ERL_NIF_TERM* arr =
                    (ERL_NIF_TERM*)enif_alloc(sizeof(ERL_NIF_TERM)*n);
                for(int i = start, arridx=0; i < n; i++,arridx++) {
                    ERL_NIF_TERM res = mres(env, s, group[i], opts.ct);
                    if (enif_is_identical(res, a_err_alloc_binary)) {
                        enif_free(arr);
                        return error(env, a_err_alloc_binary);
                    } else {
                        arr[arridx] = res;
                    }
                }

                ERL_NIF_TERM list = enif_make_list_from_array(env,arr,arrsz);
                enif_free(arr);

                return enif_make_tuple2(env, a_match, list);
            }

        } else {

            return a_nomatch;
        }

    } else {

        return enif_make_badarg(env);
    }
}
Beispiel #23
0
static ERL_NIF_TERM re2_match_ret_vlist(ErlNifEnv* env,
                                        const autohandle<re2::RE2>& re,
                                        const re2::StringPiece& s,
                                        const matchoptions& opts,
                                        std::vector<re2::StringPiece>& group,
                                        int n)
{
    std::vector<ERL_NIF_TERM> vec;
    const std::map<std::string, int>& nmap = re->NamedCapturingGroups();
    ERL_NIF_TERM VL,VH,VT;

    // empty StringPiece for unfound ValueIds
    const re2::StringPiece empty;

    for (VL=opts.vlist; enif_get_list_cell(env, VL, &VH, &VT); VL=VT) {
        int nid = 0;

        if (enif_get_int(env, VH, &nid) && nid > 0) {

            // ValueID int()

            if (nid < n) {
                const re2::StringPiece match = group[nid];
                ERL_NIF_TERM res;
                if (!match.empty())
                    res = mres(env, s, group[nid], opts.ct);
                else
                    res = mres(env, s, empty, opts.ct);

                if (enif_is_identical(res, a_err_alloc_binary))
                    return error(env, a_err_alloc_binary);
                else
                    vec.push_back(res);

            } else {
                vec.push_back(mres(env, s, empty, opts.ct));
            }

        } else if (enif_is_atom(env, VH)) {

            // ValueID atom()

            unsigned atom_len;
            char *a_id = alloc_atom(env, VH, &atom_len);
            if (a_id == NULL)
                return error(env, a_err_enif_alloc);

            if (enif_get_atom(env, VH, a_id, atom_len, ERL_NIF_LATIN1) > 0) {
                std::map<std::string, int>::const_iterator it =
                    nmap.find(a_id);

                ERL_NIF_TERM res;
                if (it != nmap.end())
                    res = mres(env, s, group[it->second], opts.ct);
                else
                    res = mres(env, s, empty, opts.ct);

                if (enif_is_identical(res, a_err_alloc_binary))
                    return error(env, a_err_alloc_binary);
                else
                    vec.push_back(res);
            }
            else
            {
                enif_free(a_id);
                return error(env, a_err_get_atom);
            }

            enif_free(a_id);

        } else {

            // ValueID string()

            unsigned str_len;
            char *str_id = alloc_str(env, VH, &str_len);
            if (str_id == NULL)
                return error(env, a_err_enif_alloc);

            if (enif_get_string(env, VH, str_id, str_len,
                                ERL_NIF_LATIN1) > 0)
            {
                std::map<std::string, int>::const_iterator it =
                    nmap.find(str_id);

                ERL_NIF_TERM res;
                if (it != nmap.end())
                    res = mres(env, s, group[it->second], opts.ct);
                else
                    res = mres(env, s, empty, opts.ct);

                if (enif_is_identical(res, a_err_alloc_binary))
                    return error(env, a_err_alloc_binary);
                else
                    vec.push_back(res);
            }
            else
            {
                enif_free(str_id);
                return error(env, a_err_get_string);
            }

            enif_free(str_id);
        }
    }

    ERL_NIF_TERM list = enif_make_list_from_array(env,&vec[0],vec.size());
    return enif_make_tuple2(env, a_match, list);
}