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