This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch feature/celix_err
in repository https://gitbox.apache.org/repos/asf/celix.git

commit c4b9d723a54762908396123ab879d19e028a9ced
Author: Pepijn Noltes <[email protected]>
AuthorDate: Mon May 1 19:58:59 2023 +0200

    Add initial implementation for celix_err
---
 libs/utils/CMakeLists.txt            |   1 +
 libs/utils/gtest/CMakeLists.txt      |   1 +
 libs/utils/gtest/src/ErrTestSuite.cc |  56 ++++++++++++++++
 libs/utils/include/celix_err.h       |  71 ++++++++++++++++++++
 libs/utils/src/celix_err.c           | 124 +++++++++++++++++++++++++++++++++++
 5 files changed, 253 insertions(+)

diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index db500513..d57c0c7c 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -44,6 +44,7 @@ add_library(utils_obj OBJECT
         src/celix_hash_map.c
         src/celix_file_utils.c
         src/celix_convert_utils.c
+        src/celix_err.c
         ${MEMSTREAM_SOURCES}
 )
 
diff --git a/libs/utils/gtest/CMakeLists.txt b/libs/utils/gtest/CMakeLists.txt
index 2d8a47f5..47e92d96 100644
--- a/libs/utils/gtest/CMakeLists.txt
+++ b/libs/utils/gtest/CMakeLists.txt
@@ -33,6 +33,7 @@ add_executable(test_utils
         src/FilterTestSuite.cc
         src/CelixUtilsTestSuite.cc
         src/ConvertUtilsTestSuite.cc
+        src/ErrTestSuite.cc
         ${CELIX_UTIL_TEST_SOURCES_FOR_CXX_HEADERS}
 )
 
