summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhyunho <hhstark.kang@samsung.com>2019-03-28 19:42:50 +0900
committerHwankyu Jhun <h.jhun@samsung.com>2019-04-04 11:34:15 +0900
commit06ec93df38c0736b947e50a02c98eb93d4bed655 (patch)
tree849dbdc0de7230da7c2508aa356199e452de0fa6
parenta31d696e0f547c82f38e8e46a3769bf92b2ba91f (diff)
downloadbundle-06ec93df38c0736b947e50a02c98eb93d4bed655.tar.gz
bundle-06ec93df38c0736b947e50a02c98eb93d4bed655.tar.bz2
bundle-06ec93df38c0736b947e50a02c98eb93d4bed655.zip
Add bundle cpp APIs
Change-Id: If49381e60053911d3911ac2eac8062a50a967eee Signed-off-by: hyunho <hhstark.kang@samsung.com> Signed-off-by: Junghoon Park <jh9216.park@samsung.com>
-rw-r--r--CMakeLists.txt45
-rw-r--r--bundle.pc.in1
-rw-r--r--include/bundle_cpp.h335
-rwxr-xr-xinclude/bundle_internal.h10
-rw-r--r--packaging/bundle.spec72
-rw-r--r--src/bundle.c34
-rw-r--r--src/bundle_cpp.cc257
-rw-r--r--src/bundle_cpp_implementation.h65
-rwxr-xr-xsrc/keyval.h8
-rwxr-xr-xsrc/keyval_array.h8
-rwxr-xr-xsrc/keyval_type.h8
-rw-r--r--unit_tests/CMakeLists.txt37
-rw-r--r--unit_tests/src/test_bundle.cc156
-rw-r--r--unit_tests/src/test_main.cc23
14 files changed, 1044 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 939e00c..631c50f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,34 +1,39 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(bundle C)
-
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(bundle C CXX)
IF("${VERSION}" STREQUAL "")
- MESSAGE(FATAL_ERROR "VERSION is not defined")
+ MESSAGE(FATAL_ERROR "VERSION is not defined")
ENDIF()
STRING(REGEX MATCH "^[0-9]+" VERSION_MAJOR ${VERSION})
IF("${VERSION_MAJOR}" STREQUAL "")
- MESSAGE(FATAL_ERROR "can't get VERSION_MAJOR")
+ MESSAGE(FATAL_ERROR "can't get VERSION_MAJOR")
ENDIF()
-### Required packages
INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 dlog capi-base-common json-glib-1.0)
+pkg_check_modules(pkgs REQUIRED
+ glib-2.0 dlog capi-base-common json-glib-1.0
+)
+
FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -flto -Wall -Werror -Winline")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fvisibility=hidden -flto")
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src)
-### Local include directories
-include_directories(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src)
+AUX_SOURCE_DIRECTORY(src SOURCES)
-### Build
-aux_source_directory(src SRCS)
-add_library(bundle SHARED ${SRCS})
+ADD_LIBRARY (${PROJECT_NAME} SHARED ${SOURCES})
set_target_properties(bundle PROPERTIES SOVERSION ${VERSION_MAJOR})
set_target_properties(bundle PROPERTIES VERSION "${VERSION}")
-message(STATUS "Version from debian/changelog: ${VERSION}, Major version: ${VERSION_MAJOR}")
-target_link_libraries(bundle ${pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIE")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-pie")
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
### Make pkgconfig file
SET(PREFIX ${CMAKE_INSTALL_PREFIX})
@@ -38,3 +43,13 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/bundle.pc.in ${CMAKE_BINARY_DIR}/bundle.pc @O
install(TARGETS bundle DESTINATION ${LIB_INSTALL_DIR})
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/)
install(FILES ${CMAKE_BINARY_DIR}/bundle.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig/)
+
+IF(NOT DEFINED MINIMUM_BUILD)
+ENABLE_TESTING()
+SET(BUNDLE_UNITTESTS bundle_unittests)
+ADD_TEST(NAME ${BUNDLE_UNITTESTS} COMMAND ${BUNDLE_UNITTESTS}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unit_tests)
+
+ADD_SUBDIRECTORY(unit_tests)
+ADD_DEPENDENCIES(bundle_unittests bundle)
+ENDIF(NOT DEFINED MINIMUM_BUILD)
diff --git a/bundle.pc.in b/bundle.pc.in
index 399ea0b..c05c076 100644
--- a/bundle.pc.in
+++ b/bundle.pc.in
@@ -11,3 +11,4 @@ Version: @VERSION@
Requires: capi-base-common
Libs: -L${libdir} -lbundle
Cflags: -I${includedir}
+cppflags: -I${includedir}
diff --git a/include/bundle_cpp.h b/include/bundle_cpp.h
new file mode 100644
index 0000000..2abc522
--- /dev/null
+++ b/include/bundle_cpp.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef BUNDLE_CPP_H_
+#define BUNDLE_CPP_H_
+
+/**
+ * @file bundle_cpp.h
+ * @brief This file declares API of the bundle C++ library.
+ */
+
+/**
+ * @addtogroup CORE_LIB_BUNDLE_CPP_MODULE
+ * @{
+ */
+
+#include <bundle.h>
+#include <dlog.h>
+
+#include <cstdio>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "BUNDLE"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace tizen_base {
+
+/**
+ * @brief The class for bundle APIs.
+ * @since_tizen 5.5
+ */
+class EXPORT_API Bundle final {
+ public:
+ /**
+ * @brief The type for raw bundle.
+ * @since_tizen 5.5
+ */
+ using BundleRaw =
+ std::pair<std::unique_ptr<bundle_raw, decltype(std::free)*>, int>;
+
+ /**
+ * @brief The class for information of keys.
+ * @since_tizen 5.5
+ */
+ class KeyInfo final {
+ public:
+ /**
+ * @brief Constructor.
+ * @since_tizen 5.5
+ * @param[in] handle The handle for type bundle_keyval_t
+ * @param[in] name The key string
+ */
+ KeyInfo(const bundle_keyval_t* handle, std::string name);
+
+ /**
+ * @brief Constructor.
+ * @since_tizen 5.5
+ */
+ KeyInfo();
+
+ /**
+ * @brief Destructor.
+ * @since_tizen 5.5
+ */
+ ~KeyInfo();
+
+ /**
+ * @brief Copy-constructor.
+ * @since_tizen 5.5
+ * @param[in] b The object to copy
+ */
+ KeyInfo(const KeyInfo& b);
+
+ /**
+ * @brief Assignment.
+ * @since_tizen 5.5
+ * @param[in] b The object to copy
+ */
+ KeyInfo& operator = (const KeyInfo& b);
+
+ /**
+ * @brief Move-constructor.
+ * @since_tizen 5.5
+ * @param[in] b The object to move
+ */
+ KeyInfo(KeyInfo&& b) noexcept;
+
+ /**
+ * @brief Assignment.
+ * @since_tizen 5.5
+ * @param[in] b The object to move
+ */
+ KeyInfo& operator = (KeyInfo&& b) noexcept;
+
+ /**
+ * @brief Gets the type of a key-value pair.
+ * @since_tizen 5.5
+ * @return The type
+ */
+ bundle_type GetType() const;
+
+ /**
+ * @brief Determines whether the type of a key-value pair is an array.
+ * @since_tizen 5.5
+ * @return True when it is an array
+ */
+ bool IsArray() const;
+
+ /**
+ * @brief Gets the key string.
+ * @since_tizen 5.5
+ * @return The key string
+ */
+ const std::string& GetName() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+ };
+
+ /**
+ * @brief Constructor.
+ * @since_tizen 5.5
+ */
+ Bundle();
+
+ /**
+ * @brief Constructor.
+ * @since_tizen 5.5
+ * @param[in] raw The object for BundleRaw
+ */
+ explicit Bundle(BundleRaw raw);
+
+ /**
+ * @brief Constructor.
+ * @since_tizen 5.5
+ * @param[in] raw The string object for raw bundle
+ */
+ explicit Bundle(const std::string& raw);
+
+ /**
+ * @brief Constructor.
+ * @since_tizen 5.5
+ * @param[in] b The handle for bundle
+ * @param[in] copy True if this object wants to copy it from the handle
+ * @param[in] own True if this object owns the handle
+ */
+ explicit Bundle(bundle* b, bool copy = true, bool own = true);
+
+ /**
+ * @brief Destructor.
+ * @since_tizen 5.5
+ */
+ ~Bundle();
+
+ /**
+ * @brief Copy-constructor.
+ * @since_tizen 5.5
+ * @param[in] b The object to copy
+ */
+ Bundle(const Bundle& b);
+
+ /**
+ * @brief Assignment.
+ * @since_tizen 5.5
+ * @param[in] b The object to copy
+ */
+ Bundle& operator = (const Bundle& b);
+
+ /**
+ * @brief Move-constructor.
+ * @since_tizen 5.5
+ * @param[in] b The object to move
+ */
+ Bundle(Bundle&& b) noexcept;
+
+ /**
+ * @brief Assignment.
+ * @since_tizen 5.5
+ * @param[in] b The object to move
+ */
+ Bundle& operator = (Bundle&& b) noexcept;
+
+ /**
+ * @brief Gets keys in bundle object.
+ * @since_tizen 5.5
+ * @return A string array of object KeyInfo
+ */
+ std::vector<KeyInfo> GetKeys();
+
+ /**
+ * @brief Adds a string type key-value pair into a bundle.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @param[in] val The string value
+ * @return The operation result
+ * @retval BUNDLE_ERROR_NONE Success
+ * @retval BUNDLE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval BUNDLE_ERROR_KEY_EXISTS Key already exists
+ * @retval BUNDLE_ERROR_OUT_OF_MEMORY Out of memory
+ */
+ int Add(const std::string& key, const std::string& val);
+
+ /**
+ * @brief Adds a string type key-value pair into a bundle.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @param[in] val The array of strings
+ * @return The operation result
+ * @retval BUNDLE_ERROR_NONE Success
+ * @retval BUNDLE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval BUNDLE_ERROR_KEY_EXISTS Key already exists
+ * @retval BUNDLE_ERROR_OUT_OF_MEMORY Out of memory
+ */
+ int Add(const std::string& key, const std::vector<std::string>& val);
+
+ /**
+ * @brief Adds a string type key-value pair into a bundle.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @param[in] val The array of bytes
+ * @return The operation result
+ * @retval BUNDLE_ERROR_NONE Success
+ * @retval BUNDLE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval BUNDLE_ERROR_KEY_EXISTS Key already exists
+ * @retval BUNDLE_ERROR_OUT_OF_MEMORY Out of memory
+ */
+ int Add(const std::string& key, const std::vector<unsigned char>& val);
+
+ /**
+ * @brief Deletes a key-value object with the given key.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @return The operation result
+ * @retval BUNDLE_ERROR_NONE Success
+ * @retval BUNDLE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval BUNDLE_ERROR_KEY_NOT_AVAILABLE Key not available
+ */
+ int Delete(const std::string& key);
+
+ /**
+ * @brief Gets a string from the key.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @return The string
+ */
+ std::string GetString(const std::string& key) const;
+
+ /**
+ * @brief Gets strings from the key.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @return The array of strings
+ */
+ std::vector<std::string> GetStringArray(const std::string& key) const;
+
+ /**
+ * @brief Gets bytes from the key.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @return Bytes
+ */
+ std::vector<unsigned char> GetByte(const std::string& key) const;
+
+ /**
+ * @brief Converts this object to BundleRaw type.
+ * @since_tizen 5.5
+ * @return The object of BundleRaw
+ */
+ BundleRaw ToRaw();
+
+ /**
+ * @brief Gets the count of keys.
+ * @since_tizen 5.5
+ * @return The count
+ */
+ int GetCount() const;
+
+ /**
+ * @brief Gets the data type from the key.
+ * @since_tizen 5.5
+ * @param[in] key The string key
+ * @return The data type
+ */
+ bundle_type GetType(const std::string& key) const;
+
+ /**
+ * @brief Gets the handle for bundle APIs.
+ * @since_tizen 5.5
+ * @return The handle for bundle
+ */
+ bundle* GetHandle() const;
+
+ /**
+ * @brief Moves this object into the bundle handle.
+ * @since_tizen 5.5
+ * @return The handle for bundle
+ */
+ bundle* Detach();
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace tizen_base
+
+/**
+ * @}
+ */
+
+#endif // BUNDLE_CPP_H_
diff --git a/include/bundle_internal.h b/include/bundle_internal.h
index e94db58..8817b13 100755
--- a/include/bundle_internal.h
+++ b/include/bundle_internal.h
@@ -137,6 +137,16 @@ API void bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *cb_data);
API int bundle_keyval_type_is_measurable(bundle_keyval_t *kv);
/**
+ * @brief Duplicate key-value pair.
+ * @since_tizen 5.5
+ * @param[in] kv A bundle_keyval_t object
+ * @return The bundle object
+ * @retval @c NULL - Failure
+ * @pre @a kv must be a valid bundle_keyval_t object.
+ */
+API bundle_keyval_t *bundle_keyval_dup(const bundle_keyval_t *kv);
+
+/**
* @brief Frees the encoded rawdata.
* @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
* @param[in] r The rawdata
diff --git a/packaging/bundle.spec b/packaging/bundle.spec
index b84bab0..9b000e9 100644
--- a/packaging/bundle.spec
+++ b/packaging/bundle.spec
@@ -11,6 +11,13 @@ BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(capi-base-common)
BuildRequires: pkgconfig(json-glib-1.0)
+BuildRequires: pkgconfig(gmock)
+
+%if 0%{?gcov:1}
+BuildRequires: lcov
+BuildRequires: zip
+%endif
+
%description
Simple string key-val dictionary ADT
@@ -22,22 +29,73 @@ Requires: %{name} = %{version}-%{release}
%description devel
Simple string key-val dictionary ADT (devel)
+#################################################
+# unittests
+#################################################
+%package unittests
+Summary: GTest for bundle
+Group: Development/Libraries
+
+%description unittests
+GTest for bundle
+
+#################################################
+# gcov
+#################################################
+%if 0%{?gcov:1}
+%package gcov
+Summary: Simple string key-val dictionary ADT (gcov)
+Group: Application Framework/Testing
+
+%description gcov
+Simple string key-val dictionary ADT gcov objects
+%endif
%prep
%setup -q -n %{name}-%{version}
cp %{SOURCE1001} .
%build
+%if 0%{?gcov:1}
+export CFLAGS+=" -fprofile-arcs -ftest-coverage"
+export CXXFLAGS+=" -fprofile-arcs -ftest-coverage"
+export FFLAGS+=" -fprofile-arcs -ftest-coverage"
+export LDFLAGS+=" -lgcov"
+%endif
+
%cmake -DVERSION=%{version} .
%__make %{?_smp_mflags}
+%if 0%{?gcov:1}
+mkdir -p gcov-obj
+find . -name '*.gcno' -exec cp '{}' gcov-obj ';'
+%endif
+
%install
%make_install
+%if 0%{?gcov:1}
+mkdir -p %{buildroot}%{_datadir}/gcov/obj
+install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
+%endif
+
+%check
+ctest --output-on-failure %{?_smp_mflags}
+%if 0%{?gcov:1}
+lcov -c --ignore-errors graph --no-external -q -d . -o bundle.info
+genhtml bundle.info -o bundle.out
+zip -r bundle.zip bundle.out
+install -m 0644 bundle.zip %{buildroot}%{_datadir}/gcov/
+%endif
+
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
+%post unittests
+%if 0%{?gcov:1}
+%{_bindir}/bundle_unittests
+%endif
%files
%manifest %{name}.manifest
@@ -51,3 +109,17 @@ cp %{SOURCE1001} .
%{_includedir}/*.h
%{_libdir}/pkgconfig/bundle.pc
%{_libdir}/libbundle.so
+
+#################################################
+# unittests
+#################################################
+%files unittests
+%{_bindir}/bundle_unittests
+
+#################################################
+# bundle-gcov
+#################################################
+%if 0%{?gcov:1}
+%files gcov
+%{_datadir}/gcov/*
+%endif
diff --git a/src/bundle.c b/src/bundle.c
index f5e6864..2afa47f 100644
--- a/src/bundle.c
+++ b/src/bundle.c
@@ -374,6 +374,40 @@ int bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val,
array_val, array_len, array_item_size);
}
+bundle_keyval_t *bundle_keyval_dup(const bundle_keyval_t *kv)
+{
+ bundle_keyval_t *ret_kv = NULL;
+ void *byte = NULL;
+ size_t byte_len;
+ size_t len;
+
+ if (!kv)
+ return NULL;
+
+ if (keyval_type_is_array(kv->type)) {
+ len = keyval_array_encode(
+ (keyval_array_t *)kv, &byte, &byte_len);
+ if (len == 0)
+ return NULL;
+ len = keyval_array_decode(byte,
+ (keyval_array_t **)&ret_kv, byte_len);
+ free(byte);
+ if (len == 0)
+ return NULL;
+ } else {
+ len = keyval_encode((keyval_t *)kv,
+ (unsigned char **)&byte, &byte_len);
+ if (len == 0)
+ return NULL;
+ len = keyval_decode(
+ (unsigned char *)byte, (keyval_t **)&ret_kv, byte_len);
+ free(byte);
+ if (len == 0)
+ return NULL;
+ }
+ return ret_kv;
+}
+
bundle *bundle_dup(bundle *b_from)
{
bundle *b_to;
diff --git a/src/bundle_cpp.cc b/src/bundle_cpp.cc
new file mode 100644
index 0000000..5a5001d
--- /dev/null
+++ b/src/bundle_cpp.cc
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <dlog.h>
+
+#include <memory>
+
+#include "bundle_cpp_implementation.h"
+#include "bundle_cpp.h"
+#include "bundle_internal.h"
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "BUNDLE"
+
+namespace tizen_base {
+Bundle::Impl::Impl(Bundle* parent, bool copy, bool own)
+ : copy_(copy), own_(own), parent_(parent) {
+}
+
+Bundle::Impl::Impl(Bundle* parent) : parent_(parent) {
+}
+
+Bundle::Impl::~Impl() = default;
+
+Bundle::Bundle()
+ : impl_(new Impl(this)) {
+ impl_->handle_ = bundle_create();
+}
+
+Bundle::Bundle(BundleRaw raw)
+ : impl_(new Impl(this)) {
+ impl_->handle_ = bundle_decode(raw.first.get(), raw.second);
+}
+
+Bundle::Bundle(const std::string& raw)
+ : impl_(new Impl(this)) {
+ impl_->handle_ = bundle_decode(reinterpret_cast<const bundle_raw*>(
+ raw.c_str()), raw.length());
+}
+
+Bundle::Bundle(bundle* b, bool copy, bool own)
+ : impl_(new Impl(this, copy, own)) {
+ if (!impl_->copy_)
+ impl_->handle_ = b;
+ else
+ impl_->handle_ = bundle_dup(b);
+}
+
+Bundle::~Bundle() {
+ if (impl_->handle_ && (impl_->own_ || impl_->copy_))
+ bundle_free(impl_->handle_);
+}
+
+Bundle::Bundle(const Bundle& b)
+ : impl_(new Impl(this)) {
+ impl_->handle_ = bundle_dup(b.impl_->handle_);
+}
+
+Bundle::KeyInfo::KeyInfo(const bundle_keyval_t* handle, std::string name)
+ : impl_(new Impl(this, handle, std::move(name))) {
+}
+
+Bundle::KeyInfo::KeyInfo()
+ : impl_(new Impl(this)) {
+}
+
+Bundle::KeyInfo::~KeyInfo() {
+}
+
+Bundle::KeyInfo::Impl::~Impl() = default;
+Bundle::KeyInfo::Impl::Impl(Bundle::KeyInfo* parent,
+ const bundle_keyval_t* handle,
+ std::string name)
+ : handle_(handle), name_(name), parent_(parent) {
+}
+
+Bundle::KeyInfo::Impl::Impl(Bundle::KeyInfo* parent) : parent_(parent) {
+}
+
+Bundle::KeyInfo::KeyInfo(const KeyInfo& k)
+ : impl_(new Impl(this)) {
+ impl_->handle_ = bundle_keyval_dup(k.impl_->handle_);
+ impl_->name_ = k.impl_->name_;
+}
+
+Bundle::KeyInfo& Bundle::KeyInfo::operator = (const Bundle::KeyInfo& k) {
+ if (this != &k) {
+ impl_->handle_ = bundle_keyval_dup(k.impl_->handle_);
+ impl_->name_ = k.impl_->name_;
+ }
+ return *this;
+}
+
+Bundle::KeyInfo::KeyInfo(Bundle::KeyInfo&& k) noexcept {
+ impl_ = std::unique_ptr<Impl>(new Impl(this));
+ impl_->handle_ = k.impl_->handle_;
+ impl_->name_ = k.impl_->name_;
+ k.impl_->handle_ = nullptr;
+ k.impl_->name_ = "";
+}
+
+Bundle::KeyInfo& Bundle::KeyInfo::operator = (Bundle::KeyInfo&& k) noexcept {
+ if (this != &k) {
+ impl_->handle_ = k.impl_->handle_;
+ impl_->name_ = k.impl_->name_;
+ k.impl_->handle_ = nullptr;
+ k.impl_->name_ = "";
+ }
+ return *this;
+}
+
+bundle_type Bundle::KeyInfo::GetType() const {
+ return static_cast<bundle_type>(
+ bundle_keyval_get_type(const_cast<bundle_keyval_t*>(impl_->handle_)));
+}
+
+bool Bundle::KeyInfo::IsArray() const {
+ return bundle_keyval_type_is_array(const_cast<bundle_keyval_t*>(
+ impl_->handle_));
+}
+
+const std::string& Bundle::KeyInfo::GetName() const {
+ return impl_->name_;
+}
+
+Bundle& Bundle::operator = (const Bundle& b) {
+ if (this != &b) {
+ impl_->handle_ = bundle_dup(b.impl_->handle_);
+ }
+ return *this;
+}
+
+Bundle::Bundle(Bundle&& b) noexcept {
+ impl_ = std::unique_ptr<Impl>(new Impl(this));
+ impl_->handle_ = b.impl_->handle_;
+ b.impl_->handle_ = nullptr;
+}
+
+Bundle& Bundle::operator = (Bundle&& b) noexcept {
+ if (this != &b) {
+ impl_->handle_ = b.impl_->handle_;
+ b.impl_->handle_ = nullptr;
+ }
+ return *this;
+}
+
+std::vector<Bundle::KeyInfo> Bundle::GetKeys() {
+ std::vector<Bundle::KeyInfo> v;
+
+ bundle_foreach(impl_->handle_, [](const char *key, const int type,
+ const bundle_keyval_t *kv, void *user_data) {
+ auto* v = static_cast<std::vector<KeyInfo>*>(user_data);
+ v->emplace_back(kv, key);
+ }, &v);
+
+ return v;
+}
+
+int Bundle::Add(const std::string& key, const std::string& val) {
+ return bundle_add_str(impl_->handle_, key.c_str(), val.c_str());
+}
+
+int Bundle::Add(const std::string& key, const std::vector<std::string>& val) {
+ std::vector<const char*> v;
+ for (auto& i : val) {
+ v.push_back(i.c_str());
+ }
+
+ return bundle_add_str_array(impl_->handle_, key.c_str(), v.data(), v.size());
+}
+
+int Bundle::Add(const std::string& key, const std::vector<unsigned char>& val) {
+ return bundle_add_byte(impl_->handle_, key.c_str(), val.data(), val.size());
+}
+
+int Bundle::Delete(const std::string& key) {
+ return bundle_del(impl_->handle_, key.c_str());
+}
+
+std::string Bundle::GetString(const std::string& key) const {
+ char* str = nullptr;
+ bundle_get_str(impl_->handle_, key.c_str(), &str);
+
+ if (!str)
+ return "";
+
+ return std::string(str);
+}
+
+std::vector<std::string> Bundle::GetStringArray(const std::string& key) const {
+ std::vector<std::string> v;
+
+ const char** str_array = nullptr;
+ int len = 0;
+
+ str_array = bundle_get_str_array(impl_->handle_, key.c_str(), &len);
+
+ for (int i = 0; i < len; i++) {
+ v.emplace_back(str_array[i]);
+ }
+
+ return v;
+}
+
+std::vector<unsigned char> Bundle::GetByte(const std::string& key) const {
+ size_t size;
+ unsigned char* bytes = nullptr;
+ bundle_get_byte(impl_->handle_, key.c_str(),
+ reinterpret_cast<void**>(&bytes), &size);
+ return std::vector<unsigned char>(bytes, bytes + size);
+}
+
+Bundle::BundleRaw Bundle::ToRaw() {
+ bundle_raw* raw = nullptr;
+ int len = 0;
+ bundle_encode(impl_->handle_, &raw, &len);
+
+ return BundleRaw(
+ std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free), len);
+}
+
+int Bundle::GetCount() const {
+ return bundle_get_count(impl_->handle_);
+}
+
+bundle_type Bundle::GetType(const std::string& key) const {
+ return static_cast<bundle_type>(bundle_get_type(impl_->handle_, key.c_str()));
+}
+
+bundle* Bundle::GetHandle() const {
+ return impl_->handle_;
+}
+
+bundle* Bundle::Detach() {
+ auto* h = impl_->handle_;
+ impl_->handle_ = nullptr;
+ return h;
+}
+
+} // namespace tizen_base
diff --git a/src/bundle_cpp_implementation.h b/src/bundle_cpp_implementation.h
new file mode 100644
index 0000000..5810f09
--- /dev/null
+++ b/src/bundle_cpp_implementation.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef BUNDLE_CPP_IMPLEMENTATION_H_
+#define BUNDLE_CPP_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "bundle_cpp.h"
+
+namespace tizen_base {
+
+class Bundle::KeyInfo::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(Bundle::KeyInfo* parent, const bundle_keyval_t* handle,
+ std::string name);
+ explicit Impl(Bundle::KeyInfo* parent);
+
+ private:
+ friend class Bundle::KeyInfo;
+
+ private:
+ const bundle_keyval_t* handle_;
+ std::string name_;
+ Bundle::KeyInfo* parent_;
+};
+
+class Bundle::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ explicit Impl(Bundle* parent);
+ Impl(Bundle* parent, bool copy, bool own);
+
+ private:
+ friend class Bundle;
+
+ bundle* handle_;
+ bool copy_ = true;
+ bool own_ = true;
+ Bundle* parent_;
+};
+
+} // namespace tizen_base
+
+#endif // BUNDLE_CPP_IMPLEMENTATION_H_
diff --git a/src/keyval.h b/src/keyval.h
index 1116b6b..bd8441b 100755
--- a/src/keyval.h
+++ b/src/keyval.h
@@ -25,6 +25,10 @@
#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
+# endif
+
/* ADT: object */
typedef struct keyval_t keyval_t;
@@ -68,4 +72,8 @@ size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size);
int keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size);
int keyval_get_type_from_encoded_byte(unsigned char *byte);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __KEYVAL_H__ */
diff --git a/src/keyval_array.h b/src/keyval_array.h
index 510a1c8..dd23946 100755
--- a/src/keyval_array.h
+++ b/src/keyval_array.h
@@ -25,6 +25,10 @@
#include "keyval.h"
+#ifdef __cplusplus
+extern "C" {
+# endif
+
typedef struct keyval_array_t {
struct keyval_t kv; /* Inherits keyval_t */
unsigned int len; /* length of array_val */
@@ -47,4 +51,8 @@ int keyval_array_set_element(keyval_array_t *kva,
int idx, void *val, size_t size);
int keyval_array_is_idx_valid(keyval_array_t *kva, int idx);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __KEYVAL_ARRAY_H__ */
diff --git a/src/keyval_type.h b/src/keyval_type.h
index 3d9ff15..786cf1c 100755
--- a/src/keyval_type.h
+++ b/src/keyval_type.h
@@ -28,6 +28,10 @@
#include "bundle.h"
+#ifdef __cplusplus
+extern "C" {
+# endif
+
/* measure_size function type */
typedef size_t (*keyval_type_measure_size_func_t) (void *val);
@@ -40,4 +44,8 @@ keyval_type_measure_size_func_t keyval_type_get_measure_size_func(int type);
size_t keyval_type_measure_size_str(void *val);
void keyval_type_init(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __KEYVAL_TYPE_H__ */
diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt
new file mode 100644
index 0000000..f96ee7e
--- /dev/null
+++ b/unit_tests/CMakeLists.txt
@@ -0,0 +1,37 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(bundle_unittests C CXX)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(bundle_unittests REQUIRED
+ dlog
+ gmock
+ glib-2.0
+ json-glib-1.0
+ capi-base-common
+)
+
+FOREACH(flag ${bundle_unittests_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include)
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src UNITTESTS_SOURCES)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../src BUNDLE_SOURCES)
+
+ADD_EXECUTABLE(${PROJECT_NAME}
+ ${BUNDLE_SOURCES}
+ ${UNITTESTS_SOURCES}
+)
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}")
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${bundle_unittests_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/)
diff --git a/unit_tests/src/test_bundle.cc b/unit_tests/src/test_bundle.cc
new file mode 100644
index 0000000..0ac8827
--- /dev/null
+++ b/unit_tests/src/test_bundle.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <iostream>
+#include <stdexcept>
+
+#include "bundle_cpp.h"
+
+using ::testing::AtLeast;
+using namespace tizen_base;
+using namespace std;
+
+TEST(Bundle, CtorDtor) {
+ Bundle bundle;
+}
+
+TEST(Bundle, CopyCtor) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ Bundle b2(bundle);
+ EXPECT_EQ(b2.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, MoveCtor) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ Bundle b2(std::move(bundle));
+ EXPECT_EQ(b2.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, AddStringGetString) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ EXPECT_EQ(bundle.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, AddByteGetByte) {
+ Bundle bundle;
+ std::vector<unsigned char> v = { 0, 1, 2, 3};
+ bundle.Add("TestKey", v);
+ auto v2 = bundle.GetByte("TestKey");
+
+ EXPECT_EQ(v2.size(), 4);
+ EXPECT_EQ(v2[0], 0);
+ EXPECT_EQ(v2[1], 1);
+ EXPECT_EQ(v2[2], 2);
+ EXPECT_EQ(v2[3], 3);
+}
+
+TEST(Bundle, AddStringArrayGetStringArray) {
+ Bundle bundle;
+ bundle.Add("TestKey", { "TestVal1", "TestVal2", "TestVal3" });
+
+ auto v = bundle.GetStringArray("TestKey");
+
+ EXPECT_EQ(v.size(), 3);
+ EXPECT_EQ(v[0], "TestVal1");
+ EXPECT_EQ(v[1], "TestVal2");
+ EXPECT_EQ(v[2], "TestVal3");
+}
+
+TEST(Bundle, ToRaw) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ auto r = bundle.ToRaw();
+ Bundle b2(std::move(r));
+ EXPECT_EQ(bundle.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, GetCount) {
+ Bundle bundle;
+ bundle.Add("TestKey1", "TestVal1");
+ bundle.Add("TestKey2", "TestVal2");
+
+ EXPECT_EQ(bundle.GetCount(), 2);
+}
+
+TEST(Bundle, Delete) {
+ Bundle bundle;
+ int r = bundle.Add("TestKey1", "TestVal1");
+ EXPECT_EQ(r, 0);
+
+ r = bundle.Delete("TestKey1");
+ EXPECT_EQ(r, 0);
+
+ EXPECT_EQ(bundle.GetString("TestKey1"), "");
+}
+
+TEST(Bundle, GetKeys) {
+ Bundle bundle;
+ bundle.Add("TestKey1", "TestVal1");
+ bundle.Add("TestKey2", "TestVal2");
+ bundle.Add("TestKey3", "TestVal3");
+
+ auto v = bundle.GetKeys();
+
+ EXPECT_EQ(bundle.GetCount(), 3);
+
+ for (auto& i : v) {
+ EXPECT_EQ(i.GetType(), BUNDLE_TYPE_STR);
+ }
+}
+
+TEST(Bundle, GetKeysCopy) {
+ Bundle bundle;
+ bundle.Add("TestKey1", "TestVal1");
+ bundle.Add("TestKey2", "TestVal2");
+ bundle.Add("TestKey3", "TestVal3");
+
+ auto v = bundle.GetKeys();
+
+ EXPECT_EQ(bundle.GetCount(), 3);
+
+ for (auto& i : v) {
+ Bundle::KeyInfo copied = i;
+ EXPECT_EQ(copied.GetType(), BUNDLE_TYPE_STR);
+ EXPECT_EQ(copied.GetName(), i.GetName());
+ }
+}
+
+TEST(Bundle, GetKeysMove) {
+ Bundle bundle;
+ bundle.Add("TestKey1", "TestVal1");
+ bundle.Add("TestKey2", "TestVal2");
+ bundle.Add("TestKey3", "TestVal3");
+
+ auto v = bundle.GetKeys();
+
+ EXPECT_EQ(bundle.GetCount(), 3);
+
+ for (auto& i : v) {
+ string name = i.GetName();
+ Bundle::KeyInfo copied = move(i);
+ EXPECT_EQ(copied.GetType(), BUNDLE_TYPE_STR);
+ EXPECT_EQ(copied.GetName(), name);
+ }
+}
diff --git a/unit_tests/src/test_main.cc b/unit_tests/src/test_main.cc
new file mode 100644
index 0000000..df16333
--- /dev/null
+++ b/unit_tests/src/test_main.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}