yajl_tree.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (c) 2010-2011 Florian Forster <ff at octo.it>
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /**
  17. * \file yajl_tree.h
  18. *
  19. * Parses JSON data and returns the data in tree form.
  20. *
  21. * \author Florian Forster
  22. * \date August 2010
  23. *
  24. * This interface makes quick parsing and extraction of
  25. * smallish JSON docs trivial:
  26. *
  27. * \include example/parse_config.c
  28. */
  29. #ifndef YAJL_TREE_H
  30. #define YAJL_TREE_H 1
  31. #include "yajl_common.h"
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. /** possible data types that a yajl_val_s can hold */
  36. typedef enum {
  37. yajl_t_string = 1,
  38. yajl_t_number = 2,
  39. yajl_t_object = 3,
  40. yajl_t_array = 4,
  41. yajl_t_true = 5,
  42. yajl_t_false = 6,
  43. yajl_t_null = 7,
  44. /** The any type isn't valid for yajl_val_s.type, but can be
  45. * used as an argument to routines like yajl_tree_get().
  46. */
  47. yajl_t_any = 8
  48. } yajl_type;
  49. #define YAJL_NUMBER_INT_VALID 0x01
  50. #define YAJL_NUMBER_DOUBLE_VALID 0x02
  51. #define YAJL_NUMBER_UINT_VALID 0x04
  52. /** A pointer to a node in the parse tree */
  53. typedef struct yajl_val_s * yajl_val;
  54. /**
  55. * A JSON value representation capable of holding one of the seven
  56. * types above. For "string", "number", "object", and "array"
  57. * additional data is available in the union. The "YAJL_IS_*"
  58. * and "YAJL_GET_*" macros below allow type checking and convenient
  59. * value extraction.
  60. */
  61. struct yajl_val_s
  62. {
  63. /** Type of the value contained. Use the "YAJL_IS_*" macros to check for a
  64. * specific type. */
  65. yajl_type type;
  66. /** Type-specific data. You may use the "YAJL_GET_*" macros to access these
  67. * members. */
  68. union
  69. {
  70. char * string;
  71. struct {
  72. long long i; /*< integer value, if representable. */
  73. unsigned long long ui; /*< unsigned integer value, if representable. */
  74. double d; /*< double value, if representable. */
  75. char *r; /*< unparsed number in string form. */
  76. /** Signals whether the \em i and \em d members are
  77. * valid. See \c YAJL_NUMBER_INT_VALID and
  78. * \c YAJL_NUMBER_DOUBLE_VALID. */
  79. unsigned int flags;
  80. } number;
  81. struct {
  82. const char **keys; /*< Array of keys */
  83. yajl_val *values; /*< Array of values. */
  84. size_t len; /*< Number of key-value-pairs. */
  85. } object;
  86. struct {
  87. yajl_val *values; /*< Array of elements. */
  88. size_t len; /*< Number of elements. */
  89. } array;
  90. } u;
  91. };
  92. /**
  93. * Parse a string.
  94. *
  95. * Parses an null-terminated string containing JSON data and returns a pointer
  96. * to the top-level value (root of the parse tree).
  97. *
  98. * \param input Pointer to a null-terminated utf8 string containing
  99. * JSON data.
  100. * \param error_buffer Pointer to a buffer in which an error message will
  101. * be stored if \em yajl_tree_parse fails, or
  102. * \c NULL. The buffer will be initialized before
  103. * parsing, so its content will be destroyed even if
  104. * \em yajl_tree_parse succeeds.
  105. * \param error_buffer_size Size of the memory area pointed to by
  106. * \em error_buffer_size. If \em error_buffer_size is
  107. * \c NULL, this argument is ignored.
  108. *
  109. * \returns Pointer to the top-level value or \c NULL on error. The memory
  110. * pointed to must be freed using \em yajl_tree_free. In case of an error, a
  111. * null terminated message describing the error in more detail is stored in
  112. * \em error_buffer if it is not \c NULL.
  113. */
  114. YAJL_API yajl_val yajl_tree_parse (const char *input,
  115. char *error_buffer, size_t error_buffer_size);
  116. /**
  117. * Free a parse tree returned by "yajl_tree_parse".
  118. *
  119. * \param v Pointer to a JSON value returned by "yajl_tree_parse". Passing NULL
  120. * is valid and results in a no-op.
  121. */
  122. YAJL_API void yajl_tree_free (yajl_val v);
  123. /**
  124. * Access a nested value inside a tree.
  125. *
  126. * \param parent the node under which you'd like to extract values.
  127. * \param path A null terminated array of strings, each the name of an object key
  128. * \param type the yajl_type of the object you seek, or yajl_t_any if any will do.
  129. *
  130. * \returns a pointer to the found value, or NULL if we came up empty.
  131. *
  132. * Future Ideas: it'd be nice to move path to a string and implement support for
  133. * a teeny tiny micro language here, so you can extract array elements, do things
  134. * like .first and .last, even .length. Inspiration from JSONPath and css selectors?
  135. * No it wouldn't be fast, but that's not what this API is about.
  136. */
  137. YAJL_API yajl_val yajl_tree_get(yajl_val parent, const char ** path, yajl_type type);
  138. /* Various convenience macros to check the type of a `yajl_val` */
  139. #define YAJL_IS_STRING(v) (((v) != NULL) && ((v)->type == yajl_t_string))
  140. #define YAJL_IS_NUMBER(v) (((v) != NULL) && ((v)->type == yajl_t_number))
  141. #define YAJL_IS_INTEGER(v) (YAJL_IS_NUMBER(v) && ((v)->u.number.flags & YAJL_NUMBER_INT_VALID))
  142. #define YAJL_IS_UINTEGER(v) (YAJL_IS_NUMBER(v) && ((v)->u.number.flags & YAJL_NUMBER_UINT_VALID))
  143. #define YAJL_IS_DOUBLE(v) (YAJL_IS_NUMBER(v) && ((v)->u.number.flags & YAJL_NUMBER_DOUBLE_VALID))
  144. #define YAJL_IS_OBJECT(v) (((v) != NULL) && ((v)->type == yajl_t_object))
  145. #define YAJL_IS_ARRAY(v) (((v) != NULL) && ((v)->type == yajl_t_array ))
  146. #define YAJL_IS_TRUE(v) (((v) != NULL) && ((v)->type == yajl_t_true ))
  147. #define YAJL_IS_FALSE(v) (((v) != NULL) && ((v)->type == yajl_t_false ))
  148. #define YAJL_IS_NULL(v) (((v) != NULL) && ((v)->type == yajl_t_null ))
  149. /** Given a yajl_val_string return a ptr to the bare string it contains,
  150. * or NULL if the value is not a string. */
  151. #define YAJL_GET_STRING(v) (YAJL_IS_STRING(v) ? (v)->u.string : NULL)
  152. /** Get the string representation of a number. You should check type first,
  153. * perhaps using YAJL_IS_NUMBER */
  154. #define YAJL_GET_NUMBER(v) ((v)->u.number.r)
  155. /** Get the double representation of a number. You should check type first,
  156. * perhaps using YAJL_IS_DOUBLE */
  157. #define YAJL_GET_DOUBLE(v) ((v)->u.number.d)
  158. /** Get the 64bit (long long) integer representation of a number. You should
  159. * check type first, perhaps using YAJL_IS_INTEGER */
  160. #define YAJL_GET_INTEGER(v) ((v)->u.number.i)
  161. /** Get the 64bit (unsigned long long) unsigned integer representation of a number. You should
  162. * check type first, perhaps using YAJL_IS_UINTEGER */
  163. #define YAJL_GET_UINTEGER(v) ((v)->u.number.ui)
  164. /** Get a pointer to a yajl_val_object or NULL if the value is not an object. */
  165. #define YAJL_GET_OBJECT(v) (YAJL_IS_OBJECT(v) ? &(v)->u.object : NULL)
  166. /** Get a pointer to a yajl_val_array or NULL if the value is not an object. */
  167. #define YAJL_GET_ARRAY(v) (YAJL_IS_ARRAY(v) ? &(v)->u.array : NULL)
  168. #ifdef __cplusplus
  169. }
  170. #endif
  171. #endif /* YAJL_TREE_H */