http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/dfi/CMakeLists.txt b/dfi/CMakeLists.txt index 3fd196b..ad3a41f 100644 --- a/dfi/CMakeLists.txt +++ b/dfi/CMakeLists.txt @@ -18,72 +18,56 @@ find_package(FFI REQUIRED) find_package(Jansson REQUIRED) -include_directories( - ${FFI_INCLUDE_DIRS} - ${JANSSON_INCLUDE_DIRS} - private/include - public/include - ${PROJECT_SOURCE_DIR}/utils/public/include +add_library(dfi SHARED + src/dyn_common.c + src/dyn_type.c + src/dyn_function.c + src/dyn_interface.c + src/dyn_message.c + src/json_serializer.c + src/json_rpc.c ) +set_target_properties(dfi PROPERTIES OUTPUT_NAME "celix_dfi") -set(MEMSTREAM_SOURCES ) -set(MEMSTREAM_INCLUDES ) -if (APPLE OR ANDROID) - set(MEMSTREAM_SOURCES ${PROJECT_SOURCE_DIR}/utils/private/src/memstream/open_memstream.c ${PROJECT_SOURCE_DIR}/utils/private/src/memstream/fmemopen.c) - set(MEMSTREAM_INCLUDES ${PROJECT_SOURCE_DIR}/utils/public/include/memstream/open_memstream.h ${PROJECT_SOURCE_DIR}/utils/public/include/memstream/fmemopen.h) - include_directories(${PROJECT_SOURCE_DIR}/utils/public/include/memstream) -endif() +target_include_directories(dfi PUBLIC + include + ${JANSSON_INCLUDE_DIRS} +) +target_include_directories(dfi PRIVATE + src + ${FFI_INCLUDE_DIRS} +) -add_library(celix_dfi SHARED - private/src/dyn_common.c - private/src/dyn_type.c - private/src/dyn_function.c - private/src/dyn_interface.c - private/src/dyn_message.c - private/src/json_serializer.c - private/src/json_rpc.c - ${MEMSTREAM_SOURCES} +target_link_libraries(dfi PUBLIC ${JANSSON_LIBRARY}) +target_link_libraries(dfi PRIVATE Celix::utils ${FFI_LIBRARIES}) - public/include/dyn_common.h - public/include/dyn_type.h - public/include/dyn_function.h - public/include/dyn_interface.h - public/include/dyn_message.h - public/include/json_serializer.h - public/include/json_rpc.h - ${MEMSTREAM_INCLUDES} -) -set_target_properties(celix_dfi PROPERTIES "SOVERSION" 1) -target_link_libraries(celix_dfi celix_utils ${FFI_LIBRARIES} ${JANSSON_LIBRARY}) +set_target_properties(dfi PROPERTIES "SOVERSION" 1) -install(TARGETS celix_dfi DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework) -FILE(GLOB files "public/include/*.h" ${MEMSTREAM_INCLUDES}) -INSTALL(FILES ${files} DESTINATION include/celix/dfi COMPONENT framework) +install(TARGETS dfi DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework) +#Alias setup to match external usage +add_library(Celix::dfi ALIAS dfi) + if (ENABLE_TESTING) find_package(CppUTest REQUIRED) - include_directories(${CPPUTEST_INCLUDE_DIR}) - SET(CMAKE_SKIP_BUILD_RPATH FALSE) #TODO needed? - SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) #TODO needed? - SET(CMAKE_INSTALL_RPATH "${PROJECT_BINARY_DIR}/dfi" "${PROJECT_BINARY_DIR}/utils") - add_executable(test_dfi - private/test/dyn_type_tests.cpp - private/test/dyn_function_tests.cpp - private/test/dyn_closure_tests.cpp - private/test/dyn_interface_tests.cpp - private/test/dyn_message_tests.cpp - private/test/json_serializer_tests.cpp - private/test/json_rpc_tests.cpp - private/test/run_tests.cpp + test/dyn_type_tests.cpp + test/dyn_function_tests.cpp + test/dyn_closure_tests.cpp + test/dyn_interface_tests.cpp + test/dyn_message_tests.cpp + test/json_serializer_tests.cpp + test/json_rpc_tests.cpp + test/run_tests.cpp ) - target_link_libraries(test_dfi celix_dfi ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY}) + target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY}) + target_include_directories(test_dfi PRIVATE ${FFI_INCLUDE_DIRS}) - file(COPY ${CMAKE_CURRENT_LIST_DIR}/private/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - file(COPY ${CMAKE_CURRENT_LIST_DIR}/private/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_test(NAME run_test_dfi COMMAND test_dfi) SETUP_TARGET_FOR_COVERAGE(test_dfi_cov test_dfi ${CMAKE_BINARY_DIR}/coverage/test_dfi/test_dfi)
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/include/dfi_log_util.h ---------------------------------------------------------------------- diff --git a/dfi/include/dfi_log_util.h b/dfi/include/dfi_log_util.h new file mode 100644 index 0000000..2bcd8fa --- /dev/null +++ b/dfi/include/dfi_log_util.h @@ -0,0 +1,63 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 _DFI_LOG_UTIL_H_ +#define _DFI_LOG_UTIL_H_ + +typedef void (*logf_ft)(void *handle, int level, const char *file, int line, const char *format, ...); + +#define DFI_SETUP_LOG_HEADER(cmp) \ + void cmp ## _logSetup(logf_ft logf, void *handle, int currentLogLevel); + +#define DFI_SETUP_LOG(cmp) \ + static logf_ft g_logf = NULL; \ + static void *g_logHandle = NULL; \ + static int g_currentLogLevel = 1; \ + \ + void cmp ## _logSetup(logf_ft logf, void *handle, int currentLogLevel) { \ + g_currentLogLevel = currentLogLevel; \ + g_logHandle = handle; \ + g_logf = logf; \ + } + +#define LOG_LVL_ERROR 1 +#define LOG_LVL_WARNING 2 +#define LOG_LVL_INFO 3 +#define LOG_LVL_DEBUG 4 + +#define LOG_ERROR(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel >= LOG_LVL_ERROR) { \ + g_logf(g_logHandle, LOG_LVL_ERROR, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#define LOG_WARNING(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel >= LOG_LVL_WARNING) { \ + g_logf(g_logHandle, LOG_LVL_WARNING, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#define LOG_INFO(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel >= LOG_LVL_INFO) { \ + g_logf(g_logHandle, LOG_LVL_INFO, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#define LOG_DEBUG(msg, ...) \ + if (g_logf != NULL && g_currentLogLevel >= LOG_LVL_DEBUG) { \ + g_logf(g_logHandle, LOG_LVL_DEBUG, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \ + } + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/include/dyn_common.h ---------------------------------------------------------------------- diff --git a/dfi/include/dyn_common.h b/dfi/include/dyn_common.h new file mode 100644 index 0000000..6ec236f --- /dev/null +++ b/dfi/include/dyn_common.h @@ -0,0 +1,47 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 _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/a1c30887/dfi/include/dyn_function.h ---------------------------------------------------------------------- diff --git a/dfi/include/dyn_function.h b/dfi/include/dyn_function.h new file mode 100644 index 0000000..7f5cd57 --- /dev/null +++ b/dfi/include/dyn_function.h @@ -0,0 +1,60 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 __DYN_FUNCTION_H_ +#define __DYN_FUNCTION_H_ + +#include "dyn_type.h" +#include "dfi_log_util.h" + +/** + * Uses the following schema + * (Name)([Type]*)Type + * + * Dyn fynction argument meta (am) as meta info, with the following possible values + * am=handle #void pointer for the handle + * am=pre #output pointer with memory preallocated + * am=out #output pointer + */ + +typedef struct _dyn_function_type dyn_function_type; + +DFI_SETUP_LOG_HEADER(dynFunction); + +enum dyn_function_argument_meta { + DYN_FUNCTION_ARGUMENT_META__STD = 0, + DYN_FUNCTION_ARGUMENT_META__HANDLE = 1, + DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT = 2, + DYN_FUNCTION_ARGUMENT_META__OUTPUT = 3 +}; + +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); + +int dynFunction_nrOfArguments(dyn_function_type *dynFunc); +dyn_type *dynFunction_argumentTypeForIndex(dyn_function_type *dynFunc, int argumentNr); +enum dyn_function_argument_meta dynFunction_argumentMetaForIndex(dyn_function_type *dynFunc, int argumentNr); +dyn_type * dynFunction_returnType(dyn_function_type *dynFunction); + +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/a1c30887/dfi/include/dyn_interface.h ---------------------------------------------------------------------- diff --git a/dfi/include/dyn_interface.h b/dfi/include/dyn_interface.h new file mode 100644 index 0000000..54bf41c --- /dev/null +++ b/dfi/include/dyn_interface.h @@ -0,0 +1,66 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 __DYN_INTERFACE_H_ +#define __DYN_INTERFACE_H_ + +#include "dyn_common.h" +#include "dyn_type.h" +#include "dyn_function.h" +#include "dfi_log_util.h" + +#include "version.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] + * + */ +typedef struct _dyn_interface_type dyn_interface_type; + +TAILQ_HEAD(methods_head, method_entry); +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, version_pt* version); +int dynInterface_getVersionString(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); +int dynInterface_methods(dyn_interface_type *intf, struct methods_head **list); +int dynInterface_nrOfMethods(dyn_interface_type *intf); + + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/include/dyn_message.h ---------------------------------------------------------------------- diff --git a/dfi/include/dyn_message.h b/dfi/include/dyn_message.h new file mode 100644 index 0000000..d1c8dd7 --- /dev/null +++ b/dfi/include/dyn_message.h @@ -0,0 +1,56 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 __DYN_MESSAGE_H_ +#define __DYN_MESSAGE_H_ + +#include "dyn_common.h" +#include "dyn_type.h" +#include "dfi_log_util.h" + +#include "version.h" + +DFI_SETUP_LOG_HEADER(dynMessage); + +/* Description string + * + * Descriptor (message) = HeaderSection AnnotationSection TypesSection MessageSection + * + * HeaderSection= + * ':header\n' [NameValue]* + * ':annotations\n' [NameValue]* + * ':types\n' [TypeIdValue]* + * ':message\n' [MessageIdValue] + * + */ +typedef struct _dyn_message_type dyn_message_type; + + +int dynMessage_parse(FILE *descriptor, dyn_message_type **out); +void dynMessage_destroy(dyn_message_type *msg); + +int dynMessage_getName(dyn_message_type *msg, char **name); +int dynMessage_getVersion(dyn_message_type *msg, version_pt* version); +int dynMessage_getVersionString(dyn_message_type *msg, char **version); +int dynMessage_getHeaderEntry(dyn_message_type *msg, const char *name, char **value); +int dynMessage_getAnnotationEntry(dyn_message_type *msg, const char *name, char **value); +int dynMessage_getMessageType(dyn_message_type *msg, dyn_type **type); + + + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/include/dyn_type.h ---------------------------------------------------------------------- diff --git a/dfi/include/dyn_type.h b/dfi/include/dyn_type.h new file mode 100644 index 0000000..554966a --- /dev/null +++ b/dfi/include/dyn_type.h @@ -0,0 +1,155 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 _DYN_TYPE_H_ +#define _DYN_TYPE_H_ + +#include <stdio.h> +#include <sys/queue.h> +#include <stdbool.h> + +#include <stdint.h> + +#include "dfi_log_util.h" + +#if defined(BSD) || defined(__APPLE__) || defined(__ANDROID__) +#include "memstream/open_memstream.h" +#include "memstream/fmemopen.h" +#endif + +/* Description string + * + * Type = [TypeDef]* (MetaInfo)* (SimpleType | ComplexType | SequenceType | TypedPointer | PointerReference ) [TypeDef]* + * Name = alpha[(alpha|numeric)*] + * SPACE = ' ' + * + * SimplesTypes (based on java bytecode method signatures) + * //Java based: + * B char + * C (not supported) + * D double + * F float + * I 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) + * + * MetaInfo 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; + +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); +const char * dynType_getMetaInfo(dyn_type *type, const char *name); + +//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/a1c30887/dfi/include/json_rpc.h ---------------------------------------------------------------------- diff --git a/dfi/include/json_rpc.h b/dfi/include/json_rpc.h new file mode 100644 index 0000000..1cc1464 --- /dev/null +++ b/dfi/include/json_rpc.h @@ -0,0 +1,37 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 __JSON_RPC_H_ +#define __JSON_RPC_H_ + +#include <jansson.h> +#include "dfi_log_util.h" +#include "dyn_type.h" +#include "dyn_function.h" +#include "dyn_interface.h" + +//logging +DFI_SETUP_LOG_HEADER(jsonRpc); + +int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, char **out); + + +int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void *args[], char **out); +int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]); + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/include/json_serializer.h ---------------------------------------------------------------------- diff --git a/dfi/include/json_serializer.h b/dfi/include/json_serializer.h new file mode 100644 index 0000000..2f91f2b --- /dev/null +++ b/dfi/include/json_serializer.h @@ -0,0 +1,37 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 __JSON_SERIALIZER_H_ +#define __JSON_SERIALIZER_H_ + +#include <jansson.h> +#include "dfi_log_util.h" +#include "dyn_type.h" +#include "dyn_function.h" +#include "dyn_interface.h" + +//logging +DFI_SETUP_LOG_HEADER(jsonSerializer); + +int jsonSerializer_deserialize(dyn_type *type, const char *input, void **result); +int jsonSerializer_deserializeJson(dyn_type *type, json_t *input, void **result); + +int jsonSerializer_serialize(dyn_type *type, const void* input, char **output); +int jsonSerializer_serializeJson(dyn_type *type, const void* input, json_t **out); + +#endif http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/private/src/dyn_common.c ---------------------------------------------------------------------- diff --git a/dfi/private/src/dyn_common.c b/dfi/private/src/dyn_common.c deleted file mode 100644 index ea8f425..0000000 --- a/dfi/private/src/dyn_common.c +++ /dev/null @@ -1,151 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you 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. - */ -#include "dyn_common.h" - -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <stdbool.h> - -#if defined(BSD) || defined(__APPLE__) || defined(ANDROID) -#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; - char *name = NULL; - char *value = NULL; - - status = dynCommon_parseName(stream, &name); - if (status == OK) { - status = dynCommon_eatChar(stream, '='); - } - if (status == OK) { - const char *valueAcceptedChars = ".<>{}[]?;:~!@#$%^&*()_+-=,./\\'\""; - - 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, c, 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 *entry = TAILQ_FIRST(head); - while (entry != NULL) { - struct namval_entry *tmp = entry; - - if (entry->name != NULL) { - free(entry->name); - } - if (entry->value != NULL) { - free(entry->value); - } - entry = TAILQ_NEXT(entry, entries); - free(tmp); - } -} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/private/src/dyn_function.c ---------------------------------------------------------------------- diff --git a/dfi/private/src/dyn_function.c b/dfi/private/src/dyn_function.c deleted file mode 100644 index 615ad16..0000000 --- a/dfi/private/src/dyn_function.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you 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. - */ -#include "dyn_function.h" - -#include <strings.h> -#include <stdlib.h> -#include <ffi.h> - -#include "dyn_common.h" - -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; - enum dyn_function_argument_meta argumentMeta; - 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; - -DFI_SETUP_LOG(dynFunction) - -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); - -extern ffi_type * dynType_ffiType(dyn_type *type); - -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 == OK) { - dyn_function_argument_type *arg = NULL; - TAILQ_FOREACH(arg, &dynFunc->arguments, entries) { - const char *meta = dynType_getMetaInfo(arg->type, "am"); - if (meta == NULL) { - arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD; - } else if (strcmp(meta, "handle") == 0) { - arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__HANDLE; - } else if (strcmp(meta, "pre") == 0) { - arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT; - } else if (strcmp(meta, "out") == 0) { - arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__OUTPUT; - } else { - LOG_WARNING("unknown argument meta '%s' encountered", meta); - arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD; - } - } - } - - if (status == OK) { - *out = dynFunc; - } else { - if (dynFunc != NULL) { - dynFunction_destroy(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; - char argName[32]; - while (nextChar != ')' && status == 0) { - ungetc(nextChar, descriptor); - type = NULL; - - dyn_function_argument_type *arg = NULL; - - status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &type); - if (status == OK) { - arg = calloc(1, sizeof(*arg)); - if (arg != NULL) { - arg->index = index; - arg->type = type; - snprintf(argName, 32, "arg%04i", index); - arg->name = strdup(argName); - - index += 1; - } else { - LOG_ERROR("Error allocating memory"); - status = MEM_ERROR; - } - } - - if (status == OK) { - TAILQ_INSERT_TAIL(&dynFunc->arguments, arg, entries); - } - - nextChar = fgetc(descriptor); - } - - if (status == 0) { - status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &dynFunc->funcReturn); - } - - return status; -} - -enum dyn_function_argument_meta dynFunction_argumentMetaForIndex(dyn_function_type *dynFunc, int argumentNr) { - enum dyn_function_argument_meta result = 0; - dyn_function_argument_type *arg = NULL; - int index = 0; - TAILQ_FOREACH(arg, &dynFunc->arguments, entries) { - if (index == argumentNr) { - result = arg->argumentMeta; - break; - } - index += 1; - } - return result; -} - - -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) { - 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->userData = userData; - 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; -} - -int dynFunction_nrOfArguments(dyn_function_type *dynFunc) { - int count = 0; - dyn_function_argument_type *entry = NULL; - TAILQ_FOREACH(entry, &dynFunc->arguments, entries) { - count += 1; - } - return count; -} - -dyn_type *dynFunction_argumentTypeForIndex(dyn_function_type *dynFunc, int argumentNr) { - dyn_type *result = NULL; - int index = 0; - dyn_function_argument_type *entry = NULL; - TAILQ_FOREACH(entry, &dynFunc->arguments, entries) { - if (index == argumentNr) { - result = entry->type; - break; - } - index +=1; - } - return result; -} - -dyn_type * dynFunction_returnType(dyn_function_type *dynFunction) { - return dynFunction->funcReturn; -} - http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/private/src/dyn_interface.c ---------------------------------------------------------------------- diff --git a/dfi/private/src/dyn_interface.c b/dfi/private/src/dyn_interface.c deleted file mode 100644 index 63aafac..0000000 --- a/dfi/private/src/dyn_interface.c +++ /dev/null @@ -1,444 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you 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. - */ -#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); - -struct _dyn_interface_type { - struct namvals_head header; - struct namvals_head annotations; - struct types_head types; - struct methods_head methods; - version_pt version; -}; - -static const int OK = 0; -static 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 = (char)fgetc(descriptor); - while (peek == ':') { - ungetc(peek, descriptor); - status = dynInterface_parseSection(intf, descriptor); - if (status == OK) { - peek = (char)fgetc(descriptor); - } else { - break; - } - } - - if (status == OK) { - status = dynCommon_eatChar(descriptor, EOF); - } - - if (status == OK) { - status = dynInterface_checkInterface(intf); - } - - if(status==OK){ /* We are sure that version field is present in the header */ - char* version=NULL; - dynInterface_getVersionString(intf,&version); - if(version!=NULL){ - status = (version_createVersionFromString(version,&(intf->version)) == CELIX_SUCCESS)?OK:ERROR; - } - if(status==ERROR){ - LOG_ERROR("Invalid version (%s) in parsed descriptor\n",version); - } - } - } 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"); - } - - struct method_entry *mEntry = NULL; - TAILQ_FOREACH(mEntry, &intf->methods, entries) { - dyn_type *type = dynFunction_returnType(mEntry->dynFunc); - int descriptor = dynType_descriptorType(type); - if (descriptor != 'N') { - status = ERROR; - LOG_ERROR("Parse Error. Only method with a return type 'N' (native int) are supported. Got return type '%c'\n", descriptor); - break; - } - } - } - - 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, §ionName); - } - - 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); - } - 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); - } - 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; - entry->name = strndup(id, 1024); - if (entry->name != NULL) { - int i; - for (i = 0; i < 1024; i += 1) { - if (entry->name[i] == '\0') { - break; - } else if (entry->name[i] == '(') { - entry->name[i] = '\0'; - break; - } - } - } - 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 - } - 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 method_entry *mInfo = TAILQ_FIRST(&intf->methods); - while (mInfo != NULL) { - struct method_entry *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); - } - - struct type_entry *tInfo = TAILQ_FIRST(&intf->types); - while (tInfo != NULL) { - struct type_entry *tmp = tInfo; - tInfo = TAILQ_NEXT(tInfo, entries); - dynType_destroy(tmp->type); - free(tmp); - } - - if(intf->version!=NULL){ - version_destroy(intf->version); - } - - 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 , version_pt* version){ - *version = intf->version; - if(*version==NULL){ - return ERROR; - } - return OK; -} - -int dynInterface_getVersionString(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; -} - -int dynInterface_methods(dyn_interface_type *intf, struct methods_head **list) { - int status = OK; - *list = &intf->methods; - return status; -} - -int dynInterface_nrOfMethods(dyn_interface_type *intf) { - int count = 0; - struct method_entry *entry = NULL; - TAILQ_FOREACH(entry, &intf->methods, entries) { - count +=1; - } - return count; -} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/private/src/dyn_message.c ---------------------------------------------------------------------- diff --git a/dfi/private/src/dyn_message.c b/dfi/private/src/dyn_message.c deleted file mode 100644 index 652be83..0000000 --- a/dfi/private/src/dyn_message.c +++ /dev/null @@ -1,358 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you 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. - */ -#include "dyn_message.h" - -#include <stdlib.h> -#include <string.h> - -#include "dyn_common.h" -#include "dyn_type.h" - -DFI_SETUP_LOG(dynMessage); - -struct _dyn_message_type { - struct namvals_head header; - struct namvals_head annotations; - struct types_head types; - dyn_type *msgType; - version_pt msgVersion; -}; - -static const int OK = 0; -static const int ERROR = 1; - -static int dynMessage_parseSection(dyn_message_type *msg, FILE *stream); -static int dynMessage_parseAnnotations(dyn_message_type *msg, FILE *stream); -static int dynMessage_parseTypes(dyn_message_type *msg, FILE *stream); -static int dynMessage_parseMessage(dyn_message_type *msg, FILE *stream); -static int dynMessage_parseHeader(dyn_message_type *msg, FILE *stream); -static int dynMessage_parseNameValueSection(dyn_message_type *msg, FILE *stream, struct namvals_head *head); -static int dynMessage_checkMessage(dyn_message_type *msg); -static int dynMessage_getEntryForHead(struct namvals_head *head, const char *name, char **value); - -int dynMessage_parse(FILE *descriptor, dyn_message_type **out) { - int status = OK; - - dyn_message_type *msg = calloc(1, sizeof(*msg)); - if (msg != NULL) { - TAILQ_INIT(&msg->header); - TAILQ_INIT(&msg->annotations); - TAILQ_INIT(&msg->types); - - char peek = (char)fgetc(descriptor); - while (peek == ':') { - ungetc(peek, descriptor); - status = dynMessage_parseSection(msg, descriptor); - if (status == OK) { - peek = (char)fgetc(descriptor); - } else { - break; - } - } - - if (status == OK) { - status = dynCommon_eatChar(descriptor, EOF); - } - - if (status == OK) { - status = dynMessage_checkMessage(msg); - } - - if(status==OK){ /* We are sure that version field is present in the header */ - char* version=NULL; - dynMessage_getVersionString(msg,&version); - if(version!=NULL){ - status = (version_createVersionFromString(version,&(msg->msgVersion)) == CELIX_SUCCESS)?OK:ERROR; - } - if(status==ERROR){ - LOG_ERROR("Invalid version (%s) in parsed descriptor\n",version); - } - } - - } else { - status = ERROR; - LOG_ERROR("Error allocating memory for dynamic message\n"); - } - - if (status == OK) { - *out = msg; - } else if (msg != NULL) { - LOG_ERROR("Error parsing msg\n"); - dynMessage_destroy(msg); - } - return status; -} - -static int dynMessage_checkMessage(dyn_message_type *msg) { - 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, &msg->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 dynMessage_parseSection(dyn_message_type *msg, FILE *stream) { - int status; - 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("header", sectionName) == 0) { - status = dynMessage_parseHeader(msg, stream); - } else if (strcmp("annotations", sectionName) == 0) { - status = dynMessage_parseAnnotations(msg, stream); - } else if (strcmp("types", sectionName) == 0) { - status = dynMessage_parseTypes(msg, stream); - } else if (strcmp("message", sectionName) == 0) { - status = dynMessage_parseMessage(msg, stream); - } else { - status = ERROR; - LOG_ERROR("unsupported section '%s'", sectionName); - } - } - - if (sectionName != NULL) { - free(sectionName); - } - - return status; -} - -static int dynMessage_parseHeader(dyn_message_type *msg, FILE *stream) { - return dynMessage_parseNameValueSection(msg, stream, &msg->header); -} - -static int dynMessage_parseAnnotations(dyn_message_type *msg, FILE *stream) { - return dynMessage_parseNameValueSection(msg, stream, &msg->annotations); -} - -static int dynMessage_parseNameValueSection(dyn_message_type *msg, 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); - } - break; - } - peek = fgetc(stream); - } - ungetc(peek, stream); - - return status; -} - -static int dynMessage_parseTypes(dyn_message_type *msg, FILE *stream) { - int status = OK; - - //expected input (Name)=<Type>\n - int peek = fgetc(stream); - while (peek != ':' && peek != EOF) { - ungetc(peek, stream); - - char *name = NULL; - status = dynCommon_parseName(stream, &name); - - if (status == OK) { - status = dynCommon_eatChar(stream, '='); - } - - dyn_type *type = NULL; - if (status == OK) { - status = dynType_parse(stream, name, &msg->types, &type); - } - - if (status == OK) { - status = dynCommon_eatChar(stream, '\n'); - } - - struct type_entry *entry = NULL; - if (status == OK) { - entry = calloc(1, sizeof(*entry)); - if (entry != NULL) { - LOG_DEBUG("Adding type '%s' with pointer %p to types", name, type); - entry->type = type; - TAILQ_INSERT_TAIL(&msg->types, entry, entries); - } else { - status = ERROR; - LOG_ERROR("Error allocating memory for type entry"); - } - } - - if (name != NULL) { - free(name); - } - - if (status != OK) { - if (type != NULL) { - dynType_destroy(type); - } - break; - } - peek = fgetc(stream); - } - ungetc(peek, stream); - - return status; -} - -static int dynMessage_parseMessage(dyn_message_type *msg, FILE *stream) { - int status; - - //expected input <dynType>\n - char *name = NULL; - status = dynMessage_getName(msg, &name); - - if (status == OK) { - status = dynType_parse(stream, name, &(msg->types), &(msg->msgType)); - } - - return status; -} - -void dynMessage_destroy(dyn_message_type *msg) { - if (msg != NULL) { - dynCommon_clearNamValHead(&msg->header); - dynCommon_clearNamValHead(&msg->annotations); - - struct type_entry *tInfo = TAILQ_FIRST(&msg->types); - while (tInfo != NULL) { - struct type_entry *tmp = tInfo; - tInfo = TAILQ_NEXT(tInfo, entries); - dynType_destroy(tmp->type); - free(tmp); - } - - if (msg->msgType != NULL) { - dynType_destroy(msg->msgType); - } - - if(msg->msgVersion != NULL){ - version_destroy(msg->msgVersion); - } - - free(msg); - } -} - -int dynMessage_getName(dyn_message_type *msg, char **out) { - return dynMessage_getEntryForHead(&msg->header, "name", out); -} - -int dynMessage_getVersion(dyn_message_type *msg, version_pt* version){ - *version = msg->msgVersion; - if(*version==NULL){ - return ERROR; - } - return OK; -} - -int dynMessage_getVersionString(dyn_message_type *msg, char **version) { - return dynMessage_getEntryForHead(&msg->header, "version", version); -} - -int dynMessage_getHeaderEntry(dyn_message_type *msg, const char *name, char **value) { - return dynMessage_getEntryForHead(&msg->header, name, value); -} - -int dynMessage_getAnnotationEntry(dyn_message_type *msg, const char *name, char **value) { - return dynMessage_getEntryForHead(&msg->annotations, name, value); -} - -static int dynMessage_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; -} - -int dynMessage_getMessageType(dyn_message_type *msg, dyn_type **type) { - int status = OK; - *type = msg->msgType; - return status; -}
