jer_decoder.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
7 #include <etsi_its_cam_ts_coding/jer_support.h> /* JER/JSON parsing support */
8 
9 
10 /*
11  * Decode the jer encoding of a given type.
12  */
14 jer_decode(const asn_codec_ctx_t *opt_codec_ctx,
15  const asn_TYPE_descriptor_t *td, void **struct_ptr,
16  const void *buffer, size_t size) {
17  asn_codec_ctx_t s_codec_ctx;
18 
19  /*
20  * Stack checker requires that the codec context
21  * must be allocated on the stack.
22  */
23  if(opt_codec_ctx) {
24  if(opt_codec_ctx->max_stack_size) {
25  s_codec_ctx = *opt_codec_ctx;
26  opt_codec_ctx = &s_codec_ctx;
27  }
28  } else {
29  /* If context is not given, be security-conscious anyway */
30  memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
32  opt_codec_ctx = &s_codec_ctx;
33  }
34 
35  /*
36  * Invoke type-specific decoder.
37  */
38  return td->op->jer_decoder(opt_codec_ctx, td, 0, struct_ptr, buffer, size);
39 }
40 
41 
42 
43 struct jer__cb_arg {
45  size_t chunk_size;
46  const void *chunk_buf;
48 };
49 
50 static int
51 jer__token_cb(pjson_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {
52  struct jer__cb_arg *arg = (struct jer__cb_arg *)key;
53  arg->chunk_type = type;
54  arg->chunk_size = _chunk_size;
55  arg->chunk_buf = _chunk_data;
56  arg->callback_not_invoked = 0;
57  return -1; /* Terminate the JSON parsing */
58 }
59 
60 /*
61  * Fetch the next token from the JER/JSON stream.
62  */
63 ssize_t
64 jer_next_token(int *stateContext, const void *buffer, size_t size, pjer_chunk_type_e *ch_type) {
65  struct jer__cb_arg arg;
66  int new_stateContext = *stateContext;
67  ssize_t ret;
68 
69  arg.callback_not_invoked = 1;
70  ret = pjson_parse(&new_stateContext, buffer, size, jer__token_cb, &arg);
71  if(ret < 0) return -1;
72  if(arg.callback_not_invoked) {
73  assert(ret == 0); /* No data was consumed */
74  *ch_type = PJER_WMORE;
75  return 0; /* Try again with more data */
76  } else {
77  assert(arg.chunk_size);
78  assert(arg.chunk_buf == buffer);
79  }
80 
81  /*
82  * Translate the JSON chunk types into more convenient ones.
83  */
84  switch(arg.chunk_type) {
85  case PJSON_TEXT:
86  *ch_type = PJER_TEXT;
87  break;
88  case PJSON_KEY:
89  *ch_type = PJER_WMORE;
90  break;
91  case PJSON_DLM:
92  *ch_type = PJER_DLM;
93  break;
94  case PJSON_KEY_END:
95  *ch_type = PJER_KEY;
96  break;
97  case PJSON_VALUE_END:
98  *ch_type = PJER_VALUE;
99  break;
100  default:
101  return 0; /* Want more */
102  }
103 
104  *stateContext = new_stateContext;
105  return arg.chunk_size;
106 }
107 
108 #define LCBRAC 0x7b /* '{' */
109 #define RCBRAC 0x7d /* '}' */
110 #define CQUOTE 0x22 /* '"' */
111 #define CCOMMA 0x2c /* ',' */
112 #define LSBRAC 0x5b /* '[' */
113 #define RSBRAC 0x5d /* ']' */
114 
116 jer_check_sym(const void *buf_ptr, int size, const char *need_key) {
117  const char *buf = (const char *)buf_ptr;
118  const char *end;
119 
120  if(!need_key) { /* expected data end */
121  switch(buf[size-1]) {
122  case LCBRAC:
123  return JCK_OSTART;
124  case RCBRAC:
125  return JCK_OEND;
126  case LSBRAC:
127  return JCK_ASTART;
128  case RSBRAC:
129  return JCK_AEND;
130  case CCOMMA:
131  return JCK_COMMA;
132  default:
133  return JCK_UNKNOWN;
134  }
135  }
136 
137  if(size < 2 ||
138  (buf[0] != CQUOTE || buf[size-1] != CQUOTE)) {
139  if(size >= 2)
140  ASN_DEBUG("Broken JSON key: \"%c...%c\"",
141  buf[0], buf[size - 1]);
142  return JCK_BROKEN;
143  }
144 
145  buf++; /* advance past first quote */
146  size -= 2; /* strip quotes */
147 
148  /*
149  * Determine the key name.
150  */
151  for(end = buf + size; buf < end; buf++, need_key++) {
152  int b = *buf, n = *need_key;
153  if(b != n) {
154  if(n == 0) {
155  switch(b) {
156  case 0x09: case 0x0a: case 0x0c: case 0x0d:
157  case 0x20:
158  /* "abc def": accept whitespace */
159  return JCK_KEY;
160  }
161  }
162  return JCK_UNKNOWN;
163  }
164  if(b == 0)
165  return JCK_BROKEN; /* Embedded 0 in buf?! */
166  }
167  if(*need_key)
168  return JCK_UNKNOWN;
169 
170  return JCK_KEY;
171 }
172 
173 
174 #undef ADVANCE
175 #define ADVANCE(num_bytes) do { \
176  size_t num = (num_bytes); \
177  buf_ptr = ((const char *)buf_ptr) + num; \
178  size -= num; \
179  consumed_myself += num; \
180  } while(0)
181 
182 #undef RETURN
183 #define RETURN(_code) do { \
184  rval.code = _code; \
185  rval.consumed = consumed_myself; \
186  if(rval.code != RC_OK) \
187  ASN_DEBUG("Failed with %d", rval.code); \
188  return rval; \
189  } while(0)
190 
191 #define JER_GOT_BODY(chunk_buf, chunk_size, size) do { \
192  ssize_t converted_size = body_receiver \
193  (struct_key, chunk_buf, chunk_size, \
194  (size_t)chunk_size <= size); \
195  if(converted_size == -1) RETURN(RC_FAIL); \
196  if(converted_size == 0 \
197  && size == (size_t)chunk_size) \
198  RETURN(RC_WMORE); \
199  chunk_size = converted_size; \
200  } while(0)
201 #define JER_GOT_EMPTY() do { \
202  if(body_receiver(struct_key, 0, 0, size > 0) == -1) \
203  RETURN(RC_FAIL); \
204  } while(0)
205 
206 /*
207  * Generalized function for decoding the primitive values.
208  */
210 jer_decode_general(const asn_codec_ctx_t *opt_codec_ctx,
211  asn_struct_ctx_t *ctx, /* Type decoder context */
212  void *struct_key,
213  const void *buf_ptr, size_t size,
214  int (*opt_unexpected_key_decoder)
215  (void *struct_key, const void *chunk_buf, size_t chunk_size),
216  ssize_t (*body_receiver)
217  (void *struct_key, const void *chunk_buf, size_t chunk_size,
218  int have_more)
219  ) {
220 
221  asn_dec_rval_t rval;
222  ssize_t consumed_myself = 0;
223 
224  (void)opt_codec_ctx;
225  (void)opt_unexpected_key_decoder;
226 
227  /*
228  * Phases of jer/JSON processing:
229  * Phase 0: Check that the opening key matches our expectations.
230  * Phase 1: Processing body and reacting on closing token.
231  */
232  if(ctx->phase > 1) RETURN(RC_FAIL);
233  for(;;) {
234  pjer_chunk_type_e ch_type; /* jer chunk type */
235  ssize_t ch_size; /* Chunk size */
236 
237  /*
238  * Get the next part of the JSON stream.
239  */
240  ch_size = jer_next_token(&ctx->context, buf_ptr, size,
241  &ch_type);
242  if(ch_size == -1) {
243  RETURN(RC_FAIL);
244  } else {
245  switch(ch_type) {
246  case PJER_WMORE:
247  RETURN(RC_WMORE);
248  case PJER_TEXT:
249  ADVANCE(ch_size);
250  continue;
251  case PJER_VALUE:
252  JER_GOT_BODY(buf_ptr, ch_size, size);
253  ADVANCE(ch_size);
254  ADVANCE(jer_whitespace_span(buf_ptr, size)); /* skip whitespace */
255  ch_size = 1;
256  case PJER_KEY:
257  case PJER_DLM:
258  break; /* Check the rest down there */
259  }
260  }
261 
262  ctx->phase = 2; /* Phase out */
263  RETURN(RC_OK);
264 
265  break; /* Dark and mysterious things have just happened */
266  }
267 
268  RETURN(RC_FAIL);
269 }
270 
271 
272 size_t
274  const char *p = (const char *)chunk_buf;
275  const char *pend = (p == NULL)? NULL : p + chunk_size;
276 
277  for(; p < pend; p++) {
278  switch(*p) {
279  /* X.693, #8.1.4
280  * HORISONTAL TAB (9)
281  * LINE FEED (10)
282  * CARRIAGE RETURN (13)
283  * SPACE (32)
284  */
285  case 0x09: case 0x0a: case 0x0d: case 0x20:
286  continue;
287  default:
288  break;
289  }
290  break;
291  }
292  return (p - (const char *)chunk_buf);
293 }
294 
295 /*
296  * This is a vastly simplified, non-validating JSON tree skipper. [TODO]
297  */
298 int
300  assert(*depth > 0);
301  switch(scv) {
302  case JCK_KEY:
303  ++(*depth);
304  return 0;
305  case JCK_COMMA:
306  case JCK_OEND:
307  case JCK_UNKNOWN:
308  if(--(*depth) == 0)
309  return (scv == JCK_OEND) ? 2 : 1;
310  return 0;
311  default:
312  return -1;
313  }
314 }
asn_struct_ctx_s
Definition: constr_TYPE.h:29
RCBRAC
#define RCBRAC
Definition: jer_decoder.c:109
jer_support.h
PJSON_VALUE_END
@ PJSON_VALUE_END
Definition: jer_support.h:35
PJER_TEXT
@ PJER_TEXT
Definition: jer_decoder.h:68
PJSON_DLM
@ PJSON_DLM
Definition: jer_support.h:29
JCK_COMMA
@ JCK_COMMA
Definition: jer_decoder.h:84
jer_whitespace_span
size_t jer_whitespace_span(const void *chunk_buf, size_t chunk_size)
Definition: jer_decoder.c:273
JCK_BROKEN
@ JCK_BROKEN
Definition: jer_decoder.h:81
asn_struct_ctx_s::phase
short phase
Definition: constr_TYPE.h:30
PJSON_TEXT
@ PJSON_TEXT
Definition: jer_support.h:26
CQUOTE
#define CQUOTE
Definition: jer_decoder.c:110
RC_WMORE
@ RC_WMORE
Definition: asn_codecs.h:83
jer__cb_arg
Definition: jer_decoder.c:43
pjson_chunk_type_e
pjson_chunk_type_e
Definition: jer_support.h:25
JCK_OEND
@ JCK_OEND
Definition: jer_decoder.h:86
pjer_chunk_type_e
enum pjer_chunk_type pjer_chunk_type_e
ber_tlv_len_t
ssize_t ber_tlv_len_t
Definition: ber_tlv_length.h:12
JCK_UNKNOWN
@ JCK_UNKNOWN
Definition: jer_decoder.h:82
asn_TYPE_descriptor_s
Definition: constr_TYPE.h:224
RETURN
#define RETURN(_code)
Definition: jer_decoder.c:183
JER_GOT_BODY
#define JER_GOT_BODY(chunk_buf, chunk_size, size)
Definition: jer_decoder.c:191
JCK_KEY
@ JCK_KEY
Definition: jer_decoder.h:83
PJSON_KEY
@ PJSON_KEY
Definition: jer_support.h:27
RC_OK
@ RC_OK
Definition: asn_codecs.h:82
jer__token_cb
static int jer__token_cb(pjson_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key)
Definition: jer_decoder.c:51
asn_TYPE_descriptor_s::op
asn_TYPE_operation_t * op
Definition: constr_TYPE.h:232
asn_struct_ctx_s::context
int context
Definition: constr_TYPE.h:32
PJER_DLM
@ PJER_DLM
Definition: jer_decoder.h:71
jer_decode
asn_dec_rval_t jer_decode(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td, void **struct_ptr, const void *buffer, size_t size)
Definition: jer_decoder.c:14
pjson_parse
ssize_t pjson_parse(int *_stateContext, const void *_buf, size_t _size, pjson_callback_f *cb, void *_key)
Definition: jer_support.c:79
LCBRAC
#define LCBRAC
Definition: jer_decoder.c:108
jer__cb_arg::chunk_size
size_t chunk_size
Definition: jer_decoder.c:45
jer_skip_unknown
int jer_skip_unknown(jer_check_sym_e scv, ber_tlv_len_t *depth)
Definition: jer_decoder.c:299
PJER_VALUE
@ PJER_VALUE
Definition: jer_decoder.h:70
RSBRAC
#define RSBRAC
Definition: jer_decoder.c:113
asn_TYPE_operation_s::jer_decoder
jer_type_decoder_f * jer_decoder
Definition: constr_TYPE.h:193
key
static void ssize_t void * key
Definition: asn_internal.h:96
jer_decode_general
asn_dec_rval_t jer_decode_general(const asn_codec_ctx_t *opt_codec_ctx, asn_struct_ctx_t *ctx, void *struct_key, const void *buf_ptr, size_t size, int(*opt_unexpected_key_decoder)(void *struct_key, const void *chunk_buf, size_t chunk_size), ssize_t(*body_receiver)(void *struct_key, const void *chunk_buf, size_t chunk_size, int have_more))
Definition: jer_decoder.c:210
asn_internal.h
JCK_ASTART
@ JCK_ASTART
Definition: jer_decoder.h:87
asn_codec_ctx_s
Definition: asn_codecs.h:23
jer_next_token
ssize_t jer_next_token(int *stateContext, const void *buffer, size_t size, pjer_chunk_type_e *ch_type)
Definition: jer_decoder.c:64
ADVANCE
#define ADVANCE(num_bytes)
Definition: jer_decoder.c:175
asn_dec_rval_s
Definition: asn_codecs.h:86
PJER_KEY
@ PJER_KEY
Definition: jer_decoder.h:69
jer__cb_arg::chunk_buf
const void * chunk_buf
Definition: jer_decoder.c:46
CCOMMA
#define CCOMMA
Definition: jer_decoder.c:111
asn_application.h
ASN__DEFAULT_STACK_MAX
#define ASN__DEFAULT_STACK_MAX
Definition: asn_internal.h:155
asn_codec_ctx_s::max_stack_size
size_t max_stack_size
Definition: asn_codecs.h:35
LSBRAC
#define LSBRAC
Definition: jer_decoder.c:112
JCK_AEND
@ JCK_AEND
Definition: jer_decoder.h:88
jer_check_sym
jer_check_sym_e jer_check_sym(const void *buf_ptr, int size, const char *need_key)
Definition: jer_decoder.c:116
jer_check_sym_e
enum jer_check_sym jer_check_sym_e
jer__cb_arg::chunk_type
pjson_chunk_type_e chunk_type
Definition: jer_decoder.c:44
PJER_WMORE
@ PJER_WMORE
Definition: jer_decoder.h:67
jer__cb_arg::callback_not_invoked
int callback_not_invoked
Definition: jer_decoder.c:47
PJSON_KEY_END
@ PJSON_KEY_END
Definition: jer_support.h:34
RC_FAIL
@ RC_FAIL
Definition: asn_codecs.h:84
JCK_OSTART
@ JCK_OSTART
Definition: jer_decoder.h:85


etsi_its_cam_ts_coding
Author(s): Jean-Pierre Busch , Guido Küppers , Lennart Reiher
autogenerated on Sun May 18 2025 02:21:23