celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [03/10] celix git commit: CELIX-237: Moved dynamic function interface under remote_service_admin_dfi
Date Fri, 31 Jul 2015 20:57:32 GMT
http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.c
new file mode 100644
index 0000000..0cca69b
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.c
@@ -0,0 +1,136 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "dyn_common.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#if defined(BSD) || defined(__APPLE__) 
+#include "open_memstream.h"
+#include "fmemopen.h"
+#endif
+
+static const int OK = 0;
+static const int ERROR = 1;
+
+DFI_SETUP_LOG(dynCommon)
+
+static bool dynCommon_charIn(int c, const char *acceptedChars);
+
+int dynCommon_parseName(FILE *stream, char **result) {
+    return dynCommon_parseNameAlsoAccept(stream, NULL, result);
+}
+
+int dynCommon_parseNameAlsoAccept(FILE *stream, const char *acceptedChars, char **result) {
+    int status = OK;
+
+    char *buf = NULL;
+    size_t size = 0;
+    int strLen = 0;
+    FILE *name = open_memstream(&buf, &size);
+
+    if (name != NULL) { 
+        int c = getc(stream);
+        while (isalnum(c) || c == '_' || dynCommon_charIn(c, acceptedChars)) {
+            fputc(c, name); 
+            c = getc(stream);
+            strLen += 1;
+        }
+        fflush(name);
+        fclose(name);
+        ungetc(c, stream);
+    } else {
+        status = ERROR;
+        LOG_ERROR("Error creating mem stream for name. %s", strerror(errno));
+    }
+
+    if (status == OK) {
+        if (strLen == 0) {
+            status = ERROR;
+            LOG_ERROR("Parsed empty name");
+        }
+    }
+
+    if (status == OK) {
+       LOG_DEBUG("Parsed name '%s'", buf);
+       *result = buf;
+    } else if (buf != NULL) {
+        free(buf);
+    }
+
+    return status;
+}
+
+int dynCommon_parseNameValue(FILE *stream, char **outName, char **outValue) {
+    int status = OK;
+    char *name = NULL;
+    char *value = NULL;
+    const char *valueAcceptedChars = ".<>{}[]?;:~!@#$%^&*()_+-=,./\\'\"";
+
+    status = dynCommon_parseName(stream, &name);
+    if (status == OK) {
+        status = dynCommon_eatChar(stream, '=');
+    }
+    if (status == OK) {
+        status = dynCommon_parseNameAlsoAccept(stream, valueAcceptedChars, &value); //NOTE use different more lenient function e.g. only stop at '\n' ?
+    }
+
+    if (status == OK) {
+        *outName = name;
+        *outValue = value;
+    } else {
+        if (name != NULL) {
+            free(name);
+        }
+        if (value != NULL) {
+            free(value);
+        }
+    }
+    return status;
+}
+
+int dynCommon_eatChar(FILE *stream, int expected) {
+    int status = OK;
+    long loc = ftell(stream);
+    int c = fgetc(stream);
+    if (c != expected) {
+        status = ERROR;
+        LOG_ERROR("Error parsing, expected token '%c' got '%c' at position %li", expected, loc);
+    }
+    return status;
+}
+
+static bool dynCommon_charIn(int c, const char *acceptedChars) {
+    bool status = false;
+    if (acceptedChars != NULL) {
+        int i;
+        for (i = 0; acceptedChars[i] != '\0'; i += 1) {
+            if (c == acceptedChars[i]) {
+                status = true;
+                break;
+            }
+        }
+    }
+
+    return status;
+}
+
+void dynCommon_clearNamValHead(struct namvals_head *head) {
+    struct namval_entry *tmp = NULL;
+    struct namval_entry *entry = TAILQ_FIRST(head);
+    while (entry != NULL) {
+        tmp = entry;
+
+        if (entry->name != NULL) {
+            free(entry->name);
+        }
+        if (entry->value != NULL) {
+            free(entry->value);
+        }
+        entry = TAILQ_NEXT(entry, entries);
+        free(tmp);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.h
new file mode 100644
index 0000000..a31cbc4
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_common.h
@@ -0,0 +1,32 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef _DYN_COMMON_H_
+#define _DYN_COMMON_H_
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include "dfi_log_util.h"
+
+//logging
+DFI_SETUP_LOG_HEADER(dynCommon);
+
+TAILQ_HEAD(namvals_head, namval_entry);
+
+struct namval_entry {
+    char *name;
+    char *value;
+    TAILQ_ENTRY(namval_entry) entries;
+};
+
+int dynCommon_parseName(FILE *stream, char **result);
+int dynCommon_parseNameAlsoAccept(FILE *stream, const char *acceptedChars, char **result);
+int dynCommon_parseNameValue(FILE *stream, char **name, char **value);
+int dynCommon_eatChar(FILE *stream, int c);
+
+void dynCommon_clearNamValHead(struct namvals_head *head);
+
+#endif 

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c
new file mode 100644
index 0000000..0ae2a8a
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c
@@ -0,0 +1,243 @@
+/*
+ * 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_common.h"
+#include "dyn_type.h"
+#include "dfi_log_util.h"
+
+DFI_SETUP_LOG(dynFunction)
+
+struct _dyn_function_type {
+    char *name;
+    struct types_head *refTypes; //NOTE not owned
+    TAILQ_HEAD(,_dyn_function_argument_type) arguments;
+    ffi_type **ffiArguments;
+    dyn_type *funcReturn;
+    ffi_cif cif;
+
+    //closure part
+    ffi_closure *ffiClosure;
+    void (*fn)(void);
+    void *userData;
+    void (*bind)(void *userData, void *args[], void *ret);
+};
+
+typedef struct _dyn_function_argument_type dyn_function_argument_type;
+struct _dyn_function_argument_type {
+    int index;
+    char *name;
+    dyn_type *type;
+    TAILQ_ENTRY(_dyn_function_argument_type) entries;
+};
+
+static const int OK = 0;
+static const int MEM_ERROR = 1;
+static const int PARSE_ERROR = 2;
+static const int ERROR = 2;
+
+static int dynFunction_initCif(dyn_function_type *dynFunc);
+static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descriptor);
+static void dynFunction_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData); 
+
+int dynFunction_parse(FILE *descriptor, struct types_head *refTypes, dyn_function_type **out) {
+    int status = OK;
+    dyn_function_type *dynFunc = NULL;
+    LOG_DEBUG("Creating dyn function", descriptor);
+    
+    dynFunc = calloc(1, sizeof(*dynFunc));
+
+    if (dynFunc != NULL) {
+        TAILQ_INIT(&dynFunc->arguments);
+        dynFunc->refTypes = refTypes;
+        status = dynFunction_parseDescriptor(dynFunc, descriptor);
+        if (status == 0) {
+            int rc = dynFunction_initCif(dynFunc);
+            if (rc != 0) {
+                LOG_ERROR("Error initializing cif");
+                status = ERROR;
+            }
+        }
+    } else {
+        LOG_ERROR("Error allocationg memory for dyn functipn\n");
+        status = MEM_ERROR;
+    }
+    
+    if (status == 0) {
+        *out = dynFunc;
+    }     
+    
+    return status;
+}
+
+int dynFunction_parseWithStr(const char *descriptor, struct types_head *refTypes, dyn_function_type **out)  {
+    int status = OK;
+    FILE *stream = fmemopen((char *)descriptor, strlen(descriptor), "r");
+    if (stream != NULL) {
+        status = dynFunction_parse(stream, refTypes, out);
+        fclose(stream);
+    } else {
+        status = MEM_ERROR;
+        LOG_ERROR("Error creating mem stream for descriptor string. %s", strerror(errno)); 
+    }
+    return status;
+}
+
+static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descriptor) {
+    int status = OK;
+    char *name = NULL;
+
+    status = dynCommon_parseName(descriptor, &name);
+
+    if (status == OK) {
+        dynFunc->name = name;
+    }
+
+    if (status == OK) {
+        int c = fgetc(descriptor);
+        if ( c != '(') {
+            status = PARSE_ERROR;
+            LOG_ERROR("Expected '(' token got '%c'", c);
+        }
+    }
+
+    int nextChar = fgetc(descriptor);
+    int index = 0;
+    dyn_type *type = NULL;
+    while (nextChar != ')' && status == 0)  {
+        type = NULL;
+        ungetc(nextChar, descriptor);
+        status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &type); 
+        if (status == 0) {
+            dyn_function_argument_type *arg = calloc(1, sizeof(*arg));
+            arg->index = index++;
+            arg->type = type;
+            arg->name = NULL; //TODO
+            if (arg != NULL) {
+                TAILQ_INSERT_TAIL(&dynFunc->arguments, arg, entries);
+            } else {
+                LOG_ERROR("Error allocating memory");
+                status = MEM_ERROR;
+            }
+        } 
+        nextChar = fgetc(descriptor);
+    }
+
+    if (status == 0) {
+        status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &dynFunc->funcReturn); 
+    }
+    
+    return status;
+}
+
+static int dynFunction_initCif(dyn_function_type *dynFunc) {
+    int status = 0;
+
+    int count = 0;
+    dyn_function_argument_type *entry = NULL;
+    TAILQ_FOREACH(entry, &dynFunc->arguments, entries) {
+        count +=1;
+    }
+
+    dynFunc->ffiArguments = calloc(count, sizeof(ffi_type));
+
+    TAILQ_FOREACH(entry, &dynFunc->arguments, entries) {
+        dynFunc->ffiArguments[entry->index] = dynType_ffiType(entry->type);
+    }
+    
+    ffi_type **args = dynFunc->ffiArguments;
+    ffi_type *returnType = dynType_ffiType(dynFunc->funcReturn);
+
+    int ffiResult = ffi_prep_cif(&dynFunc->cif, FFI_DEFAULT_ABI, count, returnType, args);
+    if (ffiResult != FFI_OK) {
+        status = 1;
+    }
+
+    return status;
+}
+
+void dynFunction_destroy(dyn_function_type *dynFunc) {
+    if (dynFunc != NULL) {
+        if (dynFunc->funcReturn != NULL) {
+            dynType_destroy(dynFunc->funcReturn);
+        }
+        if (dynFunc->ffiClosure != NULL) {
+            ffi_closure_free(dynFunc->ffiClosure);
+        }
+        if (dynFunc->name != NULL) {
+            free(dynFunc->name);
+        }
+        if (dynFunc->ffiArguments != NULL) {
+            free(dynFunc->ffiArguments);
+        }
+        
+        dyn_function_argument_type *entry = NULL;
+        dyn_function_argument_type *tmp = NULL;
+        entry = TAILQ_FIRST(&dynFunc->arguments); 
+        while (entry != NULL) {
+            if (entry->name != NULL) {
+                free(entry->name);
+            }
+            dynType_destroy(entry->type);
+            tmp = entry;
+            entry = TAILQ_NEXT(entry, entries);
+            free(tmp);
+        }
+
+        free(dynFunc);
+    }
+}
+
+int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnValue, void **argValues) {
+    //TODO check dynFunc arg
+    ffi_call(&dynFunc->cif, fn, returnValue, argValues);    
+    return 0;
+}
+
+static void dynFunction_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData) {
+    dyn_function_type *dynFunc = userData;
+    dynFunc->bind(dynFunc->userData, args, ret);
+}
+
+int dynFunction_createClosure(dyn_function_type *dynFunc, void (*bind)(void *, void **, void*), void *userData, void(**out)(void)) {
+    int status = 0;
+    void (*fn)(void);
+    dynFunc->ffiClosure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&fn);
+    if (dynFunc->ffiClosure != NULL) {
+        int rc = ffi_prep_closure_loc(dynFunc->ffiClosure, &dynFunc->cif, dynFunction_ffiBind, dynFunc, fn);
+        if (rc != FFI_OK) {
+            status = 1;
+        }
+    } else {
+        status = 2;
+    }
+
+    if (status == 0) {
+        dynFunc->bind = bind;
+        dynFunc->fn = fn;
+        *out =fn;
+    }
+
+    return status;
+}
+
+int dynFunction_getFnPointer(dyn_function_type *dynFunc, void (**fn)(void)) {
+    int status = 0;
+    if (dynFunc != NULL && dynFunc->fn != NULL) {
+        (*fn) = dynFunc->fn;
+    } else {
+        status = 1;
+    }
+    return status;
+}
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h
new file mode 100644
index 0000000..2d5d6bb
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h
@@ -0,0 +1,31 @@
+/*
+ * 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_parse(FILE *descriptorStream, struct types_head *refTypes, dyn_function_type **dynFunc);
+int dynFunction_parseWithStr(const char *descriptor, struct types_head *refTypes, dyn_function_type **dynFunc);
+
+void dynFunction_destroy(dyn_function_type *dynFunc);
+int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnValue, void **argValues);
+
+int dynFunction_createClosure(dyn_function_type *func, void (*bind)(void *, void **, void*), void *userData, void(**fn)(void));
+int dynFunction_getFnPointer(dyn_function_type *func, void (**fn)(void));
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c
new file mode 100644
index 0000000..878cfea
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c
@@ -0,0 +1,371 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "dyn_interface.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "dyn_interface.h"
+
+DFI_SETUP_LOG(dynInterface);
+
+const int OK = 0;
+const int ERROR = 1;
+
+static int dynInterface_parseSection(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseAnnotations(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseTypes(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseHeader(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseNameValueSection(dyn_interface_type *intf, FILE *stream, struct namvals_head *head);
+static int dynInterface_checkInterface(dyn_interface_type *intf);
+static int dynInterface_getEntryForHead(struct namvals_head *head, const char *name, char **value);
+
+int dynInterface_parse(FILE *descriptor, dyn_interface_type **out) {
+    int status = OK;
+
+    dyn_interface_type *intf = calloc(1, sizeof(*intf));
+    if (intf != NULL) {
+        TAILQ_INIT(&intf->header);
+        TAILQ_INIT(&intf->annotations);
+        TAILQ_INIT(&intf->types);
+        TAILQ_INIT(&intf->methods);
+
+        char peek = fgetc(descriptor);
+        while (peek == ':') {
+            ungetc(peek, descriptor);
+            status = dynInterface_parseSection(intf, descriptor);
+            if (status == OK) {
+                peek = fgetc(descriptor);
+            } else {
+                break;
+            }
+        }
+
+        if (status == OK) {
+            status = dynCommon_eatChar(descriptor, EOF);
+        }
+
+        if (status == OK) {
+            status = dynInterface_checkInterface(intf);
+        }
+    } else {
+        status = ERROR;
+        LOG_ERROR("Error allocating memory for dynamic interface\n");
+    }
+
+    if (status == OK) {
+        *out = intf;
+    } else if (intf != NULL) {
+        dynInterface_destroy(intf);
+    }
+    return status;
+}
+
+static int dynInterface_checkInterface(dyn_interface_type *intf) {
+    int status = OK;
+
+    //check header section
+    if (status == OK) {
+        bool foundType = false;
+        bool foundVersion = false;
+        bool foundName = false;
+        struct namval_entry *entry = NULL;
+        TAILQ_FOREACH(entry, &intf->header, entries) {
+            if (strcmp(entry->name, "type") == 0) {
+                foundType = true;
+            } else if (strcmp(entry->name, "version") == 0) {
+                foundVersion = true;
+            } else if (strcmp(entry->name, "name") == 0) {
+                foundName = true;
+            }
+        }
+
+        if (!foundType || !foundVersion || !foundName) {
+            status = ERROR;
+            LOG_ERROR("Parse Error. There must be a header section with a type, version and name entry");
+        }
+    }
+
+    return status;
+}
+
+static int dynInterface_parseSection(dyn_interface_type *intf, FILE *stream) {
+    int status = OK;
+    char *sectionName = NULL;
+
+    status = dynCommon_eatChar(stream, ':');
+
+    if (status == OK) {
+        status = dynCommon_parseName(stream, &sectionName);
+    }
+
+    if (status == OK) {
+        status = dynCommon_eatChar(stream, '\n');
+    }
+
+    if (status == OK) {
+        if (strcmp("header", sectionName) == 0) {
+            status = dynInterface_parseHeader(intf, stream);
+        } else if (strcmp("annotations", sectionName) == 0) {
+            status = dynInterface_parseAnnotations(intf, stream);
+        } else if (strcmp("types", sectionName) == 0) {
+            status = dynInterface_parseTypes(intf, stream);
+        } else if (strcmp("methods", sectionName) == 0) {
+            status = dynInterface_parseMethods(intf, stream);
+        } else {
+            status = ERROR;
+            LOG_ERROR("unsupported section '%s'", sectionName);
+        }
+    }
+
+    if (sectionName != NULL) {
+        free(sectionName);
+    }
+
+    return status;
+}
+
+static int dynInterface_parseHeader(dyn_interface_type *intf, FILE *stream) {
+    return dynInterface_parseNameValueSection(intf, stream, &intf->header);
+}
+
+static int dynInterface_parseAnnotations(dyn_interface_type *intf, FILE *stream) {
+    return dynInterface_parseNameValueSection(intf, stream, &intf->annotations);
+}
+
+static int dynInterface_parseNameValueSection(dyn_interface_type *intf, FILE *stream, struct namvals_head *head) {
+    int status = OK;
+
+    int peek = fgetc(stream);
+    while (peek != ':' && peek != EOF) {
+        ungetc(peek, stream);
+
+        char *name;
+        char *value;
+        status = dynCommon_parseNameValue(stream, &name, &value);
+
+        if (status == OK) {
+            status = dynCommon_eatChar(stream, '\n');
+        }
+
+        struct namval_entry *entry = NULL;
+        if (status == OK) {
+            entry = calloc(1, sizeof(*entry));
+            if (entry != NULL) {
+                entry->name = name;
+                entry->value = value;
+                TAILQ_INSERT_TAIL(head, entry, entries);
+            } else {
+                status = ERROR;
+                LOG_ERROR("Error allocating memory for namval entry");
+            }
+        }
+
+        if (status != OK) {
+            if (name != NULL) {
+                free(name);
+            }
+            if (value != NULL) {
+                free(value);
+            }
+            if (entry != NULL) {
+                free(entry);
+            }
+            break;
+        }
+        peek = fgetc(stream);
+    }
+    ungetc(peek, stream);
+
+    return status;
+}
+
+static int dynInterface_parseTypes(dyn_interface_type *intf, FILE *stream) {
+    int status = OK;
+
+    //expected input (Name)=<Type>\n
+    int peek = fgetc(stream);
+    while (peek != ':' && peek != EOF) {
+        ungetc(peek, stream);
+
+        char *name;
+        status = dynCommon_parseName(stream, &name);
+
+        if (status == OK) {
+            status = dynCommon_eatChar(stream, '=');
+        }
+
+        dyn_type *type = NULL;
+        if (status == OK) {
+            dynType_parse(stream, name, &intf->types, &type);
+        }
+        if (name != NULL) {
+            free(name);
+        }
+
+        if (status == OK) {
+            status = dynCommon_eatChar(stream, '\n');
+        }
+
+        struct type_entry *entry = NULL;
+        if (status == OK) {
+            entry = calloc(1, sizeof(*entry));
+            if (entry != NULL) {
+                entry->type = type;
+                TAILQ_INSERT_TAIL(&intf->types, entry, entries);
+            } else {
+                status = ERROR;
+                LOG_ERROR("Error allocating memory for type entry");
+            }
+        }
+
+        if (status != OK) {
+            if (type != NULL) {
+                dynType_destroy(type);
+            }
+            if (entry != NULL) {
+                free(entry);
+            }
+            break;
+        }
+        peek = fgetc(stream);
+    }
+    ungetc(peek, stream);
+
+    return status;
+}
+
+static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream) {
+    int status = OK;
+
+    //expected input (Name)=<Method>\n
+    int peek = fgetc(stream);
+    int index = 0;
+    while (peek != ':' && peek != EOF) {
+        ungetc(peek, stream);
+
+        char *id;
+        status = dynCommon_parseNameAlsoAccept(stream, "();[{}", &id);
+
+        if (status == OK) {
+            status = dynCommon_eatChar(stream, '=');
+        }
+
+
+        dyn_function_type *func = NULL;
+        if (status == OK) {
+            status = dynFunction_parse(stream, &intf->types, &func);
+        }
+
+        if (status == OK) {
+            status = dynCommon_eatChar(stream, '\n');
+        }
+
+        struct method_entry *entry = NULL;
+        if (status == OK) {
+            entry = calloc(1, sizeof(*entry));
+            if (entry != NULL) {
+                entry->index = index++;
+                entry->id = id;
+                entry->dynFunc = func;
+                TAILQ_INSERT_TAIL(&intf->methods, entry, entries);
+            } else {
+                status = ERROR;
+                LOG_ERROR("Error allocating memory for method entry");
+            }
+        }
+
+        if (status != OK) {
+            if (id != NULL) {
+                free(id);
+            }
+            if (func != NULL) {
+                dynFunction_destroy(func);
+                //TODO free strIdentier, name
+            }
+            if (entry != NULL) {
+                free(entry);
+            }
+            break;
+        }
+        peek = fgetc(stream);
+    }
+    ungetc(peek, stream);
+
+    return status;
+}
+
+void dynInterface_destroy(dyn_interface_type *intf) {
+    if (intf != NULL) {
+        dynCommon_clearNamValHead(&intf->header);
+        dynCommon_clearNamValHead(&intf->annotations);
+
+        struct type_entry *tmp = NULL;
+        struct type_entry *tInfo = TAILQ_FIRST(&intf->types);
+        while (tInfo != NULL) {
+            tmp = tInfo;
+            tInfo = TAILQ_NEXT(tInfo, entries);
+            dynType_destroy(tmp->type);
+            free(tmp);
+        }
+
+        struct method_entry *mTmp = NULL;
+        struct method_entry *mInfo = TAILQ_FIRST(&intf->methods);
+        while (mInfo != NULL) {
+            mTmp = mInfo;
+            mInfo = TAILQ_NEXT(mInfo, entries);
+            
+            if (mTmp->id != NULL) {
+                free(mTmp->id);
+            }
+            if (mTmp->name != NULL) {
+                free(mTmp->name);
+            }
+            if (mTmp->dynFunc != NULL) {
+                dynFunction_destroy(mTmp->dynFunc);
+            }
+            free(mTmp);
+        }
+
+        free(intf);
+    } 
+}
+
+int dynInterface_getName(dyn_interface_type *intf, char **out) {
+    return dynInterface_getEntryForHead(&intf->header, "name", out);
+}
+
+int dynInterface_getVersion(dyn_interface_type *intf, char **version) {
+    return dynInterface_getEntryForHead(&intf->header, "version", version);
+}
+
+int dynInterface_getHeaderEntry(dyn_interface_type *intf, const char *name, char **value) {
+    return dynInterface_getEntryForHead(&intf->header, name, value);
+}
+
+int dynInterface_getAnnotationEntry(dyn_interface_type *intf, const char *name, char **value) {
+    return dynInterface_getEntryForHead(&intf->annotations, name, value);
+}
+
+static int dynInterface_getEntryForHead(struct namvals_head *head, const char *name, char **out) {
+    int status = OK;
+    char *value = NULL;
+    struct namval_entry *entry = NULL;
+    TAILQ_FOREACH(entry, head, entries) {
+        if (strcmp(name, entry->name) == 0) {
+            value = entry->value;
+            break;
+        }
+    }
+    if (value != NULL) {
+        *out = value;
+    } else {
+        status = ERROR;
+        LOG_WARNING("Cannot find '%s' in list", name);
+    }
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.h
new file mode 100644
index 0000000..0b0898f
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.h
@@ -0,0 +1,58 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef __DYN_INTERFACE_H_
+#define __DYN_INTERFACE_H_
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "dyn_function.h"
+#include "dfi_log_util.h"
+
+DFI_SETUP_LOG_HEADER(dynInterface);
+
+/* Description string
+ *
+ * Descriptor (interface) = HeaderSection AnnotationSection TypesSection MethodsSection
+ *
+ * HeaderSection=
+ * ':header\n' [NameValue]*
+ * ':annotations\n' [NameValue]*
+ * ':types\n' [TypeIdValue]*
+ * ':methods\n' [MethodIdValue]
+ *
+ */
+
+//struct namvals_head in dyn_common.h
+TAILQ_HEAD(methods_head, method_entry);
+//struct reference_types_head in dyn_type.h
+
+typedef struct _dyn_interface_type dyn_interface_type;
+
+struct _dyn_interface_type {
+    struct namvals_head header;
+    struct namvals_head annotations;
+    struct types_head types;
+    struct methods_head methods;
+};
+
+struct method_entry {
+    int index;
+    char *id;
+    char *name;
+
+    dyn_function_type *dynFunc;
+
+    TAILQ_ENTRY(method_entry) entries; 
+};
+
+int dynInterface_parse(FILE *descriptor, dyn_interface_type **out);
+void dynInterface_destroy(dyn_interface_type *intf);
+
+int dynInterface_getName(dyn_interface_type *intf, char **name);
+int dynInterface_getVersion(dyn_interface_type *intf, char **version);
+int dynInterface_getHeaderEntry(dyn_interface_type *intf, const char *name, char **value);
+int dynInterface_getAnnotationEntry(dyn_interface_type *intf, const char *name, char **value);
+
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c
new file mode 100644
index 0000000..2946607
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c
@@ -0,0 +1,1031 @@
+/**
+ * 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>
+
+#include "dyn_common.h"
+
+DFI_SETUP_LOG(dynType)
+
+static int dynType_parseWithStream(FILE *stream, const char *name, dyn_type *parent, struct types_head *refTypes, dyn_type **result);
+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 struct type_entry *dynType_allocTypeEntry(void);
+
+static ffi_type * dynType_ffiTypeFor(int c);
+static dyn_type * dynType_findType(dyn_type *type, char *name);
+static int dynType_parseAny(FILE *stream, dyn_type *type);
+static int dynType_parseComplex(FILE *stream, dyn_type *type);
+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, FILE *stream);
+static void dynType_printComplex(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printSequence(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printSimple(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printTypedPointer(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printDepth(int depth, FILE *stream);
+
+static void dynType_printTypes(dyn_type *type, FILE *stream);
+static void dynType_printComplexType(dyn_type *type, FILE *stream);
+static void dynType_printSimpleType(dyn_type *type, FILE *stream);
+
+static int dynType_parseText(FILE *stream, dyn_type *type);
+void dynType_freeComplexType(dyn_type *type, void *loc);
+void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf);
+void dynType_freeSequenceType(dyn_type *type, void *seqLoc);
+
+struct generic_sequence {
+    uint32_t cap;
+    uint32_t len;
+    void *buf;
+};
+
+struct _dyn_type {
+    char *name;
+    char descriptor;
+    int type;
+    ffi_type *ffiType;
+    dyn_type *parent;
+    struct types_head *referenceTypes; //NOTE: not owned
+    struct types_head nestedTypesHead;
+    union {
+        struct {
+            struct complex_type_entries_head 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;
+    };
+};
+
+static const int OK = 0;
+static const int ERROR = 1;
+static const int MEM_ERROR = 2;
+static const int PARSE_ERROR = 3;
+
+int dynType_parse(FILE *descriptorStream, const char *name, struct types_head *refTypes, dyn_type **type) {
+    return dynType_parseWithStream(descriptorStream, name, NULL, refTypes, type);
+}
+
+int dynType_parseWithStr(const char *descriptor, const char *name, struct types_head *refTypes, dyn_type **type) {
+    int status = OK;
+    FILE *stream = fmemopen((char *)descriptor, strlen(descriptor), "r");
+    if (stream != NULL) {
+        status = dynType_parseWithStream(stream, name, NULL, refTypes, type);
+        if (status == OK) {
+            int c = fgetc(stream);
+            if (c != '\0' && c != EOF) {
+                status = PARSE_ERROR;
+                LOG_ERROR("Expected EOF got %c", c);
+            }
+        } 
+        fclose(stream);
+    } else {
+        status = ERROR;
+        LOG_ERROR("Error creating mem stream for descriptor string. %s", strerror(errno)); 
+    }
+    return status;
+}
+
+static int dynType_parseWithStream(FILE *stream, const char *name, dyn_type *parent, struct types_head *refTypes, dyn_type **result) {
+    int status = OK;
+    dyn_type *type = calloc(1, sizeof(*type));
+    if (type != NULL) {
+        type->parent = parent;
+        type->type = DYN_TYPE_INVALID;
+        type->referenceTypes = refTypes;
+        TAILQ_INIT(&type->nestedTypesHead);
+        if (name != NULL) {
+            type->name = strdup(name);
+            if (type->name == NULL) {
+                status = MEM_ERROR;
+                LOG_ERROR("Error strdup'ing name '%s'\n", name);			
+            } 
+        }
+        if (status == OK) {
+            status = dynType_parseAny(stream, type);        
+        }
+        if (status == OK) {
+            *result = type;
+        } else {
+            dynType_destroy(type);
+        }
+    } else {
+        status = MEM_ERROR;
+        LOG_ERROR("Error allocating memory for type");
+    }
+    return status;
+}
+
+static int dynType_parseAny(FILE *stream, dyn_type *type) {
+    int status = OK;
+
+    int c = fgetc(stream);
+    switch(c) {
+        case 'T' :
+            status = dynType_parseNestedType(stream, type);
+            if (status == OK) {
+                status = dynType_parseAny(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;
+        case 't' :
+            status = dynType_parseText(stream, type);
+            break;
+        default :
+            status = dynType_parseSimple(c, type);
+            break;
+    }
+
+    return status;
+}
+
+static int dynType_parseText(FILE *stream, dyn_type *type) {
+    int status = OK;
+    type->type = DYN_TYPE_TEXT;
+    type->descriptor = 't';
+    type->ffiType = &ffi_type_pointer;
+    return status;
+}
+
+static int dynType_parseComplex(FILE *stream, dyn_type *type) {
+    int status = 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 = calloc(1, sizeof(*entry->type));
+        }
+        if (entry != NULL && entry->type != 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_parseAny(stream, entry->type);
+        } else {
+            if (entry != NULL) {
+                free(entry);
+            }
+            status = MEM_ERROR;
+            LOG_ERROR("Error allocating memory for type");
+        }
+        c = fgetc(stream);
+    }
+
+    entry = TAILQ_FIRST(&type->complex.entriesHead);
+    char *name = NULL;
+    while (c == ' ' && entry != NULL) {
+        status = dynCommon_parseName(stream, &name);
+        if (status == 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 == 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 = MEM_ERROR;
+            //T\nODO log: error allocating memory
+        }
+    }
+
+    if (status == 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 = MEM_ERROR;
+            LOG_ERROR("Error allocating memory for type")
+        }
+    }
+
+    if (status == OK) {
+        dynType_prepCif(type->ffiType);
+    }
+
+
+    return status;
+}
+
+static int dynType_parseNestedType(FILE *stream, dyn_type *type) {
+    int status = OK;
+    char *name = NULL;
+    struct type_entry *entry = NULL;
+
+    entry = dynType_allocTypeEntry();
+    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 = dynCommon_parseName(stream, &name);
+        entry->type->name = name;
+    } else {
+        status = MEM_ERROR;
+        LOG_ERROR("Error allocating entry");
+    }     
+
+    if (status == OK) {
+        int c = fgetc(stream);
+        if (c != '=') {
+            status = PARSE_ERROR;
+            LOG_ERROR("Error parsing nested type expected '=' got '%c'", c);
+        }
+    }
+
+    if (status == OK) {
+        status = dynType_parseAny(stream, entry->type);
+        int c = fgetc(stream);
+        if (c != ';') {
+            status = PARSE_ERROR;
+            LOG_ERROR("Expected ';' got '%c'\n", c);
+        }
+    }
+
+    return status;
+}
+
+static int dynType_parseReference(FILE *stream, dyn_type *type) {
+    int status = 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 = MEM_ERROR;
+        LOG_ERROR("Error allocating memory for subtype\n");
+    }
+
+    return status;
+}
+
+static int dynType_parseRefByValue(FILE *stream, dyn_type *type) {
+    int status = OK;
+    type->type = DYN_TYPE_REF;
+    type->descriptor = 'l';
+
+    char *name = NULL;
+    status = dynCommon_parseName(stream, &name);
+    if (status == OK) {
+        dyn_type *ref = dynType_findType(type, name);
+        if (ref != NULL) {
+            type->ref.ref = ref;
+        } else {
+            status = PARSE_ERROR;
+            LOG_ERROR("Error cannot find type '%s'", name);
+        }
+        free(name);
+    } 
+
+    if (status == OK) {
+        int c = fgetc(stream);
+        if (c != ';') {
+            status = PARSE_ERROR;
+            LOG_ERROR("Error expected ';' got '%c'", c);
+        } 
+    }
+
+    return status;
+}
+
+static struct type_entry *dynType_allocTypeEntry(void) {
+    struct type_entry *entry = calloc(1, sizeof(*entry));
+    if (entry != NULL) {
+        entry->type = calloc(1, sizeof(*entry->type));
+        if (entry->type == NULL) {
+            free(entry);
+            entry = NULL;
+        }
+    }
+    return entry;
+}
+
+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 = OK;
+    type->type = DYN_TYPE_SEQUENCE;
+    type->descriptor = '[';
+
+    type->sequence.seqType.elements = seq_types;
+    status = dynType_parseWithStream(stream, NULL, type, NULL, &type->sequence.itemType);
+
+    if (status == OK) {
+        type->ffiType = &type->sequence.seqType;
+        dynType_prepCif(&type->sequence.seqType);
+    }
+
+    return status;
+}
+
+static int dynType_parseSimple(int c, dyn_type *type) {
+    int status = OK;
+    ffi_type *ffiType = dynType_ffiTypeFor(c);
+    if (ffiType != NULL) {
+        type->type = DYN_TYPE_SIMPLE;
+        type->descriptor = c;
+        type->ffiType = ffiType;
+    } else {
+        status = PARSE_ERROR;
+        LOG_ERROR("Error unsupported type '%c'", c);
+    }
+
+    return status;
+}
+
+static int dynType_parseTypedPointer(FILE *stream, dyn_type *type) {
+    int status = OK;
+    type->type = DYN_TYPE_TYPED_POINTER;
+    type->descriptor = '*';
+    type->ffiType = &ffi_type_pointer;
+
+    status = dynType_parseWithStream(stream, NULL, type, NULL, &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 type_entry *entry = TAILQ_FIRST(&type->nestedTypesHead);
+    struct type_entry *tmp = NULL;
+    while (entry != NULL) {
+        tmp = entry;
+        entry = TAILQ_NEXT(entry, entries);
+        if (tmp->type != NULL) {
+            dynType_destroy(tmp->type);
+            tmp->type = NULL;
+        }
+        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_destroy(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) {
+    assert(type->type != DYN_TYPE_REF);
+    int status = OK;
+
+    void *inst = calloc(1, type->ffiType->size);
+    if (inst != NULL) {
+        *bufLoc = inst;
+    } else {
+        status = MEM_ERROR;
+        LOG_ERROR("Error allocating memory for type '%c'", type->descriptor);
+    }
+
+    return status;
+}
+
+
+int dynType_complex_indexForName(dyn_type *type, const char *name) {
+    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;
+}
+
+int dynType_complex_dynTypeAt(dyn_type *type, int index, dyn_type **result) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    dyn_type *sub = type->complex.types[index];
+    if (sub->type == DYN_TYPE_REF) {
+        sub = sub->ref.ref;
+    }
+    *result = sub;
+    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;
+}
+
+int dynType_complex_entries(dyn_type *type, struct complex_type_entries_head **entries) {
+    assert(type->type == DYN_TYPE_COMPLEX);
+    int status = OK;
+    *entries = &type->complex.entriesHead;
+    return status;
+}
+
+//sequence
+int dynType_sequence_alloc(dyn_type *type, void *inst, uint32_t cap) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    int status = 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;;
+        } else {
+            seq->cap = 0;
+            status = MEM_ERROR;
+            LOG_ERROR("Error allocating memory for buf")
+        }
+    } else {
+            status = MEM_ERROR;
+            LOG_ERROR("Error allocating memory for seq")
+    }
+    return status;
+}
+
+void dynType_free(dyn_type *type, void *loc) {
+    dynType_deepFree(type, loc, true);
+}
+
+void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf) {
+    if (loc != NULL) {
+        dyn_type *subType = NULL;
+        char *text = NULL;
+        switch (type->type) {
+            case DYN_TYPE_COMPLEX :
+                dynType_freeComplexType(type, loc);
+                break;
+            case DYN_TYPE_SEQUENCE :
+                dynType_freeSequenceType(type, loc);
+                break;
+            case DYN_TYPE_TYPED_POINTER:
+                dynType_typedPointer_getTypedType(type, &subType);
+                dynType_deepFree(subType, *(void **)loc, true);
+                break;
+            case DYN_TYPE_TEXT :
+                text = *(char **)loc;
+                free(text);
+                break;
+        }
+
+        if (alsoDeleteSelf) {
+            free(loc);
+        }
+    }
+}
+
+void dynType_freeSequenceType(dyn_type *type, void *seqLoc) {
+    struct generic_sequence *seq = seqLoc;
+    dyn_type *itemType = dynType_sequence_itemType(type);
+    void *itemLoc = NULL;
+    int i;
+    for (i = 0; i < seq->len; i += 1) {
+        dynType_sequence_locForIndex(type, seqLoc, i, &itemLoc);
+        dynType_deepFree(itemType, itemLoc, false);
+    }
+    free(seq->buf);
+}
+
+void dynType_freeComplexType(dyn_type *type, void *loc) {
+    struct complex_type_entry *entry = NULL;
+    int index = 0;
+    void *entryLoc = NULL;
+    TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+        dynType_complex_valLocAt(type, index++, loc, &entryLoc);
+        dynType_deepFree(entry->type, entryLoc, false);
+    }
+}
+
+
+uint32_t dynType_sequence_length(void *seqLoc) {
+    struct generic_sequence *seq = seqLoc;
+    return seq->len;
+}
+
+int dynType_sequence_locForIndex(dyn_type *type, void *seqLoc, int index, void **out) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    int status = OK;
+
+    struct generic_sequence *seq = seqLoc;
+    char *valLoc = seq->buf;
+    size_t itemSize = type->sequence.itemType->ffiType->size;
+
+    if (index >= seq->cap) {
+        status = ERROR;
+        LOG_ERROR("Requested index (%i) is greater than capacity (%u) of sequence", index, seq->cap);
+    }
+
+    if (index >= seq->len) {
+        LOG_WARNING("Requesting index (%i) outsize defined length (%u) but within capacity", index, seq->len);
+    }
+
+    if (status == OK) { }
+    int i;
+    for (i = 0; i < seq->cap; i += 1) {
+        if (index == i) {
+            break;
+        } else {
+            valLoc += itemSize;
+        }
+    }
+
+    (*out) = valLoc;
+
+    return status;
+}
+
+int dynType_sequence_increaseLengthAndReturnLastLoc(dyn_type *type, void *seqLoc, void **valLoc) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    int status = OK;
+    struct generic_sequence *seq = seqLoc;
+
+    int lastIndex = seq->len;
+    if (seq->len < seq->cap) {
+        seq->len += 1;
+    } else {
+        status = ERROR;
+        LOG_ERROR("Cannot increase sequence length beyond capacity (%u)", seq->cap);
+    }
+
+    if (status == OK) {
+        status = dynType_sequence_locForIndex(type, seqLoc, lastIndex, valLoc);
+    }
+
+    return status;
+}
+
+dyn_type * dynType_sequence_itemType(dyn_type *type) {
+    assert(type->type == DYN_TYPE_SEQUENCE);
+    dyn_type *itemType = type->sequence.itemType;
+    if (itemType->type == DYN_TYPE_REF) {
+        itemType = itemType->ref.ref;
+    }
+    return 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;
+}
+
+ffi_type *dynType_ffiType(dyn_type *type) {
+    if (type->type == DYN_TYPE_REF) {
+        return type->ref.ref->ffiType;
+    }
+    return type->ffiType;
+}
+
+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 type_entry *entry = NULL;
+    if (type->referenceTypes != NULL) {
+        TAILQ_FOREACH(entry, type->referenceTypes, entries) {
+            LOG_DEBUG("checking ref type '%s' with name '%s'", entry->type->name, name);
+            if (strcmp(name, entry->type->name) == 0) {
+                result = entry->type;
+                break;
+            }
+        }
+    }
+
+    if (result == NULL) {
+        struct type_entry *nEntry = NULL;
+        TAILQ_FOREACH(nEntry, &type->nestedTypesHead, entries) {
+            LOG_DEBUG("checking nested type '%s' with name '%s'", nEntry->type->name, name);
+            if (strcmp(name, nEntry->type->name) == 0) {
+                result = nEntry->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;
+}
+
+
+int dynType_typedPointer_getTypedType(dyn_type *type, dyn_type **out) {
+    assert(type->type == DYN_TYPE_TYPED_POINTER);
+    int status = 0;
+
+    dyn_type *typedType = type->typedPointer.typedType;
+    if (typedType->type == DYN_TYPE_REF) {
+        typedType = typedType->ref.ref;
+    }
+
+    *out = typedType;
+    return status;
+}
+
+
+int dynType_text_allocAndInit(dyn_type *type, void *textLoc, const char *value) {
+    assert(type->type == DYN_TYPE_TEXT);
+    int status = 0;
+    const char *str = strdup(value);
+    char const **loc = textLoc;
+    if (str != NULL) {
+        *loc = str;
+    } else {
+        status = ERROR;
+        LOG_ERROR("Cannot allocate memory for string");
+    }
+    return status;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void dynType_print(dyn_type *type, FILE *stream) {
+    if (type != NULL) {
+        dynType_printTypes(type, stream);
+
+        fprintf(stream, "main type:\n");
+        dynType_printAny("root", type, 0, stream);
+    } else {
+        fprintf(stream, "invalid type\n");
+    }
+}
+
+static void dynType_printDepth(int depth, FILE *stream) {
+    int i;
+    for (i = 0; i < depth; i +=1 ) {
+        fprintf(stream, "\t");
+    }
+}
+
+static void dynType_printAny(char *name, dyn_type *type, int depth, FILE *stream) {
+    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, stream);
+            break;
+        case DYN_TYPE_SIMPLE :
+            dynType_printSimple(name, toPrint, depth, stream);
+            break;
+        case DYN_TYPE_SEQUENCE :
+            dynType_printSequence(name, toPrint, depth, stream);
+            break;
+        case DYN_TYPE_TYPED_POINTER :
+            dynType_printTypedPointer(name, toPrint, depth, stream);
+            break;
+        default :
+            fprintf(stream, "TODO Unsupported type %i\n", toPrint->type);
+            break;
+    }
+}
+
+static void dynType_printComplex(char *name, dyn_type *type, int depth, FILE *stream) {
+    if (type->name == NULL) {
+        dynType_printDepth(depth, stream);
+        fprintf(stream, "%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, stream);
+        }
+
+        dynType_printDepth(depth, stream);
+        printf("}\n");
+    } else {
+        dynType_printDepth(depth, stream);
+        fprintf(stream, "%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, FILE *stream) {
+    dynType_printDepth(depth, stream);
+    fprintf(stream, "sequence, size is %zu, alignment is %i, descriptor is '%c'. fields:\n", type->ffiType->size, type->ffiType->alignment, type->descriptor);
+
+    dynType_printDepth(depth + 1, stream);
+    fprintf(stream, "cap: simple type, size is %zu, alignment is %i.\n", type->sequence.seqType.elements[0]->size, type->sequence.seqType.elements[0]->alignment);
+
+    dynType_printDepth(depth + 1, stream);
+    fprintf(stream, "len: simple type, size is %zu, alignment is %i.\n", type->sequence.seqType.elements[1]->size, type->sequence.seqType.elements[1]->alignment);
+
+    dynType_printDepth(depth + 1, stream);
+    fprintf(stream, "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, stream);
+}
+
+static void dynType_printSimple(char *name, dyn_type *type, int depth, FILE *stream) {
+    dynType_printDepth(depth, stream);
+    fprintf(stream, "%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, FILE *stream) {
+    dynType_printDepth(depth, stream);
+    fprintf(stream, "%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, stream);
+}
+
+static void dynType_printTypes(dyn_type *type, FILE *stream) {
+
+    dyn_type *parent = type->parent;
+    struct type_entry *pentry = NULL;
+    while (parent != NULL) {
+        TAILQ_FOREACH(pentry, &parent->nestedTypesHead, entries) {
+            if (pentry->type == type) {
+                return;
+            }
+        }
+        parent = parent->parent;
+    }
+
+    struct type_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, stream);
+                break;
+            case DYN_TYPE_SIMPLE :
+                dynType_printSimpleType(toPrint, stream);
+                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, stream);
+            }
+            break;
+        case DYN_TYPE_SEQUENCE :
+            dynType_printTypes(type->sequence.itemType, stream);
+            break;
+        case DYN_TYPE_TYPED_POINTER :
+            dynType_printTypes(type->typedPointer.typedType, stream);
+            break;
+    }
+}
+
+static void dynType_printComplexType(dyn_type *type, FILE *stream) {
+    fprintf(stream, "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, stream);
+    }
+
+    fprintf(stream, "}\n");
+}
+
+static void dynType_printSimpleType(dyn_type *type, FILE *stream) {
+    fprintf(stream, "\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/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.h
new file mode 100644
index 0000000..9fdbff2
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.h
@@ -0,0 +1,140 @@
+/**
+ * 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>
+#include <stdint.h>
+
+#include "dfi_log_util.h"
+
+#if defined(BSD) || defined(__APPLE__) 
+#include "open_memstream.h"
+#include "fmemopen.h"
+#endif
+
+/* Description string
+ *
+ * Type = [TypeDef]* (SimpleType | ComplexType | SequenceType | TypedPointer | PointerReference ) [TypeDef]* [Annotation]*
+ * Name = alpha[(alpha|numeric)*]
+ * SPACE = ' ' 
+ *
+ * SimplesTypes (based on java bytecode method signatures)
+ * //Java based:
+ * B char
+ * C (not supported)
+ * D double
+ * F float
+ * I int32_t 
+ * J int64_t 
+ * S int16_t 
+ * V void
+ * Z boolean
+ * //Extended
+ * b unsigned char
+ * i uint32_t
+ * j uint62_t
+ * s uint64_t
+ * P untyped pointer (void *)
+ * t char* string
+ * N native int
+ *
+ * ComplexTypes (Struct)
+ * {[Type]+ [(Name)(SPACE)]+}
+ *
+ * ReferenceByValue
+ * l(name);
+ *
+ * PointerReference -> note shortcut for *l(name);
+ * L(Name);
+ *
+ * TypeDef 
+ * T(Name)=Type;
+ *
+ * SequenceType
+ * [(Type)
+ *
+ * TypedPointer
+ * *(Type)
+ *
+ * Annotation TODO
+ * <(Name)=(Value)>
+ *
+ * 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_TEXT 5
+#define DYN_TYPE_REF 6
+
+typedef struct _dyn_type dyn_type;
+
+//TODO rename
+TAILQ_HEAD(types_head, type_entry);
+struct type_entry {
+    dyn_type *type;
+    TAILQ_ENTRY(type_entry) entries;
+};
+
+TAILQ_HEAD(complex_type_entries_head, complex_type_entry);
+struct complex_type_entry {
+    dyn_type *type;
+    char *name;
+    TAILQ_ENTRY(complex_type_entry) entries;
+};
+
+//logging
+DFI_SETUP_LOG_HEADER(dynType);
+
+//generic
+int dynType_parse(FILE *descriptorStream, const char *name, struct types_head *refTypes, dyn_type **type);
+int dynType_parseWithStr(const char *descriptor, const char *name, struct types_head *refTypes, dyn_type **type);
+void dynType_destroy(dyn_type *type);
+
+int dynType_alloc(dyn_type *type, void **bufLoc);
+void dynType_free(dyn_type *type, void *loc);
+
+void dynType_print(dyn_type *type, FILE *stream);
+size_t dynType_size(dyn_type *type);
+int dynType_type(dyn_type *type);
+int dynType_descriptorType(dyn_type *type);
+ffi_type *dynType_ffiType(dyn_type *type);
+
+//complexType
+int dynType_complex_indexForName(dyn_type *type, const char *name);
+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);
+int dynType_complex_entries(dyn_type *type, struct complex_type_entries_head **entries);
+
+//sequence
+int dynType_sequence_alloc(dyn_type *type, void *inst, uint32_t cap);
+int dynType_sequence_locForIndex(dyn_type *type, void *seqLoc, int index, void **valLoc);
+int dynType_sequence_increaseLengthAndReturnLastLoc(dyn_type *type, void *seqLoc, void **valLoc);
+dyn_type * dynType_sequence_itemType(dyn_type *type);
+uint32_t dynType_sequence_length(void *seqLoc);
+
+//typed pointer
+int dynType_typedPointer_getTypedType(dyn_type *type, dyn_type **typedType);
+
+//text
+int dynType_text_allocAndInit(dyn_type *type, void *textLoc, const char *value);
+
+//simple
+void dynType_simple_setValue(dyn_type *type, void *inst, void *in);
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.c
new file mode 100644
index 0000000..614e948
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.c
@@ -0,0 +1,414 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "json_serializer.h"
+#include "dyn_type.h"
+
+#include <jansson.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+static int jsonSerializer_createObject(dyn_type *type, json_t *object, void **result);
+static int jsonSerializer_parseObject(dyn_type *type, json_t *object, void *inst);
+static int jsonSerializer_parseObjectMember(dyn_type *type, const char *name, json_t *val, void *inst);
+static int jsonSerializer_parseSequence(dyn_type *seq, json_t *array, void *seqLoc);
+static int jsonSerializer_parseAny(dyn_type *type, void *input, json_t *val);
+
+static int jsonSerializer_writeAny(dyn_type *type, void *input, json_t **val);
+
+static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **val);
+
+static int jsonSerializer_writeSequence(dyn_type *type, void *input, json_t **out);
+
+static int OK = 0;
+static int ERROR = 1;
+
+DFI_SETUP_LOG(jsonSerializer);
+
+int jsonSerializer_deserialize(dyn_type *type, const char *input, void **result) {
+    assert(dynType_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) {
+        if (json_is_object(root)) {
+            status = jsonSerializer_createObject(type, root, result);
+        } else {
+            status = ERROR;
+            LOG_ERROR("Error expected root element to be an object");
+        }
+        json_decref(root);
+    } else {
+        status = ERROR;
+        LOG_ERROR("Error parsing json input '%s'. Error is %s\n", input, error.text);
+    }
+
+    return status;
+}
+
+static int jsonSerializer_createObject(dyn_type *type, json_t *object, void **result) {
+    assert(object != NULL);
+    int status = OK;
+
+    void *inst = NULL;
+    status = dynType_alloc(type, &inst);
+
+    if (status == OK) {
+        assert(inst != NULL);
+        status = jsonSerializer_parseObject(type, object, inst);
+
+        if (status != OK) {
+            dynType_free(type, inst);
+        }
+    }
+
+    if (status == OK) {
+        *result = inst;
+    }
+
+    return status;
+}
+
+static int jsonSerializer_parseObject(dyn_type *type, json_t *object, void *inst) {
+    assert(object != NULL);
+    int status = 0;
+    json_t *value;
+    const char *key;
+
+    json_object_foreach(object, key, value) {
+        status = jsonSerializer_parseObjectMember(type, key, value, inst);
+        if (status != OK) {
+            break;
+        }
+    }
+
+    return status;
+}
+
+static int jsonSerializer_parseObjectMember(dyn_type *type, const char *name, json_t *val, void *inst) {
+    int status = OK;
+    int index = dynType_complex_indexForName(type, name);
+    void *valp = NULL;
+    dyn_type *valType = NULL;
+
+    status = dynType_complex_valLocAt(type, index, inst, &valp);
+
+    if (status == OK ) {
+        status = dynType_complex_dynTypeAt(type, index, &valType);
+    }
+
+    if (status == OK) {
+        status = jsonSerializer_parseAny(valType, valp, val);
+    }
+
+    return status;
+}
+
+static int jsonSerializer_parseAny(dyn_type *type, void *loc, json_t *val) {
+    int status = OK;
+
+    dyn_type *subType = NULL;
+    char c = dynType_descriptorType(type);
+
+    float *f;           //F
+    double *d;          //D
+    char *b;            //B
+    int *n;             //N
+    int16_t *s;         //S
+    int32_t *i;         //I
+    int64_t *l;         //J
+    uint16_t  *us;      //s
+    uint32_t  *ui;      //i
+    uint64_t  *ul;      //j
+
+    switch (c) {
+        case 'F' :
+            f = loc;
+            *f = (float) json_real_value(val);
+            break;
+        case 'D' :
+            d = loc;
+            *d = json_real_value(val);
+            break;
+        case 'N' :
+            n = loc;
+            *n = (int) json_real_value(val);
+            break;
+        case 'B' :
+            b = loc;
+            *b = (char) json_integer_value(val);
+            break;
+        case 'S' :
+            s = loc;
+            *s = (int16_t) json_integer_value(val);
+            break;
+        case 'I' :
+            i = loc;
+            *i = (int32_t) json_integer_value(val);
+            break;
+        case 'J' :
+            l = loc;
+            *l = (int64_t) json_integer_value(val);
+            break;
+        case 's' :
+            us = loc;
+            *us = (uint16_t) json_integer_value(val);
+            break;
+        case 'i' :
+            ui = loc;
+            *ui = (uint32_t) json_integer_value(val);
+            break;
+        case 'j' :
+            ul = loc;
+            *ul = (uint64_t) json_integer_value(val);
+            break;
+        case 't' :
+            if (json_is_string(val)) {
+                dynType_text_allocAndInit(type, loc, json_string_value(val));
+            } else {
+                status = ERROR;
+                LOG_ERROR("Expected json string type got %i", json_typeof(val));
+            }
+            break;
+        case '[' :
+            if (json_is_array(val)) {
+                status = jsonSerializer_parseSequence(type, val, loc);
+            } else {
+                status = ERROR;
+                LOG_ERROR("Expected json array type got '%i'", json_typeof(val));
+            }
+            break;
+        case '{' :
+            if (status == OK) {
+                status = jsonSerializer_parseObject(type, val, loc);
+            }
+            break;
+        case '*' :
+            status = dynType_typedPointer_getTypedType(type, &subType);
+            if (status == OK) {
+                status = jsonSerializer_createObject(subType, val, (void **)loc);
+            }
+            break;
+        case 'P' :
+            status = ERROR;
+            LOG_WARNING("Untyped pointer are not supported for serialization");
+            break;
+        default :
+            status = ERROR;
+            LOG_ERROR("Error provided type '%c' not supported for JSON\n", dynType_descriptorType(type));
+            break;
+    }
+
+    return status;
+}
+
+static int jsonSerializer_parseSequence(dyn_type *seq, json_t *array, void *seqLoc) {
+    assert(dynType_type(seq) == DYN_TYPE_SEQUENCE);
+    int status = OK;
+
+    size_t size = json_array_size(array);
+    LOG_DEBUG("Allocating sequence with capacity %zu", size);
+    status = dynType_sequence_alloc(seq, seqLoc, (int) size);
+
+    if (status == OK) {
+        dyn_type *itemType = dynType_sequence_itemType(seq);
+        size_t index;
+        json_t *val;
+        json_array_foreach(array, index, val) {
+            void *valLoc = NULL;
+            status = dynType_sequence_increaseLengthAndReturnLastLoc(seq, seqLoc, &valLoc);
+            LOG_DEBUG("Got sequence loc %p", valLoc);
+
+            if (status == OK) {
+                status = jsonSerializer_parseAny(itemType, valLoc, val);
+                if (status != OK) {
+                    break;
+                }
+            }
+        }
+    }
+
+    return status;
+}
+
+int jsonSerializer_serialize(dyn_type *type, void *input, char **output) {
+    int status = OK;
+
+    json_t *root = NULL;
+    status = jsonSerializer_writeAny(type, input, &root);
+
+    if (status == OK) {
+        *output = json_dumps(root, JSON_COMPACT);
+        json_decref(root);
+    }
+
+    return status;
+}
+
+static int jsonSerializer_writeAny(dyn_type *type, void *input, json_t **out) {
+    int status = OK;
+
+    int descriptor = dynType_descriptorType(type);
+    json_t *val = NULL;
+    dyn_type *subType = NULL;
+
+    float *f;           //F
+    double *d;          //D
+    char *b;            //B
+    int *n;             //N
+    int16_t *s;         //S
+    int32_t *i;         //I
+    int64_t *l;         //J
+    uint16_t  *us;      //s
+    uint32_t  *ui;      //i
+    uint64_t  *ul;      //j
+
+    switch (descriptor) {
+        case 'B' :
+            b = input;
+            val = json_integer((json_int_t)*b);
+            break;
+        case 'S' :
+            s = input;
+            val = json_integer((json_int_t)*s);
+            break;
+        case 'I' :
+            i = input;
+            val = json_integer((json_int_t)*i);
+            break;
+        case 'J' :
+            l = input;
+            val = json_integer((json_int_t)*l);
+            break;
+        case 's' :
+            us = input;
+            val = json_integer((json_int_t)*us);
+            break;
+        case 'i' :
+            ui = input;
+            val = json_integer((json_int_t)*ui);
+            break;
+        case 'j' :
+            ul = input;
+            val = json_integer((json_int_t)*ul);
+            break;
+        case 'N' :
+            n = input;
+            val = json_integer((json_int_t)*n);
+            break;
+        case 'F' :
+            f = input;
+            val = json_real((double) *f);
+            break;
+        case 'D' :
+            d = input;
+            val = json_real(*d);
+            break;
+        case 't' :
+            val = json_string(*(const char **) input);
+            break;
+        case '*' :
+            status = dynType_typedPointer_getTypedType(type, &subType);
+            if (status == OK) {
+                status = jsonSerializer_writeAny(subType, *(void **)input, &val);
+            }
+            break;
+        case '{' :
+            status = jsonSerializer_writeComplex(type, input, &val);
+            break;
+        case '[' :
+            status = jsonSerializer_writeSequence(type, input, &val);
+            break;
+        case 'P' :
+            LOG_WARNING("Untyped pointer not supported for serialization. ignoring");
+            break;
+        default :
+            LOG_ERROR("Unsupported descriptor '%c'", descriptor);
+            status = ERROR;
+            break;
+    }
+
+    if (status == OK && val != NULL) {
+        *out = val;
+    }
+
+    return status;
+}
+
+static int jsonSerializer_writeSequence(dyn_type *type, void *input, json_t **out) {
+    assert(dynType_type(type) == DYN_TYPE_SEQUENCE);
+    int status = OK;
+
+    json_t *array = json_array();
+    dyn_type *itemType = dynType_sequence_itemType(type);
+    uint32_t len = dynType_sequence_length(input);
+
+    int i = 0;
+    void *itemLoc = NULL;
+    json_t *item = NULL;
+    for (i = 0; i < len; i += 1) {
+        item = NULL;
+        status = dynType_sequence_locForIndex(type, input, i, &itemLoc);
+        if (status == OK) {
+            status = jsonSerializer_writeAny(itemType, itemLoc, &item);
+            if (status == OK) {
+                json_array_append(array, item);
+                json_decref(item);
+            }
+        }
+
+        if (status != OK) {
+            break;
+        }
+    }
+
+    if (status == OK && array != NULL) {
+        *out = array;
+    }
+
+    return status;
+}
+
+static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **out) {
+    assert(dynType_type(type) == DYN_TYPE_COMPLEX);
+    int status = OK;
+
+    json_t *val = json_object();
+    struct complex_type_entry *entry = NULL;
+    struct complex_type_entries_head *entries = NULL;
+    int index = -1;
+
+    status = dynType_complex_entries(type, &entries);
+    if (status == OK) {
+        TAILQ_FOREACH(entry, entries, entries) {
+            void *subLoc = NULL;
+            json_t *subVal = NULL;
+            dyn_type *subType = NULL;
+            index = dynType_complex_indexForName(type, entry->name);
+            status = dynType_complex_valLocAt(type, index, input, &subLoc);
+            if (status == OK ) {
+                status = dynType_complex_dynTypeAt(type, index, &subType);
+            }
+            if (status == OK) {
+                status = jsonSerializer_writeAny(subType, subLoc, &subVal);
+            }
+            if (status == OK) {
+                json_object_set(val, entry->name, subVal);
+                json_decref(subVal);
+            }
+
+            if (status != OK) {
+                break;
+            }
+        }
+    }
+
+    if (status == OK && val != NULL) {
+        *out = val;
+    }
+
+    return status;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.h
new file mode 100644
index 0000000..eb2e629
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_serializer.h
@@ -0,0 +1,16 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef __JSON_SERIALIZER_H_
+#define __JSON_SERIALIZER_H_
+
+#include "dfi_log_util.h"
+#include "dyn_type.h"
+
+//logging
+DFI_SETUP_LOG_HEADER(jsonSerializer);
+
+int jsonSerializer_deserialize(dyn_type *type, const char *input, void **result);
+int jsonSerializer_serialize(dyn_type *type, void *input, char **output);
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/README.md
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/README.md b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/README.md
new file mode 100644
index 0000000..476810e
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/README.md
@@ -0,0 +1,49 @@
+fmemopen for Mac OS and iOS
+===========================
+
+Originally ported from [ingenuitas python-tesseract](https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c). Ported by Jeff Verkoeyen under the Apache 2.0 License.
+
+From the fmemopen man page:
+
+> FILE *fmemopen(void *buf, size_t size, const char *mode);
+>
+> The fmemopen() function opens a stream that permits the access specified by mode. The stream
+> allows I/O to be performed on the string or memory buffer pointed to by buf. This buffer must be
+> at least size bytes long.
+
+Alas, this method does not exist on BSD operating systems (specifically Mac OS X and iOS). It is
+possible to recreate this functionality using a BSD-specific method called `funopen`.
+
+From the funopen man page:
+
+> FILE * funopen(const void *cookie, int (*readfn)(void *, char *, int),
+>                int (*writefn)(void *, const char *, int), fpos_t (*seekfn)(void *, fpos_t, int),
+>                int (*closefn)(void *));
+>
+> The funopen() function associates a stream with up to four ``I/O functions''.  Either readfn or
+> writefn must be specified; the others can be given as an appropriately-typed NULL pointer.  These
+> I/O functions will be used to read, write, seek and close the new stream.
+
+fmemopen.c provides a simple implementation of fmemopen using funopen so that you can create FILE
+pointers to blocks of memory.
+
+Adding it to your Project
+=========================
+
+Drag fmemopen.h and fmemopen.c to your project and add them to your target. `#include "fmemopen.h"`
+wherever you need to use `fmemopen`.
+
+Examples
+========
+
+```obj-c
+#import "fmemopen.h"
+
+NSString* string = @"fmemopen in Objective-C";
+const char* cstr = [string UTF8String];
+FILE* file = fmemopen((void *)cstr, sizeof(char) * (string.length + 1), "r");
+
+// fread on file will now read the contents of the NSString
+
+fclose(file);
+```

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.c
new file mode 100644
index 0000000..926ce36
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.c
@@ -0,0 +1,78 @@
+/*
+ * fmem.c : fmemopen() on top of BSD's funopen()
+ * 20081017 AF
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef linux
+struct fmem {
+    size_t pos;
+    size_t size;
+    char *buffer;
+};
+typedef struct fmem fmem_t;
+
+static int readfn(void *handler, char *buf, int size)
+{
+    int count = 0;
+    fmem_t *mem = handler;
+    size_t available = mem->size - mem->pos;
+
+    if(size > available) size = available;
+    for(count=0; count < size; mem->pos++, count++)
+        buf[count] = mem->buffer[mem->pos];
+
+    return count;
+}
+
+static int writefn(void *handler, const char *buf, int size)
+{
+    int count = 0;
+    fmem_t *mem = handler;
+    size_t available = mem->size - mem->pos;
+
+    if(size > available) size = available;
+    for(count=0; count < size; mem->pos++, count++)
+        mem->buffer[mem->pos] = buf[count];
+
+    return count; // ? count : size;
+}
+
+static fpos_t seekfn(void *handler, fpos_t offset, int whence)
+{
+    size_t pos;
+    fmem_t *mem = handler;
+
+    switch(whence) {
+        case SEEK_SET: pos = offset; break;
+        case SEEK_CUR: pos = mem->pos + offset; break;
+        case SEEK_END: pos = mem->size + offset; break;
+        default: return -1;
+    }
+
+    if(pos < 0 || pos > mem->size) return -1;
+
+    mem->pos = pos;
+    return (fpos_t) pos;
+}
+
+static int closefn(void *handler)
+{
+    free(handler);
+    return 0;
+}
+
+/* simple, but portable version of fmemopen for OS X / BSD */
+FILE *fmemopen(void *buf, size_t size, const char *mode)
+{
+    fmem_t *mem = (fmem_t *) malloc(sizeof(fmem_t));
+
+    memset(mem, 0, sizeof(fmem_t));
+    mem->size = size, mem->buffer = buf;
+    return funopen(mem, readfn, writefn, seekfn, closefn);
+}
+#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.h
new file mode 100644
index 0000000..3d06b20
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/fmemopen.h
@@ -0,0 +1,52 @@
+//
+// Copyright 2012 Jeff Verkoeyen
+// Originally ported from https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef FMEMOPEN_H_
+#define FMEMOPEN_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * A BSD port of the fmemopen Linux method using funopen.
+ *
+ * man docs for fmemopen:
+ * http://linux.die.net/man/3/fmemopen
+ *
+ * man docs for funopen:
+ * https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/funopen.3.html
+ *
+ * This method is ported from ingenuitas' python-tesseract project.
+ *
+ * You must call fclose on the returned file pointer or memory will be leaked.
+ *
+ *      @param buf The data that will be used to back the FILE* methods. Must be at least
+ *                 @c size bytes.
+ *      @param size The size of the @c buf data.
+ *      @param mode The permitted stream operation modes.
+ *      @returns A pointer that can be used in the fread/fwrite/fseek/fclose family of methods.
+ *               If a failure occurred NULL will be returned.
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef FMEMOPEN_H_

http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.c
new file mode 100644
index 0000000..6bc4f01
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.c
@@ -0,0 +1,130 @@
+/* Use funopen(3) to provide open_memstream(3) like functionality. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct memstream {
+	char **cp;
+	size_t *lenp;
+	size_t offset;
+};
+
+static void
+memstream_grow(struct memstream *ms, size_t newsize)
+{
+	char *buf;
+
+	if (newsize > *ms->lenp) {
+		buf = realloc(*ms->cp, newsize + 1);
+		if (buf != NULL) {
+#ifdef DEBUG
+			fprintf(stderr, "MS: %p growing from %zd to %zd\n",
+			    ms, *ms->lenp, newsize);
+#endif
+			memset(buf + *ms->lenp + 1, 0, newsize - *ms->lenp);
+			*ms->cp = buf;
+			*ms->lenp = newsize;
+		}
+	}
+}
+
+static int
+memstream_read(void *cookie, char *buf, int len)
+{
+	struct memstream *ms;
+	int tocopy;
+
+	ms = cookie;
+	memstream_grow(ms, ms->offset + len);
+	tocopy = *ms->lenp - ms->offset;
+	if (len < tocopy)
+		tocopy = len;
+	memcpy(buf, *ms->cp + ms->offset, tocopy);
+	ms->offset += tocopy;
+#ifdef DEBUG
+	fprintf(stderr, "MS: read(%p, %d) = %d\n", ms, len, tocopy);
+#endif
+	return (tocopy);
+}
+
+static int
+memstream_write(void *cookie, const char *buf, int len)
+{
+	struct memstream *ms;
+	int tocopy;
+
+	ms = cookie;
+	memstream_grow(ms, ms->offset + len);
+	tocopy = *ms->lenp - ms->offset;
+	if (len < tocopy)
+		tocopy = len;
+	memcpy(*ms->cp + ms->offset, buf, tocopy);
+	ms->offset += tocopy;
+#ifdef DEBUG
+	fprintf(stderr, "MS: write(%p, %d) = %d\n", ms, len, tocopy);
+#endif
+	return (tocopy);
+}
+
+static fpos_t
+memstream_seek(void *cookie, fpos_t pos, int whence)
+{
+	struct memstream *ms;
+#ifdef DEBUG
+	size_t old;
+#endif
+
+	ms = cookie;
+#ifdef DEBUG
+	old = ms->offset;
+#endif
+	switch (whence) {
+	case SEEK_SET:
+		ms->offset = pos;
+		break;
+	case SEEK_CUR:
+		ms->offset += pos;
+		break;
+	case SEEK_END:
+		ms->offset = *ms->lenp + pos;
+		break;
+	}
+#ifdef DEBUG
+	fprintf(stderr, "MS: seek(%p, %zd, %d) %zd -> %zd\n", ms, pos, whence,
+	    old, ms->offset);
+#endif
+	return (ms->offset);
+}
+
+static int
+memstream_close(void *cookie)
+{
+
+	free(cookie);
+	return (0);
+}
+
+FILE *
+open_memstream(char **cp, size_t *lenp)
+{
+	struct memstream *ms;
+	int save_errno;
+	FILE *fp;
+
+	*cp = NULL;
+	*lenp = 0;
+	ms = malloc(sizeof(*ms));
+	ms->cp = cp;
+	ms->lenp = lenp;
+	ms->offset = 0;
+	fp = funopen(ms, memstream_read, memstream_write, memstream_seek,
+	    memstream_close);
+	if (fp == NULL) {
+		save_errno = errno;
+		free(ms);
+		errno = save_errno;
+	}
+	return (fp);
+}
\ No newline at end of file


Mime
View raw message