Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add missing files.

add enhanced EEP0018 (better utf-8 encoding)
  • Loading branch information...
commit 26bcc3872c289d2bdf7cd24fbdcfb2cd3451ff30 1 parent b059ab6
unknown authored
Showing with 4,521 additions and 1 deletion.
  1. +1 −1  lib/Makefile
  2. +5 −0 lib/eep0018/Makefile
  3. +51 −0 lib/eep0018/c_src/Makefile
  4. +464 −0 lib/eep0018/c_src/decode_json.c
  5. +68 −0 lib/eep0018/c_src/eep0018.c
  6. +22 −0 lib/eep0018/c_src/eep0018.h
  7. +413 −0 lib/eep0018/c_src/encode_json.c
  8. +190 −0 lib/eep0018/c_src/term_buf.c
  9. +50 −0 lib/eep0018/c_src/term_buf.h
  10. +152 −0 lib/eep0018/c_src/yajl.c
  11. +65 −0 lib/eep0018/c_src/yajl_alloc.c
  12. +50 −0 lib/eep0018/c_src/yajl_alloc.h
  13. +119 −0 lib/eep0018/c_src/yajl_buf.c
  14. +66 −0 lib/eep0018/c_src/yajl_buf.h
  15. +85 −0 lib/eep0018/c_src/yajl_common.h
  16. +234 −0 lib/eep0018/c_src/yajl_encode.c
  17. +44 −0 lib/eep0018/c_src/yajl_encode.h
  18. +297 −0 lib/eep0018/c_src/yajl_gen.c
  19. +124 −0 lib/eep0018/c_src/yajl_gen.h
  20. +749 −0 lib/eep0018/c_src/yajl_lex.c
  21. +133 −0 lib/eep0018/c_src/yajl_lex.h
  22. +179 −0 lib/eep0018/c_src/yajl_parse.h
  23. +475 −0 lib/eep0018/c_src/yajl_parser.c
  24. +86 −0 lib/eep0018/c_src/yajl_parser.h
  25. +1 −0  lib/eep0018/src/Makefile
  26. +37 −0 lib/eep0018/src/eep0018.erl
  27. +93 −0 lib/eep0018/src/gen_linkedin_driver.erl
  28. +268 −0 lib/mcache/src/dynamic_compile.erl
