indent pass MODAPP-202
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11335 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
d88a0fbefc
commit
af82478311
|
@ -23,71 +23,73 @@
|
|||
#include "bits.h"
|
||||
#include "arraylist.h"
|
||||
|
||||
struct array_list*
|
||||
array_list_new(array_list_free_fn *free_fn)
|
||||
struct array_list *array_list_new(array_list_free_fn * free_fn)
|
||||
{
|
||||
struct array_list *this;
|
||||
struct array_list *this;
|
||||
|
||||
if(!(this = calloc(1, sizeof(struct array_list)))) return NULL;
|
||||
this->size = ARRAY_LIST_DEFAULT_SIZE;
|
||||
this->length = 0;
|
||||
this->free_fn = free_fn;
|
||||
if(!(this->array = calloc(sizeof(void*), this->size))) {
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return this;
|
||||
if (!(this = calloc(1, sizeof(struct array_list))))
|
||||
return NULL;
|
||||
this->size = ARRAY_LIST_DEFAULT_SIZE;
|
||||
this->length = 0;
|
||||
this->free_fn = free_fn;
|
||||
if (!(this->array = calloc(sizeof(void *), this->size))) {
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
extern void
|
||||
array_list_free(struct array_list *this)
|
||||
extern void array_list_free(struct array_list *this)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < this->length; i++)
|
||||
if(this->array[i]) this->free_fn(this->array[i]);
|
||||
free(this->array);
|
||||
free(this);
|
||||
int i;
|
||||
for (i = 0; i < this->length; i++)
|
||||
if (this->array[i])
|
||||
this->free_fn(this->array[i]);
|
||||
free(this->array);
|
||||
free(this);
|
||||
}
|
||||
|
||||
void*
|
||||
array_list_get_idx(struct array_list *this, int i)
|
||||
void *array_list_get_idx(struct array_list *this, int i)
|
||||
{
|
||||
if(i >= this->length) return NULL;
|
||||
return this->array[i];
|
||||
if (i >= this->length)
|
||||
return NULL;
|
||||
return this->array[i];
|
||||
}
|
||||
|
||||
static int array_list_expand_internal(struct array_list *this, int max)
|
||||
{
|
||||
void *t;
|
||||
int new_size;
|
||||
void *t;
|
||||
int new_size;
|
||||
|
||||
if(max < this->size) return 0;
|
||||
new_size = max(this->size << 1, max);
|
||||
if(!(t = realloc(this->array, new_size*sizeof(void*)))) return -1;
|
||||
this->array = t;
|
||||
(void)memset(this->array + this->size, 0, (new_size-this->size)*sizeof(void*));
|
||||
this->size = new_size;
|
||||
return 0;
|
||||
if (max < this->size)
|
||||
return 0;
|
||||
new_size = max(this->size << 1, max);
|
||||
if (!(t = realloc(this->array, new_size * sizeof(void *))))
|
||||
return -1;
|
||||
this->array = t;
|
||||
(void) memset(this->array + this->size, 0, (new_size - this->size) * sizeof(void *));
|
||||
this->size = new_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
array_list_put_idx(struct array_list *this, int idx, void *data)
|
||||
int array_list_put_idx(struct array_list *this, int idx, void *data)
|
||||
{
|
||||
if(array_list_expand_internal(this, idx)) return -1;
|
||||
if(this->array[idx]) this->free_fn(this->array[idx]);
|
||||
this->array[idx] = data;
|
||||
if(this->length <= idx) this->length = idx + 1;
|
||||
return 0;
|
||||
if (array_list_expand_internal(this, idx))
|
||||
return -1;
|
||||
if (this->array[idx])
|
||||
this->free_fn(this->array[idx]);
|
||||
this->array[idx] = data;
|
||||
if (this->length <= idx)
|
||||
this->length = idx + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
array_list_add(struct array_list *this, void *data)
|
||||
int array_list_add(struct array_list *this, void *data)
|
||||
{
|
||||
return array_list_put_idx(this, this->length, data);
|
||||
return array_list_put_idx(this, this->length, data);
|
||||
}
|
||||
|
||||
int
|
||||
array_list_length(struct array_list *this)
|
||||
int array_list_length(struct array_list *this)
|
||||
{
|
||||
return this->length;
|
||||
return this->length;
|
||||
}
|
||||
|
|
|
@ -16,30 +16,23 @@
|
|||
|
||||
typedef void (array_list_free_fn) (void *data);
|
||||
|
||||
struct array_list
|
||||
{
|
||||
void **array;
|
||||
int length;
|
||||
int size;
|
||||
array_list_free_fn *free_fn;
|
||||
struct array_list {
|
||||
void **array;
|
||||
int length;
|
||||
int size;
|
||||
array_list_free_fn *free_fn;
|
||||
};
|
||||
|
||||
extern struct array_list*
|
||||
array_list_new(array_list_free_fn *free_fn);
|
||||
extern struct array_list *array_list_new(array_list_free_fn * free_fn);
|
||||
|
||||
extern void
|
||||
array_list_free(struct array_list *al);
|
||||
extern void array_list_free(struct array_list *al);
|
||||
|
||||
extern void*
|
||||
array_list_get_idx(struct array_list *al, int i);
|
||||
extern void *array_list_get_idx(struct array_list *al, int i);
|
||||
|
||||
extern int
|
||||
array_list_put_idx(struct array_list *al, int i, void *data);
|
||||
extern int array_list_put_idx(struct array_list *al, int i, void *data);
|
||||
|
||||
extern int
|
||||
array_list_add(struct array_list *al, void *data);
|
||||
extern int array_list_add(struct array_list *al, void *data);
|
||||
|
||||
extern int
|
||||
array_list_length(struct array_list *al);
|
||||
extern int array_list_length(struct array_list *al);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,48 +33,55 @@
|
|||
static int _syslog = 0;
|
||||
static int _debug = 0;
|
||||
|
||||
void mc_set_debug(int debug) { _debug = debug; }
|
||||
int mc_get_debug() { return _debug; }
|
||||
void mc_set_debug(int debug)
|
||||
{
|
||||
_debug = debug;
|
||||
}
|
||||
|
||||
int mc_get_debug()
|
||||
{
|
||||
return _debug;
|
||||
}
|
||||
|
||||
extern void mc_set_syslog(int syslog)
|
||||
{
|
||||
_syslog = syslog;
|
||||
_syslog = syslog;
|
||||
}
|
||||
|
||||
void mc_abort(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
#if HAVE_VSYSLOG
|
||||
if(_syslog) {
|
||||
vsyslog(LOG_ERR, msg, ap);
|
||||
} else
|
||||
if (_syslog) {
|
||||
vsyslog(LOG_ERR, msg, ap);
|
||||
} else
|
||||
#endif
|
||||
vprintf(msg, ap);
|
||||
exit(1);
|
||||
vprintf(msg, ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void mc_debug(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if(_debug) {
|
||||
va_start(ap, msg);
|
||||
va_list ap;
|
||||
if (_debug) {
|
||||
va_start(ap, msg);
|
||||
#if HAVE_VSYSLOG
|
||||
if(_syslog) {
|
||||
vsyslog(LOG_DEBUG, msg, ap);
|
||||
} else
|
||||
if (_syslog) {
|
||||
vsyslog(LOG_DEBUG, msg, ap);
|
||||
} else
|
||||
#endif
|
||||
vprintf(msg, ap);
|
||||
}
|
||||
vprintf(msg, ap);
|
||||
}
|
||||
}
|
||||
|
||||
void mc_error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
#if HAVE_VSYSLOG
|
||||
if(_syslog) {
|
||||
if (_syslog) {
|
||||
vsyslog(LOG_ERR, msg, ap);
|
||||
} else
|
||||
#endif
|
||||
|
@ -83,10 +90,10 @@ void mc_error(const char *msg, ...)
|
|||
|
||||
void mc_info(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
#if HAVE_VSYSLOG
|
||||
if(_syslog) {
|
||||
if (_syslog) {
|
||||
vsyslog(LOG_INFO, msg, ap);
|
||||
} else
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -74,65 +74,65 @@ do {\
|
|||
#define STATUS_CODE_LEN 4
|
||||
|
||||
typedef enum tokens {
|
||||
VERSION,
|
||||
STATUS_CODE,
|
||||
PHRASE,
|
||||
HEADER,
|
||||
NEWLINE,
|
||||
SYNTAX_ERROR
|
||||
VERSION,
|
||||
STATUS_CODE,
|
||||
PHRASE,
|
||||
HEADER,
|
||||
NEWLINE,
|
||||
SYNTAX_ERROR
|
||||
} token_t;
|
||||
|
||||
typedef enum accept_states {
|
||||
ASWR,
|
||||
ASNR,
|
||||
NOAS
|
||||
ASWR,
|
||||
ASNR,
|
||||
NOAS
|
||||
} accept_state_t;
|
||||
|
||||
typedef struct state_machines {
|
||||
accept_state_t (*state)(char, struct state_machines *);
|
||||
int pos;
|
||||
char *buf;
|
||||
ssize_t buf_len;
|
||||
int stop;
|
||||
token_t token;
|
||||
accept_state_t(*state) (char, struct state_machines *);
|
||||
int pos;
|
||||
char *buf;
|
||||
ssize_t buf_len;
|
||||
int stop;
|
||||
token_t token;
|
||||
} state_machine_t;
|
||||
|
||||
typedef enum http_methods {
|
||||
GET,
|
||||
HEAD,
|
||||
POST,
|
||||
DELETE,
|
||||
PUT
|
||||
GET,
|
||||
HEAD,
|
||||
POST,
|
||||
DELETE,
|
||||
PUT
|
||||
} http_method_t;
|
||||
|
||||
typedef struct http_headers {
|
||||
char *field_name;
|
||||
char *value;
|
||||
char *field_name;
|
||||
char *value;
|
||||
} http_header_t;
|
||||
|
||||
typedef struct http_requests {
|
||||
http_method_t method;
|
||||
char *version;
|
||||
char *url;
|
||||
http_header_t *headers;
|
||||
ssize_t header_len;
|
||||
char *body;
|
||||
ssize_t body_len;
|
||||
http_method_t method;
|
||||
char *version;
|
||||
char *url;
|
||||
http_header_t *headers;
|
||||
ssize_t header_len;
|
||||
char *body;
|
||||
ssize_t body_len;
|
||||
} http_request_t;
|
||||
|
||||
typedef struct http_responses {
|
||||
char *version;
|
||||
int status_code;
|
||||
char *phrase;
|
||||
http_header_t *headers;
|
||||
ssize_t header_len;
|
||||
char *body;
|
||||
int body_len;
|
||||
char *version;
|
||||
int status_code;
|
||||
char *phrase;
|
||||
http_header_t *headers;
|
||||
ssize_t header_len;
|
||||
char *body;
|
||||
int body_len;
|
||||
} http_response_t;
|
||||
|
||||
token_t get_next_token(state_machine_t *sm);
|
||||
int http_parse_response(char *buf, ssize_t buf_len, http_response_t *response);
|
||||
int http_req(http_request_t *req, http_response_t *res);
|
||||
void free_http_response(http_response_t *response);
|
||||
token_t get_next_token(state_machine_t * sm);
|
||||
int http_parse_response(char *buf, ssize_t buf_len, http_response_t * response);
|
||||
int http_req(http_request_t * req, http_response_t * res);
|
||||
void free_http_response(http_response_t * response);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,5 +27,4 @@ extern "C" {
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#if !HAVE_STRNDUP
|
||||
|
||||
char* strndup(const char* str, size_t n);
|
||||
char *strndup(const char *str, size_t n);
|
||||
|
||||
#endif /* !HAVE_STRNDUP */
|
||||
|
||||
|
@ -35,19 +35,19 @@ char *json_number_chars = "0123456789.+-e";
|
|||
char *json_hex_chars = "0123456789abcdef";
|
||||
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
static char* json_type_name[] = {
|
||||
"null",
|
||||
"boolean",
|
||||
"double",
|
||||
"int",
|
||||
"object",
|
||||
"array",
|
||||
"string",
|
||||
static char *json_type_name[] = {
|
||||
"null",
|
||||
"boolean",
|
||||
"double",
|
||||
"int",
|
||||
"object",
|
||||
"array",
|
||||
"string",
|
||||
};
|
||||
#endif /* REFCOUNT_DEBUG */
|
||||
|
||||
static void json_object_generic_delete(struct json_object* this);
|
||||
static struct json_object* json_object_new(enum json_type o_type);
|
||||
static void json_object_generic_delete(struct json_object *this);
|
||||
static struct json_object *json_object_new(enum json_type o_type);
|
||||
|
||||
|
||||
/* ref count debugging */
|
||||
|
@ -57,24 +57,25 @@ static struct json_object* json_object_new(enum json_type o_type);
|
|||
static struct lh_table *json_object_table;
|
||||
|
||||
static void json_object_init() __attribute__ ((constructor));
|
||||
static void json_object_init() {
|
||||
mc_debug("json_object_init: creating object table\n");
|
||||
json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
|
||||
static void json_object_init()
|
||||
{
|
||||
mc_debug("json_object_init: creating object table\n");
|
||||
json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
|
||||
}
|
||||
|
||||
static void json_object_fini() __attribute__ ((destructor));
|
||||
static void json_object_fini() {
|
||||
struct lh_entry *ent;
|
||||
if(mc_get_debug() && json_object_table->count) {
|
||||
mc_debug("json_object_fini: %d referenced objects at exit\n",
|
||||
json_object_table->count);
|
||||
lh_foreach(json_object_table, ent) {
|
||||
struct json_object* obj = (struct json_object*)ent->v;
|
||||
mc_debug("\t%s:%p\n", json_type_name[obj->o_type], obj);
|
||||
}
|
||||
}
|
||||
mc_debug("json_object_fini: freeing object table\n");
|
||||
lh_table_free(json_object_table);
|
||||
static void json_object_fini()
|
||||
{
|
||||
struct lh_entry *ent;
|
||||
if (mc_get_debug() && json_object_table->count) {
|
||||
mc_debug("json_object_fini: %d referenced objects at exit\n", json_object_table->count);
|
||||
lh_foreach(json_object_table, ent) {
|
||||
struct json_object *obj = (struct json_object *) ent->v;
|
||||
mc_debug("\t%s:%p\n", json_type_name[obj->o_type], obj);
|
||||
}
|
||||
}
|
||||
mc_debug("json_object_fini: freeing object table\n");
|
||||
lh_table_free(json_object_table);
|
||||
}
|
||||
#endif /* REFCOUNT_DEBUG */
|
||||
|
||||
|
@ -83,92 +84,99 @@ static void json_object_fini() {
|
|||
|
||||
static int json_escape_str(struct printbuf *pb, char *str)
|
||||
{
|
||||
int pos = 0, start_offset = 0;
|
||||
unsigned char c;
|
||||
do {
|
||||
c = str[pos];
|
||||
switch(c) {
|
||||
case '\0':
|
||||
break;
|
||||
case '\b':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
if(pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
if(c == '\b') printbuf_memappend(pb, "\\b", 2);
|
||||
else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
|
||||
else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
|
||||
else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
|
||||
else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
|
||||
else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
|
||||
else if(c == '/') printbuf_memappend(pb, "\\/", 2);
|
||||
start_offset = ++pos;
|
||||
break;
|
||||
default:
|
||||
if(c < ' ') {
|
||||
if(pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
sprintbuf(pb, "\\u00%c%c",
|
||||
json_hex_chars[c >> 4],
|
||||
json_hex_chars[c & 0xf]);
|
||||
start_offset = ++pos;
|
||||
} else pos++;
|
||||
}
|
||||
} while(c);
|
||||
if(pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
return 0;
|
||||
int pos = 0, start_offset = 0;
|
||||
unsigned char c;
|
||||
do {
|
||||
c = str[pos];
|
||||
switch (c) {
|
||||
case '\0':
|
||||
break;
|
||||
case '\b':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
if (pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
if (c == '\b')
|
||||
printbuf_memappend(pb, "\\b", 2);
|
||||
else if (c == '\n')
|
||||
printbuf_memappend(pb, "\\n", 2);
|
||||
else if (c == '\r')
|
||||
printbuf_memappend(pb, "\\r", 2);
|
||||
else if (c == '\t')
|
||||
printbuf_memappend(pb, "\\t", 2);
|
||||
else if (c == '"')
|
||||
printbuf_memappend(pb, "\\\"", 2);
|
||||
else if (c == '\\')
|
||||
printbuf_memappend(pb, "\\\\", 2);
|
||||
else if (c == '/')
|
||||
printbuf_memappend(pb, "\\/", 2);
|
||||
start_offset = ++pos;
|
||||
break;
|
||||
default:
|
||||
if (c < ' ') {
|
||||
if (pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
sprintbuf(pb, "\\u00%c%c", json_hex_chars[c >> 4], json_hex_chars[c & 0xf]);
|
||||
start_offset = ++pos;
|
||||
} else
|
||||
pos++;
|
||||
}
|
||||
} while (c);
|
||||
if (pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* reference counting */
|
||||
|
||||
extern struct json_object* json_object_get(struct json_object *this)
|
||||
extern struct json_object *json_object_get(struct json_object *this)
|
||||
{
|
||||
if(this) {
|
||||
this->_ref_count++;
|
||||
}
|
||||
return this;
|
||||
if (this) {
|
||||
this->_ref_count++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
extern void json_object_put(struct json_object *this)
|
||||
{
|
||||
if(this) {
|
||||
this->_ref_count--;
|
||||
if(!this->_ref_count) this->_delete(this);
|
||||
}
|
||||
if (this) {
|
||||
this->_ref_count--;
|
||||
if (!this->_ref_count)
|
||||
this->_delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* generic object construction and destruction parts */
|
||||
|
||||
static void json_object_generic_delete(struct json_object* this)
|
||||
static void json_object_generic_delete(struct json_object *this)
|
||||
{
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
mc_debug("json_object_delete_%s: %p\n",
|
||||
json_type_name[this->o_type], this);
|
||||
lh_table_delete(json_object_table, this);
|
||||
mc_debug("json_object_delete_%s: %p\n", json_type_name[this->o_type], this);
|
||||
lh_table_delete(json_object_table, this);
|
||||
#endif /* REFCOUNT_DEBUG */
|
||||
printbuf_free(this->_pb);
|
||||
free(this);
|
||||
printbuf_free(this->_pb);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static struct json_object* json_object_new(enum json_type o_type)
|
||||
static struct json_object *json_object_new(enum json_type o_type)
|
||||
{
|
||||
struct json_object *this = calloc(sizeof(struct json_object), 1);
|
||||
if(!this) return NULL;
|
||||
this->o_type = o_type;
|
||||
this->_ref_count = 1;
|
||||
this->_delete = &json_object_generic_delete;
|
||||
struct json_object *this = calloc(sizeof(struct json_object), 1);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->o_type = o_type;
|
||||
this->_ref_count = 1;
|
||||
this->_delete = &json_object_generic_delete;
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
lh_table_insert(json_object_table, this, this);
|
||||
mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
|
||||
lh_table_insert(json_object_table, this, this);
|
||||
mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
|
||||
#endif /* REFCOUNT_DEBUG */
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
@ -176,335 +184,354 @@ static struct json_object* json_object_new(enum json_type o_type)
|
|||
|
||||
int json_object_is_type(struct json_object *this, enum json_type type)
|
||||
{
|
||||
return (this->o_type == type);
|
||||
return (this->o_type == type);
|
||||
}
|
||||
|
||||
enum json_type json_object_get_type(struct json_object *this)
|
||||
{
|
||||
return this->o_type;
|
||||
return this->o_type;
|
||||
}
|
||||
|
||||
|
||||
/* json_object_to_json_string */
|
||||
|
||||
char* json_object_to_json_string(struct json_object *this)
|
||||
char *json_object_to_json_string(struct json_object *this)
|
||||
{
|
||||
if(!this) return "null";
|
||||
if(!this->_pb) {
|
||||
if(!(this->_pb = printbuf_new())) return NULL;
|
||||
} else {
|
||||
printbuf_reset(this->_pb);
|
||||
}
|
||||
if(this->_to_json_string(this, this->_pb) < 0) return NULL;
|
||||
return this->_pb->buf;
|
||||
if (!this)
|
||||
return "null";
|
||||
if (!this->_pb) {
|
||||
if (!(this->_pb = printbuf_new()))
|
||||
return NULL;
|
||||
} else {
|
||||
printbuf_reset(this->_pb);
|
||||
}
|
||||
if (this->_to_json_string(this, this->_pb) < 0)
|
||||
return NULL;
|
||||
return this->_pb->buf;
|
||||
}
|
||||
|
||||
|
||||
/* json_object_object */
|
||||
|
||||
static int json_object_object_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
static int json_object_object_to_json_string(struct json_object *this, struct printbuf *pb)
|
||||
{
|
||||
int i=0;
|
||||
struct json_object_iter iter;
|
||||
sprintbuf(pb, "{");
|
||||
int i = 0;
|
||||
struct json_object_iter iter;
|
||||
sprintbuf(pb, "{");
|
||||
|
||||
/* CAW: scope operator to make ANSI correctness */
|
||||
/* CAW: switched to json_object_object_foreachC which uses an iterator struct */
|
||||
/* CAW: scope operator to make ANSI correctness */
|
||||
/* CAW: switched to json_object_object_foreachC which uses an iterator struct */
|
||||
json_object_object_foreachC(this, iter) {
|
||||
if(i) sprintbuf(pb, ",");
|
||||
sprintbuf(pb, " \"");
|
||||
json_escape_str(pb, iter.key);
|
||||
sprintbuf(pb, "\": ");
|
||||
if(iter.val == NULL) sprintbuf(pb, "null");
|
||||
else iter.val->_to_json_string(iter.val, pb);
|
||||
i++;
|
||||
if (i)
|
||||
sprintbuf(pb, ",");
|
||||
sprintbuf(pb, " \"");
|
||||
json_escape_str(pb, iter.key);
|
||||
sprintbuf(pb, "\": ");
|
||||
if (iter.val == NULL)
|
||||
sprintbuf(pb, "null");
|
||||
else
|
||||
iter.val->_to_json_string(iter.val, pb);
|
||||
i++;
|
||||
}
|
||||
|
||||
return sprintbuf(pb, " }");
|
||||
return sprintbuf(pb, " }");
|
||||
}
|
||||
|
||||
static void json_object_lh_entry_free(struct lh_entry *ent)
|
||||
{
|
||||
free(ent->k);
|
||||
json_object_put((struct json_object*)ent->v);
|
||||
free(ent->k);
|
||||
json_object_put((struct json_object *) ent->v);
|
||||
}
|
||||
|
||||
static void json_object_object_delete(struct json_object* this)
|
||||
static void json_object_object_delete(struct json_object *this)
|
||||
{
|
||||
lh_table_free(this->o.c_object);
|
||||
json_object_generic_delete(this);
|
||||
lh_table_free(this->o.c_object);
|
||||
json_object_generic_delete(this);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_object()
|
||||
struct json_object *json_object_new_object()
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_object);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_object_delete;
|
||||
this->_to_json_string = &json_object_object_to_json_string;
|
||||
this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES,
|
||||
NULL, &json_object_lh_entry_free);
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_object);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_delete = &json_object_object_delete;
|
||||
this->_to_json_string = &json_object_object_to_json_string;
|
||||
this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES, NULL, &json_object_lh_entry_free);
|
||||
return this;
|
||||
}
|
||||
|
||||
struct lh_table* json_object_get_object(struct json_object *this)
|
||||
struct lh_table *json_object_get_object(struct json_object *this)
|
||||
{
|
||||
if(!this) return NULL;
|
||||
switch(this->o_type) {
|
||||
case json_type_object:
|
||||
return this->o.c_object;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
if (!this)
|
||||
return NULL;
|
||||
switch (this->o_type) {
|
||||
case json_type_object:
|
||||
return this->o.c_object;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void json_object_object_add(struct json_object* this, char *key,
|
||||
struct json_object *val)
|
||||
void json_object_object_add(struct json_object *this, char *key, struct json_object *val)
|
||||
{
|
||||
lh_table_delete(this->o.c_object, key);
|
||||
lh_table_insert(this->o.c_object, strdup(key), val);
|
||||
lh_table_delete(this->o.c_object, key);
|
||||
lh_table_insert(this->o.c_object, strdup(key), val);
|
||||
}
|
||||
|
||||
struct json_object* json_object_object_get(struct json_object* this, char *key)
|
||||
struct json_object *json_object_object_get(struct json_object *this, char *key)
|
||||
{
|
||||
return (struct json_object*) lh_table_lookup(this->o.c_object, key);
|
||||
return (struct json_object *) lh_table_lookup(this->o.c_object, key);
|
||||
}
|
||||
|
||||
void json_object_object_del(struct json_object* this, char *key)
|
||||
void json_object_object_del(struct json_object *this, char *key)
|
||||
{
|
||||
lh_table_delete(this->o.c_object, key);
|
||||
lh_table_delete(this->o.c_object, key);
|
||||
}
|
||||
|
||||
|
||||
/* json_object_boolean */
|
||||
|
||||
static int json_object_boolean_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
static int json_object_boolean_to_json_string(struct json_object *this, struct printbuf *pb)
|
||||
{
|
||||
if(this->o.c_boolean) return sprintbuf(pb, "true");
|
||||
else return sprintbuf(pb, "false");
|
||||
if (this->o.c_boolean)
|
||||
return sprintbuf(pb, "true");
|
||||
else
|
||||
return sprintbuf(pb, "false");
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_boolean(boolean b)
|
||||
struct json_object *json_object_new_boolean(boolean b)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_boolean);
|
||||
if(!this) return NULL;
|
||||
this->_to_json_string = &json_object_boolean_to_json_string;
|
||||
this->o.c_boolean = b;
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_boolean);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_to_json_string = &json_object_boolean_to_json_string;
|
||||
this->o.c_boolean = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean json_object_get_boolean(struct json_object *this)
|
||||
boolean json_object_get_boolean(struct json_object * this)
|
||||
{
|
||||
if(!this) return FALSE;
|
||||
switch(this->o_type) {
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_int:
|
||||
return (this->o.c_int != 0);
|
||||
case json_type_double:
|
||||
return (this->o.c_double != 0);
|
||||
case json_type_string:
|
||||
if(strlen(this->o.c_string)) return TRUE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
if (!this)
|
||||
return FALSE;
|
||||
switch (this->o_type) {
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_int:
|
||||
return (this->o.c_int != 0);
|
||||
case json_type_double:
|
||||
return (this->o.c_double != 0);
|
||||
case json_type_string:
|
||||
if (strlen(this->o.c_string))
|
||||
return TRUE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_int */
|
||||
|
||||
static int json_object_int_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
static int json_object_int_to_json_string(struct json_object *this, struct printbuf *pb)
|
||||
{
|
||||
return sprintbuf(pb, "%d", this->o.c_int);
|
||||
return sprintbuf(pb, "%d", this->o.c_int);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_int(int i)
|
||||
struct json_object *json_object_new_int(int i)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_int);
|
||||
if(!this) return NULL;
|
||||
this->_to_json_string = &json_object_int_to_json_string;
|
||||
this->o.c_int = i;
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_int);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_to_json_string = &json_object_int_to_json_string;
|
||||
this->o.c_int = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
int json_object_get_int(struct json_object *this)
|
||||
{
|
||||
int cint;
|
||||
int cint;
|
||||
|
||||
if(!this) return 0;
|
||||
switch(this->o_type) {
|
||||
case json_type_int:
|
||||
return this->o.c_int;
|
||||
case json_type_double:
|
||||
return (int)this->o.c_double;
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_string:
|
||||
if(sscanf(this->o.c_string, "%d", &cint) == 1) return cint;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (!this)
|
||||
return 0;
|
||||
switch (this->o_type) {
|
||||
case json_type_int:
|
||||
return this->o.c_int;
|
||||
case json_type_double:
|
||||
return (int) this->o.c_double;
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_string:
|
||||
if (sscanf(this->o.c_string, "%d", &cint) == 1)
|
||||
return cint;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_double */
|
||||
|
||||
static int json_object_double_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
static int json_object_double_to_json_string(struct json_object *this, struct printbuf *pb)
|
||||
{
|
||||
return sprintbuf(pb, "%lf", this->o.c_double);
|
||||
return sprintbuf(pb, "%lf", this->o.c_double);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_double(double d)
|
||||
struct json_object *json_object_new_double(double d)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_double);
|
||||
if(!this) return NULL;
|
||||
this->_to_json_string = &json_object_double_to_json_string;
|
||||
this->o.c_double = d;
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_double);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_to_json_string = &json_object_double_to_json_string;
|
||||
this->o.c_double = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
double json_object_get_double(struct json_object *this)
|
||||
{
|
||||
double cdouble;
|
||||
double cdouble;
|
||||
|
||||
if(!this) return 0.0;
|
||||
switch(this->o_type) {
|
||||
case json_type_double:
|
||||
return this->o.c_double;
|
||||
case json_type_int:
|
||||
return this->o.c_int;
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_string:
|
||||
if(sscanf(this->o.c_string, "%lf", &cdouble) == 1) return cdouble;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
if (!this)
|
||||
return 0.0;
|
||||
switch (this->o_type) {
|
||||
case json_type_double:
|
||||
return this->o.c_double;
|
||||
case json_type_int:
|
||||
return this->o.c_int;
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_string:
|
||||
if (sscanf(this->o.c_string, "%lf", &cdouble) == 1)
|
||||
return cdouble;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_string */
|
||||
|
||||
static int json_object_string_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
static int json_object_string_to_json_string(struct json_object *this, struct printbuf *pb)
|
||||
{
|
||||
sprintbuf(pb, "\"");
|
||||
json_escape_str(pb, this->o.c_string);
|
||||
sprintbuf(pb, "\"");
|
||||
return 0;
|
||||
sprintbuf(pb, "\"");
|
||||
json_escape_str(pb, this->o.c_string);
|
||||
sprintbuf(pb, "\"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void json_object_string_delete(struct json_object* this)
|
||||
static void json_object_string_delete(struct json_object *this)
|
||||
{
|
||||
free(this->o.c_string);
|
||||
json_object_generic_delete(this);
|
||||
free(this->o.c_string);
|
||||
json_object_generic_delete(this);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_string(char *s)
|
||||
struct json_object *json_object_new_string(char *s)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_string);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_string_delete;
|
||||
this->_to_json_string = &json_object_string_to_json_string;
|
||||
this->o.c_string = strdup(s);
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_string);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_delete = &json_object_string_delete;
|
||||
this->_to_json_string = &json_object_string_to_json_string;
|
||||
this->o.c_string = strdup(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_string_len(char *s, int len)
|
||||
struct json_object *json_object_new_string_len(char *s, int len)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_string);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_string_delete;
|
||||
this->_to_json_string = &json_object_string_to_json_string;
|
||||
this->o.c_string = strndup(s, len);
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_string);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_delete = &json_object_string_delete;
|
||||
this->_to_json_string = &json_object_string_to_json_string;
|
||||
this->o.c_string = strndup(s, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
char* json_object_get_string(struct json_object *this)
|
||||
char *json_object_get_string(struct json_object *this)
|
||||
{
|
||||
if(!this) return NULL;
|
||||
switch(this->o_type) {
|
||||
case json_type_string:
|
||||
return this->o.c_string;
|
||||
default:
|
||||
return json_object_to_json_string(this);
|
||||
}
|
||||
if (!this)
|
||||
return NULL;
|
||||
switch (this->o_type) {
|
||||
case json_type_string:
|
||||
return this->o.c_string;
|
||||
default:
|
||||
return json_object_to_json_string(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_array */
|
||||
|
||||
static int json_object_array_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
static int json_object_array_to_json_string(struct json_object *this, struct printbuf *pb)
|
||||
{
|
||||
int i;
|
||||
sprintbuf(pb, "[");
|
||||
for(i=0; i < json_object_array_length(this); i++) {
|
||||
struct json_object *val;
|
||||
if(i) { sprintbuf(pb, ", "); }
|
||||
else { sprintbuf(pb, " "); }
|
||||
int i;
|
||||
sprintbuf(pb, "[");
|
||||
for (i = 0; i < json_object_array_length(this); i++) {
|
||||
struct json_object *val;
|
||||
if (i) {
|
||||
sprintbuf(pb, ", ");
|
||||
} else {
|
||||
sprintbuf(pb, " ");
|
||||
}
|
||||
|
||||
val = json_object_array_get_idx(this, i);
|
||||
if(val == NULL) { sprintbuf(pb, "null"); }
|
||||
else { val->_to_json_string(val, pb); }
|
||||
}
|
||||
return sprintbuf(pb, " ]");
|
||||
val = json_object_array_get_idx(this, i);
|
||||
if (val == NULL) {
|
||||
sprintbuf(pb, "null");
|
||||
} else {
|
||||
val->_to_json_string(val, pb);
|
||||
}
|
||||
}
|
||||
return sprintbuf(pb, " ]");
|
||||
}
|
||||
|
||||
static void json_object_array_entry_free(void *data)
|
||||
{
|
||||
json_object_put((struct json_object*)data);
|
||||
json_object_put((struct json_object *) data);
|
||||
}
|
||||
|
||||
static void json_object_array_delete(struct json_object* this)
|
||||
static void json_object_array_delete(struct json_object *this)
|
||||
{
|
||||
array_list_free(this->o.c_array);
|
||||
json_object_generic_delete(this);
|
||||
array_list_free(this->o.c_array);
|
||||
json_object_generic_delete(this);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_array()
|
||||
struct json_object *json_object_new_array()
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_array);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_array_delete;
|
||||
this->_to_json_string = &json_object_array_to_json_string;
|
||||
this->o.c_array = array_list_new(&json_object_array_entry_free);
|
||||
return this;
|
||||
struct json_object *this = json_object_new(json_type_array);
|
||||
if (!this)
|
||||
return NULL;
|
||||
this->_delete = &json_object_array_delete;
|
||||
this->_to_json_string = &json_object_array_to_json_string;
|
||||
this->o.c_array = array_list_new(&json_object_array_entry_free);
|
||||
return this;
|
||||
}
|
||||
|
||||
struct array_list* json_object_get_array(struct json_object *this)
|
||||
struct array_list *json_object_get_array(struct json_object *this)
|
||||
{
|
||||
if(!this) return NULL;
|
||||
switch(this->o_type) {
|
||||
case json_type_array:
|
||||
return this->o.c_array;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
if (!this)
|
||||
return NULL;
|
||||
switch (this->o_type) {
|
||||
case json_type_array:
|
||||
return this->o.c_array;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int json_object_array_length(struct json_object *this)
|
||||
{
|
||||
return array_list_length(this->o.c_array);
|
||||
return array_list_length(this->o.c_array);
|
||||
}
|
||||
|
||||
int json_object_array_add(struct json_object *this,struct json_object *val)
|
||||
int json_object_array_add(struct json_object *this, struct json_object *val)
|
||||
{
|
||||
return array_list_add(this->o.c_array, val);
|
||||
return array_list_add(this->o.c_array, val);
|
||||
}
|
||||
|
||||
int json_object_array_put_idx(struct json_object *this, int idx,
|
||||
struct json_object *val)
|
||||
int json_object_array_put_idx(struct json_object *this, int idx, struct json_object *val)
|
||||
{
|
||||
return array_list_put_idx(this->o.c_array, idx, val);
|
||||
return array_list_put_idx(this->o.c_array, idx, val);
|
||||
}
|
||||
|
||||
struct json_object* json_object_array_get_idx(struct json_object *this,
|
||||
int idx)
|
||||
struct json_object *json_object_array_get_idx(struct json_object *this, int idx)
|
||||
{
|
||||
return (struct json_object*)array_list_get_idx(this->o.c_array, idx);
|
||||
return (struct json_object *) array_list_get_idx(this->o.c_array, idx);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,13 +35,13 @@ struct json_object_iter;
|
|||
/* supported object types */
|
||||
|
||||
enum json_type {
|
||||
json_type_null,
|
||||
json_type_boolean,
|
||||
json_type_double,
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string
|
||||
json_type_null,
|
||||
json_type_boolean,
|
||||
json_type_double,
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string
|
||||
};
|
||||
|
||||
/* reference counting functions */
|
||||
|
@ -50,7 +50,7 @@ enum json_type {
|
|||
* Increment the reference count of json_object
|
||||
* @param obj the json_object instance
|
||||
*/
|
||||
extern struct json_object* json_object_get(struct json_object *obj);
|
||||
extern struct json_object *json_object_get(struct json_object *obj);
|
||||
|
||||
/**
|
||||
* Decrement the reference count of json_object and free if it reaches zero
|
||||
|
@ -90,7 +90,7 @@ extern enum json_type json_object_get_type(struct json_object *obj);
|
|||
* @param obj the json_object instance
|
||||
* @returns a string in JSON format
|
||||
*/
|
||||
extern char* json_object_to_json_string(struct json_object *obj);
|
||||
extern char *json_object_to_json_string(struct json_object *obj);
|
||||
|
||||
|
||||
/* object type methods */
|
||||
|
@ -98,13 +98,13 @@ extern char* json_object_to_json_string(struct json_object *obj);
|
|||
/** Create a new empty object
|
||||
* @returns a json_object of type json_type_object
|
||||
*/
|
||||
extern struct json_object* json_object_new_object();
|
||||
extern struct json_object *json_object_new_object();
|
||||
|
||||
/** Get the hashtable of a json_object of type json_type_object
|
||||
* @param obj the json_object instance
|
||||
* @returns a linkhash
|
||||
*/
|
||||
extern struct lh_table* json_object_get_object(struct json_object *obj);
|
||||
extern struct lh_table *json_object_get_object(struct json_object *obj);
|
||||
|
||||
/** Add an object field to a json_object of type json_type_object
|
||||
*
|
||||
|
@ -116,16 +116,14 @@ extern struct lh_table* json_object_get_object(struct json_object *obj);
|
|||
* @param key the object field name (a private copy will be duplicated)
|
||||
* @param val a json_object or NULL member to associate with the given field
|
||||
*/
|
||||
extern void json_object_object_add(struct json_object* obj, char *key,
|
||||
struct json_object *val);
|
||||
extern void json_object_object_add(struct json_object *obj, char *key, struct json_object *val);
|
||||
|
||||
/** Get the json_object associate with a given object field
|
||||
* @param obj the json_object instance
|
||||
* @param key the object field name
|
||||
* @returns the json_object associated with the given field name
|
||||
*/
|
||||
extern struct json_object* json_object_object_get(struct json_object* obj,
|
||||
char *key);
|
||||
extern struct json_object *json_object_object_get(struct json_object *obj, char *key);
|
||||
|
||||
/** Delete the given json_object field
|
||||
*
|
||||
|
@ -134,7 +132,7 @@ extern struct json_object* json_object_object_get(struct json_object* obj,
|
|||
* @param obj the json_object instance
|
||||
* @param key the object field name
|
||||
*/
|
||||
extern void json_object_object_del(struct json_object* obj, char *key);
|
||||
extern void json_object_object_del(struct json_object *obj, char *key);
|
||||
|
||||
/** Iterate through all keys and values of an object
|
||||
* @param obj the json_object instance
|
||||
|
@ -165,13 +163,13 @@ extern void json_object_object_del(struct json_object* obj, char *key);
|
|||
/** Create a new empty json_object of type json_type_array
|
||||
* @returns a json_object of type json_type_array
|
||||
*/
|
||||
extern struct json_object* json_object_new_array();
|
||||
extern struct json_object *json_object_new_array();
|
||||
|
||||
/** Get the arraylist of a json_object of type json_type_array
|
||||
* @param obj the json_object instance
|
||||
* @returns an arraylist
|
||||
*/
|
||||
extern struct array_list* json_object_get_array(struct json_object *obj);
|
||||
extern struct array_list *json_object_get_array(struct json_object *obj);
|
||||
|
||||
/** Get the length of a json_object of type json_type_array
|
||||
* @param obj the json_object instance
|
||||
|
@ -188,8 +186,7 @@ extern int json_object_array_length(struct json_object *obj);
|
|||
* @param obj the json_object instance
|
||||
* @param val the json_object to be added
|
||||
*/
|
||||
extern int json_object_array_add(struct json_object *obj,
|
||||
struct json_object *val);
|
||||
extern int json_object_array_add(struct json_object *obj, struct json_object *val);
|
||||
|
||||
/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
|
||||
*
|
||||
|
@ -206,16 +203,14 @@ extern int json_object_array_add(struct json_object *obj,
|
|||
* @param idx the index to insert the element at
|
||||
* @param val the json_object to be added
|
||||
*/
|
||||
extern int json_object_array_put_idx(struct json_object *obj, int idx,
|
||||
struct json_object *val);
|
||||
extern int json_object_array_put_idx(struct json_object *obj, int idx, struct json_object *val);
|
||||
|
||||
/** Get the element at specificed index of the array (a json_object of type json_type_array)
|
||||
* @param obj the json_object instance
|
||||
* @param idx the index to get the element at
|
||||
* @returns the json_object at the specified index (or NULL)
|
||||
*/
|
||||
extern struct json_object* json_object_array_get_idx(struct json_object *obj,
|
||||
int idx);
|
||||
extern struct json_object *json_object_array_get_idx(struct json_object *obj, int idx);
|
||||
|
||||
/* boolean type methods */
|
||||
|
||||
|
@ -223,7 +218,7 @@ extern struct json_object* json_object_array_get_idx(struct json_object *obj,
|
|||
* @param b a boolean TRUE or FALSE (0 or 1)
|
||||
* @returns a json_object of type json_type_boolean
|
||||
*/
|
||||
extern struct json_object* json_object_new_boolean(boolean b);
|
||||
extern struct json_object *json_object_new_boolean(boolean b);
|
||||
|
||||
/** Get the boolean value of a json_object
|
||||
*
|
||||
|
@ -245,7 +240,7 @@ extern boolean json_object_get_boolean(struct json_object *obj);
|
|||
* @param i the integer
|
||||
* @returns a json_object of type json_type_int
|
||||
*/
|
||||
extern struct json_object* json_object_new_int(int i);
|
||||
extern struct json_object *json_object_new_int(int i);
|
||||
|
||||
/** Get the int value of a json_object
|
||||
*
|
||||
|
@ -265,7 +260,7 @@ extern int json_object_get_int(struct json_object *obj);
|
|||
* @param d the double
|
||||
* @returns a json_object of type json_type_double
|
||||
*/
|
||||
extern struct json_object* json_object_new_double(double d);
|
||||
extern struct json_object *json_object_new_double(double d);
|
||||
|
||||
/** Get the double value of a json_object
|
||||
*
|
||||
|
@ -288,9 +283,9 @@ extern double json_object_get_double(struct json_object *obj);
|
|||
* @param s the string
|
||||
* @returns a json_object of type json_type_string
|
||||
*/
|
||||
extern struct json_object* json_object_new_string(char *s);
|
||||
extern struct json_object *json_object_new_string(char *s);
|
||||
|
||||
extern struct json_object* json_object_new_string_len(char *s, int len);
|
||||
extern struct json_object *json_object_new_string_len(char *s, int len);
|
||||
|
||||
/** Get the string value of a json_object
|
||||
*
|
||||
|
@ -303,6 +298,6 @@ extern struct json_object* json_object_new_string_len(char *s, int len);
|
|||
* @param obj the json_object instance
|
||||
* @returns a string
|
||||
*/
|
||||
extern char* json_object_get_string(struct json_object *obj);
|
||||
extern char *json_object_get_string(struct json_object *obj);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,30 +12,27 @@
|
|||
#ifndef _json_object_private_h_
|
||||
#define _json_object_private_h_
|
||||
|
||||
typedef void (json_object_delete_fn)(struct json_object *o);
|
||||
typedef int (json_object_to_json_string_fn)(struct json_object *o,
|
||||
struct printbuf *pb);
|
||||
typedef void (json_object_delete_fn) (struct json_object * o);
|
||||
typedef int (json_object_to_json_string_fn) (struct json_object * o, struct printbuf * pb);
|
||||
|
||||
struct json_object
|
||||
{
|
||||
enum json_type o_type;
|
||||
json_object_delete_fn *_delete;
|
||||
json_object_to_json_string_fn *_to_json_string;
|
||||
int _ref_count;
|
||||
struct printbuf *_pb;
|
||||
union data {
|
||||
boolean c_boolean;
|
||||
double c_double;
|
||||
int c_int;
|
||||
struct lh_table *c_object;
|
||||
struct array_list *c_array;
|
||||
char *c_string;
|
||||
} o;
|
||||
struct json_object {
|
||||
enum json_type o_type;
|
||||
json_object_delete_fn *_delete;
|
||||
json_object_to_json_string_fn *_to_json_string;
|
||||
int _ref_count;
|
||||
struct printbuf *_pb;
|
||||
union data {
|
||||
boolean c_boolean;
|
||||
double c_double;
|
||||
int c_int;
|
||||
struct lh_table *c_object;
|
||||
struct array_list *c_array;
|
||||
char *c_string;
|
||||
} o;
|
||||
};
|
||||
|
||||
/* CAW: added for ANSI C iteration correctness */
|
||||
struct json_object_iter
|
||||
{
|
||||
struct json_object_iter {
|
||||
char *key;
|
||||
struct json_object *val;
|
||||
struct lh_entry *entry;
|
||||
|
|
|
@ -32,94 +32,95 @@
|
|||
#endif /* HAVE_STRNCASECMP */
|
||||
|
||||
|
||||
static const char* json_null_str = "null";
|
||||
static const char* json_true_str = "true";
|
||||
static const char* json_false_str = "false";
|
||||
static const char *json_null_str = "null";
|
||||
static const char *json_true_str = "true";
|
||||
static const char *json_false_str = "false";
|
||||
|
||||
const char* json_tokener_errors[] = {
|
||||
"success",
|
||||
"continue",
|
||||
"nesting to deep",
|
||||
"unexpected end of data",
|
||||
"unexpected character",
|
||||
"null expected",
|
||||
"boolean expected",
|
||||
"number expected",
|
||||
"array value separator ',' expected",
|
||||
"quoted object property name expected",
|
||||
"object property name separator ':' expected",
|
||||
"object value separator ',' expected",
|
||||
"invalid string sequence",
|
||||
"expected comment",
|
||||
const char *json_tokener_errors[] = {
|
||||
"success",
|
||||
"continue",
|
||||
"nesting to deep",
|
||||
"unexpected end of data",
|
||||
"unexpected character",
|
||||
"null expected",
|
||||
"boolean expected",
|
||||
"number expected",
|
||||
"array value separator ',' expected",
|
||||
"quoted object property name expected",
|
||||
"object property name separator ':' expected",
|
||||
"object value separator ',' expected",
|
||||
"invalid string sequence",
|
||||
"expected comment",
|
||||
};
|
||||
|
||||
|
||||
struct json_tokener* json_tokener_new()
|
||||
struct json_tokener *json_tokener_new()
|
||||
{
|
||||
struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
|
||||
tok->pb = printbuf_new();
|
||||
json_tokener_reset(tok);
|
||||
return tok;
|
||||
struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
|
||||
tok->pb = printbuf_new();
|
||||
json_tokener_reset(tok);
|
||||
return tok;
|
||||
}
|
||||
|
||||
void json_tokener_free(struct json_tokener *tok)
|
||||
{
|
||||
json_tokener_reset(tok);
|
||||
if(tok) printbuf_free(tok->pb);
|
||||
free(tok);
|
||||
json_tokener_reset(tok);
|
||||
if (tok)
|
||||
printbuf_free(tok->pb);
|
||||
free(tok);
|
||||
}
|
||||
|
||||
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
|
||||
{
|
||||
tok->stack[depth].state = json_tokener_state_eatws;
|
||||
tok->stack[depth].saved_state = json_tokener_state_start;
|
||||
json_object_put(tok->stack[depth].current);
|
||||
tok->stack[depth].current = NULL;
|
||||
free(tok->stack[depth].obj_field_name);
|
||||
tok->stack[depth].obj_field_name = NULL;
|
||||
tok->stack[depth].state = json_tokener_state_eatws;
|
||||
tok->stack[depth].saved_state = json_tokener_state_start;
|
||||
json_object_put(tok->stack[depth].current);
|
||||
tok->stack[depth].current = NULL;
|
||||
free(tok->stack[depth].obj_field_name);
|
||||
tok->stack[depth].obj_field_name = NULL;
|
||||
}
|
||||
|
||||
void json_tokener_reset(struct json_tokener *tok)
|
||||
{
|
||||
int i;
|
||||
for(i = tok->depth; i >= 0; i--)
|
||||
json_tokener_reset_level(tok, i);
|
||||
tok->depth = 0;
|
||||
tok->err = json_tokener_success;
|
||||
int i;
|
||||
for (i = tok->depth; i >= 0; i--)
|
||||
json_tokener_reset_level(tok, i);
|
||||
tok->depth = 0;
|
||||
tok->err = json_tokener_success;
|
||||
}
|
||||
|
||||
struct json_object* json_tokener_parse(char *str)
|
||||
struct json_object *json_tokener_parse(char *str)
|
||||
{
|
||||
struct json_tokener* tok;
|
||||
struct json_object* obj;
|
||||
struct json_tokener *tok;
|
||||
struct json_object *obj;
|
||||
|
||||
tok = json_tokener_new();
|
||||
obj = json_tokener_parse_ex(tok, str, -1);
|
||||
if(tok->err != json_tokener_success)
|
||||
obj = error_ptr(-tok->err);
|
||||
json_tokener_free(tok);
|
||||
return obj;
|
||||
tok = json_tokener_new();
|
||||
obj = json_tokener_parse_ex(tok, str, -1);
|
||||
if (tok->err != json_tokener_success)
|
||||
obj = error_ptr(-tok->err);
|
||||
json_tokener_free(tok);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
#if !HAVE_STRNDUP
|
||||
/* CAW: compliant version of strndup() */
|
||||
char* strndup(const char* str, size_t n)
|
||||
char *strndup(const char *str, size_t n)
|
||||
{
|
||||
if(str) {
|
||||
size_t len = strlen(str);
|
||||
size_t nn = min(len,n);
|
||||
char* s = (char*)malloc(sizeof(char) * (nn + 1));
|
||||
if (str) {
|
||||
size_t len = strlen(str);
|
||||
size_t nn = min(len, n);
|
||||
char *s = (char *) malloc(sizeof(char) * (nn + 1));
|
||||
|
||||
if(s) {
|
||||
memcpy(s, str, nn);
|
||||
s[nn] = '\0';
|
||||
}
|
||||
if (s) {
|
||||
memcpy(s, str, nn);
|
||||
s[nn] = '\0';
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -129,392 +130,393 @@ char* strndup(const char* str, size_t n)
|
|||
#define current tok->stack[tok->depth].current
|
||||
#define obj_field_name tok->stack[tok->depth].obj_field_name
|
||||
|
||||
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
||||
char *str, int len)
|
||||
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, char *str, int len)
|
||||
{
|
||||
struct json_object *obj = NULL;
|
||||
char c;
|
||||
struct json_object *obj = NULL;
|
||||
char c;
|
||||
|
||||
tok->char_offset = 0;
|
||||
tok->err = json_tokener_success;
|
||||
|
||||
do {
|
||||
if(tok->char_offset == len) {
|
||||
if(tok->depth == 0 && state == json_tokener_state_eatws &&
|
||||
saved_state == json_tokener_state_finish)
|
||||
tok->char_offset = 0;
|
||||
tok->err = json_tokener_success;
|
||||
else
|
||||
tok->err = json_tokener_continue;
|
||||
goto out;
|
||||
}
|
||||
|
||||
c = *str;
|
||||
redo_char:
|
||||
switch(state) {
|
||||
do {
|
||||
if (tok->char_offset == len) {
|
||||
if (tok->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish)
|
||||
tok->err = json_tokener_success;
|
||||
else
|
||||
tok->err = json_tokener_continue;
|
||||
goto out;
|
||||
}
|
||||
|
||||
case json_tokener_state_eatws:
|
||||
if(isspace(c)) {
|
||||
/* okay */
|
||||
} else if(c == '/') {
|
||||
printbuf_reset(tok->pb);
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
state = json_tokener_state_comment_start;
|
||||
} else {
|
||||
state = saved_state;
|
||||
goto redo_char;
|
||||
}
|
||||
break;
|
||||
c = *str;
|
||||
redo_char:
|
||||
switch (state) {
|
||||
|
||||
case json_tokener_state_start:
|
||||
switch(c) {
|
||||
case '{':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_object_field_start;
|
||||
current = json_object_new_object();
|
||||
break;
|
||||
case '[':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_array;
|
||||
current = json_object_new_array();
|
||||
break;
|
||||
case 'N':
|
||||
case 'n':
|
||||
state = json_tokener_state_null;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->st_pos = 0;
|
||||
goto redo_char;
|
||||
case '"':
|
||||
case '\'':
|
||||
state = json_tokener_state_string;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->quote_char = c;
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
case 'F':
|
||||
case 'f':
|
||||
state = json_tokener_state_boolean;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->st_pos = 0;
|
||||
goto redo_char;
|
||||
case json_tokener_state_eatws:
|
||||
if (isspace(c)) {
|
||||
/* okay */
|
||||
} else if (c == '/') {
|
||||
printbuf_reset(tok->pb);
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
state = json_tokener_state_comment_start;
|
||||
} else {
|
||||
state = saved_state;
|
||||
goto redo_char;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_start:
|
||||
switch (c) {
|
||||
case '{':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_object_field_start;
|
||||
current = json_object_new_object();
|
||||
break;
|
||||
case '[':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_array;
|
||||
current = json_object_new_array();
|
||||
break;
|
||||
case 'N':
|
||||
case 'n':
|
||||
state = json_tokener_state_null;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->st_pos = 0;
|
||||
goto redo_char;
|
||||
case '"':
|
||||
case '\'':
|
||||
state = json_tokener_state_string;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->quote_char = c;
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
case 'F':
|
||||
case 'f':
|
||||
state = json_tokener_state_boolean;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->st_pos = 0;
|
||||
goto redo_char;
|
||||
/*
|
||||
#if defined(__GNUC__)
|
||||
case '0' ... '9':
|
||||
#else
|
||||
*/
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
/*
|
||||
#endif
|
||||
*/
|
||||
case '-':
|
||||
state = json_tokener_state_number;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->is_double = 0;
|
||||
goto redo_char;
|
||||
default:
|
||||
tok->err = json_tokener_error_parse_unexpected;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
state = json_tokener_state_number;
|
||||
printbuf_reset(tok->pb);
|
||||
tok->is_double = 0;
|
||||
goto redo_char;
|
||||
default:
|
||||
tok->err = json_tokener_error_parse_unexpected;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_finish:
|
||||
if(tok->depth == 0) goto out;
|
||||
obj = json_object_get(current);
|
||||
json_tokener_reset_level(tok, tok->depth);
|
||||
tok->depth--;
|
||||
goto redo_char;
|
||||
case json_tokener_state_finish:
|
||||
if (tok->depth == 0)
|
||||
goto out;
|
||||
obj = json_object_get(current);
|
||||
json_tokener_reset_level(tok, tok->depth);
|
||||
tok->depth--;
|
||||
goto redo_char;
|
||||
|
||||
case json_tokener_state_null:
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if(strncasecmp(json_null_str, tok->pb->buf,
|
||||
min(tok->st_pos+1, strlen(json_null_str))) == 0) {
|
||||
if(tok->st_pos == strlen(json_null_str)) {
|
||||
current = NULL;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_null;
|
||||
goto out;
|
||||
}
|
||||
tok->st_pos++;
|
||||
break;
|
||||
case json_tokener_state_null:
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if (strncasecmp(json_null_str, tok->pb->buf, min(tok->st_pos + 1, strlen(json_null_str))) == 0) {
|
||||
if (tok->st_pos == strlen(json_null_str)) {
|
||||
current = NULL;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_null;
|
||||
goto out;
|
||||
}
|
||||
tok->st_pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_start:
|
||||
if(c == '*') {
|
||||
state = json_tokener_state_comment;
|
||||
} else if(c == '/') {
|
||||
state = json_tokener_state_comment_eol;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_comment;
|
||||
goto out;
|
||||
}
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
break;
|
||||
case json_tokener_state_comment_start:
|
||||
if (c == '*') {
|
||||
state = json_tokener_state_comment;
|
||||
} else if (c == '/') {
|
||||
state = json_tokener_state_comment_eol;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_comment;
|
||||
goto out;
|
||||
}
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment:
|
||||
if(c == '*') state = json_tokener_state_comment_end;
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
break;
|
||||
case json_tokener_state_comment:
|
||||
if (c == '*')
|
||||
state = json_tokener_state_comment_end;
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_eol:
|
||||
if(c == '\n') {
|
||||
mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_comment_eol:
|
||||
if (c == '\n') {
|
||||
mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_end:
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if(c == '/') {
|
||||
mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
state = json_tokener_state_comment;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_comment_end:
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if (c == '/') {
|
||||
mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
state = json_tokener_state_comment;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_string:
|
||||
if(c == tok->quote_char) {
|
||||
current = json_object_new_string(tok->pb->buf);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == '\\') {
|
||||
saved_state = json_tokener_state_string;
|
||||
state = json_tokener_state_string_escape;
|
||||
} else {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_string:
|
||||
if (c == tok->quote_char) {
|
||||
current = json_object_new_string(tok->pb->buf);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == '\\') {
|
||||
saved_state = json_tokener_state_string;
|
||||
state = json_tokener_state_string_escape;
|
||||
} else {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_string_escape:
|
||||
switch(c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'b':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 't':
|
||||
if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
|
||||
else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
|
||||
else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
|
||||
else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'u':
|
||||
tok->ucs_char = 0;
|
||||
tok->st_pos = 0;
|
||||
state = json_tokener_state_escape_unicode;
|
||||
break;
|
||||
default:
|
||||
tok->err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_string_escape:
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'b':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 't':
|
||||
if (c == 'b')
|
||||
printbuf_memappend(tok->pb, "\b", 1);
|
||||
else if (c == 'n')
|
||||
printbuf_memappend(tok->pb, "\n", 1);
|
||||
else if (c == 'r')
|
||||
printbuf_memappend(tok->pb, "\r", 1);
|
||||
else if (c == 't')
|
||||
printbuf_memappend(tok->pb, "\t", 1);
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'u':
|
||||
tok->ucs_char = 0;
|
||||
tok->st_pos = 0;
|
||||
state = json_tokener_state_escape_unicode;
|
||||
break;
|
||||
default:
|
||||
tok->err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_escape_unicode:
|
||||
if(strchr(json_hex_chars, c)) {
|
||||
tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
|
||||
if(tok->st_pos == 4) {
|
||||
unsigned char utf_out[3];
|
||||
if (tok->ucs_char < 0x80) {
|
||||
utf_out[0] = tok->ucs_char;
|
||||
printbuf_memappend(tok->pb, (char*)utf_out, 1);
|
||||
} else if (tok->ucs_char < 0x800) {
|
||||
utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
|
||||
utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
|
||||
printbuf_memappend(tok->pb, (char*)utf_out, 2);
|
||||
} else {
|
||||
utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
|
||||
utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
|
||||
utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
|
||||
printbuf_memappend(tok->pb, (char*)utf_out, 3);
|
||||
}
|
||||
state = saved_state;
|
||||
}
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_escape_unicode:
|
||||
if (strchr(json_hex_chars, c)) {
|
||||
tok->ucs_char += ((unsigned int) hexdigit(c) << ((3 - tok->st_pos++) * 4));
|
||||
if (tok->st_pos == 4) {
|
||||
unsigned char utf_out[3];
|
||||
if (tok->ucs_char < 0x80) {
|
||||
utf_out[0] = tok->ucs_char;
|
||||
printbuf_memappend(tok->pb, (char *) utf_out, 1);
|
||||
} else if (tok->ucs_char < 0x800) {
|
||||
utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
|
||||
utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
|
||||
printbuf_memappend(tok->pb, (char *) utf_out, 2);
|
||||
} else {
|
||||
utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
|
||||
utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
|
||||
utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
|
||||
printbuf_memappend(tok->pb, (char *) utf_out, 3);
|
||||
}
|
||||
state = saved_state;
|
||||
}
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_boolean:
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if(strncasecmp(json_true_str, tok->pb->buf,
|
||||
min(tok->st_pos+1, strlen(json_true_str))) == 0) {
|
||||
if(tok->st_pos == strlen(json_true_str)) {
|
||||
current = json_object_new_boolean(1);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
} else if(strncasecmp(json_false_str, tok->pb->buf,
|
||||
min(tok->st_pos+1, strlen(json_false_str))) == 0) {
|
||||
if(tok->st_pos == strlen(json_false_str)) {
|
||||
current = json_object_new_boolean(0);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_boolean;
|
||||
goto out;
|
||||
}
|
||||
tok->st_pos++;
|
||||
break;
|
||||
case json_tokener_state_boolean:
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if (strncasecmp(json_true_str, tok->pb->buf, min(tok->st_pos + 1, strlen(json_true_str))) == 0) {
|
||||
if (tok->st_pos == strlen(json_true_str)) {
|
||||
current = json_object_new_boolean(1);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
} else if (strncasecmp(json_false_str, tok->pb->buf, min(tok->st_pos + 1, strlen(json_false_str))) == 0) {
|
||||
if (tok->st_pos == strlen(json_false_str)) {
|
||||
current = json_object_new_boolean(0);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_boolean;
|
||||
goto out;
|
||||
}
|
||||
tok->st_pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_number:
|
||||
if(c && strchr(json_number_chars, c)) {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if(c == '.' || c == 'e') tok->is_double = 1;
|
||||
} else {
|
||||
int numi;
|
||||
double numd;
|
||||
if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
|
||||
current = json_object_new_int(numi);
|
||||
} else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
|
||||
current = json_object_new_double(numd);
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_number;
|
||||
goto out;
|
||||
}
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_number:
|
||||
if (c && strchr(json_number_chars, c)) {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
if (c == '.' || c == 'e')
|
||||
tok->is_double = 1;
|
||||
} else {
|
||||
int numi;
|
||||
double numd;
|
||||
if (!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
|
||||
current = json_object_new_int(numi);
|
||||
} else if (tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
|
||||
current = json_object_new_double(numd);
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_number;
|
||||
goto out;
|
||||
}
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_array:
|
||||
if(c == ']') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
|
||||
tok->err = json_tokener_error_depth;
|
||||
goto out;
|
||||
}
|
||||
state = json_tokener_state_array_add;
|
||||
tok->depth++;
|
||||
json_tokener_reset_level(tok, tok->depth);
|
||||
goto redo_char;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_array:
|
||||
if (c == ']') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
if (tok->depth >= JSON_TOKENER_MAX_DEPTH - 1) {
|
||||
tok->err = json_tokener_error_depth;
|
||||
goto out;
|
||||
}
|
||||
state = json_tokener_state_array_add;
|
||||
tok->depth++;
|
||||
json_tokener_reset_level(tok, tok->depth);
|
||||
goto redo_char;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_array_add:
|
||||
json_object_array_add(current, obj);
|
||||
saved_state = json_tokener_state_array_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
case json_tokener_state_array_add:
|
||||
json_object_array_add(current, obj);
|
||||
saved_state = json_tokener_state_array_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
|
||||
case json_tokener_state_array_sep:
|
||||
if(c == ']') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == ',') {
|
||||
saved_state = json_tokener_state_array;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_array;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_array_sep:
|
||||
if (c == ']') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == ',') {
|
||||
saved_state = json_tokener_state_array;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_array;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field_start:
|
||||
if(c == '}') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == '"' || c == '\'') {
|
||||
tok->quote_char = c;
|
||||
printbuf_reset(tok->pb);
|
||||
state = json_tokener_state_object_field;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_object_key_name;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_object_field_start:
|
||||
if (c == '}') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == '"' || c == '\'') {
|
||||
tok->quote_char = c;
|
||||
printbuf_reset(tok->pb);
|
||||
state = json_tokener_state_object_field;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_object_key_name;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field:
|
||||
if(c == tok->quote_char) {
|
||||
obj_field_name = strdup(tok->pb->buf);
|
||||
saved_state = json_tokener_state_object_field_end;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == '\\') {
|
||||
saved_state = json_tokener_state_object_field;
|
||||
state = json_tokener_state_string_escape;
|
||||
} else {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_object_field:
|
||||
if (c == tok->quote_char) {
|
||||
obj_field_name = strdup(tok->pb->buf);
|
||||
saved_state = json_tokener_state_object_field_end;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == '\\') {
|
||||
saved_state = json_tokener_state_object_field;
|
||||
state = json_tokener_state_string_escape;
|
||||
} else {
|
||||
printbuf_memappend(tok->pb, &c, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field_end:
|
||||
if(c == ':') {
|
||||
saved_state = json_tokener_state_object_value;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_object_key_sep;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_object_field_end:
|
||||
if (c == ':') {
|
||||
saved_state = json_tokener_state_object_value;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_object_key_sep;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_value:
|
||||
if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
|
||||
tok->err = json_tokener_error_depth;
|
||||
goto out;
|
||||
}
|
||||
state = json_tokener_state_object_value_add;
|
||||
tok->depth++;
|
||||
json_tokener_reset_level(tok, tok->depth);
|
||||
goto redo_char;
|
||||
case json_tokener_state_object_value:
|
||||
if (tok->depth >= JSON_TOKENER_MAX_DEPTH - 1) {
|
||||
tok->err = json_tokener_error_depth;
|
||||
goto out;
|
||||
}
|
||||
state = json_tokener_state_object_value_add;
|
||||
tok->depth++;
|
||||
json_tokener_reset_level(tok, tok->depth);
|
||||
goto redo_char;
|
||||
|
||||
case json_tokener_state_object_value_add:
|
||||
json_object_object_add(current, obj_field_name, obj);
|
||||
free(obj_field_name);
|
||||
obj_field_name = NULL;
|
||||
saved_state = json_tokener_state_object_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
case json_tokener_state_object_value_add:
|
||||
json_object_object_add(current, obj_field_name, obj);
|
||||
free(obj_field_name);
|
||||
obj_field_name = NULL;
|
||||
saved_state = json_tokener_state_object_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
goto redo_char;
|
||||
|
||||
case json_tokener_state_object_sep:
|
||||
if(c == '}') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == ',') {
|
||||
saved_state = json_tokener_state_object_field_start;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_object_value_sep;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case json_tokener_state_object_sep:
|
||||
if (c == '}') {
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == ',') {
|
||||
saved_state = json_tokener_state_object_field_start;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
tok->err = json_tokener_error_parse_object_value_sep;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
str++;
|
||||
tok->char_offset++;
|
||||
} while(c);
|
||||
}
|
||||
str++;
|
||||
tok->char_offset++;
|
||||
} while (c);
|
||||
|
||||
if(state != json_tokener_state_finish &&
|
||||
saved_state != json_tokener_state_finish)
|
||||
tok->err = json_tokener_error_parse_eof;
|
||||
if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
|
||||
tok->err = json_tokener_error_parse_eof;
|
||||
|
||||
out:
|
||||
if(tok->err == json_tokener_success) return json_object_get(current);
|
||||
mc_debug("json_tokener_parse_ex: error %s at offset %d\n",
|
||||
json_tokener_errors[tok->err], tok->char_offset);
|
||||
return NULL;
|
||||
out:
|
||||
if (tok->err == json_tokener_success)
|
||||
return json_object_get(current);
|
||||
mc_debug("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err], tok->char_offset);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -15,75 +15,72 @@
|
|||
#include "json_object.h"
|
||||
|
||||
enum json_tokener_error {
|
||||
json_tokener_success,
|
||||
json_tokener_continue,
|
||||
json_tokener_error_depth,
|
||||
json_tokener_error_parse_eof,
|
||||
json_tokener_error_parse_unexpected,
|
||||
json_tokener_error_parse_null,
|
||||
json_tokener_error_parse_boolean,
|
||||
json_tokener_error_parse_number,
|
||||
json_tokener_error_parse_array,
|
||||
json_tokener_error_parse_object_key_name,
|
||||
json_tokener_error_parse_object_key_sep,
|
||||
json_tokener_error_parse_object_value_sep,
|
||||
json_tokener_error_parse_string,
|
||||
json_tokener_error_parse_comment
|
||||
json_tokener_success,
|
||||
json_tokener_continue,
|
||||
json_tokener_error_depth,
|
||||
json_tokener_error_parse_eof,
|
||||
json_tokener_error_parse_unexpected,
|
||||
json_tokener_error_parse_null,
|
||||
json_tokener_error_parse_boolean,
|
||||
json_tokener_error_parse_number,
|
||||
json_tokener_error_parse_array,
|
||||
json_tokener_error_parse_object_key_name,
|
||||
json_tokener_error_parse_object_key_sep,
|
||||
json_tokener_error_parse_object_value_sep,
|
||||
json_tokener_error_parse_string,
|
||||
json_tokener_error_parse_comment
|
||||
};
|
||||
|
||||
enum json_tokener_state {
|
||||
json_tokener_state_eatws,
|
||||
json_tokener_state_start,
|
||||
json_tokener_state_finish,
|
||||
json_tokener_state_null,
|
||||
json_tokener_state_comment_start,
|
||||
json_tokener_state_comment,
|
||||
json_tokener_state_comment_eol,
|
||||
json_tokener_state_comment_end,
|
||||
json_tokener_state_string,
|
||||
json_tokener_state_string_escape,
|
||||
json_tokener_state_escape_unicode,
|
||||
json_tokener_state_boolean,
|
||||
json_tokener_state_number,
|
||||
json_tokener_state_array,
|
||||
json_tokener_state_array_add,
|
||||
json_tokener_state_array_sep,
|
||||
json_tokener_state_object_field_start,
|
||||
json_tokener_state_object_field,
|
||||
json_tokener_state_object_field_end,
|
||||
json_tokener_state_object_value,
|
||||
json_tokener_state_object_value_add,
|
||||
json_tokener_state_object_sep
|
||||
json_tokener_state_eatws,
|
||||
json_tokener_state_start,
|
||||
json_tokener_state_finish,
|
||||
json_tokener_state_null,
|
||||
json_tokener_state_comment_start,
|
||||
json_tokener_state_comment,
|
||||
json_tokener_state_comment_eol,
|
||||
json_tokener_state_comment_end,
|
||||
json_tokener_state_string,
|
||||
json_tokener_state_string_escape,
|
||||
json_tokener_state_escape_unicode,
|
||||
json_tokener_state_boolean,
|
||||
json_tokener_state_number,
|
||||
json_tokener_state_array,
|
||||
json_tokener_state_array_add,
|
||||
json_tokener_state_array_sep,
|
||||
json_tokener_state_object_field_start,
|
||||
json_tokener_state_object_field,
|
||||
json_tokener_state_object_field_end,
|
||||
json_tokener_state_object_value,
|
||||
json_tokener_state_object_value_add,
|
||||
json_tokener_state_object_sep
|
||||
};
|
||||
|
||||
struct json_tokener_srec
|
||||
{
|
||||
enum json_tokener_state state, saved_state;
|
||||
struct json_object *obj;
|
||||
struct json_object *current;
|
||||
char *obj_field_name;
|
||||
struct json_tokener_srec {
|
||||
enum json_tokener_state state, saved_state;
|
||||
struct json_object *obj;
|
||||
struct json_object *current;
|
||||
char *obj_field_name;
|
||||
};
|
||||
|
||||
#define JSON_TOKENER_MAX_DEPTH 32
|
||||
|
||||
struct json_tokener
|
||||
{
|
||||
char *str;
|
||||
struct printbuf *pb;
|
||||
int depth, is_double, st_pos, char_offset;
|
||||
enum json_tokener_error err;
|
||||
unsigned int ucs_char;
|
||||
char quote_char;
|
||||
struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH];
|
||||
struct json_tokener {
|
||||
char *str;
|
||||
struct printbuf *pb;
|
||||
int depth, is_double, st_pos, char_offset;
|
||||
enum json_tokener_error err;
|
||||
unsigned int ucs_char;
|
||||
char quote_char;
|
||||
struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH];
|
||||
};
|
||||
|
||||
extern const char* json_tokener_errors[];
|
||||
extern const char *json_tokener_errors[];
|
||||
|
||||
extern struct json_tokener* json_tokener_new();
|
||||
extern struct json_tokener *json_tokener_new();
|
||||
extern void json_tokener_free(struct json_tokener *tok);
|
||||
extern void json_tokener_reset(struct json_tokener *tok);
|
||||
extern struct json_object* json_tokener_parse(char *str);
|
||||
extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
||||
char *str, int len);
|
||||
extern struct json_object *json_tokener_parse(char *str);
|
||||
extern struct json_object *json_tokener_parse_ex(struct json_tokener *tok, char *str, int len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,71 +51,69 @@
|
|||
#include "json_tokener.h"
|
||||
#include "json_util.h"
|
||||
|
||||
struct json_object* json_object_from_file(char *filename)
|
||||
struct json_object *json_object_from_file(char *filename)
|
||||
{
|
||||
struct printbuf *pb;
|
||||
struct json_object *obj;
|
||||
char buf[JSON_FILE_BUF_SIZE];
|
||||
int fd, ret;
|
||||
struct printbuf *pb;
|
||||
struct json_object *obj;
|
||||
char buf[JSON_FILE_BUF_SIZE];
|
||||
int fd, ret;
|
||||
|
||||
if((fd = open(filename, O_RDONLY)) < 0) {
|
||||
mc_error("json_object_from_file: error reading file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return error_ptr(-1);
|
||||
}
|
||||
if(!(pb = printbuf_new())) {
|
||||
mc_error("json_object_from_file: printbuf_new failed\n");
|
||||
return error_ptr(-1);
|
||||
}
|
||||
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
|
||||
printbuf_memappend(pb, buf, ret);
|
||||
}
|
||||
close(fd);
|
||||
if(ret < 0) {
|
||||
mc_abort("json_object_from_file: error reading file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
printbuf_free(pb);
|
||||
return error_ptr(-1);
|
||||
}
|
||||
obj = json_tokener_parse(pb->buf);
|
||||
printbuf_free(pb);
|
||||
return obj;
|
||||
if ((fd = open(filename, O_RDONLY)) < 0) {
|
||||
mc_error("json_object_from_file: error reading file %s: %s\n", filename, strerror(errno));
|
||||
return error_ptr(-1);
|
||||
}
|
||||
if (!(pb = printbuf_new())) {
|
||||
mc_error("json_object_from_file: printbuf_new failed\n");
|
||||
return error_ptr(-1);
|
||||
}
|
||||
while ((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
|
||||
printbuf_memappend(pb, buf, ret);
|
||||
}
|
||||
close(fd);
|
||||
if (ret < 0) {
|
||||
mc_abort("json_object_from_file: error reading file %s: %s\n", filename, strerror(errno));
|
||||
printbuf_free(pb);
|
||||
return error_ptr(-1);
|
||||
}
|
||||
obj = json_tokener_parse(pb->buf);
|
||||
printbuf_free(pb);
|
||||
return obj;
|
||||
}
|
||||
|
||||
int json_object_to_file(char *filename, struct json_object *obj)
|
||||
{
|
||||
char *json_str;
|
||||
int fd, ret;
|
||||
unsigned int wpos, wsize;
|
||||
char *json_str;
|
||||
int fd, ret;
|
||||
unsigned int wpos, wsize;
|
||||
|
||||
if(!obj) {
|
||||
mc_error("json_object_to_file: object is null\n");
|
||||
return -1;
|
||||
}
|
||||
if (!obj) {
|
||||
mc_error("json_object_to_file: object is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
|
||||
mc_error("json_object_to_file: error opening file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
|
||||
mc_error("json_object_to_file: error opening file %s: %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(json_str = json_object_to_json_string(obj))) { return -1; }
|
||||
if (!(json_str = json_object_to_json_string(obj))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
|
||||
wpos = 0;
|
||||
while(wpos < wsize) {
|
||||
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
|
||||
close(fd);
|
||||
mc_error("json_object_to_file: error writing file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
wsize = (unsigned int) (strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
|
||||
wpos = 0;
|
||||
while (wpos < wsize) {
|
||||
if ((ret = write(fd, json_str + wpos, wsize - wpos)) < 0) {
|
||||
close(fd);
|
||||
mc_error("json_object_to_file: error writing file %s: %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* because of the above check for ret < 0, we can safely cast and add */
|
||||
wpos += (unsigned int)ret;
|
||||
}
|
||||
/* because of the above check for ret < 0, we can safely cast and add */
|
||||
wpos += (unsigned int) ret;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#define JSON_FILE_BUF_SIZE 4096
|
||||
|
||||
/* utlitiy functions */
|
||||
extern struct json_object* json_object_from_file(char *filename);
|
||||
extern struct json_object *json_object_from_file(char *filename);
|
||||
extern int json_object_to_file(char *filename, struct json_object *obj);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,7 @@ void lh_abort(const char *msg, ...)
|
|||
uint32_t lh_ptr_hash(void *k)
|
||||
{
|
||||
/* CAW: refactored to be 64bit nice */
|
||||
return (uint32_t)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
|
||||
return (uint32_t) ((((ptrdiff_t) k * LH_PRIME) >> 4) & ULONG_MAX);
|
||||
}
|
||||
|
||||
int lh_ptr_equal(void *k1, void *k2)
|
||||
|
@ -42,48 +42,47 @@ int lh_ptr_equal(void *k1, void *k2)
|
|||
uint32_t lh_char_hash(void *k)
|
||||
{
|
||||
unsigned int h = 0;
|
||||
const char* data = k;
|
||||
const char *data = k;
|
||||
|
||||
while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
|
||||
while (*data != 0)
|
||||
h = h * 129 + (unsigned int) (*data++) + LH_PRIME;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
int lh_char_equal(void *k1, void *k2)
|
||||
{
|
||||
return (strcmp((char*)k1, (char*)k2) == 0);
|
||||
return (strcmp((char *) k1, (char *) k2) == 0);
|
||||
}
|
||||
|
||||
struct lh_table* lh_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn,
|
||||
lh_hash_fn *hash_fn,
|
||||
lh_equal_fn *equal_fn)
|
||||
struct lh_table *lh_table_new(int size, char *name, lh_entry_free_fn * free_fn, lh_hash_fn * hash_fn, lh_equal_fn * equal_fn)
|
||||
{
|
||||
int i;
|
||||
struct lh_table *t;
|
||||
|
||||
t = calloc(1, sizeof(struct lh_table));
|
||||
if(!t) lh_abort("lh_table_new: calloc failed\n");
|
||||
if (!t)
|
||||
lh_abort("lh_table_new: calloc failed\n");
|
||||
t->count = 0;
|
||||
t->size = size;
|
||||
t->name = name;
|
||||
t->table = calloc(size, sizeof(struct lh_entry));
|
||||
if(!t->table) lh_abort("lh_table_new: calloc failed\n");
|
||||
if (!t->table)
|
||||
lh_abort("lh_table_new: calloc failed\n");
|
||||
t->free_fn = free_fn;
|
||||
t->hash_fn = hash_fn;
|
||||
t->equal_fn = equal_fn;
|
||||
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
|
||||
for (i = 0; i < size; i++)
|
||||
t->table[i].k = LH_EMPTY;
|
||||
return t;
|
||||
}
|
||||
|
||||
struct lh_table* lh_kchar_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn)
|
||||
struct lh_table *lh_kchar_table_new(int size, char *name, lh_entry_free_fn * free_fn)
|
||||
{
|
||||
return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
|
||||
}
|
||||
|
||||
struct lh_table* lh_kptr_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn)
|
||||
struct lh_table *lh_kptr_table_new(int size, char *name, lh_entry_free_fn * free_fn)
|
||||
{
|
||||
return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
|
||||
}
|
||||
|
@ -95,7 +94,7 @@ void lh_table_resize(struct lh_table *t, int new_size)
|
|||
|
||||
new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
|
||||
ent = t->head;
|
||||
while(ent) {
|
||||
while (ent) {
|
||||
lh_table_insert(new_t, ent->k, ent->v);
|
||||
ent = ent->next;
|
||||
}
|
||||
|
@ -111,8 +110,8 @@ void lh_table_resize(struct lh_table *t, int new_size)
|
|||
void lh_table_free(struct lh_table *t)
|
||||
{
|
||||
struct lh_entry *c;
|
||||
for(c = t->head; c != NULL; c = c->next) {
|
||||
if(t->free_fn) {
|
||||
for (c = t->head; c != NULL; c = c->next) {
|
||||
if (t->free_fn) {
|
||||
t->free_fn(c);
|
||||
}
|
||||
}
|
||||
|
@ -126,22 +125,25 @@ int lh_table_insert(struct lh_table *t, void *k, void *v)
|
|||
uint32_t h, n;
|
||||
|
||||
t->inserts++;
|
||||
if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2);
|
||||
if (t->count > t->size * 0.66)
|
||||
lh_table_resize(t, t->size * 2);
|
||||
|
||||
h = t->hash_fn(k);
|
||||
n = h % t->size;
|
||||
|
||||
while( 1 ) {
|
||||
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
|
||||
while (1) {
|
||||
if (t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED)
|
||||
break;
|
||||
t->collisions++;
|
||||
if(++n == t->size) n = 0;
|
||||
if (++n == t->size)
|
||||
n = 0;
|
||||
}
|
||||
|
||||
t->table[n].k = k;
|
||||
t->table[n].v = v;
|
||||
t->count++;
|
||||
|
||||
if(t->head == NULL) {
|
||||
if (t->head == NULL) {
|
||||
t->head = t->tail = &t->table[n];
|
||||
t->table[n].next = t->table[n].prev = NULL;
|
||||
} else {
|
||||
|
@ -155,43 +157,50 @@ int lh_table_insert(struct lh_table *t, void *k, void *v)
|
|||
}
|
||||
|
||||
|
||||
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k)
|
||||
struct lh_entry *lh_table_lookup_entry(struct lh_table *t, void *k)
|
||||
{
|
||||
uint32_t h = t->hash_fn(k);
|
||||
uint32_t n = h % t->size;
|
||||
|
||||
t->lookups++;
|
||||
while( 1 ) {
|
||||
if(t->table[n].k == LH_EMPTY) return NULL;
|
||||
if(t->table[n].k != LH_FREED &&
|
||||
t->equal_fn(t->table[n].k, k)) return &t->table[n];
|
||||
if(++n == t->size) n = 0;
|
||||
while (1) {
|
||||
if (t->table[n].k == LH_EMPTY)
|
||||
return NULL;
|
||||
if (t->table[n].k != LH_FREED && t->equal_fn(t->table[n].k, k))
|
||||
return &t->table[n];
|
||||
if (++n == t->size)
|
||||
n = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* lh_table_lookup(struct lh_table *t, void *k)
|
||||
void *lh_table_lookup(struct lh_table *t, void *k)
|
||||
{
|
||||
struct lh_entry *e = lh_table_lookup_entry(t, k);
|
||||
if(e) return e->v;
|
||||
if (e)
|
||||
return e->v;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
|
||||
{
|
||||
ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
|
||||
ptrdiff_t n = (ptrdiff_t) (e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
|
||||
|
||||
/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
|
||||
if(n < 0) { return -2; }
|
||||
if (n < 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
|
||||
if (t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED)
|
||||
return -1;
|
||||
t->count--;
|
||||
if(t->free_fn) t->free_fn(e);
|
||||
if (t->free_fn)
|
||||
t->free_fn(e);
|
||||
t->table[n].v = NULL;
|
||||
t->table[n].k = LH_FREED;
|
||||
if(t->tail == &t->table[n] && t->head == &t->table[n]) {
|
||||
if (t->tail == &t->table[n] && t->head == &t->table[n]) {
|
||||
t->head = t->tail = NULL;
|
||||
} else if (t->head == &t->table[n]) {
|
||||
t->head->next->prev = NULL;
|
||||
|
@ -211,7 +220,7 @@ int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
|
|||
int lh_table_delete(struct lh_table *t, void *k)
|
||||
{
|
||||
struct lh_entry *e = lh_table_lookup_entry(t, k);
|
||||
if(!e) return -1;
|
||||
if (!e)
|
||||
return -1;
|
||||
return lh_table_delete_entry(t, e);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,11 @@ struct lh_entry;
|
|||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef void (lh_entry_free_fn) (struct lh_entry *e);
|
||||
typedef void (lh_entry_free_fn) (struct lh_entry * e);
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef uint32_t (lh_hash_fn) (void *k);
|
||||
typedef uint32_t(lh_hash_fn) (void *k);
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
|
@ -171,10 +171,7 @@ for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
|
|||
* and C strings respectively.
|
||||
* @return a pointer onto the linkhash table.
|
||||
*/
|
||||
extern struct lh_table* lh_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn,
|
||||
lh_hash_fn *hash_fn,
|
||||
lh_equal_fn *equal_fn);
|
||||
extern struct lh_table *lh_table_new(int size, char *name, lh_entry_free_fn * free_fn, lh_hash_fn * hash_fn, lh_equal_fn * equal_fn);
|
||||
|
||||
/**
|
||||
* Convenience function to create a new linkhash
|
||||
|
@ -184,8 +181,7 @@ extern struct lh_table* lh_table_new(int size, char *name,
|
|||
* @param free_fn callback function used to free memory for entries.
|
||||
* @return a pointer onto the linkhash table.
|
||||
*/
|
||||
extern struct lh_table* lh_kchar_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn);
|
||||
extern struct lh_table *lh_kchar_table_new(int size, char *name, lh_entry_free_fn * free_fn);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -196,8 +192,7 @@ extern struct lh_table* lh_kchar_table_new(int size, char *name,
|
|||
* @param free_fn callback function used to free memory for entries.
|
||||
* @return a pointer onto the linkhash table.
|
||||
*/
|
||||
extern struct lh_table* lh_kptr_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn);
|
||||
extern struct lh_table *lh_kptr_table_new(int size, char *name, lh_entry_free_fn * free_fn);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -224,7 +219,7 @@ extern int lh_table_insert(struct lh_table *t, void *k, void *v);
|
|||
* @param k a pointer to the key to lookup
|
||||
* @return a pointer to the record structure of the value or NULL if it does not exist.
|
||||
*/
|
||||
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k);
|
||||
extern struct lh_entry *lh_table_lookup_entry(struct lh_table *t, void *k);
|
||||
|
||||
/**
|
||||
* Lookup a record into the table
|
||||
|
@ -232,7 +227,7 @@ extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k);
|
|||
* @param k a pointer to the key to lookup
|
||||
* @return a pointer to the found value or NULL if it does not exist.
|
||||
*/
|
||||
extern void* lh_table_lookup(struct lh_table *t, void *k);
|
||||
extern void *lh_table_lookup(struct lh_table *t, void *k);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,287 +90,279 @@ GARBAGE_TYPES_INIT();
|
|||
|
||||
SWITCH_STANDARD_API(http_api_main)
|
||||
{
|
||||
char *ccmd;
|
||||
int argc;
|
||||
char *argv[HTTP_PARAMS];
|
||||
char *buf;
|
||||
char *method;
|
||||
char *url;
|
||||
char *headers_dec;
|
||||
char *headers_str;
|
||||
char *value;
|
||||
char *body;
|
||||
char *body_dec;
|
||||
char *t;
|
||||
char *json_response;
|
||||
struct json_object *json_http_headers;
|
||||
char *key;
|
||||
struct json_object *val;
|
||||
enum json_type jsontype;
|
||||
struct lh_entry *entry;
|
||||
int i;
|
||||
int j;
|
||||
int f;
|
||||
size_t l;
|
||||
size_t m;
|
||||
size_t a = 0;
|
||||
int ret;
|
||||
char *ccmd;
|
||||
int argc;
|
||||
char *argv[HTTP_PARAMS];
|
||||
char *buf;
|
||||
char *method;
|
||||
char *url;
|
||||
char *headers_dec;
|
||||
char *headers_str;
|
||||
char *value;
|
||||
char *body;
|
||||
char *body_dec;
|
||||
char *t;
|
||||
char *json_response;
|
||||
struct json_object *json_http_headers;
|
||||
char *key;
|
||||
struct json_object *val;
|
||||
enum json_type jsontype;
|
||||
struct lh_entry *entry;
|
||||
int i;
|
||||
int j;
|
||||
int f;
|
||||
size_t l;
|
||||
size_t m;
|
||||
size_t a = 0;
|
||||
int ret;
|
||||
|
||||
http_header_t *headers;
|
||||
http_request_t request;
|
||||
http_response_t response;
|
||||
http_header_t *headers;
|
||||
http_request_t request;
|
||||
http_response_t response;
|
||||
|
||||
GARBAGE_INIT();
|
||||
GARBAGE_INIT();
|
||||
|
||||
(void)memset(&response, 0, sizeof(response));
|
||||
(void) memset(&response, 0, sizeof(response));
|
||||
|
||||
if(cmd == NULL){
|
||||
stream->write_function(stream, "-USAGE: %s\n", HTTP_SYNTAX);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ccmd = strdup(cmd);
|
||||
argc = switch_separate_string(ccmd, ' ', argv, HTTP_PARAMS);
|
||||
|
||||
if(argc != HTTP_PARAMS && argc != (HTTP_PARAMS - 1)){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
method = argv[0];
|
||||
if(strcasecmp( "GET", method) == 0) request.method = GET;
|
||||
else if(strcasecmp("POST", method) == 0) request.method = POST;
|
||||
else if(strcasecmp("HEAD", method) == 0) request.method = HEAD;
|
||||
else if(strcasecmp("DELETE", method) == 0) request.method = DELETE;
|
||||
else if(strcasecmp("PUT", method) == 0) request.method = PUT;
|
||||
|
||||
|
||||
|
||||
url = argv[1];
|
||||
headers_str = argv[2];
|
||||
if(argc == HTTP_PARAMS){
|
||||
body = argv[3];
|
||||
}else{
|
||||
body = (char *)malloc(1 * sizeof(char));
|
||||
if(body == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
body[0] = '\0';
|
||||
GARBAGE_ADD(body);
|
||||
}
|
||||
|
||||
buf = (char *)malloc(HTTP_BUFFER_SIZE * sizeof(char));
|
||||
if(buf == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
GARBAGE_ADD(buf);
|
||||
|
||||
request.version = DEFAULT_HTTP_VERSION;
|
||||
l = strlen(url);
|
||||
request.url = (char *)malloc((l + 1) * sizeof(char));
|
||||
if(request.url == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
GARBAGE_ADD(request.url);
|
||||
strcpy(request.url, url);
|
||||
|
||||
|
||||
l = strlen(headers_str);
|
||||
|
||||
headers_dec = url_decode(headers_str, l);
|
||||
GARBAGE_ADD(headers_dec);
|
||||
|
||||
json_http_headers = json_tokener_parse(headers_dec);
|
||||
if(is_error(json_http_headers)){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
jsontype = json_object_get_type(json_http_headers);
|
||||
if(jsontype != json_type_object){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
json_object_object_foreach(json_http_headers, key, val){
|
||||
i++;
|
||||
}
|
||||
|
||||
request.header_len = i;
|
||||
headers = (http_header_t *)malloc(i * sizeof(http_header_t));
|
||||
request.headers = headers;
|
||||
GARBAGE_ADD(headers);
|
||||
|
||||
i = 0;
|
||||
json_object_object_foreach(json_http_headers, key, val){
|
||||
l = strlen(key);
|
||||
|
||||
request.headers[i].field_name = (char *)malloc((l + 1) * sizeof(char));
|
||||
if(request.headers[i].field_name == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
GARBAGE_ADD(request.headers[i].field_name);
|
||||
|
||||
strcpy(request.headers[i].field_name, key);
|
||||
a += strlen(key);
|
||||
|
||||
jsontype = json_object_get_type(val);
|
||||
if(jsontype != json_type_string){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
if (cmd == NULL) {
|
||||
stream->write_function(stream, "-USAGE: %s\n", HTTP_SYNTAX);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
value = json_object_get_string(val);
|
||||
/* value = json_object_to_json_string(val); */
|
||||
l = strlen(value);
|
||||
request.headers[i].value = (char *)malloc((l + 1) * sizeof(char));
|
||||
if(request.headers[i].value == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
GARBAGE_ADD(request.headers[i].value);
|
||||
strcpy(request.headers[i].value, value);
|
||||
a += strlen(value);
|
||||
i++;
|
||||
}
|
||||
ccmd = strdup(cmd);
|
||||
argc = switch_separate_string(ccmd, ' ', argv, HTTP_PARAMS);
|
||||
|
||||
if(argc == HTTP_PARAMS){
|
||||
l = strlen(body);
|
||||
body_dec = url_decode(body, l);
|
||||
GARBAGE_ADD(body_dec);
|
||||
l = strlen(body_dec);
|
||||
request.body_len = l;
|
||||
request.body = body_dec;
|
||||
}else request.body_len = 0;
|
||||
if (argc != HTTP_PARAMS && argc != (HTTP_PARAMS - 1)) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ret = http_req(&request, &response);
|
||||
|
||||
if(response.version != NULL) GARBAGE_ADD(response.version);
|
||||
if(response.phrase != NULL) GARBAGE_ADD(response.phrase);
|
||||
if(response.headers != NULL) GARBAGE_ADD(response.headers);
|
||||
if(response.body != NULL) GARBAGE_ADD(response.body);
|
||||
for(i = 0; i < response.header_len; i++){
|
||||
GARBAGE_ADD(response.headers[i].field_name);
|
||||
GARBAGE_ADD(response.headers[i].value);
|
||||
}
|
||||
method = argv[0];
|
||||
if (strcasecmp("GET", method) == 0)
|
||||
request.method = GET;
|
||||
else if (strcasecmp("POST", method) == 0)
|
||||
request.method = POST;
|
||||
else if (strcasecmp("HEAD", method) == 0)
|
||||
request.method = HEAD;
|
||||
else if (strcasecmp("DELETE", method) == 0)
|
||||
request.method = DELETE;
|
||||
else if (strcasecmp("PUT", method) == 0)
|
||||
request.method = PUT;
|
||||
|
||||
|
||||
if(ret == ERROR){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* This is evil and should be changed in the future */
|
||||
l = 128 + (256 * response.header_len) + (a * 2)
|
||||
+ strlen("version") + strlen(response.version)
|
||||
+ strlen("status_code") + 3
|
||||
+ strlen("phrase") + strlen(response.phrase)
|
||||
+ strlen("body") + (response.body_len * 3) + 1
|
||||
+ strlen("headers")
|
||||
+ 1;
|
||||
url = argv[1];
|
||||
headers_str = argv[2];
|
||||
if (argc == HTTP_PARAMS) {
|
||||
body = argv[3];
|
||||
} else {
|
||||
body = (char *) malloc(1 * sizeof(char));
|
||||
if (body == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
body[0] = '\0';
|
||||
GARBAGE_ADD(body);
|
||||
}
|
||||
|
||||
/* to be safe */
|
||||
l <<= 2;
|
||||
buf = (char *) malloc(HTTP_BUFFER_SIZE * sizeof(char));
|
||||
if (buf == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
json_response = (char *)malloc(l * sizeof(char));
|
||||
if(json_response == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
GARBAGE_ADD(json_response);
|
||||
GARBAGE_ADD(buf);
|
||||
|
||||
if(response.body_len != 0){
|
||||
t = (char *)malloc((response.body_len + 1) * sizeof(char));
|
||||
if(t == NULL){
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
GARBAGE_ADD(t);
|
||||
(void)memcpy(t, response.body, response.body_len);
|
||||
t[response.body_len] = '\0';
|
||||
response.body = url_encode(t, response.body_len);
|
||||
GARBAGE_ADD(response.body);
|
||||
}
|
||||
request.version = DEFAULT_HTTP_VERSION;
|
||||
l = strlen(url);
|
||||
request.url = (char *) malloc((l + 1) * sizeof(char));
|
||||
if (request.url == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
GARBAGE_ADD(request.url);
|
||||
strcpy(request.url, url);
|
||||
|
||||
|
||||
m = snprintf(json_response, l,
|
||||
"{"
|
||||
"\"version\": \"%s\","
|
||||
"\"status_code\": \"%3d\","
|
||||
"\"phrase\": \"%s\","
|
||||
"\"body\": \"%s\","
|
||||
"\"headers\": [",
|
||||
response.version,
|
||||
response.status_code,
|
||||
response.phrase,
|
||||
((response.body_len <= 0)? "":response.body)
|
||||
);
|
||||
l = strlen(headers_str);
|
||||
|
||||
headers_dec = url_decode(headers_str, l);
|
||||
GARBAGE_ADD(headers_dec);
|
||||
|
||||
json_http_headers = json_tokener_parse(headers_dec);
|
||||
if (is_error(json_http_headers)) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
jsontype = json_object_get_type(json_http_headers);
|
||||
if (jsontype != json_type_object) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
json_object_object_foreach(json_http_headers, key, val) {
|
||||
i++;
|
||||
}
|
||||
|
||||
request.header_len = i;
|
||||
headers = (http_header_t *) malloc(i * sizeof(http_header_t));
|
||||
request.headers = headers;
|
||||
GARBAGE_ADD(headers);
|
||||
|
||||
i = 0;
|
||||
json_object_object_foreach(json_http_headers, key, val) {
|
||||
l = strlen(key);
|
||||
|
||||
request.headers[i].field_name = (char *) malloc((l + 1) * sizeof(char));
|
||||
if (request.headers[i].field_name == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
GARBAGE_ADD(request.headers[i].field_name);
|
||||
|
||||
strcpy(request.headers[i].field_name, key);
|
||||
a += strlen(key);
|
||||
|
||||
jsontype = json_object_get_type(val);
|
||||
if (jsontype != json_type_string) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
value = json_object_get_string(val);
|
||||
/* value = json_object_to_json_string(val); */
|
||||
l = strlen(value);
|
||||
request.headers[i].value = (char *) malloc((l + 1) * sizeof(char));
|
||||
if (request.headers[i].value == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
GARBAGE_ADD(request.headers[i].value);
|
||||
strcpy(request.headers[i].value, value);
|
||||
a += strlen(value);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (argc == HTTP_PARAMS) {
|
||||
l = strlen(body);
|
||||
body_dec = url_decode(body, l);
|
||||
GARBAGE_ADD(body_dec);
|
||||
l = strlen(body_dec);
|
||||
request.body_len = l;
|
||||
request.body = body_dec;
|
||||
} else
|
||||
request.body_len = 0;
|
||||
|
||||
ret = http_req(&request, &response);
|
||||
|
||||
if (response.version != NULL)
|
||||
GARBAGE_ADD(response.version);
|
||||
if (response.phrase != NULL)
|
||||
GARBAGE_ADD(response.phrase);
|
||||
if (response.headers != NULL)
|
||||
GARBAGE_ADD(response.headers);
|
||||
if (response.body != NULL)
|
||||
GARBAGE_ADD(response.body);
|
||||
for (i = 0; i < response.header_len; i++) {
|
||||
GARBAGE_ADD(response.headers[i].field_name);
|
||||
GARBAGE_ADD(response.headers[i].value);
|
||||
}
|
||||
|
||||
|
||||
for(f = HTTP_FALSE, j = 0; j < response.header_len; j++){
|
||||
if(f != HTTP_FALSE){
|
||||
m += snprintf(json_response + m, l - m,
|
||||
","
|
||||
);
|
||||
}else f = HTTP_TRUE;
|
||||
if (ret == ERROR) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
m += snprintf(json_response + m, l - m,
|
||||
"{\"key\": \"%s\",\"value\": \"%s\"}",
|
||||
response.headers[j].field_name,
|
||||
response.headers[j].value
|
||||
);
|
||||
}
|
||||
/* This is evil and should be changed in the future */
|
||||
l = 128 + (256 * response.header_len) + (a * 2)
|
||||
+ strlen("version") + strlen(response.version)
|
||||
+ strlen("status_code") + 3 + strlen("phrase") + strlen(response.phrase)
|
||||
+ strlen("body") + (response.body_len * 3) + 1 + strlen("headers")
|
||||
+ 1;
|
||||
|
||||
/* to be safe */
|
||||
l <<= 2;
|
||||
|
||||
json_response = (char *) malloc(l * sizeof(char));
|
||||
if (json_response == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
GARBAGE_ADD(json_response);
|
||||
|
||||
if (response.body_len != 0) {
|
||||
t = (char *) malloc((response.body_len + 1) * sizeof(char));
|
||||
if (t == NULL) {
|
||||
switch_safe_free(ccmd);
|
||||
stream->write_function(stream, "-ERR\n");
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
GARBAGE_ADD(t);
|
||||
(void) memcpy(t, response.body, response.body_len);
|
||||
t[response.body_len] = '\0';
|
||||
response.body = url_encode(t, response.body_len);
|
||||
GARBAGE_ADD(response.body);
|
||||
}
|
||||
|
||||
|
||||
m += snprintf(json_response + m, l - m, "]}");
|
||||
json_response[m] = '\0';
|
||||
m = snprintf(json_response, l,
|
||||
"{"
|
||||
"\"version\": \"%s\","
|
||||
"\"status_code\": \"%3d\","
|
||||
"\"phrase\": \"%s\","
|
||||
"\"body\": \"%s\","
|
||||
"\"headers\": [", response.version, response.status_code, response.phrase, ((response.body_len <= 0) ? "" : response.body)
|
||||
);
|
||||
|
||||
|
||||
switch_log_printf(
|
||||
SWITCH_CHANNEL_LOG,
|
||||
SWITCH_LOG_NOTICE,
|
||||
"RESERVED %ld BYTES, USED %ld BYTES, HTTP Response as JSON: %s\n",
|
||||
l,
|
||||
m,
|
||||
json_response
|
||||
);
|
||||
for (f = HTTP_FALSE, j = 0; j < response.header_len; j++) {
|
||||
if (f != HTTP_FALSE) {
|
||||
m += snprintf(json_response + m, l - m, ",");
|
||||
} else
|
||||
f = HTTP_TRUE;
|
||||
|
||||
m += snprintf(json_response + m, l - m, "{\"key\": \"%s\",\"value\": \"%s\"}", response.headers[j].field_name, response.headers[j].value);
|
||||
}
|
||||
|
||||
|
||||
stream->write_function(stream, "%s\n", json_response);
|
||||
m += snprintf(json_response + m, l - m, "]}");
|
||||
json_response[m] = '\0';
|
||||
|
||||
switch_safe_free(ccmd);
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "RESERVED %ld BYTES, USED %ld BYTES, HTTP Response as JSON: %s\n", l, m, json_response);
|
||||
|
||||
|
||||
stream->write_function(stream, "%s\n", json_response);
|
||||
|
||||
switch_safe_free(ccmd);
|
||||
GARBAGE_CLEANUP();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_http_load);
|
||||
|
@ -378,25 +370,13 @@ SWITCH_MODULE_DEFINITION(mod_http, mod_http_load, NULL, NULL);
|
|||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_http_load)
|
||||
{
|
||||
switch_api_interface_t *api_interface;
|
||||
switch_api_interface_t *api_interface;
|
||||
|
||||
*module_interface =
|
||||
switch_loadable_module_create_module_interface(pool, modname);
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
switch_log_printf(
|
||||
SWITCH_CHANNEL_LOG,
|
||||
SWITCH_LOG_NOTICE,
|
||||
"HTTP request mod enabled\n"
|
||||
);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "HTTP request mod enabled\n");
|
||||
|
||||
SWITCH_ADD_API(
|
||||
api_interface,
|
||||
"http",
|
||||
"Make HTTP requests",
|
||||
http_api_main,
|
||||
HTTP_SYNTAX
|
||||
);
|
||||
SWITCH_ADD_API(api_interface, "http", "Make HTTP requests", http_api_main, HTTP_SYNTAX);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,44 +25,44 @@
|
|||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
|
||||
struct printbuf* printbuf_new()
|
||||
struct printbuf *printbuf_new()
|
||||
{
|
||||
struct printbuf *p;
|
||||
struct printbuf *p;
|
||||
|
||||
if(!(p = calloc(1, sizeof(struct printbuf)))) return NULL;
|
||||
p->size = 32;
|
||||
p->bpos = 0;
|
||||
if(!(p->buf = malloc(p->size))) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
if (!(p = calloc(1, sizeof(struct printbuf))))
|
||||
return NULL;
|
||||
p->size = 32;
|
||||
p->bpos = 0;
|
||||
if (!(p->buf = malloc(p->size))) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int printbuf_memappend(struct printbuf *p, char *buf, int size)
|
||||
{
|
||||
char *t;
|
||||
if(p->size - p->bpos <= size) {
|
||||
int new_size = max(p->size * 2, p->bpos + size + 8);
|
||||
char *t;
|
||||
if (p->size - p->bpos <= size) {
|
||||
int new_size = max(p->size * 2, p->bpos + size + 8);
|
||||
#ifdef PRINTBUF_DEBUG
|
||||
mc_debug("printbuf_memappend: realloc "
|
||||
"bpos=%d wrsize=%d old_size=%d new_size=%d\n",
|
||||
p->bpos, size, p->size, new_size);
|
||||
mc_debug("printbuf_memappend: realloc " "bpos=%d wrsize=%d old_size=%d new_size=%d\n", p->bpos, size, p->size, new_size);
|
||||
#endif /* PRINTBUF_DEBUG */
|
||||
if(!(t = realloc(p->buf, new_size))) return -1;
|
||||
p->size = new_size;
|
||||
p->buf = t;
|
||||
}
|
||||
memcpy(p->buf + p->bpos, buf, size);
|
||||
p->bpos += size;
|
||||
p->buf[p->bpos]= '\0';
|
||||
return size;
|
||||
if (!(t = realloc(p->buf, new_size)))
|
||||
return -1;
|
||||
p->size = new_size;
|
||||
p->buf = t;
|
||||
}
|
||||
memcpy(p->buf + p->bpos, buf, size);
|
||||
p->bpos += size;
|
||||
p->buf[p->bpos] = '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
#if !HAVE_VSNPRINTF && defined(WIN32)
|
||||
# define vsnprintf _vsnprintf
|
||||
#elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */
|
||||
#elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */
|
||||
# error Need vsnprintf!
|
||||
#endif /* !HAVE_VSNPRINTF && defined(WIN32) */
|
||||
|
||||
|
@ -76,22 +76,26 @@ static int vasprintf(char **buf, const char *fmt, va_list ap)
|
|||
int chars;
|
||||
char *b;
|
||||
|
||||
if(!buf) { return -1; }
|
||||
|
||||
if (!buf) {
|
||||
return -1;
|
||||
}
|
||||
#ifdef WIN32
|
||||
chars = _vscprintf(fmt, ap)+1;
|
||||
chars = _vscprintf(fmt, ap) + 1;
|
||||
#else /* !defined(WIN32) */
|
||||
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
|
||||
our buffer like on some 64bit sun systems.... but hey, its time to move on */
|
||||
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
|
||||
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
|
||||
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap) + 1;
|
||||
if (chars < 0) {
|
||||
chars *= -1;
|
||||
} /* CAW: old glibc versions have this problem */
|
||||
#endif /* defined(WIN32) */
|
||||
|
||||
b = (char*)malloc(sizeof(char)*chars);
|
||||
if(!b) { return -1; }
|
||||
b = (char *) malloc(sizeof(char) * chars);
|
||||
if (!b) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((chars = vsprintf(b, fmt, ap)) < 0)
|
||||
{
|
||||
if ((chars = vsprintf(b, fmt, ap)) < 0) {
|
||||
free(b);
|
||||
} else {
|
||||
*buf = b;
|
||||
|
@ -103,42 +107,43 @@ static int vasprintf(char **buf, const char *fmt, va_list ap)
|
|||
|
||||
int sprintbuf(struct printbuf *p, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *t;
|
||||
int size;
|
||||
char buf[128];
|
||||
va_list ap;
|
||||
char *t;
|
||||
int size;
|
||||
char buf[128];
|
||||
|
||||
/* user stack buffer first */
|
||||
va_start(ap, msg);
|
||||
size = vsnprintf(buf, 128, msg, ap);
|
||||
va_end(ap);
|
||||
/* if string is greater than stack buffer, then use dynamic string
|
||||
with vasprintf. Note: some implementation of vsnprintf return -1
|
||||
if output is truncated whereas some return the number of bytes that
|
||||
would have been writen - this code handles both cases. */
|
||||
if(size == -1 || size > 127) {
|
||||
int ret;
|
||||
va_start(ap, msg);
|
||||
if((size = vasprintf(&t, msg, ap)) == -1) return -1;
|
||||
va_end(ap);
|
||||
ret = printbuf_memappend(p, t, size);
|
||||
free(t);
|
||||
return ret;
|
||||
} else {
|
||||
return printbuf_memappend(p, buf, size);
|
||||
}
|
||||
/* user stack buffer first */
|
||||
va_start(ap, msg);
|
||||
size = vsnprintf(buf, 128, msg, ap);
|
||||
va_end(ap);
|
||||
/* if string is greater than stack buffer, then use dynamic string
|
||||
with vasprintf. Note: some implementation of vsnprintf return -1
|
||||
if output is truncated whereas some return the number of bytes that
|
||||
would have been writen - this code handles both cases. */
|
||||
if (size == -1 || size > 127) {
|
||||
int ret;
|
||||
va_start(ap, msg);
|
||||
if ((size = vasprintf(&t, msg, ap)) == -1)
|
||||
return -1;
|
||||
va_end(ap);
|
||||
ret = printbuf_memappend(p, t, size);
|
||||
free(t);
|
||||
return ret;
|
||||
} else {
|
||||
return printbuf_memappend(p, buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
void printbuf_reset(struct printbuf *p)
|
||||
{
|
||||
p->buf[0] = '\0';
|
||||
p->bpos = 0;
|
||||
p->buf[0] = '\0';
|
||||
p->bpos = 0;
|
||||
}
|
||||
|
||||
void printbuf_free(struct printbuf *p)
|
||||
{
|
||||
if(p) {
|
||||
free(p->buf);
|
||||
free(p);
|
||||
}
|
||||
if (p) {
|
||||
free(p->buf);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,24 +15,19 @@
|
|||
#undef PRINTBUF_DEBUG
|
||||
|
||||
struct printbuf {
|
||||
char *buf;
|
||||
int bpos;
|
||||
int size;
|
||||
char *buf;
|
||||
int bpos;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern struct printbuf*
|
||||
printbuf_new();
|
||||
extern struct printbuf *printbuf_new();
|
||||
|
||||
extern int
|
||||
printbuf_memappend(struct printbuf *p, char *buf, int size);
|
||||
extern int printbuf_memappend(struct printbuf *p, char *buf, int size);
|
||||
|
||||
extern int
|
||||
sprintbuf(struct printbuf *p, const char *msg, ...);
|
||||
extern int sprintbuf(struct printbuf *p, const char *msg, ...);
|
||||
|
||||
extern void
|
||||
printbuf_reset(struct printbuf *p);
|
||||
extern void printbuf_reset(struct printbuf *p);
|
||||
|
||||
extern void
|
||||
printbuf_free(struct printbuf *p);
|
||||
extern void printbuf_free(struct printbuf *p);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,96 +30,97 @@
|
|||
#ifdef DEBUG
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *buf1;
|
||||
char *buf2;
|
||||
char *buf1;
|
||||
char *buf2;
|
||||
|
||||
|
||||
buf1 = url_encode("This is a test #$ ");
|
||||
buf2 = url_decode(buf1);
|
||||
buf1 = url_encode("This is a test #$ ");
|
||||
buf2 = url_decode(buf1);
|
||||
|
||||
printf("%s\n", buf2);
|
||||
printf("%s\n", buf2);
|
||||
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return EXIT_FAILURE;
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *url_encode(char *url, size_t l)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char *buf;
|
||||
unsigned char c;
|
||||
int i;
|
||||
int j;
|
||||
char *buf;
|
||||
unsigned char c;
|
||||
|
||||
buf = (char *)malloc((l * 3) + 1);
|
||||
if(buf == NULL){
|
||||
perror("Could not allocate memory url encoding");
|
||||
return NULL;
|
||||
}
|
||||
buf = (char *) malloc((l * 3) + 1);
|
||||
if (buf == NULL) {
|
||||
perror("Could not allocate memory url encoding");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0, j = 0; i < l; i++){
|
||||
c = (unsigned char)url[i];
|
||||
if(c <= 31 || c >= 127
|
||||
|| c == '$' || c == '&' || c == '+' || c == ',' || c == '/'
|
||||
|| c == ':' || c == ';' || c == '=' || c == '?' || c == '@'
|
||||
|| c == ' ' || c == '"' || c == '<' || c == '>' || c == '#'
|
||||
|| c == '%' || c == '{' || c == '}' || c == '|' || c == '\\'
|
||||
|| c == '^' || c == '~' || c == '[' || c == ']' || c == '`'){
|
||||
for (i = 0, j = 0; i < l; i++) {
|
||||
c = (unsigned char) url[i];
|
||||
if (c <= 31 || c >= 127
|
||||
|| c == '$' || c == '&' || c == '+' || c == ',' || c == '/'
|
||||
|| c == ':' || c == ';' || c == '=' || c == '?' || c == '@'
|
||||
|| c == ' ' || c == '"' || c == '<' || c == '>' || c == '#'
|
||||
|| c == '%' || c == '{' || c == '}' || c == '|' || c == '\\' || c == '^' || c == '~' || c == '[' || c == ']' || c == '`') {
|
||||
|
||||
(void)sprintf(buf + j, "%%%X%X", c >> 4, c & 0x0F);
|
||||
j += 3;
|
||||
}else{
|
||||
buf[j] = url[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
(void) sprintf(buf + j, "%%%X%X", c >> 4, c & 0x0F);
|
||||
j += 3;
|
||||
} else {
|
||||
buf[j] = url[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
buf[j] = '\0';
|
||||
buf[j] = '\0';
|
||||
|
||||
return buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *url_decode(char *url, size_t l)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char *buf;
|
||||
char c;
|
||||
char d0;
|
||||
char d1;
|
||||
int i;
|
||||
int j;
|
||||
char *buf;
|
||||
char c;
|
||||
char d0;
|
||||
char d1;
|
||||
|
||||
buf = (char *)malloc((l + 1) * sizeof(char));
|
||||
if(buf == NULL){
|
||||
perror("Could not allocate memory for decoding");
|
||||
return NULL;
|
||||
}
|
||||
buf = (char *) malloc((l + 1) * sizeof(char));
|
||||
if (buf == NULL) {
|
||||
perror("Could not allocate memory for decoding");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0, j = 0; i < l; j++){
|
||||
c = url[i];
|
||||
if(c == '%'){
|
||||
d0 = url[i + 2];
|
||||
d1 = url[i + 1];
|
||||
d0 = toupper(d0);
|
||||
d1 = toupper(d1);
|
||||
for (i = 0, j = 0; i < l; j++) {
|
||||
c = url[i];
|
||||
if (c == '%') {
|
||||
d0 = url[i + 2];
|
||||
d1 = url[i + 1];
|
||||
d0 = toupper(d0);
|
||||
d1 = toupper(d1);
|
||||
|
||||
if(d0 >= 'A' && d0 <= 'F') d0 = d0 - 'A' + 10;
|
||||
else if(d0 >= '0' && d0 <= '9') d0 = d0 - '0';
|
||||
if(d1 >= 'A' && d1 <= 'F') d1 = d1 - 'A' + 10;
|
||||
else if(d1 >= '0' && d1 <= '9') d1 = d1 - '0';
|
||||
if (d0 >= 'A' && d0 <= 'F')
|
||||
d0 = d0 - 'A' + 10;
|
||||
else if (d0 >= '0' && d0 <= '9')
|
||||
d0 = d0 - '0';
|
||||
if (d1 >= 'A' && d1 <= 'F')
|
||||
d1 = d1 - 'A' + 10;
|
||||
else if (d1 >= '0' && d1 <= '9')
|
||||
d1 = d1 - '0';
|
||||
|
||||
buf[j] = (d1 << 4) + d0;
|
||||
i += 3;
|
||||
}else{
|
||||
buf[j] = url[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
buf[j] = (d1 << 4) + d0;
|
||||
i += 3;
|
||||
} else {
|
||||
buf[j] = url[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
buf[j] = '\0';
|
||||
buf[j] = '\0';
|
||||
|
||||
return buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,4 +39,3 @@ char *url_encode(char *url, size_t l);
|
|||
char *url_decode(char *url, size_t l);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue