summaryrefslogtreecommitdiff
path: root/upb/upb.h
diff options
context:
space:
mode:
authorJosh Haberman <haberman@google.com>2013-02-15 16:27:18 -0800
committerJosh Haberman <haberman@google.com>2013-02-15 16:27:18 -0800
commit7d3e2bd2c4cfd1296d1d6f996d7548de26540d41 (patch)
treeb4b35967b3322c65cfb1a32220e8718de09d85fc /upb/upb.h
parentea198bdcf947ba4bd51474bdd4f7b82b5e4cf41d (diff)
Sync with 8 months of Google-internal development.
Many things have changed and been simplified. The memory-management story for upb_def and upb_handlers is much more robust; upb_def and upb_handlers should be fairly stable interfaces now. There is still much work to do for the runtime component (upb_sink).
Diffstat (limited to 'upb/upb.h')
-rw-r--r--upb/upb.h303
1 files changed, 222 insertions, 81 deletions
diff --git a/upb/upb.h b/upb/upb.h
index 245d86f..a7a3ed1 100644
--- a/upb/upb.h
+++ b/upb/upb.h
@@ -5,6 +5,9 @@
* Author: Josh Haberman <jhaberman@gmail.com>
*
* 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_
@@ -25,6 +28,28 @@ extern "C" {
#define INLINE static inline
#endif
+#if __STDC_VERSION__ >= 199901L
+#define UPB_C99
+#endif
+
+#if (defined(__cplusplus) && __cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define UPB_CXX11
+#endif
+
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) && !defined(UPB_NO_CXX11)
+#define UPB_DISALLOW_POD_OPS(class_name) \
+ class_name() = delete; \
+ ~class_name() = delete; \
+ class_name(const class_name&) = delete; \
+ void operator=(const class_name&) = delete;
+#else
+#define UPB_DISALLOW_POD_OPS(class_name) \
+ class_name(); \
+ ~class_name(); \
+ class_name(const class_name&); \
+ void operator=(const class_name&);
+#endif
+
#ifdef __GNUC__
#define UPB_NORETURN __attribute__((__noreturn__))
#else
@@ -32,12 +57,33 @@ extern "C" {
#endif
#ifndef UINT16_MAX
-#define UINT16_MAX 65535
+#define UINT16_MAX 0xffff
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
#endif
#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+// For our C-based inheritance, sometimes it's necessary to upcast an object to
+// its base class. We try to minimize the need for this by replicating base
+// class functions in the derived class -- the derived class functions simply
+// forward to the base class implementations. This strategy simplifies the C++
+// API since we can't use real C++ inheritance.
+#define upb_upcast(obj) (&(obj)->base)
+#define upb_upcast2(obj) upb_upcast(upb_upcast(obj))
+
+char *upb_strdup(const char *s);
+
+#define UPB_UNUSED(var) (void)var
+
+// For asserting something about a variable when the variable is not used for
+// anything else. This prevents "unused variable" warnings when compiling in
+// debug mode.
+#define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate)
+
// The maximum that any submessages can be nested. Matches proto2's limit.
// At the moment this specifies the size of several statically-sized arrays
// and therefore setting it high will cause more memory to be used. Will
@@ -45,19 +91,7 @@ extern "C" {
// TODO: make this a runtime-settable property of upb_handlers.
#define UPB_MAX_NESTING 64
-// The maximum number of fields that any one .proto type can have. Note that
-// this is very different than the max field number. It is hard to imagine a
-// scenario where more than 2k fields (each with its own name and field number)
-// makes sense. The .proto file to describe it would be 2000 lines long and
-// contain 2000 unique names.
-//
-// With this limit we can store a has-bit offset in 8 bits (2**8 * 8 = 2048)
-// and we can store a value offset in 16 bits, since the maximum message
-// size is 16,640 bytes (2**8 has-bits + 2048 * 8-byte value). Note that
-// strings and arrays are not counted in this, only the *pointer* to them is.
-// An individual string or array is unaffected by this 16k byte limit.
-#define UPB_MAX_FIELDS (2048)
-
+// Inherent limit of protobuf wire format and schema definition.
#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
// Nested type names are separated by periods.
@@ -81,7 +115,99 @@ extern "C" {
#define UPB_MAX_TYPE_DEPTH 64
-/* upb_value ******************************************************************/
+/* upb::Status ****************************************************************/
+
+#ifdef __cplusplus
+namespace upb { class Status; }
+typedef upb::Status upb_status;
+#else
+struct upb_status;
+typedef struct upb_status upb_status;
+#endif
+
+typedef enum {
+ UPB_OK, // The operation completed successfully.
+ UPB_SUSPENDED, // The operation was suspended and may be resumed later.
+ UPB_ERROR, // An error occurred.
+} upb_success_t;
+
+typedef struct {
+ const char *name;
+ // Writes a NULL-terminated string to "buf" containing an error message for
+ // the given error code, returning false if the message was too large to fit.
+ bool (*code_to_string)(int code, char *buf, size_t len);
+} upb_errorspace;
+
+#ifdef __cplusplus
+
+class upb::Status {
+ public:
+ typedef upb_success_t Success;
+
+ Status();
+ ~Status();
+
+ bool ok();
+ bool eof();
+
+ const char *GetString() const;
+ void SetEof();
+ void SetErrorLiteral(const char* msg);
+ void Clear();
+
+ private:
+#else
+struct upb_status {
+#endif
+ bool error;
+ bool eof_;
+
+ // Specific status code defined by some error space (optional).
+ int code;
+ upb_errorspace *space;
+
+ // Error message (optional).
+ const char *str; // NULL when no message is present. NULL-terminated.
+ char *buf; // Owned by the status.
+ size_t bufsize;
+};
+
+#define UPB_STATUS_INIT {UPB_OK, false, 0, NULL, NULL, NULL, 0}
+
+void upb_status_init(upb_status *status);
+void upb_status_uninit(upb_status *status);
+
+bool upb_ok(const upb_status *status);
+bool upb_eof(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_seterrliteral(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *msg, ...);
+void upb_status_setcode(upb_status *status, upb_errorspace *space, int code);
+void upb_status_seteof(upb_status *status);
+// The returned string is invalidated by any other call into the status.
+const char *upb_status_getstr(const upb_status *status);
+void upb_status_copy(upb_status *to, const upb_status *from);
+
+// Like vasprintf (which allocates a string large enough for the result), but
+// uses *buf (which can be NULL) as a starting point and reallocates it only if
+// the new value will not fit. "size" is updated to reflect the allocated size
+// of the buffer. Starts writing at the given offset into the string; bytes
+// preceding this offset are unaffected. Returns the new length of the string,
+// or -1 on memory allocation failure.
+int upb_vrprintf(char **buf, size_t *size, size_t ofs,
+ const char *fmt, va_list args);
+
+
+/* upb::Value *****************************************************************/
+
+// TODO(haberman): upb::Value is gross and should be retired from the public
+// interface (we *may* still want to keep it for internal use). upb::Handlers
+// and upb::Def should replace their use of Value with one function for each C
+// type.
// Clients should not need to access these enum values; they are used internally
// to do typechecks of upb_value accesses.
@@ -93,13 +219,19 @@ typedef enum {
UPB_CTYPE_DOUBLE = 5,
UPB_CTYPE_FLOAT = 6,
UPB_CTYPE_BOOL = 7,
- UPB_CTYPE_PTR = 8,
- UPB_CTYPE_BYTEREGION = 9,
- UPB_CTYPE_FIELDDEF = 10,
+ UPB_CTYPE_CSTR = 8,
+ UPB_CTYPE_PTR = 9,
+ UPB_CTYPE_BYTEREGION = 10,
+ UPB_CTYPE_FIELDDEF = 11,
} upb_ctype_t;
-struct _upb_byteregion;
-struct _upb_fielddef;
+#ifdef __cplusplus
+namespace upb { class ByteRegion; }
+typedef upb::ByteRegion upb_byteregion;
+#else
+struct upb_byteregion;
+typedef struct upb_byteregion upb_byteregion;
+#endif
// A single .proto value. The owner must have an out-of-band way of knowing
// the type, so that it knows which union member to use.
@@ -112,9 +244,10 @@ typedef struct {
double _double;
float _float;
bool _bool;
- void *_void;
- struct _upb_byteregion *byteregion;
- const struct _upb_fielddef *fielddef;
+ char *cstr;
+ void *ptr;
+ const void *constptr;
+ upb_byteregion *byteregion;
} val;
#ifndef NDEBUG
@@ -124,12 +257,32 @@ typedef struct {
#endif
} upb_value;
+#ifdef UPB_C99
+#define UPB_VAL_INIT(v, member) {.member = v}
+#endif
+// TODO(haberman): C++
+
#ifdef NDEBUG
#define SET_TYPE(dest, val)
+#define UPB_VALUE_INIT(v, member, type) {UPB_VAL_INIT(v, member)}
#else
#define SET_TYPE(dest, val) dest = val
+#define UPB_VALUE_INIT(v, member, type) {UPB_VAL_INIT(v, member), type}
#endif
+#define UPB_VALUE_INIT_INT32(v) UPB_VALUE_INIT(v, int32, UPB_CTYPE_INT32)
+#define UPB_VALUE_INIT_INT64(v) UPB_VALUE_INIT(v, int64, UPB_CTYPE_INT64)
+#define UPB_VALUE_INIT_UINT32(v) UPB_VALUE_INIT(v, uint32, UPB_CTYPE_UINT32)
+#define UPB_VALUE_INIT_UINT64(v) UPB_VALUE_INIT(v, uint64, UPB_CTYPE_UINT64)
+#define UPB_VALUE_INIT_DOUBLE(v) UPB_VALUE_INIT(v, _double, UPB_CTYPE_DOUBLE)
+#define UPB_VALUE_INIT_FLOAT(v) UPB_VALUE_INIT(v, _float, UPB_CTYPE_FLOAT)
+#define UPB_VALUE_INIT_BOOL(v) UPB_VALUE_INIT(v, _bool, UPB_CTYPE_BOOL)
+#define UPB_VALUE_INIT_CSTR(v) UPB_VALUE_INIT(v, cstr, UPB_CTYPE_CSTR)
+#define UPB_VALUE_INIT_PTR(v) UPB_VALUE_INIT(v, ptr, UPB_CTYPE_PTR)
+#define UPB_VALUE_INIT_CONSTPTR(v) UPB_VALUE_INIT(v, constptr, UPB_CTYPE_PTR)
+// Non-existent type, all reads will fail.
+#define UPB_VALUE_INIT_NONE UPB_VALUE_INIT(NULL, ptr, -1)
+
// For each value type, define the following set of functions:
//
// // Get/set an int32 from a upb_value.
@@ -174,12 +327,9 @@ ALL(int64, int64, int64_t, UPB_CTYPE_INT64);
ALL(uint32, uint32, uint32_t, UPB_CTYPE_UINT32);
ALL(uint64, uint64, uint64_t, UPB_CTYPE_UINT64);
ALL(bool, _bool, bool, UPB_CTYPE_BOOL);
-ALL(ptr, _void, void*, UPB_CTYPE_PTR);
-ALL(byteregion, byteregion, struct _upb_byteregion*, UPB_CTYPE_BYTEREGION);
-
-// upb_fielddef should never be modified from a callback
-// (ie. when they're getting passed through a upb_value).
-ALL(fielddef, fielddef, const struct _upb_fielddef*, UPB_CTYPE_FIELDDEF);
+ALL(cstr, cstr, char*, UPB_CTYPE_CSTR);
+ALL(ptr, ptr, void*, UPB_CTYPE_PTR);
+ALL(byteregion, byteregion, upb_byteregion*, UPB_CTYPE_BYTEREGION);
#ifdef __KERNEL__
// Linux kernel modules are compiled without SSE and therefore are incapable
@@ -199,64 +349,55 @@ ALL(float, _float, float, UPB_CTYPE_FLOAT);
extern upb_value UPB_NO_VALUE;
+#ifdef __cplusplus
+} // extern "C"
-/* upb_status *****************************************************************/
-
-typedef enum {
- UPB_OK, // The operation completed successfully.
- UPB_SUSPENDED, // The operation was suspended and may be resumed later.
- UPB_ERROR, // An error occurred.
-} upb_success_t;
-
-typedef struct {
- const char *name;
- // Writes a NULL-terminated string to "buf" containing an error message for
- // the given error code, returning false if the message was too large to fit.
- bool (*code_to_string)(int code, char *buf, size_t len);
-} upb_errorspace;
-
-typedef struct {
- bool error;
- bool eof;
-
- // Specific status code defined by some error space (optional).
- int code;
- upb_errorspace *space;
-
- // Error message (optional).
- const char *str; // NULL when no message is present. NULL-terminated.
- char *buf; // Owned by the status.
- size_t bufsize;
-} upb_status;
-
-#define UPB_STATUS_INIT {UPB_OK, false, 0, NULL, NULL, NULL, 0}
+namespace upb {
-void upb_status_init(upb_status *status);
-void upb_status_uninit(upb_status *status);
+typedef upb_value Value;
-INLINE bool upb_ok(const upb_status *status) { return !status->error; }
-INLINE bool upb_eof(const upb_status *status) { return status->eof; }
+template <typename T> T GetValue(Value v);
+template <typename T> Value MakeValue(T v);
-void upb_status_clear(upb_status *status);
-void upb_status_seterrliteral(upb_status *status, const char *msg);
-void upb_status_seterrf(upb_status *s, const char *msg, ...);
-void upb_status_setcode(upb_status *s, upb_errorspace *space, int code);
-INLINE void upb_status_seteof(upb_status *s) { s->eof = true; }
-// The returned string is invalidated by any other call into the status.
-const char *upb_status_getstr(const upb_status *s);
-void upb_status_copy(upb_status *to, const upb_status *from);
+#define UPB_VALUE_ACCESSORS(type, ctype) \
+ template <> inline ctype GetValue<ctype>(Value v) { \
+ return upb_value_get ## type(v); \
+ } \
+ template <> inline Value MakeValue<ctype>(ctype v) { \
+ return upb_value_ ## type(v); \
+ }
-// Like vasprintf (which allocates a string large enough for the result), but
-// uses *buf (which can be NULL) as a starting point and reallocates it only if
-// the new value will not fit. "size" is updated to reflect the allocated size
-// of the buffer. Starts writing at the given offset into the string; bytes
-// preceding this offset are unaffected. Returns the new length of the string,
-// or -1 on memory allocation failure.
-int upb_vrprintf(char **buf, size_t *size, size_t ofs,
- const char *fmt, va_list args);
+UPB_VALUE_ACCESSORS(double, double);
+UPB_VALUE_ACCESSORS(float, float);
+UPB_VALUE_ACCESSORS(int32, int32_t);
+UPB_VALUE_ACCESSORS(int64, int64_t);
+UPB_VALUE_ACCESSORS(uint32, uint32_t);
+UPB_VALUE_ACCESSORS(uint64, uint64_t);
+UPB_VALUE_ACCESSORS(bool, bool);
+
+#undef UPB_VALUE_ACCESSORS
+
+template <typename T> inline T* GetPtrValue(Value v) {
+ return static_cast<T*>(upb_value_getptr(v));
+}
+template <typename T> inline Value MakePtrValue(T* v) {
+ return upb_value_ptr(static_cast<void*>(v));
+}
+
+// C++ Wrappers
+inline Status::Status() { upb_status_init(this); }
+inline Status::~Status() { upb_status_uninit(this); }
+inline bool Status::ok() { return upb_ok(this); }
+inline bool Status::eof() { return upb_eof(this); }
+inline const char *Status::GetString() const { return upb_status_getstr(this); }
+inline void Status::SetEof() { upb_status_seteof(this); }
+inline void Status::SetErrorLiteral(const char* msg) {
+ upb_status_seterrliteral(this, msg);
+}
+inline void Status::Clear() { upb_status_clear(this); }
+
+} // namespace upb
-#ifdef __cplusplus
-} /* extern "C" */
#endif
#endif /* UPB_H_ */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback