summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJanusz Kozerski <j.kozerski@samsung.com>2015-05-22 11:14:52 +0200
committerJanusz Kozerski <j.kozerski@samsung.com>2015-05-27 16:00:20 +0200
commit0cad75f144c2ef178d2bc7cced6cf4c4b0e57409 (patch)
treebafda22bd800b6ebd3519d3353d069bcf967f360 /src
parente1301082a4c40852dde8500b18bb2f3df88fac8f (diff)
downloadcert-checker-0cad75f144c2ef178d2bc7cced6cf4c4b0e57409.tar.gz
cert-checker-0cad75f144c2ef178d2bc7cced6cf4c4b0e57409.tar.bz2
cert-checker-0cad75f144c2ef178d2bc7cced6cf4c4b0e57409.zip
Add DPL code (needed for database support)
Changes: * change namespace from DPL to CCHECKER. * change LogPenantic -> LogDebug (journal doesn't support pedantic) * naiveSynchronizationObject() uses STL thread and chrono instead of DPL/thread Change-Id: I553a71dd5befbe4bc4d18f7582955af6ea329db7
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt15
-rw-r--r--src/dpl/core/include/dpl/assert.h43
-rw-r--r--src/dpl/core/include/dpl/availability.h30
-rw-r--r--src/dpl/core/include/dpl/char_traits.h38
-rw-r--r--src/dpl/core/include/dpl/errno_string.h35
-rw-r--r--src/dpl/core/include/dpl/exception.h385
-rw-r--r--src/dpl/core/include/dpl/noncopyable.h38
-rw-r--r--src/dpl/core/include/dpl/noreturn.h27
-rw-r--r--src/dpl/core/include/dpl/optional.h175
-rw-r--r--src/dpl/core/include/dpl/scoped_array.h65
-rw-r--r--src/dpl/core/include/dpl/scoped_free.h57
-rw-r--r--src/dpl/core/include/dpl/scoped_resource.h80
-rw-r--r--src/dpl/core/include/dpl/string.h140
-rw-r--r--src/dpl/core/src/assert.cpp68
-rw-r--r--src/dpl/core/src/char_traits.cpp34
-rw-r--r--src/dpl/core/src/errno_string.cpp98
-rw-r--r--src/dpl/core/src/exception.cpp57
-rw-r--r--src/dpl/core/src/noncopyable.cpp31
-rw-r--r--src/dpl/core/src/string.cpp251
-rw-r--r--src/dpl/db/include/dpl/db/naive_synchronization_object.h45
-rw-r--r--src/dpl/db/include/dpl/db/sql_connection.h493
-rw-r--r--src/dpl/db/src/naive_synchronization_object.cpp45
-rw-r--r--src/dpl/db/src/sql_connection.cpp850
23 files changed, 3100 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 94a8b74..ec7e710 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,11 +2,14 @@ PKG_CHECK_MODULES(CERT_CHECKER_DEP
REQUIRED
dbus-1
dbus-glib-1
+ db-util
glib-2.0
gio-2.0
+ icu-i18n
capi-appfw-package-manager
notification
libsystemd-journal
+ sqlite3
)
SET(CERT_CHECKER_SRC_PATH ${PROJECT_SOURCE_DIR}/src)
@@ -17,12 +20,24 @@ SET(CERT_CHECKER_SOURCES
${CERT_CHECKER_SRC_PATH}/logic.cpp
# logs
${CERT_CHECKER_SRC_PATH}/log/log.cpp
+ # dpl
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/src/assert.cpp
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/src/char_traits.cpp
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/src/errno_string.cpp
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/src/exception.cpp
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/src/noncopyable.cpp
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/src/string.cpp
+ # dpl DB
+ ${CERT_CHECKER_SRC_PATH}/dpl/db/src/sql_connection.cpp
+ ${CERT_CHECKER_SRC_PATH}/dpl/db/src/naive_synchronization_object.cpp
)
INCLUDE_DIRECTORIES(SYSTEM
${CERT_CHECKER_DEP_INCLUDE_DIRS}
${CERT_CHECKER_SRC_PATH}/include/
${CERT_CHECKER_SRC_PATH}/log/
+ ${CERT_CHECKER_SRC_PATH}/dpl/core/include/
+ ${CERT_CHECKER_SRC_PATH}/dpl/db/include/
)
ADD_EXECUTABLE(${TARGET_CERT_CHECKER} ${CERT_CHECKER_SOURCES})
diff --git a/src/dpl/core/include/dpl/assert.h b/src/dpl/core/include/dpl/assert.h
new file mode 100644
index 0000000..936c71e
--- /dev/null
+++ b/src/dpl/core/include/dpl/assert.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file assert.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of assert
+ */
+#ifndef CCHECKER_ASSERT_H
+#define CCHECKER_ASSERT_H
+
+#include <dpl/noreturn.h>
+
+namespace CCHECKER {
+// Assertion handler procedure
+// Do not call directly
+// Always use Assert macro
+CCHECKER_NORETURN void AssertProc(const char *condition,
+ const char *file,
+ int line,
+ const char *function);
+} // namespace CCHECKER
+
+#define Assert(Condition) do { if (!(Condition)) { CCHECKER::AssertProc(#Condition, \
+ __FILE__, \
+ __LINE__, \
+ __FUNCTION__); \
+ } } while (0)
+
+#endif // CCHECKER_ASSERT_H
diff --git a/src/dpl/core/include/dpl/availability.h b/src/dpl/core/include/dpl/availability.h
new file mode 100644
index 0000000..b1cb894
--- /dev/null
+++ b/src/dpl/core/include/dpl/availability.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file availability.h
+ * @author Jihoon Chung (jihoon.chung@samsung.com)
+ * @version 1.0
+ */
+#ifndef CCHECKER_AVAILABILITY_H
+#define CCHECKER_AVAILABILITY_H
+
+#define CCHECKER_DEPRECATED __attribute__((deprecated))
+#define CCHECKER_DEPRECATED_WITH_MESSAGE(msg) __attribute__((deprecated(msg)))
+
+#define CCHECKER_UNUSED __attribute__((unused))
+#define CCHECKER_UNUSED_PARAM(variable) (void)variable
+
+#endif // CCHECKER_AVAILABILITY_H
diff --git a/src/dpl/core/include/dpl/char_traits.h b/src/dpl/core/include/dpl/char_traits.h
new file mode 100644
index 0000000..e76f48b
--- /dev/null
+++ b/src/dpl/core/include/dpl/char_traits.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file char_traits.h
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ * @brief Char traits are used to create basic_string extended with
+ * additional features
+ * Current char traits could be extended in feature to boost
+ * performance
+ */
+#ifndef CCHECKER_CHAR_TRAITS
+#define CCHECKER_CHAR_TRAITS
+
+#include <cstring>
+#include <string>
+#include <ostream>
+#include <algorithm>
+#include <dpl/exception.h>
+
+namespace CCHECKER {
+typedef std::char_traits<wchar_t> CharTraits;
+} // namespace CCHECKER
+
+#endif // CCHECKER_CHAR_TRAITS
diff --git a/src/dpl/core/include/dpl/errno_string.h b/src/dpl/core/include/dpl/errno_string.h
new file mode 100644
index 0000000..498b2af
--- /dev/null
+++ b/src/dpl/core/include/dpl/errno_string.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file errno_string.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of errno string
+ */
+#ifndef CCHECKER_ERRNO_STRING_H
+#define CCHECKER_ERRNO_STRING_H
+
+#include <dpl/exception.h>
+#include <string>
+#include <cerrno>
+
+namespace CCHECKER {
+DECLARE_EXCEPTION_TYPE(CCHECKER::Exception, InvalidErrnoValue)
+
+std::string GetErrnoString(int error = errno);
+} // namespace CCHECKER
+
+#endif // CCHECKER_ERRNO_STRING_H
diff --git a/src/dpl/core/include/dpl/exception.h b/src/dpl/core/include/dpl/exception.h
new file mode 100644
index 0000000..f7b9afc
--- /dev/null
+++ b/src/dpl/core/include/dpl/exception.h
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file exception.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief Header file for base exception
+ */
+#ifndef CCHECKER_EXCEPTION_H
+#define CCHECKER_EXCEPTION_H
+
+#include <string>
+#include <cstring>
+#include <cstdio>
+#include <exception>
+#include <cstdlib>
+#include <sstream>
+
+namespace CCHECKER {
+void LogUnhandledException(const std::string &str);
+void LogUnhandledException(const std::string &str,
+ const char *filename,
+ int line,
+ const char *function);
+}
+
+namespace CCHECKER {
+class Exception
+{
+ private:
+ static unsigned int m_exceptionCount;
+ static Exception* m_lastException;
+ static void (*m_terminateHandler)();
+
+ static void AddRef(Exception* exception)
+ {
+ if (!m_exceptionCount) {
+ m_terminateHandler = std::set_terminate(&TerminateHandler);
+ }
+
+ ++m_exceptionCount;
+ m_lastException = exception;
+ }
+
+ static void UnRef(Exception* e)
+ {
+ if (m_lastException == e) {
+ m_lastException = NULL;
+ }
+
+ --m_exceptionCount;
+
+ if (!m_exceptionCount) {
+ std::set_terminate(m_terminateHandler);
+ m_terminateHandler = NULL;
+ }
+ }
+
+ static void TerminateHandler()
+ {
+ if (m_lastException != NULL) {
+ DisplayKnownException(*m_lastException);
+ abort();
+ } else {
+ DisplayUnknownException();
+ abort();
+ }
+ }
+
+ Exception *m_reason;
+ std::string m_path;
+ std::string m_function;
+ int m_line;
+
+ protected:
+ std::string m_message;
+ std::string m_className;
+
+ public:
+ static std::string KnownExceptionToString(const Exception &e)
+ {
+ std::ostringstream message;
+ message <<
+ "\033[1;5;31m\n=== Unhandled CCHECKER exception occurred ===\033[m\n\n";
+ message << "\033[1;33mException trace:\033[m\n\n";
+ message << e.DumpToString();
+ message << "\033[1;31m\n=== Will now abort ===\033[m\n";
+
+ return message.str();
+ }
+
+ static std::string UnknownExceptionToString()
+ {
+ std::ostringstream message;
+ message <<
+ "\033[1;5;31m\n=== Unhandled non-CCHECKER exception occurred ===\033[m\n\n";
+ message << "\033[1;31m\n=== Will now abort ===\033[m\n";
+
+ return message.str();
+ }
+
+ static void DisplayKnownException(const Exception& e)
+ {
+ LogUnhandledException(KnownExceptionToString(e).c_str());
+ }
+
+ static void DisplayUnknownException()
+ {
+ LogUnhandledException(UnknownExceptionToString().c_str());
+ }
+
+ Exception(const Exception &other)
+ {
+ // Deep copy
+ if (other.m_reason != NULL) {
+ m_reason = new Exception(*other.m_reason);
+ } else {
+ m_reason = NULL;
+ }
+
+ m_message = other.m_message;
+ m_path = other.m_path;
+ m_function = other.m_function;
+ m_line = other.m_line;
+
+ m_className = other.m_className;
+
+ AddRef(this);
+ }
+
+ const Exception &operator =(const Exception &other)
+ {
+ if (this == &other) {
+ return *this;
+ }
+
+ // Deep copy
+ if (other.m_reason != NULL) {
+ m_reason = new Exception(*other.m_reason);
+ } else {
+ m_reason = NULL;
+ }
+
+ m_message = other.m_message;
+ m_path = other.m_path;
+ m_function = other.m_function;
+ m_line = other.m_line;
+
+ m_className = other.m_className;
+
+ AddRef(this);
+
+ return *this;
+ }
+
+ Exception(const char *path,
+ const char *function,
+ int line,
+ const std::string &message) :
+ m_reason(NULL),
+ m_path(path),
+ m_function(function),
+ m_line(line),
+ m_message(message)
+ {
+ AddRef(this);
+ }
+
+ Exception(const char *path,
+ const char *function,
+ int line,
+ const Exception &reason,
+ const std::string &message) :
+ m_reason(new Exception(reason)),
+ m_path(path),
+ m_function(function),
+ m_line(line),
+ m_message(message)
+ {
+ AddRef(this);
+ }
+
+ virtual ~Exception() throw()
+ {
+ if (m_reason != NULL) {
+ delete m_reason;
+ m_reason = NULL;
+ }
+
+ UnRef(this);
+ }
+
+ void Dump() const
+ {
+ // Show reason first
+ if (m_reason != NULL) {
+ m_reason->Dump();
+ }
+
+ // Afterward, dump exception
+ const char *file = strchr(m_path.c_str(), '/');
+
+ if (file == NULL) {
+ file = m_path.c_str();
+ } else {
+ ++file;
+ }
+
+ printf("\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
+ file, m_line,
+ m_function.c_str(),
+ m_className.c_str(),
+ m_message.empty() ? "<EMPTY>" : m_message.c_str());
+ }
+
+ std::string DumpToString() const
+ {
+ std::string ret;
+ if (m_reason != NULL) {
+ ret = m_reason->DumpToString();
+ }
+
+ const char *file = strchr(m_path.c_str(), '/');
+
+ if (file == NULL) {
+ file = m_path.c_str();
+ } else {
+ ++file;
+ }
+
+ char buf[1024];
+ snprintf(buf,
+ sizeof(buf),
+ "\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
+ file,
+ m_line,
+ m_function.c_str(),
+ m_className.c_str(),
+ m_message.empty() ? "<EMPTY>" : m_message.c_str());
+
+ buf[sizeof(buf) - 1] = '\n';
+ ret += buf;
+
+ return ret;
+ }
+
+ Exception *GetReason() const
+ {
+ return m_reason;
+ }
+
+ std::string GetPath() const
+ {
+ return m_path;
+ }
+
+ std::string GetFunction() const
+ {
+ return m_function;
+ }
+
+ int GetLine() const
+ {
+ return m_line;
+ }
+
+ std::string GetMessage() const
+ {
+ return m_message;
+ }
+
+ std::string GetClassName() const
+ {
+ return m_className;
+ }
+};
+} // namespace CCHECKER
+
+#define Try try
+
+#define Throw(ClassName) \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__)
+
+#define ThrowMsg(ClassName, Message) \
+ do \
+ { \
+ std::ostringstream dplLoggingStream; \
+ dplLoggingStream << Message; \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__, dplLoggingStream.str()); \
+ } while (0)
+
+#define ReThrow(ClassName) \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__, _rethrown_exception)
+
+#define ReThrowMsg(ClassName, Message) \
+ throw ClassName(__FILE__, \
+ __FUNCTION__, \
+ __LINE__, \
+ _rethrown_exception, \
+ Message)
+
+#define Catch(ClassName) \
+ catch (const ClassName &_rethrown_exception)
+
+#define DECLARE_EXCEPTION_TYPE(BaseClass, Class) \
+ class Class : \
+ public BaseClass \
+ { \
+ public: \
+ Class(const char *path, \
+ const char *function, \
+ int line, \
+ const std::string & message = std::string()) : \
+ BaseClass(path, function, line, message) \
+ { \
+ BaseClass::m_className = #Class; \
+ } \
+ \
+ Class(const char *path, \
+ const char *function, \
+ int line, \
+ const CCHECKER::Exception & reason, \
+ const std::string & message = std::string()) : \
+ BaseClass(path, function, line, reason, message) \
+ { \
+ BaseClass::m_className = #Class; \
+ } \
+ };
+
+#define UNHANDLED_EXCEPTION_HANDLER_BEGIN try
+
+#define UNHANDLED_EXCEPTION_HANDLER_END \
+ catch (const CCHECKER::Exception &exception) \
+ { \
+ std::ostringstream msg; \
+ msg << CCHECKER::Exception::KnownExceptionToString(exception); \
+ CCHECKER::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } \
+ catch (std::exception& e) \
+ { \
+ std::ostringstream msg; \
+ msg << e.what(); \
+ msg << "\n"; \
+ msg << CCHECKER::Exception::UnknownExceptionToString(); \
+ CCHECKER::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } \
+ catch (...) \
+ { \
+ std::ostringstream msg; \
+ msg << CCHECKER::Exception::UnknownExceptionToString(); \
+ CCHECKER::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ }
+
+namespace CCHECKER {
+namespace CommonException {
+/**
+ * Internal exception definitions
+ *
+ * These should normally not happen.
+ * Usually, exception trace with internal error includes
+ * important messages.
+ */
+DECLARE_EXCEPTION_TYPE(Exception, InternalError) ///< Unexpected error from
+ // underlying libraries or
+ // kernel
+}
+}
+
+#endif // CCHECKER_EXCEPTION_H
diff --git a/src/dpl/core/include/dpl/noncopyable.h b/src/dpl/core/include/dpl/noncopyable.h
new file mode 100644
index 0000000..747299c
--- /dev/null
+++ b/src/dpl/core/include/dpl/noncopyable.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file noncopyable
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of noncopyable
+ */
+#ifndef CCHECKER_NONCOPYABLE_H
+#define CCHECKER_NONCOPYABLE_H
+
+namespace CCHECKER {
+class Noncopyable
+{
+ private:
+ Noncopyable(const Noncopyable &);
+ const Noncopyable &operator=(const Noncopyable &);
+
+ public:
+ Noncopyable();
+ virtual ~Noncopyable();
+};
+} // namespace CCHECKER
+
+#endif // CCHECKER_NONCOPYABLE_H
diff --git a/src/dpl/core/include/dpl/noreturn.h b/src/dpl/core/include/dpl/noreturn.h
new file mode 100644
index 0000000..6eaaa64
--- /dev/null
+++ b/src/dpl/core/include/dpl/noreturn.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file noreturn.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of noreturn
+ */
+#ifndef CCHECKER_NORETURN_H
+#define CCHECKER_NORETURN_H
+
+#define CCHECKER_NORETURN __attribute__((__noreturn__))
+
+#endif // CCHECKER_NORETURN_H
diff --git a/src/dpl/core/include/dpl/optional.h b/src/dpl/core/include/dpl/optional.h
new file mode 100644
index 0000000..6aca7bd
--- /dev/null
+++ b/src/dpl/core/include/dpl/optional.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file optional_value.h
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ */
+
+#ifndef CCHECKER_OPTIONAL_H
+#define CCHECKER_OPTIONAL_H
+
+#include <dpl/exception.h>
+
+namespace CCHECKER {
+template <typename Type>
+class Optional
+{
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(CCHECKER::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, NullReference)
+ };
+
+ public:
+ Optional() :
+ m_null(true),
+ m_value()
+ {}
+
+ Optional(const Type& t) :
+ m_null(false),
+ m_value(t)
+ {}
+
+ bool IsNull() const
+ {
+ return m_null;
+ }
+
+ Type& operator*()
+ {
+ if (m_null) {
+ Throw(typename Exception::NullReference);
+ }
+ return m_value;
+ }
+
+ const Type& operator*() const
+ {
+ if (m_null) {
+ Throw(typename Exception::NullReference);
+ }
+ return m_value;
+ }
+
+ const Type* operator->() const
+ {
+ if (m_null) {
+ Throw(typename Exception::NullReference);
+ }
+ return &m_value;
+ }
+
+ Type* operator->()
+ {
+ if (m_null) {
+ Throw(typename Exception::NullReference);
+ }
+ return &m_value;
+ }
+
+ bool operator!() const
+ {
+ return m_null;
+ }
+
+ Optional<Type>& operator=(const Type& other)
+ {
+ m_null = false;
+ m_value = other;
+ return *this;
+ }
+
+ bool operator==(const Optional<Type>& aSecond) const
+ {
+ return LogicalOperator<true>(*this, aSecond,
+ std::equal_to<Type>(), std::equal_to<bool>());
+ }
+
+ bool operator==(const Type& aSecond) const
+ {
+ return Optional<Type>(aSecond) == *this;
+ }
+
+ bool operator!=(const Optional<Type>& aSecond) const
+ {
+ return !(*this == aSecond);
+ }
+
+ bool operator<(const Optional<Type>& aSecond) const
+ {
+ return LogicalOperator<false>(*this, aSecond,
+ std::less<Type>(), std::less<bool>());
+ }
+
+ bool operator>(const Optional<Type>& aSecond) const
+ {
+ return LogicalOperator<false>(*this, aSecond,
+ std::greater<Type>(), std::greater<bool>());
+ }
+
+ bool operator<=(const Optional<Type>& aSecond) const
+ {
+ return *this == aSecond || *this < aSecond;
+ }
+
+ bool operator>=(const Optional<Type>& aSecond) const
+ {
+ return *this == aSecond || *this > aSecond;
+ }
+
+ static Optional<Type> Null;
+
+ private:
+ bool m_null;
+ Type m_value;
+
+ template <bool taEquality, typename taComparator, typename taNullComparator>
+ static bool LogicalOperator(const Optional<Type>& aFirst,
+ const Optional<Type>& aSecond,
+ taComparator aComparator,
+ taNullComparator aNullComparator)
+ {
+ if (aFirst.m_null == aSecond.m_null) {
+ if (aFirst.m_null) {
+ return taEquality;
+ } else {
+ return aComparator(aFirst.m_value, aSecond.m_value);
+ }
+ } else {
+ return aNullComparator(aFirst.m_null, aSecond.m_null);
+ }
+ }
+};
+
+template<typename Type>
+Optional<Type> Optional<Type>::Null = Optional<Type>();
+} //namespace CCHECKER
+
+template<typename Type>
+std::ostream& operator<<(std::ostream& aStream,
+ const CCHECKER::Optional<Type>& aOptional)
+{
+ if (aOptional.IsNull()) {
+ return aStream << "null optional";
+ } else {
+ return aStream << *aOptional;
+ }
+}
+
+#endif // CCHECKER_OPTIONAL_VALUE_H
diff --git a/src/dpl/core/include/dpl/scoped_array.h b/src/dpl/core/include/dpl/scoped_array.h
new file mode 100644
index 0000000..ca6a02b
--- /dev/null
+++ b/src/dpl/core/include/dpl/scoped_array.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*!
+ * @file scoped_ptr.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped array RAII
+ */
+#ifndef CCHECKER_SCOPED_ARRAY_H
+#define CCHECKER_SCOPED_ARRAY_H
+
+#include <cstddef>
+
+#include <dpl/assert.h>
+#include <dpl/scoped_resource.h>
+
+namespace CCHECKER {
+template<typename Class>
+struct ScopedArrayPolicy
+{
+ typedef Class* Type;
+ static Type NullValue()
+ {
+ return NULL;
+ }
+ static void Destroy(Type ptr)
+ {
+ delete[] ptr;
+ }
+};
+
+template<typename Class>
+class ScopedArray : public ScopedResource<ScopedArrayPolicy<Class> >
+{
+ typedef ScopedArrayPolicy<Class> Policy;
+ typedef ScopedResource<Policy> BaseType;
+
+ public:
+ explicit ScopedArray(Class *ptr = Policy::NullValue()) : BaseType(ptr) { }
+
+ Class &operator [](std::ptrdiff_t k) const
+ {
+ Assert(this->m_value != Policy::NullValue() &&
+ "Dereference of scoped NULL array!");
+ Assert(k >= 0 && "Negative array index");
+
+ return this->m_value[k];
+ }
+};
+} // namespace CCHECKER
+
+#endif // CCHECKER_SCOPED_PTR_H
diff --git a/src/dpl/core/include/dpl/scoped_free.h b/src/dpl/core/include/dpl/scoped_free.h
new file mode 100644
index 0000000..9be17b7
--- /dev/null
+++ b/src/dpl/core/include/dpl/scoped_free.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*!
+ * @file scoped_free.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped free RAII
+ */
+
+#ifndef CCHECKER_SCOPED_FREE_H
+#define CCHECKER_SCOPED_FREE_H
+
+#include <malloc.h>
+#include <cstddef>
+
+#include <dpl/scoped_resource.h>
+
+namespace CCHECKER {
+template<typename Class>
+struct ScopedFreePolicy
+{
+ typedef Class* Type;
+ static Type NullValue()
+ {
+ return NULL;
+ }
+ static void Destroy(Type ptr)
+ {
+ free(ptr);
+ }
+};
+
+template<typename Memory>
+class ScopedFree : public ScopedResource<ScopedFreePolicy<Memory> >
+{
+ typedef ScopedFreePolicy<Memory> Policy;
+ typedef ScopedResource<Policy> BaseType;
+
+ public:
+ explicit ScopedFree(Memory *ptr = Policy::NullValue()) : BaseType(ptr) { }
+};
+} // namespace CCHECKER
+
+#endif // CCHECKER_SCOPED_FREE_H
diff --git a/src/dpl/core/include/dpl/scoped_resource.h b/src/dpl/core/include/dpl/scoped_resource.h
new file mode 100644
index 0000000..c024684
--- /dev/null
+++ b/src/dpl/core/include/dpl/scoped_resource.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file scoped_resource.h
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped resource pattern
+ */
+#ifndef CCHECKER_SCOPED_RESOURCE_H
+#define CCHECKER_SCOPED_RESOURCE_H
+
+#include <dpl/noncopyable.h>
+
+namespace CCHECKER {
+template<typename ClassPolicy>
+class ScopedResource :
+ private Noncopyable
+{
+ public:
+ typedef typename ClassPolicy::Type ValueType;
+ typedef ScopedResource<ClassPolicy> ThisType;
+
+ protected:
+ ValueType m_value;
+
+ public:
+ explicit ScopedResource(ValueType value) : m_value(value) { }
+
+ ~ScopedResource()
+ {
+ ClassPolicy::Destroy(m_value);
+ }
+
+ ValueType Get() const
+ {
+ return m_value;
+ }
+
+ void Reset(ValueType value = ClassPolicy::NullValue())
+ {
+ ClassPolicy::Destroy(m_value);
+ m_value = value;
+ }
+
+ ValueType Release()
+ {
+ ValueType value = m_value;
+ m_value = ClassPolicy::NullValue();
+ return value;
+ }
+ typedef ValueType ThisType::*UnknownBoolType;
+
+ operator UnknownBoolType() const
+ {
+ return m_value == ClassPolicy::NullValue() ?
+ 0 : //0 is valid here because it converts to false
+ &ThisType::m_value; //it converts to true
+ }
+
+ bool operator !() const
+ {
+ return m_value == ClassPolicy::NullValue();
+ }
+};
+} // namespace CCHECKER
+
+#endif // CCHECKER_SCOPED_RESOURCE_H
diff --git a/src/dpl/core/include/dpl/string.h b/src/dpl/core/include/dpl/string.h
new file mode 100644
index 0000000..a271e5a
--- /dev/null
+++ b/src/dpl/core/include/dpl/string.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file string.h
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ */
+#ifndef CCHECKER_STRING
+#define CCHECKER_STRING
+
+#include <dpl/exception.h>
+#include <dpl/char_traits.h>
+#include <string>
+#include <ostream>
+#include <numeric>
+
+namespace CCHECKER {
+// @brief CCHECKER string
+typedef std::basic_string<wchar_t, CharTraits> String;
+
+// @brief String exception class
+class StringException
+{
+ public:
+ DECLARE_EXCEPTION_TYPE(CCHECKER::Exception, Base)
+
+ // @brief Invalid init for UTF8 to UTF32 converter
+ DECLARE_EXCEPTION_TYPE(Base, IconvInitErrorUTF8ToUTF32)
+
+ // @brief Invalid taStdContainerinit for UTF32 to UTF32 converter
+ DECLARE_EXCEPTION_TYPE(Base, IconvInitErrorUTF32ToUTF8)
+
+ // @brief Invalid conversion for UTF8 to UTF32 converter
+ DECLARE_EXCEPTION_TYPE(Base, IconvConvertErrorUTF8ToUTF32)
+
+ // @brief Invalid conversion for UTF8 to UTF32 converter
+ DECLARE_EXCEPTION_TYPE(Base, IconvConvertErrorUTF32ToUTF8)
+
+ // @brief Invalid ASCII character detected in FromASCII
+ DECLARE_EXCEPTION_TYPE(Base, InvalidASCIICharacter)
+
+ // @brief Invalid ASCII character detected in FromASCII
+ DECLARE_EXCEPTION_TYPE(Base, ICUInvalidCharacterFound)
+};
+
+//!\brief convert ASCII string to CCHECKER::String
+String FromASCIIString(const std::string& aString);
+
+//!\brief convert UTF32 string to CCHECKER::String
+String FromUTF32String(const std::wstring& aString);
+
+//@brief Returns String object created from UTF8 string
+//@param[in] aString input UTF-8 string
+String FromUTF8String(const std::string& aString);
+
+//@brief Returns String content as std::string
+std::string ToUTF8String(const String& aString);
+
+//@brief Compare two unicode strings
+int StringCompare(const String &left,
+ const String &right,
+ bool caseInsensitive = false);
+
+//@brief Splits the string into substrings.
+//@param[in] str Input string
+//@param[in] delimiters array or string containing a sequence of substring
+// delimiters. Can be also a single delimiter character.
+//@param[in] it InserterIterator that is used to save the generated substrings.
+template<typename StringType, typename Delimiters, typename InserterIterator>
+void Tokenize(const StringType& str,
+ const Delimiters& delimiters,
+ InserterIterator it,
+ bool ignoreEmpty = false)
+{
+ typename StringType::size_type nextSearchStart = 0;
+ typename StringType::size_type pos;
+ typename StringType::size_type length;
+
+ while (true) {
+ pos = str.find_first_of(delimiters, nextSearchStart);
+ length =
+ ((pos == StringType::npos) ? str.length() : pos) - nextSearchStart;
+
+ if (!ignoreEmpty || length > 0) {
+ *it = str.substr(nextSearchStart, length);
+ it++;
+ }
+
+ if (pos == StringType::npos) {
+ return;
+ }
+
+ nextSearchStart = pos + 1;
+ }
+}
+
+namespace Utils {
+
+template<typename T> class ConcatFunc : public std::binary_function<T, T, T>
+{
+public:
+ explicit ConcatFunc(const T & val) : m_delim(val) {}
+ T operator()(const T & arg1, const T & arg2) const
+ {
+ return arg1 + m_delim + arg2;
+ }
+private:
+ T m_delim;
+};
+
+}
+
+template<typename ForwardIterator>
+typename ForwardIterator::value_type Join(ForwardIterator begin, ForwardIterator end, typename ForwardIterator::value_type delim)
+{
+ typedef typename ForwardIterator::value_type value;
+ if(begin == end) return value();
+ Utils::ConcatFunc<value> func(delim);
+ ForwardIterator init = begin;
+ return std::accumulate(++begin, end, *init, func);
+}
+
+} //namespace CCHECKER
+
+std::ostream& operator<<(std::ostream& aStream, const CCHECKER::String& aString);
+
+#endif // CCHECKER_STRING
diff --git a/src/dpl/core/src/assert.cpp b/src/dpl/core/src/assert.cpp
new file mode 100644
index 0000000..f317dd6
--- /dev/null
+++ b/src/dpl/core/src/assert.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file assert.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of assert
+ */
+#include <stddef.h>
+#include <dpl/assert.h>
+#include <cstdlib>
+#include <dpl/exception.h>
+
+#include <log.h>
+
+namespace CCHECKER {
+void AssertProc(const char *condition,
+ const char *file,
+ int line,
+ const char *function)
+{
+#define INTERNAL_LOG(message) \
+ do \
+ { \
+ std::ostringstream platformLog; \
+ platformLog << message; \
+ JournalLog(LOG_DEBUG, \
+ platformLog.str().c_str(), \
+ __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ while (0)
+
+ // Try to log failed assertion to log system
+ Try
+ {
+ INTERNAL_LOG(
+ "################################################################################");
+ INTERNAL_LOG(
+ "### cert-checker assertion failed! ###");
+ INTERNAL_LOG(
+ "################################################################################");
+ INTERNAL_LOG("### Condition: " << condition);
+ INTERNAL_LOG("### File: " << file);
+ INTERNAL_LOG("### Line: " << line);
+ INTERNAL_LOG("### Function: " << function);
+ INTERNAL_LOG(
+ "################################################################################");
+ } catch (Exception) {
+ // Just ignore possible double errors
+ }
+
+ // Fail with c-library abort
+ abort();
+}
+} // namespace CCHECKER
diff --git a/src/dpl/core/src/char_traits.cpp b/src/dpl/core/src/char_traits.cpp
new file mode 100644
index 0000000..32b9197
--- /dev/null
+++ b/src/dpl/core/src/char_traits.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file char_traits.cpp
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ * @biref Char traits are used to create basic_string extended with
+ * additional features
+ * Current char traits could be extended in feature to boost
+ * performance
+ */
+#include <stddef.h>
+#include <dpl/char_traits.h>
+
+//
+// Note:
+//
+// The file here is left blank to enable precompilation
+// of templates in corresponding header file.
+// Do not remove this file.
+//
diff --git a/src/dpl/core/src/errno_string.cpp b/src/dpl/core/src/errno_string.cpp
new file mode 100644
index 0000000..e481a02
--- /dev/null
+++ b/src/dpl/core/src/errno_string.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file errno_string.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of errno string
+ */
+#include <stddef.h>
+#include <dpl/errno_string.h>
+#include <dpl/assert.h>
+#include <dpl/exception.h>
+#include <dpl/assert.h>
+#include <dpl/scoped_free.h>
+#include <string>
+#include <cstddef>
+#include <cstring>
+#include <malloc.h>
+#include <cerrno>
+#include <stdexcept>
+
+namespace CCHECKER {
+namespace // anonymous
+{
+const size_t DEFAULT_ERRNO_STRING_SIZE = 32;
+} // namespace anonymous
+
+std::string GetErrnoString(int error)
+{
+ size_t size = DEFAULT_ERRNO_STRING_SIZE;
+ char *buffer = NULL;
+
+ for (;;) {
+ // Add one extra characted for end of string null value
+ char *newBuffer = static_cast<char *>(::realloc(buffer, size + 1));
+
+ if (!newBuffer) {
+ // Failed to realloc
+ ::free(buffer);
+ throw std::bad_alloc();
+ }
+
+ // Setup reallocated buffer
+ buffer = newBuffer;
+ ::memset(buffer, 0, size + 1);
+
+ // Try to retrieve error string
+#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
+ // The XSI-compliant version of strerror_r() is provided if:
+ int result = ::strerror_r(error, buffer, size);
+
+ if (result == 0) {
+ ScopedFree<char> scopedBufferFree(buffer);
+ return std::string(buffer);
+ }
+#else
+ errno = 0;
+
+ // Otherwise, the GNU-specific version is provided.
+ char *result = ::strerror_r(error, buffer, size);
+
+ if (result != NULL) {
+ ScopedFree<char> scopedBufferFree(buffer);
+ return std::string(result);
+ }
+#endif
+
+ // Interpret errors
+ switch (errno) {
+ case EINVAL:
+ // We got an invalid errno value
+ ::free(buffer);
+ ThrowMsg(InvalidErrnoValue, "Invalid errno value: " << error);
+
+ case ERANGE:
+ // Incease buffer size and retry
+ size <<= 1;
+ continue;
+
+ default:
+ Assert(0 && "Invalid errno value after call to strerror_r!");
+ }
+ }
+}
+} // namespace CCHECKER
diff --git a/src/dpl/core/src/exception.cpp b/src/dpl/core/src/exception.cpp
new file mode 100644
index 0000000..7b936fe
--- /dev/null
+++ b/src/dpl/core/src/exception.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file exception.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation of exception system
+ */
+#include <stddef.h>
+#include <dpl/exception.h>
+#include <cstdio>
+
+#include <log.h>
+
+namespace CCHECKER {
+Exception* Exception::m_lastException = NULL;
+unsigned int Exception::m_exceptionCount = 0;
+void (*Exception::m_terminateHandler)() = NULL;
+
+void LogUnhandledException(const std::string &str)
+{
+ // Logging to console
+ printf("%s\n", str.c_str());
+
+ // Logging to dlog
+ LogDebug(str);
+}
+
+void LogUnhandledException(const std::string &str,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ // Logging to console
+ std::ostringstream msg;
+ msg << "\033[1;5;31m\n=== [" << filename << ":" << line << "] " <<
+ function << " ===\033[m";
+ msg << str;
+ printf("%s\n", msg.str().c_str());
+
+ // Logging to dlog
+ LogError(str.c_str() << filename << line << function);
+}
+} // namespace CCHECKER
diff --git a/src/dpl/core/src/noncopyable.cpp b/src/dpl/core/src/noncopyable.cpp
new file mode 100644
index 0000000..1ae80e9
--- /dev/null
+++ b/src/dpl/core/src/noncopyable.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file noncopyable.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of noncopyable
+ */
+#include <stddef.h>
+#include <dpl/noncopyable.h>
+
+namespace CCHECKER {
+Noncopyable::Noncopyable()
+{}
+
+Noncopyable::~Noncopyable()
+{}
+} // namespace CCHECKER
diff --git a/src/dpl/core/src/string.cpp b/src/dpl/core/src/string.cpp
new file mode 100644
index 0000000..5d33ba8
--- /dev/null
+++ b/src/dpl/core/src/string.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file string.cpp
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ */
+#include <stddef.h>
+#include <dpl/string.h>
+#include <dpl/char_traits.h>
+#include <dpl/errno_string.h>
+#include <dpl/exception.h>
+#include <dpl/scoped_array.h>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <cstring>
+#include <errno.h>
+#include <iconv.h>
+#include <unicode/ustring.h>
+
+#include <log.h>
+
+// TODO: Completely move to ICU
+namespace CCHECKER {
+namespace //anonymous
+{
+class ASCIIValidator
+{
+ const std::string& m_TestedString;
+
+ public:
+ ASCIIValidator(const std::string& aTestedString);
+
+ void operator()(char aCharacter) const;
+};
+
+ASCIIValidator::ASCIIValidator(const std::string& aTestedString) :
+ m_TestedString(aTestedString)
+{}
+
+void ASCIIValidator::operator()(char aCharacter) const
+{
+ // Check for ASCII data range
+ if (aCharacter <= 0) {
+ ThrowMsg(
+ StringException::InvalidASCIICharacter,
+ "invalid character code " << static_cast<int>(aCharacter)
+ << " from string [" <<
+ m_TestedString
+ << "] passed as ASCII");
+ }
+}
+
+const iconv_t gc_IconvOperError = reinterpret_cast<iconv_t>(-1);
+const size_t gc_IconvConvertError = static_cast<size_t>(-1);
+} // namespace anonymous
+
+String FromUTF8String(const std::string& aIn)
+{
+ if (aIn.empty()) {
+ return String();
+ }
+
+ size_t inbytes = aIn.size();
+
+ // Default iconv UTF-32 module adds BOM (4 bytes) in from of string
+ // The worst case is when 8bit UTF-8 char converts to 32bit UTF-32
+ // newsize = oldsize * 4 + end + bom
+ // newsize - bytes for UTF-32 string
+ // oldsize - letters in UTF-8 string
+ // end - end character for UTF-32 (\0)
+ // bom - Unicode header in front of string (0xfeff)
+ size_t outbytes = sizeof(wchar_t) * (inbytes + 2);
+ std::vector<wchar_t> output(inbytes + 2, 0);
+
+ size_t outbytesleft = outbytes;
+ char* inbuf = const_cast<char*>(aIn.c_str());
+
+ // vector is used to provide buffer for iconv which expects char* buffer
+ // but during conversion from UTF32 uses internaly wchar_t
+ char* outbuf = reinterpret_cast<char*>(&output[0]);
+
+ iconv_t iconvHandle = iconv_open("UTF-32", "UTF-8");
+
+ if (gc_IconvOperError == iconvHandle) {
+ int error = errno;
+
+ ThrowMsg(StringException::IconvInitErrorUTF8ToUTF32,
+ "iconv_open failed for " << "UTF-32 <- UTF-8" <<
+ "error: " << GetErrnoString(error));
+ }
+
+ size_t iconvRet = iconv(iconvHandle,
+ &inbuf,
+ &inbytes,
+ &outbuf,
+ &outbytesleft);
+
+ iconv_close(iconvHandle);
+
+ if (gc_IconvConvertError == iconvRet) {
+ ThrowMsg(StringException::IconvConvertErrorUTF8ToUTF32,
+ "iconv failed for " << "UTF-32 <- UTF-8" << "error: "
+ << GetErrnoString());
+ }
+
+ // Ignore BOM in front of UTF-32
+ return &output[1];
+}
+
+std::string ToUTF8String(const CCHECKER::String& aIn)
+{
+ if (aIn.empty()) {
+ return std::string();
+ }
+
+ size_t inbytes = aIn.size() * sizeof(wchar_t);
+ size_t outbytes = inbytes + sizeof(char);
+
+ // wstring returns wchar_t but iconv expects char*
+ // iconv internally is processing input as wchar_t
+ char* inbuf = reinterpret_cast<char*>(const_cast<wchar_t*>(aIn.c_str()));
+ std::vector<char> output(inbytes, 0);
+ char* outbuf = &output[0];
+
+ size_t outbytesleft = outbytes;
+
+ iconv_t iconvHandle = iconv_open("UTF-8", "UTF-32");
+
+ if (gc_IconvOperError == iconvHandle) {
+ ThrowMsg(StringException::IconvInitErrorUTF32ToUTF8,
+ "iconv_open failed for " << "UTF-8 <- UTF-32"
+ << "error: " << GetErrnoString());
+ }
+
+ size_t iconvRet = iconv(iconvHandle,
+ &inbuf,
+ &inbytes,
+ &outbuf,
+ &outbytesleft);
+
+ iconv_close(iconvHandle);
+
+ if (gc_IconvConvertError == iconvRet) {
+ ThrowMsg(StringException::IconvConvertErrorUTF32ToUTF8,
+ "iconv failed for " << "UTF-8 <- UTF-32"
+ << "error: " << GetErrnoString());
+ }
+
+ return &output[0];
+}
+
+String FromASCIIString(const std::string& aString)
+{
+ String output;
+
+ std::for_each(aString.begin(), aString.end(), ASCIIValidator(aString));
+ std::copy(aString.begin(), aString.end(), std::back_inserter<String>(output));
+
+ return output;
+}
+
+String FromUTF32String(const std::wstring& aString)
+{
+ return String(&aString[0]);
+}
+
+static UChar *ConvertToICU(const String &inputString)
+{
+ ScopedArray<UChar> outputString;
+ int32_t size = 0;
+ int32_t convertedSize = 0;
+ UErrorCode error = U_ZERO_ERROR;
+
+ // Calculate size of output string
+ ::u_strFromWCS(NULL,
+ 0,
+ &size,
+ inputString.c_str(),
+ -1,
+ &error);
+
+ if (error == U_ZERO_ERROR ||
+ error == U_BUFFER_OVERFLOW_ERROR)
+ {
+ // What buffer size is ok ?
+ LogDebug("ICU: Output buffer size: " << size);
+ } else {
+ ThrowMsg(StringException::ICUInvalidCharacterFound,
+ "ICU: Failed to retrieve output string size. Error: "
+ << error);
+ }
+
+ // Allocate proper buffer
+ outputString.Reset(new UChar[size + 1]);
+ ::memset(outputString.Get(), 0, sizeof(UChar) * (size + 1));
+
+ error = U_ZERO_ERROR;
+
+ // Do conversion
+ ::u_strFromWCS(outputString.Get(),
+ size + 1,
+ &convertedSize,
+ inputString.c_str(),
+ -1,
+ &error);
+
+ if (!U_SUCCESS(error)) {
+ ThrowMsg(StringException::ICUInvalidCharacterFound,
+ "ICU: Failed to convert string. Error: " << error);
+ }
+
+ // Done
+ return outputString.Release();
+}
+
+int StringCompare(const String &left,
+ const String &right,
+ bool caseInsensitive)
+{
+ // Convert input strings
+ ScopedArray<UChar> leftICU(ConvertToICU(left));
+ ScopedArray<UChar> rightICU(ConvertToICU(right));
+
+ if (caseInsensitive) {
+ return static_cast<int>(u_strcasecmp(leftICU.Get(), rightICU.Get(), 0));
+ } else {
+ return static_cast<int>(u_strcmp(leftICU.Get(), rightICU.Get()));
+ }
+}
+} //namespace CCHECKER
+
+std::ostream& operator<<(std::ostream& aStream, const CCHECKER::String& aString)
+{
+ return aStream << CCHECKER::ToUTF8String(aString);
+}
diff --git a/src/dpl/db/include/dpl/db/naive_synchronization_object.h b/src/dpl/db/include/dpl/db/naive_synchronization_object.h
new file mode 100644
index 0000000..687d666
--- /dev/null
+++ b/src/dpl/db/include/dpl/db/naive_synchronization_object.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file naive_synchronization_object.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of SQL naive
+ * synchronization object
+ */
+#ifndef CCHECKER_NAIVE_SYNCHRONIZATION_OBJECT_H
+#define CCHECKER_NAIVE_SYNCHRONIZATION_OBJECT_H
+
+#include <dpl/db/sql_connection.h>
+
+namespace CCHECKER {
+namespace DB {
+/**
+ * Naive synchronization object used to synchronize SQL connection
+ * to the same database across different threads and processes
+ */
+class NaiveSynchronizationObject :
+ public SqlConnection::SynchronizationObject
+{
+ public:
+ // [SqlConnection::SynchronizationObject]
+ virtual void Synchronize();
+ virtual void NotifyAll();
+};
+} // namespace DB
+} // namespace CCHECKER
+
+#endif // CCHECKER_NAIVE_SYNCHRONIZATION_OBJECT_H
diff --git a/src/dpl/db/include/dpl/db/sql_connection.h b/src/dpl/db/include/dpl/db/sql_connection.h
new file mode 100644
index 0000000..07cfe13
--- /dev/null
+++ b/src/dpl/db/include/dpl/db/sql_connection.h
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file sql_connection.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of SQL connection
+ */
+#ifndef CCHECKER_SQL_CONNECTION_H
+#define CCHECKER_SQL_CONNECTION_H
+
+#include <dpl/noncopyable.h>
+#include <dpl/exception.h>
+#include <dpl/optional.h>
+#include <memory>
+#include <dpl/string.h>
+#include <sqlite3.h>
+#include <string>
+#include <dpl/assert.h>
+#include <memory>
+#include <stdint.h>
+
+#include <log.h>
+
+namespace CCHECKER {
+namespace DB {
+/**
+ * SQL connection class
+ */
+class SqlConnection
+{
+ public:
+ /**
+ * SQL Exception classes
+ */
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(CCHECKER::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, SyntaxError)
+ DECLARE_EXCEPTION_TYPE(Base, ConnectionBroken)
+ DECLARE_EXCEPTION_TYPE(Base, InternalError)
+ DECLARE_EXCEPTION_TYPE(Base, InvalidColumn)
+ };
+
+ typedef int ColumnIndex;
+ typedef int ArgumentIndex;
+
+ /*
+ * SQL processed data command
+ */
+ class DataCommand :
+ private Noncopyable
+ {
+ private:
+ SqlConnection *m_masterConnection;
+ sqlite3_stmt *m_stmt;
+
+ void CheckBindResult(int result);
+ void CheckColumnIndex(SqlConnection::ColumnIndex column);
+
+ DataCommand(SqlConnection *connection, const char *buffer);
+
+ friend class SqlConnection;
+
+ public:
+ virtual ~DataCommand();
+
+ /**
+ * Bind null to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ */
+ void BindNull(ArgumentIndex position);
+
+ /**
+ * Bind int to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInteger(ArgumentIndex position, int value);
+
+ /**
+ * Bind int8_t to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt8(ArgumentIndex position, int8_t value);
+
+ /**
+ * Bind int16 to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt16(ArgumentIndex position, int16_t value);
+
+ /**
+ * Bind int32 to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt32(ArgumentIndex position, int32_t value);
+
+ /**
+ * Bind int64 to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt64(ArgumentIndex position, int64_t value);
+
+ /**
+ * Bind float to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindFloat(ArgumentIndex position, float value);
+
+ /**
+ * Bind double to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindDouble(ArgumentIndex position, double value);
+
+ /**
+ * Bind string to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindString(ArgumentIndex position, const char *value);
+
+ /**
+ * Bind string to the prepared statement argument
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindString(ArgumentIndex position, const String& value);
+
+ /**
+ * Bind optional int to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInteger(ArgumentIndex position, const Optional<int> &value);
+
+ /**
+ * Bind optional int8 to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt8(ArgumentIndex position, const Optional<int8_t> &value);
+
+ /**
+ * Bind optional int16 to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt16(ArgumentIndex position, const Optional<int16_t> &value);
+
+ /**
+ * Bind optional int32 to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt32(ArgumentIndex position, const Optional<int32_t> &value);
+
+ /**
+ * Bind optional int64 to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindInt64(ArgumentIndex position, const Optional<int64_t> &value);
+
+ /**
+ * Bind optional float to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindFloat(ArgumentIndex position, const Optional<float> &value);
+
+ /**
+ * Bind optional double to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindDouble(ArgumentIndex position, const Optional<double> &value);
+
+ /**
+ * Bind optional string to the prepared statement argument.
+ * If optional is not set null will be bound
+ *
+ * @param position Index of argument to bind value to
+ * @param value Value to bind
+ */
+ void BindString(ArgumentIndex position, const Optional<String> &value);
+
+ /**
+ * Execute the prepared statement and/or move
+ * to the next row of the result
+ *
+ * @return True when there was a row returned
+ */
+ bool Step();
+
+ /**
+ * Reset prepared statement's arguments
+ * All parameters will become null
+ */
+ void Reset();
+
+ /**
+ * Checks whether column value is null
+ *
+ * @throw Exception::InvalidColumn
+ */
+ bool IsColumnNull(ColumnIndex column);
+
+ /**
+ * Get integer value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ int GetColumnInteger(ColumnIndex column);
+
+ /**
+ * Get int8 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ int8_t GetColumnInt8(ColumnIndex column);
+
+ /**
+ * Get int16 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ int16_t GetColumnInt16(ColumnIndex column);
+ /**
+ * Get int32 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ int32_t GetColumnInt32(ColumnIndex column);
+
+ /**
+ * Get int64 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ int64_t GetColumnInt64(ColumnIndex column);
+
+ /**
+ * Get float value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ float GetColumnFloat(ColumnIndex column);
+
+ /**
+ * Get double value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ double GetColumnDouble(ColumnIndex column);
+
+ /**
+ * Get string value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ std::string GetColumnString(ColumnIndex column);
+
+ /**
+ * Get optional integer value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<int> GetColumnOptionalInteger(ColumnIndex column);
+
+ /**
+ * Get optional int8 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<int8_t> GetColumnOptionalInt8(ColumnIndex column);
+
+ /**
+ * Get optional int16value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<int16_t> GetColumnOptionalInt16(ColumnIndex column);
+
+ /**
+ * Get optional int32 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<int32_t> GetColumnOptionalInt32(ColumnIndex column);
+
+ /**
+ * Get optional int64 value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<int64_t> GetColumnOptionalInt64(ColumnIndex column);
+
+ /**
+ * Get optional float value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<float> GetColumnOptionalFloat(ColumnIndex column);
+
+ /**
+ * Get optional double value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<double> GetColumnOptionalDouble(ColumnIndex column);
+
+ /**
+ * Get optional string value from column in current row.
+ *
+ * @throw Exception::InvalidColumn
+ */
+ Optional<String> GetColumnOptionalString(ColumnIndex column);
+ };
+
+ // Move on copy semantics
+ typedef std::auto_ptr<DataCommand> DataCommandAutoPtr;
+
+ // Open flags
+ class Flag
+ {
+ public:
+ enum Type
+ {
+ None = 1 << 0,
+ UseLucene = 1 << 1
+ };
+
+ enum Option
+ {
+ RO = SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READONLY,
+ /**
+ * *TODO: please remove CREATE option from RW flag when all places
+ * that need that switched do CRW
+ */
+ RW = SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE |
+ SQLITE_OPEN_CREATE,
+ CRW = RW | SQLITE_OPEN_CREATE
+ };
+ };
+
+ // RowID
+ typedef sqlite3_int64 RowID;
+
+ /**
+ * Synchronization object used to synchronize SQL connection
+ * to the same database across different threads and processes
+ */
+ class SynchronizationObject
+ {
+ public:
+ virtual ~SynchronizationObject() {}
+
+ /**
+ * Synchronizes SQL connection for multiple clients.
+ */
+ virtual void Synchronize() = 0;
+
+ /**
+ * Notify all waiting clients that the connection is no longer locked.
+ */
+ virtual void NotifyAll() = 0;
+ };
+
+ protected:
+ sqlite3 *m_connection;
+
+ // Options
+ bool m_usingLucene;
+
+ // Stored data procedures
+ int m_dataCommandsCount;
+
+ // Synchronization object
+ std::unique_ptr<SynchronizationObject> m_synchronizationObject;
+
+ virtual void Connect(const std::string &address,
+ Flag::Type = Flag::None, Flag::Option = Flag::RO);
+ virtual void Disconnect();
+
+ void TurnOnForeignKeys();
+
+ static SynchronizationObject *AllocDefaultSynchronizationObject();
+
+ public:
+ /**
+ * Open SQL connection
+ *
+ * Synchronization is archieved by using provided asynchronization object.
+ * If synchronizationObject is set to NULL, so synchronization is performed.
+ * Ownership of the synchronization object is transfered to sql connection
+ * object.
+ *
+ * @param address Database file name
+ * @param flags Open flags
+ * @param synchronizationObject A synchronization object to use.
+ */
+ explicit SqlConnection(const std::string &address = std::string(),
+ Flag::Type flags = Flag::None,
+ Flag::Option options = Flag::RO,
+ SynchronizationObject *synchronizationObject =
+ AllocDefaultSynchronizationObject());
+
+ /**
+ * Destructor
+ */
+ virtual ~SqlConnection();
+
+ /**
+ * Execute SQL command without result
+ *
+ * @param format
+ * @param ...
+ */
+ void ExecCommand(const char *format, ...);
+
+ /**
+ * Prepare stored procedure
+ *
+ * @param format SQL statement
+ * @return Data command representing stored procedure
+ */
+ DataCommandAutoPtr PrepareDataCommand(const char *format, ...);
+
+ /**
+ * Check whether given table exists
+ *
+ * @param tableName Name of the table to check
+ * @return True if given table name exists
+ */
+ bool CheckTableExist(const char *tableName);
+
+ /**
+ * Get last insert operation new row id
+ *
+ * @return Row ID
+ */
+ RowID GetLastInsertRowID() const;
+};
+} // namespace DB
+} // namespace CCHECKER
+
+#endif // CCHECKER_SQL_CONNECTION_H
diff --git a/src/dpl/db/src/naive_synchronization_object.cpp b/src/dpl/db/src/naive_synchronization_object.cpp
new file mode 100644
index 0000000..2592c3c
--- /dev/null
+++ b/src/dpl/db/src/naive_synchronization_object.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file naive_synchronization_object.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of SQL naive
+ * synchronization object
+ */
+#include <stddef.h>
+#include <dpl/db/naive_synchronization_object.h>
+#include <chrono>
+#include <thread>
+
+namespace {
+ unsigned int seed = time(NULL);
+}
+
+namespace CCHECKER {
+namespace DB {
+void NaiveSynchronizationObject::Synchronize()
+{
+ // Sleep for about 10ms - 30ms
+ std::this_thread::sleep_for(std::chrono::milliseconds(10 + rand_r(&seed) % 20));
+}
+
+void NaiveSynchronizationObject::NotifyAll()
+{
+ // No need to inform about anything
+}
+} // namespace DB
+} // namespace CCHECKER
diff --git a/src/dpl/db/src/sql_connection.cpp b/src/dpl/db/src/sql_connection.cpp
new file mode 100644
index 0000000..0680a58
--- /dev/null
+++ b/src/dpl/db/src/sql_connection.cpp
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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.
+ */
+/*
+ * @file sql_connection.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of SQL connection
+ */
+#include <stddef.h>
+#include <dpl/db/sql_connection.h>
+#include <dpl/db/naive_synchronization_object.h>
+#include <dpl/scoped_free.h>
+#include <dpl/noncopyable.h>
+#include <dpl/assert.h>
+#include <db-util.h>
+#include <unistd.h>
+#include <cstdio>
+#include <cstdarg>
+
+namespace CCHECKER {
+namespace DB {
+namespace // anonymous
+{
+class ScopedNotifyAll :
+ public Noncopyable
+{
+ private:
+ SqlConnection::SynchronizationObject *m_synchronizationObject;
+
+ public:
+ explicit ScopedNotifyAll(
+ SqlConnection::SynchronizationObject *synchronizationObject) :
+ m_synchronizationObject(synchronizationObject)
+ {}
+
+ ~ScopedNotifyAll()
+ {
+ if (!m_synchronizationObject) {
+ return;
+ }
+
+ LogDebug("Notifying after successful synchronize");
+ m_synchronizationObject->NotifyAll();
+ }
+};
+} // namespace anonymous
+
+SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
+ const char *buffer) :
+ m_masterConnection(connection),
+ m_stmt(NULL)
+{
+ Assert(connection != NULL);
+
+ // Notify all after potentially synchronized database connection access
+ ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
+
+ for (;;) {
+ int ret = sqlite3_prepare_v2(connection->m_connection,
+ buffer, strlen(buffer),
+ &m_stmt, NULL);
+
+ if (ret == SQLITE_OK) {
+ LogDebug("Data command prepared successfuly");
+ break;
+ } else if (ret == SQLITE_BUSY) {
+ LogDebug("Collision occurred while preparing SQL command");
+
+ // Synchronize if synchronization object is available
+ if (connection->m_synchronizationObject) {
+ LogDebug("Performing synchronization");
+ connection->m_synchronizationObject->Synchronize();
+ continue;
+ }
+
+ // No synchronization object defined. Fail.
+ }
+
+ // Fatal error
+ const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
+
+ LogDebug("SQL prepare data command failed");
+ LogDebug(" Statement: " << buffer);
+ LogDebug(" Error: " << error);
+
+ ThrowMsg(Exception::SyntaxError, error);
+ }
+
+ LogDebug("Prepared data command: " << buffer);
+
+ // Increment stored data command count
+ ++m_masterConnection->m_dataCommandsCount;
+}
+
+SqlConnection::DataCommand::~DataCommand()
+{
+ LogDebug("SQL data command finalizing");
+
+ if (sqlite3_finalize(m_stmt) != SQLITE_OK) {
+ LogDebug("Failed to finalize data command");
+ }
+
+ // Decrement stored data command count
+ --m_masterConnection->m_dataCommandsCount;
+}
+
+void SqlConnection::DataCommand::CheckBindResult(int result)
+{
+ if (result != SQLITE_OK) {
+ const char *error = sqlite3_errmsg(
+ m_masterConnection->m_connection);
+
+ LogDebug("Failed to bind SQL statement parameter");
+ LogDebug(" Error: " << error);
+
+ ThrowMsg(Exception::SyntaxError, error);
+ }
+}
+
+void SqlConnection::DataCommand::BindNull(
+ SqlConnection::ArgumentIndex position)
+{
+ CheckBindResult(sqlite3_bind_null(m_stmt, position));
+ LogDebug("SQL data command bind null: ["
+ << position << "]");
+}
+
+void SqlConnection::DataCommand::BindInteger(
+ SqlConnection::ArgumentIndex position,
+ int value)
+{
+ CheckBindResult(sqlite3_bind_int(m_stmt, position, value));
+ LogDebug("SQL data command bind integer: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindInt8(
+ SqlConnection::ArgumentIndex position,
+ int8_t value)
+{
+ CheckBindResult(sqlite3_bind_int(m_stmt, position,
+ static_cast<int>(value)));
+ LogDebug("SQL data command bind int8: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindInt16(
+ SqlConnection::ArgumentIndex position,
+ int16_t value)
+{
+ CheckBindResult(sqlite3_bind_int(m_stmt, position,
+ static_cast<int>(value)));
+ LogDebug("SQL data command bind int16: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindInt32(
+ SqlConnection::ArgumentIndex position,
+ int32_t value)
+{
+ CheckBindResult(sqlite3_bind_int(m_stmt, position,
+ static_cast<int>(value)));
+ LogDebug("SQL data command bind int32: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindInt64(
+ SqlConnection::ArgumentIndex position,
+ int64_t value)
+{
+ CheckBindResult(sqlite3_bind_int64(m_stmt, position,
+ static_cast<sqlite3_int64>(value)));
+ LogDebug("SQL data command bind int64: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindFloat(
+ SqlConnection::ArgumentIndex position,
+ float value)
+{
+ CheckBindResult(sqlite3_bind_double(m_stmt, position,
+ static_cast<double>(value)));
+ LogDebug("SQL data command bind float: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindDouble(
+ SqlConnection::ArgumentIndex position,
+ double value)
+{
+ CheckBindResult(sqlite3_bind_double(m_stmt, position, value));
+ LogDebug("SQL data command bind double: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindString(
+ SqlConnection::ArgumentIndex position,
+ const char *value)
+{
+ if (!value) {
+ BindNull(position);
+ return;
+ }
+
+ // Assume that text may disappear
+ CheckBindResult(sqlite3_bind_text(m_stmt, position,
+ value, strlen(value),
+ SQLITE_TRANSIENT));
+
+ LogDebug("SQL data command bind string: ["
+ << position << "] -> " << value);
+}
+
+void SqlConnection::DataCommand::BindString(
+ SqlConnection::ArgumentIndex position,
+ const String &value)
+{
+ BindString(position, ToUTF8String(value).c_str());
+}
+
+void SqlConnection::DataCommand::BindInteger(
+ SqlConnection::ArgumentIndex position,
+ const Optional<int> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindInteger(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindInt8(
+ SqlConnection::ArgumentIndex position,
+ const Optional<int8_t> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindInt8(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindInt16(
+ SqlConnection::ArgumentIndex position,
+ const Optional<int16_t> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindInt16(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindInt32(
+ SqlConnection::ArgumentIndex position,
+ const Optional<int32_t> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindInt32(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindInt64(
+ SqlConnection::ArgumentIndex position,
+ const Optional<int64_t> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindInt64(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindFloat(
+ SqlConnection::ArgumentIndex position,
+ const Optional<float> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindFloat(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindDouble(
+ SqlConnection::ArgumentIndex position,
+ const Optional<double> &value)
+{
+ if (value.IsNull()) {
+ BindNull(position);
+ } else {
+ BindDouble(position, *value);
+ }
+}
+
+void SqlConnection::DataCommand::BindString(
+ SqlConnection::ArgumentIndex position,
+ const Optional<String> &value)
+{
+ if (!!value) {
+ BindString(position, ToUTF8String(*value).c_str());
+ } else {
+ BindNull(position);
+ }
+}
+
+bool SqlConnection::DataCommand::Step()
+{
+ // Notify all after potentially synchronized database connection access
+ ScopedNotifyAll notifyAll(
+ m_masterConnection->m_synchronizationObject.get());
+
+ for (;;) {
+ int ret = sqlite3_step(m_stmt);
+
+ if (ret == SQLITE_ROW) {
+ LogDebug("SQL data command step ROW");
+ return true;
+ } else if (ret == SQLITE_DONE) {
+ LogDebug("SQL data command step DONE");
+ return false;
+ } else if (ret == SQLITE_BUSY) {
+ LogDebug("Collision occurred while executing SQL command");
+
+ // Synchronize if synchronization object is available
+ if (m_masterConnection->m_synchronizationObject) {
+ LogDebug("Performing synchronization");
+
+ m_masterConnection->
+ m_synchronizationObject->Synchronize();
+
+ continue;
+ }
+
+ // No synchronization object defined. Fail.
+ }
+
+ // Fatal error
+ const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
+
+ LogDebug("SQL step data command failed");
+ LogDebug(" Error: " << error);
+
+ ThrowMsg(Exception::InternalError, error);
+ }
+}
+
+void SqlConnection::DataCommand::Reset()
+{
+ /*
+ * According to:
+ * http://www.sqlite.org/c3ref/stmt.html
+ *
+ * if last sqlite3_step command on this stmt returned an error,
+ * then sqlite3_reset will return that error, althought it is not an error.
+ * So sqlite3_reset allways succedes.
+ */
+ sqlite3_reset(m_stmt);
+
+ LogDebug("SQL data command reset");
+}
+
+void SqlConnection::DataCommand::CheckColumnIndex(
+ SqlConnection::ColumnIndex column)
+{
+ if (column < 0 || column >= sqlite3_column_count(m_stmt)) {
+ ThrowMsg(Exception::InvalidColumn, "Column index is out of bounds");
+ }
+}
+
+bool SqlConnection::DataCommand::IsColumnNull(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column type: [" << column << "]");
+ CheckColumnIndex(column);
+ return sqlite3_column_type(m_stmt, column) == SQLITE_NULL;
+}
+
+int SqlConnection::DataCommand::GetColumnInteger(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column integer: [" << column << "]");
+ CheckColumnIndex(column);
+ int value = sqlite3_column_int(m_stmt, column);
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+int8_t SqlConnection::DataCommand::GetColumnInt8(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column int8: [" << column << "]");
+ CheckColumnIndex(column);
+ int8_t value = static_cast<int8_t>(sqlite3_column_int(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+int16_t SqlConnection::DataCommand::GetColumnInt16(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column int16: [" << column << "]");
+ CheckColumnIndex(column);
+ int16_t value = static_cast<int16_t>(sqlite3_column_int(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+int32_t SqlConnection::DataCommand::GetColumnInt32(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column int32: [" << column << "]");
+ CheckColumnIndex(column);
+ int32_t value = static_cast<int32_t>(sqlite3_column_int(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+int64_t SqlConnection::DataCommand::GetColumnInt64(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column int64: [" << column << "]");
+ CheckColumnIndex(column);
+ int64_t value = static_cast<int64_t>(sqlite3_column_int64(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+float SqlConnection::DataCommand::GetColumnFloat(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column float: [" << column << "]");
+ CheckColumnIndex(column);
+ float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+double SqlConnection::DataCommand::GetColumnDouble(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column double: [" << column << "]");
+ CheckColumnIndex(column);
+ double value = sqlite3_column_double(m_stmt, column);
+ LogDebug(" Value: " << value);
+ return value;
+}
+
+std::string SqlConnection::DataCommand::GetColumnString(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column string: [" << column << "]");
+ CheckColumnIndex(column);
+
+ const char *value = reinterpret_cast<const char *>(
+ sqlite3_column_text(m_stmt, column));
+
+ LogDebug("Value: " << (value ? value : "NULL"));
+
+ if (value == NULL) {
+ return std::string();
+ }
+
+ return std::string(value);
+}
+
+Optional<int> SqlConnection::DataCommand::GetColumnOptionalInteger(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional integer: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<int>::Null;
+ }
+ int value = sqlite3_column_int(m_stmt, column);
+ LogDebug(" Value: " << value);
+ return Optional<int>(value);
+}
+
+Optional<int8_t> SqlConnection::DataCommand::GetColumnOptionalInt8(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional int8: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<int8_t>::Null;
+ }
+ int8_t value = static_cast<int8_t>(sqlite3_column_int(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return Optional<int8_t>(value);
+}
+
+Optional<int16_t> SqlConnection::DataCommand::GetColumnOptionalInt16(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional int16: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<int16_t>::Null;
+ }
+ int16_t value = static_cast<int16_t>(sqlite3_column_int(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return Optional<int16_t>(value);
+}
+
+Optional<int32_t> SqlConnection::DataCommand::GetColumnOptionalInt32(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional int32: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<int32_t>::Null;
+ }
+ int32_t value = static_cast<int32_t>(sqlite3_column_int(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return Optional<int32_t>(value);
+}
+
+Optional<int64_t> SqlConnection::DataCommand::GetColumnOptionalInt64(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional int64: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<int64_t>::Null;
+ }
+ int64_t value = static_cast<int64_t>(sqlite3_column_int64(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return Optional<int64_t>(value);
+}
+
+Optional<float> SqlConnection::DataCommand::GetColumnOptionalFloat(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional float: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<float>::Null;
+ }
+ float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
+ LogDebug(" Value: " << value);
+ return Optional<float>(value);
+}
+
+Optional<double> SqlConnection::DataCommand::GetColumnOptionalDouble(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional double: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<double>::Null;
+ }
+ double value = sqlite3_column_double(m_stmt, column);
+ LogDebug(" Value: " << value);
+ return Optional<double>(value);
+}
+
+Optional<String> SqlConnection::DataCommand::GetColumnOptionalString(
+ SqlConnection::ColumnIndex column)
+{
+ LogDebug("SQL data command get column optional string: ["
+ << column << "]");
+ CheckColumnIndex(column);
+ if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL) {
+ return Optional<String>::Null;
+ }
+ const char *value = reinterpret_cast<const char *>(
+ sqlite3_column_text(m_stmt, column));
+ LogDebug("Value: " << value);
+ String s = FromUTF8String(value);
+ return Optional<String>(s);
+}
+
+void SqlConnection::Connect(const std::string &address,
+ Flag::Type type,
+ Flag::Option flag)
+{
+ if (m_connection != NULL) {
+ LogDebug("Already connected.");
+ return;
+ }
+ LogDebug("Connecting to DB: " << address << "...");
+
+ // Connect to database
+ int result;
+ if (type & Flag::UseLucene) {
+ result = db_util_open_with_options(
+ address.c_str(),
+ &m_connection,
+ flag,
+ NULL);
+
+ m_usingLucene = true;
+ LogDebug("Lucene index enabled");
+ } else {
+ result = sqlite3_open_v2(
+ address.c_str(),
+ &m_connection,
+ flag,
+ NULL);
+
+ m_usingLucene = false;
+ LogDebug("Lucene index disabled");
+ }
+
+ if (result == SQLITE_OK) {
+ LogDebug("Connected to DB");
+ } else {
+ LogDebug("Failed to connect to DB!");
+ ThrowMsg(Exception::ConnectionBroken, address);
+ }
+
+ // Enable foreign keys
+ TurnOnForeignKeys();
+}
+
+void SqlConnection::Disconnect()
+{
+ if (m_connection == NULL) {
+ LogDebug("Already disconnected.");
+ return;
+ }
+
+ LogDebug("Disconnecting from DB...");
+
+ // All stored data commands must be deleted before disconnect
+ Assert(m_dataCommandsCount == 0 &&
+ "All stored procedures must be deleted"
+ " before disconnecting SqlConnection");
+
+ int result;
+
+ if (m_usingLucene) {
+ result = db_util_close(m_connection);
+ } else {
+ result = sqlite3_close(m_connection);
+ }
+
+ if (result != SQLITE_OK) {
+ const char *error = sqlite3_errmsg(m_connection);
+ LogDebug("SQL close failed");
+ LogDebug(" Error: " << error);
+ Throw(Exception::InternalError);
+ }
+
+ m_connection = NULL;
+
+ LogDebug("Disconnected from DB");
+}
+
+bool SqlConnection::CheckTableExist(const char *tableName)
+{
+ if (m_connection == NULL) {
+ LogDebug("Cannot execute command. Not connected to DB!");
+ return false;
+ }
+
+ DataCommandAutoPtr command =
+ PrepareDataCommand("select tbl_name from sqlite_master where name=?;");
+
+ command->BindString(1, tableName);
+
+ if (!command->Step()) {
+ LogDebug("No matching records in table");
+ return false;
+ }
+
+ return command->GetColumnString(0) == tableName;
+}
+
+SqlConnection::SqlConnection(const std::string &address,
+ Flag::Type flag,
+ Flag::Option option,
+ SynchronizationObject *synchronizationObject) :
+ m_connection(NULL),
+ m_usingLucene(false),
+ m_dataCommandsCount(0),
+ m_synchronizationObject(synchronizationObject)
+{
+ LogDebug("Opening database connection to: " << address);
+
+ // Connect to DB
+ SqlConnection::Connect(address, flag, option);
+
+ if (!m_synchronizationObject) {
+ LogDebug("No synchronization object defined");
+ }
+}
+
+SqlConnection::~SqlConnection()
+{
+ LogDebug("Closing database connection");
+
+ // Disconnect from DB
+ Try
+ {
+ SqlConnection::Disconnect();
+ }
+ Catch(Exception::Base)
+ {
+ LogDebug("Failed to disconnect from database");
+ }
+}
+
+void SqlConnection::ExecCommand(const char *format, ...)
+{
+ if (m_connection == NULL) {
+ LogDebug("Cannot execute command. Not connected to DB!");
+ return;
+ }
+
+ if (format == NULL) {
+ LogDebug("Null query!");
+ ThrowMsg(Exception::SyntaxError, "Null statement");
+ }
+
+ char *rawBuffer;
+
+ va_list args;
+ va_start(args, format);
+
+ if (vasprintf(&rawBuffer, format, args) == -1) {
+ rawBuffer = NULL;
+ }
+
+ va_end(args);
+
+ ScopedFree<char> buffer(rawBuffer);
+
+ if (!buffer) {
+ LogDebug("Failed to allocate statement string");
+ return;
+ }
+
+ LogDebug("Executing SQL command: " << buffer.Get());
+
+ // Notify all after potentially synchronized database connection access
+ ScopedNotifyAll notifyAll(m_synchronizationObject.get());
+
+ for (;;) {
+ char *errorBuffer;
+
+ int ret = sqlite3_exec(m_connection,
+ buffer.Get(),
+ NULL,
+ NULL,
+ &errorBuffer);
+
+ std::string errorMsg;
+
+ // Take allocated error buffer
+ if (errorBuffer != NULL) {
+ errorMsg = errorBuffer;
+ sqlite3_free(errorBuffer);
+ }
+
+ if (ret == SQLITE_OK) {
+ return;
+ }
+
+ if (ret == SQLITE_BUSY) {
+ LogDebug("Collision occurred while executing SQL command");
+
+ // Synchronize if synchronization object is available
+ if (m_synchronizationObject) {
+ LogDebug("Performing synchronization");
+ m_synchronizationObject->Synchronize();
+ continue;
+ }
+
+ // No synchronization object defined. Fail.
+ }
+
+ // Fatal error
+ LogDebug("Failed to execute SQL command. Error: " << errorMsg);
+ ThrowMsg(Exception::SyntaxError, errorMsg);
+ }
+}
+
+SqlConnection::DataCommandAutoPtr SqlConnection::PrepareDataCommand(
+ const char *format,
+ ...)
+{
+ if (m_connection == NULL) {
+ LogDebug("Cannot execute data command. Not connected to DB!");
+ return DataCommandAutoPtr();
+ }
+
+ char *rawBuffer;
+
+ va_list args;
+ va_start(args, format);
+
+ if (vasprintf(&rawBuffer, format, args) == -1) {
+ rawBuffer = NULL;
+ }
+
+ va_end(args);
+
+ ScopedFree<char> buffer(rawBuffer);
+
+ if (!buffer) {
+ LogDebug("Failed to allocate statement string");
+ return DataCommandAutoPtr();
+ }
+
+ LogDebug("Executing SQL data command: " << buffer.Get());
+
+ return DataCommandAutoPtr(new DataCommand(this, buffer.Get()));
+}
+
+SqlConnection::RowID SqlConnection::GetLastInsertRowID() const
+{
+ return static_cast<RowID>(sqlite3_last_insert_rowid(m_connection));
+}
+
+void SqlConnection::TurnOnForeignKeys()
+{
+ ExecCommand("PRAGMA foreign_keys = ON;");
+}
+
+SqlConnection::SynchronizationObject *
+SqlConnection::AllocDefaultSynchronizationObject()
+{
+ return new NaiveSynchronizationObject();
+}
+} // namespace DB
+} // namespace CCHECKER