Motr  M0
xcode.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/bob.h"
24 #include "lib/misc.h" /* M0_SET0 */
25 #include "lib/errno.h"
26 #include "lib/assert.h"
27 #include "lib/memory.h"
28 #include "lib/string.h" /* m0_streq */
29 #include "lib/arith.h" /* m0_align, max_check */
30 #include "xcode/xcode.h"
31 
32 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_XCODE
33 #include "lib/trace.h"
34 
41 static bool is_pointer(const struct m0_xcode_type *xt,
42  const struct m0_xcode_field *field)
43 {
44  return xt->xct_aggr == M0_XA_SEQUENCE && field == &xt->xct_child[1];
45 }
46 
51 static unsigned alignment_mask(const struct m0_xcode_field *field)
52 {
53  unsigned x;
54  const struct m0_xcode_type *ft = field->xf_type;
55 
56  x = ft->xct_aggr == M0_XA_ATOM ? ft->xct_sizeof : 1;
58  return x > 0 ? x - 1 : 0;
59 }
60 
61 static bool field_invariant(const struct m0_xcode_type *xt,
62  const struct m0_xcode_field *field)
63 {
64  return
65  _0C(field->xf_name != NULL) && _0C(field->xf_type != NULL) &&
66  _0C(ergo(xt == &M0_XT_OPAQUE, field->xf_opaque != NULL)) &&
67  _0C(field->xf_offset +
68  (is_pointer(xt, field) ? sizeof(void *) :
69  field->xf_type->xct_sizeof) <= xt->xct_sizeof) &&
70  /* check that alignment is portable. */
71  _0C((field->xf_offset & alignment_mask(field)) == 0);
72 }
73 
75 {
76  size_t prev = 0;
77  uint32_t offset = 0;
78 
79  static const size_t min[M0_XA_NR] = {
80  [M0_XA_RECORD] = 0,
81  [M0_XA_UNION] = 2,
82  [M0_XA_SEQUENCE] = 2,
83  [M0_XA_ARRAY] = 1,
84  [M0_XA_TYPEDEF] = 1,
85  [M0_XA_OPAQUE] = 0,
86  [M0_XA_ATOM] = 0
87  };
88 
89  static const size_t max[M0_XA_NR] = {
90  [M0_XA_RECORD] = ~0ULL,
91  [M0_XA_UNION] = ~0ULL,
92  [M0_XA_SEQUENCE] = 2,
93  [M0_XA_ARRAY] = 1,
94  [M0_XA_TYPEDEF] = 1,
95  [M0_XA_OPAQUE] = 0,
96  [M0_XA_ATOM] = 0
97  };
98 
99  return
100  _0C(0 <= xt->xct_aggr) &&
101  _0C(xt->xct_aggr < M0_XA_NR) &&
102  _0C(xt->xct_nr >= min[xt->xct_aggr]) &&
103  _0C(xt->xct_nr <= max[xt->xct_aggr]) &&
104  m0_forall(i, xt->xct_nr, ({
105  const struct m0_xcode_field *f = &xt->xct_child[i];
106 
107  field_invariant(xt, f) &&
108  /* field doesn't overlap with the previous one */
109  _0C(i == 0 || offset +
110  xt->xct_child[prev].xf_type->xct_sizeof <=
111  f->xf_offset) &&
112  /* field names are unique */
113  m0_forall(j, xt->xct_nr,
114  m0_streq(f->xf_name,
115  xt->xct_child[j].xf_name) ==
116  (i == j)) &&
117  /* union tags are unique. */
118  _0C(ergo(xt->xct_aggr == M0_XA_UNION && i > 0,
119  m0_forall(j, xt->xct_nr,
120  ergo(j > 0,
121  (f->xf_tag == xt->xct_child[j].xf_tag) ==
122  (i == j))))) &&
123  /* update the previous field offset: for UNION all
124  branches follow the first field. */
125  _0C(ergo(i == 0 || xt->xct_aggr != M0_XA_UNION,
126  ({ offset = f->xf_offset;
127  prev = i;
128  true; }) )); }) ) &&
130  xt->xct_child[0].xf_type->xct_aggr == M0_XA_ATOM)) &&
132  xt == &M0_XT_OPAQUE &&
133  xt->xct_sizeof == sizeof (void *))) &&
135  0 <= xt->xct_atype && xt->xct_atype < M0_XAT_NR));
136 }
137 M0_EXPORTED(m0_xcode_type_invariant);
138 
139 #include "xcode/cursor.c"
140 
141 enum xcode_op {
146 };
147 
148 static bool at_array(const struct m0_xcode_cursor *it,
149  const struct m0_xcode_cursor_frame *prev,
150  const struct m0_xcode_obj *par)
151 {
152  return it->xcu_depth > 0 && par->xo_type->xct_aggr == M0_XA_SEQUENCE &&
153  prev->s_fieldno == 1 && prev->s_elno == 0 &&
154  m0_xcode_tag(par) > 0;
155 }
156 
157 static void **allocp(struct m0_xcode_cursor *it, size_t *out)
158 {
159  const struct m0_xcode_cursor_frame *prev;
160  const struct m0_xcode_obj *par;
161  const struct m0_xcode_type *xt;
162  const struct m0_xcode_type *pt;
163  struct m0_xcode_cursor_frame *top;
164  struct m0_xcode_obj *obj;
165  size_t nob;
166  size_t size;
167  void **slot;
168 
169  /*
170  * New memory has to be allocated in 3 cases:
171  *
172  * - to decode topmost object (this is different from sunrpc XDR
173  * interfaces, where topmost object is pre-allocated by the caller);
174  *
175  * - to store an array: a SEQUENCE object has the following in-memory
176  * structure:
177  *
178  * struct {
179  * scalar_t count;
180  * struct elem *data;
181  *
182  * };
183  *
184  * This function allocates count * sizeof(struct elem) bytes to hold
185  * "data";
186  *
187  * - to store an object pointed to by an opaque pointer.
188  *
189  */
190 
191  nob = 0;
193  prev = top - 1;
194  obj = &top->s_obj; /* an object being decoded */
195  par = &prev->s_obj; /* obj's parent object */
196  xt = obj->xo_type;
197  pt = par->xo_type;
198  size = xt->xct_sizeof;
199 
200  if (it->xcu_depth == 0) {
201  /* allocate top-most object */
202  nob = size;
203  slot = &obj->xo_ptr;
204  } else {
205  if (at_array(it, prev, par))
206  /* allocate array */
207  nob = m0_xcode_tag(par) * size;
208  else if (pt->xct_child[prev->s_fieldno].xf_type == &M0_XT_OPAQUE)
209  /*
210  * allocate the object referenced by an opaque
211  * pointer. At this moment "xt" is the type of the
212  * pointed object.
213  */
214  nob = size;
215  slot = m0_xcode_addr(par, prev->s_fieldno, ~0ULL);
216  }
217  *out = nob;
218  return slot;
219 }
220 
221 M0_INTERNAL bool m0_xcode_is_byte_array(const struct m0_xcode_type *xt)
222 {
223  return xt->xct_aggr == M0_XA_SEQUENCE &&
224  xt->xct_child[1].xf_type == &M0_XT_U8;
225 }
226 
227 M0_INTERNAL ssize_t
229  void *(*alloc)(struct m0_xcode_cursor *, size_t))
230 {
231  struct m0_xcode_obj *obj;
232  size_t nob = 0;
233  void **slot;
234 
235  obj = &m0_xcode_cursor_top(it)->s_obj; /* an object being decoded */
236 
237  slot = allocp(it, &nob);
238  if (nob != 0 && *slot == NULL) {
239  M0_ASSERT(obj->xo_ptr == NULL);
240 
241  obj->xo_ptr = *slot = alloc(it, nob);
242  if (obj->xo_ptr == NULL)
243  return M0_ERR(-ENOMEM);
244  }
245  return 0;
246 }
247 
248 M0_INTERNAL void m0_xcode_free_obj(struct m0_xcode_obj *obj)
249 {
250  struct m0_xcode_ctx ctx;
251 
252  M0_SET0(&ctx);
254  m0_xcode_free(&ctx);
255 }
256 
260 static int ctx_walk(struct m0_xcode_ctx *ctx, enum xcode_op op)
261 {
262  void *ptr;
264  int length = 0;
265  int result;
266  struct m0_bufvec area = M0_BUFVEC_INIT_BUF(&ptr, &size);
267  struct m0_bufvec_cursor mem;
268  struct m0_xcode_cursor *it = &ctx->xcx_it;
269 
270  M0_PRE(M0_IN(op, (XO_ENC, XO_DEC, XO_LEN)));
271 
272  while ((result = m0_xcode_next(it)) > 0) {
273  const struct m0_xcode_type *xt;
274  const struct m0_xcode_type_ops *ops;
275  struct m0_xcode_obj *cur;
276  struct m0_xcode_cursor_frame *top;
277 
279 
280  if (top->s_flag != M0_XCODE_CURSOR_PRE)
281  continue;
282 
283  cur = &top->s_obj;
284 
285  if (op == XO_DEC) {
286  result = m0_xcode_alloc_obj(it, ctx->xcx_alloc);
287  if (result != 0)
288  break;
289  }
290 
291  if (ctx->xcx_iter != NULL) {
292  result = ctx->xcx_iter(it);
293  if (result != 0)
294  break;
295  }
296 
297  xt = cur->xo_type;
298  ptr = cur->xo_ptr;
299  ops = xt->xct_ops;
300 
301  if (ops != NULL &&
302  ((op == XO_ENC && ops->xto_encode != NULL) ||
303  (op == XO_DEC && ops->xto_decode != NULL) ||
304  (op == XO_LEN && ops->xto_length != NULL))) {
305  switch (op) {
306  case XO_ENC:
307  result = ops->xto_encode(ctx, ptr);
308  break;
309  case XO_DEC:
310  result = ops->xto_decode(ctx, ptr);
311  break;
312  case XO_LEN:
313  length += ops->xto_length(ctx, ptr);
314  break;
315  default:
316  M0_IMPOSSIBLE("op");
317  }
318  m0_xcode_skip(it);
319  } else if (xt->xct_aggr == M0_XA_ATOM) {
320  struct m0_xcode_cursor_frame *prev = top - 1;
321  struct m0_xcode_obj *par = &prev->s_obj;
322  bool array = at_array(it, prev, par) &&
324 
325  size = xt->xct_sizeof;
326  if (array)
327  size *= m0_xcode_tag(par);
328 
329  if (op == XO_LEN)
330  length += size;
331  else {
332  struct m0_bufvec_cursor *src;
333  struct m0_bufvec_cursor *dst;
334 
335  m0_bufvec_cursor_init(&mem, &area);
336  /* XXX endianness and sharing */
337  switch (op) {
338  case XO_ENC:
339  src = &mem;
340  dst = &ctx->xcx_buf;
341  break;
342  case XO_DEC:
343  dst = &mem;
344  src = &ctx->xcx_buf;
345  break;
346  default:
347  M0_IMPOSSIBLE("op");
348  src = dst = 0;
349  break;
350  }
352  src, size) != size)
353  result = -EPROTO;
354  }
355  if (array) {
356  it->xcu_depth--;
357  m0_xcode_skip(it);
358  }
359  }
360  if (result < 0)
361  break;
362  }
363 
364  if (ctx->xcx_iter_end != NULL)
365  ctx->xcx_iter_end(it);
366 
367  if (op == XO_LEN)
368  result = result ?: length;
369 
370  return result;
371 }
372 
373 M0_INTERNAL void m0_xcode_ctx_init(struct m0_xcode_ctx *ctx,
374  const struct m0_xcode_obj *obj)
375 {
376  M0_SET0(ctx);
377  m0_xcode_cursor_init(&ctx->xcx_it, obj);
378 }
379 
380 M0_INTERNAL int m0_xcode_decode(struct m0_xcode_ctx *ctx)
381 {
382  return ctx_walk(ctx, XO_DEC);
383 }
384 
385 M0_INTERNAL int m0_xcode_encode(struct m0_xcode_ctx *ctx)
386 {
387  return ctx_walk(ctx, XO_ENC);
388 }
389 
390 M0_INTERNAL int m0_xcode_length(struct m0_xcode_ctx *ctx)
391 {
392  return ctx_walk(ctx, XO_LEN);
393 }
394 
395 M0_INTERNAL void m0_xcode_type_iterate(struct m0_xcode_type *xt,
396  void (*t)(struct m0_xcode_type *,
397  void *),
398  void (*f)(struct m0_xcode_type *,
399  struct m0_xcode_field *,
400  void *), void *datum)
401 {
402  int i;
403 
404  if (t != NULL)
405  (*t)(xt, datum);
406  for (i = 0; i < xt->xct_nr; ++i) {
407  struct m0_xcode_field *field = &xt->xct_child[i];
408 
409  if (f != NULL)
410  (*f)(xt, field, datum);
411  /* Discard const. Not good. */
412  m0_xcode_type_iterate((void *)field->xf_type, t, f, datum);
413  }
414 }
415 
416 M0_INTERNAL int m0_xcode_encdec(struct m0_xcode_obj *obj,
417  struct m0_bufvec_cursor *cur,
418  enum m0_xcode_what what)
419 {
420  struct m0_xcode_ctx ctx;
421  int result;
422 
424  ctx.xcx_buf = *cur;
425  ctx.xcx_alloc = m0_xcode_alloc;
426 
427  result = what == M0_XCODE_ENCODE ? m0_xcode_encode(&ctx) :
429  if (result == 0) {
430  *cur = ctx.xcx_buf;
431  if (obj->xo_ptr == NULL)
432  obj->xo_ptr = m0_xcode_ctx_top(&ctx);
433  }
434  return result;
435 }
436 
437 M0_INTERNAL int m0_xcode_data_size(struct m0_xcode_ctx *ctx,
438  const struct m0_xcode_obj *obj)
439 {
441  return m0_xcode_length(ctx);
442 }
443 
444 M0_INTERNAL void *m0_xcode_alloc(struct m0_xcode_cursor *it, size_t nob)
445 {
446  return m0_alloc(nob);
447 }
448 
449 static void __xcode_free(struct m0_xcode_cursor *it)
450 {
451  struct m0_xcode_cursor_frame *top = m0_xcode_cursor_top(it);
452  size_t nob = 0;
453  void **slot;
454 
455  slot = allocp(it, &nob);
456  if (top->s_datum != 0) {
457  m0_free((void *) top->s_datum);
458  top->s_datum = 0;
459  } else if (nob != 0)
460  m0_free(*slot);
461 }
462 
476 M0_INTERNAL void m0_xcode_free(struct m0_xcode_ctx *ctx)
477 {
478  struct m0_xcode_cursor *it;
479 
480  it = &ctx->xcx_it;
481  if (ctx->xcx_free == NULL)
482  ctx->xcx_free = __xcode_free;
483  while (m0_xcode_next(it) > 0) {
484  struct m0_xcode_cursor_frame *top = m0_xcode_cursor_top(it);
485  size_t nob = 0;
486  struct m0_xcode_cursor_frame *prev = top -1;
487  struct m0_xcode_obj *par = &prev->s_obj;
488  bool arrayp = at_array(it, prev, par);
489  void **slot;
490 
491  if (top->s_flag == M0_XCODE_CURSOR_POST) {
492  slot = allocp(it, &nob);
493  if (top->s_datum != 0) {
494  ctx->xcx_free(it);
495  top->s_datum = 0;
496  }
497  if (arrayp)
498  /*
499  * Store the address of allocated array in the
500  * parent stack frame.
501  */
502  prev->s_datum = (uint64_t)*slot;
503  else if (nob != 0)
504  ctx->xcx_free(it);
505  } else if (top->s_flag == M0_XCODE_CURSOR_PRE) {
506  /*
507  * Deal with partially constructed objects.
508  */
509  if (top->s_obj.xo_ptr == NULL) {
510  if (arrayp)
511  /*
512  * If array allocation failed, skip the
513  * array entirely.
514  */
515  --it->xcu_depth;
516  m0_xcode_skip(it);
517  }
518  }
519  }
520 }
521 
522 M0_INTERNAL int m0_xcode_dup(struct m0_xcode_ctx *dest,
523  struct m0_xcode_ctx *src)
524 {
525  struct m0_xcode_cursor *dit;
526  struct m0_xcode_cursor *sit;
527  int result;
528 
529  dit = &dest->xcx_it;
530  sit = &src->xcx_it;
531  M0_ASSERT(m0_xcode_cursor_top(dit)->s_obj.xo_type ==
532  m0_xcode_cursor_top(sit)->s_obj.xo_type);
533 
534  while ((result = m0_xcode_next(sit)) > 0) {
535  struct m0_xcode_cursor_frame *sf;
536  struct m0_xcode_cursor_frame *df;
537  struct m0_xcode_obj *sobj;
538  struct m0_xcode_obj *dobj;
539  const struct m0_xcode_type *xt;
540 
541  result = m0_xcode_next(dit);
542  M0_ASSERT(result > 0);
543 
544  sf = m0_xcode_cursor_top(sit);
545  df = m0_xcode_cursor_top(dit);
546  M0_ASSERT(sf->s_flag == df->s_flag);
547  sobj = &sf->s_obj;
548  dobj = &df->s_obj;
549  xt = sobj->xo_type;
550  M0_ASSERT(xt == dobj->xo_type);
551 
552  if (sf->s_flag != M0_XCODE_CURSOR_PRE)
553  continue;
554 
555  result = m0_xcode_alloc_obj(dit, dest->xcx_alloc == NULL ?
557  dest->xcx_alloc);
558  if (result != 0)
559  return result;
560 
561  if (xt->xct_aggr == M0_XA_ATOM) {
562  M0_ASSERT(dobj->xo_ptr != NULL);
563  memcpy(dobj->xo_ptr, sobj->xo_ptr, xt->xct_sizeof);
564  }
565  }
566 
567  M0_POST(ergo(result == 0, m0_xcode_cmp(&dit->xcu_stack[0].s_obj,
568  &sit->xcu_stack[0].s_obj) == 0));
569  return result;
570 }
571 
572 M0_INTERNAL int m0_xcode_cmp(const struct m0_xcode_obj *o0,
573  const struct m0_xcode_obj *o1)
574 {
575  int result;
576  struct m0_xcode_cursor it0;
577  struct m0_xcode_cursor it1;
578 
579  M0_PRE(o0->xo_type == o1->xo_type);
580 
581  m0_xcode_cursor_init(&it0, o0);
582  m0_xcode_cursor_init(&it1, o1);
583 
584  while ((result = m0_xcode_next(&it0)) > 0) {
585  struct m0_xcode_cursor_frame *t0;
586  struct m0_xcode_cursor_frame *t1;
587  struct m0_xcode_obj *s0;
588  struct m0_xcode_obj *s1;
589  const struct m0_xcode_type *xt;
590 
591  result = m0_xcode_next(&it1);
592  M0_ASSERT(result > 0);
593 
594  t0 = m0_xcode_cursor_top(&it0);
595  t1 = m0_xcode_cursor_top(&it1);
596  M0_ASSERT(t0->s_flag == t1->s_flag);
597  s0 = &t0->s_obj;
598  s1 = &t1->s_obj;
599  xt = s0->xo_type;
600  M0_ASSERT(xt == s1->xo_type);
601 
602  if (t0->s_flag == M0_XCODE_CURSOR_PRE &&
603  xt->xct_aggr == M0_XA_ATOM) {
604  result = memcmp(s0->xo_ptr, s1->xo_ptr, xt->xct_sizeof);
605  if (result != 0)
606  return result;
607  }
608  }
609  return 0;
610 }
611 
612 M0_INTERNAL void *m0_xcode_addr(const struct m0_xcode_obj *obj, int fileno,
613  uint64_t elno)
614 {
615  char *addr = (char *)obj->xo_ptr;
616  const struct m0_xcode_type *xt = obj->xo_type;
617  const struct m0_xcode_field *f = &xt->xct_child[fileno];
618  const struct m0_xcode_type *ct = f->xf_type;
619 
620  M0_ASSERT(fileno < xt->xct_nr);
621  addr += f->xf_offset;
622  if (xt->xct_aggr == M0_XA_SEQUENCE && fileno == 1 && elno != ~0ULL)
623  addr = *((char **)addr) + elno * ct->xct_sizeof;
624  else if (xt->xct_aggr == M0_XA_ARRAY && fileno == 0)
625  addr += elno * ct->xct_sizeof;
626  else if (ct == &M0_XT_OPAQUE && elno != ~0ULL)
627  addr = *((char **)addr);
628  return addr;
629 }
630 
631 M0_INTERNAL int m0_xcode_subobj(struct m0_xcode_obj *subobj,
632  const struct m0_xcode_obj *obj, int fieldno,
633  uint64_t elno)
634 {
635  const struct m0_xcode_field *f;
636  int result;
637 
638  M0_PRE(0 <= fieldno && fieldno < obj->xo_type->xct_nr);
639 
640  f = &obj->xo_type->xct_child[fieldno];
641 
642  subobj->xo_ptr = m0_xcode_addr(obj, fieldno, elno);
643  if (f->xf_type == &M0_XT_OPAQUE) {
644  result = f->xf_opaque(obj, &subobj->xo_type);
645  } else {
646  subobj->xo_type = f->xf_type;
647  result = 0;
648  }
649  return result;
650 }
651 
652 M0_INTERNAL uint64_t m0_xcode_atom(const struct m0_xcode_obj *obj)
653 {
654  const struct m0_xcode_type *xt = obj->xo_type;
655  void *ptr = obj->xo_ptr;
656  uint64_t val;
657 
659 
660  switch (xt->xct_atype) {
661  case M0_XAT_U8:
662  val = *(uint8_t *)ptr;
663  break;
664  case M0_XAT_U32:
665  val = *(uint32_t *)ptr;
666  break;
667  case M0_XAT_U64:
668  val = *(uint64_t *)ptr;
669  break;
670  case M0_XAT_VOID:
671  default:
672  M0_IMPOSSIBLE("value of void");
673  val = 0;
674  break;
675  }
676  return val;
677 }
678 
679 M0_INTERNAL uint64_t m0_xcode_tag(const struct m0_xcode_obj *obj)
680 {
681  const struct m0_xcode_type *xt = obj->xo_type;
682  const struct m0_xcode_field *f = &xt->xct_child[0];
683  uint64_t tag;
684 
686 
687  if (xt->xct_aggr != M0_XA_ARRAY) {
688  M0_PRE(f->xf_type->xct_aggr == M0_XA_ATOM);
689 
690  switch (f->xf_type->xct_atype) {
691  case M0_XAT_VOID:
692  tag = f->xf_tag;
693  break;
694  case M0_XAT_U8:
695  case M0_XAT_U32:
696  case M0_XAT_U64: {
697  struct m0_xcode_obj subobj;
698 
699  m0_xcode_subobj(&subobj, obj, 0, 0);
700  tag = m0_xcode_atom(&subobj);
701  break;
702  }
703  default:
704  M0_IMPOSSIBLE("atype");
705  tag = 0;
706  break;
707  }
708  } else
709  tag = f->xf_tag;
710  return tag;
711 }
712 
713 M0_INTERNAL int m0_xcode_find(struct m0_xcode_obj *obj,
714  const struct m0_xcode_type *xt, void **place)
715 {
716  struct m0_xcode_cursor it;
717  int result;
718 
720  while ((result = m0_xcode_next(&it)) > 0) {
721  struct m0_xcode_obj *cur = &m0_xcode_cursor_top(&it)->s_obj;
722 
723  if (cur->xo_type == xt) {
724  *place = cur->xo_ptr;
725  return 0;
726  }
727  }
728  return result ?: -ENOENT;
729 }
730 
731 M0_INTERNAL void m0_xcode_bob_type_init(struct m0_bob_type *bt,
732  const struct m0_xcode_type *xt,
733  size_t magix_field, uint64_t magix)
734 {
735  const struct m0_xcode_field *mf = &xt->xct_child[magix_field];
736 
737  M0_PRE(magix_field < xt->xct_nr);
739  M0_PRE(mf->xf_type == &M0_XT_U64);
740 
741  bt->bt_name = xt->xct_name;
742  bt->bt_magix = magix;
743  bt->bt_magix_offset = mf->xf_offset;
744 }
745 
746 M0_INTERNAL void *m0_xcode_ctx_top(const struct m0_xcode_ctx *ctx)
747 {
748  return ctx->xcx_it.xcu_stack[0].s_obj.xo_ptr;
749 }
750 
751 M0_INTERNAL void m0_xcode_union_init(struct m0_xcode_type *un, const char *name,
752  const char *discriminator,
753  size_t maxbranches)
754 {
755  *un = (typeof(*un)) {
756  .xct_aggr = M0_XA_UNION,
757  .xct_name = name,
758  .xct_nr = maxbranches + 1
759  };
760  /* Cannot put this in the initialiser above, because
761  m0_xcode_type::xct_child[] is declared to have 0 elements. */
762  un->xct_child[0] = (struct m0_xcode_field) {
763  .xf_name = discriminator,
764  .xf_type = &M0_XT_U64
765  };
766 }
767 
768 M0_INTERNAL void m0_xcode_union_fini(struct m0_xcode_type *un)
769 {
770  int i;
771  for (i = 0; i < un->xct_nr; ++i)
772  un->xct_child[i].xf_name = NULL;
773  *un = (typeof(*un)) {
774  .xct_aggr = 0,
775  .xct_name = NULL,
776  .xct_nr = 0
777  };
778 }
779 
780 M0_INTERNAL void m0_xcode_union_add(struct m0_xcode_type *un, const char *name,
781  const struct m0_xcode_type *xt,
782  uint64_t tag)
783 {
784  int i;
785  struct m0_xcode_field *f = NULL; /* "may be used uninitialized" */
786 
787  M0_PRE(un->xct_aggr == M0_XA_UNION);
788  M0_PRE(un->xct_child[0].xf_name != NULL);
789  M0_PRE(un->xct_child[0].xf_type != NULL);
790 
791  for (i = 1; i < un->xct_nr; ++i) {
792  f = &un->xct_child[i];
793  if (f->xf_name == NULL)
794  break;
795  }
796  M0_ASSERT(i < un->xct_nr);
797  *f = (typeof(*f)) {
798  .xf_name = name,
799  .xf_type = xt,
800  .xf_tag = tag,
801  .xf_offset = un->xct_child[0].xf_type->xct_sizeof
802  };
803 }
804 
805 M0_INTERNAL void m0_xcode_union_close(struct m0_xcode_type *un)
806 {
807  int i;
808  struct m0_xcode_field *f;
809  size_t maxsize = 0;
810 
811  M0_PRE(un->xct_aggr == M0_XA_UNION);
812 
813  for (i = 1; i < un->xct_nr; ++i) {
814  f = &un->xct_child[i];
815  if (f->xf_name != NULL)
816  /*
817  * If we ever maintain ->xct_alignof, it can be used to
818  * calculate padding between the discriminator and union
819  * branches.
820  */
821  maxsize = max_check(maxsize, f->xf_type->xct_sizeof);
822  else
823  break;
824  }
825  M0_ASSERT(i < un->xct_nr);
826  un->xct_nr = i;
827  un->xct_sizeof = m0_align(un->xct_child[0].xf_type->xct_sizeof +
828  maxsize, 16);
830 }
831 
832 M0_INTERNAL int m0_xcode_obj_enc_to_buf(struct m0_xcode_obj *obj,
833  void **buf,
834  m0_bcount_t *len)
835 {
836  struct m0_xcode_ctx ctx;
837  struct m0_bufvec val;
838  struct m0_bufvec_cursor cur;
839 
840  M0_PRE(obj != NULL);
841  *len = m0_xcode_data_size(&ctx, obj);
842  *buf = m0_alloc(*len);
843  if (*buf == NULL)
844  return M0_ERR(-ENOMEM);
845  val = M0_BUFVEC_INIT_BUF(buf, len);
848 }
849 
851  void *buf,
852  m0_bcount_t len)
853 {
854  struct m0_bufvec val;
855  struct m0_bufvec_cursor cur;
856 
857  M0_PRE(obj != NULL);
858  val = M0_BUFVEC_INIT_BUF(&buf, &len);
861 }
862 
863 struct flags_data {
864  uint32_t fd_on;
865  uint32_t fd_off;
866  uint64_t fd_aggr_umask;
867  bool fd_ok;
868 };
869 
870 static void xcode_flags_check(struct m0_xcode_type *xt, struct flags_data *fd)
871 {
872  if ((M0_BITS(xt->xct_aggr) & fd->fd_aggr_umask) == 0) {
873  fd->fd_ok &= (xt->xct_flags & fd->fd_on) == fd->fd_on;
874  fd->fd_ok &= (xt->xct_flags & fd->fd_off) == 0;
875  }
876 }
877 
878 M0_INTERNAL bool m0_xcode_type_flags(struct m0_xcode_type *xt,
879  uint32_t on, uint32_t off,
880  uint64_t aggr_umask)
881 {
882  struct flags_data fd = {
883  .fd_on = on,
884  .fd_off = off,
885  .fd_aggr_umask = aggr_umask,
886  .fd_ok = true
887  };
889  return fd.fd_ok;
890 }
891 
892 void m0_xc_u8_init(void)
893 {
894 }
895 
896 void m0_xc_u16_init(void)
897 {
898 }
899 
900 void m0_xc_u32_init(void)
901 {
902 }
903 
904 void m0_xc_u64_init(void)
905 {
906 }
907 
908 void m0_xc_void_init(void)
909 {
910 }
911 
913 {
914 }
915 
916 const struct m0_xcode_type M0_XT_VOID = {
917  .xct_aggr = M0_XA_ATOM,
918  .xct_name = "void",
919  .xct_atype = M0_XAT_VOID,
920  .xct_sizeof = 0,
921  .xct_nr = 0
922 };
923 
924 const struct m0_xcode_type M0_XT_U8 = {
925  .xct_aggr = M0_XA_ATOM,
926  .xct_name = "u8",
927  .xct_atype = M0_XAT_U8,
928  .xct_sizeof = sizeof(uint8_t),
929  .xct_nr = 0
930 };
931 
932 const struct m0_xcode_type M0_XT_U32 = {
933  .xct_aggr = M0_XA_ATOM,
934  .xct_name = "u32",
935  .xct_atype = M0_XAT_U32,
936  .xct_sizeof = sizeof(uint32_t),
937  .xct_nr = 0
938 };
939 
940 const struct m0_xcode_type M0_XT_U64 = {
941  .xct_aggr = M0_XA_ATOM,
942  .xct_name = "u64",
943  .xct_atype = M0_XAT_U64,
944  .xct_sizeof = sizeof(uint64_t),
945  .xct_nr = 0
946 };
947 
948 const struct m0_xcode_type M0_XT_OPAQUE = {
950  .xct_name = "opaque",
951  .xct_sizeof = sizeof (void *),
952  .xct_nr = 0
953 };
954 
955 const char *m0_xcode_aggr_name[M0_XA_NR] = {
956  [M0_XA_RECORD] = "record",
957  [M0_XA_UNION] = "union",
958  [M0_XA_SEQUENCE] = "sequence",
959  [M0_XA_ARRAY] = "array",
960  [M0_XA_TYPEDEF] = "typedef",
961  [M0_XA_OPAQUE] = "opaque",
962  [M0_XA_ATOM] = "atom"
963 };
964 
966  [M0_XAT_VOID] = "void",
967  [M0_XAT_U8] = "u8",
968  [M0_XAT_U32] = "u32",
969  [M0_XAT_U64] = "u64",
970 };
971 
973  [M0_XEND_LE] = "le",
974  [M0_XEND_BE] = "be"
975 };
976 
978  [M0_XCODE_CURSOR_NONE] = "none",
979  [M0_XCODE_CURSOR_PRE] = "pre",
980  [M0_XCODE_CURSOR_IN] = "in",
981  [M0_XCODE_CURSOR_POST] = "post"
982 };
983 
984 #undef M0_TRACE_SUBSYSTEM
985 
988 /*
989  * Local variables:
990  * c-indentation-style: "K&R"
991  * c-basic-offset: 8
992  * tab-width: 8
993  * fill-column: 80
994  * scroll-step: 1
995  * End:
996  */
M0_INTERNAL struct m0_xcode_cursor_frame * m0_xcode_cursor_top(struct m0_xcode_cursor *it)
Definition: cursor.c:41
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
M0_INTERNAL int m0_xcode_encdec(struct m0_xcode_obj *obj, struct m0_bufvec_cursor *cur, enum m0_xcode_what what)
Definition: xcode.c:416
M0_INTERNAL void * m0_xcode_addr(const struct m0_xcode_obj *obj, int fileno, uint64_t elno)
Definition: xcode.c:612
static void ptr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:440
M0_INTERNAL void * m0_xcode_ctx_top(const struct m0_xcode_ctx *ctx)
Definition: xcode.c:746
#define M0_PRE(cond)
const struct m0_xcode_type * xo_type
Definition: xcode.h:351
const struct m0_xcode_type * xf_type
Definition: xcode.h:253
Definition: xcode.c:145
M0_EXTERN ssize_t m0_xcode_alloc_obj(struct m0_xcode_cursor *it, void *(*alloc)(struct m0_xcode_cursor *, size_t))
Definition: xcode.c:228
#define NULL
Definition: misc.h:38
static struct m0_bufvec dst
Definition: xform.c:61
M0_INTERNAL void m0_xcode_type_iterate(struct m0_xcode_type *xt, void(*t)(struct m0_xcode_type *, void *), void(*f)(struct m0_xcode_type *, struct m0_xcode_field *, void *), void *datum)
Definition: xcode.c:395
M0_INTERNAL void m0_xcode_union_close(struct m0_xcode_type *un)
Definition: xcode.c:805
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
Definition: idx_mock.c:52
#define ergo(a, b)
Definition: misc.h:293
static bool x
Definition: sm.c:168
static int ctx_walk(struct m0_xcode_ctx *ctx, enum xcode_op op)
Definition: xcode.c:260
static FILE * f
Definition: adieu.c:79
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
size_t xct_nr
Definition: xcode.h:343
void m0_xc_u16_init(void)
Definition: xcode.c:896
#define max_check(a, b)
Definition: arith.h:95
static bool m0_is_po2(uint64_t val)
Definition: arith.h:153
M0_INTERNAL int m0_xcode_subobj(struct m0_xcode_obj *subobj, const struct m0_xcode_obj *obj, int fieldno, uint64_t elno)
Definition: xcode.c:631
static struct m0_be_emap_cursor it
Definition: extmap.c:46
struct m0_xcode_field xct_child[0]
Definition: xcode.h:345
M0_INTERNAL void m0_xcode_free_obj(struct m0_xcode_obj *obj)
Definition: xcode.c:248
struct m0_xcode_cursor::m0_xcode_cursor_frame xcu_stack[M0_XCODE_DEPTH_MAX]
#define M0_BITS(...)
Definition: misc.h:236
Definition: xcode.c:59
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL int m0_xcode_decode(struct m0_xcode_ctx *ctx)
Definition: xcode.c:380
const struct m0_xcode_type_ops * xct_ops
Definition: xcode.h:320
m0_xcode_what
Definition: xcode.h:647
#define M0_SET0(obj)
Definition: misc.h:64
static struct m0_xcode_type ** xt[]
Definition: protocol.c:64
static unsigned alignment_mask(const struct m0_xcode_field *field)
Definition: xcode.c:51
void m0_xc_void_init(void)
Definition: xcode.c:908
const char * m0_xcode_endianness_name[M0_XEND_NR]
Definition: xcode.c:972
static struct foo * obj
Definition: tlist.c:302
Definition: sock.c:887
M0_INTERNAL int m0_xcode_dup(struct m0_xcode_ctx *dest, struct m0_xcode_ctx *src)
Definition: xcode.c:522
const char * m0_xcode_cursor_flag_name[M0_XCODE_CURSOR_NR]
Definition: xcode.c:977
static int top
Definition: formation2.c:86
op
Definition: libdemo.c:64
M0_INTERNAL int m0_xcode_length(struct m0_xcode_ctx *ctx)
Definition: xcode.c:390
static bool is_pointer(const struct m0_xcode_type *xt, const struct m0_xcode_field *field)
Definition: xcode.c:41
static struct btype bt[]
Definition: beck.c:459
static char * addr
Definition: node_k.c:37
M0_INTERNAL void m0_xcode_union_fini(struct m0_xcode_type *un)
Definition: xcode.c:768
int i
Definition: dir.c:1033
M0_INTERNAL bool m0_xcode_is_byte_array(const struct m0_xcode_type *xt)
Definition: xcode.c:221
return M0_ERR(-EOPNOTSUPP)
const char * name
Definition: trace.c:110
M0_INTERNAL uint64_t m0_xcode_tag(const struct m0_xcode_obj *obj)
Definition: xcode.c:679
static struct m0_addb2_sit * sit
Definition: storage.c:40
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_copy(struct m0_bufvec_cursor *dcur, struct m0_bufvec_cursor *scur, m0_bcount_t num_bytes)
Definition: vec.c:620
Definition: xcode.c:45
const struct m0_xcode_type M0_XT_OPAQUE
Definition: xcode.c:948
#define M0_ASSERT(cond)
static int field(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:84
M0_INTERNAL void m0_xcode_union_add(struct m0_xcode_type *un, const char *name, const struct m0_xcode_type *xt, uint64_t tag)
Definition: xcode.c:780
M0_INTERNAL int m0_xcode_cmp(const struct m0_xcode_obj *o0, const struct m0_xcode_obj *o1)
Definition: xcode.c:572
enum m0_xode_atom_type xct_atype
Definition: xcode.h:326
static struct m0_thread t[8]
Definition: service_ut.c:1230
const struct m0_xcode_type M0_XT_VOID
Definition: xcode.c:916
Definition: bob.c:40
static long long max(long long a, long long b)
Definition: crate.c:196
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
M0_INTERNAL int m0_xcode_obj_enc_to_buf(struct m0_xcode_obj *obj, void **buf, m0_bcount_t *len)
Definition: xcode.c:832
uint32_t fd_off
Definition: xcode.c:865
Definition: xcode.c:142
static struct ff2c_term * alloc(void)
Definition: parser.c:37
void * m0_alloc(size_t size)
Definition: memory.c:126
uint64_t fd_aggr_umask
Definition: xcode.c:866
M0_INTERNAL void m0_xcode_union_init(struct m0_xcode_type *un, const char *name, const char *discriminator, size_t maxbranches)
Definition: xcode.c:751
#define M0_POST(cond)
Definition: xcode.h:73
M0_INTERNAL int m0_xcode_next(struct m0_xcode_cursor *it)
Definition: cursor.c:59
static void xcode_flags_check(struct m0_xcode_type *xt, struct flags_data *fd)
Definition: xcode.c:870
bool m0_xcode_type_invariant(const struct m0_xcode_type *xt)
Definition: xcode.c:74
static m0_bindex_t offset
Definition: dump.c:173
static void t0(int self)
Definition: chan.c:39
static void __xcode_free(struct m0_xcode_cursor *it)
Definition: xcode.c:449
M0_INTERNAL void * m0_xcode_alloc(struct m0_xcode_cursor *it, size_t nob)
Definition: xcode.c:444
const char * m0_xcode_atom_type_name[M0_XAT_NR]
Definition: xcode.c:965
M0_INTERNAL void m0_xcode_bob_type_init(struct m0_bob_type *bt, const struct m0_xcode_type *xt, size_t magix_field, uint64_t magix)
Definition: xcode.c:731
void m0_xc_u64_init(void)
Definition: xcode.c:904
const char * m0_xcode_aggr_name[M0_XA_NR]
Definition: xcode.c:955
M0_INTERNAL void m0_xcode_free(struct m0_xcode_ctx *ctx)
Definition: xcode.c:476
static bool field_invariant(const struct m0_xcode_type *xt, const struct m0_xcode_field *field)
Definition: xcode.c:61
M0_INTERNAL int m0_xcode_data_size(struct m0_xcode_ctx *ctx, const struct m0_xcode_obj *obj)
Definition: xcode.c:437
M0_INTERNAL uint64_t m0_xcode_atom(const struct m0_xcode_obj *obj)
Definition: xcode.c:652
#define m0_forall(var, nr,...)
Definition: misc.h:112
static void ** allocp(struct m0_xcode_cursor *it, size_t *out)
Definition: xcode.c:157
const struct m0_xcode_type M0_XT_U32
Definition: xcode.c:932
M0_INTERNAL void m0_xcode_cursor_init(struct m0_xcode_cursor *it, const struct m0_xcode_obj *obj)
Definition: cursor.c:33
static long long min(long long a, long long b)
Definition: crate.c:191
enum m0_xcode_aggr xct_aggr
Definition: xcode.h:316
bool fd_ok
Definition: xcode.c:867
Definition: xcode.c:143
uint32_t fd_on
Definition: xcode.c:864
M0_INTERNAL int m0_xcode_obj_dec_from_buf(struct m0_xcode_obj *obj, void *buf, m0_bcount_t len)
Definition: xcode.c:850
Definition: xcode.c:144
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL int m0_xcode_find(struct m0_xcode_obj *obj, const struct m0_xcode_type *xt, void **place)
Definition: xcode.c:713
uint32_t xf_offset
Definition: xcode.h:285
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL int m0_xcode_encode(struct m0_xcode_ctx *ctx)
Definition: xcode.c:385
const struct m0_xcode_type M0_XT_U8
Definition: xcode.c:924
M0_INTERNAL void m0_xcode_skip(struct m0_xcode_cursor *it)
Definition: cursor.c:148
size_t xct_sizeof
Definition: xcode.h:341
struct m0t1fs_filedata * fd
Definition: dir.c:1030
void m0_xc_u8_init(void)
Definition: xcode.c:892
void * xo_ptr
Definition: xcode.h:353
void m0_xc_u32_init(void)
Definition: xcode.c:900
static void t1(int n)
Definition: mutex.c:48
static struct m0_fop_type * ft[]
Definition: service_ut.c:856
Definition: nucleus.c:42
M0_INTERNAL void m0_xcode_ctx_init(struct m0_xcode_ctx *ctx, const struct m0_xcode_obj *obj)
Definition: xcode.c:373
#define out(...)
Definition: gen.c:41
M0_INTERNAL bool m0_xcode_type_flags(struct m0_xcode_type *xt, uint32_t on, uint32_t off, uint64_t aggr_umask)
Definition: xcode.c:878
struct m0_fom_ops ops
Definition: io_foms.c:623
xcode_op
Definition: xcode.c:141
void m0_free(void *data)
Definition: memory.c:146
const struct m0_xcode_type M0_XT_U64
Definition: xcode.c:940
void m0_xc_opaque_init(void)
Definition: xcode.c:912
struct m0_pdclust_src_addr src
Definition: fd.c:108
static bool at_array(const struct m0_xcode_cursor *it, const struct m0_xcode_cursor_frame *prev, const struct m0_xcode_obj *par)
Definition: xcode.c:148
static uint64_t m0_align(uint64_t val, uint64_t alignment)
Definition: arith.h:170
uint32_t xct_flags
Definition: xcode.h:331
const char * xct_name
Definition: xcode.h:318
Definition: vec.h:145
#define M0_IMPOSSIBLE(fmt,...)