diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/util.c b/src/hlib/flatBuffers/util.c new file mode 100644 index 0000000..d96f281 --- /dev/null +++ b/src/hlib/flatBuffers/util.c @@ -0,0 +1,130 @@ +#include "flatBuffers.h" + +uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size) { + if (size < 0) { + return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); + } + switch (size) { + case 1: + return *((uint8_t *)(data + 1)); + case 2: + return *((uint16_t *)(data + 1)); + case 4: + return *((uint32_t *)(data + 1)); + // TODO: 64-bit numbers! + } + printf("cannot read length of size %i!\n", size); + return 0; +} + +void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent) { + FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; + uint32_t bytesToRead = 1; + uint32_t dataOffset = 0, dataSize = 0; + uintmax_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + switch (info->readType) { + case Inline: + break; + case InlineLength: + bytesToRead += length; + dataOffset = 1; + dataSize = length; + break; + case FixedLength: + bytesToRead += info->readTypeParameter; + dataOffset = 1; + dataSize = info->readTypeParameter; + break; + case ReadLength: + bytesToRead += info->readTypeParameter + length; + dataOffset = 1 + info->readTypeParameter; + dataSize = length; + break; + case ElementsInline: + dataOffset = 1; + break; + case ReadElements: + bytesToRead += info->readTypeParameter; + dataOffset = 1 + info->readTypeParameter; + dataSize = info->readTypeParameter; + } + char *hexData = malloc(3*bytesToRead); + for (uint32_t i = 0; i < bytesToRead; i++) { + sprintf(hexData + 3*i, "%x ", data[i]); + } + hexData[3*bytesToRead - 1] = 0; + char *indentData = malloc(indent + 1); + memset(indentData, ' ', indent); + indentData[indent] = 0; + void *next = data + bytesToRead; + uint8_t *buffer; + switch (info->dataType) { + case TYPE_NIL: + printf("%s%s: %s\n", indentData, hexData, info->name); break; + case TYPE_INTEGER: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(allocationData, data)); break; + case TYPE_BOOLEAN: + printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; + // can't even print a float yet... + case TYPE_STRING: + buffer = malloc(length + 1); + memcpy(data + dataOffset, buffer, length); + buffer[length] = 0; + printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); + free(buffer); + break; + case TYPE_ARRAY: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + case TYPE_MAP: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 1); + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + default: + // this branch should actually be impossible to reach... + printf("unknown\n"); break; + } + free(hexData); + free(indentData); + free(buffer); + return next; +} + +void *msgPackSeek(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + uint32_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + if (info->dataType == TYPE_MAP) { + length <<= 1; + } + switch (info->readType) { + case Inline: + return data + 1; + case FixedLength: + return data + 1 + info->readTypeParameter; + case ReadLength: + return data + 1 + info->readTypeParameter + length; + case InlineLength: + return data + 1 + length; + case ElementsInline: + data++; + goto READ_ELEMENTS; + case ReadElements: + data += 1 + info->readTypeParameter; + READ_ELEMENTS: + for (uint8_t i = 0; i < length; i++) { + data = msgPackSeek(allocationData, data); + } + return data; + } + // should never happen + printf("seek: cannot read %s\n", info->name); + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/util.c b/src/hlib/flatBuffers/util.c new file mode 100644 index 0000000..d96f281 --- /dev/null +++ b/src/hlib/flatBuffers/util.c @@ -0,0 +1,130 @@ +#include "flatBuffers.h" + +uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size) { + if (size < 0) { + return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); + } + switch (size) { + case 1: + return *((uint8_t *)(data + 1)); + case 2: + return *((uint16_t *)(data + 1)); + case 4: + return *((uint32_t *)(data + 1)); + // TODO: 64-bit numbers! + } + printf("cannot read length of size %i!\n", size); + return 0; +} + +void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent) { + FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; + uint32_t bytesToRead = 1; + uint32_t dataOffset = 0, dataSize = 0; + uintmax_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + switch (info->readType) { + case Inline: + break; + case InlineLength: + bytesToRead += length; + dataOffset = 1; + dataSize = length; + break; + case FixedLength: + bytesToRead += info->readTypeParameter; + dataOffset = 1; + dataSize = info->readTypeParameter; + break; + case ReadLength: + bytesToRead += info->readTypeParameter + length; + dataOffset = 1 + info->readTypeParameter; + dataSize = length; + break; + case ElementsInline: + dataOffset = 1; + break; + case ReadElements: + bytesToRead += info->readTypeParameter; + dataOffset = 1 + info->readTypeParameter; + dataSize = info->readTypeParameter; + } + char *hexData = malloc(3*bytesToRead); + for (uint32_t i = 0; i < bytesToRead; i++) { + sprintf(hexData + 3*i, "%x ", data[i]); + } + hexData[3*bytesToRead - 1] = 0; + char *indentData = malloc(indent + 1); + memset(indentData, ' ', indent); + indentData[indent] = 0; + void *next = data + bytesToRead; + uint8_t *buffer; + switch (info->dataType) { + case TYPE_NIL: + printf("%s%s: %s\n", indentData, hexData, info->name); break; + case TYPE_INTEGER: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(allocationData, data)); break; + case TYPE_BOOLEAN: + printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; + // can't even print a float yet... + case TYPE_STRING: + buffer = malloc(length + 1); + memcpy(data + dataOffset, buffer, length); + buffer[length] = 0; + printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); + free(buffer); + break; + case TYPE_ARRAY: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + case TYPE_MAP: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 1); + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + default: + // this branch should actually be impossible to reach... + printf("unknown\n"); break; + } + free(hexData); + free(indentData); + free(buffer); + return next; +} + +void *msgPackSeek(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + uint32_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + if (info->dataType == TYPE_MAP) { + length <<= 1; + } + switch (info->readType) { + case Inline: + return data + 1; + case FixedLength: + return data + 1 + info->readTypeParameter; + case ReadLength: + return data + 1 + info->readTypeParameter + length; + case InlineLength: + return data + 1 + length; + case ElementsInline: + data++; + goto READ_ELEMENTS; + case ReadElements: + data += 1 + info->readTypeParameter; + READ_ELEMENTS: + for (uint8_t i = 0; i < length; i++) { + data = msgPackSeek(allocationData, data); + } + return data; + } + // should never happen + printf("seek: cannot read %s\n", info->name); + return NULL; +} \ No newline at end of file diff --git a/src/include/buffers.h b/src/include/buffers.h new file mode 100644 index 0000000..b286d20 --- /dev/null +++ b/src/include/buffers.h @@ -0,0 +1,258 @@ +#ifndef HLIB_BUFFERS_H +#define HLIB_BUFFERS_H + +#include +#include "../hlib/malloc.h" + +#define COMMA , + +#define EMPTY(...) +#define DEFER(...) __VA_ARGS__ EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() + +#define EXPAND3(...) __VA_ARGS__ +#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) +#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) +#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) + +#define STRING_Length(x) msgPackStringLength(strlen(x)) + +#define ONE(...) 1 + +#define ARRAY_Length_id() ARRAY_Length +#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) +#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) +#define INTEGER_Length_id() INTEGER_Length +#define STRING_Length_id() STRING_Length +#define MAP_Length_id() MAP_Length + +#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) +#define MAP_Length(contents) msgPackMapLength(allocationData, contents(ONE, +)) + contents(LENGTH, +) + +#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) + +#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); +#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) +#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); + +#define INTEGER_Write_id() INTEGER_Write +#define ARRAY_Write_id() ARRAY_Write +#define STRING_Write_id() STRING_Write +#define MAP_Write_id() MAP_Write + +#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) +#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) + +#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) + +#define CONTENTS contents (LENGTH, +) + +#define CREATE(name, definition) \ + uint32_t name##Length = EXPAND(definition(LENGTH)); \ + void *name = malloc(name##Length); \ + { \ + void *buffer = name; \ + EXPAND(definition(WRITE)) \ + } + +// helper macros to make accessing data in a buffer easier +// all of these check if the type is correct and throw an error if not +#define _AS_INT(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + msgPackReadInt(allocationData, data); \ + }) + +#define _AS_UINT(data, catchError, catchNegative) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + intmax_t asInt = msgPackReadInt(allocationData, data); \ + if (asInt < 0) catchNegative \ + (uint32_t) asInt; \ + }) + +#define _AS_STRING(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_STRING) catchError \ + msgPackReadStr(allocationData, data); \ + }) + +#define AS_INT(data, retval, ...) \ + _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) + +#define AS_UINT(data, retval, ...) \ + _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) + +#define AS_STRING(data, retval, ...) \ + _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) + +#define ARRAY_LOOP(data, retval, elementName, action) \ + { \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_ARRAY) { \ + printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ + return retval; \ + } \ + void *elementName; \ + uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ + for (uint32_t i = 0; i < maxElement; i++) { \ + (action); \ + elementName = msgPackSeek(elementName); \ + } \ + } + +#define GET_FROM_INT(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromInt(allocationData, data, value); \ + }) + +#define GET_FROM_STRING(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromString(allocationData, data, value); \ + }) + + +typedef enum ReadTypes { + Inline, + InlineLength, + FixedLength, + ReadLength, + ElementsInline, + ReadElements, +} ReadTypes; + +typedef enum IntegerType { + Signed, + Unsigned +} IntegerType; + +#define DATA_TYPES(X, S) \ + X(INTEGER) S \ + X(NIL) S \ + X(BOOLEAN) S \ + X(FLOAT) S \ + X(STRING) S \ + X(BINARY) S \ + X(ARRAY) S \ + X(MAP) S \ + X(EXTENSION) S \ + X(UNUSED) + +#define FORMATS(X, S) \ + X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ + X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ + X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ + X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ + X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ + X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ + X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ + X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ + X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ + X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ + X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ + X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ + X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ + X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ + X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ + X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ + X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ + X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ + X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ + X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ + X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ + X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ + X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ + X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ + X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ + X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ + X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ + X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ + X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ + X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ + X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ + X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ + X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ + X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ + X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ + X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) + +// define enums +#define ENUM_X(name) TYPE_##name +typedef enum DataTypes { + DATA_TYPES(ENUM_X, COMMA) +} DataTypes; + +#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name +typedef enum Formats { + FORMATS(ENUM_FORMATS_X, COMMA) +} Formats; + +typedef struct FormatInfo { + char *name; + DataTypes dataType; + ReadTypes readType; + uint32_t readTypeParameter; + uint8_t min, max; +} FormatInfo; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +typedef char * STRING; +typedef intmax_t INT; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); +#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) + +// query functions +extern void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue); +extern void *msgPackMapGEtFromInt(AllocationData allocationData, void *data, intmax_t searchValue); + +// length functions +extern uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount); +extern uint32_t msgPackArrayLength(uint32_t elementCount); +extern uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType); +extern uint32_t msgPackStringLength(uint32_t strlength); + +// write functions +extern void *msgPackArrayWrite(void *buffer, uint32_t elementCount); +extern void *msgPackMapWrite(void *buffer, uint32_t elementCount); +extern void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type); +extern void *msgPackStringWrite(void *buffer, char *string); + +// read functions +extern uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement); +extern uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement); +extern intmax_t msgPackReadInt(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadUint(AllocationData allocationData, void *data); +extern char *msgPackReadStr(AllocationData allocationData, void *data); + +// util / debugging functions +extern void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent); +#define msgPackDump(data) _msgPackDump(allocationData, data, 0) + +extern void initializeFlatBuffers(); + +#endif \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/util.c b/src/hlib/flatBuffers/util.c new file mode 100644 index 0000000..d96f281 --- /dev/null +++ b/src/hlib/flatBuffers/util.c @@ -0,0 +1,130 @@ +#include "flatBuffers.h" + +uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size) { + if (size < 0) { + return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); + } + switch (size) { + case 1: + return *((uint8_t *)(data + 1)); + case 2: + return *((uint16_t *)(data + 1)); + case 4: + return *((uint32_t *)(data + 1)); + // TODO: 64-bit numbers! + } + printf("cannot read length of size %i!\n", size); + return 0; +} + +void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent) { + FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; + uint32_t bytesToRead = 1; + uint32_t dataOffset = 0, dataSize = 0; + uintmax_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + switch (info->readType) { + case Inline: + break; + case InlineLength: + bytesToRead += length; + dataOffset = 1; + dataSize = length; + break; + case FixedLength: + bytesToRead += info->readTypeParameter; + dataOffset = 1; + dataSize = info->readTypeParameter; + break; + case ReadLength: + bytesToRead += info->readTypeParameter + length; + dataOffset = 1 + info->readTypeParameter; + dataSize = length; + break; + case ElementsInline: + dataOffset = 1; + break; + case ReadElements: + bytesToRead += info->readTypeParameter; + dataOffset = 1 + info->readTypeParameter; + dataSize = info->readTypeParameter; + } + char *hexData = malloc(3*bytesToRead); + for (uint32_t i = 0; i < bytesToRead; i++) { + sprintf(hexData + 3*i, "%x ", data[i]); + } + hexData[3*bytesToRead - 1] = 0; + char *indentData = malloc(indent + 1); + memset(indentData, ' ', indent); + indentData[indent] = 0; + void *next = data + bytesToRead; + uint8_t *buffer; + switch (info->dataType) { + case TYPE_NIL: + printf("%s%s: %s\n", indentData, hexData, info->name); break; + case TYPE_INTEGER: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(allocationData, data)); break; + case TYPE_BOOLEAN: + printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; + // can't even print a float yet... + case TYPE_STRING: + buffer = malloc(length + 1); + memcpy(data + dataOffset, buffer, length); + buffer[length] = 0; + printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); + free(buffer); + break; + case TYPE_ARRAY: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + case TYPE_MAP: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 1); + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + default: + // this branch should actually be impossible to reach... + printf("unknown\n"); break; + } + free(hexData); + free(indentData); + free(buffer); + return next; +} + +void *msgPackSeek(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + uint32_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + if (info->dataType == TYPE_MAP) { + length <<= 1; + } + switch (info->readType) { + case Inline: + return data + 1; + case FixedLength: + return data + 1 + info->readTypeParameter; + case ReadLength: + return data + 1 + info->readTypeParameter + length; + case InlineLength: + return data + 1 + length; + case ElementsInline: + data++; + goto READ_ELEMENTS; + case ReadElements: + data += 1 + info->readTypeParameter; + READ_ELEMENTS: + for (uint8_t i = 0; i < length; i++) { + data = msgPackSeek(allocationData, data); + } + return data; + } + // should never happen + printf("seek: cannot read %s\n", info->name); + return NULL; +} \ No newline at end of file diff --git a/src/include/buffers.h b/src/include/buffers.h new file mode 100644 index 0000000..b286d20 --- /dev/null +++ b/src/include/buffers.h @@ -0,0 +1,258 @@ +#ifndef HLIB_BUFFERS_H +#define HLIB_BUFFERS_H + +#include +#include "../hlib/malloc.h" + +#define COMMA , + +#define EMPTY(...) +#define DEFER(...) __VA_ARGS__ EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() + +#define EXPAND3(...) __VA_ARGS__ +#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) +#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) +#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) + +#define STRING_Length(x) msgPackStringLength(strlen(x)) + +#define ONE(...) 1 + +#define ARRAY_Length_id() ARRAY_Length +#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) +#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) +#define INTEGER_Length_id() INTEGER_Length +#define STRING_Length_id() STRING_Length +#define MAP_Length_id() MAP_Length + +#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) +#define MAP_Length(contents) msgPackMapLength(allocationData, contents(ONE, +)) + contents(LENGTH, +) + +#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) + +#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); +#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) +#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); + +#define INTEGER_Write_id() INTEGER_Write +#define ARRAY_Write_id() ARRAY_Write +#define STRING_Write_id() STRING_Write +#define MAP_Write_id() MAP_Write + +#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) +#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) + +#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) + +#define CONTENTS contents (LENGTH, +) + +#define CREATE(name, definition) \ + uint32_t name##Length = EXPAND(definition(LENGTH)); \ + void *name = malloc(name##Length); \ + { \ + void *buffer = name; \ + EXPAND(definition(WRITE)) \ + } + +// helper macros to make accessing data in a buffer easier +// all of these check if the type is correct and throw an error if not +#define _AS_INT(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + msgPackReadInt(allocationData, data); \ + }) + +#define _AS_UINT(data, catchError, catchNegative) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + intmax_t asInt = msgPackReadInt(allocationData, data); \ + if (asInt < 0) catchNegative \ + (uint32_t) asInt; \ + }) + +#define _AS_STRING(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_STRING) catchError \ + msgPackReadStr(allocationData, data); \ + }) + +#define AS_INT(data, retval, ...) \ + _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) + +#define AS_UINT(data, retval, ...) \ + _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) + +#define AS_STRING(data, retval, ...) \ + _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) + +#define ARRAY_LOOP(data, retval, elementName, action) \ + { \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_ARRAY) { \ + printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ + return retval; \ + } \ + void *elementName; \ + uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ + for (uint32_t i = 0; i < maxElement; i++) { \ + (action); \ + elementName = msgPackSeek(elementName); \ + } \ + } + +#define GET_FROM_INT(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromInt(allocationData, data, value); \ + }) + +#define GET_FROM_STRING(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromString(allocationData, data, value); \ + }) + + +typedef enum ReadTypes { + Inline, + InlineLength, + FixedLength, + ReadLength, + ElementsInline, + ReadElements, +} ReadTypes; + +typedef enum IntegerType { + Signed, + Unsigned +} IntegerType; + +#define DATA_TYPES(X, S) \ + X(INTEGER) S \ + X(NIL) S \ + X(BOOLEAN) S \ + X(FLOAT) S \ + X(STRING) S \ + X(BINARY) S \ + X(ARRAY) S \ + X(MAP) S \ + X(EXTENSION) S \ + X(UNUSED) + +#define FORMATS(X, S) \ + X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ + X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ + X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ + X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ + X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ + X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ + X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ + X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ + X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ + X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ + X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ + X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ + X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ + X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ + X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ + X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ + X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ + X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ + X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ + X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ + X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ + X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ + X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ + X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ + X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ + X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ + X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ + X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ + X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ + X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ + X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ + X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ + X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ + X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ + X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ + X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) + +// define enums +#define ENUM_X(name) TYPE_##name +typedef enum DataTypes { + DATA_TYPES(ENUM_X, COMMA) +} DataTypes; + +#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name +typedef enum Formats { + FORMATS(ENUM_FORMATS_X, COMMA) +} Formats; + +typedef struct FormatInfo { + char *name; + DataTypes dataType; + ReadTypes readType; + uint32_t readTypeParameter; + uint8_t min, max; +} FormatInfo; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +typedef char * STRING; +typedef intmax_t INT; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); +#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) + +// query functions +extern void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue); +extern void *msgPackMapGEtFromInt(AllocationData allocationData, void *data, intmax_t searchValue); + +// length functions +extern uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount); +extern uint32_t msgPackArrayLength(uint32_t elementCount); +extern uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType); +extern uint32_t msgPackStringLength(uint32_t strlength); + +// write functions +extern void *msgPackArrayWrite(void *buffer, uint32_t elementCount); +extern void *msgPackMapWrite(void *buffer, uint32_t elementCount); +extern void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type); +extern void *msgPackStringWrite(void *buffer, char *string); + +// read functions +extern uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement); +extern uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement); +extern intmax_t msgPackReadInt(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadUint(AllocationData allocationData, void *data); +extern char *msgPackReadStr(AllocationData allocationData, void *data); + +// util / debugging functions +extern void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent); +#define msgPackDump(data) _msgPackDump(allocationData, data, 0) + +extern void initializeFlatBuffers(); + +#endif \ No newline at end of file diff --git a/src/include/hlib.h b/src/include/hlib.h index 4ba8e13..d505a69 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -10,6 +10,7 @@ } ListElement; #include "../hlib/malloc.h" +#include "buffers.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) @@ -109,4 +110,9 @@ extern bool checkFocus(); +#define COMMA , +#define NOTHING +#define SEMICOLON ; +#define ABS(x) (x >= 0 ? x : -x) + #endif diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/util.c b/src/hlib/flatBuffers/util.c new file mode 100644 index 0000000..d96f281 --- /dev/null +++ b/src/hlib/flatBuffers/util.c @@ -0,0 +1,130 @@ +#include "flatBuffers.h" + +uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size) { + if (size < 0) { + return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); + } + switch (size) { + case 1: + return *((uint8_t *)(data + 1)); + case 2: + return *((uint16_t *)(data + 1)); + case 4: + return *((uint32_t *)(data + 1)); + // TODO: 64-bit numbers! + } + printf("cannot read length of size %i!\n", size); + return 0; +} + +void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent) { + FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; + uint32_t bytesToRead = 1; + uint32_t dataOffset = 0, dataSize = 0; + uintmax_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + switch (info->readType) { + case Inline: + break; + case InlineLength: + bytesToRead += length; + dataOffset = 1; + dataSize = length; + break; + case FixedLength: + bytesToRead += info->readTypeParameter; + dataOffset = 1; + dataSize = info->readTypeParameter; + break; + case ReadLength: + bytesToRead += info->readTypeParameter + length; + dataOffset = 1 + info->readTypeParameter; + dataSize = length; + break; + case ElementsInline: + dataOffset = 1; + break; + case ReadElements: + bytesToRead += info->readTypeParameter; + dataOffset = 1 + info->readTypeParameter; + dataSize = info->readTypeParameter; + } + char *hexData = malloc(3*bytesToRead); + for (uint32_t i = 0; i < bytesToRead; i++) { + sprintf(hexData + 3*i, "%x ", data[i]); + } + hexData[3*bytesToRead - 1] = 0; + char *indentData = malloc(indent + 1); + memset(indentData, ' ', indent); + indentData[indent] = 0; + void *next = data + bytesToRead; + uint8_t *buffer; + switch (info->dataType) { + case TYPE_NIL: + printf("%s%s: %s\n", indentData, hexData, info->name); break; + case TYPE_INTEGER: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(allocationData, data)); break; + case TYPE_BOOLEAN: + printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; + // can't even print a float yet... + case TYPE_STRING: + buffer = malloc(length + 1); + memcpy(data + dataOffset, buffer, length); + buffer[length] = 0; + printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); + free(buffer); + break; + case TYPE_ARRAY: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + case TYPE_MAP: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 1); + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + default: + // this branch should actually be impossible to reach... + printf("unknown\n"); break; + } + free(hexData); + free(indentData); + free(buffer); + return next; +} + +void *msgPackSeek(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + uint32_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + if (info->dataType == TYPE_MAP) { + length <<= 1; + } + switch (info->readType) { + case Inline: + return data + 1; + case FixedLength: + return data + 1 + info->readTypeParameter; + case ReadLength: + return data + 1 + info->readTypeParameter + length; + case InlineLength: + return data + 1 + length; + case ElementsInline: + data++; + goto READ_ELEMENTS; + case ReadElements: + data += 1 + info->readTypeParameter; + READ_ELEMENTS: + for (uint8_t i = 0; i < length; i++) { + data = msgPackSeek(allocationData, data); + } + return data; + } + // should never happen + printf("seek: cannot read %s\n", info->name); + return NULL; +} \ No newline at end of file diff --git a/src/include/buffers.h b/src/include/buffers.h new file mode 100644 index 0000000..b286d20 --- /dev/null +++ b/src/include/buffers.h @@ -0,0 +1,258 @@ +#ifndef HLIB_BUFFERS_H +#define HLIB_BUFFERS_H + +#include +#include "../hlib/malloc.h" + +#define COMMA , + +#define EMPTY(...) +#define DEFER(...) __VA_ARGS__ EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() + +#define EXPAND3(...) __VA_ARGS__ +#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) +#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) +#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) + +#define STRING_Length(x) msgPackStringLength(strlen(x)) + +#define ONE(...) 1 + +#define ARRAY_Length_id() ARRAY_Length +#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) +#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) +#define INTEGER_Length_id() INTEGER_Length +#define STRING_Length_id() STRING_Length +#define MAP_Length_id() MAP_Length + +#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) +#define MAP_Length(contents) msgPackMapLength(allocationData, contents(ONE, +)) + contents(LENGTH, +) + +#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) + +#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); +#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) +#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); + +#define INTEGER_Write_id() INTEGER_Write +#define ARRAY_Write_id() ARRAY_Write +#define STRING_Write_id() STRING_Write +#define MAP_Write_id() MAP_Write + +#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) +#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) + +#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) + +#define CONTENTS contents (LENGTH, +) + +#define CREATE(name, definition) \ + uint32_t name##Length = EXPAND(definition(LENGTH)); \ + void *name = malloc(name##Length); \ + { \ + void *buffer = name; \ + EXPAND(definition(WRITE)) \ + } + +// helper macros to make accessing data in a buffer easier +// all of these check if the type is correct and throw an error if not +#define _AS_INT(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + msgPackReadInt(allocationData, data); \ + }) + +#define _AS_UINT(data, catchError, catchNegative) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + intmax_t asInt = msgPackReadInt(allocationData, data); \ + if (asInt < 0) catchNegative \ + (uint32_t) asInt; \ + }) + +#define _AS_STRING(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_STRING) catchError \ + msgPackReadStr(allocationData, data); \ + }) + +#define AS_INT(data, retval, ...) \ + _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) + +#define AS_UINT(data, retval, ...) \ + _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) + +#define AS_STRING(data, retval, ...) \ + _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) + +#define ARRAY_LOOP(data, retval, elementName, action) \ + { \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_ARRAY) { \ + printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ + return retval; \ + } \ + void *elementName; \ + uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ + for (uint32_t i = 0; i < maxElement; i++) { \ + (action); \ + elementName = msgPackSeek(elementName); \ + } \ + } + +#define GET_FROM_INT(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromInt(allocationData, data, value); \ + }) + +#define GET_FROM_STRING(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromString(allocationData, data, value); \ + }) + + +typedef enum ReadTypes { + Inline, + InlineLength, + FixedLength, + ReadLength, + ElementsInline, + ReadElements, +} ReadTypes; + +typedef enum IntegerType { + Signed, + Unsigned +} IntegerType; + +#define DATA_TYPES(X, S) \ + X(INTEGER) S \ + X(NIL) S \ + X(BOOLEAN) S \ + X(FLOAT) S \ + X(STRING) S \ + X(BINARY) S \ + X(ARRAY) S \ + X(MAP) S \ + X(EXTENSION) S \ + X(UNUSED) + +#define FORMATS(X, S) \ + X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ + X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ + X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ + X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ + X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ + X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ + X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ + X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ + X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ + X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ + X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ + X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ + X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ + X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ + X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ + X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ + X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ + X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ + X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ + X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ + X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ + X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ + X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ + X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ + X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ + X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ + X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ + X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ + X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ + X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ + X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ + X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ + X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ + X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ + X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ + X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) + +// define enums +#define ENUM_X(name) TYPE_##name +typedef enum DataTypes { + DATA_TYPES(ENUM_X, COMMA) +} DataTypes; + +#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name +typedef enum Formats { + FORMATS(ENUM_FORMATS_X, COMMA) +} Formats; + +typedef struct FormatInfo { + char *name; + DataTypes dataType; + ReadTypes readType; + uint32_t readTypeParameter; + uint8_t min, max; +} FormatInfo; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +typedef char * STRING; +typedef intmax_t INT; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); +#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) + +// query functions +extern void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue); +extern void *msgPackMapGEtFromInt(AllocationData allocationData, void *data, intmax_t searchValue); + +// length functions +extern uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount); +extern uint32_t msgPackArrayLength(uint32_t elementCount); +extern uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType); +extern uint32_t msgPackStringLength(uint32_t strlength); + +// write functions +extern void *msgPackArrayWrite(void *buffer, uint32_t elementCount); +extern void *msgPackMapWrite(void *buffer, uint32_t elementCount); +extern void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type); +extern void *msgPackStringWrite(void *buffer, char *string); + +// read functions +extern uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement); +extern uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement); +extern intmax_t msgPackReadInt(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadUint(AllocationData allocationData, void *data); +extern char *msgPackReadStr(AllocationData allocationData, void *data); + +// util / debugging functions +extern void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent); +#define msgPackDump(data) _msgPackDump(allocationData, data, 0) + +extern void initializeFlatBuffers(); + +#endif \ No newline at end of file diff --git a/src/include/hlib.h b/src/include/hlib.h index 4ba8e13..d505a69 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -10,6 +10,7 @@ } ListElement; #include "../hlib/malloc.h" +#include "buffers.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) @@ -109,4 +110,9 @@ extern bool checkFocus(); +#define COMMA , +#define NOTHING +#define SEMICOLON ; +#define ABS(x) (x >= 0 ? x : -x) + #endif diff --git a/src/userland/buffersTests/include/buffers.h b/src/userland/buffersTests/include/buffers.h deleted file mode 100644 index afb0a0e..0000000 --- a/src/userland/buffersTests/include/buffers.h +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef BUFFERS_H -#define BUFFERS_H - -#include - -#define COMMA , -#define SEMICOLON ; -#define NOTHING - -typedef enum ReadTypes { - Inline, - InlineLength, - FixedLength, - ReadLength, - ElementsInline, - ReadElements, -} ReadTypes; - -typedef enum IntegerType { - Signed, - Unsigned -} IntegerType; - -#define DATA_TYPES(X, S) \ - X(INTEGER) S \ - X(NIL) S \ - X(BOOLEAN) S \ - X(FLOAT) S \ - X(STRING) S \ - X(BINARY) S \ - X(ARRAY) S \ - X(MAP) S \ - X(EXTENSION) S \ - X(UNUSED) - -#define FORMATS(X, S) \ - X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ - X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ - X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ - X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ - X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ - X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ - X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ - X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ - X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ - X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ - X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ - X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ - X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ - X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ - X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ - X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ - X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ - X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ - X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ - X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ - X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ - X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ - X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ - X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ - X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ - X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ - X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ - X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ - X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ - X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ - X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ - X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ - X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ - X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ - X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ - X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) - -// define enums -#define ENUM_X(name) TYPE_##name -typedef enum DataTypes { - DATA_TYPES(ENUM_X, COMMA) -} DataTypes; - -#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name -typedef enum Formats { - FORMATS(ENUM_FORMATS_X, COMMA) -} Formats; - -typedef struct FormatInfo { - char *name; - DataTypes dataType; - ReadTypes readType; - uint32_t readTypeParameter; - uint8_t min, max; -} FormatInfo; - -extern Formats FirstByteToFormat[256]; -extern FormatInfo formatInfo[]; - -// macros for initializing a buffer -#define ABS(x) (x >= 0 ? x : -x) -#define EMPTY(...) -#define DEFER(...) __VA_ARGS__ EMPTY() -#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() - -#define EXPAND3(...) __VA_ARGS__ -#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) -#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) -#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) - -#define STRING_Length(x) msgPackStringLength(strlen(x)) - -#define ONE(...) 1 - -#define ARRAY_Length_id() ARRAY_Length -#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) -#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) -#define INTEGER_Length_id() INTEGER_Length -#define STRING_Length_id() STRING_Length -#define MAP_Length_id() MAP_Length - -#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) -#define MAP_Length(contents) msgPackMapLength(contents(ONE, +)) + contents(LENGTH, +) - -#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) - -#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); -#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) -#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); - -#define INTEGER_Write_id() INTEGER_Write -#define ARRAY_Write_id() ARRAY_Write -#define STRING_Write_id() STRING_Write -#define MAP_Write_id() MAP_Write - -#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) -#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) - -#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) - -#define CONTENTS contents (LENGTH, +) - -extern uint32_t msgPackReadUint(void *data); -extern intmax_t msgPackReadInt(void *data); - -#define CREATE(name, definition) \ - uint32_t name##Length = EXPAND(definition(LENGTH)); \ - void *name = malloc(name##Length); \ - { \ - void *buffer = name; \ - EXPAND(definition(WRITE)) \ - } - -// helper macros to make accessing data in a buffer easier -// all of these check if the type is correct and throw an error if not -#define _AS_INT(data, catchError) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ - msgPackReadInt(data); \ - }) - -#define _AS_UINT(data, catchError, catchNegative) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ - intmax_t asInt = msgPackReadInt(data); \ - if (asInt < 0) catchNegative \ - (uint32_t) asInt; \ - }) - -#define _AS_STRING(data, catchError) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_STRING) catchError \ - msgPackReadStr(data); \ - }) - -#define AS_INT(data, retval, ...) \ - _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) - -#define AS_UINT(data, retval, ...) \ - _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) - -#define AS_STRING(data, retval, ...) \ - _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) - -#define ARRAY_LOOP(data, retval, elementName, action) \ - { \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_ARRAY) { \ - printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ - return retval; \ - } \ - void *elementName; \ - uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ - for (uint32_t i = 0; i < maxElement; i++) { \ - (action); \ - elementName = msgPackSeek(elementName); \ - } \ - } - -#define GET_FROM_INT(data, value, retval) \ - ({ \ - uint8_t *buffer = (uint8_t *)data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_MAP) { \ - printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ - return retval; \ - } \ - msgPackMapGetFromInt(data, value); \ - }) - -#define GET_FROM_STRING(data, value, retval) \ - ({ \ - uint8_t *buffer = (uint8_t *)data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_MAP) { \ - printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ - return retval; \ - } \ - msgPackMapGetFromString(data, value); \ - }) - -typedef char * STRING; -typedef intmax_t INT; - -#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); -#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) - -#endif // BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/util.c b/src/hlib/flatBuffers/util.c new file mode 100644 index 0000000..d96f281 --- /dev/null +++ b/src/hlib/flatBuffers/util.c @@ -0,0 +1,130 @@ +#include "flatBuffers.h" + +uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size) { + if (size < 0) { + return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); + } + switch (size) { + case 1: + return *((uint8_t *)(data + 1)); + case 2: + return *((uint16_t *)(data + 1)); + case 4: + return *((uint32_t *)(data + 1)); + // TODO: 64-bit numbers! + } + printf("cannot read length of size %i!\n", size); + return 0; +} + +void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent) { + FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; + uint32_t bytesToRead = 1; + uint32_t dataOffset = 0, dataSize = 0; + uintmax_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + switch (info->readType) { + case Inline: + break; + case InlineLength: + bytesToRead += length; + dataOffset = 1; + dataSize = length; + break; + case FixedLength: + bytesToRead += info->readTypeParameter; + dataOffset = 1; + dataSize = info->readTypeParameter; + break; + case ReadLength: + bytesToRead += info->readTypeParameter + length; + dataOffset = 1 + info->readTypeParameter; + dataSize = length; + break; + case ElementsInline: + dataOffset = 1; + break; + case ReadElements: + bytesToRead += info->readTypeParameter; + dataOffset = 1 + info->readTypeParameter; + dataSize = info->readTypeParameter; + } + char *hexData = malloc(3*bytesToRead); + for (uint32_t i = 0; i < bytesToRead; i++) { + sprintf(hexData + 3*i, "%x ", data[i]); + } + hexData[3*bytesToRead - 1] = 0; + char *indentData = malloc(indent + 1); + memset(indentData, ' ', indent); + indentData[indent] = 0; + void *next = data + bytesToRead; + uint8_t *buffer; + switch (info->dataType) { + case TYPE_NIL: + printf("%s%s: %s\n", indentData, hexData, info->name); break; + case TYPE_INTEGER: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(allocationData, data)); break; + case TYPE_BOOLEAN: + printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; + // can't even print a float yet... + case TYPE_STRING: + buffer = malloc(length + 1); + memcpy(data + dataOffset, buffer, length); + buffer[length] = 0; + printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); + free(buffer); + break; + case TYPE_ARRAY: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + case TYPE_MAP: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 1); + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + default: + // this branch should actually be impossible to reach... + printf("unknown\n"); break; + } + free(hexData); + free(indentData); + free(buffer); + return next; +} + +void *msgPackSeek(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + uint32_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + if (info->dataType == TYPE_MAP) { + length <<= 1; + } + switch (info->readType) { + case Inline: + return data + 1; + case FixedLength: + return data + 1 + info->readTypeParameter; + case ReadLength: + return data + 1 + info->readTypeParameter + length; + case InlineLength: + return data + 1 + length; + case ElementsInline: + data++; + goto READ_ELEMENTS; + case ReadElements: + data += 1 + info->readTypeParameter; + READ_ELEMENTS: + for (uint8_t i = 0; i < length; i++) { + data = msgPackSeek(allocationData, data); + } + return data; + } + // should never happen + printf("seek: cannot read %s\n", info->name); + return NULL; +} \ No newline at end of file diff --git a/src/include/buffers.h b/src/include/buffers.h new file mode 100644 index 0000000..b286d20 --- /dev/null +++ b/src/include/buffers.h @@ -0,0 +1,258 @@ +#ifndef HLIB_BUFFERS_H +#define HLIB_BUFFERS_H + +#include +#include "../hlib/malloc.h" + +#define COMMA , + +#define EMPTY(...) +#define DEFER(...) __VA_ARGS__ EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() + +#define EXPAND3(...) __VA_ARGS__ +#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) +#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) +#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) + +#define STRING_Length(x) msgPackStringLength(strlen(x)) + +#define ONE(...) 1 + +#define ARRAY_Length_id() ARRAY_Length +#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) +#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) +#define INTEGER_Length_id() INTEGER_Length +#define STRING_Length_id() STRING_Length +#define MAP_Length_id() MAP_Length + +#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) +#define MAP_Length(contents) msgPackMapLength(allocationData, contents(ONE, +)) + contents(LENGTH, +) + +#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) + +#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); +#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) +#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); + +#define INTEGER_Write_id() INTEGER_Write +#define ARRAY_Write_id() ARRAY_Write +#define STRING_Write_id() STRING_Write +#define MAP_Write_id() MAP_Write + +#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) +#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) + +#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) + +#define CONTENTS contents (LENGTH, +) + +#define CREATE(name, definition) \ + uint32_t name##Length = EXPAND(definition(LENGTH)); \ + void *name = malloc(name##Length); \ + { \ + void *buffer = name; \ + EXPAND(definition(WRITE)) \ + } + +// helper macros to make accessing data in a buffer easier +// all of these check if the type is correct and throw an error if not +#define _AS_INT(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + msgPackReadInt(allocationData, data); \ + }) + +#define _AS_UINT(data, catchError, catchNegative) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + intmax_t asInt = msgPackReadInt(allocationData, data); \ + if (asInt < 0) catchNegative \ + (uint32_t) asInt; \ + }) + +#define _AS_STRING(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_STRING) catchError \ + msgPackReadStr(allocationData, data); \ + }) + +#define AS_INT(data, retval, ...) \ + _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) + +#define AS_UINT(data, retval, ...) \ + _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) + +#define AS_STRING(data, retval, ...) \ + _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) + +#define ARRAY_LOOP(data, retval, elementName, action) \ + { \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_ARRAY) { \ + printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ + return retval; \ + } \ + void *elementName; \ + uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ + for (uint32_t i = 0; i < maxElement; i++) { \ + (action); \ + elementName = msgPackSeek(elementName); \ + } \ + } + +#define GET_FROM_INT(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromInt(allocationData, data, value); \ + }) + +#define GET_FROM_STRING(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromString(allocationData, data, value); \ + }) + + +typedef enum ReadTypes { + Inline, + InlineLength, + FixedLength, + ReadLength, + ElementsInline, + ReadElements, +} ReadTypes; + +typedef enum IntegerType { + Signed, + Unsigned +} IntegerType; + +#define DATA_TYPES(X, S) \ + X(INTEGER) S \ + X(NIL) S \ + X(BOOLEAN) S \ + X(FLOAT) S \ + X(STRING) S \ + X(BINARY) S \ + X(ARRAY) S \ + X(MAP) S \ + X(EXTENSION) S \ + X(UNUSED) + +#define FORMATS(X, S) \ + X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ + X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ + X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ + X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ + X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ + X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ + X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ + X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ + X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ + X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ + X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ + X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ + X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ + X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ + X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ + X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ + X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ + X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ + X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ + X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ + X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ + X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ + X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ + X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ + X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ + X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ + X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ + X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ + X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ + X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ + X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ + X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ + X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ + X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ + X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ + X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) + +// define enums +#define ENUM_X(name) TYPE_##name +typedef enum DataTypes { + DATA_TYPES(ENUM_X, COMMA) +} DataTypes; + +#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name +typedef enum Formats { + FORMATS(ENUM_FORMATS_X, COMMA) +} Formats; + +typedef struct FormatInfo { + char *name; + DataTypes dataType; + ReadTypes readType; + uint32_t readTypeParameter; + uint8_t min, max; +} FormatInfo; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +typedef char * STRING; +typedef intmax_t INT; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); +#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) + +// query functions +extern void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue); +extern void *msgPackMapGEtFromInt(AllocationData allocationData, void *data, intmax_t searchValue); + +// length functions +extern uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount); +extern uint32_t msgPackArrayLength(uint32_t elementCount); +extern uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType); +extern uint32_t msgPackStringLength(uint32_t strlength); + +// write functions +extern void *msgPackArrayWrite(void *buffer, uint32_t elementCount); +extern void *msgPackMapWrite(void *buffer, uint32_t elementCount); +extern void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type); +extern void *msgPackStringWrite(void *buffer, char *string); + +// read functions +extern uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement); +extern uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement); +extern intmax_t msgPackReadInt(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadUint(AllocationData allocationData, void *data); +extern char *msgPackReadStr(AllocationData allocationData, void *data); + +// util / debugging functions +extern void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent); +#define msgPackDump(data) _msgPackDump(allocationData, data, 0) + +extern void initializeFlatBuffers(); + +#endif \ No newline at end of file diff --git a/src/include/hlib.h b/src/include/hlib.h index 4ba8e13..d505a69 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -10,6 +10,7 @@ } ListElement; #include "../hlib/malloc.h" +#include "buffers.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) @@ -109,4 +110,9 @@ extern bool checkFocus(); +#define COMMA , +#define NOTHING +#define SEMICOLON ; +#define ABS(x) (x >= 0 ? x : -x) + #endif diff --git a/src/userland/buffersTests/include/buffers.h b/src/userland/buffersTests/include/buffers.h deleted file mode 100644 index afb0a0e..0000000 --- a/src/userland/buffersTests/include/buffers.h +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef BUFFERS_H -#define BUFFERS_H - -#include - -#define COMMA , -#define SEMICOLON ; -#define NOTHING - -typedef enum ReadTypes { - Inline, - InlineLength, - FixedLength, - ReadLength, - ElementsInline, - ReadElements, -} ReadTypes; - -typedef enum IntegerType { - Signed, - Unsigned -} IntegerType; - -#define DATA_TYPES(X, S) \ - X(INTEGER) S \ - X(NIL) S \ - X(BOOLEAN) S \ - X(FLOAT) S \ - X(STRING) S \ - X(BINARY) S \ - X(ARRAY) S \ - X(MAP) S \ - X(EXTENSION) S \ - X(UNUSED) - -#define FORMATS(X, S) \ - X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ - X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ - X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ - X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ - X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ - X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ - X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ - X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ - X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ - X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ - X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ - X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ - X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ - X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ - X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ - X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ - X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ - X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ - X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ - X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ - X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ - X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ - X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ - X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ - X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ - X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ - X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ - X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ - X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ - X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ - X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ - X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ - X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ - X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ - X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ - X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) - -// define enums -#define ENUM_X(name) TYPE_##name -typedef enum DataTypes { - DATA_TYPES(ENUM_X, COMMA) -} DataTypes; - -#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name -typedef enum Formats { - FORMATS(ENUM_FORMATS_X, COMMA) -} Formats; - -typedef struct FormatInfo { - char *name; - DataTypes dataType; - ReadTypes readType; - uint32_t readTypeParameter; - uint8_t min, max; -} FormatInfo; - -extern Formats FirstByteToFormat[256]; -extern FormatInfo formatInfo[]; - -// macros for initializing a buffer -#define ABS(x) (x >= 0 ? x : -x) -#define EMPTY(...) -#define DEFER(...) __VA_ARGS__ EMPTY() -#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() - -#define EXPAND3(...) __VA_ARGS__ -#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) -#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) -#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) - -#define STRING_Length(x) msgPackStringLength(strlen(x)) - -#define ONE(...) 1 - -#define ARRAY_Length_id() ARRAY_Length -#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) -#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) -#define INTEGER_Length_id() INTEGER_Length -#define STRING_Length_id() STRING_Length -#define MAP_Length_id() MAP_Length - -#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) -#define MAP_Length(contents) msgPackMapLength(contents(ONE, +)) + contents(LENGTH, +) - -#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) - -#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); -#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) -#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); - -#define INTEGER_Write_id() INTEGER_Write -#define ARRAY_Write_id() ARRAY_Write -#define STRING_Write_id() STRING_Write -#define MAP_Write_id() MAP_Write - -#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) -#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) - -#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) - -#define CONTENTS contents (LENGTH, +) - -extern uint32_t msgPackReadUint(void *data); -extern intmax_t msgPackReadInt(void *data); - -#define CREATE(name, definition) \ - uint32_t name##Length = EXPAND(definition(LENGTH)); \ - void *name = malloc(name##Length); \ - { \ - void *buffer = name; \ - EXPAND(definition(WRITE)) \ - } - -// helper macros to make accessing data in a buffer easier -// all of these check if the type is correct and throw an error if not -#define _AS_INT(data, catchError) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ - msgPackReadInt(data); \ - }) - -#define _AS_UINT(data, catchError, catchNegative) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ - intmax_t asInt = msgPackReadInt(data); \ - if (asInt < 0) catchNegative \ - (uint32_t) asInt; \ - }) - -#define _AS_STRING(data, catchError) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_STRING) catchError \ - msgPackReadStr(data); \ - }) - -#define AS_INT(data, retval, ...) \ - _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) - -#define AS_UINT(data, retval, ...) \ - _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) - -#define AS_STRING(data, retval, ...) \ - _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) - -#define ARRAY_LOOP(data, retval, elementName, action) \ - { \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_ARRAY) { \ - printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ - return retval; \ - } \ - void *elementName; \ - uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ - for (uint32_t i = 0; i < maxElement; i++) { \ - (action); \ - elementName = msgPackSeek(elementName); \ - } \ - } - -#define GET_FROM_INT(data, value, retval) \ - ({ \ - uint8_t *buffer = (uint8_t *)data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_MAP) { \ - printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ - return retval; \ - } \ - msgPackMapGetFromInt(data, value); \ - }) - -#define GET_FROM_STRING(data, value, retval) \ - ({ \ - uint8_t *buffer = (uint8_t *)data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_MAP) { \ - printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ - return retval; \ - } \ - msgPackMapGetFromString(data, value); \ - }) - -typedef char * STRING; -typedef intmax_t INT; - -#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); -#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) - -#endif // BUFFERS_H \ No newline at end of file diff --git a/src/userland/buffersTests/main.c b/src/userland/buffersTests/main.c index 57e8153..12cdef0 100644 --- a/src/userland/buffersTests/main.c +++ b/src/userland/buffersTests/main.c @@ -1,509 +1,6 @@ #include #include -// see https://github.com/msgpack/msgpack/blob/master/spec.md - -#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ - { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } - -FormatInfo formatInfo[] = { - FORMATS(FORMATS_STRUCTS_X, COMMA) -}; - -Formats FirstByteToFormat[256]; - -uintmax_t msgPackReadLength(void *data, int8_t size) { - if (size < 0) { - return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); - } - switch (size) { - case 1: - return *((uint8_t *)(data + 1)); - case 2: - return *((uint16_t *)(data + 1)); - case 4: - return *((uint32_t *)(data + 1)); - // TODO: 64-bit numbers! - } - printf("cannot read length of size %i!\n", size); - return 0; -} - -void *msgPackDump(uint8_t *data, uint32_t indent) { - FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; - uint32_t bytesToRead = 1; - uint32_t dataOffset = 0, dataSize = 0; - uintmax_t length = msgPackReadLength(data, info->readTypeParameter); - switch (info->readType) { - case Inline: - break; - case InlineLength: - bytesToRead += length; - dataOffset = 1; - dataSize = length; - break; - case FixedLength: - bytesToRead += info->readTypeParameter; - dataOffset = 1; - dataSize = info->readTypeParameter; - break; - case ReadLength: - bytesToRead += info->readTypeParameter + length; - dataOffset = 1 + info->readTypeParameter; - dataSize = length; - break; - case ElementsInline: - dataOffset = 1; - break; - case ReadElements: - bytesToRead += info->readTypeParameter; - dataOffset = 1 + info->readTypeParameter; - dataSize = info->readTypeParameter; - } - char *hexData = malloc(3*bytesToRead); - for (uint32_t i = 0; i < bytesToRead; i++) { - sprintf(hexData + 3*i, "%x ", data[i]); - } - hexData[3*bytesToRead - 1] = 0; - char *indentData = malloc(indent + 1); - memset(indentData, ' ', indent); - indentData[indent] = 0; - void *next = data + bytesToRead; - uint8_t *buffer; - switch (info->dataType) { - case TYPE_NIL: - printf("%s%s: %s\n", indentData, hexData, info->name); break; - case TYPE_INTEGER: - printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(data)); break; - case TYPE_BOOLEAN: - printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; - // can't even print a float yet... - case TYPE_STRING: - buffer = malloc(length + 1); - memcpy(data + dataOffset, buffer, length); - buffer[length] = 0; - printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); - free(buffer); - break; - case TYPE_ARRAY: - printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); - for (uint32_t i = 0; i < length; i++) { - next = msgPackDump(next, indent + 2); - } - break; - case TYPE_MAP: - printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); - for (uint32_t i = 0; i < length; i++) { - next = msgPackDump(next, indent + 1); - next = msgPackDump(next, indent + 2); - } - break; - default: - // this branch should actually be impossible to reach... - printf("unknown\n"); break; - } - free(hexData); - free(indentData); - free(buffer); - return next; -} - -void fillSpots(uint16_t from, uint16_t to, Formats value) { - for (uint16_t i = from; i <= to; i++) { - FirstByteToFormat[i] = value; - } -} - -#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); -void initialize() { - FORMATS(FILL_SPOTS_X, NOTHING); -} - -uint32_t msgPackStringLength(uint32_t strlength) { - if ((strlength & 0x1F) == strlength) { - // fixstr - return 1 + strlength; - } - if ((strlength & 0xFF) == strlength) { - // str8 - return 2 + strlength; - } - if ((strlength & 0xFFFF) == strlength) { - // str16 - return 3 + strlength; - } - // str32 - return 5 + strlength; -} - -void *msgPackStringWrite(void *buffer, char *string) { - uint32_t length = strlen(string); - uint8_t *bufferByte = buffer; - if ((length & 0x1F) == length) { - *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; - buffer++; - } else if ((length & 0xFF) == length) { - *bufferByte = formatInfo[FORMAT_STR8].min; - *(uint8_t *)(buffer + 1) = (uint8_t) length; - buffer += 2; - } else if ((length & 0xFFFF) == length) { - *bufferByte = formatInfo[FORMAT_STR16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) length; - buffer += 3; - } else { - *bufferByte = formatInfo[FORMAT_STR32].min; - *(uint32_t *)(buffer + 1) = (uint32_t) length; - buffer += 5; - } - memcpy(string, buffer, length); - return buffer + length; -} - -uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { - if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { - // fixint - return 1; - } - value = ABS(value); - if ((value & 0xFF) == value) { - // int8 - return 2; - } - if ((value & 0xFFFF) == value) { - // int16 - return 3; - } - if ((value & 0xFFFFFFFF) == value) { - // int32 - return 5; - } - // int64 - return 9; -} - -void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { - if (x < 0 && type != Signed) { - printf("integerWrite: %i is negative but type is Unsigned!\n", x); - return buffer; - } - uint8_t *bufferByte = buffer; - if ((x & 0x7F) == x) { - *bufferByte = (uint8_t)x; - // fixint - return buffer + 1; - } - if (((~x) & 0x1F) == ~x) { - *bufferByte = (int8_t)x; - // negative fixint - return buffer + 1; - } - if ((uint8_t)x == x) { - *bufferByte = formatInfo[FORMAT_UINT8].min; - *(uint8_t *)(buffer + 1) = (uint8_t) x; - return buffer + 2; - } - if ((int8_t) x == x) { - *bufferByte = formatInfo[FORMAT_INT8].min; - *(int8_t *)(buffer + 1) = (int8_t) x; - return buffer + 2; - } - if ((uint16_t)x == x) { - *bufferByte = formatInfo[FORMAT_UINT16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) x; - return buffer + 3; - } - if ((int16_t) x == x) { - *bufferByte = formatInfo[FORMAT_INT16].min; - *(int16_t *)(buffer + 1) = (int16_t) x; - return buffer + 3; - } - if ((uint32_t)x == x) { - *bufferByte = formatInfo[FORMAT_UINT32].min; - *(uint32_t *)(buffer + 1) = (uint32_t) x; - return buffer + 5; - } - if ((int32_t) x == x) { - *bufferByte = formatInfo[FORMAT_INT32].min; - *(int32_t *)(buffer + 1) = (int32_t) x; - return buffer + 5; - } - // TODO: 64 bit numbers - return buffer; -} - -uint32_t msgPackArrayLength(uint32_t elementCount) { - if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { - return 1; - } - if ((uint16_t)elementCount == elementCount) { - return 3; - } - if ((uint32_t)elementCount == elementCount) { - return 5; - } - // TODO: 64 bit numbers - return 1; -} - -void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { - uint8_t *bufferByte = buffer; - if ((elementCount & 0xF) == elementCount) { - *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; - return buffer + 1; - } - if ((uint16_t)elementCount == elementCount) { - *bufferByte = formatInfo[FORMAT_ARRAY16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; - return buffer + 3; - } - if ((uint32_t)elementCount == elementCount) { - *bufferByte = formatInfo[FORMAT_ARRAY32].min; - *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; - return buffer + 5; - } - // TODO: 64 bit numbers - return buffer; -} - -uint32_t msgPackMapLength(uint32_t elementCount) { - if (elementCount % 2) { - printf("map: bad element count %i\n", elementCount); - return 0; - } - return msgPackArrayLength(elementCount / 2); -} - -void *msgPackMapWrite(void *buffer, uint32_t elementCount) { - uint8_t *bufferByte = buffer; - if (elementCount % 2) { - printf("map: bad element count %i\n", elementCount); - return buffer; - } - elementCount >>= 1; - if ((elementCount & 0x0F) == elementCount) { - *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; - // fixmap - return buffer + 1; - } - if ((elementCount & 0xFFFF) == elementCount) { - *bufferByte = formatInfo[FORMAT_MAP16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; - return buffer + 3; - } - *bufferByte = formatInfo[FORMAT_MAP32].min; - *(uint32_t *)(buffer + 1) = elementCount; - return buffer + 5; -} - -// for reading values from a buffer: malloc is very slow, so only use it sparingly, when reutrning a value. -intmax_t msgPackReadInt(void *data) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_INTEGER) { - printf("readInt: cannot convert %s to int\n", info->name); - return 0; - } - if (format < FORMAT_INT8) { - // definietly working with a uint - if (format == FORMAT_POSITIVE_FIXINT) { - return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); - } - if (format == FORMAT_UINT8) { - return *((uint8_t *)(data + 1)); - } - if (format == FORMAT_UINT16) { - return *((uint16_t *)(data + 1)); - } - if (format == FORMAT_UINT32) { - return *((uint32_t *)(data + 1)); - } - goto fail; - } - if (format == FORMAT_NEGATIVE_FIXINT) { - return (intmax_t) (int8_t) (*buffer); - } - if (format == FORMAT_INT8) { - return (intmax_t) *((int8_t *)data); - } - if (format == FORMAT_INT16) { - return (intmax_t) *((int16_t *)(data + 1)); - } - if (format == FORMAT_INT32) { - return (intmax_t) *((int32_t *)(data + 1)); - } -fail: - // TODO: 64-bit numbers - printf("readUint: cannot read %s\n", info->name); - return 0; -} - -uint32_t msgPackReadUint(void *data) { - intmax_t asInt = msgPackReadInt(data); - if (asInt < 0) { - printf("readUint: value %i is negative\n", asInt); - return 0; - } - return asInt; -} - -char *msgPackReadStr(void *data) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_STRING) { - printf("readString: cannot convert %s to string\n", info->name); - return NULL; - } - uint8_t offset; - if (format == FORMAT_FIXSTR) { - offset = 1; - } else if (format == FORMAT_STR8) { - offset = 2; - } else if (format == FORMAT_STR16) { - offset = 3; - } else if (format == FORMAT_STR32) { - offset = 5; - } - uint32_t size = msgPackReadLength(data, info->readTypeParameter); - char *str = malloc(size + 1); - memcpy(data + offset, str, size); - str[size] = 0; - return str; -} - -uintmax_t msgPackReadArraySize(void *data, void **firstElement) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_ARRAY) { - printf("readArraySize: cannot convert %s to array\n", info->name); - return 0; - } - switch (format) { - case FORMAT_FIXARRAY: - *firstElement = data + 1; - case FORMAT_ARRAY16: - *firstElement = data + 3; - case FORMAT_ARRAY32: - *firstElement = data + 5; - } - return msgPackReadLength(data, info->readTypeParameter); -} - -uintmax_t msgPackReadMapSize(void *data, void **firstElement) { - uint8_t *buffer = data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_MAP) { - printf("readMapSize: cannot convert %s to a map\n", info->name); - return 0; - } - switch (format) { - case FORMAT_FIXMAP: - *firstElement = data + 1; break; - case FORMAT_MAP16: - *firstElement = data + 3; break; - case FORMAT_MAP32: - *firstElement = data + 5; break; - } - return msgPackReadLength(data, info->readTypeParameter); -} - -void *msgPackSeek(void *data) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - uint32_t length = msgPackReadLength(data, info->readTypeParameter); - if (info->dataType == TYPE_MAP) { - length <<= 1; - } - switch (info->readType) { - case Inline: - return data + 1; - case FixedLength: - return data + 1 + info->readTypeParameter; - case ReadLength: - return data + 1 + info->readTypeParameter + length; - case InlineLength: - return data + 1 + length; - case ElementsInline: - data++; - goto READ_ELEMENTS; - case ReadElements: - data += 1 + info->readTypeParameter; - READ_ELEMENTS: - for (uint8_t i = 0; i < length; i++) { - data = msgPackSeek(data); - } - return data; - } - // should never happen - printf("seek: cannot read %s\n", info->name); - return NULL; -} - -void *msgPackMapGetFromInt(void *data, uintmax_t searchValue) { - uint8_t *buffer = data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_MAP) { - printf("mapGetFromInt cannot convert %s to a map\n", info->name); - return 0; - } - uint8_t *element; - uint32_t pairCount = msgPackReadMapSize(data, (void *)&element); - for (uintmax_t i = 0; i < pairCount; i++) { - if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { - element = msgPackSeek(element); - element = msgPackSeek(element); - } - if (msgPackReadInt(element) == searchValue) { - return msgPackSeek(element); - } - element = msgPackSeek(element); - element = msgPackSeek(element); - } - printf("mapGetFromInt: key %i not found!\n", searchValue); - // TODO: return something sensible here / throw an actual exception - return NULL; -} - -void *msgPackMapGetFromString(void *data, char *searchValue) { - uint8_t *buffer = data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_MAP) { - printf("mapGetFromString cannot convert %s to a map\n", info->name); - return 0; - } - uint8_t *element; - uint32_t pairCount = msgPackReadMapSize(data, (void *)&element); - for (uintmax_t i = 0; i < pairCount; i++) { - if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { - element = msgPackSeek(element); - element = msgPackSeek(element); - } - char *key = msgPackReadStr(element); - bool equal = true; - for (uint32_t i = 0; searchValue[i]; i++) { - if (key[i] != searchValue[i]) { - equal = false; - break; - } - } - free(key); - if (equal) { - return msgPackSeek(element); - } - element = msgPackSeek(element); - element = msgPackSeek(element); - } - printf("mapGetFromString: key '%s' not found!\n", searchValue); - // TODO: return something sensible here / throw an actual exception - return NULL; -} - #define SAMPLE_2_ARRAY_CONTENT(X, S) \ X(INTEGER, 1) S \ X(STRING, "hi") S \ @@ -535,15 +32,8 @@ } int32_t main() { - static bool intitialized = false; - if (!intitialized) { - intitialized = true; - initialize(); - } CREATE(test, SAMPLE_3); - msgPackDump(test, 0); - + msgPackDump(test); testFunction(test); - free(test); } \ No newline at end of file diff --git a/src/hlib/flatBuffers/array.c b/src/hlib/flatBuffers/array.c new file mode 100644 index 0000000..c085b9a --- /dev/null +++ b/src/hlib/flatBuffers/array.c @@ -0,0 +1,104 @@ +#include "flatBuffers.h" + +uint32_t msgPackArrayLength(uint32_t elementCount) { + if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { + return 1; + } + if ((uint16_t)elementCount == elementCount) { + return 3; + } + if ((uint32_t)elementCount == elementCount) { + return 5; + } + // TODO: 64 bit numbers + return 1; +} + +void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if ((elementCount & 0xF) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; + return buffer + 1; + } + if ((uint16_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + if ((uint32_t)elementCount == elementCount) { + *bufferByte = formatInfo[FORMAT_ARRAY32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount) { + if (elementCount % 2) { + printf("map: bad element count %i\n", elementCount); + return 0; + } + return msgPackArrayLength(elementCount / 2); +} + +void *msgPackMapWrite(void *buffer, uint32_t elementCount) { + uint8_t *bufferByte = buffer; + if (elementCount % 2) { + // printf("map: bad element count %i\n", elementCount); + // should never occur + return buffer; + } + elementCount >>= 1; + if ((elementCount & 0x0F) == elementCount) { + *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; + // fixmap + return buffer + 1; + } + if ((elementCount & 0xFFFF) == elementCount) { + *bufferByte = formatInfo[FORMAT_MAP16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; + return buffer + 3; + } + *bufferByte = formatInfo[FORMAT_MAP32].min; + *(uint32_t *)(buffer + 1) = elementCount; + return buffer + 5; +} + +uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_ARRAY) { + printf("readArraySize: cannot convert %s to array\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXARRAY: + *firstElement = data + 1; + case FORMAT_ARRAY16: + *firstElement = data + 3; + case FORMAT_ARRAY32: + *firstElement = data + 5; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} + +uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("readMapSize: cannot convert %s to a map\n", info->name); + return 0; + } + switch (format) { + case FORMAT_FIXMAP: + *firstElement = data + 1; break; + case FORMAT_MAP16: + *firstElement = data + 3; break; + case FORMAT_MAP32: + *firstElement = data + 5; break; + } + return msgPackReadLength(allocationData, data, info->readTypeParameter); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/flatBuffers.h b/src/hlib/flatBuffers/flatBuffers.h new file mode 100644 index 0000000..0e68bd3 --- /dev/null +++ b/src/hlib/flatBuffers/flatBuffers.h @@ -0,0 +1,9 @@ +#ifndef FLAT_BUFFERS_H +#define FLAT_BUFFERS_H + +#include + +extern void *msgPackSeek(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size); + +#endif // FLAT_BUFFERS_H \ No newline at end of file diff --git a/src/hlib/flatBuffers/integer.c b/src/hlib/flatBuffers/integer.c new file mode 100644 index 0000000..19d34d1 --- /dev/null +++ b/src/hlib/flatBuffers/integer.c @@ -0,0 +1,152 @@ +#include "flatBuffers.h" + +uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { + if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { + // fixint + return 1; + } + value = ABS(value); + if ((value & 0xFF) == value) { + // int8 + return 2; + } + if ((value & 0xFFFF) == value) { + // int16 + return 3; + } + if ((value & 0xFFFFFFFF) == value) { + // int32 + return 5; + } + // int64 + return 9; +} + +void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { + if (x < 0 && type != Signed) { + // printf("integerWrite: %i is negative but type is Unsigned!\n", x); + // should never occur when using the correct macros + return buffer; + } + uint8_t *bufferByte = buffer; + if ((x & 0x7F) == x) { + *bufferByte = (uint8_t)x; + // fixint + return buffer + 1; + } + if (((~x) & 0x1F) == ~x) { + *bufferByte = (int8_t)x; + // negative fixint + return buffer + 1; + } + if ((uint8_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) x; + return buffer + 2; + } + if ((int8_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT8].min; + *(int8_t *)(buffer + 1) = (int8_t) x; + return buffer + 2; + } + if ((uint16_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) x; + return buffer + 3; + } + if ((int16_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT16].min; + *(int16_t *)(buffer + 1) = (int16_t) x; + return buffer + 3; + } + if ((uint32_t)x == x) { + *bufferByte = formatInfo[FORMAT_UINT32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) x; + return buffer + 5; + } + if ((int32_t) x == x) { + *bufferByte = formatInfo[FORMAT_INT32].min; + *(int32_t *)(buffer + 1) = (int32_t) x; + return buffer + 5; + } + // TODO: 64 bit numbers + return buffer; +} + +intmax_t msgPackReadInt(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_INTEGER) { + printf("readInt: cannot convert %s to int\n", info->name); + return 0; + } + if (format < FORMAT_INT8) { + // definietly working with a uint + if (format == FORMAT_POSITIVE_FIXINT) { + return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); + } + if (format == FORMAT_UINT8) { + return *((uint8_t *)(data + 1)); + } + if (format == FORMAT_UINT16) { + return *((uint16_t *)(data + 1)); + } + if (format == FORMAT_UINT32) { + return *((uint32_t *)(data + 1)); + } + goto fail; + } + if (format == FORMAT_NEGATIVE_FIXINT) { + return (intmax_t) (int8_t) (*buffer); + } + if (format == FORMAT_INT8) { + return (intmax_t) *((int8_t *)data); + } + if (format == FORMAT_INT16) { + return (intmax_t) *((int16_t *)(data + 1)); + } + if (format == FORMAT_INT32) { + return (intmax_t) *((int32_t *)(data + 1)); + } +fail: + // TODO: 64-bit numbers + printf("readUint: cannot read %s\n", info->name); + return 0; +} + +uintmax_t msgPackReadUint(AllocationData allocationData, void *data) { + intmax_t asInt = msgPackReadInt(allocationData, data); + if (asInt < 0) { + printf("readUint: value %i is negative\n", asInt); + return 0; + } + return asInt; +} + +void *msgPackMapGetFromInt(AllocationData allocationData, void *data, uintmax_t searchValue) { + // need a reference to allocationData for printing + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromInt cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + if (msgPackReadInt(allocationData, element) == searchValue) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromInt: key %i not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/static.c b/src/hlib/flatBuffers/static.c new file mode 100644 index 0000000..f35450e --- /dev/null +++ b/src/hlib/flatBuffers/static.c @@ -0,0 +1,24 @@ +#include +#include "flatBuffers.h" + +// see https://github.com/msgpack/msgpack/blob/master/spec.md + +#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ + { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } + +FormatInfo formatInfo[] = { + FORMATS(FORMATS_STRUCTS_X, COMMA) +}; + +Formats FirstByteToFormat[256]; + +void fillSpots(uint16_t from, uint16_t to, Formats value) { + for (uint16_t i = from; i <= to; i++) { + FirstByteToFormat[i] = value; + } +} + +#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); +void initializeFlatBuffers() { + FORMATS(FILL_SPOTS_X, NOTHING); +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/string.c b/src/hlib/flatBuffers/string.c new file mode 100644 index 0000000..9670d10 --- /dev/null +++ b/src/hlib/flatBuffers/string.c @@ -0,0 +1,102 @@ +#include "flatBuffers.h" + +uint32_t msgPackStringLength(uint32_t strlength) { + if ((strlength & 0x1F) == strlength) { + // fixstr + return 1 + strlength; + } + if ((strlength & 0xFF) == strlength) { + // str8 + return 2 + strlength; + } + if ((strlength & 0xFFFF) == strlength) { + // str16 + return 3 + strlength; + } + // str32 + return 5 + strlength; +} + +void *msgPackStringWrite(void *buffer, char *string) { + uint32_t length = strlen(string); + uint8_t *bufferByte = buffer; + if ((length & 0x1F) == length) { + *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; + buffer++; + } else if ((length & 0xFF) == length) { + *bufferByte = formatInfo[FORMAT_STR8].min; + *(uint8_t *)(buffer + 1) = (uint8_t) length; + buffer += 2; + } else if ((length & 0xFFFF) == length) { + *bufferByte = formatInfo[FORMAT_STR16].min; + *(uint16_t *)(buffer + 1) = (uint16_t) length; + buffer += 3; + } else { + *bufferByte = formatInfo[FORMAT_STR32].min; + *(uint32_t *)(buffer + 1) = (uint32_t) length; + buffer += 5; + } + memcpy(string, buffer, length); + return buffer + length; +} + + +char *msgPackReadStr(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_STRING) { + printf("readString: cannot convert %s to string\n", info->name); + return NULL; + } + uint8_t offset; + if (format == FORMAT_FIXSTR) { + offset = 1; + } else if (format == FORMAT_STR8) { + offset = 2; + } else if (format == FORMAT_STR16) { + offset = 3; + } else if (format == FORMAT_STR32) { + offset = 5; + } + uint32_t size = msgPackReadLength(allocationData, data, info->readTypeParameter); + char *str = malloc(size + 1); + memcpy(data + offset, str, size); + str[size] = 0; + return str; +} + +void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue) { + uint8_t *buffer = data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + if (info->dataType != TYPE_MAP) { + printf("mapGetFromString cannot convert %s to a map\n", info->name); + return 0; + } + uint8_t *element; + uint32_t pairCount = msgPackReadMapSize(allocationData, data, (void *)&element); + for (uintmax_t i = 0; i < pairCount; i++) { + if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + char *key = msgPackReadStr(allocationData, element); + bool equal = true; + for (uint32_t i = 0; searchValue[i]; i++) { + if (key[i] != searchValue[i]) { + equal = false; + break; + } + } + free(key); + if (equal) { + return msgPackSeek(allocationData, element); + } + element = msgPackSeek(allocationData, element); + element = msgPackSeek(allocationData, element); + } + printf("mapGetFromString: key '%s' not found!\n", searchValue); + // TODO: return something sensible here / throw an actual exception + return NULL; +} \ No newline at end of file diff --git a/src/hlib/flatBuffers/util.c b/src/hlib/flatBuffers/util.c new file mode 100644 index 0000000..d96f281 --- /dev/null +++ b/src/hlib/flatBuffers/util.c @@ -0,0 +1,130 @@ +#include "flatBuffers.h" + +uintmax_t msgPackReadLength(AllocationData allocationData, void *data, int8_t size) { + if (size < 0) { + return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); + } + switch (size) { + case 1: + return *((uint8_t *)(data + 1)); + case 2: + return *((uint16_t *)(data + 1)); + case 4: + return *((uint32_t *)(data + 1)); + // TODO: 64-bit numbers! + } + printf("cannot read length of size %i!\n", size); + return 0; +} + +void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent) { + FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; + uint32_t bytesToRead = 1; + uint32_t dataOffset = 0, dataSize = 0; + uintmax_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + switch (info->readType) { + case Inline: + break; + case InlineLength: + bytesToRead += length; + dataOffset = 1; + dataSize = length; + break; + case FixedLength: + bytesToRead += info->readTypeParameter; + dataOffset = 1; + dataSize = info->readTypeParameter; + break; + case ReadLength: + bytesToRead += info->readTypeParameter + length; + dataOffset = 1 + info->readTypeParameter; + dataSize = length; + break; + case ElementsInline: + dataOffset = 1; + break; + case ReadElements: + bytesToRead += info->readTypeParameter; + dataOffset = 1 + info->readTypeParameter; + dataSize = info->readTypeParameter; + } + char *hexData = malloc(3*bytesToRead); + for (uint32_t i = 0; i < bytesToRead; i++) { + sprintf(hexData + 3*i, "%x ", data[i]); + } + hexData[3*bytesToRead - 1] = 0; + char *indentData = malloc(indent + 1); + memset(indentData, ' ', indent); + indentData[indent] = 0; + void *next = data + bytesToRead; + uint8_t *buffer; + switch (info->dataType) { + case TYPE_NIL: + printf("%s%s: %s\n", indentData, hexData, info->name); break; + case TYPE_INTEGER: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(allocationData, data)); break; + case TYPE_BOOLEAN: + printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; + // can't even print a float yet... + case TYPE_STRING: + buffer = malloc(length + 1); + memcpy(data + dataOffset, buffer, length); + buffer[length] = 0; + printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); + free(buffer); + break; + case TYPE_ARRAY: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + case TYPE_MAP: + printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); + for (uint32_t i = 0; i < length; i++) { + next = _msgPackDump(allocationData, next, indent + 1); + next = _msgPackDump(allocationData, next, indent + 2); + } + break; + default: + // this branch should actually be impossible to reach... + printf("unknown\n"); break; + } + free(hexData); + free(indentData); + free(buffer); + return next; +} + +void *msgPackSeek(AllocationData allocationData, void *data) { + uint8_t *buffer = (uint8_t *) data; + uint8_t format = FirstByteToFormat[*buffer]; + FormatInfo *info = &formatInfo[format]; + uint32_t length = msgPackReadLength(allocationData, data, info->readTypeParameter); + if (info->dataType == TYPE_MAP) { + length <<= 1; + } + switch (info->readType) { + case Inline: + return data + 1; + case FixedLength: + return data + 1 + info->readTypeParameter; + case ReadLength: + return data + 1 + info->readTypeParameter + length; + case InlineLength: + return data + 1 + length; + case ElementsInline: + data++; + goto READ_ELEMENTS; + case ReadElements: + data += 1 + info->readTypeParameter; + READ_ELEMENTS: + for (uint8_t i = 0; i < length; i++) { + data = msgPackSeek(allocationData, data); + } + return data; + } + // should never happen + printf("seek: cannot read %s\n", info->name); + return NULL; +} \ No newline at end of file diff --git a/src/include/buffers.h b/src/include/buffers.h new file mode 100644 index 0000000..b286d20 --- /dev/null +++ b/src/include/buffers.h @@ -0,0 +1,258 @@ +#ifndef HLIB_BUFFERS_H +#define HLIB_BUFFERS_H + +#include +#include "../hlib/malloc.h" + +#define COMMA , + +#define EMPTY(...) +#define DEFER(...) __VA_ARGS__ EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() + +#define EXPAND3(...) __VA_ARGS__ +#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) +#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) +#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) + +#define STRING_Length(x) msgPackStringLength(strlen(x)) + +#define ONE(...) 1 + +#define ARRAY_Length_id() ARRAY_Length +#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) +#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) +#define INTEGER_Length_id() INTEGER_Length +#define STRING_Length_id() STRING_Length +#define MAP_Length_id() MAP_Length + +#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) +#define MAP_Length(contents) msgPackMapLength(allocationData, contents(ONE, +)) + contents(LENGTH, +) + +#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) + +#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); +#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) +#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); + +#define INTEGER_Write_id() INTEGER_Write +#define ARRAY_Write_id() ARRAY_Write +#define STRING_Write_id() STRING_Write +#define MAP_Write_id() MAP_Write + +#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) +#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) + +#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) + +#define CONTENTS contents (LENGTH, +) + +#define CREATE(name, definition) \ + uint32_t name##Length = EXPAND(definition(LENGTH)); \ + void *name = malloc(name##Length); \ + { \ + void *buffer = name; \ + EXPAND(definition(WRITE)) \ + } + +// helper macros to make accessing data in a buffer easier +// all of these check if the type is correct and throw an error if not +#define _AS_INT(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + msgPackReadInt(allocationData, data); \ + }) + +#define _AS_UINT(data, catchError, catchNegative) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ + intmax_t asInt = msgPackReadInt(allocationData, data); \ + if (asInt < 0) catchNegative \ + (uint32_t) asInt; \ + }) + +#define _AS_STRING(data, catchError) \ + ({ \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_STRING) catchError \ + msgPackReadStr(allocationData, data); \ + }) + +#define AS_INT(data, retval, ...) \ + _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) + +#define AS_UINT(data, retval, ...) \ + _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) + +#define AS_STRING(data, retval, ...) \ + _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) + +#define ARRAY_LOOP(data, retval, elementName, action) \ + { \ + uint8_t *buffer = (uint8_t *) data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_ARRAY) { \ + printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ + return retval; \ + } \ + void *elementName; \ + uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ + for (uint32_t i = 0; i < maxElement; i++) { \ + (action); \ + elementName = msgPackSeek(elementName); \ + } \ + } + +#define GET_FROM_INT(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromInt(allocationData, data, value); \ + }) + +#define GET_FROM_STRING(data, value, retval) \ + ({ \ + uint8_t *buffer = (uint8_t *)data; \ + uint8_t type = FirstByteToFormat[*buffer]; \ + if (formatInfo[type].dataType != TYPE_MAP) { \ + printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ + return retval; \ + } \ + msgPackMapGetFromString(allocationData, data, value); \ + }) + + +typedef enum ReadTypes { + Inline, + InlineLength, + FixedLength, + ReadLength, + ElementsInline, + ReadElements, +} ReadTypes; + +typedef enum IntegerType { + Signed, + Unsigned +} IntegerType; + +#define DATA_TYPES(X, S) \ + X(INTEGER) S \ + X(NIL) S \ + X(BOOLEAN) S \ + X(FLOAT) S \ + X(STRING) S \ + X(BINARY) S \ + X(ARRAY) S \ + X(MAP) S \ + X(EXTENSION) S \ + X(UNUSED) + +#define FORMATS(X, S) \ + X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ + X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ + X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ + X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ + X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ + X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ + X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ + X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ + X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ + X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ + X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ + X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ + X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ + X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ + X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ + X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ + X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ + X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ + X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ + X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ + X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ + X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ + X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ + X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ + X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ + X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ + X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ + X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ + X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ + X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ + X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ + X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ + X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ + X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ + X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ + X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) + +// define enums +#define ENUM_X(name) TYPE_##name +typedef enum DataTypes { + DATA_TYPES(ENUM_X, COMMA) +} DataTypes; + +#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name +typedef enum Formats { + FORMATS(ENUM_FORMATS_X, COMMA) +} Formats; + +typedef struct FormatInfo { + char *name; + DataTypes dataType; + ReadTypes readType; + uint32_t readTypeParameter; + uint8_t min, max; +} FormatInfo; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +typedef char * STRING; +typedef intmax_t INT; + +extern Formats FirstByteToFormat[256]; +extern FormatInfo formatInfo[]; + +#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); +#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) + +// query functions +extern void *msgPackMapGetFromString(AllocationData allocationData, void *data, char *searchValue); +extern void *msgPackMapGEtFromInt(AllocationData allocationData, void *data, intmax_t searchValue); + +// length functions +extern uint32_t msgPackMapLength(AllocationData allocationData, uint32_t elementCount); +extern uint32_t msgPackArrayLength(uint32_t elementCount); +extern uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType); +extern uint32_t msgPackStringLength(uint32_t strlength); + +// write functions +extern void *msgPackArrayWrite(void *buffer, uint32_t elementCount); +extern void *msgPackMapWrite(void *buffer, uint32_t elementCount); +extern void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type); +extern void *msgPackStringWrite(void *buffer, char *string); + +// read functions +extern uintmax_t msgPackReadArraySize(AllocationData allocationData, void *data, void **firstElement); +extern uintmax_t msgPackReadMapSize(AllocationData allocationData, void *data, void **firstElement); +extern intmax_t msgPackReadInt(AllocationData allocationData, void *data); +extern uintmax_t msgPackReadUint(AllocationData allocationData, void *data); +extern char *msgPackReadStr(AllocationData allocationData, void *data); + +// util / debugging functions +extern void *_msgPackDump(AllocationData allocationData, uint8_t *data, uint32_t indent); +#define msgPackDump(data) _msgPackDump(allocationData, data, 0) + +extern void initializeFlatBuffers(); + +#endif \ No newline at end of file diff --git a/src/include/hlib.h b/src/include/hlib.h index 4ba8e13..d505a69 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -10,6 +10,7 @@ } ListElement; #include "../hlib/malloc.h" +#include "buffers.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) @@ -109,4 +110,9 @@ extern bool checkFocus(); +#define COMMA , +#define NOTHING +#define SEMICOLON ; +#define ABS(x) (x >= 0 ? x : -x) + #endif diff --git a/src/userland/buffersTests/include/buffers.h b/src/userland/buffersTests/include/buffers.h deleted file mode 100644 index afb0a0e..0000000 --- a/src/userland/buffersTests/include/buffers.h +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef BUFFERS_H -#define BUFFERS_H - -#include - -#define COMMA , -#define SEMICOLON ; -#define NOTHING - -typedef enum ReadTypes { - Inline, - InlineLength, - FixedLength, - ReadLength, - ElementsInline, - ReadElements, -} ReadTypes; - -typedef enum IntegerType { - Signed, - Unsigned -} IntegerType; - -#define DATA_TYPES(X, S) \ - X(INTEGER) S \ - X(NIL) S \ - X(BOOLEAN) S \ - X(FLOAT) S \ - X(STRING) S \ - X(BINARY) S \ - X(ARRAY) S \ - X(MAP) S \ - X(EXTENSION) S \ - X(UNUSED) - -#define FORMATS(X, S) \ - X(POSITIVE_FIXINT, INTEGER, 0x00, 0x7F, Inline, -7) S \ - X(FIXMAP, MAP, 0x80, 0x8F, ElementsInline, -4) S \ - X(FIXARRAY, ARRAY, 0x90, 0x9F, ElementsInline, -4) S \ - X(FIXSTR, STRING, 0xA0, 0xBF, InlineLength, -5) S \ - X(NIL, NIL, 0xC0, 0xC0, Inline, 0x00) S \ - X(UNUSED, UNUSED, 0xC1, 0xC1, Inline, 0x00) S \ - X(FIXBOOL, BOOLEAN, 0xC2, 0xC3, Inline, -1) S \ - X(BIN8, BINARY, 0xC4, 0xC4, ReadLength, 1) S \ - X(BIN16, BINARY, 0xC5, 0xC5, ReadLength, 2) S \ - X(BIN32, BINARY, 0xc6, 0xC6, ReadLength, 4) S \ - X(EXT8, EXTENSION, 0xC7, 0xC7, ReadLength, 1) S \ - X(EXT16, EXTENSION, 0xC8, 0xC8, ReadLength, 2) S \ - X(EXT32, EXTENSION, 0xC9, 0xC9, ReadLength, 4) S \ - X(FLOAT32, FLOAT, 0xCA, 0xCA, FixedLength, 4) S \ - X(FLOAT64, FLOAT, 0xCB, 0xCB, FixedLength, 8) S \ - X(UINT8, INTEGER, 0xCC, 0xCC, FixedLength, 1) S \ - X(UINT16, INTEGER, 0xCD, 0xCD, FixedLength, 2) S \ - X(UINT32, INTEGER, 0xCE, 0xCE, FixedLength, 4) S \ - X(UINT64, INTEGER, 0xCF, 0xCF, FixedLength, 8) S \ - X(INT8, INTEGER, 0xD0, 0xD0, FixedLength, 1) S \ - X(INT16, INTEGER, 0xD1, 0xD1, FixedLength, 2) S \ - X(INT32, INTEGER, 0xD2, 0xD2, FixedLength, 4) S \ - X(INT64, INTEGER, 0xD3, 0xD3, FixedLength, 8) S \ - X(FIXEXT1, EXTENSION, 0xD4, 0xD4, FixedLength, 1) S \ - X(FIXEXT2, EXTENSION, 0xD5, 0xD5, FixedLength, 2) S \ - X(FIXEXT4, EXTENSION, 0xD6, 0xD6, FixedLength, 4) S \ - X(FIXEXT8, EXTENSION, 0xD7, 0xD7, FixedLength, 8) S \ - X(FIXEXT16, EXTENSION, 0xD8, 0xD8, FixedLength, 16) S \ - X(STR8, STRING, 0xD9, 0xD9, ReadLength, 1) S \ - X(STR16, STRING, 0xDA, 0xDA, ReadLength, 2) S \ - X(STR32, STRING, 0xDB, 0xDB, ReadLength, 4) S \ - X(ARRAY16, ARRAY, 0xDC, 0xDC, ReadElements, 2) S \ - X(ARRAY32, ARRAY, 0xDD, 0xDD, ReadElements, 4) S \ - X(MAP16, MAP, 0xDE, 0xDE, ReadElements, 2) S \ - X(MAP32, MAP, 0xDF, 0xDF, ReadElements, 4) S \ - X(NEGATIVE_FIXINT, INTEGER, 0xE0, 0xFF, Inline, -5) - -// define enums -#define ENUM_X(name) TYPE_##name -typedef enum DataTypes { - DATA_TYPES(ENUM_X, COMMA) -} DataTypes; - -#define ENUM_FORMATS_X(name, dataType, min, max, readType, readTypeParameter) FORMAT_##name -typedef enum Formats { - FORMATS(ENUM_FORMATS_X, COMMA) -} Formats; - -typedef struct FormatInfo { - char *name; - DataTypes dataType; - ReadTypes readType; - uint32_t readTypeParameter; - uint8_t min, max; -} FormatInfo; - -extern Formats FirstByteToFormat[256]; -extern FormatInfo formatInfo[]; - -// macros for initializing a buffer -#define ABS(x) (x >= 0 ? x : -x) -#define EMPTY(...) -#define DEFER(...) __VA_ARGS__ EMPTY() -#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() - -#define EXPAND3(...) __VA_ARGS__ -#define EXPAND2(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) -#define EXPAND1(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) -#define EXPAND(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) - -#define STRING_Length(x) msgPackStringLength(strlen(x)) - -#define ONE(...) 1 - -#define ARRAY_Length_id() ARRAY_Length -#define _INTEGER_LENGTH(x, type, ...) msgPackIntegerLength(x, type) -#define INTEGER_Length(x, ...) _INTEGER_LENGTH(x, ##__VA_ARGS__ , Unsigned) -#define INTEGER_Length_id() INTEGER_Length -#define STRING_Length_id() STRING_Length -#define MAP_Length_id() MAP_Length - -#define ARRAY_Length(contents) msgPackArrayLength(contents(ONE, +)) + contents(LENGTH, +) -#define MAP_Length(contents) msgPackMapLength(contents(ONE, +)) + contents(LENGTH, +) - -#define LENGTH(type, ...) DEFER(type##_Length_id)()(__VA_ARGS__) - -#define _INTEGER_WRITE(x, type, ...) buffer = msgPackIntegerWrite(buffer, x, type); -#define INTEGER_Write(x, ...) _INTEGER_WRITE(x, ##__VA_ARGS__ , Unsigned) -#define STRING_Write(x) buffer = msgPackStringWrite(buffer, x); - -#define INTEGER_Write_id() INTEGER_Write -#define ARRAY_Write_id() ARRAY_Write -#define STRING_Write_id() STRING_Write -#define MAP_Write_id() MAP_Write - -#define ARRAY_Write(contents) buffer = msgPackArrayWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) -#define MAP_Write(contents) buffer = msgPackMapWrite(buffer, contents(ONE, +)); contents(WRITE, NOTHING) - -#define WRITE(type, ...) DEFER(type##_Write_id)()(__VA_ARGS__) - -#define CONTENTS contents (LENGTH, +) - -extern uint32_t msgPackReadUint(void *data); -extern intmax_t msgPackReadInt(void *data); - -#define CREATE(name, definition) \ - uint32_t name##Length = EXPAND(definition(LENGTH)); \ - void *name = malloc(name##Length); \ - { \ - void *buffer = name; \ - EXPAND(definition(WRITE)) \ - } - -// helper macros to make accessing data in a buffer easier -// all of these check if the type is correct and throw an error if not -#define _AS_INT(data, catchError) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ - msgPackReadInt(data); \ - }) - -#define _AS_UINT(data, catchError, catchNegative) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_INTEGER) catchError \ - intmax_t asInt = msgPackReadInt(data); \ - if (asInt < 0) catchNegative \ - (uint32_t) asInt; \ - }) - -#define _AS_STRING(data, catchError) \ - ({ \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_STRING) catchError \ - msgPackReadStr(data); \ - }) - -#define AS_INT(data, retval, ...) \ - _AS_INT(data, ##__VA_ARGS__, { printf("AS_INT: cannot convert '" #data "' to an integer\n"); return retval; }) - -#define AS_UINT(data, retval, ...) \ - _AS_UINT(data, ##__VA_ARGS__, { printf("AS_UINT: cannot convert '" #data "' to an integer\n"); return retval; }, { printf("AS_UINT: '" #data "' is negative!\n"); asInt = 0; }) - -#define AS_STRING(data, retval, ...) \ - _AS_STRING(data, ##__VA_ARGS__, { printf("AS_STRING: cannot convert '" #data "' to a string\n"); return retval; }) - -#define ARRAY_LOOP(data, retval, elementName, action) \ - { \ - uint8_t *buffer = (uint8_t *) data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_ARRAY) { \ - printf("ARRAY_LOOP: cannot convert '" #data "' to an array\n"); \ - return retval; \ - } \ - void *elementName; \ - uint32_t maxElement = msgPackReadArraySize(data, &elementName); \ - for (uint32_t i = 0; i < maxElement; i++) { \ - (action); \ - elementName = msgPackSeek(elementName); \ - } \ - } - -#define GET_FROM_INT(data, value, retval) \ - ({ \ - uint8_t *buffer = (uint8_t *)data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_MAP) { \ - printf("GET_FROM_INT: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ - return retval; \ - } \ - msgPackMapGetFromInt(data, value); \ - }) - -#define GET_FROM_STRING(data, value, retval) \ - ({ \ - uint8_t *buffer = (uint8_t *)data; \ - uint8_t type = FirstByteToFormat[*buffer]; \ - if (formatInfo[type].dataType != TYPE_MAP) { \ - printf("GET_FROM_STRING: cannot convert '" #data "' to a map, got %s\n", formatInfo[type].name); \ - return retval; \ - } \ - msgPackMapGetFromString(data, value); \ - }) - -typedef char * STRING; -typedef intmax_t INT; - -#define _GET(type, name, retval, ...) type name = AS_##type(GET_FROM_STRING(data, #name, retval), retval); -#define GET(type, name, ...) _GET(type, name, ##__VA_ARGS__, -1) - -#endif // BUFFERS_H \ No newline at end of file diff --git a/src/userland/buffersTests/main.c b/src/userland/buffersTests/main.c index 57e8153..12cdef0 100644 --- a/src/userland/buffersTests/main.c +++ b/src/userland/buffersTests/main.c @@ -1,509 +1,6 @@ #include #include -// see https://github.com/msgpack/msgpack/blob/master/spec.md - -#define FORMATS_STRUCTS_X(_name, _dataType, _min, _max, _readType, _readTypeParameter) \ - { .name = #_name, .dataType = TYPE_##_dataType, .readType = _readType, .readTypeParameter = _readTypeParameter, .min = _min, .max = _max } - -FormatInfo formatInfo[] = { - FORMATS(FORMATS_STRUCTS_X, COMMA) -}; - -Formats FirstByteToFormat[256]; - -uintmax_t msgPackReadLength(void *data, int8_t size) { - if (size < 0) { - return (*(uint8_t *)(data)) & ((1 << (-size)) - 1); - } - switch (size) { - case 1: - return *((uint8_t *)(data + 1)); - case 2: - return *((uint16_t *)(data + 1)); - case 4: - return *((uint32_t *)(data + 1)); - // TODO: 64-bit numbers! - } - printf("cannot read length of size %i!\n", size); - return 0; -} - -void *msgPackDump(uint8_t *data, uint32_t indent) { - FormatInfo *info = &formatInfo[FirstByteToFormat[data[0]]]; - uint32_t bytesToRead = 1; - uint32_t dataOffset = 0, dataSize = 0; - uintmax_t length = msgPackReadLength(data, info->readTypeParameter); - switch (info->readType) { - case Inline: - break; - case InlineLength: - bytesToRead += length; - dataOffset = 1; - dataSize = length; - break; - case FixedLength: - bytesToRead += info->readTypeParameter; - dataOffset = 1; - dataSize = info->readTypeParameter; - break; - case ReadLength: - bytesToRead += info->readTypeParameter + length; - dataOffset = 1 + info->readTypeParameter; - dataSize = length; - break; - case ElementsInline: - dataOffset = 1; - break; - case ReadElements: - bytesToRead += info->readTypeParameter; - dataOffset = 1 + info->readTypeParameter; - dataSize = info->readTypeParameter; - } - char *hexData = malloc(3*bytesToRead); - for (uint32_t i = 0; i < bytesToRead; i++) { - sprintf(hexData + 3*i, "%x ", data[i]); - } - hexData[3*bytesToRead - 1] = 0; - char *indentData = malloc(indent + 1); - memset(indentData, ' ', indent); - indentData[indent] = 0; - void *next = data + bytesToRead; - uint8_t *buffer; - switch (info->dataType) { - case TYPE_NIL: - printf("%s%s: %s\n", indentData, hexData, info->name); break; - case TYPE_INTEGER: - printf("%s%s: %s(%i)\n", indentData, hexData, info->name, msgPackReadInt(data)); break; - case TYPE_BOOLEAN: - printf("%s%s: %s(%s)\n", indentData, hexData, info->name, length ? "true" : "false"); break; - // can't even print a float yet... - case TYPE_STRING: - buffer = malloc(length + 1); - memcpy(data + dataOffset, buffer, length); - buffer[length] = 0; - printf("%s%s: %s(\"%s\")\n", indentData, hexData, info->name, buffer); - free(buffer); - break; - case TYPE_ARRAY: - printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); - for (uint32_t i = 0; i < length; i++) { - next = msgPackDump(next, indent + 2); - } - break; - case TYPE_MAP: - printf("%s%s: %s(%i)\n", indentData, hexData, info->name, length); - for (uint32_t i = 0; i < length; i++) { - next = msgPackDump(next, indent + 1); - next = msgPackDump(next, indent + 2); - } - break; - default: - // this branch should actually be impossible to reach... - printf("unknown\n"); break; - } - free(hexData); - free(indentData); - free(buffer); - return next; -} - -void fillSpots(uint16_t from, uint16_t to, Formats value) { - for (uint16_t i = from; i <= to; i++) { - FirstByteToFormat[i] = value; - } -} - -#define FILL_SPOTS_X(name, dataType, min, max, readType, readTypeParameter) fillSpots(min, max, FORMAT_##name); -void initialize() { - FORMATS(FILL_SPOTS_X, NOTHING); -} - -uint32_t msgPackStringLength(uint32_t strlength) { - if ((strlength & 0x1F) == strlength) { - // fixstr - return 1 + strlength; - } - if ((strlength & 0xFF) == strlength) { - // str8 - return 2 + strlength; - } - if ((strlength & 0xFFFF) == strlength) { - // str16 - return 3 + strlength; - } - // str32 - return 5 + strlength; -} - -void *msgPackStringWrite(void *buffer, char *string) { - uint32_t length = strlen(string); - uint8_t *bufferByte = buffer; - if ((length & 0x1F) == length) { - *bufferByte = formatInfo[FORMAT_FIXSTR].min + length; - buffer++; - } else if ((length & 0xFF) == length) { - *bufferByte = formatInfo[FORMAT_STR8].min; - *(uint8_t *)(buffer + 1) = (uint8_t) length; - buffer += 2; - } else if ((length & 0xFFFF) == length) { - *bufferByte = formatInfo[FORMAT_STR16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) length; - buffer += 3; - } else { - *bufferByte = formatInfo[FORMAT_STR32].min; - *(uint32_t *)(buffer + 1) = (uint32_t) length; - buffer += 5; - } - memcpy(string, buffer, length); - return buffer + length; -} - -uint32_t msgPackIntegerLength(int32_t value, IntegerType integerType) { - if ((value & 0x7F) == value || ((~value) & 0x1F) == ~value) { - // fixint - return 1; - } - value = ABS(value); - if ((value & 0xFF) == value) { - // int8 - return 2; - } - if ((value & 0xFFFF) == value) { - // int16 - return 3; - } - if ((value & 0xFFFFFFFF) == value) { - // int32 - return 5; - } - // int64 - return 9; -} - -void *msgPackIntegerWrite(void *buffer, int32_t x, IntegerType type) { - if (x < 0 && type != Signed) { - printf("integerWrite: %i is negative but type is Unsigned!\n", x); - return buffer; - } - uint8_t *bufferByte = buffer; - if ((x & 0x7F) == x) { - *bufferByte = (uint8_t)x; - // fixint - return buffer + 1; - } - if (((~x) & 0x1F) == ~x) { - *bufferByte = (int8_t)x; - // negative fixint - return buffer + 1; - } - if ((uint8_t)x == x) { - *bufferByte = formatInfo[FORMAT_UINT8].min; - *(uint8_t *)(buffer + 1) = (uint8_t) x; - return buffer + 2; - } - if ((int8_t) x == x) { - *bufferByte = formatInfo[FORMAT_INT8].min; - *(int8_t *)(buffer + 1) = (int8_t) x; - return buffer + 2; - } - if ((uint16_t)x == x) { - *bufferByte = formatInfo[FORMAT_UINT16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) x; - return buffer + 3; - } - if ((int16_t) x == x) { - *bufferByte = formatInfo[FORMAT_INT16].min; - *(int16_t *)(buffer + 1) = (int16_t) x; - return buffer + 3; - } - if ((uint32_t)x == x) { - *bufferByte = formatInfo[FORMAT_UINT32].min; - *(uint32_t *)(buffer + 1) = (uint32_t) x; - return buffer + 5; - } - if ((int32_t) x == x) { - *bufferByte = formatInfo[FORMAT_INT32].min; - *(int32_t *)(buffer + 1) = (int32_t) x; - return buffer + 5; - } - // TODO: 64 bit numbers - return buffer; -} - -uint32_t msgPackArrayLength(uint32_t elementCount) { - if ((elementCount & formatInfo[FORMAT_FIXARRAY].readTypeParameter) == elementCount) { - return 1; - } - if ((uint16_t)elementCount == elementCount) { - return 3; - } - if ((uint32_t)elementCount == elementCount) { - return 5; - } - // TODO: 64 bit numbers - return 1; -} - -void *msgPackArrayWrite(void *buffer, uint32_t elementCount) { - uint8_t *bufferByte = buffer; - if ((elementCount & 0xF) == elementCount) { - *bufferByte = formatInfo[FORMAT_FIXARRAY].min + elementCount; - return buffer + 1; - } - if ((uint16_t)elementCount == elementCount) { - *bufferByte = formatInfo[FORMAT_ARRAY16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; - return buffer + 3; - } - if ((uint32_t)elementCount == elementCount) { - *bufferByte = formatInfo[FORMAT_ARRAY32].min; - *(uint32_t *)(buffer + 1) = (uint32_t) elementCount; - return buffer + 5; - } - // TODO: 64 bit numbers - return buffer; -} - -uint32_t msgPackMapLength(uint32_t elementCount) { - if (elementCount % 2) { - printf("map: bad element count %i\n", elementCount); - return 0; - } - return msgPackArrayLength(elementCount / 2); -} - -void *msgPackMapWrite(void *buffer, uint32_t elementCount) { - uint8_t *bufferByte = buffer; - if (elementCount % 2) { - printf("map: bad element count %i\n", elementCount); - return buffer; - } - elementCount >>= 1; - if ((elementCount & 0x0F) == elementCount) { - *bufferByte = formatInfo[FORMAT_FIXMAP].min + elementCount; - // fixmap - return buffer + 1; - } - if ((elementCount & 0xFFFF) == elementCount) { - *bufferByte = formatInfo[FORMAT_MAP16].min; - *(uint16_t *)(buffer + 1) = (uint16_t) elementCount; - return buffer + 3; - } - *bufferByte = formatInfo[FORMAT_MAP32].min; - *(uint32_t *)(buffer + 1) = elementCount; - return buffer + 5; -} - -// for reading values from a buffer: malloc is very slow, so only use it sparingly, when reutrning a value. -intmax_t msgPackReadInt(void *data) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_INTEGER) { - printf("readInt: cannot convert %s to int\n", info->name); - return 0; - } - if (format < FORMAT_INT8) { - // definietly working with a uint - if (format == FORMAT_POSITIVE_FIXINT) { - return *((uint8_t *)data) & ((1 << (-info->readTypeParameter)) - 1); - } - if (format == FORMAT_UINT8) { - return *((uint8_t *)(data + 1)); - } - if (format == FORMAT_UINT16) { - return *((uint16_t *)(data + 1)); - } - if (format == FORMAT_UINT32) { - return *((uint32_t *)(data + 1)); - } - goto fail; - } - if (format == FORMAT_NEGATIVE_FIXINT) { - return (intmax_t) (int8_t) (*buffer); - } - if (format == FORMAT_INT8) { - return (intmax_t) *((int8_t *)data); - } - if (format == FORMAT_INT16) { - return (intmax_t) *((int16_t *)(data + 1)); - } - if (format == FORMAT_INT32) { - return (intmax_t) *((int32_t *)(data + 1)); - } -fail: - // TODO: 64-bit numbers - printf("readUint: cannot read %s\n", info->name); - return 0; -} - -uint32_t msgPackReadUint(void *data) { - intmax_t asInt = msgPackReadInt(data); - if (asInt < 0) { - printf("readUint: value %i is negative\n", asInt); - return 0; - } - return asInt; -} - -char *msgPackReadStr(void *data) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_STRING) { - printf("readString: cannot convert %s to string\n", info->name); - return NULL; - } - uint8_t offset; - if (format == FORMAT_FIXSTR) { - offset = 1; - } else if (format == FORMAT_STR8) { - offset = 2; - } else if (format == FORMAT_STR16) { - offset = 3; - } else if (format == FORMAT_STR32) { - offset = 5; - } - uint32_t size = msgPackReadLength(data, info->readTypeParameter); - char *str = malloc(size + 1); - memcpy(data + offset, str, size); - str[size] = 0; - return str; -} - -uintmax_t msgPackReadArraySize(void *data, void **firstElement) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_ARRAY) { - printf("readArraySize: cannot convert %s to array\n", info->name); - return 0; - } - switch (format) { - case FORMAT_FIXARRAY: - *firstElement = data + 1; - case FORMAT_ARRAY16: - *firstElement = data + 3; - case FORMAT_ARRAY32: - *firstElement = data + 5; - } - return msgPackReadLength(data, info->readTypeParameter); -} - -uintmax_t msgPackReadMapSize(void *data, void **firstElement) { - uint8_t *buffer = data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_MAP) { - printf("readMapSize: cannot convert %s to a map\n", info->name); - return 0; - } - switch (format) { - case FORMAT_FIXMAP: - *firstElement = data + 1; break; - case FORMAT_MAP16: - *firstElement = data + 3; break; - case FORMAT_MAP32: - *firstElement = data + 5; break; - } - return msgPackReadLength(data, info->readTypeParameter); -} - -void *msgPackSeek(void *data) { - uint8_t *buffer = (uint8_t *) data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - uint32_t length = msgPackReadLength(data, info->readTypeParameter); - if (info->dataType == TYPE_MAP) { - length <<= 1; - } - switch (info->readType) { - case Inline: - return data + 1; - case FixedLength: - return data + 1 + info->readTypeParameter; - case ReadLength: - return data + 1 + info->readTypeParameter + length; - case InlineLength: - return data + 1 + length; - case ElementsInline: - data++; - goto READ_ELEMENTS; - case ReadElements: - data += 1 + info->readTypeParameter; - READ_ELEMENTS: - for (uint8_t i = 0; i < length; i++) { - data = msgPackSeek(data); - } - return data; - } - // should never happen - printf("seek: cannot read %s\n", info->name); - return NULL; -} - -void *msgPackMapGetFromInt(void *data, uintmax_t searchValue) { - uint8_t *buffer = data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_MAP) { - printf("mapGetFromInt cannot convert %s to a map\n", info->name); - return 0; - } - uint8_t *element; - uint32_t pairCount = msgPackReadMapSize(data, (void *)&element); - for (uintmax_t i = 0; i < pairCount; i++) { - if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_INTEGER) { - element = msgPackSeek(element); - element = msgPackSeek(element); - } - if (msgPackReadInt(element) == searchValue) { - return msgPackSeek(element); - } - element = msgPackSeek(element); - element = msgPackSeek(element); - } - printf("mapGetFromInt: key %i not found!\n", searchValue); - // TODO: return something sensible here / throw an actual exception - return NULL; -} - -void *msgPackMapGetFromString(void *data, char *searchValue) { - uint8_t *buffer = data; - uint8_t format = FirstByteToFormat[*buffer]; - FormatInfo *info = &formatInfo[format]; - if (info->dataType != TYPE_MAP) { - printf("mapGetFromString cannot convert %s to a map\n", info->name); - return 0; - } - uint8_t *element; - uint32_t pairCount = msgPackReadMapSize(data, (void *)&element); - for (uintmax_t i = 0; i < pairCount; i++) { - if (formatInfo[FirstByteToFormat[*element]].dataType != TYPE_STRING) { - element = msgPackSeek(element); - element = msgPackSeek(element); - } - char *key = msgPackReadStr(element); - bool equal = true; - for (uint32_t i = 0; searchValue[i]; i++) { - if (key[i] != searchValue[i]) { - equal = false; - break; - } - } - free(key); - if (equal) { - return msgPackSeek(element); - } - element = msgPackSeek(element); - element = msgPackSeek(element); - } - printf("mapGetFromString: key '%s' not found!\n", searchValue); - // TODO: return something sensible here / throw an actual exception - return NULL; -} - #define SAMPLE_2_ARRAY_CONTENT(X, S) \ X(INTEGER, 1) S \ X(STRING, "hi") S \ @@ -535,15 +32,8 @@ } int32_t main() { - static bool intitialized = false; - if (!intitialized) { - intitialized = true; - initialize(); - } CREATE(test, SAMPLE_3); - msgPackDump(test, 0); - + msgPackDump(test); testFunction(test); - free(test); } \ No newline at end of file diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index f48495c..3425077 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -2,6 +2,7 @@ #include int32_t main() { + initializeFlatBuffers(); loadFromInitrd("ioManager"); printf("HONEY-OS - made by Lukas Eisenhauer\n"); printf("finished loading all the essential modules\n");