summaryrefslogtreecommitdiff
path: root/pbstruct.h
diff options
context:
space:
mode:
Diffstat (limited to 'pbstruct.h')
-rw-r--r--pbstruct.h114
1 files changed, 88 insertions, 26 deletions
diff --git a/pbstruct.h b/pbstruct.h
index 227d7bb..db4d242 100644
--- a/pbstruct.h
+++ b/pbstruct.h
@@ -39,6 +39,14 @@
* This proto will take N times more memory if structures are by value than if
* they are by reference. To avoid such bad cases, submessages are by
* reference.
+ *
+ * Ownership semantics:
+ * - Each pbstruct absolutely owns any data allocated for its arrays or
+ * strings. If you want a copy of this data that will outlive the struct,
+ * you must copy it out.
+ * - Each pbstruct optionally owns any data allocated for substructs, based
+ * on whether you pass the free_substructs parameter to any of several
+ * functions.
*/
#ifndef PBSTRUCT_H_
@@ -52,24 +60,25 @@ extern "C" {
#endif
typedef enum pbstruct_type {
- PBSTRUCT_TYPE_DOUBLE = 0,
- PBSTRUCT_TYPE_FLOAT = 1,
- PBSTRUCT_TYPE_INT32 = 2,
- PBSTRUCT_TYPE_UINT32 = 3,
- PBSTRUCT_TYPE_INT64 = 4,
- PBSTRUCT_TYPE_UINT64 = 5,
- PBSTRUCT_TYPE_BOOL = 6,
+ PBSTRUCT_TYPE_DOUBLE = 1,
+ PBSTRUCT_TYPE_FLOAT = 2,
+ PBSTRUCT_TYPE_INT32 = 3,
+ PBSTRUCT_TYPE_UINT32 = 4,
+ PBSTRUCT_TYPE_INT64 = 5,
+ PBSTRUCT_TYPE_UINT64 = 6,
+ PBSTRUCT_TYPE_BOOL = 7,
+
/* Main struct contains a pointer to a pbstruct. */
- PBSTRUCT_TYPE_SUBSTRUCT = 7,
+ PBSTRUCT_TYPE_SUBSTRUCT = 8,
/* Main struct contains a pointer to a pbstruct_delimited. */
- PBSTRUCT_DELIMITED = 8, /* Not itself a real type. */
- PBSTRUCT_TYPE_BYTES = PBSTRUCT_DELIMITED | 1,
- PBSTRUCT_TYPE_STRING = PBSTRUCT_DELIMITED | 2,
+ PBSTRUCT_DYNAMIC = 16,
+ PBSTRUCT_TYPE_BYTES = PBSTRUCT_DYNAMIC | 1,
+ PBSTRUCT_TYPE_STRING = PBSTRUCT_DYNAMIC | 2,
/* The main struct contains a pointer to a pbstruct_array, for which each
* element is identical to the non-array form. */
- PBSTRUCT_ARRAY = 16, /* Not itself a real type. */
+ PBSTRUCT_ARRAY = PBSTRUCT_DYNAMIC | 32, /* Not itself a real type. */
PBSTRUCT_TYPE_DOUBLE_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_DOUBLE,
PBSTRUCT_TYPE_FLOAT_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_FLOAT,
PBSTRUCT_TYPE_INT32_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_INT32,
@@ -90,13 +99,9 @@ struct pbstruct_field {
uint8_t isset_byte_mask;
};
-struct pbstruct_delimited {
- size_t len; /* Measured in bytes. */
- uint8_t data[];
-};
-
-struct pbstruct_array {
- size_t len; /* Measured in elements. */
+struct pbstruct_dynamic {
+ size_t len; /* Number of present elements (bytes for string/bytes). */
+ size_t size; /* Total size in present elements. */
uint8_t data[];
};
@@ -113,17 +118,74 @@ struct pbstruct {
uint8_t data[]; /* layout is described by definition. */
};
-/* Initializes everything to unset. */
-void pbstruct_init(struct pbstruct *s, struct pbstruct_definition *definition);
+struct pballoc {
+ void *(*realloc)(void *ptr, size_t size, void *user_data);
+ void (*free)(void *ptr, void *user_data);
+};
+
+/* Initializes everything to unset, with no dynamic memory alocated. */
+void pbstruct_init(struct pbstruct *s, struct pbstruct_definition *d);
+pbstruct *pbstruct_new(struct pbstruct_defintion *d, struct pballoc *a);
+/* Frees the struct itself and any dynamic string or array data, and substructs
+ * also if free_substructs is true. */
+void pbstruct_free(struct pbstruct *s, struct pballoc *a, bool free_substructs);
+
+/* For setting, clearing, and testing the "set" flag for each field.
+ * Clearing the "set" flag does not free any dynamically allocated
+ * storage -- it will be reused again if the field becomes set again. */
bool pbstruct_is_set(struct pbstruct *s, struct pbstruct_field *f);
-/* Doesn't check whether the field is holding allocated memory, and will leak
- * the memory if it is. */
void pbstruct_unset(struct pbstruct *s, struct pbstruct_field *f);
+void pbstruct_unset_all(struct pbstruct *s);
void pbstruct_set(struct pbstruct *s, struct pbstruct_field *f);
-/* These do no existence checks or type checks. */
+/* Resizes the given string field to len, triggering a realloc() if
+ * necessary. Never reallocs() the string to be shorter. */
+void pbstruct_resize_str(struct pbstruct *s, struct pbstruct_field *f,
+ size_t len, struct pballoc *a);
+
+/* Appends an element to the given array field, triggering a realloc() if
+ * necessary. Returns the offset of the new array element. */
+size_t pbstruct_append_array(struct pbstruct *s, struct pbstruct_field *f,
+ struct pballoc *a);
+
+/* Sets the size of the given array field to zero, but does not free the
+ * array itself (call pbstruct_free_field() for that). Does free any
+ * strings that were in the array (for string arrays), and any substructs
+ * if free_substructs is true. Does not affect the "set" flag (if the
+ * field was previously set, it will remain set, but as zero elements long). */
+void pbstruct_clear_array(struct pbstruct *s, struct pbstruct_field *f,
+ struct pballoc *a, bool free_substructs);
+
+/* Resizes a delimited field (string or bytes) string that is within an array.
+ * The array must already be large enough that str_offset is a valid member. */
+void pbstruct_resize_arraystr(struct pbstruct *s, struct pbstruct_field *f,
+ size_t str_offset, size_t len, struct pballoc *a);
+
+/* Like pbstruct_append_array, but appends a string of the specified length. */
+size_t pbstruct_append_arraystr(struct pbstruct *s, struct pbstruct_field *f,
+ size_t len, struct pballoc *a);
+
+/* Clears all data associated with f (like pbstruct_clear_array()), but also
+ * frees all underlying storage. For string array fields, also frees the
+ * individual strings. Clears the "set" flag since it is an error for an
+ * array field to be set if it has no dynamic data allocated. */
+void pbstruct_free_field(struct pbstruct *s, struct pbstruct_field *f,
+ bool free_substructs);
+void pbstruct_free_all_fields(struct pbstruct *s, bool free_substructs);
+
+/* These do no existence checks, bounds checks, or type checks. */
#define DECLARE_GETTERS(ctype, name) \
- ctype *pbstruct_get_ ## name(struct pbstruct *s, struct pbstruct_field *f);
+ ctype pbstruct_get_ ## name(struct pbstruct *s, \
+ struct pbstruct_field *f); \
+ ctype *pbstruct_get_ ## name ## _ptr(struct pbstruct *s, \
+ struct pbstruct_field *f); \
+ ctype pbstruct_get_ ## name ## _array(struct pbstruct *s, \
+ struct pbstruct_field *f, \
+ int i); \
+ ctype *pbstruct_get_ ## name ## _array_ptr(struct pbstruct *s, \
+ struct pbstruct_field *f, \
+ int i); \
+
DECLARE_GETTERS(double, double)
DECLARE_GETTERS(float, float)
@@ -132,9 +194,9 @@ DECLARE_GETTERS(int64_t, int64)
DECLARE_GETTERS(uint32_t, uint32)
DECLARE_GETTERS(uint64_t, uint64)
DECLARE_GETTERS(bool, bool)
+DECLARE_GETTERS(struct pbstruct*, substruct)
DECLARE_GETTERS(struct pbstruct_delimited*, bytes)
DECLARE_GETTERS(struct pbstruct_delimited*, string)
-DECLARE_GETTERS(struct pbstruct*, substruct)
#ifdef __cplusplus
} /* extern "C" */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback