#ifndef RALLOC_H
#define RALLOC_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
#include "macros.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/**
* \def ralloc(ctx, type)
* Allocate a new object chained off of the given context.
void ralloc_steal(const void *new_ctx, void *ptr);
/**
- * Return the given pointer's ralloc context.
+ * Reparent all children from one context to another.
+ *
+ * This effectively calls ralloc_steal(new_ctx, child) for all children of \p old_ctx.
*/
-void *ralloc_parent(const void *ptr);
+void ralloc_adopt(const void *new_ctx, void *old_ctx);
/**
- * Return a context whose memory will be automatically freed at program exit.
- *
- * The first call to this function creates a context and registers a handler
- * to free it using \c atexit. This may cause trouble if used in a library
- * loaded with \c dlopen.
+ * Return the given pointer's ralloc context.
*/
-void *ralloc_autofree_context(void);
+void *ralloc_parent(const void *ptr);
/**
* Set a callback to occur just before an object is freed.
bool ralloc_strncat(char **dest, const char *str, size_t n);
/**
+ * Concatenate two strings, allocating the necessary space.
+ *
+ * This appends \p n bytes of \p str to \p *dest, using ralloc_resize
+ * to expand \p *dest to the appropriate size. \p dest will be updated to the
+ * new pointer unless allocation fails.
+ *
+ * The result will always be null-terminated.
+ *
+ * This function differs from ralloc_strcat() and ralloc_strncat() in that it
+ * does not do any strlen() calls which can become costly on large strings.
+ *
+ * \return True unless allocation failed.
+ */
+bool
+ralloc_str_append(char **dest, const char *str,
+ size_t existing_length, size_t str_size);
+
+/**
* Print to a string.
*
* This is analogous to \c sprintf, but allocates enough space (using \p ctx
bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args);
/// @}
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-
/**
* Declare C++ new and delete operators which use ralloc.
*
*
* which is more idiomatic in C++ than calling ralloc.
*/
-#define DECLARE_RALLOC_CXX_OPERATORS(TYPE) \
+#define DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(TYPE, ALLOC_FUNC) \
private: \
static void _ralloc_destructor(void *p) \
{ \
public: \
static void* operator new(size_t size, void *mem_ctx) \
{ \
- void *p = ralloc_size(mem_ctx, size); \
+ void *p = ALLOC_FUNC(mem_ctx, size); \
assert(p != NULL); \
if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \
ralloc_set_destructor(p, _ralloc_destructor); \
ralloc_free(p); \
}
+#define DECLARE_RALLOC_CXX_OPERATORS(type) \
+ DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, ralloc_size)
+
+#define DECLARE_RZALLOC_CXX_OPERATORS(type) \
+ DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, rzalloc_size)
+
+#define DECLARE_LINEAR_ALLOC_CXX_OPERATORS(type) \
+ DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, linear_alloc_child)
+
+#define DECLARE_LINEAR_ZALLOC_CXX_OPERATORS(type) \
+ DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, linear_zalloc_child)
+
+
+/**
+ * Do a fast allocation from the linear buffer, also known as the child node
+ * from the allocator's point of view. It can't be freed directly. You have
+ * to free the parent or the ralloc parent.
+ *
+ * \param parent parent node of the linear allocator
+ * \param size size to allocate (max 32 bits)
+ */
+void *linear_alloc_child(void *parent, unsigned size);
+
+/**
+ * Allocate a parent node that will hold linear buffers. The returned
+ * allocation is actually the first child node, but it's also the handle
+ * of the parent node. Use it for all child node allocations.
+ *
+ * \param ralloc_ctx ralloc context, must not be NULL
+ * \param size size to allocate (max 32 bits)
+ */
+void *linear_alloc_parent(void *ralloc_ctx, unsigned size);
+
+/**
+ * Same as linear_alloc_child, but also clears memory.
+ */
+void *linear_zalloc_child(void *parent, unsigned size);
+
+/**
+ * Same as linear_alloc_parent, but also clears memory.
+ */
+void *linear_zalloc_parent(void *ralloc_ctx, unsigned size);
+
+/**
+ * Free the linear parent node. This will free all child nodes too.
+ * Freeing the ralloc parent will also free this.
+ */
+void linear_free_parent(void *ptr);
+
+/**
+ * Same as ralloc_steal, but steals the linear parent node.
+ */
+void ralloc_steal_linear_parent(void *new_ralloc_ctx, void *ptr);
+
+/**
+ * Return the ralloc parent of the linear parent node.
+ */
+void *ralloc_parent_of_linear_parent(void *ptr);
+
+/**
+ * Same as realloc except that the linear allocator doesn't free child nodes,
+ * so it's reduced to memory duplication. It's used in places where
+ * reallocation is required. Don't use it often. It's much slower than
+ * realloc.
+ */
+void *linear_realloc(void *parent, void *old, unsigned new_size);
+
+/* The functions below have the same semantics as their ralloc counterparts,
+ * except that they always allocate a linear child node.
+ */
+char *linear_strdup(void *parent, const char *str);
+char *linear_asprintf(void *parent, const char *fmt, ...);
+char *linear_vasprintf(void *parent, const char *fmt, va_list args);
+bool linear_asprintf_append(void *parent, char **str, const char *fmt, ...);
+bool linear_vasprintf_append(void *parent, char **str, const char *fmt,
+ va_list args);
+bool linear_asprintf_rewrite_tail(void *parent, char **str, size_t *start,
+ const char *fmt, ...);
+bool linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start,
+ const char *fmt, va_list args);
+bool linear_strcat(void *parent, char **dest, const char *str);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
#endif