View
2  lib/Makefile
@@ -1,3 +1,3 @@
include $(ERL_TOP)/make/subdir.mk
-SUB_DIRECTORIES = mcache
+SUB_DIRECTORIES = eep0018 mcache
View
5 lib/eep0018/Makefile
@@ -0,0 +1,5 @@
+include $(ERL_TOP)/make/otp.mk
+
+SUB_DIRECTORIES = src c_src
+
+include $(ERL_TOP)/make/subdir.mk
View
51 lib/eep0018/c_src/Makefile
@@ -0,0 +1,51 @@
+include $(ERL_TOP)/make/otp.mk
+
+OBJ_DIR = ../obj
+LIB_DIR = $(PRIV_DIR)/lib
+
+ERLENV = $(shell env escript $(ERL_TOP)/make/erlenv.escript)
+ERL_ROOT_DIR = $(word 1,$(ERLENV))
+ERL_EI_DIR = $(word 2,$(ERLENV))
+
+CC = gcc
+LD = gcc
+CFLAGS = -g -O2 -D_REENTRANT -DUSE_THREADS -D_GNU_SOURCE -fPIC
+LDFLAGS = -shared
+
+ALL_CFLAGS = -I . -I $(ERL_ROOT_DIR)/usr/include -I $(ERL_EI_DIR)/include
+LDLIBS = -L $(ERL_EI_DIR)/lib -L $(ERL_ROOT_DIR)/usr/lib -lei -lerl_interface
+
+EEP0018_OBJS = $(OBJ_DIR)/decode_json.o \
+ $(OBJ_DIR)/eep0018.o \
+ $(OBJ_DIR)/encode_json.o \
+ $(OBJ_DIR)/term_buf.o \
+ $(OBJ_DIR)/yajl_alloc.o \
+ $(OBJ_DIR)/yajl_buf.o \
+ $(OBJ_DIR)/yajl.o \
+ $(OBJ_DIR)/yajl_encode.o \
+ $(OBJ_DIR)/yajl_gen.o \
+ $(OBJ_DIR)/yajl_lex.o \
+ $(OBJ_DIR)/yajl_parser.o
+
+DYN_DRIVER = $(LIB_DIR)/eep0018_drv.so
+
+debug opt: $(OBJ_DIR) $(LIB_DIR) $(DYN_DRIVER)
+
+$(OBJ_DIR):
+ -@mkdir -p $(OBJ_DIR)
+ echo $(ERLENV)
+
+$(LIB_DIR):
+ -@mkdir -p $(LIB_DIR)
+
+$(OBJ_DIR)/%.o: %.c
+ -$(INSTALL_DIR) $(OBJ_DIR)
+ $(CC) -c -o $@ $(CFLAGS) $(ALL_CFLAGS) $<
+
+$(LIB_DIR)/eep0018_drv.so: $(EEP0018_OBJS) Makefile
+ -$(INSTALL_DIR) $(LIB_DIR)
+ $(LD) $(LDFLAGS) -o $@ $(EEP0018_OBJS) $(LDLIBS)
+
+
+clean:
+ -@rm -rf $(LIB_DIR) $(OBJ_DIR)
View
464 lib/eep0018/c_src/decode_json.c
@@ -0,0 +1,464 @@
+/* Copyright (c) 2008-2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+ * Copyright (c) 2008-2009 Enrico Thierbach <eno@open-lab.org>
+ *
+ * This file is part of EEP0018, which is released under the MIT license.
+ */
+
+#ifndef WIN32
+#include <string.h>
+#endif
+
+#include "eep0018.h"
+#include "yajl_parse.h"
+
+#define INIT_DBL_LEN 1024
+#define INIT_TERM_LEN 4096
+#define INIT_OBJ_LEN 256
+#define INIT_STR_LEN 4096
+
+#define NO_TYPE 0
+#define MAP_TYPE 1
+#define ARRAY_TYPE 2
+
+#define CHECK(call) if((call) != OK) goto done
+
+typedef ErlDrvTermData TermData;
+typedef unsigned char uchar;
+
+typedef struct
+{
+ double* dbl_data;
+ int dbl_length;
+ int dbl_used;
+
+ TermData* term_data;
+ int term_length;
+ int term_used;
+
+ char* obj_types;
+ int* obj_members;
+ int obj_length;
+ int obj_used;
+
+ uchar* str_start;
+ uchar* str_end;
+ uchar* str_data;
+ int str_length;
+ int str_used;
+
+ TermData nullTerm;
+ TermData trueTerm;
+ TermData falseTerm;
+} Decoder;
+
+void destroy_decoder(Decoder* dec);
+
+Decoder*
+init_decoder(uchar* str_start, uchar* str_end)
+{
+ int status = ERROR;
+ Decoder* dec = (Decoder*) malloc(sizeof(Decoder));
+ if(dec == NULL) goto done;
+ memset(dec, 0, sizeof(Decoder));
+
+ dec->dbl_data = (double*) malloc(INIT_DBL_LEN * sizeof(double));
+ if(dec->dbl_data == NULL) goto done;
+ dec->dbl_length = INIT_DBL_LEN;
+ dec->dbl_used = 0;
+
+ dec->term_data = (TermData*) malloc(INIT_TERM_LEN * sizeof(TermData));
+ if(dec->term_data == NULL) goto done;
+ dec->term_length = INIT_TERM_LEN;
+ dec->term_used = 0;
+
+ dec->obj_types = (char*) malloc(INIT_OBJ_LEN * sizeof(char));
+ if(dec->obj_types == NULL) goto done;
+ dec->obj_members = (int*) malloc(INIT_OBJ_LEN * sizeof(int));
+ if(dec->obj_members == NULL) goto done;
+ dec->obj_length = INIT_OBJ_LEN;
+ dec->obj_used = 0;
+
+ dec->str_start = str_start;
+ dec->str_end = str_end;
+ dec->str_data = (uchar*) malloc(INIT_STR_LEN * sizeof(uchar));
+ if(dec->str_data == NULL) goto done;
+ dec->str_length = INIT_STR_LEN;
+ dec->str_used = 0;
+
+ dec->nullTerm = driver_mk_atom("null");
+ dec->trueTerm = driver_mk_atom("true");
+ dec->falseTerm = driver_mk_atom("false");
+
+ status = OK;
+
+done:
+ if(status != OK && dec != NULL)
+ {
+ destroy_decoder(dec);
+ dec = NULL;
+ }
+
+ return dec;
+}
+
+void
+destroy_decoder(Decoder* dec)
+{
+ if(dec == NULL) return;
+ if(dec->dbl_data != NULL) free(dec->dbl_data);
+ if(dec->term_data != NULL) free(dec->term_data);
+ if(dec->obj_types != NULL) free(dec->obj_types);
+ if(dec->obj_members != NULL) free(dec->obj_members);
+ if(dec->str_data != NULL) free(dec->str_data);
+ free(dec);
+}
+
+static inline double*
+add_double(Decoder* dec, double val)
+{
+ double* ret = NULL;
+ double* next = NULL;
+
+ if(dec->dbl_used >= dec->dbl_length)
+ {
+ next = (double*) malloc(dec->dbl_length * 2 * sizeof(double));
+ if(next == NULL) goto done;
+
+ memcpy(next, dec->dbl_data, dec->dbl_length * sizeof(double));
+ free(dec->dbl_data);
+ dec->dbl_data = next;
+
+ dec->dbl_length *= 2;
+ }
+
+ dec->dbl_data[dec->dbl_used++] = val;
+ ret = dec->dbl_data + (dec->dbl_used-1);
+
+done:
+ return ret;
+}
+
+static inline int
+add_term(Decoder* dec, TermData val)
+{
+ int ret = ERROR;
+ TermData* next = NULL;
+
+ if(dec->term_used >= dec->term_length)
+ {
+ next = (TermData*) malloc(dec->term_length * 2 * sizeof(TermData));
+ if(next == NULL) goto done;
+
+ memcpy(next, dec->term_data, dec->term_length * sizeof(TermData));
+ free(dec->term_data);
+ dec->term_data = next;
+
+ dec->term_length *= 2;
+ }
+
+ dec->term_data[dec->term_used++] = val;
+ ret = OK;
+
+done:
+ return ret;
+}
+
+static inline int
+open_object(Decoder* dec, char type)
+{
+ int ret = ERROR;
+ char* next_typ = NULL;
+ int* next_mem = NULL;
+
+ if(dec->obj_used >= dec->obj_length)
+ {
+ next_typ = (char*) malloc(dec->obj_length * 2 * sizeof(char));
+ if(next_typ == NULL) goto done;
+ next_mem = (int*) malloc(dec->obj_length * 2 * sizeof(int));
+ if(next_mem == NULL) goto done;
+
+ memcpy(next_typ, dec->obj_types, dec->obj_length * sizeof(char));
+ free(dec->obj_types);
+ dec->obj_types = next_typ;
+ next_typ = NULL;
+
+ memcpy(next_mem, dec->obj_members, dec->obj_length * sizeof(int));
+ free(dec->obj_members);
+ dec->obj_members = next_mem;
+ next_mem = NULL;
+
+ dec->obj_length *= 2;
+ }
+
+ dec->obj_types[dec->obj_used] = type;
+ dec->obj_members[dec->obj_used] = 0;
+ dec->obj_used++;
+ ret = OK;
+
+done:
+ if(ret != OK && next_typ != NULL) free(next_typ);
+ if(ret != OK && next_mem != NULL) free(next_mem);
+ return ret;
+}
+
+static inline int
+check_object(Decoder* dec)
+{
+ if(dec->obj_used == 0) return OK;
+
+ // Adding a member to this object.
+ dec->obj_members[dec->obj_used-1]++;
+
+ if(dec->obj_types[dec->obj_used-1] != MAP_TYPE) return OK;
+
+ //fprintf(stderr, "Adding map tuple\n");
+ if(!add_term(dec, ERL_DRV_TUPLE)) return ERROR;
+ return add_term(dec, 2);
+}
+
+static inline int
+close_object(Decoder* dec)
+{
+ int ret = ERROR;
+
+ if(dec->obj_used < 1) goto done;
+
+ if(dec->obj_types[dec->obj_used-1] == MAP_TYPE)
+ {
+ // {"foo": 1} -> {[{<<"foo">>, 1}]}
+ // Close proplist
+ CHECK(add_term(dec, ERL_DRV_NIL));
+ CHECK(add_term(dec, ERL_DRV_LIST));
+ CHECK(add_term(dec, dec->obj_members[dec->obj_used-1]+1));
+
+ /*
+ // Close tuple
+ CHECK(add_term(dec, ERL_DRV_TUPLE));
+ CHECK(add_term(dec, 1));
+ */
+ }
+ else if(dec->obj_types[dec->obj_used-1] == ARRAY_TYPE)
+ {
+ // Close list
+ CHECK(add_term(dec, ERL_DRV_NIL));
+ CHECK(add_term(dec, ERL_DRV_LIST));
+ CHECK(add_term(dec, dec->obj_members[dec->obj_used-1]+1));
+ }
+ else
+ {
+ // Invalid object type.
+ goto done;
+ }
+
+ dec->obj_types[dec->obj_used] = NO_TYPE;
+ dec->obj_members[dec->obj_used] = 0;
+ dec->obj_used--;
+ ret = OK;
+
+done:
+ return ret;
+}
+
+static inline const uchar*
+add_string(Decoder* dec, const uchar* buf, unsigned int length)
+{
+ const uchar* ret = NULL;
+ uchar* next = NULL;
+ int new_length = 0;
+
+ // String still in buffer
+ if(buf >= dec->str_start && buf <= dec->str_end) return buf;
+
+ if(length > dec->str_length - dec->str_used)
+ {
+ new_length = 2 * dec->str_length;
+ if(length > new_length - dec->str_used) new_length += 2 * length;
+ next = (uchar*) malloc(new_length * sizeof(uchar));
+ if(next == NULL) goto done;
+
+ memcpy(next, dec->str_data, dec->str_length * sizeof(uchar));
+ free(dec->str_data);
+ dec->str_data = next;
+
+ dec->str_length = new_length;
+ }
+
+ memcpy(dec->str_data + dec->str_used, buf, length * sizeof(uchar));
+ dec->str_used += length;
+ ret = dec->str_data + (dec->str_used - length);
+done:
+ return ret;
+}
+
+static inline int
+json_null(void* ctx)
+{
+ //fprintf(stderr, "null\n");
+ Decoder* dec = (Decoder*) ctx;
+ if(add_term(dec, ERL_DRV_ATOM) != OK) return ERROR;
+ if(add_term(dec, dec->nullTerm) != OK) return ERROR;
+ return check_object(dec);
+}
+
+static inline int
+json_boolean(void* ctx, int boolVal)
+{
+ //fprintf(stderr, "boolean\n");
+ Decoder* dec = (Decoder*) ctx;
+ if(boolVal)
+ {
+ if(add_term(dec, ERL_DRV_ATOM) != OK) return ERROR;
+ if(add_term(dec, dec->trueTerm) != OK) return ERROR;
+ }
+ else
+ {
+ if(add_term(dec, ERL_DRV_ATOM) != OK) return ERROR;
+ if(add_term(dec, dec->falseTerm) != OK) return ERROR;
+ }
+
+ return check_object(dec);
+}
+
+static inline int
+json_integer(void* ctx, long integerVal)
+{
+ //fprintf(stderr, "integer\n");
+ Decoder* dec = (Decoder*) ctx;
+ if(add_term(dec, ERL_DRV_INT) != OK) return ERROR;
+ if(add_term(dec, (ErlDrvSInt) integerVal) != OK) return ERROR;
+ return check_object(dec);
+}
+
+static inline int
+json_double(void* ctx, double doubleVal)
+{
+ //fprintf(stderr, "double\n");
+ Decoder* dec = (Decoder*) ctx;
+ double* pos = add_double(dec, doubleVal);
+ if(pos == NULL) return ERROR;
+
+ if(add_term(dec, ERL_DRV_FLOAT) != OK) return ERROR;
+ if(add_term(dec, (TermData) pos) != OK) return ERROR;
+ return check_object(dec);
+}
+
+static inline int
+json_string(void* ctx, const unsigned char* stringVal, unsigned int stringLen)
+{
+ //fprintf(stderr, "string\n");
+ Decoder* dec = (Decoder*) ctx;
+ const uchar* data = add_string(dec, stringVal, stringLen);
+ if(add_term(dec, ERL_DRV_BUF2BINARY) != OK) return ERROR;
+ if(add_term(dec, (ErlDrvTermData) data) != OK) return ERROR;
+ if(add_term(dec, stringLen) != OK) return ERROR;
+ return check_object(dec);
+}
+
+static inline int
+json_start_map(void* ctx)
+{
+ //fprintf(stderr, "map start\n");
+ Decoder* dec = (Decoder*) ctx;
+ return open_object(dec, MAP_TYPE);
+}
+
+static inline int
+json_map_key(void* ctx, const unsigned char* key, unsigned int stringLen)
+{
+ //fprintf(stderr, "map key\n");
+ Decoder* dec = (Decoder*) ctx;
+ const uchar* buf = add_string(dec, key, stringLen);
+ if(key == NULL) return ERROR;
+ if(add_term(dec, ERL_DRV_BUF2BINARY) != OK) return ERROR;
+ if(add_term(dec, (ErlDrvTermData) buf) != OK) return ERROR;
+ return add_term(dec, stringLen);
+}
+
+static inline int
+json_end_map(void* ctx)
+{
+ //fprintf(stderr, "map end\n");
+ Decoder* dec = (Decoder*) ctx;
+ if(close_object(dec) != OK) return ERROR;
+ return check_object(dec);
+}
+
+static inline int
+json_start_array(void* ctx)
+{
+ //fprintf(stderr, "array start\n");
+ Decoder* dec = (Decoder*) ctx;
+ return open_object(dec, ARRAY_TYPE);
+}
+
+static inline int
+json_end_array(void* ctx)
+{
+ //fprintf(stderr, "array end\n");
+ Decoder* dec = (Decoder*) ctx;
+ if(close_object(dec) != OK) return ERROR;
+ return check_object(dec);
+}
+
+static yajl_callbacks json_callbacks = {
+ json_null,
+ json_boolean,
+ json_integer,
+ json_double,
+ NULL,
+ json_string,
+ json_start_map,
+ json_map_key,
+ json_end_map,
+ json_start_array,
+ json_end_array
+};
+
+int
+decode_json(ErlDrvPort port, char* buf, int len, char** rbuf, int rlen)
+{
+ unsigned char* ubuf = (unsigned char*) buf;
+ int ret = -1;
+ int resp;
+ uchar* mesg = NULL;
+ int mlen = 0;
+
+ Decoder* dec = init_decoder(ubuf, ubuf+len);
+ if(dec == NULL) goto done;
+
+ // Setup so we return {ok, Json}
+ if(add_term(dec, ERL_DRV_ATOM) != OK) goto done;
+ if(add_term(dec, driver_mk_atom("json")) != OK) goto done;
+
+ yajl_parser_config conf = {0, 1}; // No comments, check utf8
+ yajl_handle handle = yajl_alloc(&json_callbacks, &conf, NULL, dec);
+ yajl_status status = yajl_parse(handle, (unsigned char*) buf, len);
+
+ if(status != yajl_status_ok)
+ {
+ mesg = yajl_get_error(handle, 0, NULL, 0);
+ mlen = strlen((char*) mesg);
+ memcpy(*rbuf, mesg, mlen < rlen ? mlen : rlen);
+ ret = mlen < rlen ? mlen : rlen;
+ goto done;
+ }
+
+ // Finish the tuple of the our response
+ if(add_term(dec, ERL_DRV_TUPLE) != OK) goto done;
+ if(add_term(dec, 2) != OK) goto done;
+
+ *rbuf = NULL;
+ resp = driver_send_term(
+ port,
+ driver_caller(port),
+ dec->term_data,
+ dec->term_used
+ );
+ if(resp == 1) ret = 0;
+
+done:
+ if(mesg != NULL) yajl_free_error(handle, mesg);
+ if(handle != NULL) yajl_free(handle);
+ destroy_decoder(dec);
+ return ret;
+}
View
68 lib/eep0018/c_src/eep0018.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2008-2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+ * Copyright (c) 2008-2009 Enrico Thierbach <eno@open-lab.org>
+ *
+ * This file is part of EEP0018, which is released under the MIT license.
+ */
+
+#include "eep0018.h"
+
+static ErlDrvData
+eep0018_start(ErlDrvPort port, char *buff)
+{
+ if(port == NULL) return ERL_DRV_ERROR_GENERAL;
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+ return (ErlDrvData) port;
+}
+
+static int
+eep0018_control(
+ ErlDrvData drv_data,
+ unsigned int command,
+ char* buf,
+ int len,
+ char** rbuf,
+ int rlen
+)
+{
+ switch(command)
+ {
+ case 0:
+ return encode_json(buf, len, rbuf, rlen);
+ case 1:
+ return decode_json((ErlDrvPort) drv_data, buf, len, rbuf, rlen);
+ default:
+ return -1;
+ }
+}
+
+static ErlDrvEntry
+eep0018_driver_entry =
+{
+ NULL, /* Init */
+ eep0018_start,
+ NULL, /* Stop */
+ NULL, /* Output */
+ NULL, /* Input Ready */
+ NULL, /* Output Ready */
+ "eep0018_drv", /* Driver Name */
+ NULL, /* Finish */
+ NULL, /* Handle */
+ eep0018_control, /* Control */
+ NULL, /* Timeout */
+ NULL, /* Outputv */
+ NULL, /* Ready Async */
+ NULL, /* Flush */
+ NULL, /* Call */
+ NULL, /* Event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ ERL_DRV_FLAG_USE_PORT_LOCKING,
+ NULL, /* Reserved */
+ NULL, /* Process Exit */
+};
+
+DRIVER_INIT(eep0018_drv) /* must match name in driver_entry */
+{
+ return &eep0018_driver_entry;
+}
View
22 lib/eep0018/c_src/eep0018.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2008-2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+ * Copyright (c) 2008-2009 Enrico Thierbach <eno@open-lab.org>
+ *
+ * This file is part of EEP0018, which is released under the MIT license.
+ */
+
+#ifndef __EEP0018_H__
+#define __EEP0018_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <erl_driver.h>
+
+#define OK 1
+#define ERROR 0
+
+int encode_json(char* buf, int len, char** rbuf, int rlen);
+int decode_json(ErlDrvPort port, char* buf, int len, char** rbuf, int rlen);
+
+#endif
View
413 lib/eep0018/c_src/encode_json.c
@@ -0,0 +1,413 @@
+/* Copyright (c) 2008-2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+ * Copyright (c) 2008-2009 Enrico Thierbach <eno@open-lab.org>
+ *
+ * This file is part of EEP0018, which is released under the MIT license.
+ */
+
+#include <ei.h>
+
+#ifndef WIN32
+#include <string.h>
+#endif
+
+#include "eep0018.h"
+#include "yajl_gen.h"
+
+#ifdef VERSION
+#undef VERSION
+#endif
+
+#define LONG 97
+#define NEG_LONG 98
+#define DOUBLE 99
+#define ATOM 100
+#define TUPLE 104
+#define EMPTY_LIST 106
+#define STRING 107
+#define LIST 108
+#define BINARY 109
+#define BIGNUM 110
+#define VERSION 131
+
+int
+atom_to_json(char* buf, int* index, yajl_gen handle)
+{
+ char data[MAXATOMLEN+1];
+ unsigned char* atom = (unsigned char*) data;
+ int type, size;
+ int ret = ERROR;
+
+ // Check atom type?
+ if(ei_get_type(buf, index, &type, &size)) goto done;
+ if(type != ATOM) goto done;
+ if(ei_decode_atom(buf, index, data)) goto done;
+
+ if(strcmp(data, "null") == 0)
+ {
+ if(yajl_gen_null(handle) != yajl_gen_status_ok) goto done;
+ }
+ else if(strcmp(data, "true") == 0)
+ {
+ if(yajl_gen_bool(handle, 1) != yajl_gen_status_ok) goto done;
+ }
+ else if(strcmp(data, "false") == 0)
+ {
+ if(yajl_gen_bool(handle, 0) != yajl_gen_status_ok) goto done;
+ }
+ else
+ {
+ if(yajl_gen_string(handle, atom, strlen(data)) != yajl_gen_status_ok)
+ {
+ goto done;
+ }
+ }
+
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int
+string_to_json(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ int i, type, size, val;
+
+ if(ei_get_type(buf, index, &type, &size)) goto done;
+ if(type != STRING) goto done;
+
+ *index += 3;
+
+ if(yajl_gen_array_open(handle) != yajl_gen_status_ok) goto done;
+ for(i = 0; i < size; i++)
+ {
+ val = (int) *(buf+*index+i);
+ if(yajl_gen_integer(handle, val) != yajl_gen_status_ok) goto done;
+ }
+ if(yajl_gen_array_close(handle) != yajl_gen_status_ok) goto done;
+
+ *index += size;
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int
+key_to_json(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ char data[MAXATOMLEN];
+ int type, size;
+ unsigned char* string;
+
+ if(ei_get_type(buf, index, &type, &size)) goto done;
+ if(type == BINARY)
+ {
+ return binary_to_json(buf, index, handle);
+ }
+ else if(type == ATOM)
+ {
+ if(ei_decode_atom(buf, index, data)) goto done;
+ string = (unsigned char*) data;
+ if(yajl_gen_string(handle, string, size) != yajl_gen_status_ok)
+ {
+ goto done;
+ }
+ }
+ else if(type == STRING)
+ {
+ *index += 3;
+ string = (unsigned char*) (buf + *index);
+ if(yajl_gen_string(handle, string, size) != yajl_gen_status_ok)
+ {
+ goto done;
+ }
+ *index += size;
+ }
+ else
+ {
+ // Invalid key type.
+ goto done;
+ }
+
+ ret = OK;
+
+done:
+ return ret;
+}
+
+/*
+ * 只处理map的[{k,v},...]部分
+ */
+int map_to_json_inner(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ int i, arity, size;
+
+ if(ei_decode_list_header(buf, index, &arity)) goto done;
+
+ if(yajl_gen_map_open(handle) != yajl_gen_status_ok) goto done;
+
+ for(i = 0 ; i < arity ; i++)
+ {
+ if(ei_decode_tuple_header(buf, index, &size)) goto done;
+ if(size != 2) goto done;
+ if(key_to_json(buf, index, handle) != OK) goto done;
+ if(value_to_json(buf, index, handle) != OK) goto done;
+ }
+
+ if(yajl_gen_map_close(handle) != yajl_gen_status_ok) goto done;
+
+
+ if(arity > 0)
+ {
+ if(ei_decode_list_header(buf, index, &arity)) goto done;
+ if(arity != 0) goto done;
+ }
+
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int map_to_json_header(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ int arity;
+ if (ei_decode_tuple_header(buf, index, &arity)) goto done;
+
+ if (arity == 2)
+ {
+ char atom[MAXATOMLEN+1];
+ if (ei_decode_atom(buf, index, atom)) goto done;
+ if(strcmp(atom, "struct") != 0 && strcmp(atom, "obj") != 0) goto done;
+ }
+ else if (arity != 1)
+ {
+ goto done;
+ }
+ ret = OK;
+done:
+ return ret;
+}
+
+/*
+ * 有几种情形:
+ * {struct, [{key, value},...]}
+ * {[{key, value}, ...]}
+ * [{key, value}, ...]
+ */
+int
+map_to_json(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+
+ if (map_to_json_header(buf, index, handle)!=OK) goto done;
+
+ if(map_to_json_inner(buf, index, handle)!=OK) goto done;
+
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int peek_tuple_first_atom(char* buf, int* index, char *atom)
+{
+ int ret = ERROR;
+ int arity;
+ int old_index = *index;
+
+ if(ei_decode_tuple_header(buf, index, &arity)) goto done;
+ if (arity < 1) goto done;
+
+ if(ei_decode_atom(buf, index, atom)) goto done;
+ ret = OK;
+done:
+ *index = old_index;
+ return ret;
+}
+
+/*
+ * 如果形如[{key, value},...],则应该是map_to_json
+ */
+int
+array_to_json(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ int i, arity, type, size;
+ int old_index = *index; // remember old index
+
+ if(ei_decode_list_header(buf, index, &arity)) goto done;
+
+ if(ei_get_type(buf, index, &type, &size)) goto done;
+
+ if(type == TUPLE)
+ {
+ char atom[MAXATOMLEN+1];
+ if (size == 2) {
+ if (peek_tuple_first_atom(buf, index, atom)!=OK ||
+ strcmp(atom, "struct")!=0 && strcmp(atom, "obj") != 0)
+ {
+ *index = old_index;
+ if (map_to_json_inner(buf, index, handle)!=OK) goto done;
+ goto ok;
+ }
+ }
+ }
+
+ if(yajl_gen_array_open(handle) != yajl_gen_status_ok) goto done;
+ for(i = 0; i < arity; i++)
+ {
+ if(value_to_json(buf, index, handle) != OK) goto done;
+ }
+ if(yajl_gen_array_close(handle) != yajl_gen_status_ok) goto done;
+
+ //Pass over empty list tail.
+ if(arity > 0)
+ {
+ if(ei_decode_list_header(buf, index, &arity)) goto done;
+ if(arity != 0) goto done;
+ }
+
+ok:
+ ret = OK;
+done:
+ return ret;
+}
+
+int
+binary_to_json(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ int type, size;
+
+ if(ei_get_type(buf, index, &type, &size)) goto done;
+ if(type != BINARY) goto done;
+ *index += 5;
+
+ unsigned char* string = (unsigned char*) (buf + *index);
+ if(yajl_gen_string(handle, string, size) != yajl_gen_status_ok)
+ {
+ goto done;
+ }
+
+ *index += size;
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int
+value_to_json(char* buf, int* index, yajl_gen handle)
+{
+ int ret = ERROR;
+ int type, size;
+ long lval;
+ double dval;
+
+ if(ei_get_type(buf, index, &type, &size)) goto done;
+
+ if(type == VERSION)
+ {
+ if(ei_decode_version(buf, index, &type)) goto done;
+ if(!value_to_json(buf, index, handle)) goto done;
+ }
+ else if(type == LONG || type == NEG_LONG)
+ {
+ if(ei_decode_long(buf, index, &lval)) goto done;
+ if(yajl_gen_integer(handle, lval) != yajl_gen_status_ok) goto done;
+ }
+ else if(type == BIGNUM)
+ {
+ EI_LONGLONG l;
+ char num[128];
+
+ if (ei_decode_longlong(buf, index, &l)) goto done;
+
+ snprintf(num, sizeof(num)-1, "%lld", l);
+ if (yajl_gen_number(handle, num, strlen(num)) != yajl_gen_status_ok) goto done;
+ }
+ else if(type == DOUBLE)
+ {
+ if(ei_decode_double(buf, index, &dval)) goto done;
+ if(yajl_gen_double(handle, dval) != yajl_gen_status_ok) goto done;
+ }
+ else if(type == ATOM)
+ {
+ if(atom_to_json(buf, index, handle) != OK) goto done;
+ }
+ else if(type == STRING)
+ {
+ if(string_to_json(buf, index, handle) != OK) goto done;
+ }
+ else if(type == TUPLE)
+ {
+ if(map_to_json(buf, index, handle) != OK) goto done;
+ }
+ else if(type == LIST)
+ {
+ if(array_to_json(buf, index, handle) != OK) goto done;
+ }
+ else if(type == EMPTY_LIST)
+ {
+ if(ei_decode_list_header(buf, index, &size)) goto done;
+ if(size != 0) goto done;
+ if(yajl_gen_array_open(handle) != yajl_gen_status_ok) goto done;
+ if(yajl_gen_array_close(handle) != yajl_gen_status_ok) goto done;
+ }
+ else if(type == BINARY)
+ {
+ if(binary_to_json(buf, index, handle) != OK) goto done;
+ }
+ else
+ {
+ goto done;
+ }
+
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int
+encode_json(char* buf, int len, char** rbuf, int rlen)
+{
+ int index = 1;
+ int ret = -1;
+ ErlDrvBinary* rval = NULL;
+ const unsigned char* json = NULL;
+ unsigned int jsonlen = 0;
+
+ /*
+ ei_print_term(stdout, buf, &index);
+ fprintf(stdout, "\r\n");
+ */
+
+ index = 0;
+
+ yajl_gen_config config = {0, NULL, 0};
+ yajl_gen handle = yajl_gen_alloc(&config, NULL);
+
+ if(value_to_json(buf, &index, handle) != OK) goto done;
+
+ yajl_gen_status status = yajl_gen_get_buf(handle, &json, &jsonlen);
+ if(status != yajl_gen_status_ok) goto done;
+
+ rval = driver_alloc_binary(jsonlen);
+ if(rval == NULL) goto done;
+
+ memcpy(rval->orig_bytes, json, jsonlen);
+ *rbuf = (char*) rval;
+ //ret = jsonlen;
+ ret = 0;
+
+done:
+ if(handle != NULL) yajl_gen_free(handle);
+ return ret;
+}
View
190 lib/eep0018/c_src/term_buf.c
@@ -0,0 +1,190 @@
+/* Copyright (c) 2008-2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+ * Copyright (c) 2008-2009 Enrico Thierbach <eno@open-lab.org>
+ *
+ * This file is part of EEP0018, which is released under the MIT license.
+ */
+
+#include "eep0018.h"
+#include "term_buf.h"
+
+#define INIT_DBUF_SIZE 16
+#define INIT_TBUF_SIZE 2048
+
+#define CHECK_REQUIRE(BUF, N) if(!term_buf_require(BUF, N)) return ERROR;
+
+dbl_buf*
+dbl_buf_init()
+{
+ dbl_buf* ret = (dbl_buf*) malloc(sizeof(dbl_buf));
+ if(ret == NULL) return NULL;
+
+ ret->data = NULL;
+ ret->data = (double*) malloc(INIT_DBUF_SIZE * sizeof(double));
+ if(ret->data == NULL)
+ {
+ free(ret);
+ return NULL;
+ }
+
+ ret->length = INIT_DBUF_SIZE;
+ ret->used = 0;
+ return ret;
+}
+
+void
+dbl_buf_destroy(dbl_buf* buf)
+{
+ if(buf == NULL) return;
+ if(buf->data != NULL) free(buf->data);
+ free(buf);
+}
+
+double*
+dbl_buf_add(dbl_buf* buf, double val)
+{
+ double* next;
+ if(buf->used >= buf->length)
+ {
+ buf->length *= 2;
+ next = (double*) realloc(buf->data, buf->length * sizeof(double));
+ if(next == NULL) return NULL;
+ }
+
+ buf->data[buf->used++] = val;
+ return buf->data + (buf->used-1);
+}
+
+term_buf*
+term_buf_init(void)
+{
+ int status = ERROR;
+ term_buf* ret = (term_buf*) malloc(sizeof(term_buf));
+ if(ret == NULL) goto done;
+
+ ret->terms = NULL;
+ ret->terms = (TermData*) malloc(INIT_TBUF_SIZE * sizeof(TermData));
+ if(ret->terms == NULL) goto done;
+
+ ret->doubles = NULL;
+ ret->doubles = dbl_buf_init();
+ if(ret->doubles == NULL) goto done;
+
+ ret->length = INIT_TBUF_SIZE;
+ ret->used = 0;
+
+ status = OK;
+done:
+ if(status != OK)
+ {
+ term_buf_destroy(ret);
+ ret = NULL;
+ }
+ return ret;
+}
+
+void
+term_buf_destroy(term_buf* buf)
+{
+ if(buf == NULL) return;
+ if(buf->doubles != NULL) dbl_buf_destroy(buf->doubles);
+ if(buf->terms != NULL) free(buf->terms);
+ free(buf);
+}
+
+int
+term_buf_require(term_buf* buf, int want)
+{
+ int ret = ERROR;
+ TermData* next;
+
+ if(buf->length - buf->used > want) return OK;
+
+ buf->length *= 2;
+ next = (TermData*) realloc(buf->terms, buf->length * sizeof(TermData));
+ if(next == NULL) goto done;
+
+ buf->terms = next;
+ ret = OK;
+
+done:
+ return ret;
+}
+
+int
+term_buf_tuple(term_buf* buf, unsigned int elements)
+{
+ CHECK_REQUIRE(buf, 2);
+ buf->terms[buf->used++] = ERL_DRV_TUPLE;
+ buf->terms[buf->used++] = elements;
+ return OK;
+}
+
+int
+term_buf_list(term_buf* buf, unsigned int elements)
+{
+ CHECK_REQUIRE(buf, 3);
+ buf->terms[buf->used++] = ERL_DRV_NIL;
+ buf->terms[buf->used++] = ERL_DRV_LIST;
+ buf->terms[buf->used++] = elements+1;
+ return OK;
+}
+
+int
+term_buf_binary(term_buf* buf, const void* data, unsigned int length)
+{
+ CHECK_REQUIRE(buf, 3);
+ buf->terms[buf->used++] = ERL_DRV_BUF2BINARY;
+ buf->terms[buf->used++] = (ErlDrvTermData) data;
+ buf->terms[buf->used++] = length;
+ return OK;
+}
+
+int
+term_buf_true(term_buf* buf)
+{
+ CHECK_REQUIRE(buf, 2);
+ buf->terms[buf->used++] = ERL_DRV_ATOM;
+ buf->terms[buf->used++] = driver_mk_atom("true");
+ return OK;
+}
+
+int
+term_buf_false(term_buf* buf)
+{
+ CHECK_REQUIRE(buf, 2);
+ buf->terms[buf->used++] = ERL_DRV_ATOM;
+ buf->terms[buf->used++] = driver_mk_atom("false");
+ return OK;
+}
+
+int
+term_buf_null(term_buf* buf)
+{
+ CHECK_REQUIRE(buf, 2);
+ buf->terms[buf->used++] = ERL_DRV_ATOM;
+ buf->terms[buf->used++] = driver_mk_atom("null");
+ return OK;
+}
+
+int
+term_buf_int(term_buf* buf, int value)
+{
+ CHECK_REQUIRE(buf, 2);
+ buf->terms[buf->used++] = ERL_DRV_INT;
+ buf->terms[buf->used++] = (ErlDrvSInt) value;
+ return OK;
+}
+
+int
+term_buf_double(term_buf* buf, double value)
+{
+ CHECK_REQUIRE(buf, 2);
+
+ double* pos = dbl_buf_add(buf->doubles, value);
+ if(pos == NULL) return ERROR;
+
+ buf->terms[buf->used++] = ERL_DRV_FLOAT;
+ buf->terms[buf->used++] = (ErlDrvTermData) pos;
+
+ return OK;
+}
View
50 lib/eep0018/c_src/term_buf.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2008-2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+ * Copyright (c) 2008-2009 Enrico Thierbach <eno@open-lab.org>
+ *
+ * This file is part of EEP0018, which is released under the MIT license.
+ */
+
+#ifndef __TERM_BUF_H__
+#define __TERM_BUF_H__
+
+#include <erl_driver.h>
+
+typedef ErlDrvTermData TermData;
+
+typedef struct
+{
+ double* data;
+ int used;
+ int length;
+} dbl_buf;
+
+typedef struct
+{
+ int* types;
+ int* depths;
+} state_buf;
+
+typedef struct
+{
+ TermData* terms;
+ int length;
+ int used;
+ dbl_buf* doubles;
+} term_buf;
+
+term_buf* term_buf_init(void);
+void term_buf_destroy(term_buf* buf);
+
+int term_buf_tuple(term_buf* buf, unsigned int elements);
+int term_buf_list(term_buf* buf, unsigned int elements);
+int term_buf_binary(term_buf* buf, const void* data, unsigned int length);
+
+// These can be better optimized to store the atom value and reuse the value.
+int term_buf_true(term_buf* buf);
+int term_buf_false(term_buf* buf);
+int term_buf_null(term_buf* buf);
+
+int term_buf_int(term_buf* buf, int value);
+int term_buf_double(term_buf* buf, double value);
+
+#endif
View
152 lib/eep0018/c_src/yajl.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_parse.h"
+#include "yajl_lex.h"
+#include "yajl_parser.h"
+#include "yajl_alloc.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+const char *
+yajl_status_to_string(yajl_status stat)
+{
+ const char * statStr = "unknown";
+ switch (stat) {
+ case yajl_status_ok:
+ statStr = "ok, no error";
+ break;
+ case yajl_status_client_canceled:
+ statStr = "client canceled parse";
+ break;
+ case yajl_status_insufficient_data:
+ statStr = "eof was met before the parse could complete";
+ break;
+ case yajl_status_error:
+ statStr = "parse error";
+ break;
+ }
+ return statStr;
+}
+
+yajl_handle
+yajl_alloc(const yajl_callbacks * callbacks,
+ const yajl_parser_config * config,
+ const yajl_alloc_funcs * afs,
+ void * ctx)
+{
+ unsigned int allowComments = 0;
+ unsigned int validateUTF8 = 0;
+ yajl_handle hand = NULL;
+ yajl_alloc_funcs afsBuffer;
+
+ /* first order of business is to set up memory allocation routines */
+ if (afs != NULL) {
+ if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
+ {
+ return NULL;
+ }
+ } else {
+ yajl_set_default_alloc_funcs(&afsBuffer);
+ afs = &afsBuffer;
+ }
+
+ hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t));
+
+ /* copy in pointers to allocation routines */
+ memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
+
+ if (config != NULL) {
+ allowComments = config->allowComments;
+ validateUTF8 = config->checkUTF8;
+ }
+
+ hand->callbacks = callbacks;
+ hand->ctx = ctx;
+ hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8);
+ hand->errorOffset = 0;
+ hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
+ hand->stateBuf = yajl_buf_alloc(&(hand->alloc));
+
+ yajl_state_push(hand, yajl_state_start);
+
+ return hand;
+}
+
+void
+yajl_free(yajl_handle handle)
+{
+ yajl_buf_free(handle->stateBuf);
+ yajl_buf_free(handle->decodeBuf);
+ yajl_lex_free(handle->lexer);
+ YA_FREE(&(handle->alloc), handle);
+}
+
+yajl_status
+yajl_parse(yajl_handle hand, const unsigned char * jsonText,
+ unsigned int jsonTextLen)
+{
+ unsigned int offset = 0;
+ yajl_status status;
+ status = yajl_do_parse(hand, &offset, jsonText, jsonTextLen);
+ return status;
+}
+
+yajl_status
+yajl_parse_complete(yajl_handle hand)
+{
+ /* The particular case we want to handle is a trailing number.
+ * Further input consisting of digits could cause our interpretation
+ * of the number to change (buffered "1" but "2" comes in).
+ * A very simple approach to this is to inject whitespace to terminate
+ * any number in the lex buffer.
+ */
+ return yajl_parse(hand, (const unsigned char *)" ", 1);
+}
+
+unsigned char *
+yajl_get_error(yajl_handle hand, int verbose,
+ const unsigned char * jsonText, unsigned int jsonTextLen)
+{
+ return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose);
+}
+
+void
+yajl_free_error(yajl_handle hand, unsigned char * str)
+{
+ /* use memory allocation functions if set */
+ YA_FREE(&(hand->alloc), str);
+}
+
+/* XXX: add utility routines to parse from file */
View
65 lib/eep0018/c_src/yajl_alloc.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_alloc.h
+ * default memory allocation routines for yajl which use malloc/realloc and
+ * free
+ */
+
+#include "yajl_alloc.h"
+#include <stdlib.h>
+
+static void * yajl_internal_malloc(void *ctx, unsigned int sz)
+{
+ return malloc(sz);
+}
+
+static void * yajl_internal_realloc(void *ctx, void * previous,
+ unsigned int sz)
+{
+ return realloc(previous, sz);
+}
+
+static void yajl_internal_free(void *ctx, void * ptr)
+{
+ free(ptr);
+}
+
+void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf)
+{
+ yaf->malloc = yajl_internal_malloc;
+ yaf->free = yajl_internal_free;
+ yaf->realloc = yajl_internal_realloc;
+ yaf->ctx = NULL;
+}
+
View
50 lib/eep0018/c_src/yajl_alloc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_alloc.h
+ * default memory allocation routines for yajl which use malloc/realloc and
+ * free
+ */
+
+#ifndef __YAJL_ALLOC_H__
+#define __YAJL_ALLOC_H__
+
+#include "yajl_common.h"
+
+#define YA_MALLOC(afs, sz) (afs)->malloc((afs)->ctx, (sz))
+#define YA_FREE(afs, ptr) (afs)->free((afs)->ctx, (ptr))
+#define YA_REALLOC(afs, ptr, sz) (afs)->realloc((afs)->ctx, (ptr), (sz))
+
+void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf);
+
+#endif
View
119 lib/eep0018/c_src/yajl_buf.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_buf.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define YAJL_BUF_INIT_SIZE 2048
+
+struct yajl_buf_t {
+ unsigned int len;
+ unsigned int used;
+ unsigned char * data;
+ yajl_alloc_funcs * alloc;
+};
+
+static
+void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
+{
+ unsigned int need;
+
+ assert(buf != NULL);
+
+ /* first call */
+ if (buf->data == NULL) {
+ buf->len = YAJL_BUF_INIT_SIZE;
+ buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len);
+ buf->data[0] = 0;
+ }
+
+ need = buf->len;
+
+ while (want >= (need - buf->used)) need <<= 1;
+
+ if (need != buf->len) {
+ buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);
+ buf->len = need;
+ }
+}
+
+yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
+{
+ yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
+ memset((void *) b, 0, sizeof(struct yajl_buf_t));
+ b->alloc = alloc;
+ return b;
+}
+
+void yajl_buf_free(yajl_buf buf)
+{
+ assert(buf != NULL);
+ if (buf->data) YA_FREE(buf->alloc, buf->data);
+ YA_FREE(buf->alloc, buf);
+}
+
+void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
+{
+ yajl_buf_ensure_available(buf, len);
+ if (len > 0) {
+ assert(data != NULL);
+ memcpy(buf->data + buf->used, data, len);
+ buf->used += len;
+ buf->data[buf->used] = 0;
+ }
+}
+
+void yajl_buf_clear(yajl_buf buf)
+{
+ buf->used = 0;
+ if (buf->data) buf->data[buf->used] = 0;
+}
+
+const unsigned char * yajl_buf_data(yajl_buf buf)
+{
+ return buf->data;
+}
+
+unsigned int yajl_buf_len(yajl_buf buf)
+{
+ return buf->used;
+}
+
+void
+yajl_buf_truncate(yajl_buf buf, unsigned int len)
+{
+ assert(len <= buf->used);
+ buf->used = len;
+}
View
66 lib/eep0018/c_src/yajl_buf.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_BUF_H__
+#define __YAJL_BUF_H__
+
+#include "yajl_common.h"
+#include "yajl_alloc.h"
+
+/**
+ * yajl_buf is a buffer with exponential growth. the buffer ensures that
+ * you are always null padded.
+ */
+typedef struct yajl_buf_t * yajl_buf;
+
+/* allocate a new buffer */
+yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc);
+
+/* free the buffer */
+void yajl_buf_free(yajl_buf buf);
+
+/* append a number of bytes to the buffer */
+void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len);
+
+/* empty the buffer */
+void yajl_buf_clear(yajl_buf buf);
+
+/* get a pointer to the beginning of the buffer */
+const unsigned char * yajl_buf_data(yajl_buf buf);
+
+/* get the length of the buffer */
+unsigned int yajl_buf_len(yajl_buf buf);
+
+/* truncate the buffer */
+void yajl_buf_truncate(yajl_buf buf, unsigned int len);
+
+#endif
View
85 lib/eep0018/c_src/yajl_common.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_COMMON_H__
+#define __YAJL_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define YAJL_MAX_DEPTH 128
+
+/* msft dll export gunk. To build a DLL on windows, you
+ * must define WIN32, YAJL_SHARED, and YAJL_BUILD. To use a shared
+ * DLL, you must define YAJL_SHARED and WIN32 */
+#if defined(WIN32) && defined(YAJL_SHARED)
+# ifdef YAJL_BUILD
+# define YAJL_API __declspec(dllexport)
+# else
+# define YAJL_API __declspec(dllimport)
+# endif
+#else
+# define YAJL_API
+#endif
+
+/** pointer to a malloc function, supporting client overriding memory
+ * allocation routines */
+typedef void * (*yajl_malloc_func)(void *ctx, unsigned int sz);
+
+/** pointer to a free function, supporting client overriding memory
+ * allocation routines */
+typedef void (*yajl_free_func)(void *ctx, void * ptr);
+
+/** pointer to a realloc function which can resize an allocation. */
+typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, unsigned int sz);
+
+/** A structure which can be passed to yajl_*_alloc routines to allow the
+ * client to specify memory allocation functions to be used. */
+typedef struct
+{
+ /** pointer to a function that can allocate uninitialized memory */
+ yajl_malloc_func malloc;
+ /** pointer to a function that can resize memory allocations */
+ yajl_realloc_func realloc;
+ /** pointer to a function that can free memory allocated using
+ * reallocFunction or mallocFunction */
+ yajl_free_func free;
+ /** a context pointer that will be passed to above allocation routines */
+ void * ctx;
+} yajl_alloc_funcs;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View
234 lib/eep0018/c_src/yajl_encode.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_encode.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static void CharToHex(unsigned char c, char * hexBuf)
+{
+ const char * hexchar = "0123456789abcdef";
+ hexBuf[0] = hexchar[c >> 4];
+ hexBuf[1] = hexchar[c & 0x0F];
+}
+
+void
+yajl_string_encode(yajl_buf buf, const unsigned char * str,
+ unsigned int len, int encode_utf8)
+{
+ unsigned int beg = 0;
+ unsigned int end = 0;
+ char hexBuf[7] = "\\u0000";
+ char rawBuf[5] = "\0\0\0\0";
+
+ while (end < len) {
+ unsigned int inc = 1;
+ const char * escaped = NULL;
+ switch (str[end]) {
+ case '\r': escaped = "\\r"; break;
+ case '\n': escaped = "\\n"; break;
+ case '\\': escaped = "\\\\"; break;
+ /* case '/': escaped = "\\/"; break; */
+ case '"': escaped = "\\\""; break;
+ case '\f': escaped = "\\f"; break;
+ case '\b': escaped = "\\b"; break;
+ case '\t': escaped = "\\t"; break;
+ default:
+ // utf8: U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
+ if (((str[end] & 0xE0) == 0xC0) &&
+ (end+1<len) &&
+ ((str[end+1] & 0xC0) == 0x80))
+ {
+ if (encode_utf8)
+ {
+ unsigned int cp = (str[end] & 0x1F) << 6;
+ cp |= str[end+1] & 0x3F;
+ inc = 2;
+ CharToHex((cp >> 8) & 0xFF, hexBuf + 2);
+ CharToHex(cp & 0xFF, hexBuf + 4);
+ escaped = hexBuf;
+ } else {
+ rawBuf[0] = str[end];
+ rawBuf[1] = str[end+1];
+ rawBuf[2] = 0;
+ rawBuf[3] = 0;
+ inc = 2;
+ escaped = rawBuf;
+ }
+ break;
+ }
+ // utf8: U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
+ else
+ if (((str[end] & 0xF0) == 0xE0) &&
+ (end+2<len) &&
+ ((str[end+1] & 0xC0) == 0x80) &&
+ ((str[end+2] & 0xC0) == 0x80))
+ {
+ if (encode_utf8)
+ {
+ unsigned int cp = (str[end] & 0x0F) << 12;
+ cp |= (str[end+1] & 0x3F) << 6;
+ cp |= (str[end+2] & 0x3F);
+ inc = 3;
+ CharToHex((cp >> 8) & 0xFF, hexBuf + 2);
+ CharToHex(cp & 0xFF, hexBuf + 4);
+ escaped = hexBuf;
+ } else
+ {
+ rawBuf[0] = str[end];
+ rawBuf[1] = str[end+1];
+ rawBuf[2] = str[end+2];
+ rawBuf[3] = 0;
+ inc = 3;
+ escaped = rawBuf;
+ }
+ break;
+ }
+
+ if (!(str[end] >= ' ' && str[end] < 127)) { // don't know why isprint doesn't work!!!
+ // convert to \uXXXX in spite of encode_utf8 or not
+ hexBuf[2] = '0';
+ hexBuf[3] = '0';
+ CharToHex(str[end], hexBuf + 4);
+ escaped = hexBuf;
+ }
+ break;
+ }
+ if (escaped != NULL) {
+ yajl_buf_append(buf, str + beg, end - beg);
+ yajl_buf_append(buf, escaped, strlen(escaped));
+ end += inc;
+ beg = end;
+ } else {
+ end += inc;
+ }
+ }
+ yajl_buf_append(buf, str + beg, end - beg);
+}
+
+static void hexToDigit(unsigned int * val, const unsigned char * hex)
+{
+ unsigned int i;
+ for (i=0;i<4;i++) {
+ unsigned char c = hex[i];
+ if (c >= 'A') c = (c & ~0x20) - 7;
+ c -= '0';
+ assert(!(c & 0xF0));
+ *val = (*val << 4) | c;
+ }
+}
+
+static void Utf32toUtf8(unsigned int codepoint, char * utf8Buf)
+{
+ if (codepoint < 0x80) {
+ utf8Buf[0] = (char) codepoint;
+ utf8Buf[1] = 0;
+ } else if (codepoint < 0x0800) {
+ utf8Buf[0] = (char) ((codepoint >> 6) | 0xC0);
+ utf8Buf[1] = (char) ((codepoint & 0x3F) | 0x80);
+ utf8Buf[2] = 0;
+ } else if (codepoint < 0x10000) {
+ utf8Buf[0] = (char) ((codepoint >> 12) | 0xE0);
+ utf8Buf[1] = (char) (((codepoint >> 6) & 0x3F) | 0x80);
+ utf8Buf[2] = (char) ((codepoint & 0x3F) | 0x80);
+ utf8Buf[3] = 0;
+ } else if (codepoint < 0x200000) {
+ utf8Buf[0] =(char)((codepoint >> 18) | 0xF0);
+ utf8Buf[1] =(char)(((codepoint >> 12) & 0x3F) | 0x80);
+ utf8Buf[2] =(char)(((codepoint >> 6) & 0x3F) | 0x80);
+ utf8Buf[3] =(char)((codepoint & 0x3F) | 0x80);
+ utf8Buf[4] = 0;
+ } else {
+ utf8Buf[0] = '?';
+ utf8Buf[1] = 0;
+ }
+}
+
+void yajl_string_decode(yajl_buf buf, const unsigned char * str,
+ unsigned int len)
+{
+ unsigned int beg = 0;
+ unsigned int end = 0;
+
+ while (end < len) {
+ if (str[end] == '\\') {
+ char utf8Buf[5];
+ const char * unescaped = "?";
+ yajl_buf_append(buf, str + beg, end - beg);
+ switch (str[++end]) {
+ case 'r': unescaped = "\r"; break;
+ case 'n': unescaped = "\n"; break;
+ case '\\': unescaped = "\\"; break;
+ case '/': unescaped = "/"; break;
+ case '"': unescaped = "\""; break;
+ case 'f': unescaped = "\f"; break;
+ case 'b': unescaped = "\b"; break;
+ case 't': unescaped = "\t"; break;
+ case 'u': {
+ unsigned int codepoint = 0;
+ hexToDigit(&codepoint, str + ++end);
+ end+=3;
+ /* check if this is a surrogate */
+ if ((codepoint & 0xFC00) == 0xD800) {
+ end++;
+ if (str[end] == '\\' && str[end + 1] == 'u') {
+ unsigned int surrogate = 0;
+ hexToDigit(&surrogate, str + end + 2);
+ codepoint =
+ (((codepoint & 0x3F) << 10) |
+ ((((codepoint >> 6) & 0xF) + 1) << 16) |
+ (surrogate & 0x3FF));
+ end += 5;
+ } else {
+ unescaped = "?";
+ break;
+ }
+ }
+
+ Utf32toUtf8(codepoint, utf8Buf);
+ unescaped = utf8Buf;
+ break;
+ }
+ default:
+ assert("this should never happen" == NULL);
+ }
+ yajl_buf_append(buf, unescaped, strlen(unescaped));
+ beg = ++end;
+ } else {
+ end++;
+ }
+ }
+ yajl_buf_append(buf, str + beg, end - beg);
+}
View
44 lib/eep0018/c_src/yajl_encode.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_ENCODE_H__
+#define __YAJL_ENCODE_H__
+
+#include "yajl_buf.h"
+
+void yajl_string_encode(yajl_buf buf, const unsigned char * str,
+ unsigned int length, int encode_utf8);
+
+void yajl_string_decode(yajl_buf buf, const unsigned char * str,
+ unsigned int length);
+
+#endif
View
297 lib/eep0018/c_src/yajl_gen.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_gen.h"
+#include "yajl_buf.h"
+#include "yajl_encode.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+typedef enum {
+ yajl_gen_start,
+ yajl_gen_map_start,
+ yajl_gen_map_key,
+ yajl_gen_map_val,
+ yajl_gen_array_start,
+ yajl_gen_in_array,
+ yajl_gen_complete,
+ yajl_gen_error
+} yajl_gen_state;
+
+struct yajl_gen_t
+{
+ unsigned int depth;
+ unsigned int pretty;
+ unsigned int encode_utf8;
+ const char * indentString;
+ yajl_gen_state state[YAJL_MAX_DEPTH];
+ yajl_buf buf;
+ /* memory allocation routines */
+ yajl_alloc_funcs alloc;
+};
+
+yajl_gen
+yajl_gen_alloc(const yajl_gen_config * config,
+ const yajl_alloc_funcs * afs)
+{
+ yajl_gen g = NULL;
+ yajl_alloc_funcs afsBuffer;
+
+ /* first order of business is to set up memory allocation routines */
+ if (afs != NULL) {
+ if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
+ {
+ return NULL;
+ }
+ } else {
+ yajl_set_default_alloc_funcs(&afsBuffer);
+ afs = &afsBuffer;
+ }
+
+ g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t));
+ memset((void *) g, 0, sizeof(struct yajl_gen_t));
+ /* copy in pointers to allocation routines */
+ memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
+
+ if (config) {
+ g->pretty = config->beautify;
+ g->indentString = config->indentString ? config->indentString : " ";
+ g->encode_utf8 = config->encode_utf8;
+ }
+ g->buf = yajl_buf_alloc(&(g->alloc));
+
+ return g;
+}
+
+void
+yajl_gen_free(yajl_gen g)
+{
+ yajl_buf_free(g->buf);
+ YA_FREE(&(g->alloc), g);
+}
+
+#define INSERT_SEP \
+ if (g->state[g->depth] == yajl_gen_map_key || \
+ g->state[g->depth] == yajl_gen_in_array) { \
+ yajl_buf_append(g->buf, ",", 1); \
+ if (g->pretty) yajl_buf_append(g->buf, "\n", 1); \
+ } else if (g->state[g->depth] == yajl_gen_map_val) { \
+ yajl_buf_append(g->buf, ":", 1); \
+ if (g->pretty) yajl_buf_append(g->buf, " ", 1); \
+ }
+
+#define INSERT_WHITESPACE \
+ if (g->pretty) { \
+ if (g->state[g->depth] != yajl_gen_map_val) { \
+ unsigned int _i; \
+ for (_i=0;_i<g->depth;_i++) \
+ yajl_buf_append(g->buf, g->indentString, \
+ strlen(g->indentString)); \
+ } \
+ }
+
+#define ENSURE_NOT_KEY \
+ if (g->state[g->depth] == yajl_gen_map_key) { \
+ return yajl_gen_keys_must_be_strings; \
+ } \
+
+/* check that we're not complete, or in error state. in a valid state
+ * to be generating */
+#define ENSURE_VALID_STATE \
+ if (g->state[g->depth] == yajl_gen_error) { \
+ return yajl_gen_in_error_state;\
+ } else if (g->state[g->depth] == yajl_gen_complete) { \
+ return yajl_gen_generation_complete; \
+ }
+
+#define INCREMENT_DEPTH \
+ if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
+
+#define APPENDED_ATOM \
+ switch (g->state[g->depth]) { \
+ case yajl_gen_start: \
+ g->state[g->depth] = yajl_gen_complete; \
+ break; \
+ case yajl_gen_map_start: \
+ case yajl_gen_map_key: \
+ g->state[g->depth] = yajl_gen_map_val; \
+ break; \
+ case yajl_gen_array_start: \
+ g->state[g->depth] = yajl_gen_in_array; \
+ break; \
+ case yajl_gen_map_val: \
+ g->state[g->depth] = yajl_gen_map_key; \
+ break; \
+ default: \
+ break; \
+ } \
+
+#define FINAL_NEWLINE \
+ if (g->pretty && g->state[g->depth] == yajl_gen_complete) \
+ yajl_buf_append(g->buf, "\n", 1);
+
+yajl_gen_status
+yajl_gen_integer(yajl_gen g, long int number)
+{
+ char i[32];
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ sprintf(i, "%ld", number);
+ yajl_buf_append(g->buf, i, strlen(i));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_double(yajl_gen g, double number)
+{
+ char i[32];
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ sprintf(i, "%g", number);
+ yajl_buf_append(g->buf, i, strlen(i));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, s, l);
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_string(yajl_gen g, const unsigned char * str,
+ unsigned int len)
+{
+ ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "\"", 1);
+ yajl_string_encode(g->buf, str, len, g->encode_utf8);
+ yajl_buf_append(g->buf, "\"", 1);
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_null(yajl_gen g)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "null", strlen("null"));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_bool(yajl_gen g, int boolean)
+{
+ const char * val = boolean ? "true" : "false";
+
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, val, strlen(val));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_map_open(yajl_gen g)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ INCREMENT_DEPTH;
+
+ g->state[g->depth] = yajl_gen_map_start;
+ yajl_buf_append(g->buf, "{", 1);
+ if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_map_close(yajl_gen g)
+{
+ ENSURE_VALID_STATE;
+ (g->depth)--;
+ if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
+ APPENDED_ATOM;
+ INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "}", 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_array_open(yajl_gen g)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ INCREMENT_DEPTH;
+ g->state[g->depth] = yajl_gen_array_start;
+ yajl_buf_append(g->buf, "[", 1);
+ if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_array_close(yajl_gen g)
+{
+ ENSURE_VALID_STATE;
+ if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
+ (g->depth)--;
+ APPENDED_ATOM;
+ INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "]", 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
+ unsigned int * len)
+{
+ *buf = yajl_buf_data(g->buf);
+ *len = yajl_buf_len(g->buf);
+ return yajl_gen_status_ok;
+}
+
+void
+yajl_gen_clear(yajl_gen g)
+{
+ yajl_buf_clear(g->buf);
+}
View
124 lib/eep0018/c_src/yajl_gen.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_gen.h
+ * Interface to YAJL's JSON generation facilities.
+ */
+
+#include "yajl_common.h"
+
+#ifndef __YAJL_GEN_H__
+#define __YAJL_GEN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /** generator status codes */
+ typedef enum {
+ /** no error */
+ yajl_gen_status_ok = 0,
+ /** at a point where a map key is generated, a function other than
+ * yajl_gen_string was called */
+ yajl_gen_keys_must_be_strings,
+ /** YAJL's maximum generation depth was exceeded. see
+ * YAJL_MAX_DEPTH */
+ yajl_max_depth_exceeded,
+ /** A generator function (yajl_gen_XXX) was called while in an error
+ * state */
+ yajl_gen_in_error_state,
+ /** A complete JSON document has been generated */
+ yajl_gen_generation_complete
+ } yajl_gen_status;
+
+ /** an opaque handle to a generator */
+ typedef struct yajl_gen_t * yajl_gen;
+
+ /** configuration structure for the generator */
+ typedef struct {
+ /** generate indented (beautiful) output */
+ unsigned int beautify;
+ /** an opportunity to define an indent string. such as \\t or
+ * some number of spaces. default is four spaces ' '. This
+ * member is only relevant when beautify is true */
+ const char * indentString;
+ int encode_utf8;
+ } yajl_gen_config;
+
+ /** allocate a generator handle
+ * \param config a pointer to a structure containing parameters which
+ * configure the behavior of the json generator
+ * \param allocFuncs an optional pointer to a structure which allows
+ * the client to overide the memory allocation
+ * used by yajl. May be NULL, in which case
+ * malloc/free/realloc will be used.
+ *
+ * \returns an allocated handle on success, NULL on failure (bad params)
+ */
+ yajl_gen YAJL_API yajl_gen_alloc(const yajl_gen_config * config,
+ const yajl_alloc_funcs * allocFuncs);
+
+ /** free a generator handle */
+ void YAJL_API yajl_gen_free(yajl_gen handle);
+
+ yajl_gen_status YAJL_API yajl_gen_integer(yajl_gen hand, long int number);
+ yajl_gen_status YAJL_API yajl_gen_double(yajl_gen hand, double number);
+ yajl_gen_status YAJL_API yajl_gen_number(yajl_gen hand,
+ const char * num,
+ unsigned int len);
+ yajl_gen_status YAJL_API yajl_gen_string(yajl_gen hand,
+ const unsigned char * str,
+ unsigned int len);
+ yajl_gen_status YAJL_API yajl_gen_null(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_bool(yajl_gen hand, int boolean);
+ yajl_gen_status YAJL_API yajl_gen_map_open(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_map_close(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_array_open(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_array_close(yajl_gen hand);
+
+ /** access the null terminated generator buffer. If incrementally
+ * outputing JSON, one should call yajl_gen_clear to clear the
+ * buffer. This allows stream generation. */
+ yajl_gen_status YAJL_API yajl_gen_get_buf(yajl_gen hand,
+ const unsigned char ** buf,
+ unsigned int * len);
+
+ /** clear yajl's output buffer, but maintain all internal generation
+ * state. This function will not "reset" the generator state, and is
+ * intended to enable incremental JSON outputing. */
+ void YAJL_API yajl_gen_clear(yajl_gen hand);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View
749 lib/eep0018/c_src/yajl_lex.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_lex.h"
+#include "yajl_buf.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef YAJL_LEXER_DEBUG
+static const char *
+tokToStr(yajl_tok tok)
+{
+ switch (tok) {
+ case yajl_tok_bool: return "bool";
+ case yajl_tok_colon: return "colon";
+ case yajl_tok_comma: return "comma";
+ case yajl_tok_eof: return "eof";
+ case yajl_tok_error: return "error";
+ case yajl_tok_left_brace: return "brace";
+ case yajl_tok_left_bracket: return "bracket";
+ case yajl_tok_null: return "null";
+ case yajl_tok_integer: return "integer";
+ case yajl_tok_double: return "double";
+ case yajl_tok_right_brace: return "brace";
+ case yajl_tok_right_bracket: return "bracket";
+ case yajl_tok_string: return "string";
+ case yajl_tok_string_with_escapes: return "string_with_escapes";
+ }
+ return "unknown";
+}
+#endif
+
+/* Impact of the stream parsing feature on the lexer:
+ *
+ * YAJL support stream parsing. That is, the ability to parse the first
+ * bits of a chunk of JSON before the last bits are available (still on
+ * the network or disk). This makes the lexer more complex. The
+ * responsibility of the lexer is to handle transparently the case where
+ * a chunk boundary falls in the middle of a token. This is
+ * accomplished is via a buffer and a character reading abstraction.
+ *
+ * Overview of implementation
+ *
+ * When we lex to end of input string before end of token is hit, we
+ * copy all of the input text composing the token into our lexBuf.
+ *
+ * Every time we read a character, we do so through the readChar function.
+ * readChar's responsibility is to handle pulling all chars from the buffer
+ * before pulling chars from input text
+ */
+
+struct yajl_lexer_t {
+ /* the overal line and char offset into the data */
+ unsigned int lineOff;
+ unsigned int charOff;
+
+ /* error */
+ yajl_lex_error error;
+
+ /* a input buffer to handle the case where a token is spread over
+ * multiple chunks */
+ yajl_buf buf;
+
+ /* in the case where we have data in the lexBuf, bufOff holds
+ * the current offset into the lexBuf. */
+ unsigned int bufOff;
+
+ /* are we using the lex buf? */
+ unsigned int bufInUse;
+
+ /* shall we allow comments? */
+ unsigned int allowComments;
+
+ /* shall we validate utf8 inside strings? */
+ unsigned int validateUTF8;
+
+ yajl_alloc_funcs * alloc;
+};
+
+static unsigned char
+readChar(yajl_lexer lxr, const unsigned char * txt, unsigned int *off)
+{
+ if (lxr->bufInUse && yajl_buf_len(lxr->buf) &&
+ lxr->bufOff < yajl_buf_len(lxr->buf))
+ {
+ return *((const unsigned char *) yajl_buf_data(lxr->buf) +
+ (lxr->bufOff)++);
+ }
+ return txt[(*off)++];
+}
+
+static void
+unreadChar(yajl_lexer lxr, unsigned int *off)
+{
+ if (*off > 0) (*off)--;
+ else (lxr->bufOff)--;
+}
+
+yajl_lexer
+yajl_lex_alloc(yajl_alloc_funcs * alloc,
+ unsigned int allowComments, unsigned int validateUTF8)
+{
+ yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
+ memset((void *) lxr, 0, sizeof(struct yajl_lexer_t));
+ lxr->buf = yajl_buf_alloc(alloc);
+ lxr->allowComments = allowComments;
+ lxr->validateUTF8 = validateUTF8;
+ lxr->alloc = alloc;
+ return lxr;
+}
+
+void
+yajl_lex_free(yajl_lexer lxr)
+{
+ yajl_buf_free(lxr->buf);
+ YA_FREE(lxr->alloc, lxr);
+ return;
+}
+
+/* a lookup table which lets us quickly determine three things:
+ * VEC - valid escaped conrol char
+ * IJC - invalid json char
+ * VHC - valid hex char
+ * note. the solidus '/' may be escaped or not.
+ * note. the
+ */
+#define VEC 1
+#define IJC 2
+#define VHC 4
+static const char charLookupTable[256] =
+{
<