Exemple #1
0
static int
decode_number(void * ctx, const char * numberVal, unsigned int numberLen)
{
    // scan in the input to see if it's a float or int

    int numberType = 0; // 0 means integer, 1 means float
    unsigned int i;
    ErlNifBinary bin;
    int missingDot = 1;
    unsigned int expPos;

    for(i=0; i<numberLen; i++) {
        switch (numberVal[i]) {
        case '.':
            missingDot = 0;
            numberType = 1; // it's  a float
            goto loopend;
        case 'E':
        case 'e':
            expPos = i;
            numberType = 1; // it's  a float
            goto loopend;
        }
    }
loopend:
    if ((numberType == 1) && missingDot)
    {
        if(!enif_alloc_binary_compat(ENV(ctx), numberLen + 2, &bin))
        {
            return CANCEL;
        }
        memcpy(bin.data, numberVal, expPos);
        bin.data[expPos] = '.';
        bin.data[expPos + 1] = '0';
        memcpy(bin.data + expPos + 2, numberVal + expPos, numberLen - expPos);
    }
    else
    {
        if(!enif_alloc_binary_compat(ENV(ctx), numberLen, &bin))
        {
            return CANCEL;
        }
        memcpy(bin.data, numberVal, numberLen);
    }
    add_to_head(ctx, enif_make_tuple(ENV(ctx), 2,
                        enif_make_int(ENV(ctx), numberType),
                        enif_make_binary(ENV(ctx), &bin)));
    return CONTINUE;
}
Exemple #2
0
static int
decode_string(void* ctx, const unsigned char* data, unsigned int size)
{
    ErlNifBinary bin;
    if(!enif_alloc_binary_compat(ENV(ctx), size, &bin))
    {
        return CANCEL;
    }
    memcpy(bin.data, data, size);
    add_to_head(ctx, enif_make_binary(ENV(ctx), &bin));
    return CONTINUE;
}
Exemple #3
0
ERL_NIF_TERM blake2_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    blake2_handle *handle = NULL;
    enif_get_resource(env, argv[0], blake2_hashstate, (void**)&handle);
    
    ErlNifBinary out;
    enif_alloc_binary_compat(env, (size_t)(handle->digest_length), &out);

    int r = blake2b_final(&(handle->state), (uint8_t *)out.data, handle->digest_length);
    if (r == 0) {
        return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_binary(env, &out));
    } else {
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "finalization_failure"));
    }
}
Exemple #4
0
ERL_NIF_TERM blake2_hash(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    int bits = 0;
    enif_get_int(env, argv[0], &bits);
    
    ErlNifBinary bin, out;
    enif_inspect_binary(env, argv[1], &bin);
    enif_alloc_binary_compat(env, (size_t)(bits/8), &out);

    int r = blake2b((uint8_t *)out.data, (const void *)bin.data, NULL, (bits / 8), bin.size, 0);
    if (r == 0) {
        return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_binary(env, &out));
    } else {
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "hash_failure"));
    }   
}
Exemple #5
0
int hammy_get(ErlNifEnv *env, hammy_db *db, unsigned char *key, int key_size, ErlNifBinary *value) {
    ham_key_t k;
    ham_record_t rec;
    ham_txn_t *txn;
    int rc;
    int retval = HAMMY_FALSE;

    setup_key(&k, key, key_size);
    memset(&rec, 0, sizeof(ham_record_t));

    ham_txn_begin(&txn, db->databases[0], HAM_TXN_READ_ONLY);
    rc = ham_find(db->databases[0], txn, &k, &rec, 0);
    if (rc == HAM_SUCCESS) {
        if (enif_alloc_binary_compat(env, rec.size, value)) {
            memcpy(value->data, rec.data, rec.size);
            retval = HAMMY_TRUE;
        }
    }
    ham_txn_commit(txn, 0);
    return retval;
}
Exemple #6
0
ERL_NIF_TERM derive_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ihandle* handle;
    ERL_NIF_TERM head;
    ERL_NIF_TERM tail;
    char fmt[4];
    
    if(enif_get_resource(env, argv[0], EIM_IMAGE_RESOURCE, (void**)&handle)
    && enif_get_atom_compat(env, argv[1], fmt, 4, ERL_NIF_LATIN1)
    && enif_get_list_cell(env, argv[2], &head, &tail))
    {
        ErlNifBinary new_binary;
        size_t new_length;
        unsigned char *new_blob;
        
        do {
            //todo: error handle
            int tuplec;
            const ERL_NIF_TERM* tuple;
            char type[9];
            if(!enif_get_tuple(env, head, &tuplec, &tuple)
            || !enif_get_atom_compat(env, tuple[0], type, 9, ERL_NIF_LATIN1))
            {
                return enif_make_badarg(env);
            }
            long x, y;
            long width, height;
            long value;
            int rotate;
            char dimension[7];
            switch(type[0])
            {
                case 's'://scale
                    if(!enif_get_atom_compat(env, tuple[1], dimension, 7, ERL_NIF_LATIN1)
                    || !enif_get_long(env, tuple[2], &value))
                    {
                        return enif_make_badarg(env);
                    }
                    if(dimension[0]=='w')
                    {
                        handle->image->scale_width(value);
                    }
                    else if(dimension[0]=='h')
                    {
                        handle->image->scale_height(value);
                    }
                    else
                    {
                        return enif_make_badarg(env);
                    }
                    break;
                case 'c'://crop
                    if(!enif_get_long(env, tuple[1], &width) || !enif_get_long(env, tuple[2], &height)
                    || !enif_get_long(env, tuple[3], &x) || !enif_get_long(env, tuple[4], &y))
                    {
                        return enif_make_badarg(env);
                    }
                    handle->image->crop(width, height, x, y);
                    break;
                case 'm'://max
                    if(!enif_get_atom_compat(env, tuple[1], dimension, 7, ERL_NIF_LATIN1)
                    || !enif_get_long(env, tuple[2], &value))
                    {
                        return enif_make_badarg(env);
                    }
                    if(dimension[0]=='w')
                    {
                        handle->image->max_width(value);
                    }
                    else if(dimension[0]=='h')
                    {
                        handle->image->max_height(value);
                    }
                    else
                    {
                        return enif_make_badarg(env);
                    }
                    break;
                case 'f'://fit
                    if(!enif_get_long(env, tuple[1], &width) || !enif_get_long(env, tuple[2], &height))
                    {
                        return enif_make_badarg(env);
                    }
                    handle->image->fit(width, height);
                    break;
                case 'r'://rotate
                    if(!enif_get_int(env, tuple[1], &rotate))
                    {
                        return enif_make_badarg(env);
                    }
                    switch(rotate)
                    {
                        case 1: handle->image->rotate(EIM_ROTATE_90); break;
                        case 2: handle->image->rotate(EIM_ROTATE_180); break;
                        case 3: handle->image->rotate(EIM_ROTATE_270); break;
                        default:
                            return enif_make_badarg(env);
                    };
                    break;
                case 'b'://box
                    if(!enif_get_long(env, tuple[1], &width) || !enif_get_long(env, tuple[2], &height))
                    {
                        return enif_make_badarg(env);
                    }
                    char float_x[7], float_y[7];
                    char floated;
                    if(enif_get_atom_compat(env, tuple[3], float_x, 7, ERL_NIF_LATIN1))
                    {
                        if(!enif_get_atom_compat(env, tuple[4], float_y, 7, ERL_NIF_LATIN1))
                        {
                            return enif_make_badarg(env);
                        }
                        // can actually write top,left instead of left,top if you want
                        // just helps with typos like that. Just works.
                        switch(float_x[0])
                        {
                            case 'l': floated = EIM_FLOAT_LEFT; break;
                            case 'c': floated = EIM_FLOAT_CENTER; break;
                            case 'r': floated = EIM_FLOAT_RIGHT; break;
                            case 't': floated = EIM_FLOAT_TOP; break;
                            case 'b': floated = EIM_FLOAT_BOTTOM; break;
                            default:
                                return enif_make_badarg(env);
                        }
                        switch(float_y[0])
                        {
                            case 'l': floated ^= EIM_FLOAT_LEFT; break;
                            case 'c': floated ^= EIM_FLOAT_CENTER; break;
                            case 'r': floated ^= EIM_FLOAT_RIGHT; break;
                            case 't': floated ^= EIM_FLOAT_TOP; break;
                            case 'b': floated ^= EIM_FLOAT_BOTTOM; break;
                            default:
                                return enif_make_badarg(env);
                        }
                    }
                    else
                    {
                        floated = EIM_FLOAT_CENTER | EIM_FLOAT_CENTER;
                    }
                    handle->image->box(width, height, floated);
                    break;
                default:
                    return enif_make_badarg(env);
            }
            
        } while(enif_get_list_cell(env, tail, &head, &tail));
        
        EIM_FORMAT eim_format;
        switch(fmt[0])
        {
            case 'j': eim_format = EIM_FORMAT_JPG; break;
            case 'g': eim_format = EIM_FORMAT_GIF; break;
            case 'p': eim_format = EIM_FORMAT_PNG; break;
            default:
                return enif_make_badarg(env);
        }
        try
        {
            new_blob = handle->image->process(eim_format, &new_length);
            enif_alloc_binary_compat(env, new_length, &new_binary);
            memcpy(new_binary.data, new_blob, new_length);
            return enif_make_binary(env, &new_binary);
        }
        catch(const char* msg)
        {
            return enif_make_atom(env, "error");
        }
    }
    else
    {
        return enif_make_badarg(env);
    }
}
Exemple #7
0
ERL_NIF_TERM
json_encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    Encoder enc;
    yajl_gen_config config = {0, NULL};
    yajl_gen handle = yajl_gen_alloc(&config, NULL);
    yajl_gen_status status;
    ERL_NIF_TERM ret = enif_make_badarg(env);
    ErlNifBinary bin;
    const unsigned char* json;
    unsigned int jsonlen;
    
    if(argc != 1) goto done;

    if(handle == NULL)
    {
        ret = enif_make_tuple(env, 2,
            enif_make_atom(env, "error"),
            enif_make_atom(env, "memory_error")
        );
        goto done;
    }

    enc.env = env;
    enc.handle = handle;
    enc.error = 0;
    if(enc_json(&enc, argv[0]) == ERROR)
    {
        if(enc.error == 0)
        {
            ret = enif_make_atom(env, "unknown");
        }
        else
        {
            ret = enc.error;
        }
        ret = enif_make_tuple(env, 2,
            enif_make_atom(env, "error"),
            ret
        );
        goto done;
    }

    status = yajl_gen_get_buf(handle, &json, &jsonlen);
    if(status != yajl_gen_status_ok)
    {
        ret = enif_make_tuple(env, 2,
            enif_make_atom(env, "error"),
            enif_make_atom(env, "unknown")
        );
        goto done;
    }
    
    if(!enif_alloc_binary_compat(env, jsonlen, &bin))
    {
        ret = enif_make_atom(env, "memory_error");
        goto done;
    }
    
    memcpy(bin.data, json, jsonlen);
    
    ret = enif_make_tuple(env, 2,
        enif_make_atom(env, "ok"),
        enif_make_binary(env, &bin)
    );

