You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2015/07/12 21:50:09 UTC

celix git commit: CELIX-237: Added dyn_interface implementation. dyn_interface works on top of dyn_type and dyn_function

Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-237_rsa-ffi 08b5bc0ca -> 3cc606e8e


CELIX-237: Added dyn_interface implementation. dyn_interface works on top  of dyn_type and dyn_function


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/3cc606e8
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/3cc606e8
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/3cc606e8

Branch: refs/heads/feature/CELIX-237_rsa-ffi
Commit: 3cc606e8e9837fa7dbc5f471121b66dba8c8c89c
Parents: 08b5bc0
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Sun Jul 12 21:54:31 2015 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Sun Jul 12 21:54:31 2015 +0200

----------------------------------------------------------------------
 .../dynamic_function_interface/CMakeLists.txt   |   2 +
 .../dynamic_function_interface/dyn_common.c     |  55 ++++++-
 .../dynamic_function_interface/dyn_common.h     |   4 +-
 .../dynamic_function_interface/dyn_interface.c  | 158 +++++++++++++++++--
 .../dynamic_function_interface/dyn_interface.h  |  26 +--
 .../tst/dyn_interface_tests.cpp                 |  61 +++++++
 6 files changed, 279 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/3cc606e8/remote_services/dynamic_function_interface/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/CMakeLists.txt b/remote_services/dynamic_function_interface/CMakeLists.txt
index 0c69d92..309176f 100644
--- a/remote_services/dynamic_function_interface/CMakeLists.txt
+++ b/remote_services/dynamic_function_interface/CMakeLists.txt
@@ -35,6 +35,7 @@ target_link_libraries(dfi ${FFI_LIBRARIES} ${JANSSON_LIBRARY})
 	    tst/dyn_type_tests.cpp
 	    tst/dyn_function_tests.cpp
 	    tst/dyn_closure_tests.cpp
+        tst/dyn_interface_tests.cpp
 	    tst/json_serializer_tests.cpp
 #	    tst/avro_descriptor_translator_tests.cpp
 	    tst/run_tests.cpp
@@ -43,6 +44,7 @@ target_link_libraries(dfi ${FFI_LIBRARIES} ${JANSSON_LIBRARY})
 
 	add_custom_target(copy-input 
 	    COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/schemas schemas
+	    COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/descriptors descriptors
 	)
 	add_dependencies(dfi_tests copy-input)
 

http://git-wip-us.apache.org/repos/asf/celix/blob/3cc606e8/remote_services/dynamic_function_interface/dyn_common.c
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_common.c b/remote_services/dynamic_function_interface/dyn_common.c
index c0d5ca0..05844ef 100644
--- a/remote_services/dynamic_function_interface/dyn_common.c
+++ b/remote_services/dynamic_function_interface/dyn_common.c
@@ -3,6 +3,7 @@
  */
 #include "dyn_common.h"
 
+#include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
 
