jsonification into the core and ESL (part 2)

This commit is contained in:
Anthony Minessale 2010-06-17 11:49:16 -05:00
parent c5086b1517
commit 7048c16fc4
9 changed files with 772 additions and 67 deletions

View File

@ -169,6 +169,7 @@ library_include_HEADERS = \
src/include/switch_xml.h \
src/include/switch_xml_config.h \
src/include/switch_cpp.h \
src/include/switch_json.h\
libs/libteletone/src/libteletone_detect.h \
libs/libteletone/src/libteletone_generate.h \
libs/libteletone/src/libteletone.h \
@ -230,6 +231,7 @@ libfreeswitch_la_SOURCES = \
src/g711.c \
src/switch_pcm.c \
src/switch_profile.c\
src/switch_json.c\
libs/stfu/stfu.c \
libs/libteletone/src/libteletone_detect.c \
libs/libteletone/src/libteletone_generate.c \
@ -268,9 +270,9 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd
##
## fs_cli ()
##
fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c
fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c
fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS)
fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
if HAVE_LIBEDIT
fs_cli_CFLAGS += -DHAVE_EDITLINE -I$(switch_srcdir)/libs/libedit/src
@ -280,9 +282,9 @@ endif
##
## fs_ivrd ()
##
fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c
fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c
fs_ivrd_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS)
fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
##
## freeswitch ()

View File

@ -7,11 +7,11 @@ PICKY=-O2 -ffast-math -Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-p
CFLAGS=$(BASE_FLAGS) $(PICKY)
CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable
MYLIB=libesl.a
LIBS=-lncurses -lpthread -lesl
LIBS=-lncurses -lpthread -lesl -lm
LDFLAGS=-L.
OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o
SRC=src/esl.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp
HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h
OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o
SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c
HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h
SOLINK=-shared -Xlinker -x
# comment the next line to disable c++ (no swig mods for you then)
OBJS += src/esl_oop.o

View File

