summaryrefslogtreecommitdiff
path: root/upb/shim/shim.c
blob: a249e84121db684d4c3cebf3e00ebc255bd2a4e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * upb - a minimalist implementation of protocol buffers.
 *
 * Copyright (c) 2013 Google Inc.  See LICENSE for details.
 * Author: Josh Haberman <jhaberman@gmail.com>
 */

#include "upb/shim/shim.h"

#include <stdlib.h>

// Fallback implementation if the shim is not specialized by the JIT.
#define SHIM_WRITER(type, ctype)                                              \
  bool upb_shim_set ## type (void *c, const void *hd, ctype val) {            \
    uint8_t *m = c;                                                           \
    const upb_shim_data *d = hd;                                              \
    if (d->hasbit > 0)                                                        \
      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
    *(ctype*)&m[d->offset] = val;                                             \
    return true;                                                              \
  }                                                                           \

SHIM_WRITER(double, double)
SHIM_WRITER(float,  float)
SHIM_WRITER(int32,  int32_t)
SHIM_WRITER(int64,  int64_t)
SHIM_WRITER(uint32, uint32_t)
SHIM_WRITER(uint64, uint64_t)
SHIM_WRITER(bool,   bool)
#undef SHIM_WRITER

bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
                  int32_t hasbit) {
  upb_shim_data *d = malloc(sizeof(*d));
  if (!d) return false;
  d->offset = offset;
  d->hasbit = hasbit;

#define TYPE(u, l) \
  case UPB_TYPE_##u: return upb_handlers_set##l(h, f, upb_shim_set##l, d, free)

  switch (upb_fielddef_type(f)) {
    TYPE(INT64,  int64);
    TYPE(INT32,  int32);
    TYPE(ENUM,   int32);
    TYPE(UINT64, uint64);
    TYPE(UINT32, uint32);
    TYPE(DOUBLE, double);
    TYPE(FLOAT,  float);
    TYPE(BOOL,   bool);
    default: assert(false); return false;
  }
#undef TYPE
}

const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
                                      upb_fieldtype_t *type) {
  upb_func *f = upb_handlers_gethandler(h, s);

  if ((upb_int64_handler*)f == upb_shim_setint64) {
    *type = UPB_TYPE_INT64;
  } else if ((upb_int32_handler*)f == upb_shim_setint32) {
    *type = UPB_TYPE_INT32;
  } else if ((upb_uint64_handler*)f == upb_shim_setuint64) {
    *type = UPB_TYPE_UINT64;
  } else if ((upb_uint32_handler*)f == upb_shim_setuint32) {
    *type = UPB_TYPE_UINT32;
  } else if ((upb_double_handler*)f == upb_shim_setdouble) {
    *type = UPB_TYPE_DOUBLE;
  } else if ((upb_float_handler*)f == upb_shim_setfloat) {
    *type = UPB_TYPE_FLOAT;
  } else if ((upb_bool_handler*)f == upb_shim_setbool) {
    *type = UPB_TYPE_BOOL;
  } else {
    return NULL;
  }

  return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback