CELIX-237: refactoring to dynamic_function_interface. dyn_type now uses mem stream and avro descriptor translator added
Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/bdeba2bc Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/bdeba2bc Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/bdeba2bc Branch: refs/heads/feature/CELIX-237_rsa-ffi Commit: bdeba2bcb6ef277ad7e809fbd482f6a6cd2ff1ce Parents: 7f33832 Author: Pepijn Noltes <pepijnnol...@gmail.com> Authored: Thu Jul 2 09:59:43 2015 +0200 Committer: Pepijn Noltes <pepijnnol...@gmail.com> Committed: Thu Jul 2 09:59:43 2015 +0200 ---------------------------------------------------------------------- remote_services/CMakeLists.txt | 2 +- remote_services/dyn_type/CMakeLists.txt | 23 - remote_services/dyn_type/closure_tests.c | 98 --- remote_services/dyn_type/dyn_function.c | 209 ----- remote_services/dyn_type/dyn_function.h | 24 - remote_services/dyn_type/dyn_type.c | 535 ------------ remote_services/dyn_type/dyn_type.h | 104 --- remote_services/dyn_type/func_tests.c | 66 -- remote_services/dyn_type/json_serializer.c | 123 --- remote_services/dyn_type/json_serializer.h | 9 - remote_services/dyn_type/struct_tests.c | 159 ---- .../dynamic_function_interface/CMakeLists.txt | 40 + .../avro_descriptor_translator.c | 294 +++++++ .../descriptor_translator.h | 28 + .../dynamic_function_interface/dfi_log_util.h | 50 ++ .../dynamic_function_interface/dyn_function.c | 185 +++++ .../dynamic_function_interface/dyn_function.h | 30 + .../dynamic_function_interface/dyn_type.c | 822 +++++++++++++++++++ .../dynamic_function_interface/dyn_type.h | 137 ++++ .../json_serializer.c | 151 ++++ .../json_serializer.h | 12 + .../schemas/complex.avdl | 11 + .../schemas/complex.avpr | 36 + .../schemas/simple.avdl | 6 + .../schemas/simple.avpr | 33 + .../schemas/simple_min.avpr | 1 + .../tst/avro_descriptor_translator_tests.cpp | 67 ++ .../tst/dyn_closure_tests.cpp | 139 ++++ .../tst/dyn_function_tests.cpp | 109 +++ .../tst/dyn_type_tests.cpp | 183 +++++ .../tst/json_serializer_tests.cpp | 182 ++++ .../tst/run_tests.cpp | 9 + 32 files changed, 2526 insertions(+), 1351 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/CMakeLists.txt b/remote_services/CMakeLists.txt index 9f56b58..b7dc13c 100644 --- a/remote_services/CMakeLists.txt +++ b/remote_services/CMakeLists.txt @@ -42,7 +42,7 @@ if (REMOTE_SERVICE_ADMIN) add_subdirectory(discovery_etcd) #add_subdirectory(discovery_shm) - add_subdirectory(dyn_type) + add_subdirectory(dynamic_function_interface) endif (REMOTE_SERVICE_ADMIN) http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/CMakeLists.txt b/remote_services/dyn_type/CMakeLists.txt deleted file mode 100644 index 351bb7c..0000000 --- a/remote_services/dyn_type/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -find_package(Jansson REQUIRED) - -add_executable(struct_tests - struct_tests.c - dyn_type.c - json_serializer.c -) - -add_executable(func_tests - func_tests.c - dyn_type.c - dyn_function.c -) - -add_executable(closure_tests - closure_tests.c - dyn_type.c - dyn_function.c -) - -target_link_libraries(struct_tests ${JANSSON_LIBRARIES} /lib64/libffi.so ) -target_link_libraries(func_tests ${JANSSON_LIBRARIES} /lib64/libffi.so ) -target_link_libraries(closure_tests ${JANSSON_LIBRARIES} /lib64/libffi.so ) http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/closure_tests.c ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/closure_tests.c b/remote_services/dyn_type/closure_tests.c deleted file mode 100644 index 39e4ca5..0000000 --- a/remote_services/dyn_type/closure_tests.c +++ /dev/null @@ -1,98 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#include "dyn_function.h" - -#define EXAMPLE1_SCHEMA "example(III)I" -void example1_binding(void *userData, void* args[], void *out) { - printf("example1 closure called\n"); - int32_t a = *((int32_t *)args[0]); - int32_t b = *((int32_t *)args[1]); - int32_t c = *((int32_t *)args[2]); - int32_t *ret = out; - *ret = a + b + c; -} - -#define EXAMPLE2_SCHEMA "example(I{DDD val1 val2 val3}I)D" -struct example2_arg2 { - double val1; - double val2; - double val3; -}; -void example2_binding(void *userData, void* args[], void *out) { - printf("example2 closure called\n"); - int32_t a = *((int32_t *)args[0]); - struct example2_arg2 *b = *((struct example2_arg2 **)args[1]); - int32_t c = *((int32_t *)args[2]); - int32_t *ret = out; - *ret = a + b->val1 + b->val2 + b->val3 + c; -} - - -#define EXAMPLE3_SCHEMA "example(III){III sum max min}" -struct example3_ret { - int32_t sum; - int32_t max; - int32_t min; -}; - -void example3_binding(void *userData, void* args[], void *out) { - printf("exampleelosure called\n"); - int32_t a = *((int32_t *)args[0]); - int32_t b = *((int32_t *)args[1]); - int32_t c = *((int32_t *)args[2]); - struct example3_ret *result = calloc(1,sizeof(*result)); - result->sum = a + b + c; - result->min = a <= b ? a : b; - result->max = a >= b ? a : b; - result->min = result->min <= c ? result->min : c; - result->max = result->max >= c ? result->max : c; - - struct example3_ret **ret = out; - (*ret) = result; -} - -int main() { - dyn_closure_type *dynClosure = NULL; - int rc; - - rc = dynClosure_create(EXAMPLE1_SCHEMA, example1_binding, NULL, &dynClosure); - if (rc == 0) { - int32_t (*func)(int32_t a, int32_t b, int32_t c) = NULL; - dynClosure_getFnPointer(dynClosure, (void *)&func); - int32_t ret = func(2,3,4); - printf("Return value for example1 is %i\n", ret); - dynClosure_destroy(dynClosure); - } else { - printf("example1 failed\n"); - } - - dynClosure = NULL; - rc = dynClosure_create(EXAMPLE2_SCHEMA, example2_binding, NULL, &dynClosure); - if (rc == 0) { - double (*func)(int32_t a, struct example2_arg2 *b, int32_t c) = NULL; - dynClosure_getFnPointer(dynClosure, (void *)&func); - struct example2_arg2 b = { .val1 = 1.0, .val2 = 1.5, .val3 = 2.0 }; - double ret = func(2,&b,4); - printf("Return value for example2 is %f\n", ret); - dynClosure_destroy(dynClosure); - } else { - printf("example2 failed\n"); - } - - dynClosure = NULL; - rc = dynClosure_create(EXAMPLE3_SCHEMA, example3_binding, NULL, &dynClosure); - if (rc == 0) { - struct example3_ret * (*func)(int32_t a, int32_t b, int32_t c) = NULL; - dynClosure_getFnPointer(dynClosure, (void *)&func); - struct example3_ret *ret = func(2,8,4); - printf("Return value for example3 is {sum:%i, max:%i, min:%i}\n", ret->sum, ret->max, ret->min); - dynClosure_destroy(dynClosure); - free(ret); - } else { - printf("example2 failed\n"); - } -} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_function.c ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/dyn_function.c b/remote_services/dyn_type/dyn_function.c deleted file mode 100644 index a90bc64..0000000 --- a/remote_services/dyn_type/dyn_function.c +++ /dev/null @@ -1,209 +0,0 @@ -#include "dyn_function.h" - -#include <stdio.h> -#include <stdarg.h> -#include <strings.h> -#include <string.h> -#include <stdlib.h> - -#include <ffi.h> - -#include "dyn_type.h" - -struct _dyn_function_type { - dyn_type *arguments; - dyn_type *funcReturn; - void (*fn)(void); - ffi_cif cif; -}; - -struct _dyn_closure_type { - dyn_type *arguments; - dyn_type *funcReturn; - ffi_cif cif; - ffi_closure *ffiClosure; - void (*fn)(void); - void (*bind)(void *userData, void *args[], void *ret); - void *userData; -}; - - -static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *funcReturn); -static int dynFunction_parseSchema(const char *schema, dyn_type **arguments, dyn_type **funcReturn); -static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData); - -int dynFunction_create(const char *schema, void (*fn)(void), dyn_function_type **out) { - int status = 0; - dyn_function_type *dynFunc = NULL; - - dynFunc = calloc(1, sizeof(*dynFunc)); - - if (dynFunc != NULL) { - dynFunc->fn = fn; - status = dynFunction_parseSchema(schema, &dynFunc->arguments, &dynFunc->funcReturn); - if (status == 0) { - status = dynFunction_initCif(&dynFunc->cif, dynFunc->arguments, dynFunc->funcReturn); - } - } else { - status = 2; - } - - if (status == 0) { - *out = dynFunc; - } else { - if (status == 1) { - printf("Cannot parse func schema '%s'\n", schema); - } else { - printf("Cannot allocate memory for dyn function\n"); - } - } - return status; -} - -static int dynFunction_parseSchema(const char *schema, dyn_type **arguments, dyn_type **funcReturn) { - int status = 0; - //FIXME white space parsing is missing. Note move parsing to lex/bison? - //TODO move to parse schema function - char *startPos = index(schema, '('); - char *endPos = index(schema, ')'); - - if (startPos != NULL && endPos != NULL) { - int nrOfArgs = 0; - int len = endPos - startPos - 1; - - char *pos = startPos + 1; - while (*pos != ')') { - nrOfArgs += 1; - if (*pos == '{') { //embedded struct - while (*pos != '}' && *pos != '\0') { - pos += 1; - } - } - pos += 1; - } - - printf("nrOfAgrs is %i\n", nrOfArgs); - - //length needed is len args +2 -> {DD} - //+ 7 per arg e.g. {DD arg001 arg002} - //+ 1 x \0 - //--> len args + 3 + 7 * nrArgs - int argLength = 3 + len + 7 * nrOfArgs; - - char argSchema[argLength]; - argSchema[0] = '{'; - memcpy(argSchema + 1, startPos + 1, len); - pos += len + 1; - int i; - for (i = 0 ; i < nrOfArgs; i += 1) { - sprintf(argSchema + 1 + len + 7 * i, " arg%03d", i); - pos += 7; - } - argSchema[argLength -2] = '}'; - argSchema[argLength -1] = '\0'; - printf("arg schema is '%s'\n", argSchema); - - size_t returnLen = strlen(endPos + 1); - char returnSchema[returnLen + 1]; - memcpy(returnSchema, endPos +1, returnLen); - returnSchema[returnLen] = '\0'; - printf("return schema is '%s'\n", returnSchema); - - status = dynType_create(argSchema, arguments); - if (status == 0) { - status = dynType_create(returnSchema, funcReturn); - } - } else { - status = 1; - } - - return status; -} - -static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *returnValue) { - int result = 0; - - int count = 0; - int i; - for (i = 0; arguments->complex.ffiType.elements[i] != NULL; i += 1) { - count += 1; - } - - ffi_type **args = arguments->complex.ffiType.elements; - ffi_type *returnType = &ffi_type_pointer; - if (returnType->type == DYN_TYPE_SIMPLE) { - returnType = returnValue->simple.ffiType; - } - - - int ffiResult = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, returnType, args); - if (ffiResult != FFI_OK) { - result = 1; - } - - return result; -} - -int dynFunction_destroy(dyn_function_type *dynFunc) { - int result = 0; - printf("TODO destroy dyn dync\n"); - return result; -} - -int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues) { - ffi_call(&dynFunc->cif, dynFunc->fn, returnValue, argValues); - return 0; -} - -static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData) { - dyn_closure_type *dynClosure = userData; - dynClosure->bind(dynClosure->userData, args, ret); -} - -int dynClosure_create(const char *schema, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out) { - int status = 0; - dyn_closure_type *dynClosure = calloc(1, sizeof(*dynClosure)); - if (dynClosure != NULL) { - dynClosure->bind = bind; - dynClosure->userData = userData; - status = dynFunction_parseSchema(schema, &dynClosure->arguments, &dynClosure->funcReturn); - if (status == 0) { - status = dynFunction_initCif(&dynClosure->cif, dynClosure->arguments, dynClosure->funcReturn); - if (status == 0) { - dynClosure->ffiClosure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&dynClosure->fn); - if (dynClosure->ffiClosure != NULL) { - int rc = ffi_prep_closure_loc(dynClosure->ffiClosure, &dynClosure->cif, dynClosure_ffiBind, dynClosure, dynClosure->fn); - if (rc != FFI_OK) { - status = 1; - } - } else { - status = 2; - } - } - } - } else { - status = 2; - } - - if (status == 0) { - *out = dynClosure; - } - return status; -} - -int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void (**fn)(void)) { - int status = 0; - if (dynClosure != NULL) { - (*fn) = dynClosure->fn; - } else { - status = 1; - } - return status; -} - - -int dynClosure_destroy(dyn_closure_type *dynClosure) { - int result = 0; - printf("TODO destroy closure\n"); - return result; -} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_function.h ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/dyn_function.h b/remote_services/dyn_type/dyn_function.h deleted file mode 100644 index 21a5e0d..0000000 --- a/remote_services/dyn_type/dyn_function.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __DYN_FUNCTION_H_ -#define __DYN_FUNCTION_H_ - -#include <ffi.h> -#include "dyn_type.h" - -/** - * Uses the following schema - * (Name)([Type]*)Type - * e.g add(DD)D or sum({[D[D setA setB})D - */ - -typedef struct _dyn_function_type dyn_function_type; -typedef struct _dyn_closure_type dyn_closure_type; - -int dynFunction_create(const char *schema, void (*fn)(void), dyn_function_type **dynFunc); -int dynFunction_destroy(dyn_function_type *dynFunc); -int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues); - -int dynClosure_create(const char *schema, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out); -int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void(**fn)(void)); -int dynClosure_destroy(dyn_closure_type *dynClosure); - -#endif http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_type.c ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/dyn_type.c b/remote_services/dyn_type/dyn_type.c deleted file mode 100644 index e7a2645..0000000 --- a/remote_services/dyn_type/dyn_type.c +++ /dev/null @@ -1,535 +0,0 @@ -#include "dyn_type.h" - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdbool.h> -#include <assert.h> - - -//place in dyn_type.h? -struct generic_sequence { - uint32_t _cap; - uint32_t _len; - void *buf; -}; - - -static char dynType_schemaType(dyn_type *dynType, ffi_type *ffiType); - -static void dynType_print_sequence(dyn_type *type, int depth); -static void dynType_print_complex(dyn_type *type, int depth); -static void dynType_print_any(dyn_type *type, int depth); - -static unsigned short get_offset_at(ffi_type *type, int index); -static void dynType_trim(const char *str, size_t len, int *start, int *end); - -static int dynType_complex_create(char *schema, dyn_type **result); -static int dynType_sequence_create(char *schema, dyn_type **result); -static int dynType_simple_create(char t, dyn_type **result); - -static ffi_type* dynType_ffiType_for(char c); - -int dynType_create(const char *schema, dyn_type **result) { - //trim white space - int status = 0; - int offset, len; - dynType_trim(schema, strlen(schema), &offset, &len); - - /* - char test[len+1]; - memcpy(test, schema + offset, len); - test[len] = '\0'; - printf("trimmed schema is %s\n", test); - */ - - if (schema[offset] == '{' && schema[offset + len -1] == '}') { - //complex - - //removing prefix { and postfix } - offset += 1; - len -= 2; - - int offsetType; - int lenType; - //trim again - dynType_trim(schema + offset, len , &offsetType, &lenType); - - char type[lenType + 1]; - memcpy(type, schema + offset + offsetType, lenType); - type[lenType] = '\0'; - status = dynType_complex_create(type, result); - } else if (schema[offset] == '[') { - //sequence - //fixme assuming simple type - offset += 1; //remove [ - len -= 1; - char type[len + 1]; - memcpy(type, schema + offset, len); - type[len] = '\0'; - status = dynType_sequence_create(type, result); - } else if (len == 1){ - //simple - status = dynType_simple_create(schema[offset], result); - } else { - printf("invalid schema '%s'\n", schema); - } - - return status; -} - -static int dynType_simple_create(char t, dyn_type **result) { - int status = 0; - ffi_type *ffiType = dynType_ffiType_for(t); - dyn_type *simple = NULL; - if (ffiType != NULL) { - simple = calloc(1,sizeof(*simple)); - simple->type = DYN_TYPE_SIMPLE; - simple->simple.ffiType = ffiType; - } - if (ffiType != NULL && simple != NULL) { - *result = simple; - } else { - printf("Error creating simple dyn type for '%c'\n", t); - status = 1; - } - return status; -} - -static int dynType_sequence_create(char *schema, dyn_type **result) { - int status = 0; - dyn_type *type = calloc(1, sizeof(*type)); - - type->type = DYN_TYPE_SEQUENCE; - type->sequence.seqStruct.elements = calloc(4, sizeof(ffi_type)); - type->sequence.seqStruct.elements[0] = &ffi_type_uint32; //_cap - type->sequence.seqStruct.elements[1] = &ffi_type_uint32; //_len - type->sequence.seqStruct.elements[2] = &ffi_type_pointer; - type->sequence.seqStruct.elements[3] = NULL; - - if (schema[0] == '{') { //complex type - int len = strlen(schema) -2; - char complexSchema[len + 1]; - memcpy(complexSchema, schema + 1, len); - complexSchema[len] = '\0'; - status = dynType_complex_create(complexSchema, &type->sequence.dynType); - } else { //simple type - type->sequence.simpleType = dynType_ffiType_for(schema[0]); - } - //TODO sequence of sequence - - if (status == 0) { - //dummy cif prep to ensure size for struct ffi_type is set - ffi_cif cif; - ffi_type *args[1]; - args[0] = &type->sequence.seqStruct; - ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args); - - *result = type; - return 0; - } else { - printf("DYN_TYPE: invalid type schema\n"); - return 1; - } - - return status; -} - -static int dynType_complex_create(char *schema, dyn_type **result) { - bool valid = true; - size_t len = strlen(schema); - int i = 0; - - dyn_type *type = calloc(1, sizeof(*type)); - type->type = DYN_TYPE_COMPLEX; - if (type == NULL) { - return -1; - } - - //count elements - int k; - size_t count = 0; - for (k=i; k < len && !isspace(schema[k]); k += 1) { - if (schema[k] == '[') { - k += 1; - } else if (schema[k] == '{') { - for (; schema[k] != '}'; k += 1) ; - } - count += 1; - } - - type->complex.ffiType.elements = calloc(count + 1, sizeof(ffi_type)); - type->complex.nested_types = calloc(count + 1, sizeof(dyn_type *)); - int index = 0; - for (k=0; k+i < len && !isspace(schema[k+i]); k += 1, index += 1) { - if (schema[k+i] == '[') { //sequence - //FIXME assume simple type - dyn_type *seqType; - char seq[2]; - seq[0] = schema[k+i+1]; - seq[1] = '\0'; - dynType_sequence_create(seq, &seqType); - - type->complex.nested_types[index] = seqType; - type->complex.ffiType.elements[index] = &seqType->sequence.seqStruct; - k += 1; - } else if (schema[k+i] == '{') { //nested complex - int start = k+i; - int end; - for (; schema[k+i] != '}' && k+i < len; k +=1) ; - if (schema[k+i] == '}') { - end = k+i; - size_t len = end-start + 1 -2; //without {} - char nested[len+1]; - memcpy(nested, schema + start + 1, len); - nested[len] = '\0'; - dyn_type *nestedType = NULL; - //TODO catch nested problem - dynType_complex_create(nested, &nestedType); //TODO use status result - type->complex.nested_types[index] = nestedType; - type->complex.ffiType.elements[index] = &ffi_type_pointer; - } else { - printf("invalid schema. object not closed '%s'\n", schema); - } - } else { - ffi_type *elType = NULL; - elType = dynType_ffiType_for(schema[k+i]); - if (elType != NULL) { - type->complex.ffiType.elements[index] = elType; - } else { - valid=false; - } - } - } - - - //eat { and } - int j; - int nrOfBraces = 0; - for (j = 0; j < len; j += 1) { //TODO make safer - if (isspace(schema[j]) && nrOfBraces == 0) { - break; - } - if (schema[j] == '{') { - nrOfBraces += 1; - } else if (schema[j] == '}') { - nrOfBraces -=1 ; - } - } - - char *names = schema + j +1; - - type->complex.names = calloc(count, sizeof(char *)); - k = 0; - char *savePtr; - char *token = NULL; - token = strtok_r(names, " ", &savePtr); - while (token != NULL && k < count) { - type->complex.names[k] = strdup(token); - k += 1; - token = strtok_r(NULL, " ", &savePtr); - } - if ( k != count || token != NULL) { - valid =false; - } - - if (valid) { - //dummy cif prep to ensure size for struct ffi_type is set - ffi_cif cif; - ffi_type *args[1]; - args[0] = &type->complex.ffiType; - ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args); - - *result = type; - return 0; - } else { - printf("DYN_TYPE: invalid type schema '%s'\n", schema); - return 1; - } -} - -int dynType_destroy(dyn_type *type) { - //TODO - return 0; -} - -void * dynType_alloc(dyn_type *type) { - assert(type != NULL); - void *result = NULL; - switch(type->type) { - case DYN_TYPE_COMPLEX : - result = calloc(1, type->complex.ffiType.size); - break; - case DYN_TYPE_SEQUENCE : - result = calloc(1, type->sequence.seqStruct.size); - break; - case DYN_TYPE_SIMPLE : - result = calloc(1, type->simple.ffiType->size); - break; - default : - printf("DYN_TYPE: unsupported type %i\n", type->type); - break; - } - return result; -} - -static ffi_type* dynType_ffiType_for(char c) { - ffi_type *type = NULL; - switch (c) { - case 'F' : - type = &ffi_type_float; - break; - case 'D' : - type = &ffi_type_double; - break; - case 'B' : - type = &ffi_type_sint8; - break; - case 'S' : - type = &ffi_type_sint16; - break; - case 'I' : - type = &ffi_type_sint32; - break; - case 'J' : - type = &ffi_type_sint64; - break; - default: - printf("unsupported type %c\n", c); - } - return type; -} - -static unsigned short get_offset_at(ffi_type *type, int index) { - unsigned short offset = 0; - - int i; - for (i = 0; i <= index && type->elements[i] != NULL; i += 1) { - size_t size = type->elements[i]->size; - unsigned short alignment = type->elements[i]->alignment; - int alignment_diff = offset % alignment; - if (alignment_diff > 0) { - offset += (alignment - alignment_diff); - } - if (i < index) { - offset += size; - } - } - - //TODO check if last element is not reached - - return offset; -} - -int dynType_complex_set_value_at(dyn_type *type, int index, void *start, void *in) { - assert(type->type == DYN_TYPE_COMPLEX); - char *loc = ((char *)start) + get_offset_at(&type->complex.ffiType, index); - size_t size = type->complex.ffiType.elements[index]->size; - memcpy(loc, in, size); - return 0; -} - -int dynType_complex_index_for_name(dyn_type *type, const char *name) { - assert(type->type == DYN_TYPE_COMPLEX); - int i; - int index = -1; - for (i = 0; type->complex.ffiType.elements[i] != NULL; i += 1) { - if (strcmp(type->complex.names[i], name) == 0) { - index = i; - break; - } - } - return index; -} - -char dynType_complex_schemaType_at(dyn_type *complexType, int index) { - assert(complexType->type == DYN_TYPE_COMPLEX); - - ffi_type *type = complexType->complex.ffiType.elements[index]; - dyn_type *nestedType = complexType->complex.nested_types[index]; - - return dynType_schemaType(nestedType, type); -} - -static char dynType_schemaType(dyn_type *dynType, ffi_type *ffiType) { - char result = '\0'; - if (dynType != NULL) { - switch(dynType->type) { - case DYN_TYPE_SIMPLE : - result = dynType_schemaType(NULL, dynType->simple.ffiType); - break; - case DYN_TYPE_COMPLEX : - result = '{'; - break; - case DYN_TYPE_SEQUENCE : - result = '['; - break; - } - } else if (ffiType != NULL) { - switch(ffiType->type) { - case FFI_TYPE_FLOAT : - result = 'F'; - break; - case FFI_TYPE_DOUBLE : - result = 'D'; - break; - case FFI_TYPE_SINT8 : - result = 'B'; - break; - case FFI_TYPE_SINT16 : - result = 'S'; - break; - case FFI_TYPE_SINT32 : - result = 'I'; - break; - case FFI_TYPE_SINT64 : - result = 'J'; - break; - default : - printf("Unsurported ffi type encounted. ffi type is %u\n", ffiType->type); - } - } - return result; -} - -dyn_type * dynType_complex_dynType_at(dyn_type *type, int index) { - assert(type->type == DYN_TYPE_COMPLEX); - return type->complex.nested_types[index]; -} - -void * dynType_complex_val_loc_at(dyn_type *type, void *inst_loc, int index) { - assert(type->type == DYN_TYPE_COMPLEX); - char *l = inst_loc; - return (void *)(l + get_offset_at(&type->complex.ffiType, index)); -} - -int dynType_simple_set_value(dyn_type *type, void *typeLoc, void *in) { - //TODO - return 0; -} - -static void dynType_print_sequence(dyn_type *type, int depth) { - assert(type->type == DYN_TYPE_SEQUENCE); - static const char const *SEQ_NAMES[] = {"_cap", "_len", "buf"}; - - int i; - for (i = 0; i < 3 ; i += 1) { - int k; - for (k = 0; k < depth; k += 1) { - printf("\t"); - } - printf("element %i with name '%s': size is %zu, allignment is %i and offset is %i\n", i, - SEQ_NAMES[i], type->sequence.seqStruct.elements[i]->size, type->sequence.seqStruct.elements[i]->alignment, get_offset_at(&type->sequence.seqStruct, i)); - } -} - -static void dynType_print_complex(dyn_type *type, int depth) { - assert(type->type == DYN_TYPE_COMPLEX); - int i, k; - for (k = 0; k < depth; k += 1) { - printf("\t"); - } - printf("printing ffi type. size is %zu, allignment is %i :\n", type->complex.ffiType.size, type->complex.ffiType.alignment); - for (i = 0; type->complex.ffiType.elements[i] != NULL; i += 1) { - for (k = 0; k < depth; k += 1) { - printf("\t"); - } - printf(" element %i with name '%s': size is %zu, allignment is %i and offset is %i\n", i, - type->complex.names[i], type->complex.ffiType.elements[i]->size, type->complex.ffiType.elements[i]->alignment, get_offset_at(&type->complex.ffiType, i)); - if (type->complex.nested_types[i] != NULL) { - dynType_print_any(type->complex.nested_types[i], depth + 1); - } - } -} - -static void dynType_print_any(dyn_type *type, int depth) { - switch (type->type) { - case DYN_TYPE_COMPLEX : - dynType_print_complex(type, depth); - break; - case DYN_TYPE_SEQUENCE : - dynType_print_sequence(type, depth); - break; - default : - printf("Unsurported dyn type %i\n", type->type); - } -} - -void dynType_print(dyn_type *type) { - dynType_print_any(type, 0); -} - -size_t dynType_size(dyn_type *type) { - assert(type != NULL); - size_t size = 0; - switch (type->type) { - case DYN_TYPE_COMPLEX : - size = type->complex.ffiType.size; - break; - case DYN_TYPE_SEQUENCE : - size = type->sequence.seqStruct.size; - break; - case DYN_TYPE_SIMPLE : - size = type->simple.ffiType->size; - break; - default : - printf("Error unsupported type %i\n", type->type); - break; - } - return size; -} - -int dynType_type(dyn_type *type) { - return type->type; -} - -static void dynType_trim(const char *str, size_t strLen, int *offset, int *len) { - int i; - for (i = 0; i < strLen && isspace(str[i]); i += 1) { - ; - } - *offset = i; - - for (i = strLen-1; i >= 0 && isspace(str[i]); i -= 1) { - ; - } - *len = i - (*offset) + 1; -} - - -void* dynType_sequence_init(dyn_type *type, void *inst, size_t cap) { - assert(type->type == DYN_TYPE_SEQUENCE); - char *result; - struct generic_sequence *seq = inst; - if (seq != NULL) { - size_t size = type->sequence.simpleType != NULL ? type->sequence.simpleType->size : dynType_size(type->sequence.dynType); - seq->buf = calloc(cap, size); - seq->_cap = cap; - result = seq->buf; - } - return result; -} - -char dynType_sequence_elementSchemaType(dyn_type *type) { - assert(type->type == DYN_TYPE_SEQUENCE); - return dynType_schemaType(type->sequence.dynType, type->sequence.simpleType); -} - -int dynType_sequence_append(dyn_type *type, void *inst, void *in) { - int index = -1; - struct generic_sequence *seq = inst; - if (seq->_len + 1 <= seq->_cap) { - index = seq->_len; - seq->_len += 1; - char *buf = seq->buf; - size_t elSize = type->sequence.dynType != NULL ? dynType_size(type->sequence.dynType) : type->sequence.simpleType->size; - size_t offset = (elSize * index); - memcpy(buf + offset, in, elSize); - } else { - printf("DYN_TYPE: sequence out of capacity\n"); - //todo resize ? - } - return index; -} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_type.h ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/dyn_type.h b/remote_services/dyn_type/dyn_type.h deleted file mode 100644 index c7fabc5..0000000 --- a/remote_services/dyn_type/dyn_type.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __DYN_TYPE_H_ -#define __DYN_TYPE_H_ - -#include <ffi.h> - - -/*Schema description - * - * Type = SimpleType | ComplexType | ArrayType - * Name = alpha[(alpha|numeric)*] - * SPACE = ' ' - * - * SimplesTypes (based on java bytecode method signatures) - * //Java based: - * B char - * C (not supported) - * D double - * F float - * I int //TODO use int32_t instead? - * J long //TODO use int64_t intead? - * S short //TODO use int16_t instead? - * V void - * Z boolean - * //Extended - * b unsigned char - * i unsigned int (see I) - * j unsigned long (see J) - * s unsigned short (see S) - * P pointer - * T char* string - * - * - * ComplexTypes - * {[Type]+ [(Name)(SPACE)]+} - * - * NOTE MAYBE SUPPORT STRUCT BY VALUE -> - * <[Type]+ [(Name)(SPACE)]+> - * - * SequenceType - * [(Type) - * - * examples - * "{DDII a b c d}" -> struct { double a; double b; int c; int d; }; - * "{DD{FF c1 c2} a b c" -> struct { double a; double b; struct c { float c1; float c2; }; }; - * - * - */ - -#define DYN_TYPE_SIMPLE 1 -#define DYN_TYPE_COMPLEX 2 -#define DYN_TYPE_SEQUENCE 3 - -typedef struct _dyn_type dyn_type; - -/* TODO MOVE TO PRIVATE HEADER */ -struct _dyn_type { - int type; - union { - struct { - ffi_type *ffiType; - } simple; - - struct { - ffi_type ffiType; - char **names; - dyn_type **nested_types; - } complex; - - struct { - ffi_type seqStruct; - dyn_type *dynType; //set if sequence is of a complex type - ffi_type *simpleType; //set if sequence is of a simple type - } sequence; - }; -}; - - -int dynType_create(const char *schema, dyn_type **type); -int dynType_destroy(dyn_type *type); - -//generic -void dynType_print(dyn_type *type); -size_t dynType_size(dyn_type *type); -int dynType_type(dyn_type *type); -void * dynType_alloc(dyn_type *type); -//TODO void dynType_free(dyn_type *type, void *inst); - -//complex -int dynType_complex_index_for_name(dyn_type *type, const char *name); -char dynType_complex_schemaType_at(dyn_type *type, int index); -dyn_type * dynType_complex_dynType_at(dyn_type *type, int index); -void * dynType_complex_val_loc_at(dyn_type *type, void *inst_loc, int index); -int dynType_complex_set_value_at(dyn_type *type, int index, void *start_loc_type, void *in); - -//sequence -void * dynType_sequence_init(dyn_type *type, void *seqInst, size_t cap); //note assume seq struct at seqLoc. only allocates buf -char dynType_sequence_elementSchemaType(dyn_type *type); -int dynType_sequence_append(dyn_type *type, void *inst, void *in); - -//simple -int dynType_simple_set_value(dyn_type *type, void *typeLoc, void *in); - - -#endif http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/func_tests.c ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/func_tests.c b/remote_services/dyn_type/func_tests.c deleted file mode 100644 index 95811d7..0000000 --- a/remote_services/dyn_type/func_tests.c +++ /dev/null @@ -1,66 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#include "dyn_function.h" - -#define EXAMPLE1_SCHEMA "example(III)I" -int32_t example1(int32_t a, int32_t b, int32_t c) { - printf("example1 called with a:%i, b:%i, c:%i\n", a, b, c); - return 1; -} - -#define EXAMPLE2_SCHEMA "example(I{IID val1 val2 val3}D)D" -struct example2_arg { - int32_t val1; - int32_t val2; - double val3; -}; - -double example2(int32_t arg1, struct example2_arg *arg2, double arg3) { - printf("example2 called with arg1:%i, arg2:{val1:%i, val2:%i, val3:%f}, arg3:%f\n", arg1, arg2->val1, arg2->val2, arg2->val3, arg3); - return 2.2; -} - - -int main() { - dyn_function_type *dynFunc = NULL; - int rc; - - rc = dynFunction_create(EXAMPLE1_SCHEMA, (void *)example1, &dynFunc); - if (rc == 0 ) { - int32_t a = 2; - int32_t b = 4; - int32_t c = 8; - void *values[3]; - int32_t rVal = 0; - values[0] = &a; - values[1] = &b; - values[2] = &c; - dynFunction_call(dynFunc, &rVal, values); - dynFunction_destroy(dynFunc); - dynFunc = NULL; - } else { - printf("Example 1 failed\n"); - } - - rc = dynFunction_create(EXAMPLE2_SCHEMA, (void *)example2, &dynFunc); - if (rc == 0 ) { - int32_t arg1 = 2; - struct example2_arg complexVal = { .val1 = 2, .val2 = 3, .val3 = 4.1 }; - struct example2_arg *arg2 = &complexVal; - double arg3 = 8.1; - double returnVal = 0; - void *values[3]; - values[0] = &arg1; - values[1] = &arg2; - values[2] = &arg3; - dynFunction_call(dynFunc, &returnVal, values); - dynFunction_destroy(dynFunc); - dynFunc = NULL; - } else { - printf("Example 3 failed\n"); - } -} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/json_serializer.c ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/json_serializer.c b/remote_services/dyn_type/json_serializer.c deleted file mode 100644 index e198445..0000000 --- a/remote_services/dyn_type/json_serializer.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "json_serializer.h" - -#include <jansson.h> -#include <assert.h> - -static int json_serializer_writeObject(dyn_type *type, json_t *object, void **result); -static void json_serializer_writeObjectMember(dyn_type *type, const char *name, json_t *val, void *inst); -static void json_serializer_writeSequence(json_t *array, dyn_type *seq, void *seqLoc); - -int json_deserialize(dyn_type *type, const char *input, void **result) { - //FIXME function is assuming complex type - int status = 0; - - - json_error_t error; - json_t *root = json_loads(input, JSON_DECODE_ANY, &error); - - if (root != NULL) { - status = json_serializer_writeObject(type, root, result); - json_decref(root); - } else { - status = 1; - printf("JSON_SERIALIZER: error parsing json input '%s'. Error is %s\n", input, error.text); - } - - return status; -} - -static int json_serializer_writeObject(dyn_type *type, json_t *object, void **result) { - assert(object != NULL); - int status = 0; - - void *inst = dynType_alloc(type); - json_t *value; - const char *key; - - if (inst != NULL) { - json_object_foreach(object, key, value) { - json_serializer_writeObjectMember(type, key, value, inst); - } - *result = inst; - } else { - status = 1; - printf("JSON_SERIALIZER: Error allocating memory\n"); - } - - return status; -} - -static void json_serializer_writeObjectMember(dyn_type *type, const char *name, json_t *val, void *inst) { - //TODO rename to complex. write generic write - int index = dynType_complex_index_for_name(type, name); - char charType = dynType_complex_schemaType_at(type, index); - void *valp = dynType_complex_val_loc_at(type, inst, index); - - - float *f; - double *d; - char *c; - short *s; - int *i; - long *l; - dyn_type *nested; - - switch (charType) { - case 'F' : - f = valp; - *f = json_real_value(val); - break; - case 'D' : - d = valp; - *d = json_real_value(val); - break; - case 'B' : - c = valp; - *c = json_integer_value(val); - break; - case 'S' : - s = valp; - *s = json_integer_value(val); - break; - case 'I' : - i = valp; - *i = json_integer_value(val); - break; - case 'J' : - l = valp; - *l = json_integer_value(val); - break; - case '[' : - nested = dynType_complex_dynType_at(type, index); - json_serializer_writeSequence(val, nested, valp); - break; - case '{' : - nested = dynType_complex_dynType_at(type, index); - json_serializer_writeObject(nested, val, (void **)valp); - break; - default : - printf("JSON_SERIALIZER: error provided type '%c' not supported\n", charType); - printf("Skipping\n"); - } -} - -static void json_serializer_writeSequence(json_t *array, dyn_type *seq, void *seqLoc) { - assert(dynType_type(seq) == DYN_TYPE_SEQUENCE); - size_t size = json_array_size(array); - //char seqType = dynType_sequence_elementSchemaType(seq); - - dynType_sequence_init(seq, seqLoc, size); //seq is already allocated. only need to allocate the buf - - //assuming int - int32_t i; - int index; - json_t *val; - json_array_foreach(array, index, val) { - i = json_number_value(val); - dynType_sequence_append(seq, seqLoc, &i); - } -} - -int json_serialize(dyn_type *type, void *input, char **output, size_t *size) { - return 0; -} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/json_serializer.h ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/json_serializer.h b/remote_services/dyn_type/json_serializer.h deleted file mode 100644 index edc87af..0000000 --- a/remote_services/dyn_type/json_serializer.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __JSON_SERIALIZER_H_ -#define __JSON_SERIALIZER_H_ - -#include "dyn_type.h" - -int json_deserialize(dyn_type *type, const char *input, void **result); -int json_serialize(dyn_type *type, void *input, char **output, size_t *size); - -#endif http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/struct_tests.c ---------------------------------------------------------------------- diff --git a/remote_services/dyn_type/struct_tests.c b/remote_services/dyn_type/struct_tests.c deleted file mode 100644 index ecf1fd4..0000000 --- a/remote_services/dyn_type/struct_tests.c +++ /dev/null @@ -1,159 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#include <ffi.h> - -#include "dyn_type.h" -#include "json_serializer.h" - -/*********** example 1 ************************/ -/** struct type ******************************/ -const char *example1_schema = "{DJISF a b c d e}"; - -const char *example1_input = "{ \ - \"a\" : 1.0, \ - \"b\" : 22, \ - \"c\" : 32, \ - \"d\" : 42, \ - \"e\" : 4.4 \ -}"; - -struct example1 { - double a; //0 - int64_t b; //1 - int32_t c; //2 - int16_t d; //3 - float e; //4 -}; - -void print_example1(void *data) { - struct example1 *ex = data; - printf("example1: a:%f, b:%li, c:%i, d:%i, e:%f\n", ex->a, ex->b, ex->c, ex->d, ex->e); -} - -/*********** example 2 ************************/ -/** struct type with some extra whitespace*/ -const char *example2_schema = " { BJJDFD byte long1 long2 double1 float1 double2 } "; - -const char *example2_input = "{ \ - \"byte\" : 42, \ - \"long1\" : 232, \ - \"long2\" : 242, \ - \"double1\" : 4.2, \ - \"float1\" : 3.2, \ - \"double2\" : 4.4 \ -}"; - -struct example2 { - char byte; //0 - int64_t long1; //1 - int64_t long2; //2 - double double1; //3 - float float1; //4 - double double2; //5 -}; - -void print_example2(void *data) { - struct example2 *ex = data; - printf("example2: byte:%i, long1:%li, long2:%li, double1:%f, float1:%f, double2:%f\n", ex->byte, ex->long1, ex->long2, ex->double1, ex->float1, ex->double2); -} - - -/*********** example 3 ************************/ -/** sequence with a simple type **************/ -const char *example3_schema = "{[I numbers}"; - -const char *example3_input = "{ \ - \"numbers\" : [22,32,42] \ -}"; - -struct example3 { - struct { - uint32_t _cap; - uint32_t _len; - int32_t *buf; - } numbers; -}; - -void print_example3(void *data) { - struct example3 *ex = data; - printf("example3: numbers length is %u and cap is %u and pointer buf is %p\n", ex->numbers._len, ex->numbers._cap, ex->numbers.buf); - int i; - for (i = 0; i < ex->numbers._len; i += 1) { - printf("\telement %i : %i\n", i, ex->numbers.buf[i]); - } -} - -/*********** example 4 ************************/ -/** structs within a struct (by reference)*******/ -//TODO think about references in schema e.g "{Lleaf;Lleaf; left right}\nleaf{IDD index val1 val2}" -const char *example4_schema = "{{IDD index val1 val2}{IDD index val1 val2} left right}"; - -const char *example4_input = "{ \ - \"left\" : {\"index\":1, \"val1\":1.0, \"val2\":2.0 }, \ - \"right\" : {\"index\":2, \"val1\":5.0, \"val2\":4.0 } \ -}"; - -struct leaf { - int32_t index; - double val1; - double val2; -}; - -struct example4 { - struct leaf *left; - struct leaf *right; -}; - -void print_example4(void *data) { - struct example4 *ex = data; - printf("example4: left { index:%i, val1:%f, val2:%f }, right { index;%i, val1:%f, val2:%f }\n", ex->left->index, ex->left->val1, ex->left->val2, ex->right->index, ex->right->val1, ex->right->val2); -} - -int main() { - printf("Starting ffi struct test\n"); - dyn_type *type; - void *inst; - - type = NULL; - inst = NULL; - dynType_create(example1_schema, &type); - printf("-- example 1\n"); - dynType_print(type); - json_deserialize(type, example1_input, &inst); - print_example1(inst); - printf("--\n\n"); - - - type = NULL; - inst = NULL; - dynType_create(example2_schema, &type); - printf("-- example 2\n"); - dynType_print(type); - json_deserialize(type, example2_input, &inst); - print_example2(inst); - printf("--\n\n"); - - type = NULL; - inst = NULL; - dynType_create(example3_schema, &type); - printf("-- example 3\n"); - dynType_print(type); - json_deserialize(type, example3_input, &inst); - print_example3(inst); - printf("--\n\n"); - - type = NULL; - inst = NULL; - dynType_create(example4_schema, &type); - printf("-- example 4\n"); - dynType_print(type); - json_deserialize(type, example4_input, &inst); - print_example4(inst); - printf("--\n\n"); - - return 0; -} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/dynamic_function_interface/CMakeLists.txt b/remote_services/dynamic_function_interface/CMakeLists.txt new file mode 100644 index 0000000..81e935e --- /dev/null +++ b/remote_services/dynamic_function_interface/CMakeLists.txt @@ -0,0 +1,40 @@ +# +# Licensed under Apache License v2. See LICENSE for more information. +# +find_package(Jansson REQUIRED) +find_package(CppUTest REQUIRED) +set(FFI_LIB /lib64/libffi.so) #TODO add findPackag for lib ffi + +include_directories( + ${CPPUTEST_INCLUDE_DIR} + ${JANSSON_INCLUDE_DIRS} + ${CMAKE_CURRENT_LIST_DIR} +) + +add_library(dfi + dyn_type.c + dyn_function.c + json_serializer.c + avro_descriptor_translator.c +) +target_link_libraries(dfi ${FFI_LIB} ${JANSSON_LIBRARY}) + + +add_executable(dfi_tests + tst/dyn_type_tests.cpp + tst/dyn_function_tests.cpp + tst/dyn_closure_tests.cpp + tst/json_serializer_tests.cpp + tst/avro_descriptor_translator_tests.cpp + tst/run_tests.cpp +) +target_link_libraries(dfi_tests dfi ${FFI_LIB} ${CPPUTEST_LIBRARY} ${JANSSON_LIBRARY}) + +add_custom_target(copy-input + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/schemas schemas +) +add_dependencies(dfi_tests copy-input) + +ADD_TARGET_FOR_TEST(dfi_tests) +SETUP_TARGET_FOR_COVERAGE(dfi_tests_cov dfi_tests ${CMAKE_BINARY_DIR}/coverage/dfi) + http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/avro_descriptor_translator.c ---------------------------------------------------------------------- diff --git a/remote_services/dynamic_function_interface/avro_descriptor_translator.c b/remote_services/dynamic_function_interface/avro_descriptor_translator.c new file mode 100644 index 0000000..9d52926 --- /dev/null +++ b/remote_services/dynamic_function_interface/avro_descriptor_translator.c @@ -0,0 +1,294 @@ +/** + * Licensed under Apache License v2. See LICENSE for more information. + */ +#include "descriptor_translator.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#include <jansson.h> + +static const int OK = 0; +static const int MEM_ERROR = 1; +static const int PARSE_ERROR = 2; +static const int INV_ARG_ERROR = 2; + +static int descriptorTranslator_createMethodDescriptor(interface_descriptor_type *desc, json_t *schema, const char *name, int index, json_t *message); +static int descriptorTranslator_parseMessage(json_t *schema, const char *name, json_t *message, bool asJavaSignature, char **descriptor); +static int descriptorTranslator_parseArgument(FILE *stream, json_t *schema, json_t *type); +static int descriptorTranslator_parseType(FILE *stream, json_t *schema, const char *typeName); + +int descriptorTranslator_create(const char *schemaStr, interface_descriptor_type **out) { + int status = OK; + + interface_descriptor_type *desc = calloc(1, sizeof(*desc)); + if (desc != NULL) { + TAILQ_INIT(&desc->methodDescriptors); + json_error_t error; + json_t *schema = json_loads(schemaStr, JSON_DECODE_ANY, &error); + + if (schema != NULL) { + //TODO + json_t *messages = json_object_get(schema, "messages"); + if (messages != NULL) { + const char *name; + json_t *message; + int rc = 0; + int index = 0; + json_object_foreach(messages, name, message) { + rc = descriptorTranslator_createMethodDescriptor(desc, schema, name, index++, message); + if (rc != OK) { + break; + } + } + } + //json_decref(schema); + } else { + status = PARSE_ERROR; + printf("AVRO_DESCRIPTOR_TRANSLATOR: error parsing json input '%s'. Error is %s\n", schemaStr, error.text); + } + } else { + status = MEM_ERROR; + } + + + if (status == 0) { + *out = desc; + } else if (status == MEM_ERROR) { + printf("AVRO_DESCRIPTOR_TRANSLATOR: error cannot allocate memory\n"); + descriptorTranslator_destroy(desc); + } else { + descriptorTranslator_destroy(desc); + } + return status; +} + +int descriptorTranslator_destroy(interface_descriptor_type *desc) { + int status = OK; + if (desc != NULL) { + //TODO free existing members + free(desc); + } else { + status = INV_ARG_ERROR; + } + return status; +} + +static int descriptorTranslator_createMethodDescriptor(interface_descriptor_type *desc, json_t *schema, const char *name, int index, json_t *message) { + int status = OK; + + method_descriptor_type *mDesc = calloc(1, sizeof(*mDesc)); + if (mDesc != NULL) { + mDesc->identifier = index; + status = descriptorTranslator_parseMessage(schema, name, message, false, &mDesc->descriptor); + if (status == OK) { + mDesc->name = strdup(name); + if (mDesc->name == NULL) { + status = MEM_ERROR; + } else { + status = descriptorTranslator_parseMessage(schema, name, message, true, &mDesc->strIdentifier); + } + } + } else { + status = MEM_ERROR; + } + + if (status == OK) { + TAILQ_INSERT_TAIL(&desc->methodDescriptors, mDesc, entries); + } else { + if (mDesc != NULL) { + if (mDesc->name != NULL) { + free(mDesc->name); + } + if (mDesc->descriptor != NULL) { + free(mDesc->descriptor); + } + if (mDesc->strIdentifier != NULL) { + free(mDesc->strIdentifier); + } + free(mDesc); + } + } + + return status; +} + +static int descriptorTranslator_parseMessage(json_t *schema, const char *name, json_t *message, bool asJavaSignature, char **descriptor) { + int status = OK; + //message -> { "request" : [ {"name":"<name>", "type":"<type>"} * ], "response":"<type>" } + //array -> "type":"array", "items:"<type>" + + char *ptr = NULL; + size_t ptrSize; + FILE *memStream = open_memstream(&ptr, &ptrSize); + + if (memStream != NULL) { + json_t *request = json_object_get(message, "request"); + fwrite(name, 1, strlen(name), memStream); + fputc('(', memStream); + if (!asJavaSignature) { + fputc('P', memStream); //handle + } + + if (request != NULL) { + size_t index; + json_t *arg; + json_array_foreach(request, index, arg) { + //json_t *name = json_object_get(arg, "name"); + json_t *type = json_object_get(arg, "type"); + if (type != NULL) { + status = descriptorTranslator_parseArgument(memStream, schema, type); + } else { + printf("expected type for request argument %zu for message %s\n", index, name); + status = PARSE_ERROR; + } + if (status != OK) { + break; + } + } + } else { + status = PARSE_ERROR; + printf("Expected request for message %s\n", name); + } + + json_t *response = json_object_get(message, "response"); + if (status == OK && response != NULL) { + if (asJavaSignature) { + fputc(')', memStream); + } else { + fputc('*', memStream); //output parameter + } + status = descriptorTranslator_parseArgument(memStream, schema, response); + } + + if (!asJavaSignature) { + fputc(')', memStream); + fputc('N', memStream); //error / exceptions + } + } else { + status = MEM_ERROR; + } + + if (memStream != NULL) { + fclose(memStream); + if (status == OK) { + *descriptor = ptr; + } else { + free(ptr); + } + } + + return status; +} + +static const char * const PRIMITIVE_INT = "int"; +static const char * const PRIMITIVE_LONG = "long"; +static const char * const PRIMITIVE_STRING = "string"; +static const char * const PRIMITIVE_BOOL = "boolean"; +static const char * const PRIMITIVE_FLOAT = "float"; +static const char * const PRIMITIVE_DOUBLE = "double"; +static const char * const PRIMITIVE_NULL = "null"; +static const char * const PRIMITIVE_BYTES = "bytes"; + +static int descriptorTranslator_parseArgument(FILE *stream, json_t *schema, json_t *type) { + int status = OK; + if (json_is_string(type)) { + const char *typeStr = json_string_value(type); + char t = '\0'; + if (strcmp(typeStr, PRIMITIVE_INT) == 0) { + t = 'I'; + } else if (strcmp(typeStr, PRIMITIVE_LONG) == 0) { + t = 'J'; + } else if (strcmp(typeStr, PRIMITIVE_STRING) == 0) { + t = 'T'; + } else if (strcmp(typeStr, PRIMITIVE_BOOL) == 0) { + t = 'Z'; + } else if (strcmp(typeStr, PRIMITIVE_FLOAT) == 0) { + t = 'F'; + } else if (strcmp(typeStr, PRIMITIVE_DOUBLE) == 0) { + t = 'D'; + } else if (strcmp(typeStr, PRIMITIVE_NULL) == 0) { + t = 'V'; + } else if (strcmp(typeStr, PRIMITIVE_BYTES) == 0) { + t = 'B'; + } else { + status = descriptorTranslator_parseType(stream, schema, typeStr); + } + if (t != '\0') { + fputc(t, stream); + } + } else { + json_t *subType = json_object_get(type, "type"); + json_t *items = json_object_get(type, "items"); + if (strcmp("array", json_string_value(subType)) == 0) { + //array + fputc('[', stream); + descriptorTranslator_parseArgument(stream, schema, items); + } else { + printf("sub type %s not supported\n", json_string_value(subType)); + status = PARSE_ERROR; + } + } + return status; +} + + +static int descriptorTranslator_parseType(FILE *stream, json_t *schema, const char *typeName) { + int status = OK; + + json_t *types = json_object_get(schema, "types"); + json_t *type = NULL; + if (json_is_array(types)) { + json_t *el; + int index; + json_array_foreach(types, index, el) { + const char *name = json_string_value(json_object_get(el, "name")); + if (strcmp(typeName, name) == 0) { + type = el; + break; + } + } + + if (el != NULL) { + fputc('{', stream); + json_t *fields = json_object_get(type, "fields"); + if (json_is_array(fields)) { + json_t *field; + json_array_foreach(fields, index, field) { + json_t *type = json_object_get(field, "type"); + status = descriptorTranslator_parseArgument(stream, schema, type); + if (status != OK) { + break; + } + } + if (status == OK) { + json_array_foreach(fields, index, field) { + const char *fieldName = json_string_value(json_object_get(field, "name")); + if (fieldName != NULL) { + fputc(' ', stream); + fwrite(fieldName, 1, strlen(fieldName), stream); + } else { + status = PARSE_ERROR; + printf("Expected name for field\n"); + break; + } + } + } + } else { + status = PARSE_ERROR; + printf("Expected array type"); + } + fputc('}', stream); + } else { + status = PARSE_ERROR; + printf("cannot find type with name %s\n", typeName); + } + } else { + status = PARSE_ERROR; + printf("Expected array type\n"); + } + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/descriptor_translator.h ---------------------------------------------------------------------- diff --git a/remote_services/dynamic_function_interface/descriptor_translator.h b/remote_services/dynamic_function_interface/descriptor_translator.h new file mode 100644 index 0000000..b75c8d7 --- /dev/null +++ b/remote_services/dynamic_function_interface/descriptor_translator.h @@ -0,0 +1,28 @@ +/** + * Licensed under Apache License v2. See LICENSE for more information. + */ +#ifndef __DESCRIPTOR_TRANSLATOR_H_ +#define __DESCRIPTOR_TRANSLATOR_H_ + +#include <sys/queue.h> + +typedef struct _interface_descriptor_type interface_descriptor_type; + +struct _interface_descriptor_type { + TAILQ_HEAD(, _method_descriptor_type) methodDescriptors; +}; + +typedef struct _method_descriptor_type method_descriptor_type; + +struct _method_descriptor_type { + int identifier; + char *strIdentifier; + char *descriptor; + char *name; + TAILQ_ENTRY(_method_descriptor_type) entries; +}; + +int descriptorTranslator_create(const char *schemaStr, interface_descriptor_type **out); +int descriptorTranslator_destroy(interface_descriptor_type *desc); + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dfi_log_util.h ---------------------------------------------------------------------- diff --git a/remote_services/dynamic_function_interface/dfi_log_util.h b/remote_services/dynamic_function_interface/dfi_log_util.h new file mode 100644 index 0000000..85208ff --- /dev/null +++ b/remote_services/dynamic_function_interface/dfi_log_util.h @@ -0,0 +1,50 @@ +/** + * Licensed under Apache License v2. See LICENSE for more information. + */ +#ifndef _DFI_LOG_UTIL_H_ +#define _DFI_LOG_UTIL_H_ + +#define DFI_TEST(cmp) printf("%s", cmp); + +typedef void (*logf_ft)(void *handle, int level, const char *file, int line, const char *format, ...); + +#define DFI_SETUP_LOG_HEADER(cmp) \ + void cmp ## _logSetup(logf_ft logf, void *handle, int currentLogLevel); + +#define DFI_SETUP_LOG(cmp) \ + static logf_ft g_logf = NULL; \ + static void *g_logHandle = NULL; \ + static int g_currentLogLevel = 1; \ + \ + void cmp ## _logSetup(logf_ft logf, void *handle, int currentLogLevel) { \ + g_currentLogLevel = currentLogLevel; \ + g_logHandle = handle; \ + g_logf = logf; \ + } + +#define LOG_LVL_ERROR 1 +#define LOG_LVL_WARNING 2 +#define LOG_LVL_INFO 3 +#define LOG_LVL_DEBUG 4 + +#define LOG_ERROR(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_ERROR) { \ + g_logf(g_logHandle, LOG_LVL_ERROR, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#define LOG_WARNING(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_WARNING) { \ + g_logf(g_logHandle, LOG_LVL_WARNING, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#define LOG_INFO(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_INFO) { \ + g_logf(g_logHandle, LOG_LVL_INFO, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#define LOG_DEBUG(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_DEBUG) { \ + g_logf(g_logHandle, LOG_LVL_DEBUG, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dyn_function.c ---------------------------------------------------------------------- diff --git a/remote_services/dynamic_function_interface/dyn_function.c b/remote_services/dynamic_function_interface/dyn_function.c new file mode 100644 index 0000000..116803f --- /dev/null +++ b/remote_services/dynamic_function_interface/dyn_function.c @@ -0,0 +1,185 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#include "dyn_function.h" + +#include <stdio.h> +#include <stdarg.h> +#include <strings.h> +#include <string.h> +#include <stdlib.h> + +#include <ffi.h> + +#include "dyn_type.h" +#include "dfi_log_util.h" + +DFI_SETUP_LOG(dynFunction) + +struct _dyn_function_type { + dyn_type *arguments; + dyn_type *funcReturn; + void (*fn)(void); + ffi_cif cif; +}; + +struct _dyn_closure_type { + dyn_type *arguments; + dyn_type *funcReturn; + ffi_cif cif; + ffi_closure *ffiClosure; + void (*fn)(void); + void (*bind)(void *userData, void *args[], void *ret); + void *userData; +}; + + +static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *funcReturn); +static int dynFunction_parseDescriptor(const char *functionDescriptor, dyn_type **arguments, dyn_type **funcReturn); +static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData); + +int dynFunction_create(const char *descriptor, void (*fn)(void), dyn_function_type **out) { + int status = 0; + dyn_function_type *dynFunc = NULL; + LOG_DEBUG("Creating dyn function for descriptor '%s'\n", descriptor); + + dynFunc = calloc(1, sizeof(*dynFunc)); + + if (dynFunc != NULL) { + dynFunc->fn = fn; + status = dynFunction_parseDescriptor(descriptor, &dynFunc->arguments, &dynFunc->funcReturn); + if (status == 0) { + status = dynFunction_initCif(&dynFunc->cif, dynFunc->arguments, dynFunc->funcReturn); + } + } else { + status = 2; + } + + if (status == 0) { + *out = dynFunc; + } else { + if (status == 1) { + LOG_ERROR("Cannot parse func descriptor '%s'\n", descriptor); + } else { + LOG_ERROR("Cannot allocate memory for dyn function\n"); + } + } + return status; +} + +static int dynFunction_parseDescriptor(const char *descriptor, dyn_type **arguments, dyn_type **funcReturn) { + int status = 0; + char *startPos = index(descriptor, '('); + char *endPos = index(descriptor, ')'); + + if (startPos != NULL && endPos != NULL) { + int len = endPos - startPos - 1; + + //TODO add names (arg001, arg002, etc) + char argDesc[len+3]; + argDesc[0] = '{'; + argDesc[len+1] = '}'; + memcpy(argDesc+1, startPos +1, len); + argDesc[len+2] = '\0'; + LOG_DEBUG("argDesc is '%s'\n", argDesc); + + len = strlen(endPos); + char returnDesc[len+1]; + memcpy(returnDesc, endPos + 1, len); + returnDesc[len] = '\0'; + LOG_DEBUG("returnDesc is '%s'\n", returnDesc); + + status = dynType_create(argDesc, arguments); + if (status == 0) { + status = dynType_create(returnDesc, funcReturn); + } + } else { + status = 1; + } + + return status; +} + +static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *returnValue) { + int result = 0; + + int count = 0; + int i; + for (i = 0; arguments->ffiType->elements[i] != NULL; i += 1) { + count += 1; + } + + ffi_type **args = arguments->ffiType->elements; + ffi_type *returnType = returnValue->ffiType; + + int ffiResult = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, returnType, args); + if (ffiResult != FFI_OK) { + result = 1; + } + + return result; +} + +int dynFunction_destroy(dyn_function_type *dynFunc) { + int result = 0; + LOG_WARNING("TODO destroy dyn dync\n"); + return result; +} + +int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues) { + ffi_call(&dynFunc->cif, dynFunc->fn, returnValue, argValues); + return 0; +} + +static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData) { + dyn_closure_type *dynClosure = userData; + dynClosure->bind(dynClosure->userData, args, ret); +} + +int dynClosure_create(const char *descriptor, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out) { + int status = 0; + dyn_closure_type *dynClosure = calloc(1, sizeof(*dynClosure)); + if (dynClosure != NULL) { + dynClosure->bind = bind; + dynClosure->userData = userData; + status = dynFunction_parseDescriptor(descriptor, &dynClosure->arguments, &dynClosure->funcReturn); + if (status == 0) { + status = dynFunction_initCif(&dynClosure->cif, dynClosure->arguments, dynClosure->funcReturn); + if (status == 0) { + dynClosure->ffiClosure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&dynClosure->fn); + if (dynClosure->ffiClosure != NULL) { + int rc = ffi_prep_closure_loc(dynClosure->ffiClosure, &dynClosure->cif, dynClosure_ffiBind, dynClosure, dynClosure->fn); + if (rc != FFI_OK) { + status = 1; + } + } else { + status = 2; + } + } + } + } else { + status = 2; + } + + if (status == 0) { + *out = dynClosure; + } + return status; +} + +int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void (**fn)(void)) { + int status = 0; + if (dynClosure != NULL) { + (*fn) = dynClosure->fn; + } else { + status = 1; + } + return status; +} + + +int dynClosure_destroy(dyn_closure_type *dynClosure) { + int result = 0; + LOG_WARNING("TODO destroy closure\n"); + return result; +} http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dyn_function.h ---------------------------------------------------------------------- diff --git a/remote_services/dynamic_function_interface/dyn_function.h b/remote_services/dynamic_function_interface/dyn_function.h new file mode 100644 index 0000000..976f2d7 --- /dev/null +++ b/remote_services/dynamic_function_interface/dyn_function.h @@ -0,0 +1,30 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#ifndef __DYN_FUNCTION_H_ +#define __DYN_FUNCTION_H_ + +#include <ffi.h> +#include "dyn_type.h" +#include "dfi_log_util.h" + +/** + * Uses the following schema + * (Name)([Type]*)Type + * e.g add(DD)D or sum({[D[D setA setB})D + */ + +typedef struct _dyn_function_type dyn_function_type; +typedef struct _dyn_closure_type dyn_closure_type; + +DFI_SETUP_LOG_HEADER(dynFunction); + +int dynFunction_create(const char *descriptor, void (*fn)(void), dyn_function_type **dynFunc); +int dynFunction_destroy(dyn_function_type *dynFunc); +int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues); + +int dynClosure_create(const char *descriptor, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out); +int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void(**fn)(void)); +int dynClosure_destroy(dyn_closure_type *dynClosure); + +#endif