@ -527,6 +527,8 @@ ESL_DECLARE(esl_status_t) esl_events(esl_handle_t *handle, esl_event_type_t etyp
if (etype == ESL_EVENT_TYPE_XML) {
type = "xml";
} else if (etype == ESL_EVENT_TYPE_JSON) {
type = "json";
}
snprintf(send_buf, sizeof(send_buf), "event %s %s\n\n", type, value);
@ -979,63 +981,67 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
if (!esl_safe_strcasecmp(hval, "text/disconnect-notice") && revent->body) {
goto fail;
}
if (!esl_safe_strcasecmp(hval, "text/event-plain") && revent->body) {
esl_event_types_t et = ESL_EVENT_CLONE;
char *body = strdup(revent->body);
if (revent->body) {
if (!esl_safe_strcasecmp(hval, "text/event-plain")) {
esl_event_types_t et = ESL_EVENT_CLONE;
char *body = strdup(revent->body);
esl_event_create(&handle->last_ievent, et);
esl_event_create(&handle->last_ievent, et);
beg = body;
beg = body;
while(beg) {
if (!(c = strchr(beg, '\n'))) {
break;
}
hname = beg;
hval = col = NULL;
if (hname && (col = strchr(hname, ':'))) {
hval = col + 1;
*col = '\0';
while(*hval == ' ') hval++;
}
*c = '\0';
if (hname && hval) {
esl_url_decode(hval);
esl_log(ESL_LOG_DEBUG, "RECV INNER HEADER [%s] = [%s]\n", hname, hval);
if (!strcasecmp(hname, "event-name")) {
esl_event_del_header(handle->last_ievent, "event-name");
while(beg) {
if (!(c = strchr(beg, '\n'))) {
break;
}
hname = beg;
hval = col = NULL;
if (hname && (col = strchr(hname, ':'))) {
hval = col + 1;
*col = '\0';
while(*hval == ' ') hval++;
}
esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
esl_name_event(hval, &handle->last_ievent->event_id);
}
beg = c + 1;
*c = '\0';
if (hname && hval) {
esl_url_decode(hval);
esl_log(ESL_LOG_DEBUG, "RECV INNER HEADER [%s] = [%s]\n", hname, hval);
if (!strcasecmp(hname, "event-name")) {
esl_event_del_header(handle->last_ievent, "event-name");
}
esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
esl_name_event(hval, &handle->last_ievent->event_id);
}
beg = c + 1;
if (*beg == '\n') {
beg++;
break;
if (*beg == '\n') {
beg++;
break;
}
}
}
if ((cl = esl_event_get_header(handle->last_ievent, "content-length"))) {
handle->last_ievent->body = strdup(beg);
}
if ((cl = esl_event_get_header(handle->last_ievent, "content-length"))) {
handle->last_ievent->body = strdup(beg);
}
free(body);
free(body);
if (esl_log_level >= 7) {
char *foo;
esl_event_serialize(handle->last_ievent, &foo, ESL_FALSE);
esl_log(ESL_LOG_DEBUG, "RECV EVENT\n%s\n", foo);
free(foo);
if (esl_log_level >= 7) {
char *foo;
esl_event_serialize(handle->last_ievent, &foo, ESL_FALSE);
esl_log(ESL_LOG_DEBUG, "RECV EVENT\n%s\n", foo);
free(foo);
}
} else if (!esl_safe_strcasecmp(hval, "text/event-json")) {
esl_event_create_json(&handle->last_ievent, revent->body);
}
}
if (esl_log_level >= 7) {
char *foo;
esl_event_serialize(revent, &foo, ESL_FALSE);

View File

@ -437,6 +437,73 @@ ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
return ESL_SUCCESS;
}
ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
{
esl_event_t *new_event;
cJSON *cj, *cjp;
if (!(cj = cJSON_Parse(json))) {
return ESL_FAIL;
}
if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
cJSON_Delete(cj);
return ESL_FAIL;
}
for (cjp = cj->child; cjp; cjp = cjp->next) {
char *name = cjp->string;
char *value = cjp->valuestring;
if (name && value) {
if (!strcasecmp(name, "_body")) {
esl_event_add_body(new_event, value);
} else {
if (!strcasecmp(name, "event-name")) {
esl_event_del_header(new_event, "event-name");
}
esl_name_event(value, &new_event->event_id);
esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
}
}
}
cJSON_Delete(cj);
*event = new_event;
return ESL_SUCCESS;
}
ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
{
esl_event_header_t *hp;
cJSON *cj;
*str = NULL;
cj = cJSON_CreateObject();
for (hp = event->headers; hp; hp = hp->next) {
cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
}
if (event->body) {
int blen = (int) strlen(event->body);
char tmp[25];
esl_snprintf(tmp, sizeof(tmp), "%d", blen);
cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
}
*str = cJSON_Print(cj);
cJSON_Delete(cj);
return ESL_SUCCESS;
}
ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode)
{
size_t len = 0;

484
libs/esl/src/esl_json.c Normal file
View File

@ -0,0 +1,484 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// cJSON
// JSON parser in C.
#include "esl.h"
#include <float.h>
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;
static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,str,len);
return copy;
}
void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
// Internal constructor.
static cJSON *cJSON_New_Item(void)
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON));
return node;
}
// Delete a cJSON structure.
void cJSON_Delete(cJSON *c)
{
cJSON *next;
while (c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (c->string) cJSON_free(c->string);
cJSON_free(c);
c=next;
}
}
// Parse the input text to generate a number, and populate the result into item.
static const char *parse_number(cJSON *item,const char *num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
// Could use sscanf for this?
if (*num=='-') sign=-1,num++; // Has sign?
if (*num=='0') num++; // is zero
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); // Number?
if (*num=='.') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} // Fractional part?
if (*num=='e' || *num=='E') // Exponent?
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; // With sign?
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); // Number?
}
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); // number = +/- number.fraction * 10^+/- exponent
item->valuedouble=n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}
// Render the number nicely from the given item into a string.
static char *print_number(cJSON *item)
{
char *str;
double d=item->valuedouble;
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
str=(char*)cJSON_malloc(21); // 2^64+1 can be represented in 21 chars.
sprintf(str,"%d",item->valueint);
}
else
{
str=(char*)cJSON_malloc(64); // This is a nice tradeoff.
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
return str;
}
// Parse the input text into an unescaped cstring, and populate item.
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
if (*str!='\"') return 0; // not a string!
while (*ptr!='\"' && (unsigned char)*ptr>31 && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes.
out=(char*)cJSON_malloc(len+1); // This is how long we need for the string, roughly.
if (!out) return 0;
ptr=str+1;ptr2=out;
while (*ptr!='\"' && (unsigned char)*ptr>31)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY.
sscanf(ptr+1,"%4x",&uc); // get the unicode char.
len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
switch (len) {
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;ptr+=4;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
item->valuestring=out;
item->type=cJSON_String;
return ptr;
}
// Render the cstring provided to an escaped version that can be printed.
static char *print_string_ptr(const char *str)
{
const char *ptr;char *ptr2,*out;int len=0;
if (!str) return cJSON_strdup("");
ptr=str;while (*ptr && ++len) {if ((unsigned char)*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;}
out=(char*)cJSON_malloc(len+3);
ptr2=out;ptr=str;
*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: ptr2--; break; // eviscerate with prejudice.
}
}
}
*ptr2++='\"';*ptr2++=0;
return out;
}
// Invote print_string_ptr (which is useful) on an item.
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
// Predeclare these prototypes.
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt);
// Utility to jump whitespace and cr/lf
static const char *skip(const char *in) {while (in && (unsigned char)*in<=32) in++; return in;}
// Parse an object - create a new root, and populate.
cJSON *cJSON_Parse(const char *value)
{
cJSON *c=cJSON_New_Item();
if (!c) return 0; /* memory fail */
if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
return c;
}
// Render a cJSON item/entity/structure to text.
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
// Parser core - when encountering text, process appropriately.
static const char *parse_value(cJSON *item,const char *value)
{
if (!value) return 0; // Fail on null.
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
if (*value=='\"') { return parse_string(item,value); }
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); }
return 0; // failure.
}
// Render a value to text.
static char *print_value(cJSON *item,int depth,int fmt)
{
char *out=0;
if (!item) return 0;
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item);break;
case cJSON_String: out=print_string(item);break;
case cJSON_Array: out=print_array(item,depth,fmt);break;
case cJSON_Object: out=print_object(item,depth,fmt);break;
}
return out;
}
// Build an array from input text.
static const char *parse_array(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='[') return 0; // not an array!
item->type=cJSON_Array;
value=skip(value+1);
if (*value==']') return value+1; // empty array.
item->child=child=cJSON_New_Item();
if (!item->child) return 0; // memory fail
value=skip(parse_value(child,skip(value))); // skip any spacing, get the value.
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; // memory fail
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1)));
if (!value) return 0; // memory fail
}
if (*value==']') return value+1; // end of array
return 0; // malformed.
}
// Render an array to text
static char *print_array(cJSON *item,int depth,int fmt)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
// How many entries in the array?
while (child) numentries++,child=child->next;
// Allocate an array to hold the values for each
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
// Retrieve all the results:
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
// If we didn't fail, try to malloc the output string
if (!fail) out=cJSON_malloc(len);
// If that fails, we fail.
if (!out) fail=1;
// Handle failure.
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
return 0;
}
// Compose the output array.
*out='[';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
cJSON_free(entries[i]);
}
cJSON_free(entries);
*ptr++=']';*ptr++=0;
return out;
}
// Build an object from the text.
static const char *parse_object(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='{') return 0; // not an object!
item->type=cJSON_Object;
value=skip(value+1);
if (*value=='}') return value+1; // empty array.
item->child=child=cJSON_New_Item();
value=skip(parse_string(child,skip(value)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') return 0; // fail!
value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value.
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; // memory fail
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') return 0; // fail!
value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value.
if (!value) return 0;
}
if (*value=='}') return value+1; // end of array
return 0; // malformed.
}
// Render an object to text.
static char *print_object(cJSON *item,int depth,int fmt)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child;
int numentries=0,fail=0;
// Count the number of entries.
while (child) numentries++,child=child->next;
// Allocate space for the names and the objects
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
// Collect all the results into our arrays:
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->string);
entries[i++]=ret=print_value(child,depth,fmt);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
// Try to allocate the output string
if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1;
// Handle failure
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) free(names[i]);if (entries[i]) free(entries[i]);}
free(names);free(entries);
return 0;
}
// Compose the output:
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
*ptr++=':';if (fmt) *ptr++='\t';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
return out;
}
// Get Array size/item / object item.
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
// Utility for array list handling.
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
// Utility for handling references.
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
// Add item to array/object.
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
// Replace array/object items with new ones.
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
// Create basic types:
cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item();item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();item->type=cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;}
cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();item->type=cJSON_Object;return item;}
// Create Arrays:
cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}

