summaryrefslogtreecommitdiff
path: root/src/upb_struct.h
blob: 094c207baae38742cb2500c50537b4432e38ab57 (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * upb - a minimalist implementation of protocol buffers.
 *
 * Copyright (c) 2009 Joshua Haberman.  See LICENSE for details.
 *
 * This file defines the in-memory format for messages, arrays, and strings
 * (which are the three dynamically-allocated structures that make up all
 * protobufs). */

#ifndef UPB_STRUCT_H
#define UPB_STRUCT_H

#include "upb.h"

/* mmhead -- this is a "base class" for strings, arrays, and messages ********/

struct upb_mm_ref;
struct upb_mmhead {
  struct upb_mm_ref *refs;  /* Head of linked list. */
  uint32_t refcount;
};

INLINE void upb_mmhead_init(struct upb_mmhead *head) {
  head->refs = NULL;
  head->refcount = 1;
}

INLINE bool upb_mmhead_norefs(struct upb_mmhead *head) {
  return head->refcount == 0 && head->refs == NULL;
}

INLINE bool upb_mmhead_only(struct upb_mmhead *head) {
  return head->refcount == 1 && head->refs == NULL;
}

INLINE bool upb_mmhead_unref(struct upb_mmhead *head) {
  head->refcount--;
  return upb_mmhead_norefs(head);
}

INLINE void upb_mmhead_ref(struct upb_mmhead *head) {
  head->refcount++;
}

/* Structures for msg, string, and array. *************************************/

/* These are all self describing. */

struct upb_msgdef;
struct upb_fielddef;

struct upb_msg {
  struct upb_mmhead mmhead;
  struct upb_msgdef *def;
  uint8_t data[1];
};

typedef uint32_t upb_arraylen_t;  /* can be at most 2**32 elements long. */
struct upb_array {
  struct upb_mmhead mmhead;
  struct upb_fielddef *fielddef;  /* Defines the type of the array. */
  union upb_value_ptr elements;
  upb_arraylen_t len;     /* Number of elements in "elements". */
  upb_arraylen_t size;    /* Memory we own. */
};

struct upb_string {
  struct upb_mmhead mmhead;
  /* We expect the data to be 8-bit clean (uint8_t), but char* is such an
   * ingrained convention that we follow it. */
  char *ptr;
  uint32_t byte_len;
  uint32_t byte_size;  /* How many bytes of ptr we own, 0 if we reference. */
};

/* Type-specific overlays on upb_array. ***************************************/

#define UPB_DEFINE_ARRAY_TYPE(name, type) \
  struct name ## _array { \
    struct upb_mmhead mmhead; \
    struct upb_fielddef *fielddef; \
    type elements; \
    upb_arraylen_t len; \
    upb_arraylen_t size; \
  };

UPB_DEFINE_ARRAY_TYPE(upb_double, double)
UPB_DEFINE_ARRAY_TYPE(upb_float,  float)
UPB_DEFINE_ARRAY_TYPE(upb_int32,  int32_t)
UPB_DEFINE_ARRAY_TYPE(upb_int64,  int64_t)
UPB_DEFINE_ARRAY_TYPE(upb_uint32, uint32_t)
UPB_DEFINE_ARRAY_TYPE(upb_uint64, uint64_t)
UPB_DEFINE_ARRAY_TYPE(upb_bool,   bool)
UPB_DEFINE_ARRAY_TYPE(upb_string, struct upb_string*)
UPB_DEFINE_ARRAY_TYPE(upb_msg,    void*)

/* Defines an array of a specific message type (an overlay of upb_array). */
#define UPB_MSG_ARRAY(msg_type) struct msg_type ## _array
#define UPB_DEFINE_MSG_ARRAY(msg_type) \
  UPB_MSG_ARRAY(msg_type) { \
    struct upb_mmhead mmhead; \
    struct upb_fielddef *fielddef; \
    msg_type **elements; \
    upb_arraylen_t len; \
    upb_arraylen_t size; \
    };

/* mmptr -- a pointer which polymorphically points to one of the above. *******/

union upb_mmptr {
  struct upb_msg *msg;
  struct upb_array *arr;
  struct upb_string *str;
};

enum {
  UPB_MM_MSG_REF,
  UPB_MM_STR_REF,
  UPB_MM_ARR_REF
};
typedef uint8_t upb_mm_ptrtype;

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