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

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