xref: /6.0.3/couchdb/src/ejson/decode.c (revision c6a29006)
12e99f965SFilipe David Borba Manana // Licensed under the Apache License, Version 2.0 (the "License"); you may not
22e99f965SFilipe David Borba Manana // use this file except in compliance with the License. You may obtain a copy of
32e99f965SFilipe David Borba Manana // the License at
42e99f965SFilipe David Borba Manana //
52e99f965SFilipe David Borba Manana //   http://www.apache.org/licenses/LICENSE-2.0
62e99f965SFilipe David Borba Manana //
72e99f965SFilipe David Borba Manana // Unless required by applicable law or agreed to in writing, software
82e99f965SFilipe David Borba Manana // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
92e99f965SFilipe David Borba Manana // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
102e99f965SFilipe David Borba Manana // License for the specific language governing permissions and limitations under
112e99f965SFilipe David Borba Manana // the License.
122e99f965SFilipe David Borba Manana 
133925e856SFilipe David Borba Manana #include <assert.h>
143925e856SFilipe David Borba Manana #include <stdio.h>
153925e856SFilipe David Borba Manana #include <string.h>
163925e856SFilipe David Borba Manana 
173925e856SFilipe David Borba Manana #include "erl_nif.h"
183925e856SFilipe David Borba Manana #include "erl_nif_compat.h"
193925e856SFilipe David Borba Manana #include "yajl/yajl_parse.h"
203925e856SFilipe David Borba Manana #include "yajl/yajl_parser.h"
213925e856SFilipe David Borba Manana #include "yajl/yajl_lex.h"
22*c6a29006STrond Norbye #include "ejson.h"
233925e856SFilipe David Borba Manana 
243925e856SFilipe David Borba Manana typedef struct {
253925e856SFilipe David Borba Manana     ERL_NIF_TERM head;
263925e856SFilipe David Borba Manana     ErlNifEnv* env;
273925e856SFilipe David Borba Manana } decode_ctx;
283925e856SFilipe David Borba Manana 
29eb0bedf8SDamien Katz #define ENV(ctx) ((decode_ctx*)ctx)->env
303925e856SFilipe David Borba Manana 
313925e856SFilipe David Borba Manana #define CONTINUE 1
323925e856SFilipe David Borba Manana #define CANCEL 0
333925e856SFilipe David Borba Manana 
34eb0bedf8SDamien Katz #define NOERROR 0
35eb0bedf8SDamien Katz #define ERR_MEMORY 1
363925e856SFilipe David Borba Manana 
372c4b88c4SFilipe David Borba Manana 
38*c6a29006STrond Norbye static void * yajl_internal_malloc(void *ctx, unsigned int sz);
39*c6a29006STrond Norbye static void * yajl_internal_realloc(void *ctx, void *previous, unsigned int sz);
402c4b88c4SFilipe David Borba Manana static void yajl_internal_free(void *ctx, void *ptr);
412c4b88c4SFilipe David Borba Manana 
422c4b88c4SFilipe David Borba Manana 
432c4b88c4SFilipe David Borba Manana static yajl_alloc_funcs allocfuncs = {
442c4b88c4SFilipe David Borba Manana     yajl_internal_malloc,
452c4b88c4SFilipe David Borba Manana     yajl_internal_realloc,
462c4b88c4SFilipe David Borba Manana     yajl_internal_free
472c4b88c4SFilipe David Borba Manana };
482c4b88c4SFilipe David Borba Manana 
492c4b88c4SFilipe David Borba Manana 
503925e856SFilipe David Borba Manana static ERL_NIF_TERM
make_error(yajl_handle handle,ErlNifEnv * env)513925e856SFilipe David Borba Manana make_error(yajl_handle handle, ErlNifEnv* env)
523925e856SFilipe David Borba Manana {
533925e856SFilipe David Borba Manana     char* yajlError = (char*) yajl_get_error(handle, 0, NULL, 0);
543925e856SFilipe David Borba Manana     ERL_NIF_TERM errMsg;
553925e856SFilipe David Borba Manana 
563925e856SFilipe David Borba Manana     if(yajlError != NULL)
573925e856SFilipe David Borba Manana     {
583925e856SFilipe David Borba Manana         errMsg = enif_make_string(env, yajlError, ERL_NIF_LATIN1);
593925e856SFilipe David Borba Manana         yajl_free_error(handle, (unsigned char*) yajlError);
603925e856SFilipe David Borba Manana     }
613925e856SFilipe David Borba Manana     else
623925e856SFilipe David Borba Manana     {
633925e856SFilipe David Borba Manana         errMsg = enif_make_string(env, "unknown parse error", ERL_NIF_LATIN1);
643925e856SFilipe David Borba Manana     }
653925e856SFilipe David Borba Manana 
663925e856SFilipe David Borba Manana     return enif_make_tuple(env, 2,
673925e856SFilipe David Borba Manana         enif_make_atom(env, "error"),
683925e856SFilipe David Borba Manana         enif_make_tuple(env, 2,
693925e856SFilipe David Borba Manana             enif_make_uint(env, handle->bytesConsumed),
703925e856SFilipe David Borba Manana             errMsg
713925e856SFilipe David Borba Manana         )
723925e856SFilipe David Borba Manana     );
733925e856SFilipe David Borba Manana }
743925e856SFilipe David Borba Manana 
753925e856SFilipe David Borba Manana 
763925e856SFilipe David Borba Manana static void
add_to_head(void * vctx,ERL_NIF_TERM newhead)773925e856SFilipe David Borba Manana add_to_head(void* vctx, ERL_NIF_TERM newhead)
783925e856SFilipe David Borba Manana {
793925e856SFilipe David Borba Manana     decode_ctx* ctx = (decode_ctx*)vctx;
803925e856SFilipe David Borba Manana     ctx->head = enif_make_list_cell(ctx->env, newhead, ctx->head);
813925e856SFilipe David Borba Manana }
823925e856SFilipe David Borba Manana 
833925e856SFilipe David Borba Manana static int
decode_null(void * ctx)843925e856SFilipe David Borba Manana decode_null(void* ctx)
853925e856SFilipe David Borba Manana {
863925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_atom(ENV(ctx), "null"));
873925e856SFilipe David Borba Manana     return CONTINUE;
883925e856SFilipe David Borba Manana }
893925e856SFilipe David Borba Manana 
903925e856SFilipe David Borba Manana static int
decode_boolean(void * ctx,int val)913925e856SFilipe David Borba Manana decode_boolean(void* ctx, int val)
923925e856SFilipe David Borba Manana {
933925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_atom(ENV(ctx), val ? "true" : "false"));
943925e856SFilipe David Borba Manana     return CONTINUE;
953925e856SFilipe David Borba Manana }
963925e856SFilipe David Borba Manana 
973925e856SFilipe David Borba Manana static int
decode_number(void * ctx,const char * numberVal,unsigned int numberLen)983925e856SFilipe David Borba Manana decode_number(void * ctx, const char * numberVal, unsigned int numberLen)
993925e856SFilipe David Borba Manana {
1003925e856SFilipe David Borba Manana     // scan in the input to see if it's a float or int
1013925e856SFilipe David Borba Manana 
1023925e856SFilipe David Borba Manana     int numberType = 0; // 0 means integer, 1 means float
1033925e856SFilipe David Borba Manana     unsigned int i;
1043925e856SFilipe David Borba Manana     ErlNifBinary bin;
1053925e856SFilipe David Borba Manana     int missingDot = 1;
1063925e856SFilipe David Borba Manana     unsigned int expPos;
1073925e856SFilipe David Borba Manana 
1083925e856SFilipe David Borba Manana     for(i=0; i<numberLen; i++) {
1093925e856SFilipe David Borba Manana         switch (numberVal[i]) {
1103925e856SFilipe David Borba Manana         case '.':
1113925e856SFilipe David Borba Manana             missingDot = 0;
1123925e856SFilipe David Borba Manana             numberType = 1; // it's  a float
1133925e856SFilipe David Borba Manana             goto loopend;
1143925e856SFilipe David Borba Manana         case 'E':
1153925e856SFilipe David Borba Manana         case 'e':
1163925e856SFilipe David Borba Manana             expPos = i;
1173925e856SFilipe David Borba Manana             numberType = 1; // it's  a float
1183925e856SFilipe David Borba Manana             goto loopend;
1193925e856SFilipe David Borba Manana         }
1203925e856SFilipe David Borba Manana     }
1213925e856SFilipe David Borba Manana loopend:
1223925e856SFilipe David Borba Manana     if ((numberType == 1) && missingDot)
1233925e856SFilipe David Borba Manana     {
1243925e856SFilipe David Borba Manana         if(!enif_alloc_binary_compat(ENV(ctx), numberLen + 2, &bin))
1253925e856SFilipe David Borba Manana         {
1263925e856SFilipe David Borba Manana             return CANCEL;
1273925e856SFilipe David Borba Manana         }
1283925e856SFilipe David Borba Manana         memcpy(bin.data, numberVal, expPos);
1293925e856SFilipe David Borba Manana         bin.data[expPos] = '.';
1303925e856SFilipe David Borba Manana         bin.data[expPos + 1] = '0';
1313925e856SFilipe David Borba Manana         memcpy(bin.data + expPos + 2, numberVal + expPos, numberLen - expPos);
1323925e856SFilipe David Borba Manana     }
1333925e856SFilipe David Borba Manana     else
1343925e856SFilipe David Borba Manana     {
1353925e856SFilipe David Borba Manana         if(!enif_alloc_binary_compat(ENV(ctx), numberLen, &bin))
1363925e856SFilipe David Borba Manana         {
1373925e856SFilipe David Borba Manana             return CANCEL;
1383925e856SFilipe David Borba Manana         }
1393925e856SFilipe David Borba Manana         memcpy(bin.data, numberVal, numberLen);
1403925e856SFilipe David Borba Manana     }
1413925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_tuple(ENV(ctx), 2,
1423925e856SFilipe David Borba Manana                         enif_make_int(ENV(ctx), numberType),
1433925e856SFilipe David Borba Manana                         enif_make_binary(ENV(ctx), &bin)));
1443925e856SFilipe David Borba Manana     return CONTINUE;
1453925e856SFilipe David Borba Manana }
1463925e856SFilipe David Borba Manana 
1473925e856SFilipe David Borba Manana 
1483925e856SFilipe David Borba Manana 
1493925e856SFilipe David Borba Manana static int
decode_string(void * ctx,const unsigned char * data,unsigned int size)1503925e856SFilipe David Borba Manana decode_string(void* ctx, const unsigned char* data, unsigned int size)
1513925e856SFilipe David Borba Manana {
1523925e856SFilipe David Borba Manana     ErlNifBinary bin;
1533925e856SFilipe David Borba Manana     if(!enif_alloc_binary_compat(ENV(ctx), size, &bin))
1543925e856SFilipe David Borba Manana     {
1553925e856SFilipe David Borba Manana         return CANCEL;
1563925e856SFilipe David Borba Manana     }
1573925e856SFilipe David Borba Manana     memcpy(bin.data, data, size);
1583925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_binary(ENV(ctx), &bin));
1593925e856SFilipe David Borba Manana     return CONTINUE;
1603925e856SFilipe David Borba Manana }
1613925e856SFilipe David Borba Manana 
1623925e856SFilipe David Borba Manana static int
decode_start_array(void * ctx)1633925e856SFilipe David Borba Manana decode_start_array(void* ctx)
1643925e856SFilipe David Borba Manana {
1653925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_int(ENV(ctx), 0));
1663925e856SFilipe David Borba Manana     return CONTINUE;
1673925e856SFilipe David Borba Manana }
1683925e856SFilipe David Borba Manana 
1693925e856SFilipe David Borba Manana 
1703925e856SFilipe David Borba Manana static int
decode_end_array(void * ctx)1713925e856SFilipe David Borba Manana decode_end_array(void* ctx)
1723925e856SFilipe David Borba Manana {
1733925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_int(ENV(ctx), 1));
1743925e856SFilipe David Borba Manana     return CONTINUE;
1753925e856SFilipe David Borba Manana }
1763925e856SFilipe David Borba Manana 
1773925e856SFilipe David Borba Manana 
1783925e856SFilipe David Borba Manana static int
decode_start_map(void * ctx)1793925e856SFilipe David Borba Manana decode_start_map(void* ctx)
1803925e856SFilipe David Borba Manana {
1813925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_int(ENV(ctx), 2));
1823925e856SFilipe David Borba Manana     return CONTINUE;
1833925e856SFilipe David Borba Manana }
1843925e856SFilipe David Borba Manana 
1853925e856SFilipe David Borba Manana 
1863925e856SFilipe David Borba Manana static int
decode_end_map(void * ctx)1873925e856SFilipe David Borba Manana decode_end_map(void* ctx)
1883925e856SFilipe David Borba Manana {
1893925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_int(ENV(ctx), 3));
1903925e856SFilipe David Borba Manana     return CONTINUE;
1913925e856SFilipe David Borba Manana }
1923925e856SFilipe David Borba Manana 
1933925e856SFilipe David Borba Manana 
1943925e856SFilipe David Borba Manana static int
decode_map_key(void * ctx,const unsigned char * data,unsigned int size)1953925e856SFilipe David Borba Manana decode_map_key(void* ctx, const unsigned char* data, unsigned int size)
1963925e856SFilipe David Borba Manana {
1973925e856SFilipe David Borba Manana     ErlNifBinary bin;
1983925e856SFilipe David Borba Manana     if(!enif_alloc_binary_compat(ENV(ctx), size, &bin))
1993925e856SFilipe David Borba Manana     {
2003925e856SFilipe David Borba Manana        return CANCEL;
2013925e856SFilipe David Borba Manana     }
2023925e856SFilipe David Borba Manana     memcpy(bin.data, data, size);
2033925e856SFilipe David Borba Manana     add_to_head(ctx, enif_make_tuple(ENV(ctx), 2,
2043925e856SFilipe David Borba Manana                         enif_make_int(ENV(ctx), 3),
2053925e856SFilipe David Borba Manana                         enif_make_binary(ENV(ctx), &bin)));
2063925e856SFilipe David Borba Manana     return CONTINUE;
2073925e856SFilipe David Borba Manana }
2083925e856SFilipe David Borba Manana 
2093925e856SFilipe David Borba Manana static yajl_callbacks
2103925e856SFilipe David Borba Manana decoder_callbacks = {
2113925e856SFilipe David Borba Manana     decode_null,
2123925e856SFilipe David Borba Manana     decode_boolean,
2133925e856SFilipe David Borba Manana     NULL,
2143925e856SFilipe David Borba Manana     NULL,
2153925e856SFilipe David Borba Manana     decode_number,
2163925e856SFilipe David Borba Manana     decode_string,
2173925e856SFilipe David Borba Manana     decode_start_map,
2183925e856SFilipe David Borba Manana     decode_map_key,
2193925e856SFilipe David Borba Manana     decode_end_map,
2203925e856SFilipe David Borba Manana     decode_start_array,
2213925e856SFilipe David Borba Manana     decode_end_array
2223925e856SFilipe David Borba Manana };
2233925e856SFilipe David Borba Manana 
2245f4e2298SAaron Miller 
2253925e856SFilipe David Borba Manana static int
check_rest(unsigned char * data,unsigned int size,unsigned int used)2263925e856SFilipe David Borba Manana check_rest(unsigned char* data, unsigned int size, unsigned int used)
2273925e856SFilipe David Borba Manana {
2283925e856SFilipe David Borba Manana     unsigned int i = 0;
2293925e856SFilipe David Borba Manana     for(i = used; i < size; i++)
2303925e856SFilipe David Borba Manana     {
2313925e856SFilipe David Borba Manana         switch(data[i])
2323925e856SFilipe David Borba Manana         {
2333925e856SFilipe David Borba Manana             case ' ':
2343925e856SFilipe David Borba Manana             case '\t':
2353925e856SFilipe David Borba Manana             case '\r':
2363925e856SFilipe David Borba Manana             case '\n':
2373925e856SFilipe David Borba Manana                 continue;
2383925e856SFilipe David Borba Manana             default:
2393925e856SFilipe David Borba Manana                 return CANCEL;
2403925e856SFilipe David Borba Manana         }
2413925e856SFilipe David Borba Manana     }
2423925e856SFilipe David Borba Manana 
2433925e856SFilipe David Borba Manana     return CONTINUE;
2443925e856SFilipe David Borba Manana }
2453925e856SFilipe David Borba Manana 
2463925e856SFilipe David Borba Manana ERL_NIF_TERM
validate_doc(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])2475f4e2298SAaron Miller validate_doc(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
2485f4e2298SAaron Miller {
249cb003124SBin Cui     yajl_parser_config conf = {0, 1};
250cb003124SBin Cui     yajl_handle handle;
251cb003124SBin Cui 
252cb003124SBin Cui     yajl_status status;
253cb003124SBin Cui     ErlNifBinary json;
254cb003124SBin Cui     ERL_NIF_TERM ret;
255cb003124SBin Cui 
2566b9fa5f1SAaron Miller     handle = yajl_alloc(NULL, &conf, &allocfuncs, NULL);
2575f4e2298SAaron Miller 
2585f4e2298SAaron Miller     if(!enif_inspect_iolist_as_binary(env, argv[0], &json))
2595f4e2298SAaron Miller     {
2605f4e2298SAaron Miller         ret = enif_make_badarg(env);
2615f4e2298SAaron Miller         goto done;
2625f4e2298SAaron Miller     }
2635f4e2298SAaron Miller 
2645f4e2298SAaron Miller     status = yajl_parse(handle, json.data, json.size);
2655f4e2298SAaron Miller 
266eb0bedf8SDamien Katz     if(status == yajl_status_insufficient_data &&
267eb0bedf8SDamien Katz        handle->bytesConsumed == json.size)
2685f4e2298SAaron Miller     {
2695f4e2298SAaron Miller         status = yajl_parse_complete(handle);
2705f4e2298SAaron Miller     }
2715f4e2298SAaron Miller 
2725f4e2298SAaron Miller     if(status == yajl_status_ok)
2735f4e2298SAaron Miller     {
274eb0bedf8SDamien Katz         if(handle->bytesConsumed != json.size &&
275eb0bedf8SDamien Katz             check_rest(json.data, json.size, handle->bytesConsumed) == CANCEL)
2765f4e2298SAaron Miller         {
2775f4e2298SAaron Miller             ret = enif_make_tuple(env, 2,
2785f4e2298SAaron Miller                 enif_make_atom(env, "error"),
2795f4e2298SAaron Miller                 enif_make_atom(env, "garbage_after_value")
2805f4e2298SAaron Miller             );
2815f4e2298SAaron Miller         }
2825f4e2298SAaron Miller         else
2835f4e2298SAaron Miller         {
2846b9fa5f1SAaron Miller             ret = enif_make_atom(env, "ok");
285eb0bedf8SDamien Katz         }
286eb0bedf8SDamien Katz     }
287eb0bedf8SDamien Katz     else
288eb0bedf8SDamien Katz     {
2895f4e2298SAaron Miller         ret = enif_make_tuple(env, 2,
2905f4e2298SAaron Miller                 enif_make_atom(env, "error"),
2915f4e2298SAaron Miller                 enif_make_atom(env, "invalid_json")
2925f4e2298SAaron Miller                 );
2935f4e2298SAaron Miller     }
2945f4e2298SAaron Miller 
2955f4e2298SAaron Miller done:
2965f4e2298SAaron Miller     if(handle != NULL) yajl_free(handle);
2975f4e2298SAaron Miller     return ret;
2985f4e2298SAaron Miller }
2995f4e2298SAaron Miller 
3005f4e2298SAaron Miller ERL_NIF_TERM
reverse_tokens(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])3013925e856SFilipe David Borba Manana reverse_tokens(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
3023925e856SFilipe David Borba Manana {
3033925e856SFilipe David Borba Manana     decode_ctx ctx;
3043925e856SFilipe David Borba Manana     yajl_parser_config conf = {0, 1}; // No comments, check utf8
3052c4b88c4SFilipe David Borba Manana     yajl_handle handle = yajl_alloc(&decoder_callbacks, &conf, &allocfuncs, &ctx);
3063925e856SFilipe David Borba Manana     yajl_status status;
3073925e856SFilipe David Borba Manana     unsigned int used;
3083925e856SFilipe David Borba Manana     ErlNifBinary bin;
3093925e856SFilipe David Borba Manana     ERL_NIF_TERM ret;
3103925e856SFilipe David Borba Manana 
3113925e856SFilipe David Borba Manana     ctx.env = env;
3123925e856SFilipe David Borba Manana     ctx.head = enif_make_list_from_array(env, NULL, 0);
3133925e856SFilipe David Borba Manana 
3143925e856SFilipe David Borba Manana     if(!enif_inspect_iolist_as_binary(env, argv[0], &bin))
3153925e856SFilipe David Borba Manana     {
3163925e856SFilipe David Borba Manana         ret = enif_make_badarg(env);
3173925e856SFilipe David Borba Manana         goto done;
3183925e856SFilipe David Borba Manana     }
3193925e856SFilipe David Borba Manana 
3203925e856SFilipe David Borba Manana     status = yajl_parse(handle, bin.data, bin.size);
3213925e856SFilipe David Borba Manana     used = handle->bytesConsumed;
3223925e856SFilipe David Borba Manana 
3233925e856SFilipe David Borba Manana     // Parsing something like "2.0" (without quotes) will
3243925e856SFilipe David Borba Manana     // cause a spurious semi-error. We add the extra size
3253925e856SFilipe David Borba Manana     // check so that "2008-20-10" doesn't pass.
3263925e856SFilipe David Borba Manana     if(status == yajl_status_insufficient_data && used == bin.size)
3273925e856SFilipe David Borba Manana     {
3283925e856SFilipe David Borba Manana         status = yajl_parse_complete(handle);
3293925e856SFilipe David Borba Manana     }
3303925e856SFilipe David Borba Manana 
3313925e856SFilipe David Borba Manana     if(status == yajl_status_ok && used != bin.size)
3323925e856SFilipe David Borba Manana     {
3333925e856SFilipe David Borba Manana         if(check_rest(bin.data, bin.size, used) == CANCEL)
3343925e856SFilipe David Borba Manana         {
3353925e856SFilipe David Borba Manana             ret = enif_make_tuple(env, 2,
3363925e856SFilipe David Borba Manana                 enif_make_atom(env, "error"),
3373925e856SFilipe David Borba Manana                 enif_make_atom(env, "garbage_after_value")
3383925e856SFilipe David Borba Manana             );
3393925e856SFilipe David Borba Manana             goto done;
3403925e856SFilipe David Borba Manana         }
3413925e856SFilipe David Borba Manana     }
3423925e856SFilipe David Borba Manana 
3433925e856SFilipe David Borba Manana     switch(status)
3443925e856SFilipe David Borba Manana     {
3453925e856SFilipe David Borba Manana         case yajl_status_ok:
3463925e856SFilipe David Borba Manana             ret = enif_make_tuple(env, 2, enif_make_atom(env, "ok"), ctx.head);
3473925e856SFilipe David Borba Manana             goto done;
3483925e856SFilipe David Borba Manana 
3493925e856SFilipe David Borba Manana         case yajl_status_error:
3503925e856SFilipe David Borba Manana             ret = make_error(handle, env);
3513925e856SFilipe David Borba Manana             goto done;
3523925e856SFilipe David Borba Manana 
3533925e856SFilipe David Borba Manana         case yajl_status_insufficient_data:
3543925e856SFilipe David Borba Manana             ret = enif_make_tuple(env, 2,
3553925e856SFilipe David Borba Manana                 enif_make_atom(env, "error"),
3563925e856SFilipe David Borba Manana                 enif_make_atom(env, "insufficient_data")
3573925e856SFilipe David Borba Manana             );
3583925e856SFilipe David Borba Manana             goto done;
3593925e856SFilipe David Borba Manana 
3603925e856SFilipe David Borba Manana         case yajl_status_client_canceled:
3613925e856SFilipe David Borba Manana         /* the only time we do this is when we can't allocate a binary. */
3623925e856SFilipe David Borba Manana             ret = enif_make_tuple(env, 2,
3633925e856SFilipe David Borba Manana                 enif_make_atom(env, "error"),
3643925e856SFilipe David Borba Manana                 enif_make_atom(env, "insufficient_memory")
3653925e856SFilipe David Borba Manana             );
3663925e856SFilipe David Borba Manana             goto done;
3673925e856SFilipe David Borba Manana 
3683925e856SFilipe David Borba Manana         default:
3693925e856SFilipe David Borba Manana             ret = enif_make_tuple(env, 2,
3703925e856SFilipe David Borba Manana                 enif_make_atom(env, "error"),
3713925e856SFilipe David Borba Manana                 enif_make_atom(env, "unknown")
3723925e856SFilipe David Borba Manana             );
3733925e856SFilipe David Borba Manana             goto done;
3743925e856SFilipe David Borba Manana     }
3753925e856SFilipe David Borba Manana 
3763925e856SFilipe David Borba Manana done:
3773925e856SFilipe David Borba Manana     if(handle != NULL) yajl_free(handle);
3783925e856SFilipe David Borba Manana     return ret;
3793925e856SFilipe David Borba Manana }
3802c4b88c4SFilipe David Borba Manana 
3812c4b88c4SFilipe David Borba Manana 
yajl_internal_malloc(void * ctx,unsigned int sz)382*c6a29006STrond Norbye static void * yajl_internal_malloc(void *ctx, unsigned int sz)
3832c4b88c4SFilipe David Borba Manana {
3842c4b88c4SFilipe David Borba Manana     return enif_alloc(sz);
3852c4b88c4SFilipe David Borba Manana }
3862c4b88c4SFilipe David Borba Manana 
yajl_internal_realloc(void * ctx,void * previous,unsigned int sz)387*c6a29006STrond Norbye static void * yajl_internal_realloc(void *ctx, void *previous, unsigned int sz)
3882c4b88c4SFilipe David Borba Manana {
3892c4b88c4SFilipe David Borba Manana     return enif_realloc(previous, sz);
3902c4b88c4SFilipe David Borba Manana }
3912c4b88c4SFilipe David Borba Manana 
yajl_internal_free(void * ctx,void * ptr)3922c4b88c4SFilipe David Borba Manana static void yajl_internal_free(void *ctx, void *ptr)
3932c4b88c4SFilipe David Borba Manana {
3942c4b88c4SFilipe David Borba Manana     enif_free(ptr);
3952c4b88c4SFilipe David Borba Manana }
396