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, §ionName);
+ }
+
+ 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();
+}