From 859bc4f32fff8cf821b9620d869aa2d3c61f04e2 Mon Sep 17 00:00:00 2001 From: Johnny Lee Date: Tue, 3 Mar 2015 09:20:15 -0600 Subject: [PATCH 1/6] #171 Implemented some serialization for declaration/definition of objects --- interface/Makefile | 3 + interface/json/include/json.h | 2 +- interface/sqlite/include/ser_sqlite.h | 18 ++ interface/sqlite/makefile | 8 + interface/sqlite/src/ser_sqlite_declare.c | 120 ++++++++++ interface/sqlite/src/ser_sqlite_define.c | 251 +++++++++++++++++++++ interface/sqlite/src/ser_sqlite_update.c | 253 ++++++++++++++++++++++ 7 files changed, 654 insertions(+), 1 deletion(-) create mode 100644 interface/sqlite/include/ser_sqlite.h create mode 100644 interface/sqlite/makefile create mode 100644 interface/sqlite/src/ser_sqlite_declare.c create mode 100644 interface/sqlite/src/ser_sqlite_define.c create mode 100644 interface/sqlite/src/ser_sqlite_update.c diff --git a/interface/Makefile b/interface/Makefile index 3c4937c5..64bca0a8 100644 --- a/interface/Makefile +++ b/interface/Makefile @@ -6,13 +6,16 @@ all: @make -C xml @make -C json @make -C fast + @make -C sqlite clean: @make clean -C xml @make clean -C json @make clean -C fast + @make clean -C sqlite gcov: @make gcov -C xml @make gcov -C json @make gcov -C fast + @make gcov -C sqlite diff --git a/interface/json/include/json.h b/interface/json/include/json.h index 881c0e52..7f6309b3 100644 --- a/interface/json/include/json.h +++ b/interface/json/include/json.h @@ -3,7 +3,7 @@ #include "cortex.h" #include "cx_serializer.h" -/* String serializer data */ +/* JSON serializer data */ typedef struct cx_json_ser_t { /* Public */ cx_string buffer; diff --git a/interface/sqlite/include/ser_sqlite.h b/interface/sqlite/include/ser_sqlite.h new file mode 100644 index 00000000..68043b4f --- /dev/null +++ b/interface/sqlite/include/ser_sqlite.h @@ -0,0 +1,18 @@ +#include + +#include "cortex.h" +#include "cx_serializer.h" + +typedef struct cx_sqlite_ser_t { + /**/ + cx_string buffer; + cx_string ptr; + /**/ + unsigned int length; + unsigned int maxlength; + unsigned int itemCount; +} cx_sqlite_ser_t; + +struct cx_serializer_s cx_sqlite_declare_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); +struct cx_serializer_s cx_sqlite_define_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); +struct cx_serializer_s cx_sqlite_update_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); diff --git a/interface/sqlite/makefile b/interface/sqlite/makefile new file mode 100644 index 00000000..7e0b6ba3 --- /dev/null +++ b/interface/sqlite/makefile @@ -0,0 +1,8 @@ + +TARGET = sqliteserializer + +INCLUDE = $(CORTEX_HOME)/dev/include + +LIBS = lang cortexdev + +include $(CORTEX_HOME)/build/component.makefile diff --git a/interface/sqlite/src/ser_sqlite_declare.c b/interface/sqlite/src/ser_sqlite_declare.c new file mode 100644 index 00000000..6ce2510e --- /dev/null +++ b/interface/sqlite/src/ser_sqlite_declare.c @@ -0,0 +1,120 @@ + +#include +#include +#include + +#include "cx_generator.h" +#include "cx_serializer.h" +#include "cx_string.h" +#include "cortex.h" +#include "ser_sqlite.h" + +/* + * https://www.sqlite.org/lang_update.html + */ + +/* agreed not to change anything except the first argument of the signature */ +static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { + if (!data->ptr) { + data->ptr = data->buffer; + } + if (!data->ptr) { + data->buffer = strdup(str); + data->ptr = data->buffer; + } else { + cx_uint32 length, bufferLength; + + if (!data->length) { + data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); + data->ptr = data->buffer; + } + + length = strlen(str); + bufferLength = strlen(data->buffer); + + if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { + strncat(data->ptr, str, data->maxlength - bufferLength); + goto maxreached; + } else { + strcat(data->ptr, str); + } + } + + return TRUE; +maxreached: + return FALSE; +} + +/* agreed not to change anything except the first argument of the signature */ +/* Append string to serializer-result */ +static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { + char alloc[1024]; + char *buff = alloc; + va_list args; + cx_uint32 memRequired; + cx_uint32 result = TRUE; + + if (data) { + va_list argcpy; + va_copy(argcpy, args); + va_start(args, fmt); + memRequired = vsnprintf(buff, 1024, fmt, args); + if (memRequired >= 1024) { + buff = cx_malloc(memRequired + 1); + vsprintf(buff, fmt, argcpy); + } + va_end(args); + result = cx_ser_appendstrbuff(data, buff); + if (buff != alloc) { + cx_dealloc(buff); + } + } + + return result; +} + +static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { + CX_UNUSED(s); + cx_object *o = cx_valueObject(v); + cx_sqlite_ser_t *data = userData; + cx_string name = cx_nameof(o); + int parentId = NULL; + cx_string parentIdStr; + { + if (parentId != NULL) { + size_t length; + length = snprintf(NULL, 0, "%d", parentId); + if (length < 1) { + goto error; + } + parentIdStr = cx_malloc(length + 1); + sprintf(parentIdStr, "%d", parentId); + } else { + parentIdStr = cx_malloc(sizeof("NULL")); + strcpy(parentIdStr, "NULL"); + } + } + if (!cx_ser_appendstr(data, + "INSERT INTO \"Objects\" (\"Name\", \"Parent\") " + "VALUES ('%s', %s);", + cx_nameof(o), + parentIdStr + )) { + goto finished; + } + return 0; +error: + return -1; +finished: + return 1; +} + +struct cx_serializer_s cx_sqlite_declare_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { + struct cx_serializer_s s; + cx_serializerInit(&s); + s.access = access; + s.accessKind = accessKind; + s.traceKind = trace; + s.metaprogram[CX_OBJECT] = cx_ser_object; + return s; +} diff --git a/interface/sqlite/src/ser_sqlite_define.c b/interface/sqlite/src/ser_sqlite_define.c new file mode 100644 index 00000000..06e487bb --- /dev/null +++ b/interface/sqlite/src/ser_sqlite_define.c @@ -0,0 +1,251 @@ +#include +#include +#include + +#include "cx_generator.h" +#include "cx_serializer.h" +#include "cx_string.h" +#include "cortex.h" +#include "ser_sqlite.h" + +/* + * https://www.sqlite.org/lang_update.html + */ + +/* agreed not to change anything except the first argument of the signature */ +static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { + if (!data->ptr) { + data->ptr = data->buffer; + } + if (!data->ptr) { + data->buffer = strdup(str); + data->ptr = data->buffer; + } else { + cx_uint32 length, bufferLength; + + if (!data->length) { + data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); + data->ptr = data->buffer; + } + + length = strlen(str); + bufferLength = strlen(data->buffer); + + if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { + strncat(data->ptr, str, data->maxlength - bufferLength); + goto maxreached; + } else { + strcat(data->ptr, str); + } + } + + return TRUE; +maxreached: + return FALSE; +} + +/* agreed not to change anything except the first argument of the signature */ +/* Append string to serializer-result */ +static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { + char alloc[1024]; + char *buff = alloc; + va_list args; + cx_uint32 memRequired; + cx_uint32 result = TRUE; + + if (data) { + va_list argcpy; + va_copy(argcpy, args); + va_start(args, fmt); + memRequired = vsnprintf(buff, 1024, fmt, args); + if (memRequired >= 1024) { + buff = cx_malloc(memRequired + 1); + vsprintf(buff, fmt, argcpy); + } + va_end(args); + result = cx_ser_appendstrbuff(data, buff); + if (buff != alloc) { + cx_dealloc(buff); + } + } + + return result; +} + +static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData) { + CX_UNUSED(s); + cx_type type; + cx_void *value; + cx_string valueString = NULL; + cx_sqlite_ser_t *data = userData; + cx_int16 result; + + type = cx_valueType(info); + value = cx_valueValue(info); + cx_primitiveKind kind = cx_primitive(type)->kind; + + if (!cx_ser_appendstr(data, "(\"Value\") VALUES (")) { + goto finished; + } + + result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); + if (result) { + goto error; + } + + if (kind == CX_CHARACTER || (kind == CX_TEXT && (*(cx_string *)value))) { + size_t length; + cx_string escapedValueString = cx_malloc((length = stresc(NULL, 0, valueString)) + 1); + stresc(escapedValueString, length, valueString); + cx_dealloc(valueString); + valueString = escapedValueString; + } + + switch (cx_primitive(type)->kind) { + case CX_BINARY: + if (!cx_ser_appendstr(data, "\"@B %s\"", valueString)) { + goto finished; + } + break; + case CX_BITMASK: + if (!cx_ser_appendstr(data, "\"@M %s\"", valueString)) { + goto finished; + } + break; + case CX_ENUM: + if (!cx_ser_appendstr(data, "\"@E %s\"", valueString)) { + goto finished; + } + break; + case CX_CHARACTER: + case CX_TEXT: + // TODO escape @'s and other characters + if (!*(cx_string *)value) { + if (!cx_ser_appendstr(data, "null")) { + goto finished; + } + } else { + if (!cx_ser_appendstr(data, "\"")) { + goto finished; + } + if (*valueString == '@' && !cx_ser_appendstr(data, "@")) { + goto finished; + } + if (!cx_ser_appendstr(data, "%s\"", valueString)) { + goto finished; + } + } + break; + default: + if (!cx_ser_appendstr(data, valueString)) { + goto finished; + } + break; + } + cx_dealloc(valueString); + if (!cx_ser_appendstr(data, ")")) { + goto finished; + } + return 0; +finished: + cx_dealloc(valueString); + return 1; +error: + return -1; +} + +static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +finished: + return 1; + +} + +static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +error: + return -1; +finished: + return 1; +} + +static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { + cx_sqlite_ser_t data = *(cx_sqlite_ser_t*)userData; + data.itemCount = 0; + cx_type type = cx_valueType(v); + + if (type->kind == CX_COMPOSITE) { + if (cx_serializeMembers(s, v, &data)) { + goto error; + } + } else if (type->kind == CX_COLLECTION) { + if (cx_serializeElements(s, v, &data)) { + goto error; + } + } else { + goto error; + } + ((cx_sqlite_ser_t*)userData)->buffer = data.buffer; + ((cx_sqlite_ser_t*)userData)->ptr = data.ptr; + return 0; +error: + return -1; +finished: + return 1; +} + +static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +error: + return -1; +finished: + return 1; +} + +/* + * It should be responsibility of the underlying value kind to add + * "(column1, column2) VALUES (value1, value2)". + */ +static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { + cx_sqlite_ser_t *data = userData; + if (!cx_ser_appendstr(data, "INSERT INTO \"%s\"", + cx_nameof(cx_valueType(v)))) { + goto finished; + } + cx_serializeValue(s, v, data); + if (!cx_ser_appendstr(data, ";")) { + goto finished; + } + return 0; +error: + return -1; +finished: + return 1; +} + +struct cx_serializer_s cx_sqlite_define_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { + struct cx_serializer_s s; + cx_serializerInit(&s); + + s.access = access; + s.accessKind = accessKind; + s.traceKind = trace; + s.program[CX_PRIMITIVE] = cx_ser_primitive; + s.reference = cx_ser_reference; + s.program[CX_COMPOSITE] = cx_ser_composite; + // s.program[CX_COLLECTION] = cx_ser_complex; + s.metaprogram[CX_ELEMENT] = cx_ser_item; + s.metaprogram[CX_MEMBER] = cx_ser_item; + s.metaprogram[CX_BASE] = cx_ser_base; + s.metaprogram[CX_OBJECT] = cx_ser_object; + return s; +} diff --git a/interface/sqlite/src/ser_sqlite_update.c b/interface/sqlite/src/ser_sqlite_update.c new file mode 100644 index 00000000..6e7d4df7 --- /dev/null +++ b/interface/sqlite/src/ser_sqlite_update.c @@ -0,0 +1,253 @@ + +#include +#include +#include + +#include "cx_generator.h" +#include "cx_serializer.h" +#include "cx_string.h" +#include "cortex.h" +#include "ser_sqlite.h" + +/* + * https://www.sqlite.org/lang_update.html + */ + +/* agreed not to change anything except the first argument of the signature */ +static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { + if (!data->ptr) { + data->ptr = data->buffer; + } + if (!data->ptr) { + data->buffer = strdup(str); + data->ptr = data->buffer; + } else { + cx_uint32 length, bufferLength; + + if (!data->length) { + data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); + data->ptr = data->buffer; + } + + length = strlen(str); + bufferLength = strlen(data->buffer); + + if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { + strncat(data->ptr, str, data->maxlength - bufferLength); + goto maxreached; + } else { + strcat(data->ptr, str); + } + } + + return TRUE; +maxreached: + return FALSE; +} + +/* agreed not to change anything except the first argument of the signature */ +/* Append string to serializer-result */ +static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { + char alloc[1024]; + char *buff = alloc; + va_list args; + cx_uint32 memRequired; + cx_uint32 result = TRUE; + + if (data) { + va_list argcpy; + va_copy(argcpy, args); + va_start(args, fmt); + memRequired = vsnprintf(buff, 1024, fmt, args); + if (memRequired >= 1024) { + buff = cx_malloc(memRequired + 1); + vsprintf(buff, fmt, argcpy); + } + va_end(args); + result = cx_ser_appendstrbuff(data, buff); + if (buff != alloc) { + cx_dealloc(buff); + } + } + + return result; +} + +static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData) { + CX_UNUSED(s); + cx_type type; + cx_void *value; + cx_string valueString = NULL; + cx_sqlite_ser_t *data = userData; + cx_int16 result; + + type = cx_valueType(info); + value = cx_valueValue(info); + cx_primitiveKind kind = cx_primitive(type)->kind; + + if (!cx_ser_appendstr(data, "(\"Value\") VALUES (")) { + goto finished; + } + + result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); + if (result) { + goto error; + } + + if (kind == CX_CHARACTER || (kind == CX_TEXT && (*(cx_string *)value))) { + size_t length; + cx_string escapedValueString = cx_malloc((length = stresc(NULL, 0, valueString)) + 1); + stresc(escapedValueString, length, valueString); + cx_dealloc(valueString); + valueString = escapedValueString; + } + + switch (cx_primitive(type)->kind) { + case CX_BINARY: + if (!cx_ser_appendstr(data, "\"@B %s\"", valueString)) { + goto finished; + } + break; + case CX_BITMASK: + if (!cx_ser_appendstr(data, "\"@M %s\"", valueString)) { + goto finished; + } + break; + case CX_ENUM: + if (!cx_ser_appendstr(data, "\"@E %s\"", valueString)) { + goto finished; + } + break; + case CX_CHARACTER: + case CX_TEXT: + // TODO escape @'s and other characters + if (!*(cx_string *)value) { + if (!cx_ser_appendstr(data, "null")) { + goto finished; + } + } else { + if (!cx_ser_appendstr(data, "\"")) { + goto finished; + } + if (*valueString == '@' && !cx_ser_appendstr(data, "@")) { + goto finished; + } + if (!cx_ser_appendstr(data, "%s\"", valueString)) { + goto finished; + } + } + break; + default: + if (!cx_ser_appendstr(data, valueString)) { + goto finished; + } + break; + } + cx_dealloc(valueString); + if (!cx_ser_appendstr(data, ")")) { + goto finished; + } + return 0; +finished: + cx_dealloc(valueString); + return 1; +error: + return -1; +} + +static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +finished: + return 1; + +} + +static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +error: + return -1; +finished: + return 1; +} + +static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { + cx_sqlite_ser_t data = *(cx_sqlite_ser_t*)userData; + data.itemCount = 0; + cx_type type = cx_valueType(v); + + if (type->kind == CX_COMPOSITE) { + if (cx_serializeMembers(s, v, &data)) { + goto error; + } + } else if (type->kind == CX_COLLECTION) { + if (cx_serializeElements(s, v, &data)) { + goto error; + } + } else { + goto error; + } + + ((cx_sqlite_ser_t*)userData)->buffer = data.buffer; + ((cx_sqlite_ser_t*)userData)->ptr = data.ptr; + return 0; +error: + return -1; +finished: + return 1; +} + +static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +error: + return -1; +finished: + return 1; +} + +/* + * It should be responsibility of the underlying value kind to add + * "(column1, column2) VALUES (value1, value2)". + */ +static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { + cx_sqlite_ser_t *data = userData; + if (!cx_ser_appendstr(data, "UPDATE \"%s\"", + cx_nameof(cx_valueType(v)))) { + goto finished; + } + cx_serializeValue(s, v, data); + if (!cx_ser_appendstr(data, ";")) { + goto finished; + } + return 0; +error: + return -1; +finished: + return 1; +} + +struct cx_serializer_s cx_sqlite_update_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { + struct cx_serializer_s s; + cx_serializerInit(&s); + + s.access = access; + s.accessKind = accessKind; + s.traceKind = trace; + s.program[CX_PRIMITIVE] = cx_ser_primitive; + s.reference = cx_ser_reference; + s.program[CX_COMPOSITE] = cx_ser_composite; + // s.program[CX_COLLECTION] = cx_ser_complex; + s.metaprogram[CX_ELEMENT] = cx_ser_item; + s.metaprogram[CX_MEMBER] = cx_ser_item; + s.metaprogram[CX_BASE] = cx_ser_base; + s.metaprogram[CX_OBJECT] = cx_ser_object; + return s; +} From 6a9f538096b8dd3715ee38877d8f40b8068305bf Mon Sep 17 00:00:00 2001 From: Johnny Lee Date: Sat, 14 Mar 2015 12:09:18 -0600 Subject: [PATCH 2/6] #18 Added string escaping --- interface/sqlite/src/sql.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 interface/sqlite/src/sql.c diff --git a/interface/sqlite/src/sql.c b/interface/sqlite/src/sql.c new file mode 100644 index 00000000..859b6339 --- /dev/null +++ b/interface/sqlite/src/sql.c @@ -0,0 +1,31 @@ +#include "cx_string.h" + +/* + * Writes at most `n` - 1 bytes from `in` into `out`. + * Returns the total length that should have been written without the null character. + * Escapes all single quotes as double quotes. + */ +size_t escsqlstr(char *out, size_t n, const char *in) { + size_t len = 0; + const char *p = in; + char *q = out; + char c; + while ((c = *p++)) { + if (c != '\'') { + len++; + if (n && (size_t)(q - out) < n) { + *q++ = c; + } + } else { + len += 2; + if (n && (size_t)(q - out) < n) { + *(q + 1) = *q = '\''; + q += 2; + } + } + } + if (n) { + *q = '\0'; + } + return len; +} From 25267fe9b86d4d14296dd0eb4eeb3ef8310c99f7 Mon Sep 17 00:00:00 2001 From: Johnny Lee Date: Sat, 14 Mar 2015 14:34:02 -0600 Subject: [PATCH 3/6] #181 CREATE TABLE statements for composite types' primitive columns --- interface/sqlite/include/ser_sqlite.h | 3 + interface/sqlite/src/ser_sqlite_declare.c | 7 +- interface/sqlite/src/ser_sqlite_define.c | 53 +++--- interface/sqlite/src/ser_sqlite_update.c | 16 -- interface/sqlite/src/sql.c | 5 +- interface/sqlite/src/typeserializer.c | 209 ++++++++++++++++++++++ 6 files changed, 246 insertions(+), 47 deletions(-) create mode 100644 interface/sqlite/src/typeserializer.c diff --git a/interface/sqlite/include/ser_sqlite.h b/interface/sqlite/include/ser_sqlite.h index 68043b4f..f94dbd9d 100644 --- a/interface/sqlite/include/ser_sqlite.h +++ b/interface/sqlite/include/ser_sqlite.h @@ -16,3 +16,6 @@ typedef struct cx_sqlite_ser_t { struct cx_serializer_s cx_sqlite_declare_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); struct cx_serializer_s cx_sqlite_define_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); struct cx_serializer_s cx_sqlite_update_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); +struct cx_serializer_s cx_type_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); + +size_t escsqlstr(char *out, size_t n, const char *in); diff --git a/interface/sqlite/src/ser_sqlite_declare.c b/interface/sqlite/src/ser_sqlite_declare.c index 6ce2510e..cb461dc3 100644 --- a/interface/sqlite/src/ser_sqlite_declare.c +++ b/interface/sqlite/src/ser_sqlite_declare.c @@ -1,4 +1,3 @@ - #include #include #include @@ -77,11 +76,11 @@ static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { CX_UNUSED(s); cx_object *o = cx_valueObject(v); cx_sqlite_ser_t *data = userData; - cx_string name = cx_nameof(o); - int parentId = NULL; + // cx_string name = cx_nameof(o); + int parentId = 0; /* todo obtain parent id */ cx_string parentIdStr; { - if (parentId != NULL) { + if (parentId != 0) { size_t length; length = snprintf(NULL, 0, "%d", parentId); if (length < 1) { diff --git a/interface/sqlite/src/ser_sqlite_define.c b/interface/sqlite/src/ser_sqlite_define.c index 06e487bb..6c5502e6 100644 --- a/interface/sqlite/src/ser_sqlite_define.c +++ b/interface/sqlite/src/ser_sqlite_define.c @@ -84,7 +84,11 @@ static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData value = cx_valueValue(info); cx_primitiveKind kind = cx_primitive(type)->kind; - if (!cx_ser_appendstr(data, "(\"Value\") VALUES (")) { + if (!cx_ser_appendstr(data, "(\"ObjectId\", \"Value\") VALUES (")) { + goto finished; + } + + if (!cx_ser_appendstr(data, "NULL, ")) { goto finished; } @@ -103,44 +107,53 @@ static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData switch (cx_primitive(type)->kind) { case CX_BINARY: - if (!cx_ser_appendstr(data, "\"@B %s\"", valueString)) { + if (!cx_ser_appendstr(data, "%s", "0")) { goto finished; } break; case CX_BITMASK: - if (!cx_ser_appendstr(data, "\"@M %s\"", valueString)) { + if (!cx_ser_appendstr(data, "%s", "0")) { goto finished; } break; case CX_ENUM: - if (!cx_ser_appendstr(data, "\"@E %s\"", valueString)) { + if (!cx_ser_appendstr(data, "%s", "0")) { goto finished; } break; case CX_CHARACTER: case CX_TEXT: - // TODO escape @'s and other characters if (!*(cx_string *)value) { - if (!cx_ser_appendstr(data, "null")) { + if (!cx_ser_appendstr(data, "NULL")) { goto finished; } } else { - if (!cx_ser_appendstr(data, "\"")) { + if (!cx_ser_appendstr(data, "'")) { goto finished; } - if (*valueString == '@' && !cx_ser_appendstr(data, "@")) { + size_t length = escsqlstr(NULL, 0, valueString); + char *escapedString = cx_malloc(length + 1); + escsqlstr(escapedString, length, valueString); + if (!cx_ser_appendstr(data, escapedString)) { goto finished; } - if (!cx_ser_appendstr(data, "%s\"", valueString)) { + cx_dealloc(escapedString); + if (!cx_ser_appendstr(data, "'")) { goto finished; } } break; - default: + case CX_INTEGER: + case CX_FLOAT: + case CX_BOOLEAN: + case CX_UINTEGER: if (!cx_ser_appendstr(data, valueString)) { goto finished; } break; + case CX_ALIAS: + cx_critical("Cannot serialize alias"); + break; } cx_dealloc(valueString); if (!cx_ser_appendstr(data, ")")) { @@ -159,9 +172,6 @@ static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(v); CX_UNUSED(userData); return 0; -finished: - return 1; - } static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { @@ -169,10 +179,6 @@ static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(v); CX_UNUSED(userData); return 0; -error: - return -1; -finished: - return 1; } static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { @@ -196,8 +202,6 @@ static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { return 0; error: return -1; -finished: - return 1; } static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { @@ -205,10 +209,6 @@ static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { CX_UNUSED(v); CX_UNUSED(userData); return 0; -error: - return -1; -finished: - return 1; } /* @@ -217,6 +217,8 @@ static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { */ static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { cx_sqlite_ser_t *data = userData; + cx_object *o = cx_valueObject(v); + // TODO think about what to do with types... will we define types if (!cx_ser_appendstr(data, "INSERT INTO \"%s\"", cx_nameof(cx_valueType(v)))) { goto finished; @@ -224,10 +226,11 @@ static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { cx_serializeValue(s, v, data); if (!cx_ser_appendstr(data, ";")) { goto finished; + } + if (cx_instanceof(cx_typeof(cx_type_o), o)) { + } return 0; -error: - return -1; finished: return 1; } diff --git a/interface/sqlite/src/ser_sqlite_update.c b/interface/sqlite/src/ser_sqlite_update.c index 6e7d4df7..4b27ae36 100644 --- a/interface/sqlite/src/ser_sqlite_update.c +++ b/interface/sqlite/src/ser_sqlite_update.c @@ -1,4 +1,3 @@ - #include #include #include @@ -160,9 +159,6 @@ static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(v); CX_UNUSED(userData); return 0; -finished: - return 1; - } static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { @@ -170,10 +166,6 @@ static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(v); CX_UNUSED(userData); return 0; -error: - return -1; -finished: - return 1; } static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { @@ -198,8 +190,6 @@ static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { return 0; error: return -1; -finished: - return 1; } static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { @@ -207,10 +197,6 @@ static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { CX_UNUSED(v); CX_UNUSED(userData); return 0; -error: - return -1; -finished: - return 1; } /* @@ -228,8 +214,6 @@ static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { goto finished; } return 0; -error: - return -1; finished: return 1; } diff --git a/interface/sqlite/src/sql.c b/interface/sqlite/src/sql.c index 859b6339..2e3fd506 100644 --- a/interface/sqlite/src/sql.c +++ b/interface/sqlite/src/sql.c @@ -1,9 +1,10 @@ #include "cx_string.h" /* - * Writes at most `n` - 1 bytes from `in` into `out`. + * Writes at most `n` - 1 bytes from `in` into `out`, plus a null character. * Returns the total length that should have been written without the null character. - * Escapes all single quotes as double quotes. + * Escapes all single quotes as two single quotes. + * https://www.sqlite.org/lang_expr.html */ size_t escsqlstr(char *out, size_t n, const char *in) { size_t len = 0; diff --git a/interface/sqlite/src/typeserializer.c b/interface/sqlite/src/typeserializer.c new file mode 100644 index 00000000..9f146548 --- /dev/null +++ b/interface/sqlite/src/typeserializer.c @@ -0,0 +1,209 @@ +#include +#include +#include + +#include "cx_generator.h" +#include "cx_serializer.h" +#include "cx_string.h" +#include "cortex.h" +#include "ser_sqlite.h" + +/* + * https://www.sqlite.org/lang_update.html + */ + +/* agreed not to change anything except the first argument of the signature */ +static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { + if (!data->ptr) { + data->ptr = data->buffer; + } + if (!data->ptr) { + data->buffer = strdup(str); + data->ptr = data->buffer; + } else { + cx_uint32 length, bufferLength; + + if (!data->length) { + data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); + data->ptr = data->buffer; + } + + length = strlen(str); + bufferLength = strlen(data->buffer); + + if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { + strncat(data->ptr, str, data->maxlength - bufferLength); + goto maxreached; + } else { + strcat(data->ptr, str); + } + } + + return TRUE; +maxreached: + return FALSE; +} + +/* agreed not to change anything except the first argument of the signature */ +/* Append string to serializer-result */ +static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { + char alloc[1024]; + char *buff = alloc; + va_list args; + cx_uint32 memRequired; + cx_uint32 result = TRUE; + + if (data) { + va_list argcpy; + va_copy(argcpy, args); + va_start(args, fmt); + memRequired = vsnprintf(buff, 1024, fmt, args); + if (memRequired >= 1024) { + buff = cx_malloc(memRequired + 1); + vsprintf(buff, fmt, argcpy); + } + va_end(args); + result = cx_ser_appendstrbuff(data, buff); + if (buff != alloc) { + cx_dealloc(buff); + } + } + + return result; +} + +static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { + CX_UNUSED(s); + CX_UNUSED(v); + CX_UNUSED(userData); + return 0; +} + +static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { + CX_UNUSED(s); + cx_type type = cx_valueType(v); + cx_sqlite_ser_t *data = userData; + if (data->itemCount) { + if (!cx_ser_appendstr(data, ", ")) { + goto finished; + } + } + cx_string memberName = cx_nameof(v->is.member.t); + switch (type->kind) { + case CX_PRIMITIVE: + switch (cx_primitive(type)->kind) { + case CX_CHARACTER: + case CX_TEXT: + if (!cx_ser_appendstr(data, "\"%s\" TEXT", memberName)) { + goto finished; + } + break; + case CX_BINARY: + case CX_BITMASK: + case CX_BOOLEAN: + case CX_INTEGER: + case CX_UINTEGER: + if (!cx_ser_appendstr(data, "\"%s\" INTEGER", memberName)) { + goto finished; + } + break; + case CX_FLOAT: + if (!cx_ser_appendstr(data, "\"%s\" REAL", memberName)) { + goto finished; + } + break; + case CX_ENUM: + if (!cx_ser_appendstr(data, "\"%s\" INTEGER REFERENCES \"%sConstant\"", + memberName, memberName)) { + goto finished; + } + break; + case CX_ALIAS: + cx_critical("CX_ALIAS not supported"); + break; + } + break; + case CX_COMPOSITE: + cx_serializeValue(s, v, userData); + break; + case CX_COLLECTION: + break; + case CX_VOID: + break; + case CX_ITERATOR: + cx_warning("CX_ITERATOR not serializable"); + break; + case CX_ANY: + cx_critical("CX_ANY not serializable"); + break; + } + data->itemCount++; + return 0; +finished: + return 1; +} + + + +static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { + cx_sqlite_ser_t *data = userData; + cx_type type = cx_valueType(v); + // TODO put fully scoped name with underscores + if (!cx_ser_appendstr(data, "CREATE TABLE \"%s\" (", + cx_nameof(cx_valueType(v)))) { + goto finished; + } + switch (type->kind) { + case CX_PRIMITIVE: + switch (cx_primitive(type)->kind) { + case CX_ENUM: + if (!cx_ser_appendstr(data, "\"Value\" INTEGER")) { + goto finished; + } + break; + case CX_BITMASK: + if (!cx_ser_appendstr(data, "\"Value\" INTEGER")) { + goto finished; + } + break; + default: + break; + } + break; + case CX_COMPOSITE: + cx_serializeValue(s, v, data); + break; + case CX_COLLECTION: + cx_warning("collection serialization not yet supported"); + break; + case CX_VOID: + break; + case CX_ANY: + break; + case CX_ITERATOR: + cx_critical("CX_ITERATOR not serializable"); + break; + } + if (!cx_ser_appendstr(data, ");")) { + goto finished; + } + return 0; +finished: + return 1; +} + +struct cx_serializer_s cx_type_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { + struct cx_serializer_s s; + cx_serializerInit(&s); + + s.access = access; + s.accessKind = accessKind; + s.traceKind = trace; + s.reference = cx_ser_reference; + s.metaprogram[CX_ELEMENT] = cx_ser_item; + + s.metaprogram[CX_MEMBER] = cx_ser_item; + // s.metaprogram[CX_BASE] = cx_ser_base; + s.metaprogram[CX_OBJECT] = cx_ser_object; + return s; +} From 6a06ea2d22deb883ed4f77c16562dc650bc32ad5 Mon Sep 17 00:00:00 2001 From: Johnny Lee Date: Sun, 15 Mar 2015 00:10:55 -0600 Subject: [PATCH 4/6] #171 Fixed serialization of primtiives/composites --- interface/sqlite/src/ser_sqlite_define.c | 154 ++++++++++++----------- interface/sqlite/src/typeserializer.c | 2 +- 2 files changed, 84 insertions(+), 72 deletions(-) diff --git a/interface/sqlite/src/ser_sqlite_define.c b/interface/sqlite/src/ser_sqlite_define.c index 6c5502e6..8b1fef03 100644 --- a/interface/sqlite/src/ser_sqlite_define.c +++ b/interface/sqlite/src/ser_sqlite_define.c @@ -72,38 +72,15 @@ static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { return result; } -static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData) { +static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(s); cx_type type; cx_void *value; - cx_string valueString = NULL; cx_sqlite_ser_t *data = userData; cx_int16 result; - type = cx_valueType(info); - value = cx_valueValue(info); - cx_primitiveKind kind = cx_primitive(type)->kind; - - if (!cx_ser_appendstr(data, "(\"ObjectId\", \"Value\") VALUES (")) { - goto finished; - } - - if (!cx_ser_appendstr(data, "NULL, ")) { - goto finished; - } - - result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); - if (result) { - goto error; - } - - if (kind == CX_CHARACTER || (kind == CX_TEXT && (*(cx_string *)value))) { - size_t length; - cx_string escapedValueString = cx_malloc((length = stresc(NULL, 0, valueString)) + 1); - stresc(escapedValueString, length, valueString); - cx_dealloc(valueString); - valueString = escapedValueString; - } + type = cx_valueType(v); + value = cx_valueValue(v); switch (cx_primitive(type)->kind) { case CX_BINARY: @@ -112,56 +89,91 @@ static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData } break; case CX_BITMASK: - if (!cx_ser_appendstr(data, "%s", "0")) { - goto finished; + { + cx_string valueString = NULL; + result = cx_convert(cx_primitive(cx_uint32_o), value, cx_primitive(cx_string_o), &valueString); + if (result) { + goto error; + } + if (!cx_ser_appendstr(data, "%s", valueString)) { + goto finished; + } + cx_dealloc(valueString); } break; case CX_ENUM: - if (!cx_ser_appendstr(data, "%s", "0")) { - goto finished; + { + cx_string valueString = NULL; + result = cx_convert(cx_primitive(cx_int32_o), value, cx_primitive(cx_string_o), &valueString); + if (result) { + goto error; + } + if (!cx_ser_appendstr(data, "%s", valueString)) { + goto finished; + } + cx_dealloc(valueString); } break; case CX_CHARACTER: case CX_TEXT: - if (!*(cx_string *)value) { - if (!cx_ser_appendstr(data, "NULL")) { - goto finished; - } - } else { - if (!cx_ser_appendstr(data, "'")) { - goto finished; + { + cx_string valueString = NULL; + result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); + if (result) { + goto error; } - size_t length = escsqlstr(NULL, 0, valueString); - char *escapedString = cx_malloc(length + 1); - escsqlstr(escapedString, length, valueString); - if (!cx_ser_appendstr(data, escapedString)) { - goto finished; + if (!*(cx_string *)value) { + if (!cx_ser_appendstr(data, "NULL")) { + goto finished; + } + } else { + if (!cx_ser_appendstr(data, "'")) { + goto finished; + } + size_t length = escsqlstr(NULL, 0, valueString); + char *escapedString = cx_malloc(length + 1); + escsqlstr(escapedString, length, valueString); + if (!cx_ser_appendstr(data, escapedString)) { + goto finished; + } + cx_dealloc(escapedString); + if (!cx_ser_appendstr(data, "'")) { + goto finished; + } } - cx_dealloc(escapedString); - if (!cx_ser_appendstr(data, "'")) { + cx_dealloc(valueString); + } + break; + case CX_BOOLEAN: + { + cx_bool *b = cx_valueValue(v); + if (!cx_ser_appendstr(data, "%s", (*b) ? "1" : "0")) { goto finished; } + } break; case CX_INTEGER: case CX_FLOAT: - case CX_BOOLEAN: case CX_UINTEGER: - if (!cx_ser_appendstr(data, valueString)) { - goto finished; + { + cx_string valueString = NULL; + result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); + if (result) { + goto error; + } + if (!cx_ser_appendstr(data, valueString)) { + goto finished; + } + cx_dealloc(valueString); } break; case CX_ALIAS: cx_critical("Cannot serialize alias"); break; } - cx_dealloc(valueString); - if (!cx_ser_appendstr(data, ")")) { - goto finished; - } return 0; finished: - cx_dealloc(valueString); return 1; error: return -1; @@ -170,31 +182,33 @@ static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { CX_UNUSED(s); CX_UNUSED(v); - CX_UNUSED(userData); + cx_sqlite_ser_t *data = userData; + if (!cx_ser_appendstr(data, "NULL")) { + goto finished; + } return 0; +finished: + return 1; } static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - CX_UNUSED(v); - CX_UNUSED(userData); + cx_sqlite_ser_t *data = userData; + if (data->itemCount) { + if (!cx_ser_appendstr(data, ", ")) { + goto finished; + } + } + cx_serializeValue(s, v, data); + data->itemCount++; return 0; +finished: + return 1; } static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { cx_sqlite_ser_t data = *(cx_sqlite_ser_t*)userData; data.itemCount = 0; - cx_type type = cx_valueType(v); - - if (type->kind == CX_COMPOSITE) { - if (cx_serializeMembers(s, v, &data)) { - goto error; - } - } else if (type->kind == CX_COLLECTION) { - if (cx_serializeElements(s, v, &data)) { - goto error; - } - } else { + if (cx_serializeMembers(s, v, &data)) { goto error; } ((cx_sqlite_ser_t*)userData)->buffer = data.buffer; @@ -218,13 +232,12 @@ static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { cx_sqlite_ser_t *data = userData; cx_object *o = cx_valueObject(v); - // TODO think about what to do with types... will we define types - if (!cx_ser_appendstr(data, "INSERT INTO \"%s\"", + if (!cx_ser_appendstr(data, "INSERT INTO \"%s\" VALUES (NULL, ", cx_nameof(cx_valueType(v)))) { goto finished; } cx_serializeValue(s, v, data); - if (!cx_ser_appendstr(data, ";")) { + if (!cx_ser_appendstr(data, ");")) { goto finished; } if (cx_instanceof(cx_typeof(cx_type_o), o)) { @@ -245,7 +258,6 @@ struct cx_serializer_s cx_sqlite_define_ser(cx_modifier access, cx_operatorKind s.program[CX_PRIMITIVE] = cx_ser_primitive; s.reference = cx_ser_reference; s.program[CX_COMPOSITE] = cx_ser_composite; - // s.program[CX_COLLECTION] = cx_ser_complex; s.metaprogram[CX_ELEMENT] = cx_ser_item; s.metaprogram[CX_MEMBER] = cx_ser_item; s.metaprogram[CX_BASE] = cx_ser_base; diff --git a/interface/sqlite/src/typeserializer.c b/interface/sqlite/src/typeserializer.c index 9f146548..6188966b 100644 --- a/interface/sqlite/src/typeserializer.c +++ b/interface/sqlite/src/typeserializer.c @@ -149,7 +149,7 @@ static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { cx_sqlite_ser_t *data = userData; cx_type type = cx_valueType(v); // TODO put fully scoped name with underscores - if (!cx_ser_appendstr(data, "CREATE TABLE \"%s\" (", + if (!cx_ser_appendstr(data, "CREATE TABLE IF NOT EXISTS \"%s\" (", cx_nameof(cx_valueType(v)))) { goto finished; } From d8113f9da1039404b675492c895a208cd0cc2757 Mon Sep 17 00:00:00 2001 From: Johnny Lee Date: Sun, 15 Mar 2015 13:33:06 -0600 Subject: [PATCH 5/6] #181 Made serialization of types more complete Some types have more custom column types. Of course, SQLite doesn't care too much as long as you read https://www.sqlite.org/datatype3.html#affname . --- interface/sqlite/include/ser_sqlite.h | 2 + interface/sqlite/src/sql.c | 48 +++++++++++++++ interface/sqlite/src/typeserializer.c | 86 +++++++++++++++++++++------ 3 files changed, 118 insertions(+), 18 deletions(-) diff --git a/interface/sqlite/include/ser_sqlite.h b/interface/sqlite/include/ser_sqlite.h index f94dbd9d..44ddaf25 100644 --- a/interface/sqlite/include/ser_sqlite.h +++ b/interface/sqlite/include/ser_sqlite.h @@ -19,3 +19,5 @@ struct cx_serializer_s cx_sqlite_update_ser(cx_modifier access, cx_operatorKind struct cx_serializer_s cx_type_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); size_t escsqlstr(char *out, size_t n, const char *in); + +// int cx_sqlite_solveName(cx_object o, cx_id out); diff --git a/interface/sqlite/src/sql.c b/interface/sqlite/src/sql.c index 2e3fd506..c1e0a60b 100644 --- a/interface/sqlite/src/sql.c +++ b/interface/sqlite/src/sql.c @@ -1,3 +1,4 @@ +#include "cx_object.h" #include "cx_string.h" /* @@ -30,3 +31,50 @@ size_t escsqlstr(char *out, size_t n, const char *in) { } return len; } + +/* + * + */ +int cx_sqlite_solveName(cx_object o, cx_id buffer) { + cx_char *ptr; + if (!o) { + *buffer = '\0'; + } else if (!cx_checkAttr(o, CX_ATTR_SCOPED)) { + goto error; + } else { + cx_object stack[CX_MAX_SCOPE_DEPTH]; + cx_uint32 depth = 0; + do { + stack[depth++] = o; + } while((o = cx_parentof(o))); + ptr = buffer; + if (depth == 1) { + *ptr++ = '_'; + } else { + while (depth--) { + cx_string name; + o = stack[depth]; + if ((name = cx_nameof(o))) { + size_t len; + *ptr++ = '_'; + if ((size_t)(ptr - buffer) >= (sizeof(cx_id) - 1)) { + goto finished; + } + len = strlen(name); + if ((size_t)(ptr - buffer + len) >= (sizeof(cx_id) - 1)) { + goto finished; + } + memcpy(ptr, name, len + 1); + ptr += len; + } + } + } + *ptr = '\0'; + } + return 0; +finished: + *ptr = '\0'; + return 1; +error: + return -1; +} diff --git a/interface/sqlite/src/typeserializer.c b/interface/sqlite/src/typeserializer.c index 6188966b..e3638f78 100644 --- a/interface/sqlite/src/typeserializer.c +++ b/interface/sqlite/src/typeserializer.c @@ -89,52 +89,95 @@ static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { } } cx_string memberName = cx_nameof(v->is.member.t); + if (!cx_ser_appendstr(data, "\"%s\"", memberName)) { + goto finished; + } + if (type->kind != CX_VOID) { + if (!cx_ser_appendstr(data, " ")) { + goto finished; + } + } switch (type->kind) { case CX_PRIMITIVE: switch (cx_primitive(type)->kind) { case CX_CHARACTER: + if (!cx_ser_appendstr(data, "CHAR")) { + goto finished; + } + break; case CX_TEXT: - if (!cx_ser_appendstr(data, "\"%s\" TEXT", memberName)) { + if (!cx_ser_appendstr(data, "TEXT")) { goto finished; } break; - case CX_BINARY: - case CX_BITMASK: case CX_BOOLEAN: + if (!cx_ser_appendstr(data, "BOOL")) { + goto finished; + } + break; + case CX_BITMASK: + if (!cx_ser_appendstr(data, "BITMASK_INT")) { + goto finished; + } + break; + case CX_BINARY: + if (!cx_ser_appendstr(data, "BINARY_INT")) { + goto finished; + } + break; case CX_INTEGER: + if (!cx_ser_appendstr(data, "INT")) { + goto finished; + } + break; case CX_UINTEGER: - if (!cx_ser_appendstr(data, "\"%s\" INTEGER", memberName)) { + if (!cx_ser_appendstr(data, "UINT")) { goto finished; } break; case CX_FLOAT: - if (!cx_ser_appendstr(data, "\"%s\" REAL", memberName)) { + if (!cx_ser_appendstr(data, "FLOAT")) { goto finished; } break; case CX_ENUM: - if (!cx_ser_appendstr(data, "\"%s\" INTEGER REFERENCES \"%sConstant\"", - memberName, memberName)) { + /* if (!cx_ser_appendstr(data, "\"%s\" INTEGER REFERENCES \"%sConstant\"", */ + if (!cx_ser_appendstr(data, "ENUM_INT")) { goto finished; } break; case CX_ALIAS: - cx_critical("CX_ALIAS not supported"); + if (!cx_ser_appendstr(data, "ALIAS")) { + goto finished; + } + cx_warning("-- CX_ALIAS not supported"); break; } break; case CX_COMPOSITE: - cx_serializeValue(s, v, userData); + if (!cx_ser_appendstr(data, "COMPOSITE")) { + goto finished; + } + // cx_serializeValue(s, v, userData); break; case CX_COLLECTION: + if (!cx_ser_appendstr(data, "COLLECTION")) { + goto finished; + } break; case CX_VOID: break; case CX_ITERATOR: - cx_warning("CX_ITERATOR not serializable"); + if (!cx_ser_appendstr(data, "ITERATOR")) { + goto finished; + } + cx_warning("-- CX_ITERATOR should not be serialized"); break; case CX_ANY: - cx_critical("CX_ANY not serializable"); + if (!cx_ser_appendstr(data, "ANY")) { + goto finished; + } + cx_critical("-- CX_ANY should not be serialized"); break; } data->itemCount++; @@ -144,25 +187,29 @@ static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { } - static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { cx_sqlite_ser_t *data = userData; cx_type type = cx_valueType(v); // TODO put fully scoped name with underscores - if (!cx_ser_appendstr(data, "CREATE TABLE IF NOT EXISTS \"%s\" (", - cx_nameof(cx_valueType(v)))) { + cx_id fullname; + cx_fullname(cx_valueType(v), fullname); + // printf("*** %s ***\n", fullname); + if (!cx_ser_appendstr(data, "CREATE TABLE IF NOT EXISTS \"%s\"" + " (\"ObjectId\" INTEGER", + fullname)) { + // cx_nameof(cx_valueType(v)))) { goto finished; } switch (type->kind) { case CX_PRIMITIVE: switch (cx_primitive(type)->kind) { case CX_ENUM: - if (!cx_ser_appendstr(data, "\"Value\" INTEGER")) { + if (!cx_ser_appendstr(data, ", \"Value\" INTEGER")) { goto finished; } break; case CX_BITMASK: - if (!cx_ser_appendstr(data, "\"Value\" INTEGER")) { + if (!cx_ser_appendstr(data, ", \"Value\" INTEGER")) { goto finished; } break; @@ -171,17 +218,20 @@ static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { } break; case CX_COMPOSITE: + if (!cx_ser_appendstr(data, ", ")) { + goto finished; + } cx_serializeValue(s, v, data); break; case CX_COLLECTION: - cx_warning("collection serialization not yet supported"); + cx_warning("-- collection serialization not yet supported"); break; case CX_VOID: break; case CX_ANY: break; case CX_ITERATOR: - cx_critical("CX_ITERATOR not serializable"); + cx_critical("-- CX_ITERATOR not serializable"); break; } if (!cx_ser_appendstr(data, ");")) { From f5cbc26bc699cbb270f6add9856342dff1b809cb Mon Sep 17 00:00:00 2001 From: Johnny Lee Date: Sun, 15 Mar 2015 18:35:27 -0600 Subject: [PATCH 6/6] #182 Removed SQLite files from project --- interface/Makefile | 3 - interface/sqlite/include/ser_sqlite.h | 23 -- interface/sqlite/makefile | 8 - interface/sqlite/src/ser_sqlite_declare.c | 119 ---------- interface/sqlite/src/ser_sqlite_define.c | 266 ---------------------- interface/sqlite/src/ser_sqlite_update.c | 237 ------------------- interface/sqlite/src/sql.c | 80 ------- interface/sqlite/src/typeserializer.c | 259 --------------------- 8 files changed, 995 deletions(-) delete mode 100644 interface/sqlite/include/ser_sqlite.h delete mode 100644 interface/sqlite/makefile delete mode 100644 interface/sqlite/src/ser_sqlite_declare.c delete mode 100644 interface/sqlite/src/ser_sqlite_define.c delete mode 100644 interface/sqlite/src/ser_sqlite_update.c delete mode 100644 interface/sqlite/src/sql.c delete mode 100644 interface/sqlite/src/typeserializer.c diff --git a/interface/Makefile b/interface/Makefile index 64bca0a8..3c4937c5 100644 --- a/interface/Makefile +++ b/interface/Makefile @@ -6,16 +6,13 @@ all: @make -C xml @make -C json @make -C fast - @make -C sqlite clean: @make clean -C xml @make clean -C json @make clean -C fast - @make clean -C sqlite gcov: @make gcov -C xml @make gcov -C json @make gcov -C fast - @make gcov -C sqlite diff --git a/interface/sqlite/include/ser_sqlite.h b/interface/sqlite/include/ser_sqlite.h deleted file mode 100644 index 44ddaf25..00000000 --- a/interface/sqlite/include/ser_sqlite.h +++ /dev/null @@ -1,23 +0,0 @@ -#include - -#include "cortex.h" -#include "cx_serializer.h" - -typedef struct cx_sqlite_ser_t { - /**/ - cx_string buffer; - cx_string ptr; - /**/ - unsigned int length; - unsigned int maxlength; - unsigned int itemCount; -} cx_sqlite_ser_t; - -struct cx_serializer_s cx_sqlite_declare_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); -struct cx_serializer_s cx_sqlite_define_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); -struct cx_serializer_s cx_sqlite_update_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); -struct cx_serializer_s cx_type_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace); - -size_t escsqlstr(char *out, size_t n, const char *in); - -// int cx_sqlite_solveName(cx_object o, cx_id out); diff --git a/interface/sqlite/makefile b/interface/sqlite/makefile deleted file mode 100644 index 7e0b6ba3..00000000 --- a/interface/sqlite/makefile +++ /dev/null @@ -1,8 +0,0 @@ - -TARGET = sqliteserializer - -INCLUDE = $(CORTEX_HOME)/dev/include - -LIBS = lang cortexdev - -include $(CORTEX_HOME)/build/component.makefile diff --git a/interface/sqlite/src/ser_sqlite_declare.c b/interface/sqlite/src/ser_sqlite_declare.c deleted file mode 100644 index cb461dc3..00000000 --- a/interface/sqlite/src/ser_sqlite_declare.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include - -#include "cx_generator.h" -#include "cx_serializer.h" -#include "cx_string.h" -#include "cortex.h" -#include "ser_sqlite.h" - -/* - * https://www.sqlite.org/lang_update.html - */ - -/* agreed not to change anything except the first argument of the signature */ -static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { - if (!data->ptr) { - data->ptr = data->buffer; - } - if (!data->ptr) { - data->buffer = strdup(str); - data->ptr = data->buffer; - } else { - cx_uint32 length, bufferLength; - - if (!data->length) { - data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); - data->ptr = data->buffer; - } - - length = strlen(str); - bufferLength = strlen(data->buffer); - - if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { - strncat(data->ptr, str, data->maxlength - bufferLength); - goto maxreached; - } else { - strcat(data->ptr, str); - } - } - - return TRUE; -maxreached: - return FALSE; -} - -/* agreed not to change anything except the first argument of the signature */ -/* Append string to serializer-result */ -static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { - char alloc[1024]; - char *buff = alloc; - va_list args; - cx_uint32 memRequired; - cx_uint32 result = TRUE; - - if (data) { - va_list argcpy; - va_copy(argcpy, args); - va_start(args, fmt); - memRequired = vsnprintf(buff, 1024, fmt, args); - if (memRequired >= 1024) { - buff = cx_malloc(memRequired + 1); - vsprintf(buff, fmt, argcpy); - } - va_end(args); - result = cx_ser_appendstrbuff(data, buff); - if (buff != alloc) { - cx_dealloc(buff); - } - } - - return result; -} - -static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { - CX_UNUSED(s); - cx_object *o = cx_valueObject(v); - cx_sqlite_ser_t *data = userData; - // cx_string name = cx_nameof(o); - int parentId = 0; /* todo obtain parent id */ - cx_string parentIdStr; - { - if (parentId != 0) { - size_t length; - length = snprintf(NULL, 0, "%d", parentId); - if (length < 1) { - goto error; - } - parentIdStr = cx_malloc(length + 1); - sprintf(parentIdStr, "%d", parentId); - } else { - parentIdStr = cx_malloc(sizeof("NULL")); - strcpy(parentIdStr, "NULL"); - } - } - if (!cx_ser_appendstr(data, - "INSERT INTO \"Objects\" (\"Name\", \"Parent\") " - "VALUES ('%s', %s);", - cx_nameof(o), - parentIdStr - )) { - goto finished; - } - return 0; -error: - return -1; -finished: - return 1; -} - -struct cx_serializer_s cx_sqlite_declare_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { - struct cx_serializer_s s; - cx_serializerInit(&s); - s.access = access; - s.accessKind = accessKind; - s.traceKind = trace; - s.metaprogram[CX_OBJECT] = cx_ser_object; - return s; -} diff --git a/interface/sqlite/src/ser_sqlite_define.c b/interface/sqlite/src/ser_sqlite_define.c deleted file mode 100644 index 8b1fef03..00000000 --- a/interface/sqlite/src/ser_sqlite_define.c +++ /dev/null @@ -1,266 +0,0 @@ -#include -#include -#include - -#include "cx_generator.h" -#include "cx_serializer.h" -#include "cx_string.h" -#include "cortex.h" -#include "ser_sqlite.h" - -/* - * https://www.sqlite.org/lang_update.html - */ - -/* agreed not to change anything except the first argument of the signature */ -static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { - if (!data->ptr) { - data->ptr = data->buffer; - } - if (!data->ptr) { - data->buffer = strdup(str); - data->ptr = data->buffer; - } else { - cx_uint32 length, bufferLength; - - if (!data->length) { - data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); - data->ptr = data->buffer; - } - - length = strlen(str); - bufferLength = strlen(data->buffer); - - if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { - strncat(data->ptr, str, data->maxlength - bufferLength); - goto maxreached; - } else { - strcat(data->ptr, str); - } - } - - return TRUE; -maxreached: - return FALSE; -} - -/* agreed not to change anything except the first argument of the signature */ -/* Append string to serializer-result */ -static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { - char alloc[1024]; - char *buff = alloc; - va_list args; - cx_uint32 memRequired; - cx_uint32 result = TRUE; - - if (data) { - va_list argcpy; - va_copy(argcpy, args); - va_start(args, fmt); - memRequired = vsnprintf(buff, 1024, fmt, args); - if (memRequired >= 1024) { - buff = cx_malloc(memRequired + 1); - vsprintf(buff, fmt, argcpy); - } - va_end(args); - result = cx_ser_appendstrbuff(data, buff); - if (buff != alloc) { - cx_dealloc(buff); - } - } - - return result; -} - -static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - cx_type type; - cx_void *value; - cx_sqlite_ser_t *data = userData; - cx_int16 result; - - type = cx_valueType(v); - value = cx_valueValue(v); - - switch (cx_primitive(type)->kind) { - case CX_BINARY: - if (!cx_ser_appendstr(data, "%s", "0")) { - goto finished; - } - break; - case CX_BITMASK: - { - cx_string valueString = NULL; - result = cx_convert(cx_primitive(cx_uint32_o), value, cx_primitive(cx_string_o), &valueString); - if (result) { - goto error; - } - if (!cx_ser_appendstr(data, "%s", valueString)) { - goto finished; - } - cx_dealloc(valueString); - } - break; - case CX_ENUM: - { - cx_string valueString = NULL; - result = cx_convert(cx_primitive(cx_int32_o), value, cx_primitive(cx_string_o), &valueString); - if (result) { - goto error; - } - if (!cx_ser_appendstr(data, "%s", valueString)) { - goto finished; - } - cx_dealloc(valueString); - } - break; - case CX_CHARACTER: - case CX_TEXT: - { - cx_string valueString = NULL; - result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); - if (result) { - goto error; - } - if (!*(cx_string *)value) { - if (!cx_ser_appendstr(data, "NULL")) { - goto finished; - } - } else { - if (!cx_ser_appendstr(data, "'")) { - goto finished; - } - size_t length = escsqlstr(NULL, 0, valueString); - char *escapedString = cx_malloc(length + 1); - escsqlstr(escapedString, length, valueString); - if (!cx_ser_appendstr(data, escapedString)) { - goto finished; - } - cx_dealloc(escapedString); - if (!cx_ser_appendstr(data, "'")) { - goto finished; - } - } - cx_dealloc(valueString); - } - break; - case CX_BOOLEAN: - { - cx_bool *b = cx_valueValue(v); - if (!cx_ser_appendstr(data, "%s", (*b) ? "1" : "0")) { - goto finished; - } - - } - break; - case CX_INTEGER: - case CX_FLOAT: - case CX_UINTEGER: - { - cx_string valueString = NULL; - result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); - if (result) { - goto error; - } - if (!cx_ser_appendstr(data, valueString)) { - goto finished; - } - cx_dealloc(valueString); - } - break; - case CX_ALIAS: - cx_critical("Cannot serialize alias"); - break; - } - return 0; -finished: - return 1; -error: - return -1; -} - -static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - CX_UNUSED(v); - cx_sqlite_ser_t *data = userData; - if (!cx_ser_appendstr(data, "NULL")) { - goto finished; - } - return 0; -finished: - return 1; -} - -static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { - cx_sqlite_ser_t *data = userData; - if (data->itemCount) { - if (!cx_ser_appendstr(data, ", ")) { - goto finished; - } - } - cx_serializeValue(s, v, data); - data->itemCount++; - return 0; -finished: - return 1; -} - -static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { - cx_sqlite_ser_t data = *(cx_sqlite_ser_t*)userData; - data.itemCount = 0; - if (cx_serializeMembers(s, v, &data)) { - goto error; - } - ((cx_sqlite_ser_t*)userData)->buffer = data.buffer; - ((cx_sqlite_ser_t*)userData)->ptr = data.ptr; - return 0; -error: - return -1; -} - -static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { - CX_UNUSED(s); - CX_UNUSED(v); - CX_UNUSED(userData); - return 0; -} - -/* - * It should be responsibility of the underlying value kind to add - * "(column1, column2) VALUES (value1, value2)". - */ -static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { - cx_sqlite_ser_t *data = userData; - cx_object *o = cx_valueObject(v); - if (!cx_ser_appendstr(data, "INSERT INTO \"%s\" VALUES (NULL, ", - cx_nameof(cx_valueType(v)))) { - goto finished; - } - cx_serializeValue(s, v, data); - if (!cx_ser_appendstr(data, ");")) { - goto finished; - } - if (cx_instanceof(cx_typeof(cx_type_o), o)) { - - } - return 0; -finished: - return 1; -} - -struct cx_serializer_s cx_sqlite_define_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { - struct cx_serializer_s s; - cx_serializerInit(&s); - - s.access = access; - s.accessKind = accessKind; - s.traceKind = trace; - s.program[CX_PRIMITIVE] = cx_ser_primitive; - s.reference = cx_ser_reference; - s.program[CX_COMPOSITE] = cx_ser_composite; - s.metaprogram[CX_ELEMENT] = cx_ser_item; - s.metaprogram[CX_MEMBER] = cx_ser_item; - s.metaprogram[CX_BASE] = cx_ser_base; - s.metaprogram[CX_OBJECT] = cx_ser_object; - return s; -} diff --git a/interface/sqlite/src/ser_sqlite_update.c b/interface/sqlite/src/ser_sqlite_update.c deleted file mode 100644 index 4b27ae36..00000000 --- a/interface/sqlite/src/ser_sqlite_update.c +++ /dev/null @@ -1,237 +0,0 @@ -#include -#include -#include - -#include "cx_generator.h" -#include "cx_serializer.h" -#include "cx_string.h" -#include "cortex.h" -#include "ser_sqlite.h" - -/* - * https://www.sqlite.org/lang_update.html - */ - -/* agreed not to change anything except the first argument of the signature */ -static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { - if (!data->ptr) { - data->ptr = data->buffer; - } - if (!data->ptr) { - data->buffer = strdup(str); - data->ptr = data->buffer; - } else { - cx_uint32 length, bufferLength; - - if (!data->length) { - data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); - data->ptr = data->buffer; - } - - length = strlen(str); - bufferLength = strlen(data->buffer); - - if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { - strncat(data->ptr, str, data->maxlength - bufferLength); - goto maxreached; - } else { - strcat(data->ptr, str); - } - } - - return TRUE; -maxreached: - return FALSE; -} - -/* agreed not to change anything except the first argument of the signature */ -/* Append string to serializer-result */ -static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { - char alloc[1024]; - char *buff = alloc; - va_list args; - cx_uint32 memRequired; - cx_uint32 result = TRUE; - - if (data) { - va_list argcpy; - va_copy(argcpy, args); - va_start(args, fmt); - memRequired = vsnprintf(buff, 1024, fmt, args); - if (memRequired >= 1024) { - buff = cx_malloc(memRequired + 1); - vsprintf(buff, fmt, argcpy); - } - va_end(args); - result = cx_ser_appendstrbuff(data, buff); - if (buff != alloc) { - cx_dealloc(buff); - } - } - - return result; -} - -static cx_int16 cx_ser_primitive(cx_serializer s, cx_value *info, void *userData) { - CX_UNUSED(s); - cx_type type; - cx_void *value; - cx_string valueString = NULL; - cx_sqlite_ser_t *data = userData; - cx_int16 result; - - type = cx_valueType(info); - value = cx_valueValue(info); - cx_primitiveKind kind = cx_primitive(type)->kind; - - if (!cx_ser_appendstr(data, "(\"Value\") VALUES (")) { - goto finished; - } - - result = cx_convert(cx_primitive(type), value, cx_primitive(cx_string_o), &valueString); - if (result) { - goto error; - } - - if (kind == CX_CHARACTER || (kind == CX_TEXT && (*(cx_string *)value))) { - size_t length; - cx_string escapedValueString = cx_malloc((length = stresc(NULL, 0, valueString)) + 1); - stresc(escapedValueString, length, valueString); - cx_dealloc(valueString); - valueString = escapedValueString; - } - - switch (cx_primitive(type)->kind) { - case CX_BINARY: - if (!cx_ser_appendstr(data, "\"@B %s\"", valueString)) { - goto finished; - } - break; - case CX_BITMASK: - if (!cx_ser_appendstr(data, "\"@M %s\"", valueString)) { - goto finished; - } - break; - case CX_ENUM: - if (!cx_ser_appendstr(data, "\"@E %s\"", valueString)) { - goto finished; - } - break; - case CX_CHARACTER: - case CX_TEXT: - // TODO escape @'s and other characters - if (!*(cx_string *)value) { - if (!cx_ser_appendstr(data, "null")) { - goto finished; - } - } else { - if (!cx_ser_appendstr(data, "\"")) { - goto finished; - } - if (*valueString == '@' && !cx_ser_appendstr(data, "@")) { - goto finished; - } - if (!cx_ser_appendstr(data, "%s\"", valueString)) { - goto finished; - } - } - break; - default: - if (!cx_ser_appendstr(data, valueString)) { - goto finished; - } - break; - } - cx_dealloc(valueString); - if (!cx_ser_appendstr(data, ")")) { - goto finished; - } - return 0; -finished: - cx_dealloc(valueString); - return 1; -error: - return -1; -} - -static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - CX_UNUSED(v); - CX_UNUSED(userData); - return 0; -} - -static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - CX_UNUSED(v); - CX_UNUSED(userData); - return 0; -} - -static cx_int16 cx_ser_composite(cx_serializer s, cx_value* v, void* userData) { - cx_sqlite_ser_t data = *(cx_sqlite_ser_t*)userData; - data.itemCount = 0; - cx_type type = cx_valueType(v); - - if (type->kind == CX_COMPOSITE) { - if (cx_serializeMembers(s, v, &data)) { - goto error; - } - } else if (type->kind == CX_COLLECTION) { - if (cx_serializeElements(s, v, &data)) { - goto error; - } - } else { - goto error; - } - - ((cx_sqlite_ser_t*)userData)->buffer = data.buffer; - ((cx_sqlite_ser_t*)userData)->ptr = data.ptr; - return 0; -error: - return -1; -} - -static cx_int16 cx_ser_base(cx_serializer s, cx_value* v, void* userData) { - CX_UNUSED(s); - CX_UNUSED(v); - CX_UNUSED(userData); - return 0; -} - -/* - * It should be responsibility of the underlying value kind to add - * "(column1, column2) VALUES (value1, value2)". - */ -static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { - cx_sqlite_ser_t *data = userData; - if (!cx_ser_appendstr(data, "UPDATE \"%s\"", - cx_nameof(cx_valueType(v)))) { - goto finished; - } - cx_serializeValue(s, v, data); - if (!cx_ser_appendstr(data, ";")) { - goto finished; - } - return 0; -finished: - return 1; -} - -struct cx_serializer_s cx_sqlite_update_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { - struct cx_serializer_s s; - cx_serializerInit(&s); - - s.access = access; - s.accessKind = accessKind; - s.traceKind = trace; - s.program[CX_PRIMITIVE] = cx_ser_primitive; - s.reference = cx_ser_reference; - s.program[CX_COMPOSITE] = cx_ser_composite; - // s.program[CX_COLLECTION] = cx_ser_complex; - s.metaprogram[CX_ELEMENT] = cx_ser_item; - s.metaprogram[CX_MEMBER] = cx_ser_item; - s.metaprogram[CX_BASE] = cx_ser_base; - s.metaprogram[CX_OBJECT] = cx_ser_object; - return s; -} diff --git a/interface/sqlite/src/sql.c b/interface/sqlite/src/sql.c deleted file mode 100644 index c1e0a60b..00000000 --- a/interface/sqlite/src/sql.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "cx_object.h" -#include "cx_string.h" - -/* - * Writes at most `n` - 1 bytes from `in` into `out`, plus a null character. - * Returns the total length that should have been written without the null character. - * Escapes all single quotes as two single quotes. - * https://www.sqlite.org/lang_expr.html - */ -size_t escsqlstr(char *out, size_t n, const char *in) { - size_t len = 0; - const char *p = in; - char *q = out; - char c; - while ((c = *p++)) { - if (c != '\'') { - len++; - if (n && (size_t)(q - out) < n) { - *q++ = c; - } - } else { - len += 2; - if (n && (size_t)(q - out) < n) { - *(q + 1) = *q = '\''; - q += 2; - } - } - } - if (n) { - *q = '\0'; - } - return len; -} - -/* - * - */ -int cx_sqlite_solveName(cx_object o, cx_id buffer) { - cx_char *ptr; - if (!o) { - *buffer = '\0'; - } else if (!cx_checkAttr(o, CX_ATTR_SCOPED)) { - goto error; - } else { - cx_object stack[CX_MAX_SCOPE_DEPTH]; - cx_uint32 depth = 0; - do { - stack[depth++] = o; - } while((o = cx_parentof(o))); - ptr = buffer; - if (depth == 1) { - *ptr++ = '_'; - } else { - while (depth--) { - cx_string name; - o = stack[depth]; - if ((name = cx_nameof(o))) { - size_t len; - *ptr++ = '_'; - if ((size_t)(ptr - buffer) >= (sizeof(cx_id) - 1)) { - goto finished; - } - len = strlen(name); - if ((size_t)(ptr - buffer + len) >= (sizeof(cx_id) - 1)) { - goto finished; - } - memcpy(ptr, name, len + 1); - ptr += len; - } - } - } - *ptr = '\0'; - } - return 0; -finished: - *ptr = '\0'; - return 1; -error: - return -1; -} diff --git a/interface/sqlite/src/typeserializer.c b/interface/sqlite/src/typeserializer.c deleted file mode 100644 index e3638f78..00000000 --- a/interface/sqlite/src/typeserializer.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include -#include - -#include "cx_generator.h" -#include "cx_serializer.h" -#include "cx_string.h" -#include "cortex.h" -#include "ser_sqlite.h" - -/* - * https://www.sqlite.org/lang_update.html - */ - -/* agreed not to change anything except the first argument of the signature */ -static cx_bool cx_ser_appendstrbuff(cx_sqlite_ser_t* data, char* str) { - if (!data->ptr) { - data->ptr = data->buffer; - } - if (!data->ptr) { - data->buffer = strdup(str); - data->ptr = data->buffer; - } else { - cx_uint32 length, bufferLength; - - if (!data->length) { - data->buffer = cx_realloc(data->buffer, strlen(data->buffer) + strlen(str) + 1); - data->ptr = data->buffer; - } - - length = strlen(str); - bufferLength = strlen(data->buffer); - - if (data->maxlength && ((bufferLength + length) >= data->maxlength)) { - strncat(data->ptr, str, data->maxlength - bufferLength); - goto maxreached; - } else { - strcat(data->ptr, str); - } - } - - return TRUE; -maxreached: - return FALSE; -} - -/* agreed not to change anything except the first argument of the signature */ -/* Append string to serializer-result */ -static cx_bool cx_ser_appendstr(cx_sqlite_ser_t* data, cx_string fmt, ...) { - char alloc[1024]; - char *buff = alloc; - va_list args; - cx_uint32 memRequired; - cx_uint32 result = TRUE; - - if (data) { - va_list argcpy; - va_copy(argcpy, args); - va_start(args, fmt); - memRequired = vsnprintf(buff, 1024, fmt, args); - if (memRequired >= 1024) { - buff = cx_malloc(memRequired + 1); - vsprintf(buff, fmt, argcpy); - } - va_end(args); - result = cx_ser_appendstrbuff(data, buff); - if (buff != alloc) { - cx_dealloc(buff); - } - } - - return result; -} - -static cx_int16 cx_ser_reference(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - CX_UNUSED(v); - CX_UNUSED(userData); - return 0; -} - -static cx_int16 cx_ser_item(cx_serializer s, cx_value *v, void *userData) { - CX_UNUSED(s); - cx_type type = cx_valueType(v); - cx_sqlite_ser_t *data = userData; - if (data->itemCount) { - if (!cx_ser_appendstr(data, ", ")) { - goto finished; - } - } - cx_string memberName = cx_nameof(v->is.member.t); - if (!cx_ser_appendstr(data, "\"%s\"", memberName)) { - goto finished; - } - if (type->kind != CX_VOID) { - if (!cx_ser_appendstr(data, " ")) { - goto finished; - } - } - switch (type->kind) { - case CX_PRIMITIVE: - switch (cx_primitive(type)->kind) { - case CX_CHARACTER: - if (!cx_ser_appendstr(data, "CHAR")) { - goto finished; - } - break; - case CX_TEXT: - if (!cx_ser_appendstr(data, "TEXT")) { - goto finished; - } - break; - case CX_BOOLEAN: - if (!cx_ser_appendstr(data, "BOOL")) { - goto finished; - } - break; - case CX_BITMASK: - if (!cx_ser_appendstr(data, "BITMASK_INT")) { - goto finished; - } - break; - case CX_BINARY: - if (!cx_ser_appendstr(data, "BINARY_INT")) { - goto finished; - } - break; - case CX_INTEGER: - if (!cx_ser_appendstr(data, "INT")) { - goto finished; - } - break; - case CX_UINTEGER: - if (!cx_ser_appendstr(data, "UINT")) { - goto finished; - } - break; - case CX_FLOAT: - if (!cx_ser_appendstr(data, "FLOAT")) { - goto finished; - } - break; - case CX_ENUM: - /* if (!cx_ser_appendstr(data, "\"%s\" INTEGER REFERENCES \"%sConstant\"", */ - if (!cx_ser_appendstr(data, "ENUM_INT")) { - goto finished; - } - break; - case CX_ALIAS: - if (!cx_ser_appendstr(data, "ALIAS")) { - goto finished; - } - cx_warning("-- CX_ALIAS not supported"); - break; - } - break; - case CX_COMPOSITE: - if (!cx_ser_appendstr(data, "COMPOSITE")) { - goto finished; - } - // cx_serializeValue(s, v, userData); - break; - case CX_COLLECTION: - if (!cx_ser_appendstr(data, "COLLECTION")) { - goto finished; - } - break; - case CX_VOID: - break; - case CX_ITERATOR: - if (!cx_ser_appendstr(data, "ITERATOR")) { - goto finished; - } - cx_warning("-- CX_ITERATOR should not be serialized"); - break; - case CX_ANY: - if (!cx_ser_appendstr(data, "ANY")) { - goto finished; - } - cx_critical("-- CX_ANY should not be serialized"); - break; - } - data->itemCount++; - return 0; -finished: - return 1; -} - - -static cx_int16 cx_ser_object(cx_serializer s, cx_value* v, void* userData) { - cx_sqlite_ser_t *data = userData; - cx_type type = cx_valueType(v); - // TODO put fully scoped name with underscores - cx_id fullname; - cx_fullname(cx_valueType(v), fullname); - // printf("*** %s ***\n", fullname); - if (!cx_ser_appendstr(data, "CREATE TABLE IF NOT EXISTS \"%s\"" - " (\"ObjectId\" INTEGER", - fullname)) { - // cx_nameof(cx_valueType(v)))) { - goto finished; - } - switch (type->kind) { - case CX_PRIMITIVE: - switch (cx_primitive(type)->kind) { - case CX_ENUM: - if (!cx_ser_appendstr(data, ", \"Value\" INTEGER")) { - goto finished; - } - break; - case CX_BITMASK: - if (!cx_ser_appendstr(data, ", \"Value\" INTEGER")) { - goto finished; - } - break; - default: - break; - } - break; - case CX_COMPOSITE: - if (!cx_ser_appendstr(data, ", ")) { - goto finished; - } - cx_serializeValue(s, v, data); - break; - case CX_COLLECTION: - cx_warning("-- collection serialization not yet supported"); - break; - case CX_VOID: - break; - case CX_ANY: - break; - case CX_ITERATOR: - cx_critical("-- CX_ITERATOR not serializable"); - break; - } - if (!cx_ser_appendstr(data, ");")) { - goto finished; - } - return 0; -finished: - return 1; -} - -struct cx_serializer_s cx_type_ser(cx_modifier access, cx_operatorKind accessKind, cx_serializerTraceKind trace) { - struct cx_serializer_s s; - cx_serializerInit(&s); - - s.access = access; - s.accessKind = accessKind; - s.traceKind = trace; - s.reference = cx_ser_reference; - s.metaprogram[CX_ELEMENT] = cx_ser_item; - - s.metaprogram[CX_MEMBER] = cx_ser_item; - // s.metaprogram[CX_BASE] = cx_ser_base; - s.metaprogram[CX_OBJECT] = cx_ser_object; - return s; -}