Skip to content

Commit bcfd1f5

Browse files
author
Keith Derrick
committed
Add alternative iterator implementation
1 parent 6917586 commit bcfd1f5

File tree

3 files changed

+425
-0
lines changed

3 files changed

+425
-0
lines changed

json.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
55
* Michael Clark <[email protected]>
6+
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
67
*
78
* This library is free software; you can redistribute it and/or modify
89
* it under the terms of the MIT license. See COPYING for details.
@@ -23,6 +24,7 @@ extern "C" {
2324
#include "json_util.h"
2425
#include "json_object.h"
2526
#include "json_tokener.h"
27+
#include "json_object_iterator.h"
2628

2729
#ifdef __cplusplus
2830
}

json_object_iterator.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/**
2+
*******************************************************************************
3+
* @file cjson_object_iterator.c
4+
*
5+
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
6+
*
7+
* This library is free software; you can redistribute it and/or modify
8+
* it under the terms of the MIT license. See COPYING for details.
9+
*
10+
* @brief cjson forces clients to use its private data
11+
* structures for JSON Object iteration. This API
12+
* implementation corrects that by abstracting the
13+
* private cjson details.
14+
*
15+
*******************************************************************************
16+
*/
17+
18+
#include <stddef.h>
19+
#include <stdbool.h>
20+
21+
#include "json.h"
22+
#include "json_object_private.h"
23+
24+
#include "json_object_iterator.h"
25+
26+
/**
27+
* How It Works
28+
*
29+
* For each JSON Object, cjson maintains a linked list of zero
30+
* or more lh_entry (link-hash entry) structures inside the
31+
* Object's link-hash table (lh_table).
32+
*
33+
* Each lh_entry structure on the JSON Object's linked list
34+
* represents a single name/value pair. The "next" field of the
35+
* last lh_entry in the list is set to NULL, which terminates
36+
* the list.
37+
*
38+
* We represent a valid iterator that refers to an actual
39+
* name/value pair via a pointer to the pair's lh_entry
40+
* structure set as the iterator's opaque_ field.
41+
*
42+
* We follow cjson's current pair list representation by
43+
* representing a valid "end" iterator (one that refers past the
44+
* last pair) with a NULL value in the iterator's opaque_ field.
45+
*
46+
* A JSON Object without any pairs in it will have the "head"
47+
* field of its lh_table structure set to NULL. For such an
48+
* object, json_object_iter_begin will return an iterator with
49+
* the opaque_ field set to NULL, which is equivalent to the
50+
* "end" iterator.
51+
*
52+
* When iterating, we simply update the iterator's opaque_ field
53+
* to point to the next lh_entry structure in the linked list.
54+
* opaque_ will become NULL once we iterate past the last pair
55+
* in the list, which makes the iterator equivalent to the "end"
56+
* iterator.
57+
*/
58+
59+
/// Our current representation of the "end" iterator;
60+
///
61+
/// @note May not always be NULL
62+
static const void* kObjectEndIterValue = NULL;
63+
64+
/**
65+
* ****************************************************************************
66+
*/
67+
struct json_object_iterator
68+
json_object_iter_begin(struct json_object* obj)
69+
{
70+
struct json_object_iterator iter;
71+
struct lh_table* pTable;
72+
73+
/// @note json_object_get_object will return NULL if passed NULL
74+
/// or a non-json_type_object instance
75+
pTable = json_object_get_object(obj);
76+
JASSERT(NULL != pTable);
77+
78+
/// @note For a pair-less Object, head is NULL, which matches our
79+
/// definition of the "end" iterator
80+
iter.opaque_ = pTable->head;
81+
return iter;
82+
}
83+
84+
/**
85+
* ****************************************************************************
86+
*/
87+
struct json_object_iterator
88+
json_object_iter_end(const struct json_object* obj)
89+
{
90+
struct json_object_iterator iter;
91+
92+
JASSERT(NULL != obj);
93+
JASSERT(json_object_is_type(obj, json_type_object));
94+
95+
iter.opaque_ = kObjectEndIterValue;
96+
97+
return iter;
98+
}
99+
100+
/**
101+
* ****************************************************************************
102+
*/
103+
void
104+
json_object_iter_next(struct json_object_iterator* iter)
105+
{
106+
JASSERT(NULL != iter);
107+
JASSERT(kObjectEndIterValue != iter->opaque_);
108+
109+
iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next;
110+
}
111+
112+
113+
/**
114+
* ****************************************************************************
115+
*/
116+
const char*
117+
json_object_iter_peek_name(const struct json_object_iterator* iter)
118+
{
119+
JASSERT(NULL != iter);
120+
JASSERT(kObjectEndIterValue != iter->opaque_);
121+
122+
return (const char*)(((struct lh_entry *)iter->opaque_)->k);
123+
}
124+
125+
126+
/**
127+
* ****************************************************************************
128+
*/
129+
struct json_object*
130+
json_object_iter_peek_value(const struct json_object_iterator* iter)
131+
{
132+
JASSERT(NULL != iter);
133+
JASSERT(kObjectEndIterValue != iter->opaque_);
134+
135+
return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v);
136+
}
137+
138+
139+
/**
140+
* ****************************************************************************
141+
*/
142+
bool
143+
json_object_iter_equal(const struct json_object_iterator* iter1,
144+
const struct json_object_iterator* iter2)
145+
{
146+
JASSERT(NULL != iter1);
147+
JASSERT(NULL != iter2);
148+
149+
return (iter1->opaque_ == iter2->opaque_);
150+
}
151+
152+
153+
/**
154+
* ****************************************************************************
155+
*/
156+
struct json_object_iterator
157+
json_object_iter_init_default(void)
158+
{
159+
struct json_object_iterator iter;
160+
161+
/**
162+
* @note Make this a negative, invalid value, such that
163+
* accidental access to it would likely be trapped by the
164+
* hardware as an invalid address.
165+
*/
166+
iter.opaque_ = NULL;
167+
168+
return iter;
169+
}

0 commit comments

Comments
 (0)