Beispiel #1
0
void strbuffer_close(strbuffer_t *strbuff)
{
    jsonp_free(strbuff->value);
    strbuff->size = 0;
    strbuff->length = 0;
    strbuff->value = NULL;
}
static int hashtable_do_rehash(hashtable_t *hashtable)
{
    list_t *list, *next;
    pair_t *pair;
    size_t i, index, new_size;

    jsonp_free(hashtable->buckets);

    hashtable->num_buckets++;
    new_size = num_buckets(hashtable);

    hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t));
    if(!hashtable->buckets)
        return -1;

    for(i = 0; i < num_buckets(hashtable); i++)
    {
        hashtable->buckets[i].first = hashtable->buckets[i].last =
            &hashtable->list;
    }

    list = hashtable->list.next;
    list_init(&hashtable->list);

    for(; list != &hashtable->list; list = next) {
        next = list->next;
        pair = list_to_pair(list);
        index = pair->hash % new_size;
        insert_to_bucket(hashtable, &hashtable->buckets[index], &pair->list);
    }

    return 0;
}
/* returns 0 on success, -1 if key was not found */
static int hashtable_do_del(hashtable_t *hashtable,
                            const char *key, size_t hash)
{
    pair_t *pair;
    bucket_t *bucket;
    size_t index;

    index = hash % num_buckets(hashtable);
    bucket = &hashtable->buckets[index];

    pair = hashtable_find_pair(hashtable, bucket, key, hash);
    if(!pair)
        return -1;

    if(&pair->list == bucket->first && &pair->list == bucket->last)
        bucket->first = bucket->last = &hashtable->list;

    else if(&pair->list == bucket->first)
        bucket->first = pair->list.next;

    else if(&pair->list == bucket->last)
        bucket->last = pair->list.prev;

    list_remove(&pair->list);
    json_decref(pair->value);

    jsonp_free(pair);
    hashtable->size--;

    return 0;
}
Beispiel #4
0
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
{
    if(size >= strbuff->size - strbuff->length)
    {
        size_t new_size;
        char *new_value;

        /* avoid integer overflow */
        if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR
            || size > STRBUFFER_SIZE_MAX - 1
            || strbuff->length > STRBUFFER_SIZE_MAX - 1 - size)
            return -1;

        new_size = max(strbuff->size * STRBUFFER_FACTOR,
                       strbuff->length + size + 1);

        new_value = (char *) jsonp_malloc(new_size);
        if(!new_value)
            return -1;

        memcpy(new_value, strbuff->value, strbuff->length);

        jsonp_free(strbuff->value);
        strbuff->value = new_value;
        strbuff->size = new_size;
    }

    memcpy(strbuff->value + strbuff->length, data, size);
    strbuff->length += size;
    strbuff->value[strbuff->length] = '\0';

    return 0;
}
Beispiel #5
0
static void hashtable_do_clear(hashtable_t *hashtable)
{
    list_t *list, *next;
    pair_t *pair;

    for(list = hashtable->list.next; list != &hashtable->list; list = next)
    {
        next = list->next;
        pair = list_to_pair(list);
        json_decref(pair->value);
        jsonp_free(pair);
    }
}
Beispiel #6
0
json_t *json_object(void)
{
    json_object_t *object = jsonp_malloc(sizeof(json_object_t));
    if(!object)
        return NULL;
    json_init(&object->json, JSON_OBJECT);

    if(hashtable_init(&object->hashtable))
    {
        jsonp_free(object);
        return NULL;
    }

    object->serial = 0;
    object->visited = 0;

    return &object->json;
}
Beispiel #7
0
int json_string_set_nocheck(json_t *json, const char *value)
{
    char *dup;
    json_string_t *string;

    if(!json_is_string(json) || !value)
        return -1;

    dup = jsonp_strdup(value);
    if(!dup)
        return -1;

    string = json_to_string(json);
    jsonp_free(string->value);
    string->value = dup;

    return 0;
}
Beispiel #8
0
json_t *json_string_nocheck(const char *value)
{
    json_string_t *string;

    if(!value)
        return NULL;

    string = (json_string_t *) jsonp_malloc(sizeof(json_string_t));
    if(!string)
        return NULL;
    json_init(&string->json, JSON_STRING);

    string->value = jsonp_strdup(value);
    if(!string->value) {
        jsonp_free(string);
        return NULL;
    }

    return &string->json;
}
Beispiel #9
0
json_t *json_array(void)
{
    json_array_t *array = (json_array_t *) jsonp_malloc(sizeof(json_array_t));
    if(!array)
        return NULL;
    json_init(&array->json, JSON_ARRAY);

    array->entries = 0;
    array->size = 8;

    array->table = (json_t **) jsonp_malloc(array->size * sizeof(json_t *));
    if(!array->table) {
        jsonp_free(array);
        return NULL;
    }

    array->visited = 0;

    return &array->json;
}
Beispiel #10
0
json_t *json_object(void)
{
    json_object_t *object = (json_object_t *) jsonp_malloc(sizeof(json_object_t));
    if(!object)
        return NULL;
    json_init(&object->json, JSON_OBJECT);

    if(hashtable_init(&object->hashtable,
                      hash_key, key_equal,
                      jsonp_free, value_decref))
    {
        jsonp_free(object);
        return NULL;
    }

    object->serial = 0;
    object->visited = 0;

    return &object->json;
}
Beispiel #11
0
int json_array_insert_new(json_t *json, size_t index, json_t *value)
{
    json_array_t *array;
    json_t **old_table;

    if(!value)
        return -1;

    if(!json_is_array(json) || json == value) {
        json_decref(value);
        return -1;
    }
    array = json_to_array(json);

    if(index > array->entries) {
        json_decref(value);
        return -1;
    }

    old_table = json_array_grow(array, 1, 0);
    if(!old_table) {
        json_decref(value);
        return -1;
    }

    if(old_table != array->table) {
        array_copy(array->table, 0, old_table, 0, index);
        array_copy(array->table, index + 1, old_table, index,
                   array->entries - index);
        jsonp_free(old_table);
    }
    else
        array_move(array, index + 1, index, array->entries - index);

    array->table[index] = value;
    array->entries++;

    return 0;
}
Beispiel #12
0
json_t *json_object(void)
{
    json_object_t *object = jsonp_malloc(sizeof(json_object_t));
    if(!object)
        return NULL;

    if (!hashtable_seed) {
        /* Autoseed */
        json_object_seed(0);
    }

    json_init(&object->json, JSON_OBJECT);

    if(hashtable_init(&object->hashtable))
    {
        jsonp_free(object);
        return NULL;
    }

    object->serial = 0;

    return &object->json;
}
Beispiel #13
0
static char *parse_string(stream_t *stream, size_t flags,
                          json_error_t *error)
{
    char *endptr;
    ssize_t colon;
    size_t pos = 0;
    size_t length;
    char *string;

    (void) flags;

    colon = search(stream, ':');
    if (colon < 0) {
        error_set(error, stream, "unterminated string length");
        return NULL;
    }

    if (validate_number(stream, error))
        return NULL;

    /* can overflow, but who cares? */
    length = strtoul(&stream->buffer[stream->pos], &endptr, 10);
    if (endptr != &stream->buffer[colon]) {
        error_set(error, stream, "invalid string length");
        return NULL;
    }
    stream->pos = colon + 1;

    string = jsonp_malloc(length + 1);
    if (!string) {
        error_set(error, stream, "out of memory (string length %zd)", length);
        return NULL;
    }
    string[length] = '\0';

    while (pos < length) {
        char *zero;

        size_t chunk = stream->buflen - stream->pos;
        if (chunk == 0) {
            if (stream_refill(stream) <= 0) {
                error_set(error, stream, "partial string: %zd/%zd", pos,
                          length);
                goto error;
            }
            continue;
        }
        if (chunk > length - pos)
            chunk = length - pos;

        /* null bytes are not allowed inside strings */
        zero = memchr(&stream->buffer[stream->pos], '\0', chunk);
        if (zero) {
            stream->pos = zero - stream->buffer;
            error_set(error, stream, "string contains a zero byte");
            goto error;
        }

        memcpy(&string[pos], &stream->buffer[stream->pos], chunk);
        stream->pos += chunk;
        pos += chunk;
    }
    return string;

error:
    jsonp_free(string);
    return NULL;
}
Beispiel #14
0
void hashtable_close(hashtable_t *hashtable)
{
    hashtable_do_clear(hashtable);
    jsonp_free(hashtable->buckets);
}
Beispiel #15
0
static void lex_free_string(lex_t *lex)
{
    jsonp_free(lex->value.string.val);
    lex->value.string.val = NULL;
    lex->value.string.len = 0;
}
Beispiel #16
0
static void finish_stream(stream_t *stream)
{
    if (stream->fill)
        jsonp_free(stream->buffer);
}
Beispiel #17
0
static void lex_close(lex_t *lex)
{
    if(lex->token == TOKEN_STRING)
        jsonp_free(lex->value.string);
    strbuffer_close(&lex->saved_text);
}
Beispiel #18
0
static void lex_scan_string(lex_t *lex, json_error_t *error)
{
    int c;
    const char *p;
    char *t;
    int i;

    lex->value.string = NULL;
    lex->token = TOKEN_INVALID;

    c = lex_get_save(lex, error);

    while(c != '"') {
        if(c == STREAM_STATE_ERROR)
            goto out;

        else if(c == STREAM_STATE_EOF) {
            error_set(error, lex, "premature end of input");
            goto out;
        }

        else if(0 <= c && c <= 0x1F) {
            /* control character */
            lex_unget_unsave(lex, c);
            if(c == '\n')
                error_set(error, lex, "unexpected newline", c);
            else
                error_set(error, lex, "control character 0x%x", c);
            goto out;
        }

        else if(c == '\\') {
            c = lex_get_save(lex, error);
            if(c == 'u') {
                c = lex_get_save(lex, error);
                for(i = 0; i < 4; i++) {
                    if(!l_isxdigit(c)) {
                        error_set(error, lex, "invalid escape");
                        goto out;
                    }
                    c = lex_get_save(lex, error);
                }
            }
            else if(c == '"' || c == '\\' || c == '/' || c == 'b' ||
                    c == 'f' || c == 'n' || c == 'r' || c == 't')
                c = lex_get_save(lex, error);
            else {
                error_set(error, lex, "invalid escape");
                goto out;
            }
        }
        else
            c = lex_get_save(lex, error);
    }

    /* the actual value is at most of the same length as the source
       string, because:
         - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte
         - a single \uXXXX escape (length 6) is converted to at most 3 bytes
         - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
           are converted to 4 bytes
    */
    lex->value.string = jsonp_malloc(lex->saved_text.length + 1);
    if(!lex->value.string) {
        /* this is not very nice, since TOKEN_INVALID is returned */
        goto out;
    }

    /* the target */
    t = lex->value.string;

    /* + 1 to skip the " */
    p = strbuffer_value(&lex->saved_text) + 1;

    while(*p != '"') {
        if(*p == '\\') {
            p++;
            if(*p == 'u') {
                char buffer[4];
                int length;
                int32_t value;

                value = decode_unicode_escape(p);
                p += 5;

                if(0xD800 <= value && value <= 0xDBFF) {
                    /* surrogate pair */
                    if(*p == '\\' && *(p + 1) == 'u') {
                        int32_t value2 = decode_unicode_escape(++p);
                        p += 5;

                        if(0xDC00 <= value2 && value2 <= 0xDFFF) {
                            /* valid second surrogate */
                            value =
                                ((value - 0xD800) << 10) +
                                (value2 - 0xDC00) +
                                0x10000;
                        }
                        else {
                            /* invalid second surrogate */
                            error_set(error, lex,
                                      "invalid Unicode '\\u%04X\\u%04X'",
                                      value, value2);
                            goto out;
                        }
                    }
                    else {
                        /* no second surrogate */
                        error_set(error, lex, "invalid Unicode '\\u%04X'",
                                  value);
                        goto out;
                    }
                }
                else if(0xDC00 <= value && value <= 0xDFFF) {
                    error_set(error, lex, "invalid Unicode '\\u%04X'", value);
                    goto out;
                }
                else if(value == 0)
                {
                    error_set(error, lex, "\\u0000 is not allowed");
                    goto out;
                }

                if(utf8_encode(value, buffer, &length))
                    assert(0);

                memcpy(t, buffer, length);
                t += length;
            }
            else {
                switch(*p) {
                    case '"': case '\\': case '/':
                        *t = *p; break;
                    case 'b': *t = '\b'; break;
                    case 'f': *t = '\f'; break;
                    case 'n': *t = '\n'; break;
                    case 'r': *t = '\r'; break;
                    case 't': *t = '\t'; break;
                    default: assert(0);
                }
                t++;
                p++;
            }
        }
        else
            *(t++) = *(p++);
    }
    *t = '\0';
    lex->token = TOKEN_STRING;
    return;

out:
    jsonp_free(lex->value.string);
}
Beispiel #19
0
void MessageBuilder::freeMessage(char * message)
{
  jsonp_free(message);
}
Beispiel #20
0
static void json_delete_string(json_string_t *string)
{
    jsonp_free(string->value);
    jsonp_free(string);
}
Beispiel #21
0
static int lex_scan(lex_t *lex, json_error_t *error)
{
    int c;

    strbuffer_clear(&lex->saved_text);

    if(lex->token == TOKEN_STRING) {
        jsonp_free(lex->value.string);
        lex->value.string = NULL;
    }

    c = lex_get(lex, error);
    while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
        c = lex_get(lex, error);

    if(c == STREAM_STATE_EOF) {
        lex->token = TOKEN_EOF;
        goto out;
    }

    if(c == STREAM_STATE_ERROR) {
        lex->token = TOKEN_INVALID;
        goto out;
    }

    lex_save(lex, c);

    if(c == '{' || c == '}' || c == '[' || c == ']' || c == ':' || c == ',')
        lex->token = c;

    else if(c == '"')
        lex_scan_string(lex, error);

    else if(l_isdigit(c) || c == '-') {
        if(lex_scan_number(lex, c, error))
            goto out;
    }

    else if(l_isalpha(c)) {
        /* eat up the whole identifier for clearer error messages */
        const char *saved_text;

        c = lex_get_save(lex, error);
        while(l_isalpha(c))
            c = lex_get_save(lex, error);
        lex_unget_unsave(lex, c);

        saved_text = strbuffer_value(&lex->saved_text);

        if(strcmp(saved_text, "true") == 0)
            lex->token = TOKEN_TRUE;
        else if(strcmp(saved_text, "false") == 0)
            lex->token = TOKEN_FALSE;
        else if(strcmp(saved_text, "null") == 0)
            lex->token = TOKEN_NULL;
        else
            lex->token = TOKEN_INVALID;
    }

    else {
        /* save the rest of the input UTF-8 sequence to get an error
           message of valid UTF-8 */
        lex_save_cached(lex);
        lex->token = TOKEN_INVALID;
    }

out:
    return lex->token;
}
Beispiel #22
0
static void json_delete_integer(json_integer_t *integer)
{
    jsonp_free(integer);
}
Beispiel #23
0
static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
{
    json_t *object = json_object();
    if(!object)
        return NULL;

    lex_scan(lex, error);
    if(lex->token == '}')
        return object;

    while(1) {
        char *key;
        json_t *value;

        if(lex->token != TOKEN_STRING) {
            error_set(error, lex, "string or '}' expected");
            goto error;
        }

        key = lex_steal_string(lex);
        if(!key)
            return NULL;

        if(flags & JSON_REJECT_DUPLICATES) {
            if(json_object_get(object, key)) {
                jsonp_free(key);
                error_set(error, lex, "duplicate object key");
                goto error;
            }
        }

        lex_scan(lex, error);
        if(lex->token != ':') {
            jsonp_free(key);
            error_set(error, lex, "':' expected");
            goto error;
        }

        lex_scan(lex, error);
        value = parse_value(lex, flags, error);
        if(!value) {
            jsonp_free(key);
            goto error;
        }

        if(json_object_set_nocheck(object, key, value)) {
            jsonp_free(key);
            json_decref(value);
            goto error;
        }

        json_decref(value);
        jsonp_free(key);

        lex_scan(lex, error);
        if(lex->token != ',')
            break;

        lex_scan(lex, error);
    }

    if(lex->token != '}') {
        error_set(error, lex, "'}' expected");
        goto error;
    }

    return object;

error:
    json_decref(object);
    return NULL;
}
Beispiel #24
0
static void json_delete_real(json_real_t *real)
{
    jsonp_free(real);
}
Beispiel #25
0
static void json_delete_object(json_object_t *object)
{
    hashtable_close(&object->hashtable);
    jsonp_free(object);
}
Beispiel #26
0
int json_path_set(json_t *json, const char *path, json_t *value,
		unsigned int append)
{
	static const char array_open = '[';
	static const char object_delim = '.';
	static const char *path_delims = ".[";
	static const char *array_close = "]";

	json_t *cursor, *parent = NULL;
	char *token, *buf = NULL, *peek, delim = '\0';
	const char *expect;
	int index_saved = -1;

	if (!json || !path || !value) {
		ERR("invalid arguments\n");
		goto fail;
	} else {
		buf = jsonp_strdup(path);
	}

	peek = buf;
	token = buf;
	cursor = json;
	expect = path_delims;

	if (*token == array_open) {
		expect = array_close;
		token++;
	}

	while (peek && *peek && cursor)
	{
		char *last_peek = peek;
		peek = strpbrk(last_peek, expect);

		if (peek) {
			if (!token && peek != last_peek) {
				ERR("unexpected trailing chars in JSON path at pos %zu\n",
						last_peek - buf);
				goto fail;
			}
			delim = *peek;
			*peek++ = '\0';
		} else { // end of path
			if (expect == path_delims) {
				break;
			} else {
				ERR("missing ']' at pos %zu\n", peek - buf);
				goto fail;
			}
		}

		if (expect == path_delims) {
			if (token) {
				if (token[0] == '\0') {
					ERR("empty token at pos %zu\n", peek - buf);
					goto fail;
				}

				parent = cursor;
				cursor = json_object_get(parent, token);

				if (!cursor) {
					if (!json_is_object(parent)) {
						ERR("object expected at pos %zu\n", peek - buf);
						goto fail;
					}
					if (delim == object_delim) {
						cursor = json_object();
						json_object_set_new(parent, token, cursor);
					} else {
						ERR("new array is not allowed at pos %zu\n", peek - buf);
						goto fail;
					}
				}
			}
			expect = (delim == array_open ? array_close : path_delims);
			token = peek;
		} else if (expect == array_close) {
			char *endptr;
			size_t index;

			parent = cursor;
			if (!json_is_array(parent)) {
				ERR("array expected at pos %zu\n", peek - buf);
				goto fail;
			}

			index = strtol(token, &endptr, 0);
			if (*endptr) {
				ERR("invalid array index at pos %zu\n", peek - buf);
				goto fail;
			}

			cursor = json_array_get(parent, index);
			if (!cursor) {
				ERR("array index out of bound at pos %zu\n", peek - buf);
				goto fail;
			}

			index_saved = index;
			token = NULL;
			expect = path_delims;

		} else {
			ERR("fatal JSON error at pos %zu\n", peek - buf);
			goto fail;
		}
	}

	if (token && append) {

		if(strlen(token) > 0) {
			json_t* tmp  = json_object_get(cursor, token);
			if(json_is_array(tmp)) {
				json_array_append(tmp, value);
				json_object_set(cursor, token, tmp);
			} else if(json_is_object(tmp) && json_is_object(value) ) {
				json_object_update(tmp, value);
				json_object_set(cursor, token, tmp);
			} else {
				ERR("JSON array or object expected at pos %zu\n", peek - buf);
				goto fail;
			}
		} else if(json_is_array(cursor)) {
			json_array_append(cursor, value);

		} else if(json_is_object(cursor) && json_is_object(value)) {
			json_object_update(cursor, value);

		} else {
			ERR("JSON array or object expected at pos %zu\n", peek - buf);
			goto fail;
		}

	} else if (token && strlen(token) != 0 ) {

		if (json_is_object(cursor)) {
			json_object_set(cursor, token, value);

		} else {
			ERR("JSON object expected at pos %zu\n", peek - buf);
			goto fail;
		}

		cursor = json_object_get(cursor, token);
	} else if (index_saved != -1 && json_is_array(parent)) {
		json_array_set(parent, index_saved, value);
		cursor = json_array_get(parent, index_saved);

	} else {
		ERR("invalid JSON path at pos %zu\n", peek - buf);
		goto fail;
	}

	json_decref(value);
	jsonp_free(buf);
	return 0;

fail:
	json_decref(value);
	jsonp_free(buf);
	return -1;
}