ITS
per_opentype.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include <asn_internal.h>
6 #include <per_support.h>
7 #include <constr_TYPE.h>
8 #include <per_opentype.h>
9 
10 typedef struct uper_ugot_key {
11  asn_per_data_t oldpd; /* Old per data source */
12  size_t unclaimed;
13  size_t ot_moved; /* Number of bits moved by OT processing */
14  int repeat;
16 
17 static int uper_ugot_refill(asn_per_data_t *pd);
18 static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
20 
21 /*
22  * Encode an "open type field".
23  * #10.1, #10.2
24  */
25 int
27  void *buf;
28  void *bptr;
29  ssize_t size;
30  size_t toGo;
31 
32  ASN_DEBUG("Open type put %s ...", td->name);
33 
34  size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
35  if(size <= 0) return -1;
36 
37  for(bptr = buf, toGo = size; toGo;) {
38  ssize_t maySave = uper_put_length(po, toGo);
39  ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
40  (int)size, td->name, (int)maySave);
41  if(maySave < 0) break;
42  if(per_put_many_bits(po, bptr, maySave * 8)) break;
43  bptr = (char *)bptr + maySave;
44  toGo -= maySave;
45  }
46 
47  FREEMEM(buf);
48  if(toGo) return -1;
49 
50  ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
51  td->name, (long)size);
52 
53  return 0;
54 }
55 
56 static asn_dec_rval_t
58  asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
59  asn_dec_rval_t rv;
60  ssize_t chunk_bytes;
61  int repeat;
62  uint8_t *buf = 0;
63  size_t bufLen = 0;
64  size_t bufSize = 0;
65  asn_per_data_t spd;
66  size_t padding;
67 
69 
70  ASN_DEBUG("Getting open type %s...", td->name);
71 
72  do {
73  chunk_bytes = uper_get_length(pd, -1, &repeat);
74  if(chunk_bytes < 0) {
75  FREEMEM(buf);
77  }
78  if(bufLen + chunk_bytes > bufSize) {
79  void *ptr;
80  bufSize = chunk_bytes + (bufSize << 2);
81  ptr = REALLOC(buf, bufSize);
82  if(!ptr) {
83  FREEMEM(buf);
85  }
86  buf = ptr;
87  }
88  if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
89  FREEMEM(buf);
91  }
92  bufLen += chunk_bytes;
93  } while(repeat);
94 
95  ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
96  (long)bufLen);
97 
98  memset(&spd, 0, sizeof(spd));
99  spd.buffer = buf;
100  spd.nbits = bufLen << 3;
101 
103  rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
105 
106  if(rv.code == RC_OK) {
107  /* Check padding validity */
108  padding = spd.nbits - spd.nboff;
109  if ((padding < 8 ||
110  /* X.691#10.1.3 */
111  (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
112  per_get_few_bits(&spd, padding) == 0) {
113  /* Everything is cool */
114  FREEMEM(buf);
115  return rv;
116  }
117  FREEMEM(buf);
118  if(padding >= 8) {
119  ASN_DEBUG("Too large padding %d in open type", (int)padding);
121  } else {
122  ASN_DEBUG("Non-zero padding");
124  }
125  } else {
126  FREEMEM(buf);
127  /* rv.code could be RC_WMORE, nonsense in this context */
128  rv.code = RC_FAIL; /* Noone would give us more */
129  }
130 
131  return rv;
132 }
133 
136  asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
137  uper_ugot_key arg;
138  asn_dec_rval_t rv;
139  ssize_t padding;
140 
142 
143  ASN_DEBUG("Getting open type %s from %s", td->name,
144  per_data_string(pd));
145  arg.oldpd = *pd;
146  arg.unclaimed = 0;
147  arg.ot_moved = 0;
148  arg.repeat = 1;
149  pd->refill = uper_ugot_refill;
150  pd->refill_key = &arg;
151  pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
152  pd->moved = 0; /* This now counts the open type size in bits */
153 
155  rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
157 
158 #define UPDRESTOREPD do { \
159  /* buffer and nboff are valid, preserve them. */ \
160  pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
161  pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
162  pd->refill = arg.oldpd.refill; \
163  pd->refill_key = arg.oldpd.refill_key; \
164  } while(0)
165 
166  if(rv.code != RC_OK) {
167  UPDRESTOREPD;
168  return rv;
169  }
170 
171  ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
172  per_data_string(pd),
173  per_data_string(&arg.oldpd),
174  (int)arg.unclaimed, (int)arg.repeat);
175 
176  padding = pd->moved % 8;
177  if(padding) {
178  int32_t pvalue;
179  if(padding > 7) {
180  ASN_DEBUG("Too large padding %d in open type",
181  (int)padding);
182  rv.code = RC_FAIL;
183  UPDRESTOREPD;
184  return rv;
185  }
186  padding = 8 - padding;
187  ASN_DEBUG("Getting padding of %d bits", (int)padding);
188  pvalue = per_get_few_bits(pd, padding);
189  switch(pvalue) {
190  case -1:
191  ASN_DEBUG("Padding skip failed");
192  UPDRESTOREPD;
194  case 0: break;
195  default:
196  ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
197  (int)padding, (int)pvalue);
198  UPDRESTOREPD;
200  }
201  }
202  if(pd->nboff != pd->nbits) {
203  ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
205  if(1) {
206  UPDRESTOREPD;
208  } else {
209  arg.unclaimed += pd->nbits - pd->nboff;
210  }
211  }
212 
213  /* Adjust pd back so it points to original data */
214  UPDRESTOREPD;
215 
216  /* Skip data not consumed by the decoder */
217  if(arg.unclaimed) {
218  ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
219  switch(per_skip_bits(pd, arg.unclaimed)) {
220  case -1:
221  ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
223  case 0:
224  ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
225  break;
226  default:
227  /* Padding must be blank */
228  ASN_DEBUG("Non-blank unconsumed padding");
230  }
231  arg.unclaimed = 0;
232  }
233 
234  if(arg.repeat) {
235  ASN_DEBUG("Not consumed the whole thing");
236  rv.code = RC_FAIL;
237  return rv;
238  }
239 
240  return rv;
241 }
242 
243 
246  asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
247 
248  return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
249 }
250 
251 int
254  asn_dec_rval_t rv;
255 
256  s_td.name = "<unknown extension>";
258 
259  rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
260  if(rv.code != RC_OK)
261  return -1;
262  else
263  return 0;
264 }
265 
266 /*
267  * Internal functions.
268  */
269 
270 static asn_dec_rval_t
272  asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
273  asn_dec_rval_t rv;
274 
275  (void)ctx;
276  (void)td;
277  (void)constraints;
278  (void)sptr;
279 
280  while(per_get_few_bits(pd, 8) >= 0);
281 
282  rv.code = RC_OK;
283  rv.consumed = pd->moved;
284 
285  return rv;
286 }
287 
288 static int
290  uper_ugot_key *arg = pd->refill_key;
291  ssize_t next_chunk_bytes, next_chunk_bits;
292  ssize_t avail;
293 
294  asn_per_data_t *oldpd = &arg->oldpd;
295 
296  ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
297  (long)pd->moved, (long)oldpd->moved);
298 
299  /* Advance our position to where pd is */
300  oldpd->buffer = pd->buffer;
301  oldpd->nboff = pd->nboff;
302  oldpd->nbits -= pd->moved - arg->ot_moved;
303  oldpd->moved += pd->moved - arg->ot_moved;
304  arg->ot_moved = pd->moved;
305 
306  if(arg->unclaimed) {
307  /* Refill the container */
308  if(per_get_few_bits(oldpd, 1))
309  return -1;
310  if(oldpd->nboff == 0) {
311  assert(0);
312  return -1;
313  }
314  pd->buffer = oldpd->buffer;
315  pd->nboff = oldpd->nboff - 1;
316  pd->nbits = oldpd->nbits;
317  ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
318  (long)pd->moved);
319  return 0;
320  }
321 
322  if(!arg->repeat) {
323  ASN_DEBUG("Want more but refill doesn't have it");
324  return -1;
325  }
326 
327  next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
328  ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
329  (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
330  if(next_chunk_bytes < 0) return -1;
331  if(next_chunk_bytes == 0) {
332  pd->refill = 0; /* No more refills, naturally */
333  assert(!arg->repeat); /* Implementation guarantee */
334  }
335  next_chunk_bits = next_chunk_bytes << 3;
336  avail = oldpd->nbits - oldpd->nboff;
337  if(avail >= next_chunk_bits) {
338  pd->nbits = oldpd->nboff + next_chunk_bits;
339  arg->unclaimed = 0;
340  ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
341  (long)next_chunk_bits, (long)oldpd->moved,
342  (long)oldpd->nboff, (long)oldpd->nbits,
343  (long)(oldpd->nbits - oldpd->nboff));
344  } else {
345  pd->nbits = oldpd->nbits;
346  arg->unclaimed = next_chunk_bits - avail;
347  ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
348  (long)avail, (long)next_chunk_bits,
349  (long)arg->unclaimed);
350  }
351  pd->buffer = oldpd->buffer;
352  pd->nboff = oldpd->nboff;
353  ASN_DEBUG("Refilled pd%s old%s",
354  per_data_string(pd), per_data_string(oldpd));
355  return 0;
356 }
357 
358 static int
359 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
360  int hasNonZeroBits = 0;
361  while(skip_nbits > 0) {
362  int skip;
363 
364  /* per_get_few_bits() is more efficient when nbits <= 24 */
365  if(skip_nbits < 24)
366  skip = skip_nbits;
367  else
368  skip = 24;
369  skip_nbits -= skip;
370 
371  switch(per_get_few_bits(pd, skip)) {
372  case -1: return -1; /* Starving */
373  case 0: continue; /* Skipped empty space */
374  default: hasNonZeroBits = 1; continue;
375  }
376  }
377  return hasNonZeroBits;
378 }
int uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd)
Definition: per_opentype.c:252
static int uper_ugot_refill(asn_per_data_t *pd)
Definition: per_opentype.c:289
struct uper_ugot_key uper_ugot_key
int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits)
Definition: per_support.c:413
asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd)
Definition: per_opentype.c:245
size_t unclaimed
Definition: per_opentype.c:12
#define _ASN_DECODE_STARVED
Definition: asn_codecs.h:98
int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po)
Definition: per_opentype.c:26
static asn_dec_rval_t GCC_NOTUSED uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd)
Definition: per_opentype.c:135
#define REALLOC(oldptr, size)
Definition: asn_internal.h:28
asn_per_data_t oldpd
Definition: per_opentype.c:11
ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length)
Definition: per_support.c:445
static int _ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx)
Definition: asn_internal.h:105
size_t ot_moved
Definition: per_opentype.c:13
#define FREEMEM(ptr)
Definition: asn_internal.h:29
static asn_dec_rval_t uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd)
Definition: per_opentype.c:57
int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align, int get_nbits)
Definition: per_support.c:123
int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits)
Definition: per_support.c:38
static int per_skip_bits(asn_per_data_t *pd, int skip_nbits)
Definition: per_opentype.c:359
size_t consumed
Definition: asn_codecs.h:89
ssize_t uper_get_length(asn_per_data_t *pd, int effective_bound_bits, int *repeat)
Definition: per_support.c:167
#define UPDRESTOREPD
enum asn_dec_rval_code_e code
Definition: asn_codecs.h:88
int(* refill)(struct asn_per_data_s *)
Definition: per_support.h:45
#define ASN_DEBUG_INDENT_ADD(i)
Definition: asn_internal.h:32
static void ASN_DEBUG(const char *fmt,...)
Definition: asn_internal.h:62
void * refill_key
Definition: per_support.h:46
const uint8_t * buffer
Definition: per_support.h:41
per_type_decoder_f * uper_decoder
Definition: constr_TYPE.h:100
char * per_data_string(asn_per_data_t *pd)
Definition: per_support.c:11
#define GCC_NOTUSED
Definition: asn_system.h:105
static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd)
Definition: per_opentype.c:271
#define _ASN_DECODE_FAILED
Definition: asn_codecs.h:91
ssize_t uper_encode_to_new_buffer(struct asn_TYPE_descriptor_s *type_descriptor, asn_per_constraints_t *constraints, void *struct_ptr, void **buffer_r)
Definition: per_encoder.c:68