@@ -228,7 +228,7 @@ static bool add_if_missing(Json_dom *candidate,
228
228
229
229
230
230
/* *
231
- Check if a seek operation performed by Json_dom:: find_child_doms()
231
+ Check if a seek operation performed by find_child_doms()
232
232
or Json_dom::seek() is done.
233
233
234
234
@return true if only one result is needed and a result has been found
@@ -240,13 +240,31 @@ static inline bool is_seek_done(const Result_vector *hits, bool only_need_one)
240
240
}
241
241
242
242
243
- bool Json_dom::find_child_doms (const Json_path_leg *path_leg,
244
- bool auto_wrap,
245
- bool only_need_one,
246
- Json_dom_vector *duplicates,
247
- Json_dom_vector *result)
248
- {
249
- enum_json_type dom_type= json_type ();
243
+ /* *
244
+ Return the child Json_doms identified by the given path leg.
245
+ The child doms are added to a vector.
246
+
247
+ See the header comment for Json_wrapper.seek() for a discussion
248
+ of complexities involving path expressions with more than one
249
+ ellipsis (**) token.
250
+
251
+ @param[in] dom the DOM to search
252
+ @param[in] path_leg identifies the child
253
+ @param[in] auto_wrap if true, match final scalar with [0] is need be
254
+ @param[in] only_need_one true if we can stop after finding one match
255
+ @param[in,out] duplicates helps to identify duplicate arrays and objects
256
+ introduced by daisy-chained ** tokens
257
+ @param[in,out] result the vector of qualifying children
258
+ @return false on success, true on error
259
+ */
260
+ static bool find_child_doms (Json_dom *dom,
261
+ const Json_path_leg *path_leg,
262
+ bool auto_wrap,
263
+ bool only_need_one,
264
+ Json_dom_vector *duplicates,
265
+ Json_dom_vector *result)
266
+ {
267
+ enum_json_type dom_type= dom->json_type ();
250
268
enum_json_path_leg_type leg_type= path_leg->get_type ();
251
269
252
270
if (is_seek_done (result, only_need_one))
@@ -256,17 +274,17 @@ bool Json_dom::find_child_doms(const Json_path_leg *path_leg,
256
274
if (auto_wrap && dom_type != enum_json_type::J_ARRAY &&
257
275
path_leg->is_autowrap ())
258
276
{
259
- return !seen_already (result, this ) &&
260
- add_if_missing (this , duplicates, result);
277
+ return !seen_already (result, dom ) &&
278
+ add_if_missing (dom , duplicates, result);
261
279
}
262
280
263
281
switch (leg_type)
264
282
{
265
283
case jpl_array_cell:
266
284
if (dom_type == enum_json_type::J_ARRAY)
267
285
{
268
- auto array= down_cast<const Json_array *>(this );
269
- Json_array_index idx= path_leg->first_array_index (array->size ());
286
+ const auto array= down_cast<const Json_array *>(dom );
287
+ const Json_array_index idx= path_leg->first_array_index (array->size ());
270
288
return idx.within_bounds () &&
271
289
add_if_missing ((*array)[idx.position ()], duplicates, result);
272
290
}
@@ -275,8 +293,8 @@ bool Json_dom::find_child_doms(const Json_path_leg *path_leg,
275
293
case jpl_array_cell_wildcard:
276
294
if (dom_type == enum_json_type::J_ARRAY)
277
295
{
278
- const auto array= down_cast<const Json_array *>(this );
279
- auto range= path_leg->get_array_range (array->size ());
296
+ const auto array= down_cast<const Json_array *>(dom );
297
+ const auto range= path_leg->get_array_range (array->size ());
280
298
for (size_t i= range.m_begin ; i < range.m_end ; ++i)
281
299
{
282
300
if (add_if_missing ((*array)[i], duplicates, result))
@@ -288,56 +306,39 @@ bool Json_dom::find_child_doms(const Json_path_leg *path_leg,
288
306
return false ;
289
307
case jpl_ellipsis:
290
308
{
291
- if (add_if_missing (this , duplicates, result))
309
+ /*
310
+ Paths that end with an ellipsis are rejected by the JSON path
311
+ parser, so there is no need to check if we can stop after the
312
+ first match on this path leg.
313
+ */
314
+ DBUG_ASSERT (!only_need_one);
315
+
316
+ // The ellipsis matches the value on which it is called ...
317
+ if (add_if_missing (dom, duplicates, result))
292
318
return true ; /* purecov: inspected */
293
319
320
+ // ... and, recursively, all the values contained in it.
294
321
if (dom_type == enum_json_type::J_ARRAY)
295
322
{
296
- const Json_array * const array= down_cast<const Json_array *>(this );
297
-
323
+ const auto array= down_cast<const Json_array *>(dom);
298
324
for (unsigned eidx= 0 ; eidx < array->size (); eidx++)
299
325
{
300
- Json_dom * child= (*array)[eidx];
301
- if (add_if_missing (child, duplicates, result))
326
+ Json_dom *child= (*array)[eidx];
327
+ // Now recurse and add the child and values under it.
328
+ if (find_child_doms (child, path_leg, auto_wrap, only_need_one,
329
+ duplicates, result))
302
330
return true ; /* purecov: inspected */
303
- if (is_seek_done (result, only_need_one))
304
- return false ; /* purecov: inspected */
305
-
306
- enum_json_type child_type= child->json_type ();
307
- if ((child_type == enum_json_type::J_ARRAY) ||
308
- (child_type == enum_json_type::J_OBJECT))
309
- {
310
- // now recurse and add all objects and arrays under the child
311
- if (child->find_child_doms (path_leg, auto_wrap, only_need_one,
312
- duplicates, result))
313
- return true ; /* purecov: inspected */
314
- }
315
331
} // end of loop through children
316
332
}
317
333
else if (dom_type == enum_json_type::J_OBJECT)
318
334
{
319
- const Json_object *const object=
320
- down_cast<const Json_object *>(this );
321
-
322
- for (Json_object::const_iterator iter= object->begin ();
323
- iter != object->end (); ++iter)
335
+ for (const auto &member : *down_cast<const Json_object *>(dom))
324
336
{
325
- Json_dom *child= iter-> second ;
326
- enum_json_type child_type= child-> json_type ();
327
-
328
- if ( add_if_missing (child, duplicates, result))
337
+ Json_dom *child= member. second ;
338
+ // Now recurse and add the child and values under it.
339
+ if ( find_child_doms (child, path_leg, auto_wrap, only_need_one,
340
+ duplicates, result))
329
341
return true ; /* purecov: inspected */
330
- if (is_seek_done (result, only_need_one))
331
- return false ; /* purecov: inspected */
332
-
333
- if ((child_type == enum_json_type::J_ARRAY) ||
334
- (child_type == enum_json_type::J_OBJECT))
335
- {
336
- // now recurse and add all objects and arrays under the child
337
- if (child->find_child_doms (path_leg, auto_wrap, only_need_one,
338
- duplicates, result))
339
- return true ; /* purecov: inspected */
340
- }
341
342
} // end of loop through children
342
343
}
343
344
@@ -347,7 +348,7 @@ bool Json_dom::find_child_doms(const Json_path_leg *path_leg,
347
348
{
348
349
if (dom_type == enum_json_type::J_OBJECT)
349
350
{
350
- const Json_object * object= down_cast<const Json_object *>(this );
351
+ const auto object= down_cast<const Json_object *>(dom );
351
352
Json_dom *child= object->get (path_leg->get_member_name ());
352
353
353
354
if (child != NULL && add_if_missing (child, duplicates, result))
@@ -360,12 +361,9 @@ bool Json_dom::find_child_doms(const Json_path_leg *path_leg,
360
361
{
361
362
if (dom_type == enum_json_type::J_OBJECT)
362
363
{
363
- const Json_object * object= down_cast<const Json_object *>(this );
364
-
365
- for (Json_object::const_iterator iter= object->begin ();
366
- iter != object->end (); ++iter)
364
+ for (const auto &member : *down_cast<const Json_object *>(dom))
367
365
{
368
- if (add_if_missing (iter-> second , duplicates, result))
366
+ if (add_if_missing (member. second , duplicates, result))
369
367
return true ; /* purecov: inspected */
370
368
if (is_seek_done (result, only_need_one))
371
369
return false ;
@@ -2280,12 +2278,17 @@ bool Json_dom::seek(const Json_seekable_path &path,
2280
2278
duplicates.clear ();
2281
2279
candidates.clear ();
2282
2280
2283
- for (Json_dom_vector::iterator it= hits->begin (); it != hits->end (); ++it)
2281
+ /*
2282
+ On the last path leg, we can stop after the first match if only
2283
+ one match is requested by the caller.
2284
+ */
2285
+ const bool stop_after_first_match=
2286
+ only_need_one && (path_idx == path_leg_count - 1 );
2287
+
2288
+ for (Json_dom *hit : *hits)
2284
2289
{
2285
- if ((*it)->find_child_doms (path_leg, auto_wrap,
2286
- (only_need_one &&
2287
- (path_idx == (path_leg_count-1 ))),
2288
- &duplicates, &candidates))
2290
+ if (find_child_doms (hit, path_leg, auto_wrap, stop_after_first_match,
2291
+ &duplicates, &candidates))
2289
2292
return true ; /* purecov: inspected */
2290
2293
}
2291
2294
0 commit comments