You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

json_visit.c 4.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (c) 2016 Eric Haszlakiewicz
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the MIT license. See COPYING for details.
  6. */
  7. #include <stdio.h>
  8. #include "config.h"
  9. #include "json_inttypes.h"
  10. #include "json_object.h"
  11. #include "json_visit.h"
  12. #include "linkhash.h"
  13. static int _json_c_visit(json_object *jso, json_object *parent_jso,
  14. const char *jso_key, size_t *jso_index,
  15. json_c_visit_userfunc *userfunc, void *userarg);
  16. int json_c_visit(json_object *jso, int future_flags,
  17. json_c_visit_userfunc *userfunc, void *userarg)
  18. {
  19. int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg);
  20. switch(ret)
  21. {
  22. case JSON_C_VISIT_RETURN_CONTINUE:
  23. case JSON_C_VISIT_RETURN_SKIP:
  24. case JSON_C_VISIT_RETURN_POP:
  25. case JSON_C_VISIT_RETURN_STOP:
  26. return 0;
  27. default:
  28. return JSON_C_VISIT_RETURN_ERROR;
  29. }
  30. }
  31. static int _json_c_visit(json_object *jso, json_object *parent_jso,
  32. const char *jso_key, size_t *jso_index,
  33. json_c_visit_userfunc *userfunc, void *userarg)
  34. {
  35. int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg);
  36. switch(userret)
  37. {
  38. case JSON_C_VISIT_RETURN_CONTINUE:
  39. break;
  40. case JSON_C_VISIT_RETURN_SKIP:
  41. case JSON_C_VISIT_RETURN_POP:
  42. case JSON_C_VISIT_RETURN_STOP:
  43. case JSON_C_VISIT_RETURN_ERROR:
  44. return userret;
  45. default:
  46. fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
  47. return JSON_C_VISIT_RETURN_ERROR;
  48. }
  49. switch(json_object_get_type(jso))
  50. {
  51. case json_type_null:
  52. case json_type_boolean:
  53. case json_type_double:
  54. case json_type_int:
  55. case json_type_uint:
  56. case json_type_string:
  57. // we already called userfunc above, move on to the next object
  58. return JSON_C_VISIT_RETURN_CONTINUE;
  59. case json_type_object:
  60. {
  61. json_object_object_foreach(jso, key, child)
  62. {
  63. userret = _json_c_visit(child, jso, key, NULL, userfunc, userarg);
  64. if (userret == JSON_C_VISIT_RETURN_POP)
  65. break;
  66. if (userret == JSON_C_VISIT_RETURN_STOP ||
  67. userret == JSON_C_VISIT_RETURN_ERROR)
  68. return userret;
  69. if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
  70. userret != JSON_C_VISIT_RETURN_SKIP)
  71. {
  72. fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
  73. return JSON_C_VISIT_RETURN_ERROR;
  74. }
  75. }
  76. break;
  77. }
  78. case json_type_array:
  79. {
  80. size_t array_len = json_object_array_length(jso);
  81. size_t ii;
  82. for (ii = 0; ii < array_len; ii++)
  83. {
  84. json_object *child = json_object_array_get_idx(jso, ii);
  85. userret = _json_c_visit(child, jso, NULL, &ii, userfunc, userarg);
  86. if (userret == JSON_C_VISIT_RETURN_POP)
  87. break;
  88. if (userret == JSON_C_VISIT_RETURN_STOP ||
  89. userret == JSON_C_VISIT_RETURN_ERROR)
  90. return userret;
  91. if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
  92. userret != JSON_C_VISIT_RETURN_SKIP)
  93. {
  94. fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
  95. return JSON_C_VISIT_RETURN_ERROR;
  96. }
  97. }
  98. break;
  99. }
  100. default:
  101. fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", json_object_get_type(jso));
  102. return JSON_C_VISIT_RETURN_ERROR;
  103. }
  104. // Call userfunc for the second type on container types, after all
  105. // members of the container have been visited.
  106. // Non-container types will have already returned before this point.
  107. userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg);
  108. switch(userret)
  109. {
  110. case JSON_C_VISIT_RETURN_SKIP:
  111. case JSON_C_VISIT_RETURN_POP:
  112. // These are not really sensible during JSON_C_VISIT_SECOND,
  113. // but map them to JSON_C_VISIT_CONTINUE anyway.
  114. // FALLTHROUGH
  115. case JSON_C_VISIT_RETURN_CONTINUE:
  116. return JSON_C_VISIT_RETURN_CONTINUE;
  117. case JSON_C_VISIT_RETURN_STOP:
  118. case JSON_C_VISIT_RETURN_ERROR:
  119. return userret;
  120. default:
  121. fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
  122. return JSON_C_VISIT_RETURN_ERROR;
  123. }
  124. // NOTREACHED
  125. }