lejp.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "libwebsockets.h"
  2. struct lejp_ctx;
  3. #ifndef ARRAY_SIZE
  4. #define ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
  5. #endif
  6. #define LEJP_FLAG_WS_KEEP 64
  7. #define LEJP_FLAG_WS_COMMENTLINE 32
  8. enum lejp_states {
  9. LEJP_IDLE = 0,
  10. LEJP_MEMBERS = 1,
  11. LEJP_M_P = 2,
  12. LEJP_MP_STRING = LEJP_FLAG_WS_KEEP | 3,
  13. LEJP_MP_STRING_ESC = LEJP_FLAG_WS_KEEP | 4,
  14. LEJP_MP_STRING_ESC_U1 = LEJP_FLAG_WS_KEEP | 5,
  15. LEJP_MP_STRING_ESC_U2 = LEJP_FLAG_WS_KEEP | 6,
  16. LEJP_MP_STRING_ESC_U3 = LEJP_FLAG_WS_KEEP | 7,
  17. LEJP_MP_STRING_ESC_U4 = LEJP_FLAG_WS_KEEP | 8,
  18. LEJP_MP_DELIM = 9,
  19. LEJP_MP_VALUE = 10,
  20. LEJP_MP_VALUE_NUM_INT = LEJP_FLAG_WS_KEEP | 11,
  21. LEJP_MP_VALUE_NUM_EXP = LEJP_FLAG_WS_KEEP | 12,
  22. LEJP_MP_VALUE_TOK = LEJP_FLAG_WS_KEEP | 13,
  23. LEJP_MP_COMMA_OR_END = 14,
  24. LEJP_MP_ARRAY_END = 15,
  25. };
  26. enum lejp_reasons {
  27. LEJP_CONTINUE = -1,
  28. LEJP_REJECT_IDLE_NO_BRACE = -2,
  29. LEJP_REJECT_MEMBERS_NO_CLOSE = -3,
  30. LEJP_REJECT_MP_NO_OPEN_QUOTE = -4,
  31. LEJP_REJECT_MP_STRING_UNDERRUN = -5,
  32. LEJP_REJECT_MP_ILLEGAL_CTRL = -6,
  33. LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC = -7,
  34. LEJP_REJECT_ILLEGAL_HEX = -8,
  35. LEJP_REJECT_MP_DELIM_MISSING_COLON = -9,
  36. LEJP_REJECT_MP_DELIM_BAD_VALUE_START = -10,
  37. LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC = -11,
  38. LEJP_REJECT_MP_VAL_NUM_FORMAT = -12,
  39. LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP = -13,
  40. LEJP_REJECT_MP_VAL_TOK_UNKNOWN = -14,
  41. LEJP_REJECT_MP_C_OR_E_UNDERF = -15,
  42. LEJP_REJECT_MP_C_OR_E_NOTARRAY = -16,
  43. LEJP_REJECT_MP_ARRAY_END_MISSING = -17,
  44. LEJP_REJECT_STACK_OVERFLOW = -18,
  45. LEJP_REJECT_MP_DELIM_ISTACK = -19,
  46. LEJP_REJECT_NUM_TOO_LONG = -20,
  47. LEJP_REJECT_MP_C_OR_E_NEITHER = -21,
  48. LEJP_REJECT_UNKNOWN = -22,
  49. LEJP_REJECT_CALLBACK = -23
  50. };
  51. #define LEJP_FLAG_CB_IS_VALUE 64
  52. enum lejp_callbacks {
  53. LEJPCB_CONSTRUCTED = 0,
  54. LEJPCB_DESTRUCTED = 1,
  55. LEJPCB_START = 2,
  56. LEJPCB_COMPLETE = 3,
  57. LEJPCB_FAILED = 4,
  58. LEJPCB_PAIR_NAME = 5,
  59. LEJPCB_VAL_TRUE = LEJP_FLAG_CB_IS_VALUE | 6,
  60. LEJPCB_VAL_FALSE = LEJP_FLAG_CB_IS_VALUE | 7,
  61. LEJPCB_VAL_NULL = LEJP_FLAG_CB_IS_VALUE | 8,
  62. LEJPCB_VAL_NUM_INT = LEJP_FLAG_CB_IS_VALUE | 9,
  63. LEJPCB_VAL_NUM_FLOAT = LEJP_FLAG_CB_IS_VALUE | 10,
  64. LEJPCB_VAL_STR_START = 11, /* notice handle separately */
  65. LEJPCB_VAL_STR_CHUNK = LEJP_FLAG_CB_IS_VALUE | 12,
  66. LEJPCB_VAL_STR_END = LEJP_FLAG_CB_IS_VALUE | 13,
  67. LEJPCB_ARRAY_START = 14,
  68. LEJPCB_ARRAY_END = 15,
  69. LEJPCB_OBJECT_START = 16,
  70. LEJPCB_OBJECT_END = 17
  71. };
  72. /**
  73. * _lejp_callback() - User parser actions
  74. * \param ctx: LEJP context
  75. * \param reason: Callback reason
  76. *
  77. * Your user callback is associated with the context at construction time,
  78. * and receives calls as the parsing progresses.
  79. *
  80. * All of the callbacks may be ignored and just return 0.
  81. *
  82. * The reasons it might get called, found in @reason, are:
  83. *
  84. * LEJPCB_CONSTRUCTED: The context was just constructed... you might want to
  85. * perform one-time allocation for the life of the context.
  86. *
  87. * LEJPCB_DESTRUCTED: The context is being destructed... if you made any
  88. * allocations at construction-time, you can free them now
  89. *
  90. * LEJPCB_START: Parsing is beginning at the first byte of input
  91. *
  92. * LEJPCB_COMPLETE: Parsing has completed successfully. You'll get a 0 or
  93. * positive return code from lejp_parse indicating the
  94. * amount of unused bytes left in the input buffer
  95. *
  96. * LEJPCB_FAILED: Parsing failed. You'll get a negative error code
  97. * returned from lejp_parse
  98. *
  99. * LEJPCB_PAIR_NAME: When a "name":"value" pair has had the name parsed,
  100. * this callback occurs. You can find the new name at
  101. * the end of ctx->path[]
  102. *
  103. * LEJPCB_VAL_TRUE: The "true" value appeared
  104. *
  105. * LEJPCB_VAL_FALSE: The "false" value appeared
  106. *
  107. * LEJPCB_VAL_NULL: The "null" value appeared
  108. *
  109. * LEJPCB_VAL_NUM_INT: A string representing an integer is in ctx->buf
  110. *
  111. * LEJPCB_VAL_NUM_FLOAT: A string representing a float is in ctx->buf
  112. *
  113. * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet
  114. *
  115. * LEJPCB_VAL_STR_CHUNK: We parsed LEJP_STRING_CHUNK -1 bytes of string data in
  116. * ctx->buf, which is as much as we can buffer, so we are
  117. * spilling it. If all your strings are less than
  118. * LEJP_STRING_CHUNK - 1 bytes, you will never see this
  119. * callback.
  120. *
  121. * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the
  122. * string is in ctx->buf.
  123. *
  124. * LEJPCB_ARRAY_START: An array started
  125. *
  126. * LEJPCB_ARRAY_END: An array ended
  127. *
  128. * LEJPCB_OBJECT_START: An object started
  129. *
  130. * LEJPCB_OBJECT_END: An object ended
  131. */
  132. LWS_EXTERN char _lejp_callback(struct lejp_ctx *ctx, char reason);
  133. typedef char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
  134. #ifndef LEJP_MAX_DEPTH
  135. #define LEJP_MAX_DEPTH 12
  136. #endif
  137. #ifndef LEJP_MAX_INDEX_DEPTH
  138. #define LEJP_MAX_INDEX_DEPTH 5
  139. #endif
  140. #ifndef LEJP_MAX_PATH
  141. #define LEJP_MAX_PATH 128
  142. #endif
  143. #ifndef LEJP_STRING_CHUNK
  144. /* must be >= 30 to assemble floats */
  145. #define LEJP_STRING_CHUNK 255
  146. #endif
  147. enum num_flags {
  148. LEJP_SEEN_MINUS = (1 << 0),
  149. LEJP_SEEN_POINT = (1 << 1),
  150. LEJP_SEEN_POST_POINT = (1 << 2),
  151. LEJP_SEEN_EXP = (1 << 3)
  152. };
  153. struct _lejp_stack {
  154. char s; /* lejp_state stack*/
  155. char p; /* path length */
  156. char i; /* index array length */
  157. char b; /* user bitfield */
  158. };
  159. struct lejp_ctx {
  160. /* sorted by type for most compact alignment
  161. *
  162. * pointers
  163. */
  164. char (*callback)(struct lejp_ctx *ctx, char reason);
  165. void *user;
  166. const char * const *paths;
  167. /* arrays */
  168. struct _lejp_stack st[LEJP_MAX_DEPTH];
  169. unsigned short i[LEJP_MAX_INDEX_DEPTH]; /* index array */
  170. unsigned short wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
  171. char path[LEJP_MAX_PATH];
  172. char buf[LEJP_STRING_CHUNK];
  173. /* int */
  174. unsigned int line;
  175. /* short */
  176. unsigned short uni;
  177. /* char */
  178. unsigned char npos;
  179. unsigned char dcount;
  180. unsigned char f;
  181. unsigned char sp; /* stack head */
  182. unsigned char ipos; /* index stack depth */
  183. unsigned char ppos;
  184. unsigned char count_paths;
  185. unsigned char path_match;
  186. unsigned char path_match_len;
  187. unsigned char wildcount;
  188. };
  189. LWS_VISIBLE LWS_EXTERN void
  190. lejp_construct(struct lejp_ctx *ctx,
  191. char (*callback)(struct lejp_ctx *ctx, char reason), void *user,
  192. const char * const *paths, unsigned char paths_count);
  193. LWS_VISIBLE LWS_EXTERN void
  194. lejp_destruct(struct lejp_ctx *ctx);
  195. LWS_VISIBLE LWS_EXTERN int
  196. lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len);
  197. LWS_VISIBLE LWS_EXTERN void
  198. lejp_change_callback(struct lejp_ctx *ctx,
  199. char (*callback)(struct lejp_ctx *ctx, char reason));
  200. LWS_VISIBLE LWS_EXTERN int
  201. lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);