aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcoopgamma.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libcoopgamma.c802
1 files changed, 802 insertions, 0 deletions
diff --git a/src/libcoopgamma.c b/src/libcoopgamma.c
new file mode 100644
index 0000000..5f71891
--- /dev/null
+++ b/src/libcoopgamma.c
@@ -0,0 +1,802 @@
+/**
+ * libcoopgamma -- Library for interfacing with cooperative gamma servers
+ * Copyright (C) 2016 Mattias Andrée (maandree@kth.se)
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "libcoopgamma.h"
+
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+
+#define SUBBUF \
+ (buf ? buf + off : NULL)
+
+#define MARSHAL_PROLOGUE \
+ char* restrict buf = vbuf; \
+ size_t off = 0;
+
+#define UNMARSHAL_PROLOGUE \
+ const char* restrict buf = vbuf; \
+ size_t off = 0;
+
+#define MARSHAL_EPILOGUE \
+ return off
+
+#define UNMARSHAL_EPILOGUE \
+ return *np = off, LIBCOOPGAMMA_SUCCESS
+
+#define marshal_prim(datum, type) \
+ ((buf != NULL ? *(type*)(buf + off) = (datum) : 0), off += sizeof(type))
+
+#define unmarshal_prim(datum, type) \
+ ((datum) = *(type*)(buf + off), off += sizeof(type))
+
+#define marshal_version(version) \
+ marshal_prim(version, int)
+
+#define unmarshal_version(version) \
+ do \
+ { \
+ int version__; \
+ unmarshal_prim(version__, int); \
+ if (version__ < version) \
+ return LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE; \
+ if (version__ > version) \
+ return LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE; \
+ } \
+ while (0)
+
+#define marshal_buffer(data, n) \
+ ((buf != NULL ? (memcpy(buf + off, (data), (n)), 0) : 0), off += (n))
+
+#define unmarshal_buffer(data, n) \
+ do \
+ { \
+ (data) = malloc(n); \
+ if ((data) == NULL) \
+ return LIBCOOPGAMMA_ERRNO_SET; \
+ memcpy((data), buf + off, (n)); \
+ off += (n); \
+ } \
+ while (0)
+
+#define marshal_string(datum) \
+ ((datum) == NULL ? marshal_prim(1, char) : \
+ (marshal_prim(0, char), marshal_buffer(datum, strlen(datum) + 1)))
+
+#define unmarshal_string(datum) \
+ do \
+ { \
+ char nonnull__; \
+ unmarshal_prim(nonnull__, char); \
+ if (nonnull__) \
+ unmarshal_buffer((datum), strlen(buf + off) + 1); \
+ else \
+ (datum) = NULL; \
+ } \
+ while (0)
+
+
+
+/**
+ * Initialise a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`,
+ * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t`
+ *
+ * `this->red_size`, `this->green_size`, and `this->blue_size` must already be set
+ *
+ * @param this The record to initialise
+ * @para width The `sizeof(*(this->red))`
+ * @return Zero on success, -1 on error
+ */
+int (libcoopgamma_ramps_initialise)(void* restrict this, size_t width)
+{
+ libcoopgamma_ramps8_t* restrict this8 = (libcoopgamma_ramps8_t* restrict)this;
+ this8->red = this8->green = this8->blue = NULL;
+ this8->red = malloc((this8->red_size + this8->green_size + this8->blue_size) * width);
+ if (this8->red == NULL)
+ return -1;
+ this8->green = this8->red + this8->red_size * width;
+ this8->blue = this8->green + this8->green_size * width;
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`,
+ * `libcoopgamma_ramps32_t`, `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or
+ * `libcoopgamma_rampsd_t`, the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_ramps_initialise`
+ * or failed call to `libcoopgamma_ramps_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_ramps_destroy(void* restrict this)
+{
+ libcoopgamma_ramps8_t* restrict this8 = (libcoopgamma_ramps8_t* restrict)this;
+ free(this8->red);
+ this8->red = this8->green = this8->blue = NULL;
+}
+
+
+/**
+ * Marshal a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`,
+ * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @param width The `sizeof(*(this->red))`
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t (libcoopgamma_ramps_marshal)(const void* restrict this, void* restrict vbuf, size_t width)
+{
+ libcoopgamma_ramps8_t* restrict this8 = (libcoopgamma_ramps8_t* restrict)this;
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_RAMPS_VERSION);
+ marshal_prim(this8->red_size, size_t);
+ marshal_prim(this8->green_size, size_t);
+ marshal_prim(this8->blue_size, size_t);
+ marshal_buffer(this8->red, (this8->red_size + this8->green_size + this8->blue_size) * width);
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`,
+ * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @param width The `sizeof(*(this->red))`
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int (libcoopgamma_ramps_unmarshal)(void* restrict this, const void* restrict vbuf,
+ size_t* restrict np, size_t width)
+{
+ libcoopgamma_ramps8_t* restrict this8 = (libcoopgamma_ramps8_t* restrict)this;
+ UNMARSHAL_PROLOGUE;
+ unmarshal_version(LIBCOOPGAMMA_RAMPS_VERSION);
+ unmarshal_prim(this8->red_size, size_t);
+ unmarshal_prim(this8->green_size, size_t);
+ unmarshal_prim(this8->blue_size, size_t);
+ unmarshal_buffer(this8->red, (this8->red_size + this8->green_size + this8->blue_size) * width);
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_filter_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_filter_initialise(libcoopgamma_filter_t* restrict this)
+{
+ memset(this, 0, sizeof(*this));
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_filter_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_filter_initialise`
+ * or failed call to `libcoopgamma_filter_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_filter_destroy(libcoopgamma_filter_t* restrict this)
+{
+ free(this->crtc);
+ free(this->class);
+ free(this->ramps.u8.red);
+ memset(this, 0, sizeof(*this));
+}
+
+
+/**
+ * Marshal a `libcoopgamma_filter_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_filter_marshal(const libcoopgamma_filter_t* restrict this, void* restrict vbuf)
+{
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_FILTER_VERSION);
+ marshal_version(LIBCOOPGAMMA_DEPTH_VERSION);
+ marshal_version(LIBCOOPGAMMA_LIFESPAN_VERSION);
+ marshal_prim(this->depth, libcoopgamma_depth_t);
+ marshal_prim(this->priority, int64_t);
+ marshal_string(this->crtc);
+ marshal_string(this->class);
+ marshal_prim(this->lifespan, libcoopgamma_lifespan_t);
+ switch (this->depth)
+ {
+ case LIBCOOPGAMMA_UINT8: off += libcoopgamma_ramps_marshal(&(this->ramps.u8), SUBBUF); break;
+ case LIBCOOPGAMMA_UINT16: off += libcoopgamma_ramps_marshal(&(this->ramps.u16), SUBBUF); break;
+ case LIBCOOPGAMMA_UINT32: off += libcoopgamma_ramps_marshal(&(this->ramps.u32), SUBBUF); break;
+ case LIBCOOPGAMMA_UINT64: off += libcoopgamma_ramps_marshal(&(this->ramps.u64), SUBBUF); break;
+ case LIBCOOPGAMMA_FLOAT: off += libcoopgamma_ramps_marshal(&(this->ramps.f), SUBBUF); break;
+ case LIBCOOPGAMMA_DOUBLE: off += libcoopgamma_ramps_marshal(&(this->ramps.d), SUBBUF); break;
+ default:
+ break;
+ }
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_filter_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_filter_unmarshal(libcoopgamma_filter_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np)
+{
+ int r = LIBCOOPGAMMA_SUCCESS;
+ size_t n = 0;
+ UNMARSHAL_PROLOGUE;
+ memset(this, 0, sizeof(*this));
+ unmarshal_version(LIBCOOPGAMMA_FILTER_VERSION);
+ unmarshal_version(LIBCOOPGAMMA_DEPTH_VERSION);
+ unmarshal_version(LIBCOOPGAMMA_LIFESPAN_VERSION);
+ unmarshal_prim(this->depth, libcoopgamma_depth_t);
+ unmarshal_prim(this->priority, int64_t);
+ unmarshal_string(this->crtc);
+ unmarshal_string(this->class);
+ unmarshal_prim(this->lifespan, libcoopgamma_lifespan_t);
+ switch (this->depth)
+ {
+ case LIBCOOPGAMMA_UINT8: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u8), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_UINT16: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u16), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_UINT32: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u32), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_UINT64: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u64), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_FLOAT: r = libcoopgamma_ramps_unmarshal(&(this->ramps.f), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_DOUBLE: r = libcoopgamma_ramps_unmarshal(&(this->ramps.d), SUBBUF, &n); break;
+ default:
+ break;
+ }
+ if (r != LIBCOOPGAMMA_SUCCESS)
+ return r;
+ off += n;
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_crtc_info_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_crtc_info_initialise(libcoopgamma_crtc_info_t* restrict this)
+{
+ memset(this, 0, sizeof(*this));
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_crtc_info_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_crtc_info_initialise`
+ * or failed call to `libcoopgamma_crtc_info_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_crtc_info_destroy(libcoopgamma_crtc_info_t* restrict this)
+{
+ (void) this;
+}
+
+
+/**
+ * Marshal a `libcoopgamma_crtc_info_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_crtc_info_marshal(const libcoopgamma_crtc_info_t* restrict this, void* restrict vbuf)
+{
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_CRTC_INFO_VERSION);
+ marshal_version(LIBCOOPGAMMA_DEPTH_VERSION);
+ marshal_version(LIBCOOPGAMMA_SUPPORT_VERSION);
+ marshal_prim(this->cooperative, int);
+ marshal_prim(this->depth, libcoopgamma_depth_t);
+ marshal_prim(this->red_size, size_t);
+ marshal_prim(this->green_size, size_t);
+ marshal_prim(this->blue_size, size_t);
+ marshal_prim(this->supported, libcoopgamma_support_t);
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_crtc_info_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_crtc_info_unmarshal(libcoopgamma_crtc_info_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np)
+{
+ UNMARSHAL_PROLOGUE;
+ unmarshal_version(LIBCOOPGAMMA_CRTC_INFO_VERSION);
+ unmarshal_version(LIBCOOPGAMMA_DEPTH_VERSION);
+ unmarshal_version(LIBCOOPGAMMA_SUPPORT_VERSION);
+ unmarshal_prim(this->cooperative, int);
+ unmarshal_prim(this->depth, libcoopgamma_depth_t);
+ unmarshal_prim(this->red_size, size_t);
+ unmarshal_prim(this->green_size, size_t);
+ unmarshal_prim(this->blue_size, size_t);
+ unmarshal_prim(this->supported, libcoopgamma_support_t);
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_filter_query_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_filter_query_initialise(libcoopgamma_filter_query_t* restrict this)
+{
+ this->crtc = NULL;
+ this->coalesce = 0;
+ this->high_priority = INT64_MAX;
+ this->low_priority = INT64_MIN;
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_filter_query_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_filter_query_initialise`
+ * or failed call to `libcoopgamma_filter_query_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_filter_query_destroy(libcoopgamma_filter_query_t* restrict this)
+{
+ free(this->crtc), this->crtc = NULL;
+}
+
+
+/**
+ * Marshal a `libcoopgamma_filter_query_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_filter_query_marshal(const libcoopgamma_filter_query_t* restrict this, void* restrict vbuf)
+{
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_FILTER_QUERY_VERSION);
+ marshal_string(this->crtc);
+ marshal_prim(this->coalesce, int);
+ marshal_prim(this->high_priority, int64_t);
+ marshal_prim(this->low_priority, int64_t);
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_filter_query_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_filter_query_unmarshal(libcoopgamma_filter_query_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np)
+{
+ UNMARSHAL_PROLOGUE;
+ this->crtc = NULL;
+ unmarshal_version(LIBCOOPGAMMA_FILTER_QUERY_VERSION);
+ unmarshal_string(this->crtc);
+ unmarshal_prim(this->coalesce, int);
+ unmarshal_prim(this->high_priority, int64_t);
+ unmarshal_prim(this->low_priority, int64_t);
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_queried_filter_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_queried_filter_initialise(libcoopgamma_queried_filter_t* restrict this)
+{
+ memset(this, 0, sizeof(*this));
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_queried_filter_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_queried_filter_initialise`
+ * or failed call to `libcoopgamma_queried_filter_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_queried_filter_destroy(libcoopgamma_queried_filter_t* restrict this)
+{
+ free(this->class), this->class = NULL;
+ libcoopgamma_ramps_destroy(&(this->ramps.u8));
+}
+
+
+/**
+ * Marshal a `libcoopgamma_queried_filter_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @param depth The type used of ramp stops
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_queried_filter_marshal(const libcoopgamma_queried_filter_t* restrict this,
+ void* restrict vbuf, libcoopgamma_depth_t depth)
+{
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_QUERIED_FILTER_VERSION);
+ marshal_prim(this->priority, int64_t);
+ marshal_string(this->class);
+ switch (depth)
+ {
+ case LIBCOOPGAMMA_UINT8: off += libcoopgamma_ramps_marshal(&(this->ramps.u8), SUBBUF); break;
+ case LIBCOOPGAMMA_UINT16: off += libcoopgamma_ramps_marshal(&(this->ramps.u16), SUBBUF); break;
+ case LIBCOOPGAMMA_UINT32: off += libcoopgamma_ramps_marshal(&(this->ramps.u32), SUBBUF); break;
+ case LIBCOOPGAMMA_UINT64: off += libcoopgamma_ramps_marshal(&(this->ramps.u64), SUBBUF); break;
+ case LIBCOOPGAMMA_FLOAT: off += libcoopgamma_ramps_marshal(&(this->ramps.f), SUBBUF); break;
+ case LIBCOOPGAMMA_DOUBLE: off += libcoopgamma_ramps_marshal(&(this->ramps.d), SUBBUF); break;
+ default:
+ break;
+ }
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_queried_filter_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @param depth The type used of ramp stops
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_queried_filter_unmarshal(libcoopgamma_queried_filter_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np,
+ libcoopgamma_depth_t depth)
+{
+ int r = LIBCOOPGAMMA_SUCCESS;
+ size_t n = 0;
+ UNMARSHAL_PROLOGUE;
+ memset(this, 0, sizeof(*this));
+ unmarshal_version(LIBCOOPGAMMA_QUERIED_FILTER_VERSION);
+ unmarshal_prim(this->priority, int64_t);
+ unmarshal_string(this->class);
+ switch (depth)
+ {
+ case LIBCOOPGAMMA_UINT8: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u8), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_UINT16: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u16), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_UINT32: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u32), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_UINT64: r = libcoopgamma_ramps_unmarshal(&(this->ramps.u64), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_FLOAT: r = libcoopgamma_ramps_unmarshal(&(this->ramps.f), SUBBUF, &n); break;
+ case LIBCOOPGAMMA_DOUBLE: r = libcoopgamma_ramps_unmarshal(&(this->ramps.d), SUBBUF, &n); break;
+ default:
+ break;
+ }
+ if (r != LIBCOOPGAMMA_SUCCESS)
+ return r;
+ off += n;
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_filter_table_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_filter_table_initialise(libcoopgamma_filter_table_t* restrict this)
+{
+ memset(this, 0, sizeof(*this));
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_filter_table_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_filter_table_initialise`
+ * or failed call to `libcoopgamma_filter_table_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_filter_table_destroy(libcoopgamma_filter_table_t* restrict this)
+{
+ while (this->filter_count)
+ libcoopgamma_queried_filter_destroy(this->filters + --(this->filter_count));
+ free(this->filters), this->filters = NULL;
+}
+
+
+/**
+ * Marshal a `libcoopgamma_filter_table_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_filter_table_marshal(const libcoopgamma_filter_table_t* restrict this, void* restrict vbuf)
+{
+ size_t i;
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_FILTER_TABLE_VERSION);
+ marshal_version(LIBCOOPGAMMA_DEPTH_VERSION);
+ marshal_prim(this->depth, libcoopgamma_depth_t);
+ marshal_prim(this->red_size, size_t);
+ marshal_prim(this->green_size, size_t);
+ marshal_prim(this->blue_size, size_t);
+ marshal_prim(this->filter_count, size_t);
+ for (i = 0; i < this->filter_count; i++)
+ off += libcoopgamma_queried_filter_marshal(this->filters + i, SUBBUF, this->depth);
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_filter_table_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_filter_table_unmarshal(libcoopgamma_filter_table_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np)
+{
+ size_t i, n, fn;
+ int r;
+ UNMARSHAL_PROLOGUE;
+ this->filter_count = 0;
+ this->filters = NULL;
+ unmarshal_version(LIBCOOPGAMMA_FILTER_TABLE_VERSION);
+ unmarshal_version(LIBCOOPGAMMA_DEPTH_VERSION);
+ unmarshal_prim(this->depth, libcoopgamma_depth_t);
+ unmarshal_prim(this->red_size, size_t);
+ unmarshal_prim(this->green_size, size_t);
+ unmarshal_prim(this->blue_size, size_t);
+ unmarshal_prim(fn, size_t);
+ this->filters = malloc(fn * sizeof(*(this->filters)));
+ if (this->filters == NULL)
+ return LIBCOOPGAMMA_ERRNO_SET;
+ for (i = 0; i < fn; i++)
+ {
+ r = libcoopgamma_queried_filter_unmarshal(this->filters + i, SUBBUF, &n, this->depth);
+ if (r != LIBCOOPGAMMA_SUCCESS)
+ return r;
+ off += n;
+ this->filter_count += 1;
+ }
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_error_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_error_initialise(libcoopgamma_error_t* restrict this)
+{
+ this->number = 0;
+ this->custom = 0;
+ this->description = NULL;
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_error_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_error_initialise`
+ * or failed call to `libcoopgamma_error_unmarshal`
+ *
+ * @param this The record to destroy
+ */
+void libcoopgamma_error_destroy(libcoopgamma_error_t* restrict this)
+{
+ free(this->description), this->description = NULL;
+}
+
+
+/**
+ * Marshal a `libcoopgamma_error_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_error_marshal(const libcoopgamma_error_t* restrict this, void* restrict vbuf)
+{
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_ERROR_VERSION);
+ marshal_prim(this->number, uint64_t);
+ marshal_prim(this->custom, int);
+ marshal_string(this->description);
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_error_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_error_unmarshal(libcoopgamma_error_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np)
+{
+ UNMARSHAL_PROLOGUE;
+ this->description = NULL;
+ unmarshal_version(LIBCOOPGAMMA_ERROR_VERSION);
+ unmarshal_prim(this->number, uint64_t);
+ unmarshal_prim(this->custom, int);
+ unmarshal_string(this->description);
+ UNMARSHAL_EPILOGUE;
+}
+
+
+
+/**
+ * Initialise a `libcoopgamma_context_t`
+ *
+ * @param this The record to initialise
+ * @return Zero on success, -1 on error
+ */
+int libcoopgamma_context_initialise(libcoopgamma_context_t* restrict this)
+{
+ this->fd = -1;
+ libcoopgamma_error_initialise(&(this->error));
+ return 0;
+}
+
+
+/**
+ * Release all resources allocated to a `libcoopgamma_context_t`,
+ * the allocation of the record itself is not freed
+ *
+ * Always call this function after failed call to `libcoopgamma_context_initialise`
+ * or failed call to `libcoopgamma_context_unmarshal`
+ *
+ * @param this The record to destroy
+ * @param disconnect Disconnect from the server?
+ */
+void libcoopgamma_context_destroy(libcoopgamma_context_t* restrict this, int disconnect)
+{
+ if (disconnect && (this->fd >= 0))
+ {
+ shutdown(this->fd, SHUT_RDWR);
+ close(this->fd);
+ }
+ this->fd = -1;
+ libcoopgamma_error_destroy(&(this->error));
+}
+
+
+/**
+ * Marshal a `libcoopgamma_context_t` into a buffer
+ *
+ * @param this The record to marshal
+ * @param vbuf The output buffer, `NULL` to only measure
+ * how large this buffer has to be
+ * @return The number of marshalled bytes, or if `buf == NULL`,
+ * how many bytes would be marshalled if `buf != NULL`
+ */
+size_t libcoopgamma_context_marshal(const libcoopgamma_context_t* restrict this, void* restrict vbuf)
+{
+ MARSHAL_PROLOGUE;
+ marshal_version(LIBCOOPGAMMA_CONTEXT_VERSION);
+ marshal_prim(this->fd, int);
+ off += libcoopgamma_error_marshal(&(this->error), SUBBUF);
+ MARSHAL_EPILOGUE;
+}
+
+
+/**
+ * Unmarshal a `libcoopgamma_context_t` from a buffer
+ *
+ * @param this The output paramater for unmarshalled record
+ * @param vbuf The buffer with the marshalled record
+ * @param np Output parameter for the number of unmarshalled bytes, undefined on failure
+ * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`,
+ * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET`
+ */
+int libcoopgamma_context_unmarshal(libcoopgamma_context_t* restrict this,
+ const void* restrict vbuf, size_t* restrict np)
+{
+ size_t n;
+ int r;
+ UNMARSHAL_PROLOGUE;
+ memset(this, 0, sizeof(*this));
+ unmarshal_version(LIBCOOPGAMMA_CONTEXT_VERSION);
+ unmarshal_prim(this->fd, int);
+ r = libcoopgamma_error_unmarshal(&(this->error), SUBBUF, &n);
+ if (r != LIBCOOPGAMMA_SUCCESS)
+ return r;
+ off += n;
+ UNMARSHAL_EPILOGUE;
+}
+