adding pods method of package managing
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
** upb_decode: parsing into a upb_msg using a upb_msglayout.
|
||||
*/
|
||||
|
||||
#ifndef UPB_DECODE_H_
|
||||
#define UPB_DECODE_H_
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/msg.h"
|
||||
#else
|
||||
#include "upb/msg.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool upb_decode(const char *buf, size_t size, upb_msg *msg,
|
||||
const upb_msglayout *l, upb_arena *arena);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* UPB_DECODE_H_ */
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
** upb_encode: parsing into a upb_msg using a upb_msglayout.
|
||||
*/
|
||||
|
||||
#ifndef UPB_ENCODE_H_
|
||||
#define UPB_ENCODE_H_
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/msg.h"
|
||||
#else
|
||||
#include "upb/msg.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
|
||||
size_t *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* UPB_ENCODE_H_ */
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
** 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>
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/msg.h"
|
||||
#else
|
||||
#include "upb/msg.h"
|
||||
#endif
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/port_def.inc"
|
||||
#else
|
||||
#include "upb/port_def.inc"
|
||||
#endif
|
||||
|
||||
#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(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)) |= (char)(1 << (idx % 8));
|
||||
}
|
||||
|
||||
UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) {
|
||||
return (*PTR_AT(msg, idx / 8, char)) &= (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
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/port_undef.inc"
|
||||
#else
|
||||
#include "upb/port_undef.inc"
|
||||
#endif
|
||||
|
||||
#endif /* UPB_GENERATED_UTIL_H_ */
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
** Data structures for message tables, used for parsing and serialization.
|
||||
** This are much lighter-weight than full reflection, but they are do not
|
||||
** have enough information to convert to text format, JSON, etc.
|
||||
**
|
||||
** The definitions in this file are internal to upb.
|
||||
**/
|
||||
|
||||
#ifndef UPB_MSG_H_
|
||||
#define UPB_MSG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/upb.h"
|
||||
#else
|
||||
#include "upb/upb.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void upb_msg;
|
||||
|
||||
/** upb_msglayout *************************************************************/
|
||||
|
||||
/* upb_msglayout represents the memory layout of a given upb_msgdef. The
|
||||
* members are public so generated code can initialize them, but users MUST NOT
|
||||
* read or write any of its members. */
|
||||
|
||||
typedef struct {
|
||||
uint32_t number;
|
||||
uint16_t offset;
|
||||
int16_t presence; /* If >0, hasbit_index+1. If <0, oneof_index+1. */
|
||||
uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */
|
||||
uint8_t descriptortype;
|
||||
uint8_t label;
|
||||
} upb_msglayout_field;
|
||||
|
||||
typedef struct upb_msglayout {
|
||||
const struct upb_msglayout *const* submsgs;
|
||||
const upb_msglayout_field *fields;
|
||||
/* Must be aligned to sizeof(void*). Doesn't include internal members like
|
||||
* unknown fields, extension dict, pointer to msglayout, etc. */
|
||||
uint16_t size;
|
||||
uint16_t field_count;
|
||||
bool extendable;
|
||||
} upb_msglayout;
|
||||
|
||||
/** Message internal representation *******************************************/
|
||||
|
||||
/* Our internal representation for repeated fields. */
|
||||
typedef struct {
|
||||
void *data; /* Each element is element_size. */
|
||||
size_t len; /* Measured in elements. */
|
||||
size_t size; /* Measured in elements. */
|
||||
} upb_array;
|
||||
|
||||
upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
|
||||
upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
|
||||
|
||||
void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
|
||||
upb_arena *arena);
|
||||
const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
|
||||
|
||||
upb_array *upb_array_new(upb_arena *a);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* UPB_MSG_H_ */
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* This is where we define macros used across upb.
|
||||
*
|
||||
* All of these macros are undef'd in port_undef.inc to avoid leaking them to
|
||||
* users.
|
||||
*
|
||||
* The correct usage is:
|
||||
*
|
||||
* #include "upb/foobar.h"
|
||||
* #include "upb/baz.h"
|
||||
*
|
||||
* // MUST be last included header.
|
||||
* #include "upb/port_def.inc"
|
||||
*
|
||||
* // Code for this file.
|
||||
* // <...>
|
||||
*
|
||||
* // Can be omitted for .c files, required for .h.
|
||||
* #include "upb/port_undef.inc"
|
||||
*
|
||||
* This file is private and must not be included by users!
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#if UINTPTR_MAX == 0xffffffff
|
||||
#define UPB_SIZE(size32, size64) size32
|
||||
#else
|
||||
#define UPB_SIZE(size32, size64) size64
|
||||
#endif
|
||||
|
||||
#define UPB_FIELD_AT(msg, fieldtype, offset) \
|
||||
*(fieldtype*)((const char*)(msg) + offset)
|
||||
|
||||
#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
|
||||
UPB_FIELD_AT(msg, int, case_offset) == case_val \
|
||||
? UPB_FIELD_AT(msg, fieldtype, offset) \
|
||||
: default
|
||||
|
||||
#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
|
||||
UPB_FIELD_AT(msg, int, case_offset) = case_val; \
|
||||
UPB_FIELD_AT(msg, fieldtype, offset) = value;
|
||||
|
||||
/* UPB_INLINE: inline if possible, emit standalone code if required. */
|
||||
#ifdef __cplusplus
|
||||
#define UPB_INLINE inline
|
||||
#elif defined (__GNUC__) || defined(__clang__)
|
||||
#define UPB_INLINE static __inline__
|
||||
#else
|
||||
#define UPB_INLINE static
|
||||
#endif
|
||||
|
||||
/* Hints to the compiler about likely/unlikely branches. */
|
||||
#if defined (__GNUC__) || defined(__clang__)
|
||||
#define UPB_LIKELY(x) __builtin_expect((x),1)
|
||||
#define UPB_UNLIKELY(x) __builtin_expect((x),0)
|
||||
#else
|
||||
#define UPB_LIKELY(x) (x)
|
||||
#define UPB_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
|
||||
* doesn't provide these preprocessor symbols. */
|
||||
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define UPB_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
/* Macros for function attributes on compilers that support them. */
|
||||
#ifdef __GNUC__
|
||||
#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
|
||||
#define UPB_NOINLINE __attribute__((noinline))
|
||||
#define UPB_NORETURN __attribute__((__noreturn__))
|
||||
#else /* !defined(__GNUC__) */
|
||||
#define UPB_FORCEINLINE
|
||||
#define UPB_NOINLINE
|
||||
#define UPB_NORETURN
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
|
||||
/* C99/C++11 versions. */
|
||||
#include <stdio.h>
|
||||
#define _upb_snprintf snprintf
|
||||
#define _upb_vsnprintf vsnprintf
|
||||
#define _upb_va_copy(a, b) va_copy(a, b)
|
||||
#elif defined(_MSC_VER)
|
||||
/* Microsoft C/C++ versions. */
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#if _MSC_VER < 1900
|
||||
int msvc_snprintf(char* s, size_t n, const char* format, ...);
|
||||
int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
|
||||
#define UPB_MSVC_VSNPRINTF
|
||||
#define _upb_snprintf msvc_snprintf
|
||||
#define _upb_vsnprintf msvc_vsnprintf
|
||||
#else
|
||||
#define _upb_snprintf snprintf
|
||||
#define _upb_vsnprintf vsnprintf
|
||||
#endif
|
||||
#define _upb_va_copy(a, b) va_copy(a, b)
|
||||
#elif defined __GNUC__
|
||||
/* A few hacky workarounds for functions not in C89.
|
||||
* For internal use only!
|
||||
* TODO(haberman): fix these by including our own implementations, or finding
|
||||
* another workaround.
|
||||
*/
|
||||
#define _upb_snprintf __builtin_snprintf
|
||||
#define _upb_vsnprintf __builtin_vsnprintf
|
||||
#define _upb_va_copy(a, b) __va_copy(a, b)
|
||||
#else
|
||||
#error Need implementations of [v]snprintf and va_copy
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900)
|
||||
/* C++11 is present */
|
||||
#else
|
||||
#error upb requires C++11 for C++ support
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
#define UPB_UNUSED(var) (void)var
|
||||
|
||||
/* UPB_ASSERT(): in release mode, we use the expression without letting it be
|
||||
* evaluated. This prevents "unused variable" warnings. */
|
||||
#ifdef NDEBUG
|
||||
#define UPB_ASSERT(expr) do {} while (false && (expr))
|
||||
#else
|
||||
#define UPB_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
|
||||
/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
|
||||
* exist in debug mode. This turns into regular assert. */
|
||||
#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
|
||||
#else
|
||||
#define UPB_UNREACHABLE() do { assert(0); } while(0)
|
||||
#endif
|
||||
|
||||
/* UPB_INFINITY representing floating-point positive infinity. */
|
||||
#include <math.h>
|
||||
#ifdef INFINITY
|
||||
#define UPB_INFINITY INFINITY
|
||||
#else
|
||||
#define UPB_INFINITY (1.0 / 0.0)
|
||||
#endif
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/* See port_def.inc. This should #undef all macros #defined there. */
|
||||
|
||||
#undef UPB_SIZE
|
||||
#undef UPB_FIELD_AT
|
||||
#undef UPB_READ_ONEOF
|
||||
#undef UPB_WRITE_ONEOF
|
||||
#undef UPB_INLINE
|
||||
#undef UPB_FORCEINLINE
|
||||
#undef UPB_NOINLINE
|
||||
#undef UPB_NORETURN
|
||||
#undef UPB_MAX
|
||||
#undef UPB_MIN
|
||||
#undef UPB_UNUSED
|
||||
#undef UPB_ASSERT
|
||||
#undef UPB_ASSERT_DEBUGVAR
|
||||
#undef UPB_UNREACHABLE
|
||||
#undef UPB_INFINITY
|
||||
#undef UPB_MSVC_VSNPRINTF
|
||||
#undef _upb_snprintf
|
||||
#undef _upb_vsnprintf
|
||||
#undef _upb_va_copy
|
||||
+519
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
** upb_table
|
||||
**
|
||||
** This header is INTERNAL-ONLY! Its interfaces are not public or stable!
|
||||
** This file defines very fast int->upb_value (inttable) and string->upb_value
|
||||
** (strtable) hash tables.
|
||||
**
|
||||
** The table uses chained scatter with Brent's variation (inspired by the Lua
|
||||
** implementation of hash tables). The hash function for strings is Austin
|
||||
** Appleby's "MurmurHash."
|
||||
**
|
||||
** The inttable uses uintptr_t as its key, which guarantees it can be used to
|
||||
** store pointers or integers of at least 32 bits (upb isn't really useful on
|
||||
** systems where sizeof(void*) < 4).
|
||||
**
|
||||
** The table must be homogenous (all values of the same type). In debug
|
||||
** mode, we check this on insert and lookup.
|
||||
*/
|
||||
|
||||
#ifndef UPB_TABLE_H_
|
||||
#define UPB_TABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/upb.h"
|
||||
#else
|
||||
#include "upb/upb.h"
|
||||
#endif
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/port_def.inc"
|
||||
#else
|
||||
#include "upb/port_def.inc"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* upb_value ******************************************************************/
|
||||
|
||||
/* A tagged union (stored untagged inside the table) so that we can check that
|
||||
* clients calling table accessors are correctly typed without having to have
|
||||
* an explosion of accessors. */
|
||||
typedef enum {
|
||||
UPB_CTYPE_INT32 = 1,
|
||||
UPB_CTYPE_INT64 = 2,
|
||||
UPB_CTYPE_UINT32 = 3,
|
||||
UPB_CTYPE_UINT64 = 4,
|
||||
UPB_CTYPE_BOOL = 5,
|
||||
UPB_CTYPE_CSTR = 6,
|
||||
UPB_CTYPE_PTR = 7,
|
||||
UPB_CTYPE_CONSTPTR = 8,
|
||||
UPB_CTYPE_FPTR = 9,
|
||||
UPB_CTYPE_FLOAT = 10,
|
||||
UPB_CTYPE_DOUBLE = 11
|
||||
} upb_ctype_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t val;
|
||||
#ifndef NDEBUG
|
||||
/* In debug mode we carry the value type around also so we can check accesses
|
||||
* to be sure the right member is being read. */
|
||||
upb_ctype_t ctype;
|
||||
#endif
|
||||
} upb_value;
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define SET_TYPE(dest, val) UPB_UNUSED(val)
|
||||
#else
|
||||
#define SET_TYPE(dest, val) dest = val
|
||||
#endif
|
||||
|
||||
/* Like strdup(), which isn't always available since it's not ANSI C. */
|
||||
char *upb_strdup(const char *s, upb_alloc *a);
|
||||
/* Variant that works with a length-delimited rather than NULL-delimited string,
|
||||
* as supported by strtable. */
|
||||
char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
|
||||
|
||||
UPB_INLINE char *upb_gstrdup(const char *s) {
|
||||
return upb_strdup(s, &upb_alloc_global);
|
||||
}
|
||||
|
||||
UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val,
|
||||
upb_ctype_t ctype) {
|
||||
v->val = val;
|
||||
SET_TYPE(v->ctype, ctype);
|
||||
}
|
||||
|
||||
UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) {
|
||||
upb_value ret;
|
||||
_upb_value_setval(&ret, val, ctype);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* For each value ctype, define the following set of functions:
|
||||
*
|
||||
* // Get/set an int32 from a upb_value.
|
||||
* int32_t upb_value_getint32(upb_value val);
|
||||
* void upb_value_setint32(upb_value *val, int32_t cval);
|
||||
*
|
||||
* // Construct a new upb_value from an int32.
|
||||
* upb_value upb_value_int32(int32_t val); */
|
||||
#define FUNCS(name, membername, type_t, converter, proto_type) \
|
||||
UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
|
||||
val->val = (converter)cval; \
|
||||
SET_TYPE(val->ctype, proto_type); \
|
||||
} \
|
||||
UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
|
||||
upb_value ret; \
|
||||
upb_value_set ## name(&ret, val); \
|
||||
return ret; \
|
||||
} \
|
||||
UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
|
||||
UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \
|
||||
return (type_t)(converter)val.val; \
|
||||
}
|
||||
|
||||
FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32)
|
||||
FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64)
|
||||
FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32)
|
||||
FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64)
|
||||
FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL)
|
||||
FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR)
|
||||
FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR)
|
||||
FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR)
|
||||
FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR)
|
||||
|
||||
#undef FUNCS
|
||||
|
||||
UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
|
||||
memcpy(&val->val, &cval, sizeof(cval));
|
||||
SET_TYPE(val->ctype, UPB_CTYPE_FLOAT);
|
||||
}
|
||||
|
||||
UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
|
||||
memcpy(&val->val, &cval, sizeof(cval));
|
||||
SET_TYPE(val->ctype, UPB_CTYPE_DOUBLE);
|
||||
}
|
||||
|
||||
UPB_INLINE upb_value upb_value_float(float cval) {
|
||||
upb_value ret;
|
||||
upb_value_setfloat(&ret, cval);
|
||||
return ret;
|
||||
}
|
||||
|
||||
UPB_INLINE upb_value upb_value_double(double cval) {
|
||||
upb_value ret;
|
||||
upb_value_setdouble(&ret, cval);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef SET_TYPE
|
||||
|
||||
|
||||
/* upb_tabkey *****************************************************************/
|
||||
|
||||
/* Either:
|
||||
* 1. an actual integer key, or
|
||||
* 2. a pointer to a string prefixed by its uint32_t length, owned by us.
|
||||
*
|
||||
* ...depending on whether this is a string table or an int table. We would
|
||||
* make this a union of those two types, but C89 doesn't support statically
|
||||
* initializing a non-first union member. */
|
||||
typedef uintptr_t upb_tabkey;
|
||||
|
||||
UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
|
||||
char* mem = (char*)key;
|
||||
if (len) memcpy(len, mem, sizeof(*len));
|
||||
return mem + sizeof(*len);
|
||||
}
|
||||
|
||||
|
||||
/* upb_tabval *****************************************************************/
|
||||
|
||||
typedef struct {
|
||||
uint64_t val;
|
||||
} upb_tabval;
|
||||
|
||||
#define UPB_TABVALUE_EMPTY_INIT {-1}
|
||||
|
||||
|
||||
/* upb_table ******************************************************************/
|
||||
|
||||
typedef struct _upb_tabent {
|
||||
upb_tabkey key;
|
||||
upb_tabval val;
|
||||
|
||||
/* Internal chaining. This is const so we can create static initializers for
|
||||
* tables. We cast away const sometimes, but *only* when the containing
|
||||
* upb_table is known to be non-const. This requires a bit of care, but
|
||||
* the subtlety is confined to table.c. */
|
||||
const struct _upb_tabent *next;
|
||||
} upb_tabent;
|
||||
|
||||
typedef struct {
|
||||
size_t count; /* Number of entries in the hash part. */
|
||||
size_t mask; /* Mask to turn hash value -> bucket. */
|
||||
upb_ctype_t ctype; /* Type of all values. */
|
||||
uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */
|
||||
|
||||
/* Hash table entries.
|
||||
* Making this const isn't entirely accurate; what we really want is for it to
|
||||
* have the same const-ness as the table it's inside. But there's no way to
|
||||
* declare that in C. So we have to make it const so that we can statically
|
||||
* initialize const hash tables. Then we cast away const when we have to.
|
||||
*/
|
||||
const upb_tabent *entries;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* This table's allocator. We make the user pass it in to every relevant
|
||||
* function and only use this to check it in debug mode. We do this solely
|
||||
* to keep upb_table as small as possible. This might seem slightly paranoid
|
||||
* but the plan is to use upb_table for all map fields and extension sets in
|
||||
* a forthcoming message representation, so there could be a lot of these.
|
||||
* If this turns out to be too annoying later, we can change it (since this
|
||||
* is an internal-only header file). */
|
||||
upb_alloc *alloc;
|
||||
#endif
|
||||
} upb_table;
|
||||
|
||||
typedef struct {
|
||||
upb_table t;
|
||||
} upb_strtable;
|
||||
|
||||
typedef struct {
|
||||
upb_table t; /* For entries that don't fit in the array part. */
|
||||
const upb_tabval *array; /* Array part of the table. See const note above. */
|
||||
size_t array_size; /* Array part size. */
|
||||
size_t array_count; /* Array part number of elements. */
|
||||
} upb_inttable;
|
||||
|
||||
#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \
|
||||
{UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount}
|
||||
|
||||
#define UPB_EMPTY_INTTABLE_INIT(ctype) \
|
||||
UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0)
|
||||
|
||||
#define UPB_ARRAY_EMPTYENT -1
|
||||
|
||||
UPB_INLINE size_t upb_table_size(const upb_table *t) {
|
||||
if (t->size_lg2 == 0)
|
||||
return 0;
|
||||
else
|
||||
return 1 << t->size_lg2;
|
||||
}
|
||||
|
||||
/* Internal-only functions, in .h file only out of necessity. */
|
||||
UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
|
||||
return e->key == 0;
|
||||
}
|
||||
|
||||
/* Used by some of the unit tests for generic hashing functionality. */
|
||||
uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed);
|
||||
|
||||
UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
|
||||
return (uint32_t)key;
|
||||
}
|
||||
|
||||
static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
|
||||
return t->entries + (hash & t->mask);
|
||||
}
|
||||
|
||||
UPB_INLINE bool upb_arrhas(upb_tabval key) {
|
||||
return key.val != (uint64_t)-1;
|
||||
}
|
||||
|
||||
/* Initialize and uninitialize a table, respectively. If memory allocation
|
||||
* failed, false is returned that the table is uninitialized. */
|
||||
bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
|
||||
bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
|
||||
void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
|
||||
void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
|
||||
|
||||
UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
|
||||
return upb_inttable_init2(table, ctype, &upb_alloc_global);
|
||||
}
|
||||
|
||||
UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
|
||||
return upb_strtable_init2(table, ctype, &upb_alloc_global);
|
||||
}
|
||||
|
||||
UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
|
||||
upb_inttable_uninit2(table, &upb_alloc_global);
|
||||
}
|
||||
|
||||
UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
|
||||
upb_strtable_uninit2(table, &upb_alloc_global);
|
||||
}
|
||||
|
||||
/* Returns the number of values in the table. */
|
||||
size_t upb_inttable_count(const upb_inttable *t);
|
||||
UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
|
||||
return t->t.count;
|
||||
}
|
||||
|
||||
void upb_inttable_packedsize(const upb_inttable *t, size_t *size);
|
||||
void upb_strtable_packedsize(const upb_strtable *t, size_t *size);
|
||||
upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs,
|
||||
size_t size);
|
||||
upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs,
|
||||
size_t size);
|
||||
|
||||
/* Inserts the given key into the hashtable with the given value. The key must
|
||||
* not already exist in the hash table. For string tables, the key must be
|
||||
* NULL-terminated, and the table will make an internal copy of the key.
|
||||
* Inttables must not insert a value of UINTPTR_MAX.
|
||||
*
|
||||
* If a table resize was required but memory allocation failed, false is
|
||||
* returned and the table is unchanged. */
|
||||
bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
|
||||
upb_alloc *a);
|
||||
bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
|
||||
upb_value val, upb_alloc *a);
|
||||
|
||||
UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
|
||||
upb_value val) {
|
||||
return upb_inttable_insert2(t, key, val, &upb_alloc_global);
|
||||
}
|
||||
|
||||
UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
|
||||
size_t len, upb_value val) {
|
||||
return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
|
||||
}
|
||||
|
||||
/* For NULL-terminated strings. */
|
||||
UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
|
||||
upb_value val) {
|
||||
return upb_strtable_insert2(t, key, strlen(key), val);
|
||||
}
|
||||
|
||||
/* Looks up key in this table, returning "true" if the key was found.
|
||||
* If v is non-NULL, copies the value for this key into *v. */
|
||||
bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
|
||||
bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
|
||||
upb_value *v);
|
||||
|
||||
/* For NULL-terminated strings. */
|
||||
UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
|
||||
upb_value *v) {
|
||||
return upb_strtable_lookup2(t, key, strlen(key), v);
|
||||
}
|
||||
|
||||
/* Removes an item from the table. Returns true if the remove was successful,
|
||||
* and stores the removed item in *val if non-NULL. */
|
||||
bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
|
||||
bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
|
||||
upb_value *val, upb_alloc *alloc);
|
||||
|
||||
UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
|
||||
size_t len, upb_value *val) {
|
||||
return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
|
||||
}
|
||||
|
||||
/* For NULL-terminated strings. */
|
||||
UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
|
||||
upb_value *v) {
|
||||
return upb_strtable_remove2(t, key, strlen(key), v);
|
||||
}
|
||||
|
||||
/* Updates an existing entry in an inttable. If the entry does not exist,
|
||||
* returns false and does nothing. Unlike insert/remove, this does not
|
||||
* invalidate iterators. */
|
||||
bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
|
||||
|
||||
/* Handy routines for treating an inttable like a stack. May not be mixed with
|
||||
* other insert/remove calls. */
|
||||
bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
|
||||
upb_value upb_inttable_pop(upb_inttable *t);
|
||||
|
||||
UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
|
||||
return upb_inttable_push2(t, val, &upb_alloc_global);
|
||||
}
|
||||
|
||||
/* Convenience routines for inttables with pointer keys. */
|
||||
bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
|
||||
upb_alloc *a);
|
||||
bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
|
||||
bool upb_inttable_lookupptr(
|
||||
const upb_inttable *t, const void *key, upb_value *val);
|
||||
|
||||
UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
|
||||
upb_value val) {
|
||||
return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
|
||||
}
|
||||
|
||||
/* Optimizes the table for the current set of entries, for both memory use and
|
||||
* lookup time. Client should call this after all entries have been inserted;
|
||||
* inserting more entries is legal, but will likely require a table resize. */
|
||||
void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
|
||||
|
||||
UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
|
||||
upb_inttable_compact2(t, &upb_alloc_global);
|
||||
}
|
||||
|
||||
/* A special-case inlinable version of the lookup routine for 32-bit
|
||||
* integers. */
|
||||
UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
|
||||
upb_value *v) {
|
||||
*v = upb_value_int32(0); /* Silence compiler warnings. */
|
||||
if (key < t->array_size) {
|
||||
upb_tabval arrval = t->array[key];
|
||||
if (upb_arrhas(arrval)) {
|
||||
_upb_value_setval(v, arrval.val, t->t.ctype);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const upb_tabent *e;
|
||||
if (t->t.entries == NULL) return false;
|
||||
for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
|
||||
if ((uint32_t)e->key == key) {
|
||||
_upb_value_setval(v, e->val.val, t->t.ctype);
|
||||
return true;
|
||||
}
|
||||
if (e->next == NULL) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Exposed for testing only. */
|
||||
bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
|
||||
|
||||
/* Iterators ******************************************************************/
|
||||
|
||||
/* Iterators for int and string tables. We are subject to some kind of unusual
|
||||
* design constraints:
|
||||
*
|
||||
* For high-level languages:
|
||||
* - we must be able to guarantee that we don't crash or corrupt memory even if
|
||||
* the program accesses an invalidated iterator.
|
||||
*
|
||||
* For C++11 range-based for:
|
||||
* - iterators must be copyable
|
||||
* - iterators must be comparable
|
||||
* - it must be possible to construct an "end" value.
|
||||
*
|
||||
* Iteration order is undefined.
|
||||
*
|
||||
* Modifying the table invalidates iterators. upb_{str,int}table_done() is
|
||||
* guaranteed to work even on an invalidated iterator, as long as the table it
|
||||
* is iterating over has not been freed. Calling next() or accessing data from
|
||||
* an invalidated iterator yields unspecified elements from the table, but it is
|
||||
* guaranteed not to crash and to return real table elements (except when done()
|
||||
* is true). */
|
||||
|
||||
|
||||
/* upb_strtable_iter **********************************************************/
|
||||
|
||||
/* upb_strtable_iter i;
|
||||
* upb_strtable_begin(&i, t);
|
||||
* for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
|
||||
* const char *key = upb_strtable_iter_key(&i);
|
||||
* const upb_value val = upb_strtable_iter_value(&i);
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const upb_strtable *t;
|
||||
size_t index;
|
||||
} upb_strtable_iter;
|
||||
|
||||
void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
|
||||
void upb_strtable_next(upb_strtable_iter *i);
|
||||
bool upb_strtable_done(const upb_strtable_iter *i);
|
||||
const char *upb_strtable_iter_key(const upb_strtable_iter *i);
|
||||
size_t upb_strtable_iter_keylength(const upb_strtable_iter *i);
|
||||
upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
|
||||
void upb_strtable_iter_setdone(upb_strtable_iter *i);
|
||||
bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
|
||||
const upb_strtable_iter *i2);
|
||||
|
||||
|
||||
/* upb_inttable_iter **********************************************************/
|
||||
|
||||
/* upb_inttable_iter i;
|
||||
* upb_inttable_begin(&i, t);
|
||||
* for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
|
||||
* uintptr_t key = upb_inttable_iter_key(&i);
|
||||
* upb_value val = upb_inttable_iter_value(&i);
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const upb_inttable *t;
|
||||
size_t index;
|
||||
bool array_part;
|
||||
} upb_inttable_iter;
|
||||
|
||||
void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
|
||||
void upb_inttable_next(upb_inttable_iter *i);
|
||||
bool upb_inttable_done(const upb_inttable_iter *i);
|
||||
uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
|
||||
upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
|
||||
void upb_inttable_iter_setdone(upb_inttable_iter *i);
|
||||
bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
|
||||
const upb_inttable_iter *i2);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/port_undef.inc"
|
||||
#else
|
||||
#include "upb/port_undef.inc"
|
||||
#endif
|
||||
|
||||
#endif /* UPB_TABLE_H_ */
|
||||
+372
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
** This file contains shared definitions that are widely used across upb.
|
||||
**
|
||||
** This is a mixed C/C++ interface that offers a full API to both languages.
|
||||
** See the top-level README for more information.
|
||||
*/
|
||||
|
||||
#ifndef UPB_H_
|
||||
#define UPB_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <memory>
|
||||
namespace upb {
|
||||
class Arena;
|
||||
class Status;
|
||||
template <int N> class InlinedArena;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/port_def.inc"
|
||||
#else
|
||||
#include "upb/port_def.inc"
|
||||
#endif
|
||||
|
||||
/* upb_status *****************************************************************/
|
||||
|
||||
/* upb_status represents a success or failure status and error message.
|
||||
* It owns no resources and allocates no memory, so it should work
|
||||
* even in OOM situations. */
|
||||
|
||||
/* The maximum length of an error message before it will get truncated. */
|
||||
#define UPB_STATUS_MAX_MESSAGE 127
|
||||
|
||||
typedef struct {
|
||||
bool ok;
|
||||
char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */
|
||||
} upb_status;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char *upb_status_errmsg(const upb_status *status);
|
||||
bool upb_ok(const upb_status *status);
|
||||
|
||||
/* Any of the functions that write to a status object allow status to be NULL,
|
||||
* to support use cases where the function's caller does not care about the
|
||||
* status message. */
|
||||
void upb_status_clear(upb_status *status);
|
||||
void upb_status_seterrmsg(upb_status *status, const char *msg);
|
||||
void upb_status_seterrf(upb_status *status, const char *fmt, ...);
|
||||
void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
|
||||
|
||||
UPB_INLINE void upb_status_setoom(upb_status *status) {
|
||||
upb_status_seterrmsg(status, "out of memory");
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
class upb::Status {
|
||||
public:
|
||||
Status() { upb_status_clear(&status_); }
|
||||
|
||||
upb_status* ptr() { return &status_; }
|
||||
|
||||
/* Returns true if there is no error. */
|
||||
bool ok() const { return upb_ok(&status_); }
|
||||
|
||||
/* Guaranteed to be NULL-terminated. */
|
||||
const char *error_message() const { return upb_status_errmsg(&status_); }
|
||||
|
||||
/* The error message will be truncated if it is longer than
|
||||
* UPB_STATUS_MAX_MESSAGE-4. */
|
||||
void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); }
|
||||
void SetFormattedErrorMessage(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
upb_status_vseterrf(&status_, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/* Resets the status to a successful state with no message. */
|
||||
void Clear() { upb_status_clear(&status_); }
|
||||
|
||||
private:
|
||||
upb_status status_;
|
||||
};
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** upb_strview ************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const char *data;
|
||||
size_t size;
|
||||
} upb_strview;
|
||||
|
||||
UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
|
||||
upb_strview ret;
|
||||
ret.data = data;
|
||||
ret.size = size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
UPB_INLINE upb_strview upb_strview_makez(const char *data) {
|
||||
return upb_strview_make(data, strlen(data));
|
||||
}
|
||||
|
||||
UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
|
||||
return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
|
||||
}
|
||||
|
||||
#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
|
||||
|
||||
#define UPB_STRVIEW_FORMAT "%.*s"
|
||||
#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
|
||||
|
||||
/** upb_alloc *****************************************************************/
|
||||
|
||||
/* A upb_alloc is a possibly-stateful allocator object.
|
||||
*
|
||||
* It could either be an arena allocator (which doesn't require individual
|
||||
* free() calls) or a regular malloc() (which does). The client must therefore
|
||||
* free memory unless it knows that the allocator is an arena allocator. */
|
||||
|
||||
struct upb_alloc;
|
||||
typedef struct upb_alloc upb_alloc;
|
||||
|
||||
/* A malloc()/free() function.
|
||||
* If "size" is 0 then the function acts like free(), otherwise it acts like
|
||||
* realloc(). Only "oldsize" bytes from a previous allocation are preserved. */
|
||||
typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
|
||||
size_t size);
|
||||
|
||||
struct upb_alloc {
|
||||
upb_alloc_func *func;
|
||||
};
|
||||
|
||||
UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
|
||||
UPB_ASSERT(alloc);
|
||||
return alloc->func(alloc, NULL, 0, size);
|
||||
}
|
||||
|
||||
UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
|
||||
size_t size) {
|
||||
UPB_ASSERT(alloc);
|
||||
return alloc->func(alloc, ptr, oldsize, size);
|
||||
}
|
||||
|
||||
UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
|
||||
assert(alloc);
|
||||
alloc->func(alloc, ptr, 0, 0);
|
||||
}
|
||||
|
||||
/* The global allocator used by upb. Uses the standard malloc()/free(). */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern upb_alloc upb_alloc_global;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/* Functions that hard-code the global malloc.
|
||||
*
|
||||
* We still get benefit because we can put custom logic into our global
|
||||
* allocator, like injecting out-of-memory faults in debug/testing builds. */
|
||||
|
||||
UPB_INLINE void *upb_gmalloc(size_t size) {
|
||||
return upb_malloc(&upb_alloc_global, size);
|
||||
}
|
||||
|
||||
UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
|
||||
return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
|
||||
}
|
||||
|
||||
UPB_INLINE void upb_gfree(void *ptr) {
|
||||
upb_free(&upb_alloc_global, ptr);
|
||||
}
|
||||
|
||||
/* upb_arena ******************************************************************/
|
||||
|
||||
/* upb_arena is a specific allocator implementation that uses arena allocation.
|
||||
* The user provides an allocator that will be used to allocate the underlying
|
||||
* arena blocks. Arenas by nature do not require the individual allocations
|
||||
* to be freed. However the Arena does allow users to register cleanup
|
||||
* functions that will run when the arena is destroyed.
|
||||
*
|
||||
* A upb_arena is *not* thread-safe.
|
||||
*
|
||||
* You could write a thread-safe arena allocator that satisfies the
|
||||
* upb_alloc interface, but it would not be as efficient for the
|
||||
* single-threaded case. */
|
||||
|
||||
typedef void upb_cleanup_func(void *ud);
|
||||
|
||||
struct upb_arena;
|
||||
typedef struct upb_arena upb_arena;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Creates an arena from the given initial block (if any -- n may be 0).
|
||||
* Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
|
||||
* is a fixed-size arena and cannot grow. */
|
||||
upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
|
||||
void upb_arena_free(upb_arena *a);
|
||||
bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
|
||||
size_t upb_arena_bytesallocated(const upb_arena *a);
|
||||
|
||||
UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
|
||||
|
||||
/* Convenience wrappers around upb_alloc functions. */
|
||||
|
||||
UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
|
||||
return upb_malloc(upb_arena_alloc(a), size);
|
||||
}
|
||||
|
||||
UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
|
||||
size_t size) {
|
||||
return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size);
|
||||
}
|
||||
|
||||
UPB_INLINE upb_arena *upb_arena_new(void) {
|
||||
return upb_arena_init(NULL, 0, &upb_alloc_global);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
class upb::Arena {
|
||||
public:
|
||||
/* A simple arena with no initial memory block and the default allocator. */
|
||||
Arena() : ptr_(upb_arena_new(), upb_arena_free) {}
|
||||
|
||||
upb_arena* ptr() { return ptr_.get(); }
|
||||
|
||||
/* Allows this arena to be used as a generic allocator.
|
||||
*
|
||||
* The arena does not need free() calls so when using Arena as an allocator
|
||||
* it is safe to skip them. However they are no-ops so there is no harm in
|
||||
* calling free() either. */
|
||||
upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); }
|
||||
|
||||
/* Add a cleanup function to run when the arena is destroyed.
|
||||
* Returns false on out-of-memory. */
|
||||
bool AddCleanup(void *ud, upb_cleanup_func* func) {
|
||||
return upb_arena_addcleanup(ptr_.get(), ud, func);
|
||||
}
|
||||
|
||||
/* Total number of bytes that have been allocated. It is undefined what
|
||||
* Realloc() does to &arena_ counter. */
|
||||
size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* upb::InlinedArena **********************************************************/
|
||||
|
||||
/* upb::InlinedArena seeds the arenas with a predefined amount of memory. No
|
||||
* heap memory will be allocated until the initial block is exceeded.
|
||||
*
|
||||
* These types only exist in C++ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
template <int N> class upb::InlinedArena : public upb::Arena {
|
||||
public:
|
||||
InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {}
|
||||
|
||||
upb_arena* ptr() { return ptr_.get(); }
|
||||
|
||||
private:
|
||||
InlinedArena(const InlinedArena*) = delete;
|
||||
InlinedArena& operator=(const InlinedArena*) = delete;
|
||||
|
||||
std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
|
||||
char initial_block_[N];
|
||||
};
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Constants ******************************************************************/
|
||||
|
||||
/* Generic function type. */
|
||||
typedef void upb_func(void);
|
||||
|
||||
/* A list of types as they are encoded on-the-wire. */
|
||||
typedef enum {
|
||||
UPB_WIRE_TYPE_VARINT = 0,
|
||||
UPB_WIRE_TYPE_64BIT = 1,
|
||||
UPB_WIRE_TYPE_DELIMITED = 2,
|
||||
UPB_WIRE_TYPE_START_GROUP = 3,
|
||||
UPB_WIRE_TYPE_END_GROUP = 4,
|
||||
UPB_WIRE_TYPE_32BIT = 5
|
||||
} upb_wiretype_t;
|
||||
|
||||
/* The types a field can have. Note that this list is not identical to the
|
||||
* types defined in descriptor.proto, which gives INT32 and SINT32 separate
|
||||
* types (we distinguish the two with the "integer encoding" enum below). */
|
||||
typedef enum {
|
||||
/* Types stored in 1 byte. */
|
||||
UPB_TYPE_BOOL = 1,
|
||||
/* Types stored in 4 bytes. */
|
||||
UPB_TYPE_FLOAT = 2,
|
||||
UPB_TYPE_INT32 = 3,
|
||||
UPB_TYPE_UINT32 = 4,
|
||||
UPB_TYPE_ENUM = 5, /* Enum values are int32. */
|
||||
/* Types stored as pointers (probably 4 or 8 bytes). */
|
||||
UPB_TYPE_STRING = 6,
|
||||
UPB_TYPE_BYTES = 7,
|
||||
UPB_TYPE_MESSAGE = 8,
|
||||
/* Types stored as 8 bytes. */
|
||||
UPB_TYPE_DOUBLE = 9,
|
||||
UPB_TYPE_INT64 = 10,
|
||||
UPB_TYPE_UINT64 = 11
|
||||
} upb_fieldtype_t;
|
||||
|
||||
/* The repeated-ness of each field; this matches descriptor.proto. */
|
||||
typedef enum {
|
||||
UPB_LABEL_OPTIONAL = 1,
|
||||
UPB_LABEL_REQUIRED = 2,
|
||||
UPB_LABEL_REPEATED = 3
|
||||
} upb_label_t;
|
||||
|
||||
/* Descriptor types, as defined in descriptor.proto. */
|
||||
typedef enum {
|
||||
UPB_DESCRIPTOR_TYPE_DOUBLE = 1,
|
||||
UPB_DESCRIPTOR_TYPE_FLOAT = 2,
|
||||
UPB_DESCRIPTOR_TYPE_INT64 = 3,
|
||||
UPB_DESCRIPTOR_TYPE_UINT64 = 4,
|
||||
UPB_DESCRIPTOR_TYPE_INT32 = 5,
|
||||
UPB_DESCRIPTOR_TYPE_FIXED64 = 6,
|
||||
UPB_DESCRIPTOR_TYPE_FIXED32 = 7,
|
||||
UPB_DESCRIPTOR_TYPE_BOOL = 8,
|
||||
UPB_DESCRIPTOR_TYPE_STRING = 9,
|
||||
UPB_DESCRIPTOR_TYPE_GROUP = 10,
|
||||
UPB_DESCRIPTOR_TYPE_MESSAGE = 11,
|
||||
UPB_DESCRIPTOR_TYPE_BYTES = 12,
|
||||
UPB_DESCRIPTOR_TYPE_UINT32 = 13,
|
||||
UPB_DESCRIPTOR_TYPE_ENUM = 14,
|
||||
UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
|
||||
UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
|
||||
UPB_DESCRIPTOR_TYPE_SINT32 = 17,
|
||||
UPB_DESCRIPTOR_TYPE_SINT64 = 18
|
||||
} upb_descriptortype_t;
|
||||
|
||||
extern const uint8_t upb_desctype_to_fieldtype[];
|
||||
|
||||
#if COCOAPODS==1
|
||||
#include "third_party/upb/upb/port_undef.inc"
|
||||
#else
|
||||
#include "upb/port_undef.inc"
|
||||
#endif
|
||||
|
||||
#endif /* UPB_H_ */
|
||||
Reference in New Issue
Block a user