From c4821c8e6bf1f81c6ea31e11ebc0fc1666e9337b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 25 Feb 2021 10:27:59 -0500 Subject: Add exess from git@gitlab.com:drobilla/exess.git 4638b1f --- subprojects/exess/src/variant.c | 431 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 subprojects/exess/src/variant.c (limited to 'subprojects/exess/src/variant.c') diff --git a/subprojects/exess/src/variant.c b/subprojects/exess/src/variant.c new file mode 100644 index 00000000..d8977abd --- /dev/null +++ b/subprojects/exess/src/variant.c @@ -0,0 +1,431 @@ +/* + Copyright 2019-2021 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "read_utils.h" +#include "write_utils.h" + +#include "exess/exess.h" + +#include +#include +#include + +// Constructors + +ExessVariant +exess_make_nothing(const ExessStatus status) +{ + ExessVariant v = {EXESS_NOTHING, .value.as_status = status}; + return v; +} + +ExessVariant +exess_make_boolean(const bool value) +{ + ExessVariant v = {EXESS_BOOLEAN, .value.as_bool = value}; + return v; +} + +ExessVariant +exess_make_decimal(const double value) +{ + ExessVariant v = {EXESS_DECIMAL, .value.as_double = value}; + return v; +} + +ExessVariant +exess_make_double(const double value) +{ + ExessVariant v = {EXESS_DOUBLE, .value.as_double = value}; + return v; +} + +ExessVariant +exess_make_float(const float value) +{ + ExessVariant v = {EXESS_FLOAT, .value.as_float = value}; + return v; +} + +ExessVariant +exess_make_long(const int64_t value) +{ + ExessVariant v = {EXESS_LONG, .value.as_long = value}; + return v; +} + +ExessVariant +exess_make_int(const int32_t value) +{ + ExessVariant v = {EXESS_INT, .value.as_int = value}; + return v; +} + +ExessVariant +exess_make_short(const int16_t value) +{ + ExessVariant v = {EXESS_SHORT, .value.as_short = value}; + return v; +} + +ExessVariant +exess_make_byte(const int8_t value) +{ + ExessVariant v = {EXESS_BYTE, .value.as_byte = value}; + return v; +} + +ExessVariant +exess_make_ulong(const uint64_t value) +{ + ExessVariant v = {EXESS_ULONG, .value.as_ulong = value}; + return v; +} + +ExessVariant +exess_make_uint(const uint32_t value) +{ + ExessVariant v = {EXESS_UINT, .value.as_uint = value}; + return v; +} + +ExessVariant +exess_make_ushort(const uint16_t value) +{ + ExessVariant v = {EXESS_USHORT, .value.as_ushort = value}; + return v; +} + +ExessVariant +exess_make_ubyte(const uint8_t value) +{ + ExessVariant v = {EXESS_UBYTE, .value.as_ubyte = value}; + return v; +} + +ExessVariant +exess_make_duration(const ExessDuration value) +{ + ExessVariant v = {EXESS_DURATION, .value.as_duration = value}; + return v; +} + +ExessVariant +exess_make_datetime(const ExessDateTime value) +{ + ExessVariant v = {EXESS_DATETIME, .value.as_datetime = value}; + return v; +} + +ExessVariant +exess_make_time(const ExessTime value) +{ + ExessVariant v = {EXESS_TIME, .value.as_time = value}; + return v; +} + +ExessVariant +exess_make_date(const ExessDate value) +{ + ExessVariant v = {EXESS_DATE, .value.as_date = value}; + return v; +} + +ExessVariant +exess_make_hex(const ExessBlob blob) +{ + ExessVariant v = {EXESS_HEX, .value.as_blob = blob}; + return v; +} + +ExessVariant +exess_make_base64(const ExessBlob blob) +{ + ExessVariant v = {EXESS_BASE64, .value.as_blob = blob}; + return v; +} + +// Accessors + +ExessStatus +exess_get_status(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_NOTHING ? variant->value.as_status + : EXESS_SUCCESS; +} +const bool* +exess_get_boolean(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_BOOLEAN ? &variant->value.as_bool : NULL; +} + +const double* +exess_get_double(const ExessVariant* const variant) +{ + return (variant->datatype == EXESS_DECIMAL || + variant->datatype == EXESS_DOUBLE) + ? &variant->value.as_double + : NULL; +} + +const float* +exess_get_float(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_FLOAT ? &variant->value.as_float : NULL; +} + +const int64_t* +exess_get_long(const ExessVariant* const variant) +{ + return (variant->datatype >= EXESS_INTEGER && variant->datatype <= EXESS_LONG) + ? &variant->value.as_long + : NULL; +} + +const int32_t* +exess_get_int(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_INT ? &variant->value.as_int : NULL; +} + +const int16_t* +exess_get_short(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_SHORT ? &variant->value.as_short : NULL; +} + +const int8_t* +exess_get_byte(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_BYTE ? &variant->value.as_byte : NULL; +} + +const uint64_t* +exess_get_ulong(const ExessVariant* const variant) +{ + return (variant->datatype == EXESS_NON_NEGATIVE_INTEGER || + variant->datatype == EXESS_ULONG || + variant->datatype == EXESS_POSITIVE_INTEGER) + ? &variant->value.as_ulong + : NULL; +} + +const uint32_t* +exess_get_uint(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_UINT ? &variant->value.as_uint : NULL; +} + +const uint16_t* +exess_get_ushort(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_USHORT ? &variant->value.as_ushort : NULL; +} + +const uint8_t* +exess_get_ubyte(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_UBYTE ? &variant->value.as_ubyte : NULL; +} + +const ExessBlob* +exess_get_blob(const ExessVariant* const variant) +{ + return (variant->datatype == EXESS_HEX || variant->datatype == EXESS_BASE64) + ? &variant->value.as_blob + : NULL; +} + +const ExessDuration* +exess_get_duration(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_DURATION ? &variant->value.as_duration + : NULL; +} + +const ExessDateTime* +exess_get_datetime(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_DATETIME ? &variant->value.as_datetime + : NULL; +} + +const ExessTime* +exess_get_time(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_TIME ? &variant->value.as_time : NULL; +} + +const ExessDate* +exess_get_date(const ExessVariant* const variant) +{ + return variant->datatype == EXESS_DATE ? &variant->value.as_date : NULL; +} + +// Reading and Writing + +ExessResult +exess_read_variant(ExessVariant* const out, + ExessDatatype datatype, + const char* const str) +{ + ExessResult r = {EXESS_UNSUPPORTED, 0}; + + out->datatype = datatype; + + switch (datatype) { + case EXESS_NOTHING: + break; + case EXESS_BOOLEAN: + return exess_read_boolean(&out->value.as_bool, str); + case EXESS_DECIMAL: + return exess_read_decimal(&out->value.as_double, str); + case EXESS_DOUBLE: + return exess_read_double(&out->value.as_double, str); + case EXESS_FLOAT: + return exess_read_float(&out->value.as_float, str); + case EXESS_INTEGER: + return exess_read_long(&out->value.as_long, str); + + case EXESS_NON_POSITIVE_INTEGER: + if (!(r = exess_read_long(&out->value.as_long, str)).status) { + if (out->value.as_long > 0) { + return result(EXESS_OUT_OF_RANGE, r.count); + } + } + break; + + case EXESS_NEGATIVE_INTEGER: + if (!(r = exess_read_long(&out->value.as_long, str)).status) { + if (out->value.as_long >= 0) { + return result(EXESS_OUT_OF_RANGE, r.count); + } + } + break; + + case EXESS_LONG: + return exess_read_long(&out->value.as_long, str); + case EXESS_INT: + return exess_read_int(&out->value.as_int, str); + case EXESS_SHORT: + return exess_read_short(&out->value.as_short, str); + case EXESS_BYTE: + return exess_read_byte(&out->value.as_byte, str); + case EXESS_NON_NEGATIVE_INTEGER: + case EXESS_ULONG: + return exess_read_ulong(&out->value.as_ulong, str); + case EXESS_UINT: + return exess_read_uint(&out->value.as_uint, str); + case EXESS_USHORT: + return exess_read_ushort(&out->value.as_ushort, str); + case EXESS_UBYTE: + return exess_read_ubyte(&out->value.as_ubyte, str); + + case EXESS_POSITIVE_INTEGER: + if (!(r = exess_read_ulong(&out->value.as_ulong, str)).status) { + if (out->value.as_ulong <= 0) { + return result(EXESS_OUT_OF_RANGE, r.count); + } + } + break; + + case EXESS_DURATION: + return exess_read_duration(&out->value.as_duration, str); + case EXESS_DATETIME: + return exess_read_datetime(&out->value.as_datetime, str); + case EXESS_TIME: + return exess_read_time(&out->value.as_time, str); + case EXESS_DATE: + return exess_read_date(&out->value.as_date, str); + case EXESS_HEX: + return exess_read_hex(&out->value.as_blob, str); + case EXESS_BASE64: + return exess_read_base64(&out->value.as_blob, str); + } + + return r; +} + +ExessResult +exess_write_variant(const ExessVariant variant, + const size_t buf_size, + char* const buf) +{ + if (buf_size > 0) { + buf[0] = '\0'; + } + + switch (variant.datatype) { + case EXESS_NOTHING: + break; + case EXESS_BOOLEAN: + return exess_write_boolean(variant.value.as_bool, buf_size, buf); + case EXESS_DECIMAL: + return exess_write_decimal(variant.value.as_double, buf_size, buf); + case EXESS_DOUBLE: + return exess_write_double(variant.value.as_double, buf_size, buf); + case EXESS_FLOAT: + return exess_write_float(variant.value.as_float, buf_size, buf); + case EXESS_INTEGER: + case EXESS_NON_POSITIVE_INTEGER: + case EXESS_NEGATIVE_INTEGER: + case EXESS_LONG: + return exess_write_long(variant.value.as_long, buf_size, buf); + case EXESS_INT: + return exess_write_int(variant.value.as_int, buf_size, buf); + case EXESS_SHORT: + return exess_write_short(variant.value.as_short, buf_size, buf); + case EXESS_BYTE: + return exess_write_byte(variant.value.as_byte, buf_size, buf); + case EXESS_NON_NEGATIVE_INTEGER: + case EXESS_ULONG: + return exess_write_ulong(variant.value.as_ulong, buf_size, buf); + case EXESS_UINT: + return exess_write_uint(variant.value.as_uint, buf_size, buf); + case EXESS_USHORT: + return exess_write_ushort(variant.value.as_ushort, buf_size, buf); + case EXESS_UBYTE: + return exess_write_ubyte(variant.value.as_ubyte, buf_size, buf); + case EXESS_POSITIVE_INTEGER: + return exess_write_ulong(variant.value.as_ulong, buf_size, buf); + case EXESS_DURATION: + return exess_write_duration(variant.value.as_duration, buf_size, buf); + case EXESS_DATETIME: + return exess_write_datetime(variant.value.as_datetime, buf_size, buf); + case EXESS_TIME: + return exess_write_time(variant.value.as_time, buf_size, buf); + case EXESS_DATE: + return exess_write_date(variant.value.as_date, buf_size, buf); + case EXESS_HEX: + if (variant.value.as_blob.data) { + return exess_write_hex(variant.value.as_blob.size, + (void*)variant.value.as_blob.data, + buf_size, + buf); + } + break; + case EXESS_BASE64: + if (variant.value.as_blob.data) { + return exess_write_base64(variant.value.as_blob.size, + (void*)variant.value.as_blob.data, + buf_size, + buf); + } + break; + } + + return end_write(EXESS_BAD_VALUE, buf_size, buf, 0); +} -- cgit v1.2.1