View File

@ -249,6 +249,8 @@ int ESLconnection::events(const char *etype, const char *value)
if (!strcmp(etype, "xml")) {
type_id = ESL_EVENT_TYPE_XML;
} else if (!strcmp(etype, "json")) {
type_id = ESL_EVENT_TYPE_JSON;
}
return esl_events(&handle, type_id, value);
@ -263,22 +265,32 @@ ESLevent::ESLevent(const char *type, const char *subclass_name)
event_construct_common();
if (esl_name_event(type, &event_id) != ESL_SUCCESS) {
event_id = ESL_EVENT_MESSAGE;
}
if (!strcasecmp(type, "json") && !esl_strlen_zero(subclass_name)) {
if (esl_event_create_json(&event, subclass_name) != ESL_SUCCESS) {
return;
}
event_id = event->event_id;
} else {
if (!esl_strlen_zero(subclass_name) && event_id != ESL_EVENT_CUSTOM) {
esl_log(ESL_LOG_WARNING, "Changing event type to custom because you specified a subclass name!\n");
event_id = ESL_EVENT_CUSTOM;
}
if (esl_name_event(type, &event_id) != ESL_SUCCESS) {
event_id = ESL_EVENT_MESSAGE;
}
if (esl_event_create_subclass(&event, event_id, subclass_name) != ESL_SUCCESS) {
esl_log(ESL_LOG_ERROR, "Failed to create event!\n");
event = NULL;
}
if (!esl_strlen_zero(subclass_name) && event_id != ESL_EVENT_CUSTOM) {
esl_log(ESL_LOG_WARNING, "Changing event type to custom because you specified a subclass name!\n");
event_id = ESL_EVENT_CUSTOM;
}
if (esl_event_create_subclass(&event, event_id, subclass_name) != ESL_SUCCESS) {
esl_log(ESL_LOG_ERROR, "Failed to create event!\n");
event = NULL;
}
}
serialized_string = NULL;
mine = 1;
}
ESLevent::ESLevent(esl_event_t *wrap_me, int free_me)
@ -289,7 +301,6 @@ ESLevent::ESLevent(esl_event_t *wrap_me, int free_me)
serialized_string = NULL;
}
ESLevent::ESLevent(ESLevent *me)
{
/* workaround for silly php thing */
@ -344,6 +355,11 @@ const char *ESLevent::serialize(const char *format)
return "";
}
if (!strcasecmp(format, "json")) {
esl_event_serialize_json(event, &serialized_string);
return serialized_string;
}
if (esl_event_serialize(event, &serialized_string, ESL_TRUE) == ESL_SUCCESS) {
return serialized_string;
}

View File

@ -49,7 +49,8 @@ typedef struct esl_event esl_event_t;
typedef enum {
ESL_EVENT_TYPE_PLAIN,
ESL_EVENT_TYPE_XML
ESL_EVENT_TYPE_XML,
ESL_EVENT_TYPE_JSON
} esl_event_type_t;
#ifdef WIN32
@ -246,6 +247,9 @@ typedef ssize_t esl_ssize_t;
typedef int esl_filehandle_t;
#endif
#include "math.h"
#include "esl_json.h"
typedef int16_t esl_port_t;
typedef enum {

View File

@ -273,7 +273,8 @@ ESL_DECLARE(esl_status_t) esl_name_event(const char *name, esl_event_types_t *ty
\note you must free the resulting string when you are finished with it
*/
ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode);
ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str);
ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json);
/*!
\brief Add a body to an event
\param event the event to add to body to

125
libs/esl/src/include/esl_json.h Executable file
View File

@ -0,0 +1,125 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "esl.h"
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
// cJSON Types:
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
// The cJSON structure:
typedef struct cJSON {
struct cJSON *next,*prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem
struct cJSON *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object.
int type; // The type of the item, as above.
char *valuestring; // The item's string, if type==cJSON_String
int valueint; // The item's number, if type==cJSON_Number
double valuedouble; // The item's number, if type==cJSON_Number
char *string; // The item's name string, if this item is the child of, or is in the list of subitems of an object.
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
// Supply malloc, realloc and free functions to cJSON
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
// Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished.
extern cJSON *cJSON_Parse(const char *value);
// Render a cJSON entity to text for transfer/storage. Free the char* when finished.
extern char *cJSON_Print(cJSON *item);
// Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished.
extern char *cJSON_PrintUnformatted(cJSON *item);
// Delete a cJSON entity and all subentities.
extern void cJSON_Delete(cJSON *c);
// Returns the number of items in an array (or object).
extern int cJSON_GetArraySize(cJSON *array);
// Retrieve item number "item" from array "array". Returns NULL if unsuccessful.
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
// Get item "string" from object. Case insensitive.
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
// These calls create a cJSON item of the appropriate type.
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);
// These utilities create an Array of count items.
extern cJSON *cJSON_CreateIntArray(int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
// Append item to the specified array/object.
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
// Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON.
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
// Remove/Detatch items from Arrays/Objects.
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
// Update array items.
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
#ifdef __cplusplus
}
#endif
#endif