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 2020/02/02 22:58:43 UTC
[celix] branch feature/query_command updated: gh-144: Adds missing
files.
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/query_command
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/query_command by this push:
new 436c737 gh-144: Adds missing files.
436c737 is described below
commit 436c737a40ee8499fad2d8e3c061b5e1b4a78a3a
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Feb 2 23:58:28 2020 +0100
gh-144: Adds missing files.
Also add celix_utils_strdup function, which does a limited length strdup.
---
bundles/shell/shell/src/activator.c | 7 +-
bundles/shell/shell/src/q_command.c | 27 +++
bundles/shell/shell/src/query_command.c | 230 +++++++++++++++++++++
bundles/shell/shell_tui/private/src/activator.c | 40 ++--
libs/framework/include/celix_bundle.h | 3 +-
libs/framework/src/bundle.c | 23 ++-
libs/framework/src/service_registration.c | 2 +-
libs/framework/src/service_registry.c | 3 +-
.../include/{celix_utils_api.h => celix_utils.h} | 34 +--
libs/utils/include/celix_utils_api.h | 1 +
libs/utils/src/filter.c | 28 +--
libs/utils/src/utils.c | 13 +-
12 files changed, 337 insertions(+), 74 deletions(-)
diff --git a/bundles/shell/shell/src/activator.c b/bundles/shell/shell/src/activator.c
index 291e802..486cccd 100644
--- a/bundles/shell/shell/src/activator.c
+++ b/bundles/shell/shell/src/activator.c
@@ -154,12 +154,13 @@ celix_status_t bundleActivator_create(celix_bundle_context_t* ctx, void **_pptr)
.exec = queryCommand_execute,
.name = "query",
.description = "Query services. Query for registered and requested services" \
- "\nIf a query is provided, only service with a service name containing the query will be displayed." \
- "\nOr if the query is a filter. the filter will be used. If a filter is used, the optional bundle id will be ignored."
+ "\nIf a query is provided (or multiple), only service with a service name matching the query will be displayed." \
+ "\nIf a query is a (LDAP) filter, filter matching will be used."
+ "\nIf no query is provided all provided and requested services will be listed."
"\n\tIf the -v option is provided, also list the service properties." \
"\n\tIf the -r option is provided, only query for requested services." \
"\n\tIf the -p option is provided, only query for provided services.",
- .usage = "ls [bundleId] [-v] [-p] [-r] [query_name ...]"
+ .usage = "query [bundleId ...] [-v] [-p] [-r] [query ...]"
};
activator->std_commands[11] =
(struct command) {
diff --git a/bundles/shell/shell/src/q_command.c b/bundles/shell/shell/src/q_command.c
new file mode 100644
index 0000000..db60e61
--- /dev/null
+++ b/bundles/shell/shell/src/q_command.c
@@ -0,0 +1,27 @@
+/**
+ *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 "celix_bundle_context.h"
+
+celix_status_t qCommand_execute(void *_ptr, char *command_line_str __attribute__((unused)), FILE *sout, FILE *serr __attribute__((unused))) {
+ bundle_context_t* ctx = _ptr;
+ fprintf(sout, "Quitting framework\n");
+ celix_bundleContext_stopBundle(ctx, 0L);
+ return CELIX_SUCCESS;
+}
diff --git a/bundles/shell/shell/src/query_command.c b/bundles/shell/shell/src/query_command.c
new file mode 100644
index 0000000..9d06049
--- /dev/null
+++ b/bundles/shell/shell/src/query_command.c
@@ -0,0 +1,230 @@
+/**
+ *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 <string.h>
+#include <stdlib.h>
+#include <celix_api.h>
+
+#include "shell_constants.h"
+#include "celix_bundle_context.h"
+#include "std_commands.h"
+#include "celix_bundle.h"
+
+
+
+struct query_options {
+ bool useColors;
+ bool verbose;
+ bool queryProvided;
+ bool queryRequested;
+ long bndId; // -1L if no bundle is selected
+ celix_array_list_t *nameQueries; //entry is char*
+ celix_array_list_t *filterQueries; //enry if celix_filter_t
+};
+
+struct bundle_callback_data {
+ const struct query_options *opts;
+ FILE *sout;
+};
+
+static bool queryCommand_printProvidedService(const struct query_options *opts, celix_bundle_service_list_entry_t *entry) {
+ bool print = celix_arrayList_size(opts->nameQueries) == 0 && celix_arrayList_size(opts->filterQueries) == 0; //no queries, always print
+ for (int i = 0; i < celix_arrayList_size(opts->nameQueries) && !print; ++i) {
+ const char *qry = celix_arrayList_get(opts->nameQueries, i);
+ print = strcasestr(entry->serviceName, qry) != NULL;
+ }
+ for (int i = 0; i < celix_arrayList_size(opts->filterQueries) && !print; ++i) {
+ celix_filter_t *filter = celix_arrayList_get(opts->filterQueries, i);
+ print = celix_filter_match(filter, entry->serviceProperties);
+ }
+ return print;
+}
+
+static bool queryCommand_printRequestedService(const struct query_options *opts, celix_bundle_service_tracker_list_entry_t *entry) {
+ bool print = celix_arrayList_size(opts->nameQueries) == 0 && celix_arrayList_size(opts->filterQueries) == 0; //no queries, always print
+ for (int i = 0; i < celix_arrayList_size(opts->nameQueries) && !print; ++i) {
+ const char *qry = celix_arrayList_get(opts->nameQueries, i);
+ print = strcasestr(entry->serviceName, qry) != NULL;
+ }
+ for (int i = 0; i < celix_arrayList_size(opts->filterQueries) && !print; ++i) {
+ //in case of filter try to match with literal filter string
+ celix_filter_t *filter = celix_arrayList_get(opts->filterQueries, i);
+ const char *f = celix_filter_getFilterString(filter);
+ print = strstr(entry->filter, f) != NULL;
+ }
+ return print;
+}
+
+/**
+ * print bundle header (only for first time)
+ */
+static void queryCommand_printBundleHeader(FILE *sout, const celix_bundle_t *bnd, bool *called) {
+ if (called != NULL && !(*called)) {
+ fprintf(sout, "Bundle %li [%s]:\n", celix_bundle_getId(bnd), celix_bundle_getSymbolicName(bnd));
+ *called = true;
+ }
+}
+
+static void queryCommand_callback(void *handle, const celix_bundle_t *bnd) {
+ struct bundle_callback_data *data = handle;
+ bool printBundleCalled = false;
+ if (data->opts->queryProvided) {
+ celix_array_list_t *services = celix_bundle_listRegisteredServices(bnd);
+ for (int i = 0; i < celix_arrayList_size(services); ++i) {
+ celix_bundle_service_list_entry_t *entry = celix_arrayList_get(services, i);
+ if (queryCommand_printProvidedService(data->opts, entry)) {
+ queryCommand_printBundleHeader(data->sout, bnd, &printBundleCalled);
+ fprintf(data->sout, "|- Provided service '%s' [id = %li]\n", entry->serviceName, entry->serviceId); //TODO underline if color enabled
+ if (data->opts->verbose) {
+ fprintf(data->sout, " |- Is factory: %s\n", entry->factory ? "true" : "false");
+ fprintf(data->sout, " |- Properties:\n");
+ const char *key;
+ CELIX_PROPERTIES_FOR_EACH(entry->serviceProperties, key) {
+ const char *val = celix_properties_get(entry->serviceProperties, key, "!ERROR!");
+ fprintf(data->sout, " |- %20s = %s\n", key, val);
+ }
+ }
+ }
+ }
+ celix_bundle_destroyRegisteredServicesList(services);
+ }
+ if (data->opts->queryRequested) {
+ celix_array_list_t *trackers = celix_bundle_listServiceTrackers(bnd);
+ for (int i = 0; i < celix_arrayList_size(trackers); ++i) {
+ celix_bundle_service_tracker_list_entry_t *entry = celix_arrayList_get(trackers, i);
+ if (queryCommand_printRequestedService(data->opts, entry)) {
+ queryCommand_printBundleHeader(data->sout, bnd, &printBundleCalled);
+ fprintf(data->sout, "|- Service tracker '%s'\n", entry->filter);
+ }
+ }
+ celix_bundle_destroyServiceTrackerList(trackers);
+ }
+
+ if (printBundleCalled) {
+ fprintf(data->sout, "\n");
+ }
+}
+
+
+static void queryCommand_listServicesForBundle(celix_bundle_context_t *ctx, long bndId, const struct query_options *opts, FILE *sout, FILE *serr) {
+ struct bundle_callback_data data;
+ data.opts = opts;
+ data.sout = sout;
+ bool called = celix_bundleContext_useBundle(ctx, bndId, &data, queryCommand_callback);
+ if (!called) {
+ fprintf(serr, "Bundle %li not installed!", bndId);
+ }
+}
+
+static void queryCommand_listServices(celix_bundle_context_t *ctx, const struct query_options *opts, FILE *sout, FILE *serr) {
+ if (opts->bndId >= 0L) {
+ queryCommand_listServicesForBundle(ctx, opts->bndId, opts, sout, serr);
+ } else {
+ celix_array_list_t *bundleIds = celix_bundleContext_listBundles(ctx);
+ for (int i = 0; i < celix_arrayList_size(bundleIds); ++i) {
+ long bndId = celix_arrayList_getLong(bundleIds, i);
+ queryCommand_listServicesForBundle(ctx, bndId, opts, sout, serr);
+ }
+ celix_arrayList_destroy(bundleIds);
+ }
+}
+
+
+celix_status_t queryCommand_execute(void *_ptr, char *command_line_str, FILE *sout, FILE *serr __attribute__((unused))) {
+ celix_status_t status = CELIX_SUCCESS;
+ bundle_context_t* ctx = _ptr;
+
+ struct query_options opts;
+ memset(&opts, 0, sizeof(opts));
+ opts.bndId = -1L;
+ opts.queryProvided = true;
+ opts.queryRequested = true;
+
+ opts.nameQueries = celix_arrayList_create();
+ opts.filterQueries = celix_arrayList_create();
+
+ const char* config = celix_bundleContext_getProperty(ctx, SHELL_USE_ANSI_COLORS, SHELL_USE_ANSI_COLORS_DEFAULT_VALUE);
+ opts.useColors = config != NULL && strncmp("true", config, 5) == 0;
+
+ if (!ctx || !command_line_str || !sout || !serr) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ bool validCommand = true;
+ if (status == CELIX_SUCCESS) {
+ char *sub_str = NULL;
+ char *save_ptr = NULL;
+
+ strtok_r(command_line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+ sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+ while (sub_str != NULL) {
+ if (strcmp(sub_str, "-v") == 0) {
+ opts.verbose = true;
+ } else if (strcmp(sub_str, "-p") == 0) {
+ opts.queryProvided = true;
+ opts.queryRequested = false;
+ } else if (strcmp(sub_str, "-r") == 0) {
+ opts.queryProvided = false;
+ opts.queryRequested = true;
+ } else {
+ //check if its a number (bundle id)
+ errno = 0;
+ long bndId = strtol(sub_str, NULL, 10);
+ if (bndId > 0 && errno == 0 /*not EINVAL*/) {
+ opts.bndId = bndId;
+ } else {
+ //not option and not a bundle id -> query
+ if (strnlen(sub_str, 16) > 1 && sub_str[0] == '(') {
+ //assume this is a filter.
+ celix_filter_t *filter = celix_filter_create(sub_str);
+ if (filter != NULL) {
+ celix_arrayList_add(opts.filterQueries, filter);
+ } else {
+ validCommand = false;
+ fprintf(serr, "Cannot parse provided filter '%s'!\n", sub_str);
+ break;
+ }
+ } else {
+ celix_arrayList_add(opts.nameQueries, celix_utils_strdup(sub_str));
+ }
+
+ }
+ }
+ sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+ }
+ }
+
+ if (validCommand) {
+ queryCommand_listServices(ctx, &opts, sout, serr);
+ }
+
+ for (int i = 0; i < arrayList_size(opts.nameQueries); ++i) {
+ char *name = celix_arrayList_get(opts.nameQueries, i);
+ free(name);
+ }
+ celix_arrayList_destroy(opts.nameQueries);
+
+ for (int i = 0; i < arrayList_size(opts.filterQueries); ++i) {
+ celix_filter_t *filter = celix_arrayList_get(opts.filterQueries, i);
+ celix_filter_destroy(filter);
+ }
+ celix_arrayList_destroy(opts.filterQueries);
+
+ return status;
+}
diff --git a/bundles/shell/shell_tui/private/src/activator.c b/bundles/shell/shell_tui/private/src/activator.c
index e2abd28..fb422a2 100644
--- a/bundles/shell/shell_tui/private/src/activator.c
+++ b/bundles/shell/shell_tui/private/src/activator.c
@@ -34,28 +34,12 @@
typedef struct shell_tui_activator {
shell_tui_t* shellTui;
- service_tracker_pt tracker;
+ long trackerId;
shell_service_t* currentSvc;
bool useAnsiControlSequences;
} shell_tui_activator_t;
-static celix_status_t activator_addShellService(void *handle, service_reference_pt ref, void *svc) {
- shell_tui_activator_t* act = (shell_tui_activator_t*) handle;
- act->currentSvc = svc;
- shellTui_setShell(act->shellTui, svc);
- return CELIX_SUCCESS;
-}
-
-static celix_status_t activator_removeShellService(void *handle, service_reference_pt ref, void *svc) {
- shell_tui_activator_t* act = (shell_tui_activator_t*) handle;
- if (act->currentSvc == svc) {
- act->currentSvc = NULL;
- shellTui_setShell(act->shellTui, NULL);
- }
- return CELIX_SUCCESS;
-}
-
celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
celix_status_t status = CELIX_SUCCESS;
@@ -68,6 +52,7 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData
shell_tui_activator_t* activator = calloc(1, sizeof(*activator));
if (activator != NULL) {
+ activator->trackerId = -1L;
bool useCommands;
const char* config = NULL;
bundleContext_getProperty(context, SHELL_USE_ANSI_CONTROL_SEQUENCES, &config);
@@ -80,9 +65,14 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData
activator->shellTui = shellTui_create(useCommands);
- service_tracker_customizer_t* cust = NULL;
- serviceTrackerCustomizer_create(activator, NULL, activator_addShellService, NULL, activator_removeShellService, &cust);
- serviceTracker_create(context, OSGI_SHELL_SERVICE_NAME, cust, &activator->tracker);
+ {
+ celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+ opts.filter.serviceName = OSGI_SHELL_SERVICE_NAME;
+ opts.callbackHandle = activator->shellTui;
+ opts.set = (void*)shellTui_setShell;
+
+ activator->trackerId = celix_bundleContext_trackServicesWithOptions(context, &opts);
+ }
}
if (activator != NULL && activator->shellTui != NULL) {
@@ -90,9 +80,8 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData
} else {
if (activator != NULL) {
shellTui_destroy(activator->shellTui);
- if (activator->tracker != NULL) {
- serviceTracker_destroy(activator->tracker);
- }
+ celix_bundleContext_stopTracker(context, activator->trackerId);
+ activator->trackerId = -1L;
}
free(activator);
status = CELIX_ENOMEM;
@@ -106,8 +95,6 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context)
shell_tui_activator_t* act = (shell_tui_activator_t*) userData;
if (act != NULL) {
- act->currentSvc = NULL;
- serviceTracker_open(act->tracker);
shellTui_start(act->shellTui);
}
@@ -119,7 +106,7 @@ celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context)
shell_tui_activator_t* act = (shell_tui_activator_t*) userData;
if (act != NULL) {
- serviceTracker_close(act->tracker);
+ celix_bundleContext_stopTracker(context, act->trackerId);
shellTui_stop(act->shellTui);
}
@@ -131,7 +118,6 @@ celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt contex
if (act != NULL) {
shellTui_destroy(act->shellTui);
- serviceTracker_destroy(act->tracker);
free(act);
}
diff --git a/libs/framework/include/celix_bundle.h b/libs/framework/include/celix_bundle.h
index 0b0dac4..c6a2ab0 100644
--- a/libs/framework/include/celix_bundle.h
+++ b/libs/framework/include/celix_bundle.h
@@ -94,7 +94,8 @@ void celix_bundle_destroyRegisteredServicesList(celix_array_list_t* list);
* Service Tracker Info provided to the service tracker tracker callbacks.
*/
typedef struct celix_bundle_service_tracker_list_entry {
- char* filter;;
+ char *filter;
+ char *serviceName;
long bundleOwner;
} celix_bundle_service_tracker_list_entry_t;
diff --git a/libs/framework/src/bundle.c b/libs/framework/src/bundle.c
index 89ac70d..9b1d4bf 100644
--- a/libs/framework/src/bundle.c
+++ b/libs/framework/src/bundle.c
@@ -20,6 +20,8 @@
#include <stdlib.h>
#include <string.h>
#include <service_tracker.h>
+#include <celix_constants.h>
+#include <celix_api.h>
#include "framework_private.h"
#include "bundle_private.h"
@@ -403,7 +405,7 @@ celix_status_t bundle_addModule(bundle_pt bundle, module_pt module) {
const char *sn = NULL;
module_getSymbolicName(module, &sn);
if (sn != NULL) {
- bundle->symbolicName = strndup(sn, 1024 * 1024);
+ bundle->symbolicName = celix_utils_strdup(sn);
}
}
@@ -678,9 +680,23 @@ celix_array_list_t* celix_bundle_listServiceTrackers(const celix_bundle_t *bnd)
while (hashMapIterator_hasNext(&iter)) {
celix_service_tracker_t *tracker = hashMapIterator_nextValue(&iter);
celix_bundle_service_tracker_list_entry_t *entry = calloc(1, sizeof(*entry));
- entry->filter = strndup(tracker->filter, 1024*1024*10);
+ entry->filter = celix_utils_strdup(tracker->filter);
+ celix_filter_t *f = celix_filter_create(entry->filter);
+ if (f != NULL) {
+ const char *sn = celix_filter_findAttribute(f, OSGI_FRAMEWORK_OBJECTCLASS);
+ if (sn != NULL) {
+ entry->serviceName = celix_utils_strdup(sn);
+ }
+ }
entry->bundleOwner = celix_bundle_getId(bnd);
- celix_arrayList_add(result, entry);
+
+ if (entry->serviceName != NULL) {
+ celix_arrayList_add(result, entry);
+ } else {
+ framework_logIfError(logger, CELIX_BUNDLE_EXCEPTION, NULL, "Failed to get service name from tracker. filter is %s", entry->filter);
+ free(entry->filter);
+ free(entry);
+ }
}
celixThreadMutex_unlock(&bnd->context->mutex);
return result;
@@ -692,6 +708,7 @@ void celix_bundle_destroyServiceTrackerList(celix_array_list_t* list) {
for (int i = 0; i < celix_arrayList_size(list); ++i) {
celix_bundle_service_tracker_list_entry_t *entry = celix_arrayList_get(list, i);
free(entry->filter);
+ free(entry->serviceName);
free(entry);
}
}
diff --git a/libs/framework/src/service_registration.c b/libs/framework/src/service_registration.c
index 49f60c8..3400134 100644
--- a/libs/framework/src/service_registration.c
+++ b/libs/framework/src/service_registration.c
@@ -311,7 +311,7 @@ bool serviceRegistration_isFactoryService(service_registration_t *registration)
bool isFactory = false;
if (registration != NULL) {
celixThreadRwlock_readLock(®istration->lock);
- isFactory = registration->svcType = CELIX_FACTORY_SERVICE || registration->svcType == CELIX_DEPRECATED_FACTORY_SERVICE;
+ isFactory = registration->svcType == CELIX_FACTORY_SERVICE || registration->svcType == CELIX_DEPRECATED_FACTORY_SERVICE;
celixThreadRwlock_unlock(®istration->lock);
}
return isFactory;
diff --git a/libs/framework/src/service_registry.c b/libs/framework/src/service_registry.c
index bf2a68b..dc38920 100644
--- a/libs/framework/src/service_registry.c
+++ b/libs/framework/src/service_registry.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <celix_api.h>
#include "service_registry_private.h"
#include "service_registration_private.h"
@@ -954,7 +955,7 @@ bool celix_serviceRegistry_getServiceInfo(
if (outServiceName != NULL) {
const char *s = NULL;
serviceRegistration_getServiceName(reg, &s);
- *outServiceName = strndup(s, 1024 * 1024 * 10);
+ *outServiceName = celix_utils_strdup(s);
}
if (outServiceProperties != NULL) {
celix_properties_t *p = NULL;
diff --git a/libs/utils/include/celix_utils_api.h b/libs/utils/include/celix_utils.h
similarity index 63%
copy from libs/utils/include/celix_utils_api.h
copy to libs/utils/include/celix_utils.h
index 0d9b576..1b96cdf 100644
--- a/libs/utils/include/celix_utils_api.h
+++ b/libs/utils/include/celix_utils.h
@@ -17,23 +17,23 @@
* under the License.
*/
-#ifndef CELIX_CELIX_UTILS_API_H_
-#define CELIX_CELIX_UTILS_API_H_
+#ifndef CELIX_UTILS_H_
+#define CELIX_UTILS_H_
-#include "celix_errno.h"
-#include "celixbool.h"
-#include "celix_threads.h"
-#include "array_list.h"
-#include "hash_map.h"
-#include "properties.h"
-#include "utils.h"
-#include "version.h"
-#include "version_range.h"
-#include "thpool.h"
-
-#if defined(BSD) || defined(__APPLE__) || defined(__ANDROID__)
-#include "memstream/open_memstream.h"
-#include "memstream/fmemopen.h"
+#ifdef __cplusplus
+extern "C" {
#endif
-#endif //CELIX_CELIX_UTILS_API_H_
+#define CELIX_UTILS_MAX_STRLEN 1024*1024*10
+
+/**
+ * Creates a copy of a provided string.
+ * The strdup is limited to the CELIX_UTILS_MAX_STRLEN and uses strndup to achieve this.
+ * @return a copy of the string (including null terminator).
+ */
+char* celix_utils_strdup(const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* CELIX_UTILS_H_ */
diff --git a/libs/utils/include/celix_utils_api.h b/libs/utils/include/celix_utils_api.h
index 0d9b576..23192a2 100644
--- a/libs/utils/include/celix_utils_api.h
+++ b/libs/utils/include/celix_utils_api.h
@@ -27,6 +27,7 @@
#include "hash_map.h"
#include "properties.h"
#include "utils.h"
+#include "celix_utils.h"
#include "version.h"
#include "version_range.h"
#include "thpool.h"
diff --git a/libs/utils/src/filter.c b/libs/utils/src/filter.c
index 45564c6..c07b54e 100644
--- a/libs/utils/src/filter.c
+++ b/libs/utils/src/filter.c
@@ -59,7 +59,7 @@ static celix_filter_t * filter_parseFilter(char * filterString, int * pos) {
celix_filter_t * filter;
filter_skipWhiteSpace(filterString, pos);
if (filterString[*pos] != '(') {
- fprintf(stderr, "Filter Error: Missing '(' in filter string '%s'.", filterString);
+ fprintf(stderr, "Filter Error: Missing '(' in filter string '%s'.\n", filterString);
return NULL;
}
(*pos)++;
@@ -69,7 +69,7 @@ static celix_filter_t * filter_parseFilter(char * filterString, int * pos) {
filter_skipWhiteSpace(filterString, pos);
if (filterString[*pos] != ')') {
- fprintf(stderr, "Filter Error: Missing ')' in filter string '%s'.", filterString);
+ fprintf(stderr, "Filter Error: Missing ')' in filter string '%s'.\n", filterString);
if(filter!=NULL){
filter_destroy(filter);
}
@@ -110,7 +110,7 @@ static celix_filter_t * filter_parseAndOrOr(char * filterString, celix_filter_op
bool failure = false;
if (filterString[*pos] != '(') {
- fprintf(stderr, "Filter Error: Missing '('.");
+ fprintf(stderr, "Filter Error: Missing '('.\n");
return NULL;
}
@@ -146,7 +146,7 @@ static celix_filter_t * filter_parseNot(char * filterString, int * pos) {
filter_skipWhiteSpace(filterString, pos);
if (filterString[*pos] != '(') {
- fprintf(stderr, "Filter Error: Missing '('.");
+ fprintf(stderr, "Filter Error: Missing '('.\n");
return NULL;
}
@@ -259,7 +259,7 @@ static celix_filter_t * filter_parseItem(char * filterString, int * pos) {
return filter;
}
}
- fprintf(stderr, "Filter Error: Invalid operator.");
+ fprintf(stderr, "Filter Error: Invalid operator.\n");
free(attr);
return NULL;
}
@@ -286,7 +286,7 @@ static char * filter_parseAttr(char * filterString, int * pos) {
length = end - begin;
if (length == 0) {
- fprintf(stderr, "Filter Error: Missing attr.");
+ fprintf(stderr, "Filter Error: Missing attr.\n");
return NULL;
} else {
char * attr = (char *) calloc(1, length+1);
@@ -309,12 +309,12 @@ static char * filter_parseValue(char * filterString, int * pos) {
break;
}
case '(': {
- fprintf(stderr, "Filter Error: Invalid value.");
+ fprintf(stderr, "Filter Error: Invalid value.\n");
free(value);
return NULL;
}
case '\0':{
- fprintf(stderr, "Filter Error: Unclosed bracket.");
+ fprintf(stderr, "Filter Error: Unclosed bracket.\n");
free(value);
return NULL;
}
@@ -335,7 +335,7 @@ static char * filter_parseValue(char * filterString, int * pos) {
}
if (strlen(value) == 0) {
- fprintf(stderr, "Filter Error: Missing value.");
+ fprintf(stderr, "Filter Error: Missing value.\n");
free(value);
return NULL;
}
@@ -360,12 +360,12 @@ static celix_array_list_t* filter_parseSubstring(char * filterString, int * pos)
break;
}
case '\0':{
- fprintf(stderr, "Filter Error: Unclosed bracket.");
+ fprintf(stderr, "Filter Error: Unclosed bracket.\n");
keepRunning = false;
break;
}
case '(': {
- fprintf(stderr, "Filter Error: Invalid value.");
+ fprintf(stderr, "Filter Error: Invalid value.\n");
keepRunning = false;
break;
}
@@ -396,7 +396,7 @@ static celix_array_list_t* filter_parseSubstring(char * filterString, int * pos)
free(sub);
if (celix_arrayList_size(operands) == 0) {
- fprintf(stderr, "Filter Error: Missing value.");
+ fprintf(stderr, "Filter Error: Missing value.\n");
celix_arrayList_destroy(operands);
return NULL;
}
@@ -534,7 +534,7 @@ celix_filter_t* celix_filter_create(const char *filterString) {
int pos = 0;
filter = filter_parseFilter(filterStr, &pos);
if (filter != NULL && pos != strlen(filterStr)) {
- fprintf(stderr, "Filter Error: Extraneous trailing characters.");
+ fprintf(stderr, "Filter Error: Extraneous trailing characters.\n");
filter_destroy(filter);
filter = NULL;
} else if (filter != NULL) {
@@ -579,7 +579,7 @@ void celix_filter_destroy(celix_filter_t *filter) {
celix_arrayList_destroy(filter->children);
filter->children = NULL;
} else {
- fprintf(stderr, "Filter Error: Corrupt filter. children has a value, but not an expected operand");
+ fprintf(stderr, "Filter Error: Corrupt filter. children has a value, but not an expected operand\n");
}
}
free((char*)filter->value);
diff --git a/libs/utils/src/utils.c b/libs/utils/src/utils.c
index fdd653b..e848422 100644
--- a/libs/utils/src/utils.c
+++ b/libs/utils/src/utils.c
@@ -16,18 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * utils.c
- *
- * \date Jul 27, 2010
- * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright Apache License, Version 2.0
- */
+
#include <stdlib.h>
#include <string.h>
#include "utils.h"
+#include "celix_utils.h"
unsigned int utils_stringHash(const void* strPtr) {
const char* string = strPtr;
@@ -146,3 +141,7 @@ double celix_difftime(const struct timespec *tBegin, const struct timespec *tEnd
float diff_ns = tEnd->tv_nsec - tBegin->tv_nsec;
return diff_s + (diff_ns / 1000000000.0);
}
+
+char* celix_utils_strdup(const char *str) {
+ return strndup(str, CELIX_UTILS_MAX_STRLEN);
+}
\ No newline at end of file