Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-237_rsa-ffi 7f3383247 -> bdeba2bcb


http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dyn_type.c
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_type.c 
b/remote_services/dynamic_function_interface/dyn_type.c
new file mode 100644
index 0000000..5ad18f4
--- /dev/null
+++ b/remote_services/dynamic_function_interface/dyn_type.c
@@ -0,0 +1,822 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "dyn_type.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <errno.h>
+
+static int dynType_createWithStream(FILE *stream, dyn_type *parent, dyn_type 
**type);
+static void dynType_clear(dyn_type *type);
+static void dynType_clearComplex(dyn_type *type);
+static void dynType_clearSequence(dyn_type *type);
+static void dynType_clearTypedPointer(dyn_type *type);
+
+static ffi_type * dynType_ffiTypeFor(int c);
+static dyn_type * dynType_findType(dyn_type *type, char *name);
+static int dynType_parse(FILE *stream, dyn_type *type);
+static int dynType_parseComplex(FILE *stream, dyn_type *type);
+static int dynType_parseName(FILE *stream, char **name);
+static int dynType_parseNestedType(FILE *stream, dyn_type *type);
+static int dynType_parseReference(FILE *stream, dyn_type *type);
+static int dynType_parseRefByValue(FILE *stream, dyn_type *type);
+static int dynType_parseSequence(FILE *stream, dyn_type *type);
+static int dynType_parseSimple(int c, dyn_type *type);
+static int dynType_parseTypedPointer(FILE *stream, dyn_type *type);
+static void dynType_prepCif(ffi_type *type);
+static unsigned short dynType_getOffset(dyn_type *type, int index);
+
+static void dynType_printAny(char *name, dyn_type *type, int depth);
+static void dynType_printComplex(char *name, dyn_type *type, int depth);
+static void dynType_printSequence(char *name, dyn_type *type, int depth);
+static void dynType_printSimple(char *name, dyn_type *type, int depth);
+static void dynType_printTypedPointer(char *name, dyn_type *type, int depth);
+static void printDepth(int depth);
+
+static void dynType_printTypes(dyn_type *type);
+static void dynType_printComplexType(dyn_type *type);
+static void dynType_printSimpleType(dyn_type *type);
+
+struct generic_sequence {
+    uint32_t cap;
+    uint32_t len;
+    void *buf;
+};
+
+static const int DT_OK = 0;
+static const int DT_ERROR = 1;
+static const int DT_MEM_ERROR = 2;
+static const int DT_PARSE_ERROR = 3;
+
+#define DT_LOG_ERROR    1
+#define DT_LOG_WARNING  2
+#define DT_LOG_INFO     3
+#define DT_LOG_DEBUG    4
+#define DT_LOG(lvl, msg, ...) if(g_logf != NULL) { \
+    g_logf(g_logHandle, (lvl), __FILE__, __LINE__, (msg),  ##__VA_ARGS__);  \
+}
+
+static void (*g_logf)(void *handle, int level, const char *file, int line, 
const char *msgFormat, ...) = NULL;
+static void *g_logHandle = NULL;
+
+void dynType_setupLogger(void (*logf)(void *handle, int level, const char 
*file, int line, const char *msgFormat, ...), void *handle) {
+    g_logHandle = handle;
+    g_logf = logf;
+}
+
+int dynType_create(const char *descriptor, dyn_type **type) {
+    int status = DT_OK;
+    FILE *stream = fmemopen((char *)descriptor, strlen(descriptor), "r");
+    if (stream != NULL) {
+        status = dynType_createWithStream(stream, NULL, type);
+        if (status == DT_OK) {
+            int c = fgetc(stream);
+            if (c != '\0' && c != EOF) {
+                status = DT_PARSE_ERROR;
+                DT_LOG(DT_LOG_ERROR, "Expected EOF got %c", c);
+            }
+        } 
+        fclose(stream);
+    } else {
+        status = DT_ERROR;
+        DT_LOG(DT_LOG_ERROR, "Error creating mem stream for descriptor string. 
%s", strerror(errno)); 
+    }
+    return status;
+}
+
+static int dynType_createWithStream(FILE *stream, dyn_type *parent, dyn_type 
**result) {
+    int status = DT_OK;
+    dyn_type *type = calloc(1, sizeof(*type));
+    if (type != NULL) {
+        type->parent = parent;
+        type->type = DYN_TYPE_INVALID;
+        TAILQ_INIT(&type->nestedTypesHead);
+        status = dynType_parse(stream, type);        
+        if (status == DT_OK) {
+            *result = type;
+        } else {
+            dynType_destroy(type);
+        }
+    } else {
+        status = DT_MEM_ERROR;
+        DT_LOG(DT_LOG_ERROR, "Error allocating memory for type");
+    }
+    return status;
+}
+
+static int dynType_parse(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+
+    int c = fgetc(stream);
+    switch(c) {
+        case 'T' :
+            status = dynType_parseNestedType(stream, type);
+            if (status == DT_OK) {
+                status = dynType_parse(stream, type);
+            } 
+            break;
+        case 'L' :
+            status = dynType_parseReference(stream, type);
+            break;
+        case 'l' :
+            status = dynType_parseRefByValue(stream, type);
+            break;
+        case '{' :
+            status = dynType_parseComplex(stream, type);
+            break;
+        case '[' :
+            status = dynType_parseSequence(stream, type);
+            break;
+        case '*' :
+            status = dynType_parseTypedPointer(stream, type);
+            break;
+        default :
+            status = dynType_parseSimple(c, type);
+            break;
+    }
+
+    return status;
+}
+
+static int dynType_parseComplex(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+    type->type = DYN_TYPE_COMPLEX;
+    type->descriptor = '{';
+    type->ffiType = &type->complex.structType;
+    TAILQ_INIT(&type->complex.entriesHead);
+
+    int c = fgetc(stream);
+    struct complex_type_entry *entry = NULL;
+    while (c != ' ' && c != '}') {
+        ungetc(c,stream);
+        entry = calloc(1, sizeof(*entry));
+        if (entry != NULL) {
+            entry->type.parent = type;
+            entry->type.type = DYN_TYPE_INVALID;
+            TAILQ_INIT(&entry->type.nestedTypesHead);
+            TAILQ_INSERT_TAIL(&type->complex.entriesHead, entry, entries);
+            status = dynType_parse(stream, &entry->type);
+        } else {
+            status = DT_MEM_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error allocating memory for type");
+        }
+        c = fgetc(stream);
+    }
+
+    entry = TAILQ_FIRST(&type->complex.entriesHead);
+    char *name = NULL;
+    while (c == ' ' && entry != NULL) {
+        status = dynType_parseName(stream, &name);
+        if (status == DT_OK) {
+            entry->name = name;
+            entry = TAILQ_NEXT(entry, entries);
+        } else {
+            break;
+        }
+        c = getc(stream); 
+    }
+
+    int count = 0;
+    TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+        count +=1;
+    }
+
+    if (status == DT_OK) {
+        type->complex.structType.type =  FFI_TYPE_STRUCT;
+        type->complex.structType.elements = calloc(count + 1, 
sizeof(ffi_type));
+        type->complex.structType.elements[count] = NULL;
+        if (type->complex.structType.elements != NULL) {
+            int index = 0;
+            TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+                type->complex.structType.elements[index++] = 
entry->type.ffiType;
+            }
+        } else {
+            status = DT_MEM_ERROR;
+            //T\nODO log: error allocating memory
+        }
+    }
+
+    if (status == DT_OK) {
+        type->complex.types = calloc(count, sizeof(dyn_type *));
+        if (type != NULL) {
+            int index = 0;
+            TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+                type->complex.types[index++] = &entry->type;
+            }
+        } else {
+            status = DT_MEM_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error allocating memory for type")
+        }
+    }
+
+    if (status == DT_OK) {
+        dynType_prepCif(type->ffiType);
+    }
+
+
+    return status;
+}
+
+static int dynType_parseName(FILE *stream, char **result) {
+    int status = DT_OK;
+
+    char *buf = NULL;
+    size_t size = 0;
+    FILE *name = open_memstream(&buf, &size);
+
+    if (name != NULL) { 
+        int c = getc(stream);
+        while (isalnum(c) || c == '_') {
+            fputc(c, name); 
+            c = getc(stream);
+        }
+        fflush(name);
+        fclose(name);
+        *result = buf;
+        ungetc(c, stream);
+    } else {
+        status = DT_ERROR;
+        DT_LOG(DT_LOG_ERROR, "Error creating mem stream for name. %s", 
strerror(errno));
+    }
+
+    return status;
+}
+
+static int dynType_parseNestedType(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+    char *name = NULL;
+    struct nested_entry *entry = NULL; 
+
+    entry = calloc(1, sizeof(*entry));
+    if (entry != NULL) {
+        entry->type.parent = type;
+        entry->type.type = DYN_TYPE_INVALID;
+        TAILQ_INIT(&entry->type.nestedTypesHead);
+        TAILQ_INSERT_TAIL(&type->nestedTypesHead, entry, entries);
+        status = dynType_parseName(stream, &name);
+        entry->type.name = name;
+    } else {
+        status = DT_MEM_ERROR;  
+    }     
+
+    if (status == DT_OK) {
+        int c = fgetc(stream);
+        if (c != '=') {
+            status = DT_PARSE_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error parsing nested type expected '=' got 
'%c'", c);
+        }
+    }
+
+    if (status == DT_OK) {
+        status = dynType_parse(stream, &entry->type);
+        int c = fgetc(stream);
+        if (c != ';') {
+            status = DT_PARSE_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Expected ';' got '%c'\n", c);
+        }
+    }
+
+    return status;
+}
+
+static int dynType_parseReference(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+    type->type = DYN_TYPE_TYPED_POINTER;
+    type->descriptor = '*';
+
+    type->ffiType = &ffi_type_pointer;
+    type->typedPointer.typedType =  NULL;
+
+    dyn_type *subType = calloc(1, sizeof(*subType));
+
+    if (subType != NULL) {
+        type->typedPointer.typedType = subType;
+        subType->parent = type;
+        subType->type = DYN_TYPE_INVALID;
+        TAILQ_INIT(&subType->nestedTypesHead);
+        status = dynType_parseRefByValue(stream, subType);
+    } else {
+        status = DT_MEM_ERROR;
+        DT_LOG(DT_LOG_ERROR, "Error allocating memory for subtype\n");
+    }
+
+    return status;
+}
+
+static int dynType_parseRefByValue(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+    type->type = DYN_TYPE_REF;
+    type->descriptor = 'l';
+
+    char *name = NULL;
+    status = dynType_parseName(stream, &name);
+    if (status == DT_OK) {
+        dyn_type *ref = dynType_findType(type, name);
+        free(name);
+        if (ref != NULL) {
+            type->ref.ref = ref;
+        } else {
+            status = DT_PARSE_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error cannot find type '%s'", name);
+        }
+    } 
+
+    if (status == DT_OK) {
+        int c = fgetc(stream);
+        if (c != ';') {
+            status = DT_PARSE_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error expected ';' got '%c'", c);
+        } 
+    }
+
+    return status;
+}
+
+static ffi_type *seq_types[] = {&ffi_type_uint32, &ffi_type_uint32, 
&ffi_type_pointer, NULL};
+
+static int dynType_parseSequence(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+    type->type = DYN_TYPE_SEQUENCE;
+    type->descriptor = '[';
+
+    type->sequence.seqType.elements = seq_types;
+    status = dynType_createWithStream(stream, type, &type->sequence.itemType);
+
+    if (status == DT_OK) {
+        type->ffiType = &type->sequence.seqType;
+        dynType_prepCif(&type->sequence.seqType);
+    }
+
+    return status;
+}
+
+static int dynType_parseSimple(int c, dyn_type *type) {
+    int status = DT_OK;
+    ffi_type *ffiType = dynType_ffiTypeFor(c);
+    if (ffiType != NULL) {
+        type->type = DYN_TYPE_SIMPLE;
+        type->descriptor = c;
+        type->ffiType = ffiType;
+    } else {
+        status = DT_PARSE_ERROR;
+        DT_LOG(DT_LOG_ERROR, "Error unsupported type '%c'", c);
+    }
+
+    return status;
+}
+
+static int dynType_parseTypedPointer(FILE *stream, dyn_type *type) {
+    int status = DT_OK;
+    type->type = DYN_TYPE_TYPED_POINTER;
+    type->descriptor = '*';
+    type->ffiType = &ffi_type_pointer;
+
+    status = dynType_createWithStream(stream, type, 
&type->typedPointer.typedType);
+
+    return status;
+}
+
+static void dynType_prepCif(ffi_type *type) {
+    ffi_cif cif;
+    ffi_type *args[1];
+    args[0] = type;
+    ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
+}
+
+void dynType_destroy(dyn_type *type) {
+    if (type != NULL) {          
+        dynType_clear(type);
+        free(type);
+    }
+}
+
+static void dynType_clear(dyn_type *type) {
+    struct nested_entry *entry = TAILQ_FIRST(&type->nestedTypesHead);
+    struct nested_entry *tmp = NULL;
+    while (entry != NULL) {
+        tmp = entry;
+        entry = TAILQ_NEXT(entry, entries);
+        dynType_clear(&tmp->type);
+        free(tmp);
+    }
+
+    switch (type->type) {
+        case DYN_TYPE_COMPLEX :
+            dynType_clearComplex(type);
+            break;
+        case DYN_TYPE_SEQUENCE :
+            dynType_clearSequence(type);
+            break;
+        case DYN_TYPE_TYPED_POINTER :
+            dynType_clearTypedPointer(type);
+            break;
+    } 
+
+    if (type->name != NULL) {
+        free(type->name);
+    }
+}
+
+static void dynType_clearComplex(dyn_type *type) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    struct complex_type_entry *entry = TAILQ_FIRST(&type->complex.entriesHead);
+    struct complex_type_entry *tmp = NULL;
+    while (entry != NULL) {
+        dynType_clear(&entry->type);
+        if (entry->name != NULL) {
+            free(entry->name);
+        }
+        tmp = entry;
+        entry = TAILQ_NEXT(entry, entries);
+        free(tmp);
+    }
+    if (type->complex.types != NULL) {
+        free(type->complex.types);
+    }
+    if (type->complex.structType.elements != NULL) {
+        free(type->complex.structType.elements);
+    }
+}
+
+static void dynType_clearSequence(dyn_type *type) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    if (type->sequence.itemType != NULL) {
+        dynType_destroy(type->sequence.itemType);
+    }
+}
+
+static void dynType_clearTypedPointer(dyn_type *type) {
+    assert(type->type == DYN_TYPE_TYPED_POINTER);
+    if (type->typedPointer.typedType != NULL) {
+        dynType_destroy(type->typedPointer.typedType);
+    }
+}
+
+int dynType_alloc(dyn_type *type, void **bufLoc) {
+    int status = DT_OK;
+    void *inst = calloc(1, type->ffiType->size);
+    if (inst != NULL) {
+        *bufLoc = inst;
+    } else {
+        status = DT_MEM_ERROR;
+        //TODO log
+    }
+    return status;
+}
+
+
+int dynType_complex_indexForName(dyn_type *type, const char *name) {
+    printf("descriptor is %c\n", type->descriptor);
+    assert(type->type == DYN_TYPE_COMPLEX);
+    int i = 0;
+    int index = -1;
+    struct complex_type_entry *entry = NULL;
+    TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+        if (strcmp(name, entry->name) == 0) {
+            index = i;
+        }
+        i +=1;
+    }
+    return index;
+}
+
+char dynType_complex_descriptorTypeAt(dyn_type *type, int index) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+
+    dyn_type *item = type->complex.types[index];
+    return item->descriptor;
+}
+
+int dynType_complex_dynTypeAt(dyn_type *type, int index, dyn_type **result) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    *result = type->complex.types[index];
+    return 0;
+}
+
+int dynType_complex_setValueAt(dyn_type *type, int index, void *start, void 
*in) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    char *loc = ((char *)start) + dynType_getOffset(type, index);
+    size_t size = type->complex.structType.elements[index]->size;
+    memcpy(loc, in, size);
+    return 0;
+}
+
+int dynType_complex_valLocAt(dyn_type *type, int index, void *inst, void 
**result) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    char *l = (char *)inst;
+    void *loc = (void *)(l + dynType_getOffset(type, index));
+    *result = loc;
+    return 0;
+}
+
+//sequence
+int dynType_sequence_alloc(dyn_type *type, void *inst, int cap, void **out) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    int status = DT_OK;
+    struct generic_sequence *seq = inst;
+    if (seq != NULL) {
+        size_t size = dynType_size(type->sequence.itemType);
+        seq->buf = calloc(cap, size);
+        if (seq->buf != NULL) {
+            seq->cap = cap;
+            seq->len = 0;
+            *out = seq->buf;
+        } else {
+            seq->cap = 0;
+            status = DT_MEM_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error allocating memory for buf")
+        }
+    } else {
+            status = DT_MEM_ERROR;
+            DT_LOG(DT_LOG_ERROR, "Error allocating memory for seq")
+    }
+    return status;
+}
+
+int dynType_sequence_append(dyn_type *type, void *inst, void *in) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    int status = DT_OK;
+    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 = dynType_size(type->sequence.itemType);
+        size_t offset = (elSize * index);
+        memcpy(buf + offset, in, elSize);
+    } else {
+        status = DT_ERROR;
+        DT_LOG(DT_LOG_ERROR, "Sequence out of capacity")
+    }
+    return status;
+}
+
+dyn_type * dynType_sequence_itemType(dyn_type *type) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    return type->sequence.itemType;
+}
+
+void dynType_simple_setValue(dyn_type *type, void *inst, void *in) {
+    size_t size = dynType_size(type);
+    memcpy(inst, in, size);
+}
+
+
+int dynType_descriptorType(dyn_type *type) {
+    return type->descriptor;
+}
+
+static ffi_type * dynType_ffiTypeFor(int 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 'b' :
+            type = &ffi_type_uint8;
+            break;
+        case 'S' :
+            type = &ffi_type_sint16;
+            break;
+        case 's' :
+            type = &ffi_type_uint16;
+            break;
+        case 'I' :
+            type = &ffi_type_sint32;
+            break;
+        case 'i' :
+            type = &ffi_type_uint32;
+            break;
+        case 'J' :
+            type = &ffi_type_sint64;
+            break;
+        case 'j' :
+            type = &ffi_type_sint64;
+            break;
+        case 'N' :
+            type = &ffi_type_sint;
+            break;
+        case 'P' :
+            type = &ffi_type_pointer;
+            break;
+    }
+    return type;
+}
+
+static dyn_type * dynType_findType(dyn_type *type, char *name) {
+    dyn_type *result = NULL;
+
+    struct nested_entry *entry = NULL;
+    TAILQ_FOREACH(entry, &type->nestedTypesHead, entries) {
+        if (strcmp(name, entry->type.name) == 0) {
+            result = &entry->type;
+            break;
+        }
+    }
+
+    if (result == NULL && type->parent != NULL) {
+        result = dynType_findType(type->parent, name);
+    }
+
+    return result;
+}
+
+static unsigned short dynType_getOffset(dyn_type *type, int index) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    unsigned short offset = 0;
+
+    ffi_type *ffiType = &type->complex.structType;
+    int i;
+    for (i = 0;  i <= index && ffiType->elements[i] != NULL; i += 1) {
+        size_t size = ffiType->elements[i]->size;
+        unsigned short alignment = ffiType->elements[i]->alignment;
+        int alignment_diff = offset % alignment;
+        if (alignment_diff > 0) {
+            offset += (alignment - alignment_diff);
+        }
+        if (i < index) {
+            offset += size;
+        }
+    }
+
+    return offset;
+}
+
+size_t dynType_size(dyn_type *type) {
+    return type->ffiType->size;
+}
+
+int dynType_type(dyn_type *type) {
+    return type->type;
+}
+
+void dynType_print(dyn_type *type) {
+    if (type != NULL) {
+        dynType_printTypes(type);
+
+        printf("main type:\n");
+        dynType_printAny("root", type, 0);
+    } else {
+        printf("invalid type\n");
+    }
+}
+
+static void printDepth(int depth) {
+    int i;
+    for (i = 0; i < depth; i +=1 ) {
+        printf("\t");
+    }
+}
+
+static void dynType_printAny(char *name, dyn_type *type, int depth) {
+    dyn_type *toPrint = type;
+    if (toPrint->type == DYN_TYPE_REF) {
+        toPrint = toPrint->ref.ref;
+    }
+    switch(toPrint->type) {
+        case DYN_TYPE_COMPLEX :
+            dynType_printComplex(name, toPrint, depth);
+            break;
+        case DYN_TYPE_SIMPLE :
+            dynType_printSimple(name, toPrint, depth);
+            break;
+        case DYN_TYPE_SEQUENCE :
+            dynType_printSequence(name, toPrint, depth);
+            break;
+        case DYN_TYPE_TYPED_POINTER :
+            dynType_printTypedPointer(name, toPrint, depth);
+            break;
+        default :
+            printf("TODO Unsupported type %i\n", toPrint->type);
+            break;
+    }
+}
+
+static void dynType_printComplex(char *name, dyn_type *type, int depth) {
+    if (type->name == NULL) {
+        printDepth(depth);
+        printf("%s: complex type (anon), size is %zu, alignment is %i, 
descriptor is '%c'. fields:\n", name,  type->ffiType->size, 
type->ffiType->alignment, type->descriptor); 
+
+        struct complex_type_entry *entry = NULL;
+        TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+            dynType_printAny(entry->name, &entry->type, depth + 1);
+        }
+
+        printDepth(depth);
+        printf("}\n");
+    } else {
+        printDepth(depth);
+        printf("%s: complex type ('%s'), size is %zu, alignment is %i, 
descriptor is '%c'.\n", name, type->name, type->ffiType->size, 
type->ffiType->alignment, type->descriptor); 
+    }
+}
+
+static void dynType_printSequence(char *name, dyn_type *type, int depth) {
+        printDepth(depth);
+        printf("sequence, size is %zu, alignment is %i, descriptor is '%c'. 
fields:\n", type->ffiType->size, type->ffiType->alignment, type->descriptor); 
+
+        printDepth(depth + 1);
+        printf("cap: simple type, size is %zu, alignment is %i.\n", 
type->sequence.seqType.elements[0]->size, 
type->sequence.seqType.elements[0]->alignment);
+
+        printDepth(depth + 1);
+        printf("len: simple type, size is %zu, alignment is %i.\n", 
type->sequence.seqType.elements[1]->size, 
type->sequence.seqType.elements[1]->alignment);
+
+        printDepth(depth + 1);
+        printf("buf: array, size is %zu, alignment is %i. points to ->\n", 
type->sequence.seqType.elements[2]->size, 
type->sequence.seqType.elements[2]->alignment);
+        dynType_printAny("element", type->sequence.itemType, depth + 1);
+}
+
+static void dynType_printSimple(char *name, dyn_type *type, int depth) {
+    printDepth(depth);
+    printf("%s: simple type, size is %zu, alignment is %i, descriptor is 
'%c'.\n", name, type->ffiType->size, type->ffiType->alignment, 
type->descriptor);
+}
+
+static void dynType_printTypedPointer(char *name, dyn_type *type, int depth) {
+    printDepth(depth);
+    printf("%s: typed pointer, size is %zu, alignment is %i, points to ->\n", 
name, type->ffiType->size, type->ffiType->alignment);
+    char *subName = NULL;
+    if (name != NULL) {
+        char buf[128];
+        snprintf(buf, 128, "*%s", name);
+        subName = buf;
+    }
+    dynType_printAny(subName, type->typedPointer.typedType, depth + 1);
+}
+
+static void dynType_printTypes(dyn_type *type) {
+
+    dyn_type *parent = type->parent;
+    struct nested_entry *pentry = NULL;
+    while (parent != NULL) {
+        TAILQ_FOREACH(pentry, &parent->nestedTypesHead, entries) {
+            if (&pentry->type == type) {
+                return;
+            }
+        }
+        parent = parent->parent;
+    }
+
+    struct nested_entry *entry = NULL;
+    TAILQ_FOREACH(entry, &type->nestedTypesHead, entries) {
+        dyn_type *toPrint = &entry->type;
+        if (toPrint->type == DYN_TYPE_REF) {
+            toPrint = toPrint->ref.ref;
+        }
+
+        switch(toPrint->type) {
+            case DYN_TYPE_COMPLEX :
+                dynType_printComplexType(toPrint);
+                break;
+            case DYN_TYPE_SIMPLE :
+                dynType_printSimpleType(toPrint);
+                break;
+            default :
+                printf("TODO Print Type\n");
+                break;
+        }
+    }
+
+
+    struct complex_type_entry *centry = NULL;
+    switch(type->type) {
+        case DYN_TYPE_COMPLEX :
+            TAILQ_FOREACH(centry, &type->complex.entriesHead, entries) {
+                dynType_printTypes(&centry->type);
+            }
+            break;
+        case DYN_TYPE_SEQUENCE :
+            dynType_printTypes(type->sequence.itemType);
+            break;
+        case DYN_TYPE_TYPED_POINTER :
+            dynType_printTypes(type->typedPointer.typedType);
+            break;
+    }
+}
+
+static void dynType_printComplexType(dyn_type *type) {
+    printf("type '%s': complex type, size is %zu, alignment is %i, descriptor 
is '%c'. fields:\n", type->name,  type->ffiType->size, 
type->ffiType->alignment, type->descriptor); 
+
+    struct complex_type_entry *entry = NULL;
+    TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+        dynType_printAny(entry->name, &entry->type, 2);
+    }
+
+    printf("}\n");
+}
+
+static void dynType_printSimpleType(dyn_type *type) {
+    printf("\ttype '%s': simple type, size is %zu, alignment is %i, descriptor 
is '%c'\n", type->name, type->ffiType->size, type->ffiType->alignment, 
type->descriptor);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dyn_type.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_type.h 
b/remote_services/dynamic_function_interface/dyn_type.h
new file mode 100644
index 0000000..2a3b445
--- /dev/null
+++ b/remote_services/dynamic_function_interface/dyn_type.h
@@ -0,0 +1,137 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+
+#ifndef _DYN_TYPE_H_
+#define _DYN_TYPE_H_
+
+#include <stdio.h>
+#include <sys/queue.h>
+#include <stdbool.h>
+
+#include <ffi.h>
+
+/* Description string
+ *
+ * Type = [TypeDef]* (SimpleType | ComplexType | SequenceType | TypedPointer | 
PointerReference ) [TypeDef]*
+ * 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
+ * N native int
+ *
+ *
+ * ComplexTypes (Struct)
+ * {[Type]+ [(Name)(SPACE)]+}
+ *
+ * PointerReference
+ * L(Name);
+ *
+ * ReferenceByValue
+ * l(name);
+ *
+ * TypeDef 
+ * T(Name)=Type;
+ *
+ * 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_INVALID 0
+#define DYN_TYPE_SIMPLE 1
+#define DYN_TYPE_COMPLEX 2
+#define DYN_TYPE_SEQUENCE 3
+#define DYN_TYPE_TYPED_POINTER 4
+#define DYN_TYPE_REF 5
+
+typedef struct _dyn_type dyn_type;
+
+struct _dyn_type {
+    char *name;
+    char descriptor;
+    int type;
+    ffi_type *ffiType;
+    dyn_type *parent;
+    TAILQ_HEAD(, nested_entry) nestedTypesHead;
+    union {
+        struct {
+            TAILQ_HEAD(, complex_type_entry) entriesHead;
+            ffi_type structType; //dyn_type.ffiType points to this
+            dyn_type **types; //based on entriesHead for fast access
+        } complex;
+        struct {
+            ffi_type seqType; //dyn_type.ffiType points to this
+            dyn_type *itemType; 
+        } sequence;
+        struct {
+            dyn_type *typedType;
+        } typedPointer;
+        struct {
+            dyn_type *ref;
+        } ref;
+    };
+};
+
+struct complex_type_entry {
+    dyn_type type;
+    char *name;
+    TAILQ_ENTRY(complex_type_entry) entries;
+};
+
+struct nested_entry {
+    dyn_type type;
+    TAILQ_ENTRY(nested_entry) entries;
+};
+
+
+//logging
+void dynType_setupLogger(void (*logf)(void *handle, int level, const char 
*file, int line, const char *msgFormat, ...), void *handle);
+
+//generic
+int dynType_create(const char *descriptor, dyn_type **type);
+void dynType_destroy(dyn_type *type);
+int dynType_alloc(dyn_type *type, void **bufLoc);
+void dynType_print(dyn_type *type);
+size_t dynType_size(dyn_type *type);
+int dynType_type(dyn_type *type);
+int dynType_descriptorType(dyn_type *type);
+
+//complexType
+int dynType_complex_indexForName(dyn_type *type, const char *name);
+char dynType_complex_descriptorTypeAt(dyn_type *type, int index);
+int dynType_complex_dynTypeAt(dyn_type *type, int index, dyn_type **subType);
+int dynType_complex_setValueAt(dyn_type *type, int index, void *inst, void 
*in);
+int dynType_complex_valLocAt(dyn_type *type, int index, void *inst, void 
**valLoc);
+
+//sequence
+int dynType_sequence_alloc(dyn_type *type, void *inst, int cap, void **buf);
+int dynType_sequence_append(dyn_type *type, void *seq, void *in);
+dyn_type * dynType_sequence_itemType(dyn_type *type);
+
+//simple
+void dynType_simple_setValue(dyn_type *type, void *inst, void *in);
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/json_serializer.c
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/json_serializer.c 
b/remote_services/dynamic_function_interface/json_serializer.c
new file mode 100644
index 0000000..628bec9
--- /dev/null
+++ b/remote_services/dynamic_function_interface/json_serializer.c
@@ -0,0 +1,151 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "json_serializer.h"
+
+#include <jansson.h>
+#include <assert.h>
+
+static int json_serializer_createObject(dyn_type *type, json_t *object, void 
**result);
+static int json_serializer_writeObject(dyn_type *type, json_t *object, void 
*inst);
+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) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    int status = 0;
+
+    json_error_t error;
+    json_t *root = json_loads(input, JSON_DECODE_ANY, &error);
+
+    if (root != NULL) {
+        status = json_serializer_createObject(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_createObject(dyn_type *type, json_t *object, void 
**result) {
+    assert(object != NULL);
+    int status = 0;
+
+    void *inst = NULL;
+    status = dynType_alloc(type, &inst);
+
+    if (status == 0) {
+        assert(inst != NULL);
+        status = json_serializer_writeObject(type, object, inst);
+    } else {
+        //TODO destroy
+    }
+
+    if (status == 0) {
+        *result = inst;
+    } 
+
+    return status;
+}
+                
+static int json_serializer_writeObject(dyn_type *type, json_t *object, void 
*inst) {
+    assert(object != NULL);
+    int status = 0;
+    json_t *value;
+    const char *key;
+
+    if (status == 0)  {
+        json_object_foreach(object, key, value) {
+            json_serializer_writeObjectMember(type, key, value, 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 status = 0;
+    int index = dynType_complex_indexForName(type, name);
+    char charType = dynType_complex_descriptorTypeAt(type, index); 
+    void *valp = NULL;
+    status = dynType_complex_valLocAt(type, index, inst, &valp);
+
+    //TODO check status
+
+    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 '[' :
+            status = dynType_complex_dynTypeAt(type, index, &nested); 
+            //TODO check status
+            //TODO json_serializer_writeSequence(val, val, valp); 
+            break;
+        case '{' :
+            status = dynType_complex_dynTypeAt(type, index, &nested); 
+            //TODO check status
+            status = json_serializer_writeObject(nested, val, valp); 
+            //TODO check status
+            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);
+
+    void *buf = NULL;
+    dynType_sequence_alloc(seq, seqLoc, size, &buf); //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/dynamic_function_interface/json_serializer.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/json_serializer.h 
b/remote_services/dynamic_function_interface/json_serializer.h
new file mode 100644
index 0000000..6b42244
--- /dev/null
+++ b/remote_services/dynamic_function_interface/json_serializer.h
@@ -0,0 +1,12 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#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/dynamic_function_interface/schemas/complex.avdl
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/schemas/complex.avdl 
b/remote_services/dynamic_function_interface/schemas/complex.avdl
new file mode 100644
index 0000000..0490dcd
--- /dev/null
+++ b/remote_services/dynamic_function_interface/schemas/complex.avdl
@@ -0,0 +1,11 @@
+protocol Complex {
+
+  record StatResult {
+    double sum;
+    double min;
+    double max;
+    array<double> input;
+  }
+
+  StatResult stats(array<double> input);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/schemas/complex.avpr
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/schemas/complex.avpr 
b/remote_services/dynamic_function_interface/schemas/complex.avpr
new file mode 100644
index 0000000..0577397
--- /dev/null
+++ b/remote_services/dynamic_function_interface/schemas/complex.avpr
@@ -0,0 +1,36 @@
+{
+  "protocol" : "Complex",
+  "namespace" : null,
+  "types" : [ {
+    "type" : "record",
+    "name" : "StatResult",
+    "fields" : [ {
+      "name" : "sum",
+      "type" : "double"
+    }, {
+      "name" : "min",
+      "type" : "double"
+    }, {
+      "name" : "max",
+      "type" : "double"
+    }, {
+      "name" : "input",
+      "type" : {
+        "type" : "array",
+        "items" : "double"
+      }
+    } ]
+  } ],
+  "messages" : {
+    "stats" : {
+      "request" : [ {
+        "name" : "input",
+        "type" : {
+          "type" : "array",
+          "items" : "double"
+        }
+      } ],
+      "response" : "StatResult"
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/schemas/simple.avdl
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/schemas/simple.avdl 
b/remote_services/dynamic_function_interface/schemas/simple.avdl
new file mode 100644
index 0000000..cd5cafe
--- /dev/null
+++ b/remote_services/dynamic_function_interface/schemas/simple.avdl
@@ -0,0 +1,6 @@
+@namespace("org.apache.avro.test")
+protocol Simple {
+  double sum(double a, double b);
+  double sub(double a, double b);
+  double sqrt(double a);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/schemas/simple.avpr
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/schemas/simple.avpr 
b/remote_services/dynamic_function_interface/schemas/simple.avpr
new file mode 100644
index 0000000..8a90bb2
--- /dev/null
+++ b/remote_services/dynamic_function_interface/schemas/simple.avpr
@@ -0,0 +1,33 @@
+{
+  "protocol" : "Simple",
+  "types" : [ ],
+  "messages" : {
+    "sum" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      }, {
+        "name" : "b",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    },
+    "sub" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      }, {
+        "name" : "b",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    },
+    "sqrt" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/schemas/simple_min.avpr
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/schemas/simple_min.avpr 
b/remote_services/dynamic_function_interface/schemas/simple_min.avpr
new file mode 100644
index 0000000..c2bce19
--- /dev/null
+++ b/remote_services/dynamic_function_interface/schemas/simple_min.avpr
@@ -0,0 +1 @@
+{"protocol":"Simple","types":[],"messages":{"sum":{"request":[{"name":"a","type":"double"},{"name":"b","type":"double"}],"response":"double"},"sub":{"request":[{"name":"a","type":"double"},{"name":"b","type":"double"}],"response":"double"},"sqrt":{"request":[{"name":"a","type":"double"}],"response":"double"}}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp
----------------------------------------------------------------------
diff --git 
a/remote_services/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp
 
b/remote_services/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp
new file mode 100644
index 0000000..4a63c16
--- /dev/null
+++ 
b/remote_services/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp
@@ -0,0 +1,67 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                    
                                                                                
                                                    
+
+extern "C" {
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include "descriptor_translator.h"
+
+void test1(void) {
+    //TODO split up
+    size_t size = 0;
+    char *ptr = NULL;
+
+    //first argument void *handle, last argument output pointer for result and 
return int with status for exception handling
+    //sum(DD)D -> sum(PDD*D)N 
+    //sub(DD)D -> sub(PDD*D)N
+    //sqrt(D)D -> sqrt(PD*D)N
+    FILE *schema = fopen("schemas/simple.avpr", "r");
+    FILE *stream = open_memstream(&ptr, &size);
+
+    int c = fgetc(schema);
+    while (c != EOF ) {
+        fputc(c, stream);
+        c = fgetc(schema);
+    }
+    fclose(schema);
+    fclose(stream);
+   
+    assert(schema != NULL && stream != NULL); 
+    interface_descriptor_type *ift= NULL;
+    int status = descriptorTranslator_create(ptr, &ift);
+    CHECK_EQUAL(0, status);
+
+    int count = 0;
+    method_descriptor_type *mDesc = NULL;
+    TAILQ_FOREACH(mDesc, &ift->methodDescriptors, entries) {
+        count +=1;
+    }
+    CHECK_EQUAL(3, count);
+
+    TAILQ_FOREACH(mDesc, &ift->methodDescriptors, entries) {
+        if (strcmp("sum", mDesc->name) == 0) {
+            STRCMP_EQUAL("sum(PDD*D)N", mDesc->descriptor);
+        } else if (strcmp("add", mDesc->name) == 0) {
+            STRCMP_EQUAL("add(PDD*D)N", mDesc->descriptor);
+        } else if (strcmp("sqrt", mDesc->name) == 0) {
+            STRCMP_EQUAL("sqrt(PD*D)N", mDesc->descriptor);
+        }
+    }
+}
+
+}
+
+TEST_GROUP(AvroDescTranslatorTest) {
+    void setup() {
+    }
+};
+
+TEST(AvroDescTranslatorTest, Test1) {
+    test1();
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/tst/dyn_closure_tests.cpp
----------------------------------------------------------------------
diff --git 
a/remote_services/dynamic_function_interface/tst/dyn_closure_tests.cpp 
b/remote_services/dynamic_function_interface/tst/dyn_closure_tests.cpp
new file mode 100644
index 0000000..30b0b65
--- /dev/null
+++ b/remote_services/dynamic_function_interface/tst/dyn_closure_tests.cpp
@@ -0,0 +1,139 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                    
                                                                                
                                                    
+
+extern "C" {
+    
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "dyn_function.h"
+
+static int g_count;
+
+static void stdLog(void *handle, int level, const char *file, int line, const 
char *msg, ...) {
+    va_list ap;
+    const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+    fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+    va_start(ap, msg);
+    vfprintf(stderr, msg, ap);
+    fprintf(stderr, "\n");
+}
+
+#define EXAMPLE1_SCHEMA "example(III)I"
+static 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 = (int32_t *)out;
+    *ret = a + b + c;
+    g_count += 1;
+}
+
+#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 = (int32_t *)out;
+    *ret = a + b.val1 + b.val2 + b.val3 + c;
+    g_count += 1;
+}
+
+
+#define EXAMPLE3_SCHEMA "example(III){III sum max min}"
+struct example3_ret {
+    int32_t sum;
+    int32_t max;
+    int32_t min;
+};
+
+static void example3_binding(void *userData, void* args[], void *out) {
+    printf("example closure 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 = (struct example3_ret 
*)calloc(1,sizeof(struct example3_ret));
+    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 = (struct example3_ret **)out;
+    (*ret) = result;
+    g_count += 1;
+}
+
+static void tests() {
+    dyn_closure_type *dynClosure = NULL;
+    int rc;
+
+    {
+        rc = dynClosure_create(EXAMPLE1_SCHEMA, example1_binding, NULL, 
&dynClosure);
+        CHECK_EQUAL(0, rc);
+        int32_t (*func)(int32_t a, int32_t b, int32_t c) = NULL;
+        int rc = dynClosure_getFnPointer(dynClosure, (void(**)(void))&func);
+        CHECK_EQUAL(0, rc);
+        int32_t ret = func(2,3,4);
+        printf("Return value for example1 is %i\n", ret);
+        CHECK_EQUAL(1, g_count);
+        dynClosure_destroy(dynClosure);
+    }
+
+    {
+        dynClosure = NULL;
+        rc = dynClosure_create(EXAMPLE2_SCHEMA, example2_binding, NULL, 
&dynClosure);
+        CHECK_EQUAL(0, rc);
+        double (*func)(int32_t a, struct example2_arg2 b, int32_t c) = NULL;
+        rc = dynClosure_getFnPointer(dynClosure, (void(**)(void))&func);
+        CHECK_EQUAL(0, rc);
+        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);
+        CHECK_EQUAL(2, g_count);
+        dynClosure_destroy(dynClosure);
+    }
+
+    {
+        dynClosure = NULL;
+        rc = dynClosure_create(EXAMPLE3_SCHEMA, example3_binding, NULL, 
&dynClosure);
+        CHECK_EQUAL(0, rc);
+        struct example3_ret * (*func)(int32_t a, int32_t b, int32_t c) = NULL;
+        rc = dynClosure_getFnPointer(dynClosure, (void(**)(void))&func);
+        CHECK_EQUAL(0, rc);
+        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);
+        CHECK_EQUAL(3, g_count);
+        dynClosure_destroy(dynClosure);
+        free(ret);
+    }
+}
+
+}
+
+
+TEST_GROUP(DynClosureTests) {
+    void setup() {
+        dynFunction_logSetup(stdLog, NULL, 4);
+        //TODO dynType_logSetup(stdLog, NULL, 4);
+        g_count = 0;
+    }
+};
+
+TEST(DynClosureTests, DynCLosureTest1) {
+    //TODO split up
+    tests();
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/tst/dyn_function_tests.cpp
----------------------------------------------------------------------
diff --git 
a/remote_services/dynamic_function_interface/tst/dyn_function_tests.cpp 
b/remote_services/dynamic_function_interface/tst/dyn_function_tests.cpp
new file mode 100644
index 0000000..a2b7f69
--- /dev/null
+++ b/remote_services/dynamic_function_interface/tst/dyn_function_tests.cpp
@@ -0,0 +1,109 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                    
                                                                                
                                                    
+
+extern "C" {
+    #include <stdio.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <ctype.h>
+
+    #include "dyn_function.h"
+
+    static void stdLog(void *handle, int level, const char *file, int line, 
const char *msg, ...) {
+        va_list ap;
+        const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+        fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, 
line);
+        va_start(ap, msg);
+        vfprintf(stderr, msg, ap);
+        fprintf(stderr, "\n");
+    }
+
+    #define EXAMPLE1_SCHEMA "example(III)I"
+    int32_t example1(int32_t a, int32_t b, int32_t c) {
+        CHECK_EQUAL(2, a);
+        CHECK_EQUAL(4, b);
+        CHECK_EQUAL(8, c);
+        return 1;
+    }
+
+    void test_example1(void) {
+        dyn_function_type *dynFunc = NULL;
+        int rc;
+        void (*fp)(void) = (void (*)(void)) example1;
+
+        rc = dynFunction_create(EXAMPLE1_SCHEMA, fp, &dynFunc);
+        CHECK_EQUAL(0, rc);
+
+        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;
+
+        rc = dynFunction_call(dynFunc, &rVal, values);
+        CHECK_EQUAL(0, rc);
+        CHECK_EQUAL(1, rVal);
+        dynFunction_destroy(dynFunc);
+    }
+
+    #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) {
+        CHECK_EQUAL(2, arg1);
+        CHECK_EQUAL(2, arg2.val1);
+        CHECK_EQUAL(3, arg2.val2);
+        CHECK_EQUAL(4.1, arg2.val3);
+        CHECK_EQUAL(8.1, arg3);
+        return 2.2;
+    }
+
+    void test_example2(void) {
+        dyn_function_type *dynFunc = NULL;
+        int rc;
+        void (*fp)(void) = (void (*)(void)) example2;
+
+        rc = dynFunction_create(EXAMPLE2_SCHEMA, fp, &dynFunc);
+        CHECK_EQUAL(0, rc);
+
+        int32_t arg1 = 2;
+        struct example2_arg arg2 = { .val1 = 2, .val2 = 3, .val3 = 4.1 };
+        double arg3 = 8.1;
+        double returnVal = 0;
+        void *values[3];
+        values[0] = &arg1;
+        values[1] = &arg2;
+        values[2] = &arg3;
+
+        rc = dynFunction_call(dynFunc, &returnVal, values);
+        CHECK_EQUAL(0, rc);
+        CHECK_EQUAL(2.2, returnVal);
+        dynFunction_destroy(dynFunc);
+    }
+}
+
+TEST_GROUP(DynFunctionTests) {
+    void setup() {
+        dynFunction_logSetup(stdLog, NULL, 4);
+        //TODO dynType_logSetup(stdLog, NULL, 4);
+    }
+};
+
+TEST(DynFunctionTests, DynFuncTest1) {
+    test_example1();
+}
+
+TEST(DynFunctionTests, DynFuncTest2) {
+    test_example2();
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/tst/dyn_type_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/tst/dyn_type_tests.cpp 
b/remote_services/dynamic_function_interface/tst/dyn_type_tests.cpp
new file mode 100644
index 0000000..07c419b
--- /dev/null
+++ b/remote_services/dynamic_function_interface/tst/dyn_type_tests.cpp
@@ -0,0 +1,183 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                    
                                                                                
                                                    
+
+extern "C" {
+    #include <string.h>
+    #include <stdarg.h>
+    
+    #include "dyn_type.h"
+
+    void runTest(const char *descriptorStr, const char *exName) {
+        dyn_type *type;
+        int i;
+        type = NULL;
+        printf("\n-- example %s with descriptor string '%s' --\n", exName, 
descriptorStr);
+        int status = dynType_create(descriptorStr, &type);
+        CHECK_EQUAL(0, status);
+        if (status == 0) {
+            dynType_print(type);
+            dynType_destroy(type);
+        }
+        printf("--\n\n");
+    }
+}
+
+TEST_GROUP(DynTypeTests) {
+};
+
+#define EX1 "{BbJjIiSsDFNN arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 
arg11 arg12}"
+#define EX2 "{D{DD b_1 b_2}I a b c}"
+#define EX3 "Tsub={DD b_1 b_2};{DLsub;I a b c}"
+#define EX4 "{[I numbers}"
+#define EX5 "[[{DD{iii val3_1 val3_2 val3_3} val1 val2 val3}"
+#define EX6 "Tsample={DD vala valb};Lsample;"
+#define EX7 "Tsample={DD vala valb};[Lsample;"
+#define EX8 "[Tsample={DD a b};Lsample;"
+#define EX9 "*D"
+#define EX10 "Tsample={DD a b};******Lsample;"
+#define EX11 "Tsample=D;Lsample;"
+#define EX12 "Tnode={Lnode;Lnode; left right};{Lnode; head}" //note recursive 
example
+#define EX13 "Ttype={DDDDD a b c d e};{ltype;Ltype;ltype;Ltype; byVal1 byRef1 
byVal2 ByRef2}" 
+#define EX14 "{DD{FF{JJ}{II*{ss}}}}"  //unnamed fields
+
+#define CREATE_EXAMPLES_TEST(DESC) \
+    TEST(DynTypeTests, ParseTestExample ## DESC) { \
+        runTest(DESC, #DESC); \
+    }    
+
+CREATE_EXAMPLES_TEST(EX1)
+CREATE_EXAMPLES_TEST(EX2)
+CREATE_EXAMPLES_TEST(EX3)
+CREATE_EXAMPLES_TEST(EX4)
+CREATE_EXAMPLES_TEST(EX5)
+CREATE_EXAMPLES_TEST(EX6)
+CREATE_EXAMPLES_TEST(EX7)
+CREATE_EXAMPLES_TEST(EX8)
+CREATE_EXAMPLES_TEST(EX9)
+CREATE_EXAMPLES_TEST(EX10)
+CREATE_EXAMPLES_TEST(EX11)
+CREATE_EXAMPLES_TEST(EX12)
+CREATE_EXAMPLES_TEST(EX13)
+CREATE_EXAMPLES_TEST(EX14)
+
+TEST(DynTypeTests, ParseRandomGarbageTest) {
+    return; //TODO enable
+    unsigned int seed = 4148;
+    char *testRandom = getenv("DYN_TYPE_TEST_RANDOM");
+    if (testRandom != NULL && strcmp("true", testRandom) == 0) {
+        seed = (unsigned int) time(NULL);
+    } 
+    srandom(seed);
+    size_t nrOfTests = 10000;
+
+    printf("\nStarting test with random seed %i and nrOfTests %zu.\n", seed, 
nrOfTests);
+
+    int i;
+    int k;
+    int c;
+    int sucesses = 0;
+    char descriptorStr[32];
+    descriptorStr[31] = '\0';
+    for(i = 0; i < nrOfTests; i += 1) {  
+        for(k = 0; k < 31; k += 1) {
+            do {
+                c = (char) (((random() * 128) / RAND_MAX) - 1);
+            } while (!isprint(c));
+            descriptorStr[k] = c;
+            if (c == '\0') { 
+                break;
+            }
+        }
+
+        //printf("ParseRandomGarbageTest iteration %i with descriptor string 
'%s'\n", k, descriptorStr); 
+        dyn_type *type = NULL;
+        int status = dynType_create(descriptorStr, &type);
+        if (status == 0) {
+            dynType_destroy(type);
+        }
+    }
+}
+
+extern "C" {
+    static int logCount = 0;
+    static void logf_test(void *handle, int level, const char *file, int line, 
const char *msg, ...) {
+        logCount += 1;
+        
+        /*
+        va_list ap;
+        const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+        printf("%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+        va_start(ap, msg);
+        vprintf(msg, ap);
+        printf("\n");
+        */
+    }
+}
+
+TEST(DynTypeTests, DynTypeLoggerTest) {
+    dyn_type *type = NULL;
+    dynType_setupLogger(logf_test, NULL);
+    dynType_create("*", &type);
+    CHECK_EQUAL(1, logCount);
+}
+
+TEST(DynTypeTests, AssignTest1) {
+    struct ex1 {
+        int32_t a;
+        int32_t b;
+        int32_t c;
+    };
+    struct ex1 inst;
+    const char *desc = "{III a b c}";
+    dyn_type *type = NULL;
+    int status = dynType_create(desc, &type);
+    CHECK_EQUAL(0, status);
+    int32_t val1 = 2;
+    int32_t val2 = 4;
+    int32_t val3 = 8;
+    dynType_complex_setValueAt(type, 0,  &inst, &val1);
+    CHECK_EQUAL(2, inst.a);
+    dynType_complex_setValueAt(type, 1,  &inst, &val2);
+    CHECK_EQUAL(4, inst.b);
+    dynType_complex_setValueAt(type, 2,  &inst, &val3);
+    CHECK_EQUAL(8, inst.c);
+}
+
+TEST(DynTypeTests, AssignTest2) {
+    struct ex {
+        int32_t a;
+        struct {
+            double a;
+            double b;
+        } b;
+    };
+    struct ex inst;
+    const char *desc = "{I{DD a b} a b}";
+    dyn_type *type = NULL;
+    int status = dynType_create(desc, &type);
+    CHECK_EQUAL(0, status);
+    int32_t a = 2;
+    double b_a = 1.1;
+    double b_b = 1.2;
+
+    dynType_complex_setValueAt(type, 0,  &inst, &a);
+    CHECK_EQUAL(2, inst.a);
+
+    void *loc = NULL;
+    dyn_type *subType = NULL;
+    dynType_complex_valLocAt(type, 1, (void *)&inst, &loc);
+    dynType_complex_dynTypeAt(type, 1, &subType);
+
+    dynType_complex_setValueAt(subType, 0, &inst.b, &b_a);
+    CHECK_EQUAL(1.1, inst.b.a);
+
+    dynType_complex_setValueAt(subType, 1, &inst.b, &b_b);
+    CHECK_EQUAL(1.2, inst.b.b);
+}
+
+//TODO allocating / freeing
+
+//TODO sequences 

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/tst/json_serializer_tests.cpp
----------------------------------------------------------------------
diff --git 
a/remote_services/dynamic_function_interface/tst/json_serializer_tests.cpp 
b/remote_services/dynamic_function_interface/tst/json_serializer_tests.cpp
new file mode 100644
index 0000000..6cabe8a
--- /dev/null
+++ b/remote_services/dynamic_function_interface/tst/json_serializer_tests.cpp
@@ -0,0 +1,182 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                    
                                                                                
                                                    
+
+extern "C" {
+#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"
+
+static void stdLog(void *handle, int level, const char *file, int line, const 
char *msg, ...) {
+    va_list ap;
+    const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+    fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+    va_start(ap, msg);
+    vfprintf(stderr, msg, ap);
+    fprintf(stderr, "\n");
+}
+
+/*********** example 1 ************************/
+/** struct type ******************************/
+const char *example1_descriptor = "{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
+};
+
+static void print_example1(void *data) {
+    struct example1 *ex = (struct example1 *)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 ************************/
+const char *example2_descriptor = "{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
+};
+
+static void print_example2(void *data) {
+    struct example2 *ex = (struct example2 *)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_descriptor = "{[I numbers}";
+
+const char *example3_input = "{ \
+    \"numbers\" : [22,32,42] \
+}";
+
+struct example3 {
+    struct {
+        uint32_t _cap;
+        uint32_t _len;
+        int32_t *buf;
+    } numbers;
+};
+
+static void print_example3(void *data) {
+    struct example3 *ex = (struct example3 *)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 descriptor e.g "{Lleaf;Lleaf; left 
right}\nleaf{IDD index val1 val2}"
+const char *example4_descriptor = "{{IDD index val1 val2}{IDD index val1 val2} 
left right}";
+
+static 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;
+};
+
+static void print_example4(void *data) {
+    struct example4 *ex = (struct example4 *)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);
+}
+
+static void tests() {
+    printf("Starting json serializer tests\n");
+    dyn_type *type;
+    void *inst;
+    int rc;
+
+    type = NULL;
+    inst = NULL;
+    rc = dynType_create(example1_descriptor, &type);    
+    CHECK_EQUAL(0, rc);
+    rc = json_deserialize(type, example1_input, &inst); 
+    CHECK_EQUAL(0, rc);
+    print_example1(inst);
+    printf("--\n\n");
+
+
+    type = NULL;
+    inst = NULL;
+    rc = dynType_create(example2_descriptor, &type);
+    CHECK_EQUAL(0, rc);
+    rc = json_deserialize(type, example2_input, &inst); 
+    CHECK_EQUAL(0, rc);
+    print_example2(inst);
+    printf("--\n\n");
+
+    type = NULL;
+    inst = NULL;
+    rc = dynType_create(example3_descriptor, &type);
+    CHECK_EQUAL(0, rc);
+    rc = json_deserialize(type, example3_input, &inst); 
+    CHECK_EQUAL(0, rc);
+    print_example3(inst);
+
+    type = NULL;
+    inst = NULL;
+    rc = dynType_create(example4_descriptor, &type);
+    CHECK_EQUAL(0, rc);
+    rc = json_deserialize(type, example4_input, &inst); 
+    CHECK_EQUAL(0, rc);
+    print_example4(inst);
+}
+}
+
+TEST_GROUP(JsonSerializerTests) {
+    void setup() {
+    }
+};
+
+TEST(JsonSerializerTests, Test1) {
+    //TODO split up
+    tests();
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/tst/run_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/tst/run_tests.cpp 
b/remote_services/dynamic_function_interface/tst/run_tests.cpp
new file mode 100644
index 0000000..f405c9f
--- /dev/null
+++ b/remote_services/dynamic_function_interface/tst/run_tests.cpp
@@ -0,0 +1,9 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                    
                                                                                
                                                    
+
+int main(int argc, char** argv) {
+        return RUN_ALL_TESTS(argc, argv);
+}

Reply via email to