summaryrefslogtreecommitdiff
path: root/upb/env.h
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2015-05-08 16:56:29 -0700
committerJosh Haberman <jhaberman@gmail.com>2015-05-08 16:56:29 -0700
commit3bd691a4975b2267ff04611507e766a7f9f87e83 (patch)
treee5628144f6f920d9ccf792a1499e55503e6ff4d2 /upb/env.h
parent87fc2c516bff207f880c71526926842fd8dcc77e (diff)
Google-internal development.
Diffstat (limited to 'upb/env.h')
-rw-r--r--upb/env.h256
1 files changed, 256 insertions, 0 deletions
diff --git a/upb/env.h b/upb/env.h
new file mode 100644
index 0000000..500b0ac
--- /dev/null
+++ b/upb/env.h
@@ -0,0 +1,256 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2014 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * A upb::Environment provides a means for injecting malloc and an
+ * error-reporting callback into encoders/decoders. This allows them to be
+ * independent of nearly all assumptions about their actual environment.
+ *
+ * It is also a container for allocating the encoders/decoders themselves that
+ * insulates clients from knowing their actual size. This provides ABI
+ * compatibility even if the size of the objects change. And this allows the
+ * structure definitions to be in the .c files instead of the .h files, making
+ * the .h files smaller and more readable.
+ */
+
+#include "upb/upb.h"
+
+#ifndef UPB_ENV_H_
+#define UPB_ENV_H_
+
+#ifdef __cplusplus
+namespace upb {
+class Environment;
+class SeededAllocator;
+}
+#endif
+
+UPB_DECLARE_TYPE(upb::Environment, upb_env);
+UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc);
+
+typedef void *upb_alloc_func(void *ud, void *ptr, size_t oldsize, size_t size);
+typedef void upb_cleanup_func(void *ud);
+typedef bool upb_error_func(void *ud, const upb_status *status);
+
+// An environment is *not* thread-safe.
+UPB_DEFINE_CLASS0(upb::Environment,
+ public:
+ Environment();
+ ~Environment();
+
+ // Set a custom memory allocation function for the environment. May ONLY
+ // be called before any calls to Malloc()/Realloc()/AddCleanup() below.
+ // If this is not called, the system realloc() function will be used.
+ // The given user pointer "ud" will be passed to the allocation function.
+ //
+ // The allocation function will not receive corresponding "free" calls. it
+ // must ensure that the memory is valid for the lifetime of the Environment,
+ // but it may be reclaimed any time thereafter. The likely usage is that
+ // "ud" points to a stateful allocator, and that the allocator frees all
+ // memory, arena-style, when it is destroyed. In this case the allocator must
+ // outlive the Environment. Another possibility is that the allocation
+ // function returns GC-able memory that is guaranteed to be GC-rooted for the
+ // life of the Environment.
+ void SetAllocationFunction(upb_alloc_func* alloc, void* ud);
+
+ template<class T>
+ void SetAllocator(T* allocator) {
+ SetAllocationFunction(allocator->GetAllocationFunction(), allocator);
+ }
+
+ // Set a custom error reporting function.
+ void SetErrorFunction(upb_error_func* func, void* ud);
+
+ // Set the error reporting function to simply copy the status to the given
+ // status and abort.
+ void ReportErrorsTo(Status* status);
+
+ // Returns true if all allocations and AddCleanup() calls have succeeded,
+ // and no errors were reported with ReportError() (except ones that recovered
+ // successfully).
+ bool ok() const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Functions for use by encoders/decoders.
+
+ // Reports an error to this environment's callback, returning true if
+ // the caller should try to recover.
+ bool ReportError(const Status* status);
+
+ // Allocate memory. Uses the environment's allocation function.
+ //
+ // There is no need to free(). All memory will be freed automatically, but is
+ // guaranteed to outlive the Environment.
+ void* Malloc(size_t size);
+
+ // Reallocate memory. Preserves "oldsize" bytes from the existing buffer
+ // Requires: oldsize <= existing_size.
+ //
+ // TODO(haberman): should we also enforce that oldsize <= size?
+ void* Realloc(void* ptr, size_t oldsize, size_t size);
+
+ // Add a cleanup function to run when the environment is destroyed.
+ // Returns false on out-of-memory.
+ //
+ // The first call to AddCleanup() after SetAllocationFunction() is guaranteed
+ // to return true -- this makes it possible to robustly set a cleanup handler
+ // for a custom allocation function.
+ bool AddCleanup(upb_cleanup_func* func, void* ud);
+
+ // Total number of bytes that have been allocated. It is undefined what
+ // Realloc() does to this counter.
+ size_t BytesAllocated() const;
+
+ private:
+ UPB_DISALLOW_COPY_AND_ASSIGN(Environment);
+,
+UPB_DEFINE_STRUCT0(upb_env,
+ bool ok_;
+ size_t bytes_allocated;
+
+ // Alloc function.
+ upb_alloc_func *alloc;
+ void *alloc_ud;
+
+ // Error-reporting function.
+ upb_error_func *err;
+ void *err_ud;
+
+ // Userdata for default alloc func.
+ void *default_alloc_ud;
+
+ // Cleanup entries. Pointer to a cleanup_ent, defined in env.c
+ void *cleanup_head;
+
+ // For future expansion, since the size of this struct is exposed to users.
+ void *future1;
+ void *future2;
+));
+
+UPB_BEGIN_EXTERN_C
+
+void upb_env_init(upb_env *e);
+void upb_env_uninit(upb_env *e);
+void upb_env_setallocfunc(upb_env *e, upb_alloc_func *func, void *ud);
+void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud);
+void upb_env_reporterrorsto(upb_env *e, upb_status *status);
+bool upb_env_ok(const upb_env *e);
+bool upb_env_reporterror(upb_env *e, const upb_status *status);
+void *upb_env_malloc(upb_env *e, size_t size);
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size);
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud);
+size_t upb_env_bytesallocated(const upb_env *e);
+
+UPB_END_EXTERN_C
+
+// An allocator that allocates from an initial memory region (likely the stack)
+// before falling back to another allocator.
+UPB_DEFINE_CLASS0(upb::SeededAllocator,
+ public:
+ SeededAllocator(void *mem, size_t len);
+ ~SeededAllocator();
+
+ // Set a custom fallback memory allocation function for the allocator, to use
+ // once the initial region runs out.
+ //
+ // May ONLY be called before GetAllocationFunction(). If this is not
+ // called, the system realloc() will be the fallback allocator.
+ void SetFallbackAllocator(upb_alloc_func *alloc, void *ud);
+
+ // Gets the allocation function for this allocator.
+ upb_alloc_func* GetAllocationFunction();
+
+ private:
+ UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator);
+,
+UPB_DEFINE_STRUCT0(upb_seededalloc,
+ // Fallback alloc function.
+ upb_alloc_func *alloc;
+ upb_cleanup_func *alloc_cleanup;
+ void *alloc_ud;
+ bool need_cleanup;
+ bool returned_allocfunc;
+
+ // Userdata for default alloc func.
+ void *default_alloc_ud;
+
+ // Pointers for the initial memory region.
+ void *mem_base;
+ void *mem_ptr;
+ void *mem_limit;
+
+ // For future expansion, since the size of this struct is exposed to users.
+ void *future1;
+ void *future2;
+));
+
+UPB_BEGIN_EXTERN_C
+
+void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len);
+void upb_seededalloc_uninit(upb_seededalloc *a);
+void upb_seededalloc_setfallbackalloc(upb_seededalloc *a, upb_alloc_func *func,
+ void *ud);
+upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+
+inline Environment::Environment() {
+ upb_env_init(this);
+}
+inline Environment::~Environment() {
+ upb_env_uninit(this);
+}
+inline void Environment::SetAllocationFunction(upb_alloc_func *alloc,
+ void *ud) {
+ upb_env_setallocfunc(this, alloc, ud);
+}
+inline void Environment::SetErrorFunction(upb_error_func *func, void *ud) {
+ upb_env_seterrorfunc(this, func, ud);
+}
+inline void Environment::ReportErrorsTo(Status* status) {
+ upb_env_reporterrorsto(this, status);
+}
+inline bool Environment::ok() const {
+ return upb_env_ok(this);
+}
+inline bool Environment::ReportError(const Status* status) {
+ return upb_env_reporterror(this, status);
+}
+inline void *Environment::Malloc(size_t size) {
+ return upb_env_malloc(this, size);
+}
+inline void *Environment::Realloc(void *ptr, size_t oldsize, size_t size) {
+ return upb_env_realloc(this, ptr, oldsize, size);
+}
+inline bool Environment::AddCleanup(upb_cleanup_func *func, void *ud) {
+ return upb_env_addcleanup(this, func, ud);
+}
+inline size_t Environment::BytesAllocated() const {
+ return upb_env_bytesallocated(this);
+}
+
+inline SeededAllocator::SeededAllocator(void *mem, size_t len) {
+ upb_seededalloc_init(this, mem, len);
+}
+inline SeededAllocator::~SeededAllocator() {
+ upb_seededalloc_uninit(this);
+}
+inline void SeededAllocator::SetFallbackAllocator(upb_alloc_func *alloc,
+ void *ud) {
+ upb_seededalloc_setfallbackalloc(this, alloc, ud);
+}
+inline upb_alloc_func *SeededAllocator::GetAllocationFunction() {
+ return upb_seededalloc_getallocfunc(this);
+}
+
+} // namespace upb
+
+#endif // __cplusplus
+
+#endif // UPB_ENV_H_
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback