summaryrefslogtreecommitdiff
path: root/upb/generated_util.h
blob: 314a6d5b049fba46ee35cd8156a5be80a260454d (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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
** Functions for use by generated code.  These are not public and users must
** not call them directly.
*/

#ifndef UPB_GENERATED_UTIL_H_
#define UPB_GENERATED_UTIL_H_

#include <stdint.h>
#include "upb/msg.h"

#include "upb/port_def.inc"

#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)

UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
                                           size_t *size) {
  const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*);
  if (arr) {
    if (size) *size = arr->len;
    return arr->data;
  } else {
    if (size) *size = 0;
    return NULL;
  }
}

UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
                                             size_t *size) {
  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
  if (arr) {
    if (size) *size = arr->len;
    return arr->data;
  } else {
    if (size) *size = 0;
    return NULL;
  }
}

/* TODO(haberman): this is a mess.  It will improve when upb_array no longer
 * carries reflective state (type, elem_size). */
UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
                                            size_t elem_size,
                                            upb_fieldtype_t type,
                                            upb_arena *arena) {
  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);

  if (!arr) {
    arr = upb_array_new(type, arena);
    if (!arr) return NULL;
    *PTR_AT(msg, ofs, upb_array*) = arr;
  }

  if (size > arr->size) {
    size_t new_size = UPB_MAX(arr->size, 4);
    size_t old_bytes = arr->size * elem_size;
    size_t new_bytes;
    while (new_size < size) new_size *= 2;
    new_bytes = new_size * elem_size;
    arr->data = upb_arena_realloc(arena, arr->data, old_bytes, new_bytes);
    if (!arr->data) {
      return NULL;
    }
    arr->size = new_size;
  }

  arr->len = size;
  return arr->data;
}

UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
                                           size_t elem_size,
                                           upb_fieldtype_t type,
                                           const void *value,
                                           upb_arena *arena) {
  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
  size_t i = arr ? arr->len : 0;
  void *data =
      _upb_array_resize_accessor(msg, ofs, i + 1, elem_size, type, arena);
  if (!data) return false;
  memcpy(PTR_AT(data, i * elem_size, char), value, elem_size);
  return true;
}

UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) {
  return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
}

UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) {
  return (*PTR_AT(msg, idx / 8, char)) |= (1 << (idx % 8));
}

UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) {
  return (*PTR_AT(msg, idx / 8, char)) &= ~(1 << (idx % 8));
}

UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) {
  return *PTR_AT(msg, case_ofs, int32_t) == num;
}

#undef PTR_AT

#include "upb/port_undef.inc"

#endif  /* UPB_GENERATED_UTIL_H_ */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback