Browse Source

Merge bcfd1f57ac into 7502b377b7

pull/21/merge
GitHub Merge Button 13 years ago
parent
commit
8c93b4eadb
8 changed files with 522 additions and 9 deletions
  1. +26
    -4
      debug.h
  2. +2
    -0
      json.h
  3. +21
    -2
      json_object.c
  4. +24
    -0
      json_object.h
  5. +169
    -0
      json_object_iterator.c
  6. +254
    -0
      json_object_iterator.h
  7. +14
    -3
      linkhash.c
  8. +12
    -0
      linkhash.h

+ 26
- 4
debug.h View File

@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
@@ -12,6 +13,8 @@
#ifndef _DEBUG_H_
#define _DEBUG_H_

#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif
@@ -25,21 +28,40 @@ extern void mc_debug(const char *msg, ...);
extern void mc_error(const char *msg, ...);
extern void mc_info(const char *msg, ...);

#ifndef __STRING
#define __STRING(x) #x
#endif

#ifndef PARSER_BROKEN_FIXED

#define JASSERT(cond) do {} while(0)

#else

#define JASSERT(cond) do { \
if (!(cond)) { \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
*(int *)0 = 1;\
abort(); \
}\
} while(0)

#endif

#define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__)
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)

#ifdef MC_MAINTAINER_MODE
#define MC_SET_DEBUG(x) mc_set_debug(x)
#define MC_GET_DEBUG() mc_get_debug()
#define MC_SET_SYSLOG(x) mc_set_syslog(x)
#define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__)
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
#else
#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
#define MC_GET_DEBUG() (0)
#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
#define MC_ABORT(x, ...) if (0) mc_abort(x, ##__VA_ARGS__)
#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
#define MC_ERROR(x, ...) if (0) mc_error(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
#endif



+ 2
- 0
json.h View File

@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
@@ -23,6 +24,7 @@ extern "C" {
#include "json_util.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_object_iterator.h"

#ifdef __cplusplus
}


+ 21
- 2
json_object.c View File

@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
@@ -24,11 +25,13 @@
#include "json_object.h"
#include "json_object_private.h"
#include "json_util.h"
#include "json_tokener.h"

#if !HAVE_STRNDUP
char* strndup(const char* str, size_t n);
#endif /* !HAVE_STRNDUP */

// Don't define this. It's not thread-safe.
/* #define REFCOUNT_DEBUG 1 */

const char *json_number_chars = "0123456789.+-eE";
@@ -260,8 +263,24 @@ void json_object_object_add(struct json_object* jso, const char *key,

struct json_object* json_object_object_get(struct json_object* jso, const char *key)
{
if(!jso) return NULL;
return (struct json_object*) lh_table_lookup(jso->o.c_object, key);
struct json_object *result;
json_object_object_get_ex(jso, key, &result);
return result;
}

json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value)
{
if (NULL == jso) return FALSE;

switch(jso->o_type) {
case json_type_object:
return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value);
default:
if (value != NULL) {
*value = NULL;
}
return FALSE;
}
}

void json_object_object_del(struct json_object* jso, const char *key)


+ 24
- 0
json_object.h View File

@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
@@ -172,10 +173,33 @@ extern void json_object_object_add(struct json_object* obj, const char *key,
* @param obj the json_object instance
* @param key the object field name
* @returns the json_object associated with the given field name
* @deprecated Please use json_object_object_get_ex
*/
extern struct json_object* json_object_object_get(struct json_object* obj,
const char *key);

/** Get the json_object associated with a given object field.
*
* This returns true if the key is found, false in all other cases (including
* if obj isn't a json_type_object).
*
* *No* reference counts will be changed. There is no need to manually adjust
* reference counts through the json_object_put/json_object_get methods unless
* you need to have the child (value) reference maintain a different lifetime
* than the owning parent (obj). Ownership of value is retained by obj.
*
* @param obj the json_object instance
* @param key the object field name
* @param value a pointer where to store a reference to the json_object
* associated with the given field name.
*
* It is safe to pass a NULL value.
* @returns whether or not the key exists
*/
extern json_bool json_object_object_get_ex(struct json_object* obj,
const char *key,
struct json_object **value);

/** Delete the given json_object field
*
* The reference count will be decremented for the deleted object. If there


+ 169
- 0
json_object_iterator.c View File

@@ -0,0 +1,169 @@
/**
*******************************************************************************
* @file cjson_object_iterator.c
*
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief cjson forces clients to use its private data
* structures for JSON Object iteration. This API
* implementation corrects that by abstracting the
* private cjson details.
*
*******************************************************************************
*/

#include <stddef.h>
#include <stdbool.h>

#include "json.h"
#include "json_object_private.h"

#include "json_object_iterator.h"

/**
* How It Works
*
* For each JSON Object, cjson maintains a linked list of zero
* or more lh_entry (link-hash entry) structures inside the
* Object's link-hash table (lh_table).
*
* Each lh_entry structure on the JSON Object's linked list
* represents a single name/value pair. The "next" field of the
* last lh_entry in the list is set to NULL, which terminates
* the list.
*
* We represent a valid iterator that refers to an actual
* name/value pair via a pointer to the pair's lh_entry
* structure set as the iterator's opaque_ field.
*
* We follow cjson's current pair list representation by
* representing a valid "end" iterator (one that refers past the
* last pair) with a NULL value in the iterator's opaque_ field.
*
* A JSON Object without any pairs in it will have the "head"
* field of its lh_table structure set to NULL. For such an
* object, json_object_iter_begin will return an iterator with
* the opaque_ field set to NULL, which is equivalent to the
* "end" iterator.
*
* When iterating, we simply update the iterator's opaque_ field
* to point to the next lh_entry structure in the linked list.
* opaque_ will become NULL once we iterate past the last pair
* in the list, which makes the iterator equivalent to the "end"
* iterator.
*/

/// Our current representation of the "end" iterator;
///
/// @note May not always be NULL
static const void* kObjectEndIterValue = NULL;

/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj)
{
struct json_object_iterator iter;
struct lh_table* pTable;

/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);

/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
}

/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj)
{
struct json_object_iterator iter;

JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));

iter.opaque_ = kObjectEndIterValue;

return iter;
}

/**
* ****************************************************************************
*/
void
json_object_iter_next(struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);

iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next;
}


/**
* ****************************************************************************
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);

return (const char*)(((struct lh_entry *)iter->opaque_)->k);
}


/**
* ****************************************************************************
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);

return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v);
}


/**
* ****************************************************************************
*/
bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2)
{
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);

return (iter1->opaque_ == iter2->opaque_);
}


/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_init_default(void)
{
struct json_object_iterator iter;

/**
* @note Make this a negative, invalid value, such that
* accidental access to it would likely be trapped by the
* hardware as an invalid address.
*/
iter.opaque_ = NULL;

return iter;
}

+ 254
- 0
json_object_iterator.h View File

@@ -0,0 +1,254 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief cjson forces clients to use its private data
* structures for JSON Object iteration. This API
* corrects that by abstracting the private cjson
* details.
*
* The intention is to add this API (and its
* implementation) to Palm's version of the cjson
* library, at which point it can be removed from the
* Wireless System Framework library implementation.
*
* API attributes:
* * Thread-safe: NO
* * Re-entrant: NO
*
*******************************************************************************
*/


#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H

#include <stddef.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;

/**
* The opaque iterator that references a name/value pair within
* a JSON Object intance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};


/**
* forward declaration of cjson's JSON value instance structure
*/
struct json_object;


/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any cjson API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);

/** Retrieves an iterator to the first pair of the JSON Object.
*
* @note WARNING: Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type
* json_type_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj = json_tokener_parse(
* "{'first':'george', 'age':100}");
* json_object_iter_begin(obj, &it);
* json_object_iter_end(obj, &itEnd);
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* struct json_object* obj = json_tokener_parse(
* "{'first':'george', 'age':100}");
* struct json_object_iterator it;
* bool iterable = json_object_iter_begin(&it);
* if (iterable) {
* do {
* printf("%s\n", json_object_iter_peek_name(&it));
* } while (json_object_iter_next(&it));
* }
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);

/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @note WARNING: Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memoize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type
* json_type_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);

/** Returns an iterator to the next pair, if any
*
* @note WARNING: Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter Iterator that references a name/value pair;
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);


/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the rerferenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);


/** Returns a pointer to the cjson instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the cjson value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this cjson node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: cjson API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);


/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @note WARNING: if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);


#ifdef __cplusplus
}
#endif


#endif // JSON_OBJECT_ITERATOR_H

+ 14
- 3
linkhash.c View File

@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
@@ -174,11 +175,21 @@ struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)

const void* lh_table_lookup(struct lh_table *t, const void *k)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if(e) return e->v;
return NULL;
void *result;
lh_table_lookup_ex(t, k, &result);
return result;
}

json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if (e != NULL) {
if (v != NULL) *v = (void *)e->v;
return TRUE; /* key found */
}
if (v != NULL) *v = NULL;
return FALSE; /* key not found */
}

int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
{


+ 12
- 0
linkhash.h View File

@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
@@ -12,6 +13,8 @@
#ifndef _linkhash_h_
#define _linkhash_h_

#include "json_object.h"

#ifdef __cplusplus
extern "C" {
#endif
@@ -241,9 +244,18 @@ extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the found value or NULL if it does not exist.
* @deprecated Use lh_table_lookup_ex instead.
*/
extern const void* lh_table_lookup(struct lh_table *t, const void *k);

/**
* Lookup a record in the table
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
* @return whether or not the key was found
*/
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);

/**
* Delete a record from the table.


Loading…
Cancel
Save