@@ -21,6 +22,7 @@ int dynCommon_parseName(FILE *stream, char **result) {
 
     char *buf = NULL;
     size_t size = 0;
+    int strLen = 0;
     FILE *name = open_memstream(&buf, &size);
 
     if (name != NULL) { 
@@ -28,14 +30,65 @@ int dynCommon_parseName(FILE *stream, char **result) {
         while (isalnum(c) || c == '_') {
             fputc(c, name); 
             c = getc(stream);
+            strLen += 1;
         }
         fflush(name);
         fclose(name);
-        *result = buf;
         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");
+            free(buf);
+        }
+    }
+
+    if (status == OK) {
+       LOG_DEBUG("Parsed name '%s'", buf);
+       *result = buf;
+    } 
+
+    return status;
+}
+
+int dynCommon_parseNameValue(FILE *stream, char **outName, char **outValue) {
+    int status = OK;
+    char *name = NULL;
+    char *value = NULL;
+
+    status = dynCommon_parseName(stream, &name);
+    if (status == OK) {
+        status = dynCommon_eatChar(stream, '=');
+    }
+    if (status == OK) {
+        status = dynCommon_parseName(stream, &value); //TODO use different more lenient function?
+    }
+
+    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;
+    int c = fgetc(stream);
+    if (c != expected) {
+        status = ERROR;
+        LOG_ERROR("Error parsing, expected token '%c' got '%c'", expected, c);
+    }
     return status;
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/3cc606e8/remote_services/dynamic_function_interface/dyn_common.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_common.h b/remote_services/dynamic_function_interface/dyn_common.h
index 8a9491a..16df6e2 100644
--- a/remote_services/dynamic_function_interface/dyn_common.h
+++ b/remote_services/dynamic_function_interface/dyn_common.h
@@ -24,8 +24,8 @@ struct _dyn_annotation_type {
 };
 
 int dynCommon_parseName(FILE *stream, char **result);
-//TODO int dynCommon_parseNameValue(FILE *stream, char **name, char **value);
-//TODO int dynCommon_parseAnnotation(FILE *stream, 
+int dynCommon_parseNameValue(FILE *stream, char **name, char **value);
+int dynCommon_eatChar(FILE *stream, int c);
 
 
 #endif 

http://git-wip-us.apache.org/repos/asf/celix/blob/3cc606e8/remote_services/dynamic_function_interface/dyn_interface.c
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_interface.c b/remote_services/dynamic_function_interface/dyn_interface.c
index 1fbb831..a563eab 100644
--- a/remote_services/dynamic_function_interface/dyn_interface.c
+++ b/remote_services/dynamic_function_interface/dyn_interface.c
@@ -6,31 +6,139 @@
 #include <stdlib.h>
 #include <string.h>
 
-DFI_SETUP_LOG(dynInterface)
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "dyn_interface.h"
 
-int dynInterface_create(const char *name, dyn_interface_type **out) {
-    int status = 0;
-    dyn_interface_type *inft = calloc(1, sizeof(*inft));
-    if (inft != NULL) {
-        inft->name = strdup(name);
-    }
-    if (inft == NULL || inft->name == NULL) {
-        status = 1;
+DFI_SETUP_LOG(dynInterface);
+
+const int OK = 0;
+const int ERROR = 1;
+
+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);
+
+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->annotations);
+        TAILQ_INIT(&intf->types);
+        TAILQ_INIT(&intf->methods);
+
+        status = dynInterface_parseAnnotations(intf, descriptor);
+        if (status == OK) {
+            status =dynInterface_parseTypes(intf, descriptor);
+        }
+        if (status == OK) {
+            status = dynInterface_parseMethods(intf, descriptor);
+        }
+    } else {
+        status = ERROR;
         LOG_ERROR("Error allocating memory for dynamic interface\n");
     }
 
