Exemplo n.º 1
0
ERL_NIF_TERM exml_parse(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    XML_Parser **parser;
    int is_final, res, errcode;
    ErlNifBinary stream;
    char *errstring;

    assert(argc == 3);

    if (!enif_get_resource(env, argv[0], PARSER_POINTER, (void **)&parser))
        return enif_make_badarg(env);

    if (!enif_is_binary(env, argv[1]))
        return enif_make_badarg(env);

    enif_get_int(env, argv[2], &is_final);
    enif_inspect_binary(env, argv[1], &stream);

    expat_parser *parser_data = XML_GetUserData((XML_Parser)(*parser));
    parser_data->result = enif_make_list(env, 0);
    parser_data->env = env;
    XML_SetUserData((XML_Parser)(*parser), parser_data);

    res = XML_Parse((XML_Parser)(*parser), (const char *)stream.data, stream.size, is_final);
    consume_timeslice(env, stream);
    if(!res)
        {
            errcode = XML_GetErrorCode((XML_Parser)(*parser));
            errstring = (char *)XML_ErrorString(errcode);

            return enif_make_tuple(env, 2, ERROR,
                                   enif_make_string(env, errstring, ERL_NIF_LATIN1));
        }

    return enif_make_tuple(env, 2, OK, parser_data->result);
};
Exemplo n.º 2
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;
}