done:
    if(handle != NULL) yajl_gen_free(handle);
    return ret;
}
Exemple #8
0
ERL_NIF_TERM
final_encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM head = argv[0];
    ERL_NIF_TERM term;
    double number;
    encode_ctx ctx;

    ctx.env = env;
    ctx.fill_offset = 0;
    ctx.error = 0;

    if (!enif_alloc_binary_compat(env, 100, &ctx.bin)) {
            return no_mem_error(env);
    }

    while(enif_get_list_cell(env, head, &term, &head)) {
        ErlNifBinary termbin;
        const ERL_NIF_TERM* array;
        int arity;
        int code;

        // We scan the list, looking for things to write into the binary, or
        // encode and then write into the binary. We encode values that are
        // tuples tagged with a type and a value: {Type, Value} where Type
        // is a an Integer and Value is what is to be encoded

        if (enif_get_tuple(env, term, &arity, &array)) {
            // It's a tuple to encode and copy
            if (arity != 2 || !enif_get_int(env, array[0], &code)) {
                // not arity 2 or the first element isn't an int
                ctx.error = BADARG;
                goto done;
            }
            if (code == 0) {
                // {0, String}
                if (encode_string(&ctx, array[1]) != SUCCESS) {
                    goto done;
                }
            }
            else {
                // {1, Double}
                if(!enif_get_double(env, array[1], &number)) {
                    ctx.error = BADARG;
                    goto done;
                }
                // We can't encode these.
                if (isnan(number) || isinf(number)) {
                    ctx.error = BADARG;
                    goto done;
                }
                if ((ctx.error = ensure_buffer(&ctx, 32)) != SUCCESS) {
                    goto done;
                }
                // write the string into the buffer
                snprintf((char*)ctx.bin.data+ctx.fill_offset, 32,
                        "%.16g", number);
                // increment the length
                ctx.fill_offset += strlen((char*)ctx.bin.data+ctx.fill_offset);
            }
        } else if (enif_inspect_binary(env, term, &termbin)) {
            // this is a regular binary, copy the contents into the buffer
            fill_buffer(&ctx, (char*)termbin.data, termbin.size);
            if (ctx.error) {
                goto done;
            }
        }
        else {
            //not a binary, not a tuple, wtf!
            ctx.error = BADARG;
            goto done;
        }
    }
done:
    if (ctx.error == NOMEM) {
        enif_release_binary_compat(env, &ctx.bin);
        return no_mem_error(env);
    } else if (ctx.error == BADARG) {
        enif_release_binary_compat(env, &ctx.bin);
        return enif_make_badarg(env);
    }

    // Resize the binary to our exact final size
    if(!enif_realloc_binary_compat(env, &(ctx.bin), ctx.fill_offset)) {
        enif_release_binary_compat(env, &ctx.bin);
        return no_mem_error(env);
    }
    // make the binary term which transfers ownership
    return enif_make_binary(env, &ctx.bin);
}