-    if (status == 0) {
-        TAILQ_INIT(&inft->types);
-        TAILQ_INIT(&inft->methods);
+    if (status == OK) {
+        *out = intf;
+    } else if (intf != NULL) {
+        dynInterface_destroy(intf);
     }
-    *out = inft;
+    return status;
+}
+
+static int dynInterface_parseAnnotations(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("annotations", sectionName) == 0) {
+            LOG_DEBUG("Parsed annotations section header");
+        } else {
+            status = ERROR;
+            LOG_ERROR("Expected annotations section, got '%s'", sectionName);
+        }
+    }
+
+    if (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');
+            }
+
+            if (status == OK) {
+                interface_namval_type *entry = calloc(1, sizeof(*entry));
+                if (entry != NULL) {
+                    entry->name = name;
+                    entry->value = value;
+                    TAILQ_INSERT_TAIL(&intf->annotations, 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);
+                }
+                break;
+            }
+            peek = fgetc(stream);
+        }
+        ungetc(peek, stream);
+    }
+    
+    return status;
+}
+
+static int dynInterface_parseTypes(dyn_interface_type *intf, FILE *stream) {
+    int status = OK;
+    //TODO implement -> extract section parse part  from parseAnnotations first?
+    return status;
+}
+
+static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream) {
+    int status = OK;
+    //TODO refactor
     return status;
 }
 
 void dynInterface_destroy(dyn_interface_type *intf) {
     if (intf != NULL) {
-        if (intf->name != NULL) {
-            free(intf->name);
+        interface_namval_type *nTmp = NULL;
+        interface_namval_type *nEntry = TAILQ_FIRST(&intf->annotations);
+        while (nEntry != NULL) {
+            nTmp = nEntry;
+            nEntry = TAILQ_NEXT(nEntry, entries);
+            if (nTmp->name != NULL) {
+                free(nTmp->name);
+            }
+            if (nTmp->value != NULL) {
+                free(nTmp->value);
+            }
+            free(nTmp);
         }
 
         interface_type_type *tmp = NULL;
@@ -68,3 +176,23 @@ void dynInterface_destroy(dyn_interface_type *intf) {
     } 
 }
 
+//TODO refactor using a dynInterface_findAnnotation method
+int dynInterface_getName(dyn_interface_type *intf, char **out) {
+    int status = OK;
+    char *name = NULL;
+    interface_namval_type *entry = NULL;
+    TAILQ_FOREACH(entry, &intf->annotations, entries) {
+        if (strcmp("name", entry->name) == 0) {
+            name = entry->value;
+            break;
+        }
+    }
+
+    if (name != NULL) {
+        *out = name;
+    } else {
+        status = ERROR;
+        LOG_WARNING("Cannot find 'name' in dyn interface annotations");
+    }
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3cc606e8/remote_services/dynamic_function_interface/dyn_interface.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_interface.h b/remote_services/dynamic_function_interface/dyn_interface.h
index 77eefb8..a574496 100644
--- a/remote_services/dynamic_function_interface/dyn_interface.h
+++ b/remote_services/dynamic_function_interface/dyn_interface.h
@@ -10,23 +10,29 @@
 
 DFI_SETUP_LOG_HEADER(dynInterface);
 
+/* Description string
+ *
+ * Descriptor = [Section]*
+ * Section = SecionHeader | Body
+ * SectionHeader = ':' (Name)
+ * SectionBody = subDescriptor '\n\
+ *
+ * expected sections: header, types & mehods
+ */
+
 typedef struct _dyn_interface_type dyn_interface_type;
 
 struct _dyn_interface_type {
-    char *name;
-    int versionMajor;
-    int versionMinor;
-    int versionMicro;
-    TAILQ_HEAD(, _interface_annotation_type) annotations;
+    TAILQ_HEAD(, _interface_namval_type) annotations;
     TAILQ_HEAD(, _interface_type_type) types;
     TAILQ_HEAD(, _interface_method_type) methods;
 };
 
-typedef struct _interface_annotation_type interface_annotation_type;
-struct _interface_annotation_type {
+typedef struct _interface_namval_type interface_namval_type;
+struct _interface_namval_type {
     char *name;
     char *value;
-    TAILQ_ENTRY(_interface_annotation_type) entries;
+    TAILQ_ENTRY(_interface_namval_type) entries;
 };
 
 typedef struct _interface_method_type interface_method_type;
@@ -46,8 +52,10 @@ struct _interface_type_type {
     TAILQ_ENTRY(_interface_type_type) entries;
 };
 
-int dynInterface_parse(const FILE *descriptor, dyn_interface_type **out);
+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);
+
 
 #endif

http://git-wip-us.apache.org/repos/asf/celix/blob/3cc606e8/remote_services/dynamic_function_interface/tst/dyn_interface_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/tst/dyn_interface_tests.cpp b/remote_services/dynamic_function_interface/tst/dyn_interface_tests.cpp
new file mode 100644
index 0000000..68dae7a
--- /dev/null
+++ b/remote_services/dynamic_function_interface/tst/dyn_interface_tests.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 <assert.h>
+
+#include "dyn_common.h"
+#include "dyn_interface.h"
+
+#if defined(BSD) || defined(__APPLE__) 
+#include "open_memstream.h"
+#include "fmemopen.h"
+#endif
+
+    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");
+    }
+
+    static void test1(void) {
+        int status = 0;
+        dyn_interface_type *dynIntf = NULL;
+        FILE *desc = fopen("descriptors/example1.descriptor", "r");
+        assert(desc != NULL);
+        status = dynInterface_parse(desc, &dynIntf);
+        CHECK_EQUAL(0, status);
+
+        char *name = NULL;
+        status = dynInterface_getName(dynIntf, &name);
+        CHECK_EQUAL(0, status);
+        STRCMP_EQUAL("calculator", name); 
+        
+        dynInterface_destroy(dynIntf);
+    }
+
+}
+
+
+TEST_GROUP(DynInterfaceTests) {
+    void setup() {
+        dynCommon_logSetup(stdLog, NULL, 4);
+        dynType_logSetup(stdLog, NULL, 4);
+        dynFunction_logSetup(stdLog, NULL, 4);
+    }
+};
+
+TEST(DynInterfaceTests, test1) {
+    test1();
+}