json_visit.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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_string:
  56. // we already called userfunc above, move on to the next object
  57. return JSON_C_VISIT_RETURN_CONTINUE;
  58. case json_type_object:
  59. {
  60. json_object_object_foreach(jso, key, child)
  61. {
  62. userret = _json_c_visit(child, jso, key, NULL, userfunc, userarg);
  63. if (userret == JSON_C_VISIT_RETURN_POP)
  64. break;
  65. if (userret == JSON_C_VISIT_RETURN_STOP ||
  66. userret == JSON_C_VISIT_RETURN_ERROR)
  67. return userret;
  68. if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
  69. userret != JSON_C_VISIT_RETURN_SKIP)
  70. {
  71. fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
  72. return JSON_C_VISIT_RETURN_ERROR;
  73. }
  74. }
  75. break;
  76. }
  77. case json_type_array:
  78. {
  79. size_t array_len = json_object_array_length(jso);
  80. size_t ii;
  81. for (ii = 0; ii < array_len; ii++)
  82. {
  83. json_object *child = json_object_array_get_idx(jso, ii);
  84. userret = _json_c_visit(child, jso, NULL, &ii, userfunc, userarg);
  85. if (userret == JSON_C_VISIT_RETURN_POP)
  86. break;
  87. if (userret == JSON_C_VISIT_RETURN_STOP ||
  88. userret == JSON_C_VISIT_RETURN_ERROR)
  89. return userret;
  90. if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
  91. userret != JSON_C_VISIT_RETURN_SKIP)
  92. {
  93. fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
  94. return JSON_C_VISIT_RETURN_ERROR;
  95. }
  96. }
  97. break;
  98. }
  99. default:
  100. fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", json_object_get_type(jso));
  101. return JSON_C_VISIT_RETURN_ERROR;
  102. }
  103. // Call userfunc for the second type on container types, after all
  104. // members of the container have been visited.
  105. // Non-container types will have already returned before this point.
  106. userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg);
  107. switch(userret)
  108. {
  109. case JSON_C_VISIT_RETURN_SKIP:
  110. case JSON_C_VISIT_RETURN_POP:
  111. // These are not really sensible during JSON_C_VISIT_SECOND,
  112. // but map them to JSON_C_VISIT_CONTINUE anyway.
  113. // FALLTHROUGH
  114. case JSON_C_VISIT_RETURN_CONTINUE:
  115. return JSON_C_VISIT_RETURN_CONTINUE;
  116. case JSON_C_VISIT_RETURN_STOP:
  117. case JSON_C_VISIT_RETURN_ERROR:
  118. return userret;
  119. default:
  120. fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
  121. return JSON_C_VISIT_RETURN_ERROR;
  122. }
  123. // NOTREACHED
  124. }