From 06ec93df38c0736b947e50a02c98eb93d4bed655 Mon Sep 17 00:00:00 2001 From: hyunho Date: Thu, 28 Mar 2019 19:42:50 +0900 Subject: [PATCH] Add bundle cpp APIs Change-Id: If49381e60053911d3911ac2eac8062a50a967eee Signed-off-by: hyunho Signed-off-by: Junghoon Park --- CMakeLists.txt | 45 ++++-- bundle.pc.in | 1 + include/bundle_cpp.h | 335 ++++++++++++++++++++++++++++++++++++++++ include/bundle_internal.h | 10 ++ packaging/bundle.spec | 72 +++++++++ src/bundle.c | 34 ++++ src/bundle_cpp.cc | 257 ++++++++++++++++++++++++++++++ src/bundle_cpp_implementation.h | 65 ++++++++ src/keyval.h | 8 + src/keyval_array.h | 8 + src/keyval_type.h | 8 + unit_tests/CMakeLists.txt | 37 +++++ unit_tests/src/test_bundle.cc | 156 +++++++++++++++++++ unit_tests/src/test_main.cc | 23 +++ 14 files changed, 1044 insertions(+), 15 deletions(-) create mode 100644 include/bundle_cpp.h create mode 100644 src/bundle_cpp.cc create mode 100644 src/bundle_cpp_implementation.h create mode 100644 unit_tests/CMakeLists.txt create mode 100644 unit_tests/src/test_bundle.cc create mode 100644 unit_tests/src/test_main.cc 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 +#include + +#include +#include +#include +#include +#include + +#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, 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_; + }; + + /** + * @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 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& 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& 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 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 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_; +}; + +} // 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 + +#include + +#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( + 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(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_keyval_get_type(const_cast(impl_->handle_))); +} + +bool Bundle::KeyInfo::IsArray() const { + return bundle_keyval_type_is_array(const_cast( + 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(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::GetKeys() { + std::vector v; + + bundle_foreach(impl_->handle_, [](const char *key, const int type, + const bundle_keyval_t *kv, void *user_data) { + auto* v = static_cast*>(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& val) { + std::vector 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& 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 Bundle::GetStringArray(const std::string& key) const { + std::vector 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 Bundle::GetByte(const std::string& key) const { + size_t size; + unsigned char* bytes = nullptr; + bundle_get_byte(impl_->handle_, key.c_str(), + reinterpret_cast(&bytes), &size); + return std::vector(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(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_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 +#include +#include + +#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 +#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 +#include +#include +#include + +#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 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 +#include + +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- 2.7.4