2 ** This file contains shared definitions that are widely used across upb.
4 ** This is a mixed C/C++ interface that offers a full API to both languages.
5 ** See the top-level README for more information.
23 template <int N> class InlinedArena;
27 #include "upb/port_def.inc"
29 /* upb_status *****************************************************************/
31 /* upb_status represents a success or failure status and error message.
32 * It owns no resources and allocates no memory, so it should work
33 * even in OOM situations. */
35 /* The maximum length of an error message before it will get truncated. */
36 #define UPB_STATUS_MAX_MESSAGE 127
40 char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */
47 const char *upb_status_errmsg(const upb_status *status);
48 bool upb_ok(const upb_status *status);
50 /* Any of the functions that write to a status object allow status to be NULL,
51 * to support use cases where the function's caller does not care about the
53 void upb_status_clear(upb_status *status);
54 void upb_status_seterrmsg(upb_status *status, const char *msg);
55 void upb_status_seterrf(upb_status *status, const char *fmt, ...);
56 void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
58 UPB_INLINE void upb_status_setoom(upb_status *status) {
59 upb_status_seterrmsg(status, "out of memory");
67 Status() { upb_status_clear(&status_); }
69 upb_status* ptr() { return &status_; }
71 /* Returns true if there is no error. */
72 bool ok() const { return upb_ok(&status_); }
74 /* Guaranteed to be NULL-terminated. */
75 const char *error_message() const { return upb_status_errmsg(&status_); }
77 /* The error message will be truncated if it is longer than
78 * UPB_STATUS_MAX_MESSAGE-4. */
79 void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); }
80 void SetFormattedErrorMessage(const char *fmt, ...) {
83 upb_status_vseterrf(&status_, fmt, args);
87 /* Resets the status to a successful state with no message. */
88 void Clear() { upb_status_clear(&status_); }
94 #endif /* __cplusplus */
96 /** upb_strview ************************************************************/
103 UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
110 UPB_INLINE upb_strview upb_strview_makez(const char *data) {
111 return upb_strview_make(data, strlen(data));
114 UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
115 return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
118 #define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
120 #define UPB_STRVIEW_FORMAT "%.*s"
121 #define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
123 /** upb_alloc *****************************************************************/
125 /* A upb_alloc is a possibly-stateful allocator object.
127 * It could either be an arena allocator (which doesn't require individual
128 * free() calls) or a regular malloc() (which does). The client must therefore
129 * free memory unless it knows that the allocator is an arena allocator. */
132 typedef struct upb_alloc upb_alloc;
134 /* A malloc()/free() function.
135 * If "size" is 0 then the function acts like free(), otherwise it acts like
136 * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */
137 typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
141 upb_alloc_func *func;
144 UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
146 return alloc->func(alloc, NULL, 0, size);
149 UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
152 return alloc->func(alloc, ptr, oldsize, size);
155 UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
157 alloc->func(alloc, ptr, 0, 0);
160 /* The global allocator used by upb. Uses the standard malloc()/free(). */
166 extern upb_alloc upb_alloc_global;
172 /* Functions that hard-code the global malloc.
174 * We still get benefit because we can put custom logic into our global
175 * allocator, like injecting out-of-memory faults in debug/testing builds. */
177 UPB_INLINE void *upb_gmalloc(size_t size) {
178 return upb_malloc(&upb_alloc_global, size);
181 UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
182 return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
185 UPB_INLINE void upb_gfree(void *ptr) {
186 upb_free(&upb_alloc_global, ptr);
189 /* upb_arena ******************************************************************/
191 /* upb_arena is a specific allocator implementation that uses arena allocation.
192 * The user provides an allocator that will be used to allocate the underlying
193 * arena blocks. Arenas by nature do not require the individual allocations
194 * to be freed. However the Arena does allow users to register cleanup
195 * functions that will run when the arena is destroyed.
197 * A upb_arena is *not* thread-safe.
199 * You could write a thread-safe arena allocator that satisfies the
200 * upb_alloc interface, but it would not be as efficient for the
201 * single-threaded case. */
203 typedef void upb_cleanup_func(void *ud);
206 typedef struct upb_arena upb_arena;
212 /* Creates an arena from the given initial block (if any -- n may be 0).
213 * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
214 * is a fixed-size arena and cannot grow. */
215 upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
216 void upb_arena_free(upb_arena *a);
217 bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
218 size_t upb_arena_bytesallocated(const upb_arena *a);
220 UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
222 /* Convenience wrappers around upb_alloc functions. */
224 UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
225 return upb_malloc(upb_arena_alloc(a), size);
228 UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
230 return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size);
233 UPB_INLINE upb_arena *upb_arena_new(void) {
234 return upb_arena_init(NULL, 0, &upb_alloc_global);
242 /* A simple arena with no initial memory block and the default allocator. */
243 Arena() : ptr_(upb_arena_new(), upb_arena_free) {}
245 upb_arena* ptr() { return ptr_.get(); }
247 /* Allows this arena to be used as a generic allocator.
249 * The arena does not need free() calls so when using Arena as an allocator
250 * it is safe to skip them. However they are no-ops so there is no harm in
251 * calling free() either. */
252 upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); }
254 /* Add a cleanup function to run when the arena is destroyed.
255 * Returns false on out-of-memory. */
256 bool AddCleanup(void *ud, upb_cleanup_func* func) {
257 return upb_arena_addcleanup(ptr_.get(), ud, func);
260 /* Total number of bytes that have been allocated. It is undefined what
261 * Realloc() does to &arena_ counter. */
262 size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); }
265 std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
270 /* upb::InlinedArena **********************************************************/
272 /* upb::InlinedArena seeds the arenas with a predefined amount of memory. No
273 * heap memory will be allocated until the initial block is exceeded.
275 * These types only exist in C++ */
279 template <int N> class upb::InlinedArena : public upb::Arena {
281 InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {}
283 upb_arena* ptr() { return ptr_.get(); }
286 InlinedArena(const InlinedArena*) = delete;
287 InlinedArena& operator=(const InlinedArena*) = delete;
289 std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
290 char initial_block_[N];
293 #endif /* __cplusplus */
295 /* Constants ******************************************************************/
297 /* Generic function type. */
298 typedef void upb_func(void);
300 /* A list of types as they are encoded on-the-wire. */
302 UPB_WIRE_TYPE_VARINT = 0,
303 UPB_WIRE_TYPE_64BIT = 1,
304 UPB_WIRE_TYPE_DELIMITED = 2,
305 UPB_WIRE_TYPE_START_GROUP = 3,
306 UPB_WIRE_TYPE_END_GROUP = 4,
307 UPB_WIRE_TYPE_32BIT = 5
310 /* The types a field can have. Note that this list is not identical to the
311 * types defined in descriptor.proto, which gives INT32 and SINT32 separate
312 * types (we distinguish the two with the "integer encoding" enum below). */
314 /* Types stored in 1 byte. */
316 /* Types stored in 4 bytes. */
320 UPB_TYPE_ENUM = 5, /* Enum values are int32. */
321 /* Types stored as pointers (probably 4 or 8 bytes). */
324 UPB_TYPE_MESSAGE = 8,
325 /* Types stored as 8 bytes. */
331 /* The repeated-ness of each field; this matches descriptor.proto. */
333 UPB_LABEL_OPTIONAL = 1,
334 UPB_LABEL_REQUIRED = 2,
335 UPB_LABEL_REPEATED = 3
338 /* Descriptor types, as defined in descriptor.proto. */
340 UPB_DESCRIPTOR_TYPE_DOUBLE = 1,
341 UPB_DESCRIPTOR_TYPE_FLOAT = 2,
342 UPB_DESCRIPTOR_TYPE_INT64 = 3,
343 UPB_DESCRIPTOR_TYPE_UINT64 = 4,
344 UPB_DESCRIPTOR_TYPE_INT32 = 5,
345 UPB_DESCRIPTOR_TYPE_FIXED64 = 6,
346 UPB_DESCRIPTOR_TYPE_FIXED32 = 7,
347 UPB_DESCRIPTOR_TYPE_BOOL = 8,
348 UPB_DESCRIPTOR_TYPE_STRING = 9,
349 UPB_DESCRIPTOR_TYPE_GROUP = 10,
350 UPB_DESCRIPTOR_TYPE_MESSAGE = 11,
351 UPB_DESCRIPTOR_TYPE_BYTES = 12,
352 UPB_DESCRIPTOR_TYPE_UINT32 = 13,
353 UPB_DESCRIPTOR_TYPE_ENUM = 14,
354 UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
355 UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
356 UPB_DESCRIPTOR_TYPE_SINT32 = 17,
357 UPB_DESCRIPTOR_TYPE_SINT64 = 18
358 } upb_descriptortype_t;
360 extern const uint8_t upb_desctype_to_fieldtype[];
362 #include "upb/port_undef.inc"