1 /**
2 *******************************************************************************
3 * @file fjson_object_iterator.h
4 *
5 * Copyright (c) 2009-2012 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  json-c forces clients to use its private data
11 *         structures for JSON Object iteration.  This API
12 *         corrects that by abstracting the private json-c
13 *         details.
14 *
15 * API attributes: <br>
16 *   * Thread-safe: NO<br>
17 *   * Reentrant: NO
18 *
19 *******************************************************************************
20 */
21 
22 
23 #ifndef FJ_JSON_OBJECT_ITERATOR_H
24 #define FJ_JSON_OBJECT_ITERATOR_H
25 
26 #include <stddef.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /**
33  * Forward declaration for the opaque iterator information.
34  */
35 struct fjson_object_iter_info_;
36 
37 /**
38  * The opaque iterator that references a name/value pair within
39  * a JSON Object instance or the "end" iterator value.
40  */
41 struct fjson_object_iterator {
42 	int objs_remain;
43 	int curr_idx;
44 	const struct _fjson_child_pg *pg;
45 };
46 
47 
48 /**
49  * forward declaration of json-c's JSON value instance structure
50  */
51 struct fjson_object;
52 
53 
54 /**
55  * Initializes an iterator structure to a "default" value that
56  * is convenient for initializing an iterator variable to a
57  * default state (e.g., initialization list in a class'
58  * constructor).
59  *
60  * @code
61  * struct fjson_object_iterator iter = fjson_object_iter_init_default();
62  * MyClass() : iter_(fjson_object_iter_init_default())
63  * @endcode
64  *
65  * @note The initialized value doesn't reference any specific
66  *       pair, is considered an invalid iterator, and MUST NOT
67  *       be passed to any json-c API that expects a valid
68  *       iterator.
69  *
70  * @note User and internal code MUST NOT make any assumptions
71  *       about and dependencies on the value of the "default"
72  *       iterator value.
73  *
74  * @return fjson_object_iterator
75  */
76 struct fjson_object_iterator
77 fjson_object_iter_init_default(void);
78 
79 /** Retrieves an iterator to the first pair of the JSON Object.
80  *
81  * @warning 	Any modification of the underlying pair invalidates all
82  * 		iterators to that pair.
83  *
84  * @param obj	JSON Object instance (MUST be of type fjson_object)
85  *
86  * @return fjson_object_iterator If the JSON Object has at
87  *              least one pair, on return, the iterator refers
88  *              to the first pair. If the JSON Object doesn't
89  *              have any pairs, the returned iterator is
90  *              equivalent to the "end" iterator for the same
91  *              JSON Object instance.
92  *
93  * @code
94  * struct fjson_object_iterator it;
95  * struct fjson_object_iterator itEnd;
96  * struct fjson_object* obj;
97  *
98  * obj = fjson_tokener_parse("{'first':'george', 'age':100}");
99  * it = fjson_object_iter_begin(obj);
100  * itEnd = fjson_object_iter_end(obj);
101  *
102  * while (!fjson_object_iter_equal(&it, &itEnd)) {
103  *     printf("%s\n",
104  *            fjson_object_iter_peek_name(&it));
105  *     fjson_object_iter_next(&it);
106  * }
107  *
108  * @endcode
109  */
110 struct fjson_object_iterator
111 fjson_object_iter_begin(struct fjson_object* obj);
112 
113 /** Retrieves the iterator that represents the position beyond the
114  *  last pair of the given JSON Object instance.
115  *
116  *  @warning Do NOT write code that assumes that the "end"
117  *        iterator value is NULL, even if it is so in a
118  *        particular instance of the implementation.
119  *
120  *  @note The reason we do not (and MUST NOT) provide
121  *        "fjson_object_iter_is_end(fjson_object_iterator* iter)"
122  *        type of API is because it would limit the underlying
123  *        representation of name/value containment (or force us
124  *        to add additional, otherwise unnecessary, fields to
125  *        the iterator structure). The "end" iterator and the
126  *        equality test method, on the other hand, permit us to
127  *        cleanly abstract pretty much any reasonable underlying
128  *        representation without burdening the iterator
129  *        structure with unnecessary data.
130  *
131  *  @note For performance reasons, memorize the "end" iterator prior
132  *        to any loop.
133  *
134  * @param obj JSON Object instance (MUST be of type fjson_object)
135  *
136  * @return fjson_object_iterator On return, the iterator refers
137  *              to the "end" of the Object instance's pairs
138  *              (i.e., NOT the last pair, but "beyond the last
139  *              pair" value)
140  */
141 struct fjson_object_iterator
142 fjson_object_iter_end(const struct fjson_object* obj);
143 
144 /** Returns an iterator to the next pair, if any
145  *
146  * @warning	Any modification of the underlying pair
147  *       	invalidates all iterators to that pair.
148  *
149  * @param iter [IN/OUT] Pointer to iterator that references a
150  *         name/value pair; MUST be a valid, non-end iterator.
151  *         WARNING: bad things will happen if invalid or "end"
152  *         iterator is passed. Upon return will contain the
153  *         reference to the next pair if there is one; if there
154  *         are no more pairs, will contain the "end" iterator
155  *         value, which may be compared against the return value
156  *         of fjson_object_iter_end() for the same JSON Object
157  *         instance.
158  */
159 void
160 fjson_object_iter_next(struct fjson_object_iterator* iter);
161 
162 
163 /** Returns a const pointer to the name of the pair referenced
164  *  by the given iterator.
165  *
166  * @param iter pointer to iterator that references a name/value
167  *             pair; MUST be a valid, non-end iterator.
168  *
169  * @warning	bad things will happen if an invalid or
170  *             	"end" iterator is passed.
171  *
172  * @return const char* Pointer to the name of the referenced
173  *         name/value pair.  The name memory belongs to the
174  *         name/value pair, will be freed when the pair is
175  *         deleted or modified, and MUST NOT be modified or
176  *         freed by the user.
177  */
178 const char*
179 fjson_object_iter_peek_name(const struct fjson_object_iterator* iter);
180 
181 
182 /** Returns a pointer to the json-c instance representing the
183  *  value of the referenced name/value pair, without altering
184  *  the instance's reference count.
185  *
186  * @param iter 	pointer to iterator that references a name/value
187  *             	pair; MUST be a valid, non-end iterator.
188  *
189  * @warning	bad things will happen if invalid or
190  *             "end" iterator is passed.
191  *
192  * @return struct fjson_object* Pointer to the json-c value
193  *         instance of the referenced name/value pair;  the
194  *         value's reference count is not changed by this
195  *         function: if you plan to hold on to this json-c node,
196  *         take a look at fjson_object_get() and
197  *         fjson_object_put(). IMPORTANT: json-c API represents
198  *         the JSON Null value as a NULL fjson_object instance
199  *         pointer.
200  */
201 struct fjson_object*
202 fjson_object_iter_peek_value(const struct fjson_object_iterator* iter);
203 
204 
205 /** Tests two iterators for equality.  Typically used to test
206  *  for end of iteration by comparing an iterator to the
207  *  corresponding "end" iterator (that was derived from the same
208  *  JSON Object instance).
209  *
210  *  @note The reason we do not (and MUST NOT) provide
211  *        "fjson_object_iter_is_end(fjson_object_iterator* iter)"
212  *        type of API is because it would limit the underlying
213  *        representation of name/value containment (or force us
214  *        to add additional, otherwise unnecessary, fields to
215  *        the iterator structure). The equality test method, on
216  *        the other hand, permits us to cleanly abstract pretty
217  *        much any reasonable underlying representation.
218  *
219  * @param iter1 Pointer to first valid, non-NULL iterator
220  * @param iter2 POinter to second valid, non-NULL iterator
221  *
222  * @warning	if a NULL iterator pointer or an uninitialized
223  *       	or invalid iterator, or iterators derived from
224  *       	different JSON Object instances are passed, bad things
225  *       	will happen!
226  *
227  * @return fjson_bool non-zero if iterators are equal (i.e., both
228  *         reference the same name/value pair or are both at
229  *         "end"); zero if they are not equal.
230  */
231 fjson_bool
232 fjson_object_iter_equal(const struct fjson_object_iterator* iter1,
233 			const struct fjson_object_iterator* iter2);
234 
235 /* some private functions -- TODO: move to their own header */
236 struct _fjson_child*
237 _fjson_object_iter_peek_child(const struct fjson_object_iterator *const __restrict__ iter);
238 
239 
240 #ifndef FJSON_NATIVE_API_ONLY
241 #define json_object_iter_info_ fjson_object_iter_info_
242 #define json_object_iterator fjson_object_iterator
243 #define json_object_iter_init_default fjson_object_iter_init_default
244 #define json_object_iter_begin fjson_object_iter_begin
245 #define json_object_iter_end fjson_object_iter_end
246 #define json_object_iter_next fjson_object_iter_next
247 #define json_object_iter_peek_name fjson_object_iter_peek_name
248 #define json_object_iter_peek_value fjson_object_iter_peek_value
249 #define json_object_iter_equal fjson_object_iter_equal
250 #endif
251 
252 #ifdef __cplusplus
253 }
254 #endif
255 
256 
257 #endif /* FJSON_OBJECT_ITERATOR_H */
258