diff --git a/libs/utils/gtest/src/ErrTestSuite.cc 
b/libs/utils/gtest/src/ErrTestSuite.cc
new file mode 100644
index 00000000..abb15cb6
--- /dev/null
+++ b/libs/utils/gtest/src/ErrTestSuite.cc
@@ -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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "celix_err.h"
+
+class ErrTestSuite : public ::testing::Test {
+public:
+    ErrTestSuite() = default;
+    ~ErrTestSuite() noexcept override = default;
+};
+
+TEST_F(ErrTestSuite, AddAndPopErrorTest) {
+    EXPECT_EQ(0, celix_err_getErrorCount());
+    celix_err_push("error message");
+    celix_err_pushf("error message from %s", "test");
+    EXPECT_EQ(2, celix_err_getErrorCount());
+
+    auto* m = celix_err_popLastError();
+    EXPECT_STREQ("error message from test", m);
+    free(m);
+    EXPECT_EQ(1, celix_err_getErrorCount());
+
+    m = celix_err_popLastError();
+    EXPECT_STREQ("error message", m);
+    free(m);
+    EXPECT_EQ(0, celix_err_getErrorCount());
+}
+
+TEST_F(ErrTestSuite, ResetErrorTest) {
+    EXPECT_EQ(0, celix_err_getErrorCount());
+    celix_err_push("error message");
+    celix_err_push("error message");
+    EXPECT_EQ(2, celix_err_getErrorCount());
+
+    celix_err_resetErrors();
+    EXPECT_EQ(0, celix_err_getErrorCount());
+    EXPECT_EQ(nullptr, celix_err_popLastError());
+}
diff --git a/libs/utils/include/celix_err.h b/libs/utils/include/celix_err.h
new file mode 100644
index 00000000..16bd2d31
--- /dev/null
+++ b/libs/utils/include/celix_err.h
@@ -0,0 +1,71 @@
+/*
+ * 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 CELIX_CELIX_ERR_H
+#define CELIX_CELIX_ERR_H
+
+#include "celix_utils_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @file celix_err.h
+* @brief The celix error handling functions.
+* @thread_safety Thread safe.
+*/
+
+/**
+ * @brief Returns the last error message from the current thread.
+ * The error message must be freed by the caller.
+ * @returnval NULL if no error message is available.
+ */
+CELIX_UTILS_EXPORT
+char* celix_err_popLastError(); //TODO update to return const char* and remove 
free
+
+/**
+ * @brief Push an formatted error message to the thread specific storage rcm 
errors.
+ */
+CELIX_UTILS_EXPORT
+void celix_err_pushf(const char* format, ...) __attribute__((format(printf, 1, 
2)));
+
+/**
+ * @brief Push an error message to the thread specific storage rcm errors.
+ */
+CELIX_UTILS_EXPORT
+void celix_err_push(const char* msg);
+
+/**
+ * @brief Returns the number of error messages from the current thread.
+ */
+CELIX_UTILS_EXPORT
+int celix_err_getErrorCount();
+
+/**
+ * @brief Resets the error message for the current thread.
+ */
+CELIX_UTILS_EXPORT
+void celix_err_resetErrors();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //CELIX_CELIX_ERR_H
diff --git a/libs/utils/src/celix_err.c b/libs/utils/src/celix_err.c
new file mode 100644
index 00000000..939c7078
--- /dev/null
+++ b/libs/utils/src/celix_err.c
@@ -0,0 +1,124 @@
+/*
+ * 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_err.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#include "celix_array_list.h"
+#include "celix_utils.h"
+
+pthread_key_t celix_rcm_tssErrorsKey; //TODO replace with celix_tss_key and 
celix_tss_* functions
+
+static void celix_err_destroyTssErrors(void* data) {
+    //TODO replace array list with some thread specific storage char buffer
+    celix_array_list_t* errors = data;
+    if (errors != NULL) {
+        for (int i = 0; i < celix_arrayList_size(errors); ++i) {
+            char* msg = celix_arrayList_get(errors, i);
+            free(msg);
+        }
+    }
+    celix_arrayList_destroy(errors);
+}
+
+__attribute__((constructor)) void celix_err_initThreadSpecificStorageKey() {
+    int rc = pthread_key_create(&celix_rcm_tssErrorsKey, 
celix_err_destroyTssErrors);
+    if (rc != 0) {
+        fprintf(stderr,"Failed to create thread specific storage key for 
celix_err\n");
+    }
+}
+
+__attribute__((destructor)) void celix_err_deinitThreadSpecificStorageKey() {
+    int rc = pthread_key_delete(celix_rcm_tssErrorsKey);
+    if (rc != 0) {
+        fprintf(stderr,"Failed to delete thread specific storage key for 
celix_err\n");
+    }
+}
+
+char* celix_err_popLastError() {
+    char* result = NULL;
+    celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+    if (errors != NULL && celix_arrayList_size(errors) > 0) {
+        int last = celix_arrayList_size(errors) - 1;
+        result = celix_arrayList_get(errors, last);
+        celix_arrayList_removeAt(errors, last);
+    }
+    return result;
+}
+
+int celix_err_getErrorCount() {
+    int result = 0;
+    celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+    if (errors != NULL) {
+        result = celix_arrayList_size(errors);
+    }
+    return result;
+}
+
+void celix_err_resetErrors() {
+    celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+    celix_err_destroyTssErrors(errors);
+    pthread_setspecific(celix_rcm_tssErrorsKey, NULL);
+}
+
+static void celix_err_pushMsg(char* msg) {
+    celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+    if (errors == NULL) {
+        errors = celix_arrayList_create();
+        if (errors == NULL) {
+            fprintf(stderr, "Failed to create error list for Apache Celix rcm 
lib\n");
+            free(msg);
+            return;
+        }
+        pthread_setspecific(celix_rcm_tssErrorsKey, errors);
+    }
+    if (errors != NULL) {
+        celix_status_t rc = celix_arrayList_add(errors, msg);
+        if (rc != CELIX_SUCCESS) {
+            fprintf(stderr, "Failed to add error to error list for Apache 
Celix rcm lib\n");
+            free(msg);
+        }
+    }
+}
+
+void celix_err_push(const char* msg) {
+    char* msgCpy = celix_utils_strdup(msg);
+    if (msgCpy == NULL) {
+        fprintf(stderr, "Failed to copy error message for Apache Celix rcm 
lib\n");
+        return;
+    }
+    celix_err_pushMsg(msgCpy);
+}
+
+void celix_err_pushf(const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    char* msg = NULL;
+    int rc = vasprintf(&msg, format, args);
+    if (rc >= 0) {
+        celix_err_pushMsg(msg);
+    } else {
+        fprintf(stderr, "Failed to copy error message for Apache Celix rcm 
lib\n");
+    }
+    va_end(args);
+}

Reply via email to