From: Hwankyu Jhun Date: Mon, 29 Jun 2020 05:10:31 +0000 (+0900) Subject: Refactor Bundle X-Git-Tag: submit/tizen/20200630.041657~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0337ede3538bbdfd843c07b3cb595bdae6be7e8c;p=platform%2Fcore%2Fbase%2Fbundle.git Refactor Bundle Change-Id: I64565f92a4d204198e07cf3ef6c50e2b66717c9b Signed-off-by: Hwankyu Jhun --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 631c50f..0eaa0a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ IF("${VERSION_MAJOR}" STREQUAL "") ENDIF() INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED +PKG_CHECK_MODULES(pkgs REQUIRED glib-2.0 dlog capi-base-common json-glib-1.0 ) @@ -24,12 +24,14 @@ SET(CMAKE_CXX_FLAGS_RELEASE "-O2") INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/) AUX_SOURCE_DIRECTORY(src SOURCES) ADD_LIBRARY (${PROJECT_NAME} SHARED ${SOURCES}) -set_target_properties(bundle PROPERTIES SOVERSION ${VERSION_MAJOR}) -set_target_properties(bundle PROPERTIES VERSION "${VERSION}") + +SET_TARGET_PROPERTIES(bundle PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(bundle PROPERTIES VERSION "${VERSION}") SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIE") SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-pie") @@ -40,9 +42,9 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/bundle.pc.in ${CMAKE_BINARY_DIR}/bundle.pc @ONLY) ### Install -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/) +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() diff --git a/include/SLP_bundle_PG.h b/include/SLP_bundle_PG.h index a6b316f..2420441 100644 --- a/include/SLP_bundle_PG.h +++ b/include/SLP_bundle_PG.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2000 - 2020 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. diff --git a/include/bundle.h b/include/bundle.h index ada3158..bdd6ff2 100644 --- a/include/bundle.h +++ b/include/bundle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2000 - 2020 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. diff --git a/include/bundle_cpp.h b/include/bundle_cpp.h index bcab268..241fa98 100644 --- a/include/bundle_cpp.h +++ b/include/bundle_cpp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 - 2020 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. diff --git a/include/bundle_internal.h b/include/bundle_internal.h index a1b8676..0fb5f68 100644 --- a/include/bundle_internal.h +++ b/include/bundle_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2000 - 2020 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. @@ -417,7 +417,7 @@ int bundle_compare(bundle *b1, bundle *b2); * @return @c 0 on success, * otherwise a negative error value * @retval #BUNDLE_ERROR_NONE Successful - * @retval #BUNDLE_ERROR_INVALID_PARAMETEr Invalid parameter + * @retval #BUNDLE_ERROR_INVALID_PARAMETER Invalid parameter * @retval #BUNDLE_ERROR_KEY_EXISTS Key already exists * @retval #BUNDLE_ERROR_OUT_OF_MEMORY Out of memory * @@ -425,6 +425,17 @@ int bundle_compare(bundle *b1, bundle *b2); */ int bundle_init_byte_array(bundle *b, const char *key, const unsigned int len); +/** + * @brief Frees the given key-value pair. + * @since_tizen 6.0 + * @param[in] kv The key-value pair + * @return @c 0 on success, + * otherwise a negative error value + * @retval #BUNDLE_ERROR_NONE Successful + * @retval #BUNDLE_ERROR_INVALID_PARAMETER Invalid parameter + */ +int bundle_keyval_free(bundle_keyval_t *kv); + #ifdef __cplusplus } #endif diff --git a/packaging/bundle.spec b/packaging/bundle.spec index 94964a6..43797c2 100644 --- a/packaging/bundle.spec +++ b/packaging/bundle.spec @@ -72,7 +72,7 @@ find . -name '*.gcno' -exec cp '{}' gcov-obj ';' %endif %check -ctest --output-on-failure %{?_smp_mflags} +ctest --verbose %{?_smp_mflags} %if 0%{?gcov:1} lcov -c --ignore-errors graph --no-external -q -d . -o bundle.info genhtml bundle.info -o bundle.out diff --git a/src/bundle-internal.cc b/src/bundle-internal.cc new file mode 100644 index 0000000..12fea42 --- /dev/null +++ b/src/bundle-internal.cc @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2020 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.h" + +#include "bundle-internal.h" +#include "exception-internal.h" + +namespace tizen_base { +namespace internal { + +static const int CHECKSUM_LENGTH = 32; + +Bundle::Bundle() = default; + +Bundle::Bundle(unsigned char* raw, int size) { + int ret = Decode(raw, size); + if (ret != BUNDLE_ERROR_NONE) + THROW(ret); +} + +Bundle::Bundle(int argc, char** argv) { + int ret = Import(argc, argv); + if (ret != BUNDLE_ERROR_NONE) + THROW(ret); +} + +Bundle::~Bundle() = default; + +Bundle::Bundle(const Bundle& b) { + map_ = b.map_; +} + +Bundle& Bundle::operator = (const Bundle& b) { + if (this != &b) + map_ = b.map_; + return *this; +} + +Bundle::Bundle(Bundle&& b) noexcept { + map_ = std::move(b.map_); +} + +Bundle& Bundle::operator = (Bundle&& b) noexcept { + if (this != &b) + map_ = std::move(b.map_); + return *this; +} + +bool Bundle::operator == (const Bundle& b) { + if (this == &b) + return true; + + if (map_.size() != b.map_.size()) + return false; + + for (const auto& kv : map_) { + auto& lhs = kv.second; + auto iter = b.map_.find(lhs->GetKey()); + if (iter == b.map_.end()) + return false; + + auto& rhs = iter->second; + if (!(lhs == rhs)) + return false; + } + + return true; +} + +void Bundle::Remove(const std::string& key) { + auto iter = map_.find(key); + if (iter == map_.end()) + THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE); + + map_.erase(iter); +} + +void Bundle::Add(std::shared_ptr key_info) { + auto iter = map_.find(key_info->GetKey()); + if (iter != map_.end()) + THROW(BUNDLE_ERROR_KEY_EXISTS); + + map_[key_info->GetKey()] = key_info; +} + +void Bundle::Set(const std::string& key, int index, + std::vector value) { + auto iter = map_.find(key); + if (iter == map_.end()) + THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE); + + iter->second->SetValue(index, value); +} + +std::shared_ptr& Bundle::Get(const std::string& key) { + auto iter = map_.find(key.c_str()); + if (iter == map_.end()) + THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE); + + return iter->second; +} + +int Bundle::GetSize() { + return map_.size(); +} + +int Bundle::GetType(const std::string& key) { + auto iter = map_.find(key); + if (iter == map_.end()) + THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE); + + return iter->second->GetType(); +} + +unsigned char* Bundle::Encode() { + std::vector bytes; + for (const auto& i : map_) { + auto& key_info = i.second; + auto encoded_bytes = key_info->Encode(); + bytes.insert(bytes.end(), encoded_bytes.begin(), encoded_bytes.end()); + } + + char* checksum = static_cast( + g_compute_checksum_for_string(G_CHECKSUM_MD5, + reinterpret_cast(&bytes[0]), + static_cast(bytes.size()))); + if (checksum == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr ptr(checksum, std::free); + unsigned char* p = reinterpret_cast(checksum); + bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH); + + char* encoded_data = reinterpret_cast( + g_base64_encode( + reinterpret_cast(&bytes[0]), + reinterpret_cast(bytes.size()))); + if (encoded_data == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + return reinterpret_cast(encoded_data); +} + +int Bundle::Decode(unsigned char* raw, int size) { + unsigned char* d_str = new (std::nothrow) unsigned char[(size / 4) * 3 + 3]; + if (d_str == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + std::unique_ptr d_ptr(d_str); + gint state = 0; + guint save = 0; + unsigned int d_len_raw = g_base64_decode_step(reinterpret_cast(raw), + size, d_str, &state, &save); + if (d_len_raw < CHECKSUM_LENGTH) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + char* extract_checksum = new (std::nothrow) char[CHECKSUM_LENGTH + 1]; + if (extract_checksum == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + std::unique_ptr extract_ptr(extract_checksum); + strncpy(extract_checksum, reinterpret_cast(d_str), CHECKSUM_LENGTH); + extract_checksum[CHECKSUM_LENGTH] = '\0'; + + char* compute_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5, + reinterpret_cast(d_str + CHECKSUM_LENGTH), + d_len_raw - CHECKSUM_LENGTH); + if (compute_checksum == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + std::unique_ptr compute_ptr(compute_checksum, + std::free); + if (strcmp(extract_checksum, compute_checksum) != 0) + return BUNDLE_ERROR_INVALID_PARAMETER; + + unsigned char* d_r = d_str + CHECKSUM_LENGTH; + unsigned int d_len = d_len_raw - CHECKSUM_LENGTH; + + unsigned int reader = 0; + std::vector bytes(d_r, d_r + d_len); + + while (reader < bytes.size()) { + std::size_t total_size = -1; + unsigned char* p = reinterpret_cast(&total_size); + std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p); + + std::vector encoded_bytes; + std::copy(&bytes[reader], &bytes[reader] + total_size, + std::back_inserter(encoded_bytes)); + reader += total_size; + + auto key_info = std::shared_ptr( + new (std::nothrow) KeyInfo(encoded_bytes)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + auto iter = map_.find(key_info->GetKey()); + if (iter != map_.end()) + continue; + + map_[key_info->GetKey()] = key_info; + } + + return BUNDLE_ERROR_NONE; +} + +const std::map>& Bundle::GetMap() { + return map_; +} + +std::vector Bundle::Export() { + std::vector argv(2); + for (const auto& kv : map_) { + auto& key_info = kv.second; + argv.push_back(key_info->GetKey()); + + auto encoded_bytes = key_info->Encode(); + auto* p = reinterpret_cast(&encoded_bytes[0]); + auto* base64_bytes = g_base64_encode(p, encoded_bytes.size()); + if (base64_bytes == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr base64_bytes_ptr(base64_bytes, + std::free); + argv.push_back(base64_bytes); + } + + return argv; +} + +int Bundle::Import(int argc, char** argv) { + if (argc < 2) + return BUNDLE_ERROR_NONE; + + if (!argv[1] || std::strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) { + for (int idx = 1; idx + 1 < argc; idx += 2) { + auto* p = reinterpret_cast(argv[idx +1]); + auto len = strlen(argv[idx + 1]) + 1; + std::vector value; + std::copy(p, p + len, std::back_inserter(value)); + auto key_info = std::shared_ptr( + new (std::nothrow) KeyInfo(Type::String, argv[idx], value)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + auto iter = map_.find(key_info->GetKey()); + if (iter != map_.end()) + continue; + + map_[key_info->GetKey()] = key_info; + } + return BUNDLE_ERROR_NONE; + } + + for (int idx = 2; idx + 1 < argc; idx += 2) { + gsize out_len = 0; + auto* bytes = g_base64_decode(argv[idx + 1], &out_len); + if (bytes == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + std::unique_ptr bytes_ptr(bytes, g_free); + + if (out_len < sizeof(std::size_t)) + continue; + + auto* p = reinterpret_cast(bytes); + std::vector decoded_bytes(p, p + (out_len + 1)); + auto key_info = std::shared_ptr( + new (std::nothrow) KeyInfo(decoded_bytes)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + auto iter = map_.find(key_info->GetKey()); + if (iter != map_.end()) + continue; + + map_[key_info->GetKey()] = key_info; + } + + return BUNDLE_ERROR_NONE; +} + +} // namespace internal +} // namespace tizen_base diff --git a/src/bundle-internal.h b/src/bundle-internal.h new file mode 100644 index 0000000..c73e5e2 --- /dev/null +++ b/src/bundle-internal.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef BUNDLE_INTERNAL_H_ +#define BUNDLE_INTERNAL_H_ + +#include +#include +#include +#include + +#include "include/bundle.h" + +#include "key-info-internal.h" + +namespace tizen_base { +namespace internal { + +static const char TAG_IMPORT_EXPORT_CHECK[] = "`zaybxcwdveuftgsh`"; + +class Bundle { + public: + enum Property { + Array = BUNDLE_TYPE_ARRAY, + Primitive = BUNDLE_TYPE_PRIMITIVE, + Measurable = BUNDLE_TYPE_MEASURABLE, + }; + + enum Type { + None = BUNDLE_TYPE_NONE, + Any = BUNDLE_TYPE_ANY, + String = BUNDLE_TYPE_STR, + StringArray = BUNDLE_TYPE_STR_ARRAY, + Byte = BUNDLE_TYPE_BYTE, + ByteArray = BUNDLE_TYPE_BYTE_ARRAY, + }; + + Bundle(); + Bundle(unsigned char* raw, int size); + Bundle(int argc, char** argv); + virtual ~Bundle(); + + Bundle(const Bundle& b); + Bundle& operator = (const Bundle& b); + Bundle(Bundle&& b) noexcept; + Bundle& operator = (Bundle&& b) noexcept; + + bool operator == (const Bundle& b); + + void Remove(const std::string& key); + void Add(std::shared_ptr key_info); + void Set(const std::string& key, int index, std::vector value); + + std::shared_ptr& Get(const std::string& key); + int GetSize(); + int GetType(const std::string& key); + + unsigned char* Encode(); + const std::map>& GetMap(); + std::vector Export(); + + private: + int Decode(unsigned char* raw, int size); + int Import(int argc, char** argv); + + private: + std::map> map_; +}; + +} // namespace internal +} // namespace tizen_base + +#endif // BUNDLE_INTERNAL_H_ diff --git a/src/bundle.c b/src/bundle.c deleted file mode 100644 index 0ffa3fb..0000000 --- a/src/bundle.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -/** - * bundle.c - */ - -#include -#include -#include - -#include "bundle.h" -#include "bundle_internal.h" -#include "bundle_log.h" -#include "bundle_private.h" -#include "keyval.h" -#include "keyval_array.h" -#include "keyval_type.h" - -#define CHECKSUM_LENGTH 32 -#define TAG_IMPORT_EXPORT_CHECK "`zaybxcwdveuftgsh`" - -/* ADT */ -struct _bundle_t { - keyval_t *kv_head; -}; - -/** - * Find a kv from bundle - */ -static keyval_t *_bundle_find_kv(bundle *b, const char *key) -{ - keyval_t *kv; - - if (b == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - - if (key == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - - kv = b->kv_head; - while (kv != NULL) { - if (strcmp(key, kv->key) == 0) { - set_last_result(BUNDLE_ERROR_NONE); - return kv; - } - kv = kv->next; - } - /* Not found */ - set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE); - return NULL; -} - -/** - * Append kv into bundle - */ -static int _bundle_append_kv(bundle *b, keyval_t *new_kv) -{ - keyval_t *kv; - - if (b->kv_head == NULL) { - b->kv_head = new_kv; - } else { - kv = b->kv_head; - while (kv->next) - kv = kv->next; - kv->next = new_kv; - } - - return BUNDLE_ERROR_NONE; -} - -static int _bundle_add_kv(bundle *b, const char *key, const void *val, - const size_t size, const int type, const unsigned int len) -{ - keyval_t *kv; - keyval_t *new_kv; - keyval_array_t *kva; - - /* basic value check */ - if (b == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - if (key == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - if (strlen(key) == 0) - return BUNDLE_ERROR_INVALID_PARAMETER; - - kv = _bundle_find_kv(b, key); - if (kv) /* Key already exists */ - return BUNDLE_ERROR_KEY_EXISTS; - - if (keyval_type_is_array(type)) { - /* array type */ - kva = keyval_array_new(NULL, key, type, - (const void **) val, len); - new_kv = (keyval_t *)kva; - } else { - /* normal type */ - new_kv = keyval_new(NULL, key, type, val, size); - } - - if (!new_kv) - return BUNDLE_ERROR_OUT_OF_MEMORY; - - _bundle_append_kv(b, new_kv); - - return BUNDLE_ERROR_NONE; -} - -static int _bundle_get_val(bundle *b, const char *key, const int type, - void **val, size_t *size, unsigned int *len, - size_t **array_element_size) -{ - keyval_t *kv; - keyval_array_t *kva; - - kv = _bundle_find_kv(b, key); - if (!kv) /* Key doesn't exist */ - return get_last_result(); - - if (BUNDLE_TYPE_ANY != type && type != kv->type) - return BUNDLE_ERROR_INVALID_PARAMETER; - - if (keyval_type_is_array(type)) { - kva = (keyval_array_t *)kv; - keyval_array_get_data(kva, NULL, (void ***)val, - len, array_element_size); - } else { - keyval_get_data(kv, NULL, val, size); - } - - return BUNDLE_ERROR_NONE; -} - -/** - * global initialization - * Run only once. - */ -static void _bundle_global_init(void) -{ - static int _is_done; - - if (_is_done) - return; - - /* Run init functions */ - keyval_type_init(); - - _is_done = 1; - return; -} - -/* APIs */ -API bundle *bundle_create(void) -{ - bundle *b = NULL; - - _bundle_global_init(); - - b = calloc(1, sizeof(bundle)); /* fill mem with NULL */ - if (b == NULL) { - BUNDLE_EXCEPTION_PRINT( - "Unable to allocate memory for bundle\n"); - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - goto exception; - } - - set_last_result(BUNDLE_ERROR_NONE); - return b; - -exception: - return NULL; -} - -API int bundle_free(bundle *b) -{ - keyval_t *kv; - keyval_t *tmp_kv; - - if (b == NULL) { - BUNDLE_EXCEPTION_PRINT("Bundle is already freed\n"); - return BUNDLE_ERROR_INVALID_PARAMETER; - } - - /* Free keyval list */ - kv = b->kv_head; - while (kv) { - tmp_kv = kv; - kv = kv->next; - tmp_kv->method->free(tmp_kv, 1); - } - - /* free bundle */ - free(b); - - return BUNDLE_ERROR_NONE; -} - -API int bundle_add_str(bundle *b, const char *key, const char *str) -{ - if (!str) - return BUNDLE_ERROR_INVALID_PARAMETER; - return _bundle_add_kv(b, key, str, strlen(str) + 1, BUNDLE_TYPE_STR, 1); -} - -API int bundle_get_str(bundle *b, const char *key, char **str) -{ - return _bundle_get_val(b, key, BUNDLE_TYPE_STR, (void **)str, - NULL, NULL, NULL); -} - -API int bundle_add(bundle *b, const char *key, const char *val) -{ - return bundle_add_str(b, key, val); -} - -API int bundle_del(bundle *b, const char *key) -{ - keyval_t *kv; - keyval_t *prev_kv = NULL; - - /* basic value check */ - if (b == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - if (key == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - if (strlen(key) == 0) - return BUNDLE_ERROR_INVALID_PARAMETER; - - kv = b->kv_head; - while (kv) { - if (strcmp(key, kv->key) == 0) - break; - prev_kv = kv; - kv = kv->next; - } - - if (kv == NULL) { - return BUNDLE_ERROR_KEY_NOT_AVAILABLE; - } else { - if (prev_kv) - prev_kv->next = kv->next; - if (kv == b->kv_head) - b->kv_head = kv->next; - kv->method->free(kv, 1); - } - - return BUNDLE_ERROR_NONE; -} - -API const char *bundle_get_val(bundle *b, const char *key) -{ - char *val = NULL; - int ret = BUNDLE_ERROR_NONE; - - ret = bundle_get_str(b, key, &val); - set_last_result(ret); - - return val; -} - -/** - * @brief used by bundle_get_count() API, to count number of items in a bundle - */ -static void _bundle_get_count_iter(const char *k, const int type, - const bundle_keyval_t *kv, void *user_data) -{ - int *count = (int *)user_data; - *count += 1; -} - -API int bundle_get_count(bundle *b) -{ - int count = 0; - - if (b == NULL) - return count; - bundle_foreach(b, _bundle_get_count_iter, &count); - return count; -} - -API void bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *data) -{ - keyval_t *kv; - - if (b == NULL || callback == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return; - } - - kv = b->kv_head; - while (kv) { - callback(kv->key, kv->val, data); - kv = kv->next; - } - - set_last_result(BUNDLE_ERROR_NONE); -} - -API void bundle_foreach(bundle *b, bundle_iterator_t iter, void *user_data) -{ - keyval_t *kv; - - if (b == NULL || iter == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return; /* TC_FIX if b = NULL- error handling */ - } - - kv = b->kv_head; - while (kv) { - iter(kv->key, kv->type, kv, user_data); - kv = kv->next; - } - - set_last_result(BUNDLE_ERROR_NONE); -} - -/* keyval functions */ -API int bundle_keyval_get_type(bundle_keyval_t *kv) -{ - if (kv == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return -1; - } - set_last_result(BUNDLE_ERROR_NONE); - return kv->type; -} - -API int bundle_keyval_type_is_array(bundle_keyval_t *kv) -{ - if (kv == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return -1; - } - set_last_result(BUNDLE_ERROR_NONE); - return keyval_type_is_array(kv->type); -} - -API int bundle_keyval_type_is_measurable(bundle_keyval_t *kv) -{ - if (kv == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return -1; - } - set_last_result(BUNDLE_ERROR_NONE); - return keyval_type_is_measurable(kv->type); -} - -API int bundle_keyval_get_basic_val(bundle_keyval_t *kv, void **val, - size_t *size) -{ - return keyval_get_data(kv, NULL, val, size); -} - -API int bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val, - unsigned int *array_len, size_t **array_item_size) -{ - return keyval_array_get_data((keyval_array_t *)kv, NULL, - array_val, array_len, array_item_size); -} - -API 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; -} - -API bundle *bundle_dup(bundle *b_from) -{ - bundle *b_to; - keyval_t *kv_from; - keyval_t *kv_to; - keyval_array_t *kva_from; - int i; - - if (b_from == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - - b_to = bundle_create(); - if (b_to == NULL) - return NULL; - - kv_from = b_from->kv_head; - while (kv_from != NULL) { - if (keyval_type_is_array(kv_from->type)) { - kva_from = (keyval_array_t *)kv_from; - kv_to = (keyval_t *)keyval_array_new(NULL, kv_from->key, - kv_from->type, NULL, kva_from->len); - if (!kv_to) - goto err; - - for (i = 0; i < kva_from->len; i++) { - if (((keyval_array_t *)kv_from)->array_val[i]) { - keyval_array_set_element( - (keyval_array_t *)kv_to, i, - ((keyval_array_t *)kv_from)->array_val[i], - ((keyval_array_t *)kv_from)->array_element_size[i]); - } - } - - _bundle_append_kv(b_to, kv_to); - } else { - if (_bundle_add_kv(b_to, kv_from->key, - kv_from->val, kv_from->size, kv_from->type, 0)) - goto err; - } - - kv_from = kv_from->next; - } - - return b_to; - -err: - bundle_free(b_to); - return NULL; -} - -API int bundle_encode(bundle *b, bundle_raw **r, int *len) -{ - keyval_t *kv; - unsigned char *m; - unsigned char *p_m; - unsigned char *byte; - size_t byte_len; - gchar *chksum_val; - size_t msize = 0; - - if (b == NULL || r == NULL || len == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - - /* calculate memory size */ - kv = b->kv_head; - while (kv != NULL) { - msize += kv->method->get_encoded_size(kv); - kv = kv->next; - } - - m = calloc(msize + CHECKSUM_LENGTH, sizeof(unsigned char)); - if (unlikely(m == NULL)) - return BUNDLE_ERROR_OUT_OF_MEMORY; - - p_m = m + CHECKSUM_LENGTH; /* temporary pointer */ - - kv = b->kv_head; - while (kv != NULL) { - byte = NULL; - byte_len = 0; - - kv->method->encode(kv, &byte, &byte_len); - memcpy(p_m, byte, byte_len); - - p_m += byte_len; - kv = kv->next; - - free(byte); - } - - /* compute checksum from the data */ - chksum_val = g_compute_checksum_for_string(G_CHECKSUM_MD5, - (const char *)(m + CHECKSUM_LENGTH), msize); - /* prefix checksum to the data */ - memcpy(m, chksum_val, CHECKSUM_LENGTH); - if (r) { - /* base64 encode for whole string checksum and data */ - *r = (unsigned char *)g_base64_encode(m, msize + CHECKSUM_LENGTH); - if (len) - *len = strlen((char *)*r); - } - free(m); - g_free(chksum_val); /* free checksum string */ - - return BUNDLE_ERROR_NONE; -} - -API int bundle_free_encoded_rawdata(bundle_raw **r) -{ - if (!*r) - return BUNDLE_ERROR_INVALID_PARAMETER; /* TC_FIX - double free sigabrt handling */ - - free(*r); - *r = NULL; - return BUNDLE_ERROR_NONE; -} - -API bundle *bundle_decode(const bundle_raw *r, const int data_size) -{ - bundle *b; - bundle_raw *p_r; - unsigned char *d_str; - gint state = 0; - guint save = 0; - unsigned int d_len_raw; - unsigned char *d_r; - unsigned int d_len; - char *extract_cksum; - gchar *compute_cksum; - size_t bytes_read; - keyval_t *kv; - int type; - size_t byte_size; - - if (r == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - - extract_cksum = calloc(CHECKSUM_LENGTH + 1, sizeof(char)); - if (unlikely(extract_cksum == NULL)) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - - /* - * base 64 decode of input string - * Since base64 encodes 3 bytes in 4 chars (+3 may be needed in case of non-zero state) - * refer to: https://developer.gnome.org/glib/stable/glib-Base64-Encoding.html#g-base64-decode-step - */ - d_str = malloc((data_size / 4) * 3 + 3); - if (unlikely(d_str == NULL)) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - free(extract_cksum); - return NULL; - } - - d_len_raw = g_base64_decode_step((char *)r, data_size, d_str, &state, &save); - if (d_len_raw < CHECKSUM_LENGTH) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - free(d_str); - free(extract_cksum); - return NULL; - } - - /* extract checksum from the received string */ - strncpy(extract_cksum, (const char *)d_str, CHECKSUM_LENGTH); - /* compute checksum for the data */ - compute_cksum = g_compute_checksum_for_string(G_CHECKSUM_MD5, - (const char *)(d_str + CHECKSUM_LENGTH), - d_len_raw - CHECKSUM_LENGTH); - /* - * compare checksum values- extracted from the received - * string and computed from the data - */ - if (strcmp(extract_cksum, compute_cksum) != 0) { - free(d_str); - free(extract_cksum); - g_free(compute_cksum); - return NULL; - } - d_r = d_str + CHECKSUM_LENGTH; - d_len = d_len_raw - CHECKSUM_LENGTH; - - /* re-construct bundle */ - b = bundle_create(); - if (b == NULL) { - free(d_str); - free(extract_cksum); - g_free(compute_cksum); - return NULL; - } - - p_r = (bundle_raw *)d_r; - while (p_r < d_r + d_len - 1) { - kv = NULL; /* To get a new kv */ - - byte_size = d_r + d_len - 1 - p_r; - if (byte_size < sizeof(size_t)) - break; - - /* Find type, and use decode function according to type */ - type = keyval_get_type_from_encoded_byte(p_r); - if (keyval_type_is_array(type)) { - bytes_read = keyval_array_decode(p_r, - (keyval_array_t **)&kv, byte_size + 1); - } else { - bytes_read = keyval_decode(p_r, &kv, byte_size + 1); - } - - if (kv) - _bundle_append_kv(b, kv); - else - break; - p_r += bytes_read; - } - - free(extract_cksum); - g_free(compute_cksum); - free(d_str); - - set_last_result(BUNDLE_ERROR_NONE); - return b; -} - -struct _argv_idx { - int argc; - char **argv; - int idx; -}; - -API int bundle_encode_raw(bundle *b, bundle_raw **r, int *len) -{ - keyval_t *kv = NULL; - unsigned char *m = NULL; - unsigned char *p_m = NULL; - unsigned char *byte = NULL; - size_t byte_len; - gchar *chksum_val = NULL; - size_t msize = 0; - - if (b == NULL || r == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - - /* calculate memory size */ - kv = b->kv_head; - while (kv != NULL) { - msize += kv->method->get_encoded_size(kv); - kv = kv->next; - } - - m = calloc(msize+CHECKSUM_LENGTH, sizeof(unsigned char)); - if (unlikely(m == NULL)) - return BUNDLE_ERROR_OUT_OF_MEMORY; - - p_m = m + CHECKSUM_LENGTH; /* temporary pointer */ - - kv = b->kv_head; - while (kv != NULL) { - byte = NULL; - byte_len = 0; - - kv->method->encode(kv, &byte, &byte_len); - memcpy(p_m, byte, byte_len); - - p_m += byte_len; - kv = kv->next; - - free(byte); - } - - /* compute checksum from the data */ - chksum_val = g_compute_checksum_for_string(G_CHECKSUM_MD5, - (const char *)(m + CHECKSUM_LENGTH), msize); - /* prefix checksum to the data */ - memcpy(m, chksum_val, CHECKSUM_LENGTH); - - *r = m; - *len = msize + CHECKSUM_LENGTH; - g_free(chksum_val); /* free checksum string */ - - return BUNDLE_ERROR_NONE; -} - -API bundle *bundle_decode_raw(const bundle_raw *r, const int data_size) -{ - bundle *b = NULL; - bundle_raw *p_r = NULL; - unsigned char *d_str = NULL; - unsigned int d_len_raw; - unsigned char *d_r = NULL; - unsigned int d_len; - char *extract_cksum; - gchar *compute_cksum = NULL; - size_t bytes_read; - keyval_t *kv; - int type; - size_t byte_size; - - if (r == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - - extract_cksum = calloc(CHECKSUM_LENGTH + 1, sizeof(char)); - if (unlikely(extract_cksum == NULL)) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - return NULL; - } - - /* base 64 decode of input string*/ - /* d_str = g_base64_decode((char*)r, &d_len_raw); */ - d_str = (unsigned char *)r; - d_len_raw = data_size; - /* extract checksum from the received string */ - strncpy(extract_cksum, (const char *)d_str, CHECKSUM_LENGTH); - /* compute checksum for the data */ - compute_cksum = g_compute_checksum_for_string(G_CHECKSUM_MD5, - (const char *)(d_str + CHECKSUM_LENGTH), - d_len_raw - CHECKSUM_LENGTH); - /* - * compare checksum values- extracted from the received - * string and computed from the data - */ - if (strcmp(extract_cksum, compute_cksum) != 0) { - free(extract_cksum); - g_free(compute_cksum); - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; - } - d_r = d_str + CHECKSUM_LENGTH; - d_len = d_len_raw - CHECKSUM_LENGTH; - - /* re-construct bundle */ - b = bundle_create(); - if (b == NULL) { - free(extract_cksum); - g_free(compute_cksum); - return NULL; - } - - p_r = (bundle_raw *)d_r; - while (p_r < d_r + d_len - 1) { - kv = NULL; /* To get a new kv */ - - byte_size = d_r + d_len - 1 - p_r; - if (byte_size < sizeof(size_t)) - break; - - /* Find type, and use decode function according to type */ - type = keyval_get_type_from_encoded_byte(p_r); - if (keyval_type_is_array(type)) { - bytes_read = keyval_array_decode(p_r, - (keyval_array_t **)&kv, byte_size + 1); - } else { - bytes_read = keyval_decode(p_r, &kv, byte_size + 1); - } - - if (kv) - _bundle_append_kv(b, kv); - else - break; - p_r += bytes_read; - } - - free(extract_cksum); - g_free(compute_cksum); - set_last_result(BUNDLE_ERROR_NONE); - - return b; -} - -void _iter_export_to_argv(const char *key, const int type, const keyval_t *kv, - void *user_data) -{ - struct _argv_idx *vi = (struct _argv_idx *)user_data; - unsigned char *byte = NULL; - unsigned char *encoded_byte = NULL; - size_t byte_len = 0; - - vi->argv[vi->idx] = strdup(key); - if (kv->method->encode((struct keyval_t *)kv, &byte, &byte_len) == 0) { - /* TODO: encode FAILED! */ - BUNDLE_EXCEPTION_PRINT("bundle: FAILED to encode keyval: %s\n", - key); - return; - } - - encoded_byte = (unsigned char *)g_base64_encode(byte, byte_len); - if (encoded_byte == NULL) { - BUNDLE_EXCEPTION_PRINT("bundle: failed to encode byte\n"); - return; - } - - vi->argv[vi->idx + 1] = (char *)encoded_byte; - (vi->idx) += 2; - - free(byte); -} - -API int bundle_export_to_argv(bundle *b, char ***argv) -{ - struct _argv_idx vi; - int argc; - int item_count; - - if (b == NULL || argv == NULL) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return -1; - } - - item_count = bundle_get_count(b); - argc = 2 * item_count + 2; - /* 2 more count for argv[0] and arv[1] = encoded */ - *argv = calloc(argc + 1, sizeof(char *)); - if (!*argv) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - return -1; - } - - vi.argc = argc; - vi.argv = *argv; - vi.idx = 2; /* start from index 2*/ - vi.argv[1] = TAG_IMPORT_EXPORT_CHECK; /* set argv[1] as encoded*/ - /* BUNDLE_LOG_PRINT("\nargument 1 is %s",vi.argv[1]); */ - - bundle_foreach(b, _iter_export_to_argv, &vi); - - set_last_result(BUNDLE_ERROR_NONE); - return argc; -} - -API int bundle_free_exported_argv(int argc, char ***argv) -{ - int i; - - if (argc < 1) - return BUNDLE_ERROR_INVALID_PARAMETER; - - if (!*argv || argc < 2) - return BUNDLE_ERROR_INVALID_PARAMETER; - - for (i = 2; i < argc; i++) - free((*argv)[i]); - free(*argv); - *argv = NULL; - - return BUNDLE_ERROR_NONE; -} - -API bundle *bundle_import_from_argv(int argc, char **argv) -{ - int idx; - int type; - keyval_t *kv; - keyval_array_t *kva; - unsigned char *byte; - char *encoded_byte; - unsigned int byte_size; - bundle *b; - - if (!argv) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - return NULL; /* TC_FIX error handling for argv =NULL*/ - } - - b = bundle_create(); - if (!b) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - return NULL; - } - - if (argc < 2) { - set_last_result(BUNDLE_ERROR_NONE); - return b; - } - - if (!argv[1] || strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) { - /* start idx from one as argv[1] is user given argument */ - for (idx = 1; idx + 1 < argc; idx = idx + 2) - bundle_add(b, argv[idx], argv[idx + 1]); - - return b; - } - - /* start idx from 2 as argv[1] is encoded */ - for (idx = 2; idx + 1 < argc; idx = idx + 2) { - kv = NULL; - kva = NULL; - - encoded_byte = argv[idx+1]; - - /* base64_decode */ - byte = g_base64_decode(encoded_byte, (gsize *)&byte_size); - if (byte == NULL) { - if (b) - set_last_result(bundle_free(b)); - return NULL; - } - - if (byte_size < sizeof(size_t)) { - free(byte); - byte = NULL; - byte_size = 0; - continue; - } - - type = keyval_get_type_from_encoded_byte(byte); - if (keyval_type_is_array(type)) { - if (keyval_array_decode(byte, &kva, byte_size + 1) == 0) /* TODO: error! */ - BUNDLE_EXCEPTION_PRINT("Unable to Decode array\n"); - kv = (keyval_t *)kva; - } else { - if (keyval_decode(byte, &kv, byte_size + 1) == 0) /* TODO: error! */ - BUNDLE_EXCEPTION_PRINT("Unable to Decode\n"); - } - _bundle_append_kv(b, kv); - - free(byte); - byte = NULL; - byte_size = 0; - } - - set_last_result(BUNDLE_ERROR_NONE); - return b; -} - -API int bundle_get_type(bundle *b, const char *key) -{ - keyval_t *kv = _bundle_find_kv(b, key); - - if (kv) { - return kv->type; - } else { - set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE); - return BUNDLE_TYPE_NONE; - } -} - -/* - * Get length of an array - */ -/* LCOV_EXCL_START */ -unsigned int bundle_get_array_len(bundle *b, const char *key) -{ - return BUNDLE_ERROR_NONE; -} -/* LCOV_EXCL_STOP */ - -/* - * Get size of an item in byte, of given pointer - */ -/* LCOV_EXCL_START */ -size_t bundle_get_array_val_size(bundle *b, const char *key, - const void *val_ptr) -{ - return BUNDLE_ERROR_NONE; -} -/* LCOV_EXCL_STOP */ - -static int bundle_set_array_val(bundle *b, const char *key, const int type, - const unsigned int idx, const void *val, const size_t size) -{ - keyval_t *kv; - keyval_array_t *kva; - - kv = _bundle_find_kv(b, key); - if (kv == NULL) - return get_last_result(); - - if (type != kv->type) - return BUNDLE_ERROR_INVALID_PARAMETER; - - /* TODO: Is this needed? */ - if (!keyval_type_is_array(kv->type)) - return BUNDLE_ERROR_INVALID_PARAMETER; - - kva = (keyval_array_t *)kv; - if (!keyval_array_is_idx_valid(kva, idx)) - return BUNDLE_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS; - - /* NULL value test (TODO: is this needed?) */ - if (!kva->array_val) - return BUNDLE_ERROR_INVALID_PARAMETER; - - return keyval_array_set_element(kva, idx, (void *)val, size); -} - -API int bundle_add_str_array(bundle *b, const char *key, const char **str_array, - const int len) -{ - return _bundle_add_kv(b, key, str_array, 0, BUNDLE_TYPE_STR_ARRAY, len); -} - -/* LCOV_EXCL_START */ -int bundle_get_val_array(bundle *b, const char *key, char ***str_array, - int *len) -{ - return _bundle_get_val(b, key, BUNDLE_TYPE_STR_ARRAY, - (void **)str_array, NULL, (unsigned int *)len, NULL); -} -/* LCOV_EXCL_STOP */ - -API const char **bundle_get_str_array(bundle *b, const char *key, int *len) -{ - int ret = BUNDLE_ERROR_NONE; - const char **arr_val = NULL; - - ret = bundle_get_val_array(b, key, (char ***)&arr_val, len); - set_last_result(ret); - - return arr_val; -} - -/* LCOV_EXCL_START */ -API int bundle_compare(bundle *b1, bundle *b2) -{ - keyval_t *kv1; - keyval_t *kv2; - - if (!b1 || !b2) - return -1; - - if (bundle_get_count(b1) != bundle_get_count(b2)) - return 1; - - for (kv1 = b1->kv_head; kv1 != NULL; kv1 = kv1->next) { - kv2 = _bundle_find_kv(b2, kv1->key); - if (!kv2) - return 1; - if (kv1->method->compare(kv1, kv2)) - return 1; - } - - return 0; -} -/* LCOV_EXCL_STOP */ - -API int bundle_set_str_array_element(bundle *b, const char *key, - const unsigned int idx, const char *val) -{ - if (!val) - return BUNDLE_ERROR_INVALID_PARAMETER; - - return bundle_set_array_val(b, key, BUNDLE_TYPE_STR_ARRAY, - idx, val, strlen(val) + 1); -} - -API int bundle_add_byte(bundle *b, const char *key, const void *bytes, - const size_t size) -{ - return _bundle_add_kv(b, key, bytes, size, BUNDLE_TYPE_BYTE, 1); -} - -API int bundle_get_byte(bundle *b, const char *key, void **bytes, size_t *size) -{ - return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE, (void **)bytes, - size, NULL, NULL); -} - -API int bundle_add_byte_array(bundle *b, const char *key, - const unsigned int len) -{ - return bundle_init_byte_array(b, key, len); -} - -API int bundle_init_byte_array(bundle *b, const char *key, - const unsigned int len) -{ - return _bundle_add_kv(b, key, NULL, 0, BUNDLE_TYPE_BYTE_ARRAY, len); -} - -API int bundle_get_byte_array(bundle *b, const char *key, void ***byte_array, - unsigned int *len, unsigned int **array_element_size) -{ - int ret; - - ret = _bundle_get_val(b, key, BUNDLE_TYPE_BYTE_ARRAY, - (void **)byte_array, NULL, len, - (size_t **)array_element_size); - return ret; -} - -API int bundle_set_byte_array_element(bundle *b, const char *key, - const unsigned int idx, const void *bytes, const size_t size) -{ - return bundle_set_array_val(b, key, BUNDLE_TYPE_BYTE_ARRAY, - idx, bytes, size); -} diff --git a/src/bundle_cpp.cc b/src/bundle_cpp.cc index 6d1163c..f23f4d6 100644 --- a/src/bundle_cpp.cc +++ b/src/bundle_cpp.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 - 2020 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. @@ -14,14 +14,12 @@ * limitations under the License. */ -#include - #include -#include "bundle_cpp_implementation.h" #include "bundle_cpp.h" +#include "bundle_cpp_implementation.h" #include "bundle_internal.h" -#include "bundle_log.h" +#include "log-private.h" namespace tizen_base { Bundle::Impl::Impl(Bundle* parent, bool copy, bool own) diff --git a/src/bundle_cpp_implementation.h b/src/bundle_cpp_implementation.h index 71bce84..907b9de 100644 --- a/src/bundle_cpp_implementation.h +++ b/src/bundle_cpp_implementation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 - 2020 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. @@ -21,7 +21,7 @@ #include #include -#include "bundle_cpp.h" +#include "include/bundle_cpp.h" namespace tizen_base { diff --git a/src/bundle_json.c b/src/bundle_json.c deleted file mode 100644 index 38be1a4..0000000 --- a/src/bundle_json.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2016 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.h" -#include "bundle_internal.h" -#include "bundle_private.h" - -static void __add_json_data_from_bundle(const char *key, - const int type, - const bundle_keyval_t *kv, - void *user_data) -{ - void *basic_val = NULL; - size_t basic_size = 0; - void **array_val = NULL; - unsigned int array_len = 0; - size_t *array_elem_size = 0; - JsonObject *json_obj = (JsonObject *)user_data; - JsonArray *json_arr; - unsigned int i; - int ret; - - if (json_obj == NULL) - return; - - if (bundle_keyval_type_is_array((bundle_keyval_t *)kv)) { - ret = bundle_keyval_get_array_val((bundle_keyval_t *)kv, - &array_val, &array_len, &array_elem_size); - if (ret != BUNDLE_ERROR_NONE) - return; - - json_arr = json_array_new(); - if (json_arr == NULL) - return; - - for (i = 0; i < array_len; i++) - json_array_add_string_element(json_arr, array_val[i]); - - json_object_set_array_member(json_obj, key, json_arr); - } else { - ret = bundle_keyval_get_basic_val((bundle_keyval_t *)kv, - &basic_val, &basic_size); - if (ret != BUNDLE_ERROR_NONE) - return; - - json_object_set_string_member(json_obj, key, basic_val); - } -} - -API int bundle_to_json(bundle *b, char **json) -{ - JsonObject *object; - JsonNode *node; - JsonGenerator *generator = NULL; - gchar *new_json = NULL; - gsize length; - int ret = BUNDLE_ERROR_NONE; - - if (b == NULL || json == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - - object = json_object_new(); - if (object == NULL) - return BUNDLE_ERROR_OUT_OF_MEMORY; - - bundle_foreach(b, __add_json_data_from_bundle, object); - - node = json_node_new(JSON_NODE_OBJECT); - if (node == NULL) { - ret = BUNDLE_ERROR_OUT_OF_MEMORY; - goto exception; - } - - json_node_set_object(node, object); - - generator = json_generator_new(); - if (generator == NULL) { - ret = BUNDLE_ERROR_OUT_OF_MEMORY; - goto exception; - } - - json_generator_set_root(generator, node); - - new_json = json_generator_to_data(generator, &length); - if (new_json == NULL) { - ret = BUNDLE_ERROR_OUT_OF_MEMORY; - goto exception; - } - - *json = (char *)new_json; - -exception: - if (generator) - g_object_unref(generator); - if (node) - json_node_free(node); - if (object) - json_object_unref(object); - - return ret; -} - -static void __add_bundle_data_from_json(JsonObject *object, - const char *key, - JsonNode *node, - gpointer user_data) -{ - bundle *b = (bundle *)user_data; - JsonNodeType node_type; - JsonArray *json_arr; - const gchar *val; - guint len; - guint i; - char **arr_val; - - if (key == NULL || node == NULL) - return; - - node_type = JSON_NODE_TYPE(node); - if (node_type == JSON_NODE_ARRAY) { - json_arr = json_node_get_array(node); - if (json_arr == NULL) - return; - - len = json_array_get_length(json_arr); - - arr_val = (char **)calloc(1, sizeof(char *) * len); - if (arr_val == NULL) - return; - - for (i = 0; i < len; i++) - arr_val[i] = strdup(json_array_get_string_element - (json_arr, i)); - - bundle_add_str_array(b, key, (const char **)arr_val, len); - - for (i = 0; i < len; i++) - free(arr_val[i]); - free(arr_val); - } else if (node_type == JSON_NODE_VALUE) { - val = json_node_get_string(node); - if (val) - bundle_add_str(b, key, (const char *)val); - } -} - -API int bundle_from_json(const char *json, bundle **b) -{ - GError *error = NULL; - JsonParser *parser; - JsonNode *root; - JsonObject *root_obj; - bundle *new_b; - int ret = BUNDLE_ERROR_NONE; - - if (json == NULL || b == NULL) - return BUNDLE_ERROR_INVALID_PARAMETER; - - parser = json_parser_new(); - if (parser == NULL) - return BUNDLE_ERROR_OUT_OF_MEMORY; - - json_parser_load_from_data(parser, json, strlen(json), &error); - if (error) { - ret = BUNDLE_ERROR_INVALID_PARAMETER; - goto exception; - } - - root = json_parser_get_root(parser); - if (root == NULL) { - ret = BUNDLE_ERROR_INVALID_PARAMETER; - goto exception; - } - - root_obj = json_node_get_object(root); - if (root_obj == NULL) { - ret = BUNDLE_ERROR_INVALID_PARAMETER; - goto exception; - } - - new_b = bundle_create(); - if (new_b == NULL) { - ret = BUNDLE_ERROR_OUT_OF_MEMORY; - goto exception; - } - - json_object_foreach_member(root_obj, - __add_bundle_data_from_json, new_b); - - *b = new_b; - -exception: - if (error) - g_error_free(error); - if (parser) - g_object_unref(parser); - - return ret; -} diff --git a/src/bundle_log.h b/src/bundle_log.h deleted file mode 100644 index b3bda77..0000000 --- a/src/bundle_log.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -#ifndef __BUNDLE_LOG_H__ -#define __BUNDLE_LOG_H__ - -#include - -#ifdef LOG_TAG -#undef LOG_TAG -#endif - -#define LOG_TAG "BUNDLE" - -#ifdef _DEBUG_MODE_ -#define BUNDLE_LOG_PRINT(FMT, ARG...) \ - do { \ - printf("%5d", getpid()); \ - printf("%s() : "FMT"\n", __FUNCTION__, ##ARG); \ - } while (0) - -#define BUNDLE_EXCEPTION_PRINT(FMT, ARG...) \ - do { \ - printf("%5d", getpid()); \ - printf("%s() : "FMT"\n", __FUNCTION__, ##ARG); \ - } while (0) - -#define BUNDLE_ASSERT_PRINT(FMT, ARG...) \ - do { \ - printf("%5d", getpid()); \ - printf("%s() : "FMT"\n", __FUNCTION__, ##ARG); \ - } while (0) -#else -#define BUNDLE_LOG_PRINT(FMT, ARG...) SLOGD(FMT, ##ARG); -#define BUNDLE_EXCEPTION_PRINT(FMT, ARG...) SLOGW(FMT, ##ARG); -#define BUNDLE_ASSERT_PRINT(FMT, ARG...) SLOGE(FMT, ##ARG); -#endif /* _DEBUG_MODE_ */ - -#endif /* __BUNDLE_LOG_H__ */ diff --git a/src/bundle_private.h b/src/bundle_private.h deleted file mode 100644 index 486d513..0000000 --- a/src/bundle_private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2020 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. - */ - -#ifndef __BUNDLE_PRIVATE_H__ -#define __BUNDLE_PRIVATE_H__ - -#ifdef API -#undef API -#endif -#define API __attribute__((visibility("default"))) - -#ifdef likely -#undef likely -#endif -#define likely(x) __builtin_expect(x, 1) - -#ifdef unlikely -#undef unlikely -#endif -#define unlikely(x) __builtin_expect(x, 0) - -#endif /* __BUNDLE_PRIVATE_H__ */ diff --git a/src/exception-internal.h b/src/exception-internal.h new file mode 100644 index 0000000..2020fbe --- /dev/null +++ b/src/exception-internal.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 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 EXCEPTION_INTERNAL_H_ +#define EXCEPTION_INTERNAL_H_ + +#include +#include + +#include "log-private.h" + +#define THROW(error_code) throw Exception(error_code) + +namespace tizen_base { +namespace internal { + +class Exception : public std::exception { + public: + explicit Exception(int error_code, std::string file = __FILE__, + int line = __LINE__ ) { + error_code_ = error_code; + message_ = file.substr(file.find_last_of("/") + 1) + ":" + + std::to_string(line) + " code:" + std::to_string(error_code_); + } + + virtual ~Exception() {} + + virtual const char *what(void) const noexcept { + return message_.c_str(); + } + + int GetErrorCode() { + return error_code_; + } + + private: + int error_code_; + std::string message_; +}; + +} // namespace internal +} // namespace tizen_base + +#endif // EXCEPTION_INTERNAL_H_ diff --git a/src/export-api-internal.h b/src/export-api-internal.h new file mode 100644 index 0000000..cd0299d --- /dev/null +++ b/src/export-api-internal.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef EXPORT_API_INTERNAL_H_ +#define EXPORT_API_INTERNAL_H_ + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#endif // EXPORT_API_INTERNAL_H_ diff --git a/src/json-internal.cc b/src/json-internal.cc new file mode 100644 index 0000000..bb63639 --- /dev/null +++ b/src/json-internal.cc @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2020 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 "exception-internal.h" +#include "json-internal.h" + +namespace tizen_base { +namespace internal { + +Json::Json(std::string json) : json_(std::move(json)) { +} + +Json::Json(Bundle* b) : b_(b) { +} + +Json::~Json() = default; + +Bundle* Json::ToBundle() { + if (json_.empty()) + return nullptr; + + JsonParser* parser = json_parser_new(); + if (parser == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr parser_ptr(parser, + g_object_unref); + + GError* error = nullptr; + json_parser_load_from_data(parser, json_.c_str(), json_.length(), &error); + if (error) { + g_error_free(error); + THROW(BUNDLE_ERROR_INVALID_PARAMETER); + } + + JsonNode* root = json_parser_get_root(parser); + if (root == nullptr) + THROW(BUNDLE_ERROR_INVALID_PARAMETER); + + JsonObject* root_obj = json_node_get_object(root); + if (root_obj == nullptr) + THROW(BUNDLE_ERROR_INVALID_PARAMETER); + + Bundle* b = new (std::nothrow) Bundle(); + if (b == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + json_object_foreach_member(root_obj, OnJsonObjectMember, b); + + return b; +} + +std::string Json::ToString() { + if (b_ == nullptr) + THROW(BUNDLE_ERROR_INVALID_PARAMETER); + + JsonObject* object = json_object_new(); + if (object == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr object_ptr(object, + json_object_unref); + + for (const auto& kv : b_->GetMap()) { + auto& key_info = kv.second; + if (key_info->GetType() == Bundle::Type::StringArray) { + JsonArray* json_arr = json_array_new(); + if (json_arr == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + for (const auto& v : key_info->GetValues()) { + json_array_add_string_element(json_arr, + const_cast(reinterpret_cast(v.get()))); + } + + json_object_set_array_member(object, key_info->GetKey().c_str(), + json_arr); + } else { + json_object_set_string_member(object, key_info->GetKey().c_str(), + const_cast( + reinterpret_cast( + key_info->GetValues()[0].get()))); + } + } + + JsonNode* node = json_node_new(JSON_NODE_OBJECT); + if (node == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr node_ptr(node, + json_node_free); + + json_node_set_object(node, object); + + JsonGenerator* generator = json_generator_new(); + if (generator == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr generator_ptr( + generator, g_object_unref); + + json_generator_set_root(generator, node); + gsize length = 0; + gchar* json = json_generator_to_data(generator, &length); + if (json == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + json_ = json; + return json_; +} + +void Json::OnJsonObjectMember(JsonObject* object, const char* key, + JsonNode* node, gpointer user_data) { + auto* b = static_cast(user_data); + std::shared_ptr key_info; + JsonNodeType node_type = JSON_NODE_TYPE(node); + if (node_type == JSON_NODE_ARRAY) { + JsonArray* json_arr = json_node_get_array(node); + if (json_arr == nullptr) + return; + + std::vector> values; + guint len = json_array_get_length(json_arr); + for (guint i = 0; i < len; ++i) { + auto* val = json_array_get_string_element(json_arr, i); + auto* p = reinterpret_cast(const_cast(val)); + std::vector value; + std::copy(p, p + (strlen(val) + 1), std::back_inserter(value)); + values.push_back(value); + } + key_info.reset( + new (std::nothrow) KeyInfo(Bundle::Type::StringArray, key, values)); + } else { + auto* val = json_node_get_string(node); + if (val == nullptr) + return; + auto* p = reinterpret_cast(const_cast(val)); + std::vector value; + std::copy(p, p + (strlen(val) + 1), std::back_inserter(value)); + key_info.reset( + new (std::nothrow) KeyInfo(Bundle::Type::String, key, value)); + } + + if (key_info.get() == nullptr) { + _E("Out of memory"); + return; + } + + try { + b->Add(key_info); + } catch (Exception& e) { + _W("Add() is failed. error(%d)", e.GetErrorCode()); + return; + } +} + +} // namespace internal +} // namespace tizen_base diff --git a/src/json-internal.h b/src/json-internal.h new file mode 100644 index 0000000..61572da --- /dev/null +++ b/src/json-internal.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef JSON_INTERNAL_H_ +#define JSON_INTERNAL_H_ + +#include +#include + +#include +#include + +#include "bundle-internal.h" + +namespace tizen_base { +namespace internal { + +class Json { + public: + explicit Json(std::string json); + explicit Json(Bundle* b); + virtual ~Json(); + + Bundle* ToBundle(); + std::string ToString(); + + private: + static void OnJsonObjectMember(JsonObject* object, const char* key, + JsonNode* node, gpointer user_data); + + private: + Bundle* b_ = nullptr; + std::string json_; +}; + +} // namespace internal +} // namespace tizen_base + +#endif // JSON_INTERNAL_H_ diff --git a/src/key-info-internal.cc b/src/key-info-internal.cc new file mode 100644 index 0000000..155a65a --- /dev/null +++ b/src/key-info-internal.cc @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2020 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 "key-info-internal.h" +#include "log-private.h" + +namespace tizen_base { +namespace internal { + +KeyInfo::KeyInfo(int type, std::string key, + std::vector value) + : type_(type), + key_(std::move(key)) { + SetValue(value); +} + +KeyInfo::KeyInfo(int type, std::string key, + std::vector> values) + : type_(type), + key_(std::move(key)) { + SetValues(values); +} + +KeyInfo::KeyInfo(std::vector encoded_bytes) { + Decode(encoded_bytes); +} + +KeyInfo::~KeyInfo() = default; + +KeyInfo::KeyInfo(const KeyInfo& key_info) { + type_ = key_info.type_; + key_ = key_info.key_; + values_size_ = key_info.values_size_; + for (unsigned int i = 0; i < key_info.values_.size(); ++i) { + auto* new_value = new (std::nothrow) unsigned char[values_size_[i]]; + std::copy(key_info.values_[i].get(), + key_info.values_[i].get() + values_size_[i], new_value); + values_.emplace_back(new_value); + } +} + +KeyInfo& KeyInfo::operator = (const KeyInfo& key_info) { + if (this != &key_info) { + type_ = key_info.type_; + key_ = key_info.key_; + values_size_ = key_info.values_size_; + for (unsigned int i = 0; i < key_info.values_.size(); ++i) { + auto* new_value = new (std::nothrow) unsigned char[values_size_[i]]; + std::copy(key_info.values_[i].get(), + key_info.values_[i].get() + values_size_[i], new_value); + values_.emplace_back(new_value); + } + } + return *this; +} + +KeyInfo::KeyInfo(KeyInfo&& key_info) noexcept { + type_ = key_info.type_; + key_info.type_ = 0; + key_ = std::move(key_info.key_); + values_ = std::move(key_info.values_); + values_size_ = std::move(key_info.values_size_); +} + +KeyInfo& KeyInfo::operator = (KeyInfo&& key_info) noexcept { + if (this != &key_info) { + type_ = key_info.type_; + key_info.type_ = 0; + key_ = std::move(key_info.key_); + values_ = std::move(key_info.values_); + values_size_ = std::move(key_info.values_size_); + } + return *this; +} + +bool KeyInfo::operator == (const KeyInfo& key_info) { + if (this == &key_info) + return true; + + if (type_ != key_info.type_) + return false; + + if (key_ != key_info.key_) + return false; + + if (values_.size() != key_info.values_.size()) + return false; + + for (unsigned int i = 0; i < values_.size(); ++i) { + if (values_size_[i] == key_info.values_size_[i]) + return false; + + int ret = std::memcmp(values_[i].get(), key_info.values_[i].get(), + values_size_[i]); + if (ret == 0) + return false; + } + + return true; +} + +int KeyInfo::GetType() const { + return type_; +} + +bool KeyInfo::IsArray() const { + if (values_.size() == 1) + return true; + + return false; +} + +const std::string& KeyInfo::GetKey() { + return key_; +} + +const std::vector>& KeyInfo::GetValues() { + return values_; +} + +const std::vector& KeyInfo::GetValuesSize() { + return values_size_; +} + +void KeyInfo::SetValue(const std::vector& value) { + auto* new_value = new (std::nothrow) unsigned char[value.size()]; + std::copy(value.begin(), value.end(), new_value); + values_.emplace_back(new_value); + values_size_.push_back(value.size()); +} + +void KeyInfo::SetValues(const std::vector>& values) { + for (unsigned int i = 0; i< values.size(); ++i) { + auto* new_value = new (std::nothrow) unsigned char[values[i].size()]; + std::copy(values[i].begin(), values[i].end(), new_value); + values_.emplace_back(new_value); + values_size_.push_back(values[i].size()); + } +} + +std::vector KeyInfo::Encode() { + std::size_t encoded_size = GetEncodedSize(); + if (encoded_size == 0) + return {}; + + std::vector bytes; + + // total size + unsigned char* p = reinterpret_cast(&encoded_size); + std::copy(p, p + sizeof(encoded_size), std::back_inserter(bytes)); + + // type + p = reinterpret_cast(&type_); + std::copy(p, p + sizeof(type_), std::back_inserter(bytes)); + + // key size + std::size_t key_length = key_.length() + 1; + p = reinterpret_cast(&key_length); + std::copy(p, p + sizeof(key_length), std::back_inserter(bytes)); + + // key + std::copy(key_.begin(), key_.end() + 1, std::back_inserter(bytes)); + + // values size + std::size_t values_size = values_.size(); + p = reinterpret_cast(&values_size); + std::copy(p , p + sizeof(values_size), std::back_inserter(bytes)); + + // values + for (unsigned int i = 0; i < values_.size(); i++) { + std::size_t value_size = values_size_[i]; + p = reinterpret_cast(&value_size); + std::copy(p, p + sizeof(value_size), std::back_inserter(bytes)); + + std::copy(values_[i].get(), values_[i].get() + value_size, + std::back_inserter(bytes)); + } + + return bytes; +} + +std::size_t KeyInfo::GetEncodedSize() { + // total size + std::size_t encoded_size = sizeof(std::size_t); + + // type + encoded_size += sizeof(int); + + // key size + encoded_size += sizeof(std::size_t); + + // key + if ((encoded_size + key_.length() + 1) < encoded_size) + return 0; + + encoded_size += key_.length() + 1; + + // values size + if ((encoded_size + sizeof(std::size_t)) < encoded_size) + return 0; + + encoded_size += sizeof(std::size_t); + + // values + std::size_t values_size = 0; + for (unsigned int i = 0; i < values_.size(); ++i) { + // value size + if ((values_size + sizeof(std::size_t)) < values_size) + return 0; + + values_size += sizeof(std::size_t); + + // value + if ((values_size + values_size_[i]) < values_size) + return 0; + + values_size += values_size_[i]; + } + + if ((encoded_size + values_size) < encoded_size) + return 0; + + encoded_size += values_size; + + return encoded_size; +} + +void KeyInfo::Decode(const std::vector& bytes) { + unsigned int reader = 0; + + // total size + std::size_t total_size = 0; + if ((reader + sizeof(total_size)) > bytes.size()) + return; + + unsigned char* p = reinterpret_cast(&total_size); + std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p); + reader += sizeof(total_size); + + // type + if ((reader + sizeof(type_)) > bytes.size()) + return; + + p = reinterpret_cast(&type_); + std::copy(&bytes[reader], &bytes[reader] + sizeof(type_), p); + reader += sizeof(type_); + + // key size + std::size_t key_size = 0; + + if ((reader + sizeof(key_size)) > bytes.size()) + return; + + p = reinterpret_cast(&key_size); + std::copy(&bytes[reader], &bytes[reader] + sizeof(key_size), p); + reader += sizeof(key_size); + + if ((reader + key_size) > bytes.size()) + return; + + // key + std::vector key(&bytes[reader], &bytes[reader] + key_size); + p = reinterpret_cast(&key[0]); + key_ = std::string(reinterpret_cast(p)); + reader += key_size; + + // values size + std::size_t values_size = 0; + if ((reader + sizeof(values_size)) > bytes.size()) + return; + + p = reinterpret_cast(&values_size); + std::copy(&bytes[reader], &bytes[reader] + sizeof(values_size), p); + reader += sizeof(values_size); + + // values + for (std::size_t i = 0; i < values_size; ++i) { + // value_size + std::size_t value_size = 0; + if ((reader + sizeof(value_size)) > bytes.size()) + return; + + p = reinterpret_cast(&value_size); + std::copy(&bytes[reader], &bytes[reader] + sizeof(value_size), p); + reader += sizeof(value_size); + + // value + if ((reader + value_size) > bytes.size()) + return; + + auto* new_value = new unsigned char[value_size]; + std::copy(&bytes[reader], &bytes[reader] + value_size, new_value); + reader += value_size; + + values_.emplace_back(new_value); + values_size_.push_back(value_size); + } +} + +void KeyInfo::SetValue(int index, const std::vector& value) { + if (index > GetSize() && index < 0) + return; + + auto* new_value = new unsigned char[value.size()]; + std::copy(value.begin(), value.end(), new_value); + values_[index].reset(new_value); + values_size_[index] = value.size(); +} + +int KeyInfo::GetSize() const { + return values_.size(); +} + +} // namespace internal +} // namespace tizen_base diff --git a/src/key-info-internal.h b/src/key-info-internal.h new file mode 100644 index 0000000..217371d --- /dev/null +++ b/src/key-info-internal.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef KEY_INFO_INTERNAL_H_ +#define KEY_INFO_INTERNAL_H_ + +#include +#include +#include + +namespace tizen_base { +namespace internal { + +class KeyInfo { + public: + KeyInfo(int type, std::string key, + std::vector value); + KeyInfo(int type, std::string key, + std::vector> values); + explicit KeyInfo(std::vector encoded_bytes); + virtual ~KeyInfo(); + + KeyInfo(const KeyInfo& key_info); + KeyInfo& operator = (const KeyInfo& key_info); + KeyInfo(KeyInfo&& key_info) noexcept; + KeyInfo& operator = (KeyInfo&& key_info) noexcept; + + bool operator == (const KeyInfo& key_info); + + int GetType() const; + bool IsArray() const; + const std::string& GetKey(); + const std::vector>& GetValues(); + const std::vector& GetValuesSize(); + std::vector Encode(); + + void SetValue(int index, const std::vector& value); + int GetSize() const; + + private: + std::size_t GetEncodedSize(); + void SetValuesSize(); + void SetValue(const std::vector& value); + void SetValues(const std::vector>& values); + void Decode(const std::vector& bytes); + + private: + int type_; + std::string key_; + std::vector> values_; + std::vector values_size_; +}; + +} // namespace internal +} // namespace tizen_base + +#endif // KEY_INFO_INTERNAL_H_ diff --git a/src/keyval.c b/src/keyval.c deleted file mode 100644 index 6be41a2..0000000 --- a/src/keyval.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -/** - * keyval.c - * Implementation of keyval object - */ - -#define _GNU_SOURCE -#include - -#include "keyval_type.h" -#include "keyval.h" -#include "bundle_log.h" -#include "bundle.h" - -static keyval_method_collection_t method = { - keyval_free, - keyval_compare, - keyval_get_encoded_size, - keyval_encode, - keyval_decode -}; - -keyval_t *keyval_new(keyval_t *kv, const char *key, - const int type, const void *val, const size_t size) -{ - int must_free_obj = kv ? 0 : 1; - char *str; - - if (!kv) { - kv = calloc(1, sizeof(keyval_t)); - if (!kv) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - return NULL; - } - } - - if (kv->key) { - keyval_free(kv, must_free_obj); - return NULL; - } - - kv->key = strdup(key); - if (!kv->key) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - keyval_free(kv, must_free_obj); - return NULL; - } - - kv->type = type; - kv->size = size; - - if (size) { - kv->val = calloc(1, size); - if (!kv->val) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - keyval_free(kv, must_free_obj); - return NULL; - } - if (val) { - memcpy(kv->val, val, size); - if (type == BUNDLE_TYPE_STR) { - str = (char *)kv->val; - if (str[size - 1] != '\0') - str[size - 1] = '\0'; - } - } - } - - kv->method = &method; - - return kv; -} - -void keyval_free(keyval_t *kv, int do_free_object) -{ - if (kv == NULL) - return; - - if (kv->key) { - free(kv->key); - kv->key = NULL; - } - - if (kv->val != NULL) { - free(kv->val); - kv->val = NULL; - } - - if (do_free_object) - free(kv); - - return; -} - -int keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size) -{ - if (!kv) - return BUNDLE_ERROR_INVALID_PARAMETER; - - if (keyval_type_is_array(kv->type)) - return BUNDLE_ERROR_INVALID_PARAMETER; - - if (type) - *type = kv->type; - if (val) - *val = kv->val; - if (size) - *size = kv->size; - - return 0; -} - -/* LCOV_EXCL_START */ -int keyval_compare(keyval_t *kv1, keyval_t *kv2) -{ - if (!kv1 || !kv2) - return -1; - - if (strcmp(kv1->key, kv2->key) != 0) - return 1; - if (kv1->type != kv2->type) - return 1; - if (kv1->size != kv2->size) - return 1; - - if (kv1->val == NULL && kv2->val == NULL) - return 0; - if (kv1->val == NULL || kv2->val == NULL) - return 1; - if (memcmp(kv1->val, kv2->val, kv1->size) != 0) - return 1; - - return 0; -} -/* LCOV_EXCL_STOP */ - -size_t keyval_get_encoded_size(keyval_t *kv) -{ - size_t encoded_size = 0; - - if (!kv) - return 0; - - encoded_size += sizeof(size_t); /* total size */ - encoded_size += sizeof(int); /* type */ - encoded_size += sizeof(size_t); /* key size */ - - if ((encoded_size + strlen(kv->key) + 1) < encoded_size) - return 0; - - encoded_size += strlen(kv->key) + 1; /* key */ - - if ((encoded_size + sizeof(size_t)) < encoded_size) - return 0; - - encoded_size += sizeof(size_t); /* size */ - - if ((encoded_size + kv->size) < encoded_size) - return 0; - - encoded_size += kv->size; /* val */ - - return encoded_size; -} - -/** - * encode a keyval to byte - * - * @pre kv must be valid. - * @post byte must be freed. - * @param[in] kv - * @param[out] byte - * @param[out] byte_len - * @return byte_len - */ -size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len) -{ - static const size_t sz_type = sizeof(int); - static const size_t sz_keysize = sizeof(size_t); - size_t sz_key = strlen(kv->key) + 1; - static const size_t sz_size = sizeof(size_t); - size_t sz_val = kv->size; - unsigned char *p; - - *byte_len = keyval_get_encoded_size(kv); - if (*byte_len == 0) - return 0; - - *byte = calloc(1, *byte_len); - if (!*byte) - return 0; - - p = *byte; - - memcpy(p, byte_len, sizeof(size_t)); - p += sizeof(size_t); - memcpy(p, &(kv->type), sz_type); - p += sz_type; - memcpy(p, &sz_key, sz_keysize); - p += sz_keysize; - memcpy(p, kv->key, sz_key); - p += sz_key; - memcpy(p, &(kv->size), sz_size); - p += sz_size; - memcpy(p, kv->val, sz_val); - p += sz_val; - - return *byte_len; -} - -/** - * decode a byte stream to a keyval - * - * @param[in] byte byte stream. - * @param[in|out] kv keyval. - * If kv is NULL, new keyval_t object comes. - * If kv is not NULL, given kv is used. (No new kv is created.) - * @return Number of bytes read from byte. - */ -size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size) -{ - static const size_t sz_byte_len = sizeof(size_t); - static const size_t sz_type = sizeof(int); - static const size_t sz_keysize = sizeof(size_t); - static const size_t sz_size = sizeof(size_t); - size_t byte_len; - int type; - size_t keysize; - char *key; - size_t size; - void *val; - unsigned char *p = byte; - size_t encoded_size; - - if (byte_size < sz_byte_len) - return 0; - - memcpy(&byte_len, p, sz_byte_len); - if (byte_size < byte_len) - return 0; - - byte_size -= sz_byte_len; - p += sz_byte_len; - - if (byte_size < sz_type) - return 0; - - memcpy(&type, p, sz_type); - - byte_size -= sz_type; - p += sz_type; - - if (byte_size < sz_keysize) - return 0; - - memcpy(&keysize, p, sz_keysize); - - byte_size -= sz_keysize; - p += sz_keysize; - - if (byte_size < keysize) - return 0; - - key = (char *)p; - if (!key || (strnlen(key, keysize) + 1) != keysize) - return 0; - - byte_size -= keysize; - p += keysize; - - if (byte_size < sz_size) - return 0; - - memcpy(&size, p, sz_size); - - encoded_size = sz_byte_len + sz_type + sz_keysize + keysize + - sz_size + size; - if (encoded_size != byte_len) - return 0; - - p += sz_size; - val = (void *)p; - - if (kv) - *kv = keyval_new(*kv, key, type, val, size); - - return byte_len; -} - -int keyval_get_type_from_encoded_byte(unsigned char *byte) -{ - static const size_t sz_byte_len = sizeof(size_t); - unsigned char *p = byte; - int type; - - p += sz_byte_len; - memcpy(&type, p, sizeof(int)); - - return type; -} diff --git a/src/keyval.h b/src/keyval.h deleted file mode 100644 index bd8441b..0000000 --- a/src/keyval.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -#ifndef __KEYVAL_H__ -#define __KEYVAL_H__ - -/** - * keyval.h - * - * keyval object - */ - -#include - -#ifdef __cplusplus -extern "C" { -# endif - -/* ADT: object */ -typedef struct keyval_t keyval_t; - -/* Object methods */ -typedef struct keyval_method_collection_t keyval_method_collection_t; - -typedef void (*keyval_method_free_t)(keyval_t *kv, int do_free_object); -typedef int (*keyval_method_compare_t) (keyval_t *kv1, keyval_t *kv2); -typedef size_t (*keyval_method_get_encoded_size_t)(keyval_t *kv); -typedef size_t (*keyval_method_encode_t)( - keyval_t *, - unsigned char **byte, - size_t *byte_len); -typedef size_t (*keyval_method_decode_t)(unsigned char *byte, keyval_t **kv, - size_t byte_size); - -struct keyval_method_collection_t { - keyval_method_free_t free; - keyval_method_compare_t compare; - keyval_method_get_encoded_size_t get_encoded_size; - keyval_method_encode_t encode; - keyval_method_decode_t decode; -}; - -struct keyval_t { - int type; - char *key; /* To be freed. */ - void *val; /* To be freed. */ - size_t size; /* Size of a single value. */ - struct keyval_t *next; - keyval_method_collection_t *method; -}; - -keyval_t * keyval_new(keyval_t *kv, const char *key, - const int type, const void *val, const size_t size); -void keyval_free(keyval_t *kv, int do_free_object); -int keyval_compare(keyval_t *kv1, keyval_t *kv2); -size_t keyval_get_encoded_size(keyval_t *kv); -size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len); -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.c b/src/keyval_array.c deleted file mode 100644 index 843cd7b..0000000 --- a/src/keyval_array.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -/** - * keyval_array.c - * Implementation of keyval_array object - */ - -#define _GNU_SOURCE -#include -#include - -#include "bundle.h" -#include "bundle_log.h" -#include "bundle_private.h" -#include "keyval.h" -#include "keyval_array.h" -#include "keyval_type.h" - -static keyval_method_collection_t method = { - (keyval_method_free_t) keyval_array_free, - (keyval_method_compare_t) keyval_array_compare, - (keyval_method_get_encoded_size_t) keyval_array_get_encoded_size, - (keyval_method_encode_t) keyval_array_encode, - (keyval_method_decode_t) keyval_array_decode -}; - -keyval_array_t *keyval_array_new(keyval_array_t *kva, const char *key, - const int type, const void **array_val, const unsigned int len) -{ - int must_free_obj = kva ? 0 : 1; - keyval_t *kv; - - if (!kva) { - kva = calloc(1, sizeof(keyval_array_t)); - if (unlikely(kva == NULL)) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - return NULL; - } - } - - /* keyval setting */ - kv = keyval_new((keyval_t *)kva, key, type, NULL, 0); - if (unlikely(kv == NULL)) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - return NULL; - } - - kv->type = kv->type | BUNDLE_TYPE_ARRAY; - kva->len = len; - - /* Set array value, if exist */ - if (kva->array_val) { - set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); - if (must_free_obj) - keyval_array_free(kva, 1); - return NULL; - } - kva->array_val = calloc(len, sizeof(void *)); - if (!(kva->array_val)) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - keyval_array_free(kva, 1); - return NULL; - } - /* array_element_size */ - kva->array_element_size = calloc(len, sizeof(size_t)); - if (!(kva->array_element_size)) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - keyval_array_free(kva, 1); - return NULL; - } - /* If available, copy array val */ - if (array_val - && keyval_type_is_measurable(type) - && keyval_type_get_measure_size_func(type)) { - /* array_val have original data array. copy it! */ - - if (keyval_array_copy_array((keyval_array_t *)kv, - (void **)array_val, - len, - keyval_type_get_measure_size_func(type)) - ) { - keyval_array_free(kva, 1); - return NULL; - } - } - - /* Set methods */ - kv->method = &method; - - return kva; -} - -void keyval_array_free(keyval_array_t *kva, int do_free_object) -{ - int i; - - if (!kva) - return; - - /* free keyval_array elements */ - free(kva->array_element_size); - for (i = 0; i < kva->len; i++) { - if (kva->array_val[i]) - free(kva->array_val[i]); - } - free(kva->array_val); - - /* free parent */ - keyval_free((keyval_t *)kva, 0); - - /* free object */ - if (do_free_object) - free(kva); -} - -/* LCOV_EXCL_START */ -int keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2) -{ - keyval_t *kv1; - keyval_t *kv2; - int i; - - if (!kva1 || !kva2) - return -1; - - kv1 = (keyval_t *)kva1; - kv2 = (keyval_t *)kva2; - - if (strcmp(kv1->key, kv2->key) != 0) - return 1; - if (kv1->type != kv2->type) - return 1; - if (kva1->len != kva2->len) - return 1; - - for (i = 0; i < kva1->len; i++) { - if (kva1->array_val[i] == NULL && kva2->array_val[i] == NULL) - continue; - if (kva1->array_val[i] == NULL || kva2->array_val[i] == NULL) - return 1; - if (memcmp(kva1->array_val[i], kva2->array_val[i], - kva1->array_element_size[i]) != 0) - return 1; - } - - return 0; -} -/* LCOV_EXCL_STOP */ - -int keyval_array_copy_array(keyval_array_t *kva, void **array_val, - unsigned int array_len, size_t (*measure_val_len)(void *val)) -{ - keyval_t *kv = (keyval_t *)kva; - keyval_type_measure_size_func_t measure_size; - int i; - - /* Get measure_size function of the value type */ - measure_size = keyval_type_get_measure_size_func(kv->type); - if (!measure_size) - return -1; - - /* Copy each array item */ - for (i = 0; i < array_len; i++) { - kva->array_val[i] = calloc(1, measure_size(array_val[i])); - if (!(kva->array_val[i])) { - set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); - goto cleanup_exit; - } - memcpy(kva->array_val[i], array_val[i], - measure_size(array_val[i])); - kva->array_element_size[i] = measure_size(array_val[i]); - } - return 0; - -cleanup_exit: - for (i = 0; i < array_len; i++) { - if (kva->array_val[i]) { - free(kva->array_val[i]); - kva->array_val[i] = NULL; - } - } - return -1; -} - -int keyval_array_is_idx_valid(keyval_array_t *kva, int idx) -{ - if (kva && kva->len > idx && 0 <= idx) - return 1; - return 0; -} - -int keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size) -{ - keyval_t *kv = (keyval_t *)kva; - char *str; - - if (size <= 0) - return BUNDLE_ERROR_INVALID_PARAMETER; - - /* An element is already exist in the idx! */ - if (kva->array_val[idx]) { - /* val==NULL means 'Free this element!' */ - if (!val) { - free(kva->array_val[idx]); - kva->array_val[idx] = NULL; - kva->array_element_size[idx] = 0; - } else { - /* Error case! */ - return BUNDLE_ERROR_INVALID_PARAMETER; - } - } else { - /* Normal case. Copy value into the array. */ - kva->array_val[idx] = calloc(1, size); - if (!(kva->array_val[idx])) - return BUNDLE_ERROR_OUT_OF_MEMORY; - if (val) { - memcpy(kva->array_val[idx], val, size); - if (kv->type & BUNDLE_TYPE_STR) { - str = (char *)kva->array_val[idx]; - if (str[size - 1] != '\0') - str[size - 1] = '\0'; - } - - kva->array_element_size[idx] = size; - } - } - - return BUNDLE_ERROR_NONE; -} - -int keyval_array_get_data(keyval_array_t *kva, int *type, void ***array_val, - unsigned int *len, size_t **array_element_size) -{ - keyval_t *kv; - - if (!kva) - return BUNDLE_ERROR_INVALID_PARAMETER; - - kv = (keyval_t *)kva; - if (!keyval_type_is_array(kv->type)) - return BUNDLE_ERROR_INVALID_PARAMETER; - - /* Return values */ - if (type) - *type = kv->type; - if (array_val) - *array_val = kva->array_val; - if (len) - *len = kva->len; - if (array_element_size) - *array_element_size = kva->array_element_size; - - return BUNDLE_ERROR_NONE; -} - -size_t keyval_array_get_encoded_size(keyval_array_t *kva) -{ - size_t sum_array_element_size = 0; - int i; - size_t encoded_size = 0; - - encoded_size += sizeof(size_t); /* total size */ - encoded_size += sizeof(int); /* type */ - encoded_size += sizeof(size_t); /* key size */ - - if ((encoded_size + strlen(((keyval_t *)kva)->key) + 1) < encoded_size) - return 0; - - encoded_size += strlen(((keyval_t *)kva)->key) + 1; /* key */ - - if ((encoded_size + sizeof(int)) < encoded_size) - return 0; - - encoded_size += sizeof(int); /* len */ - - if ((encoded_size + (kva->len * sizeof(size_t))) < encoded_size) - return 0; - - encoded_size += kva->len * sizeof(size_t); /* array_element_size */ - - for (i = 0; i < kva->len; i++) { - if ((sum_array_element_size + kva->array_element_size[i]) < sum_array_element_size) - return 0; - - sum_array_element_size += kva->array_element_size[i]; - } - - if ((encoded_size + sum_array_element_size) < encoded_size) - return 0; - - encoded_size += sum_array_element_size; - - return encoded_size; -} - -size_t keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len) -{ - keyval_t *kv = (keyval_t *)kva; - int i; - /* Calculate memory size for kva */ - static const size_t sz_type = sizeof(int); - static const size_t sz_keysize = sizeof(size_t); - size_t sz_key = strlen(kv->key) + 1; - static const unsigned int sz_len = sizeof(int); - size_t sz_array_element_size = kva->len * sizeof(size_t); - unsigned char *p; - - /* Allocate memory */ - *byte_len = keyval_array_get_encoded_size(kva); - if (*byte_len == 0) - return 0; - - *byte = calloc(1, *byte_len); - if (!*byte) - return 0; - - /* Copy data */ - p = *byte; - - memcpy(p, byte_len, sizeof(size_t)); - p += sizeof(size_t); - memcpy(p, &(kv->type), sz_type); - p += sz_type; - memcpy(p, &sz_key, sz_keysize); - p += sz_keysize; - memcpy(p, kv->key, sz_key); - p += sz_key; - memcpy(p, &(kva->len), sz_len); - p += sz_len; - memcpy(p, kva->array_element_size, sz_array_element_size); - p += sz_array_element_size; - - for (i = 0; i < kva->len; i++) { - memcpy(p, kva->array_val[i], kva->array_element_size[i]); - p += kva->array_element_size[i]; - } - - return *byte_len; -} - -size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size) -{ - static const size_t sz_byte_len = sizeof(size_t); - static const size_t sz_type = sizeof(int); - static const size_t sz_keysize = sizeof(size_t); - static const int sz_len = sizeof(unsigned int); - unsigned char *p = byte; - size_t byte_len; - int type; - size_t keysize; - char *key; - unsigned int len; - size_t *array_element_size; - void *array_val; - int i; - size_t elem_size = 0; - size_t sum_array_element_size = 0; - size_t encoded_size; - - if (byte_size < sz_byte_len) - return 0; - - memcpy(&byte_len, p, sz_byte_len); - if (byte_size < byte_len) - return 0; - - byte_size -= sz_byte_len; - p += sz_byte_len; - - if (byte_size < sz_type) - return 0; - - memcpy(&type, p, sz_type); - byte_size -= sz_type; - p += sz_type; - - if (byte_size < sz_keysize) - return 0; - - memcpy(&keysize, p, sz_keysize); - byte_size -= sz_keysize; - p += sz_keysize; - - if (byte_size < keysize) - return 0; - - key = (char *)p; - if (!key || (strnlen(key, keysize) + 1) != keysize) - return 0; - - byte_size -= keysize; - p += keysize; - - if (byte_size < sz_len) - return 0; - - memcpy(&len, p, sz_len); - byte_size -= sz_len; - p += sz_len; - - if ((sizeof(size_t) * len) < len) - return 0; - - if (byte_size < (sizeof(size_t) * len)) - return 0; - - array_element_size = (size_t *)p; - for (i = 0; i < len; ++i) { - if ((sum_array_element_size + array_element_size[i]) < sum_array_element_size) - return 0; - - sum_array_element_size += array_element_size[i]; - } - - encoded_size = sz_byte_len + sz_type + sz_keysize + keysize + - sz_len + (sizeof(size_t) * len) + sum_array_element_size; - if (encoded_size != byte_len) - return 0; - - p += sizeof(size_t) * len; - array_val = (void *)p; - - *kva = keyval_array_new(NULL, key, type, NULL, len); - for (i = 0; i < len; i++) { - elem_size += i ? array_element_size[i - 1] : 0; - if (keyval_array_set_element(*kva, i, - (void *)(array_val + elem_size), - array_element_size[i])) { - keyval_array_free(*kva, 1); - *kva = NULL; - return 0; - } - } - - return byte_len; -} diff --git a/src/keyval_array.h b/src/keyval_array.h deleted file mode 100644 index dd23946..0000000 --- a/src/keyval_array.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -#ifndef __KEYVAL_ARRAY_H__ -#define __kEYVAL_ARRAY_H__ - -/** - * keyval_array.h - * - * keyval_array object - */ - -#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 */ - size_t *array_element_size; /* Array of size of each element */ - void **array_val; /* Array */ -} keyval_array_t; - -keyval_array_t *keyval_array_new(keyval_array_t *kva, const char *key, - const int type, const void **array_val, const unsigned int len); -void keyval_array_free(keyval_array_t *kva, int do_free_object); -int keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2); -size_t keyval_array_get_encoded_size(keyval_array_t *kva); -size_t keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len); -size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size); -int keyval_array_copy_array(keyval_array_t *kva, void **array_val, - unsigned int array_len, size_t (*measure_val_len)(void * val)); -int keyval_array_get_data(keyval_array_t *kva, int *type, void ***array_val, - unsigned int *len, size_t **array_element_size); -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.c b/src/keyval_type.c deleted file mode 100644 index 8365c7c..0000000 --- a/src/keyval_type.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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 "keyval_type.h" -#include "bundle_log.h" - -void keyval_type_init(void) -{ - static int is_done; - - if (is_done) - return; - - is_done = 1; -} - -int keyval_type_is_array(int type) -{ - if (type & BUNDLE_TYPE_ARRAY) - return 1; - return 0; -} - -int keyval_type_is_measurable(int type) -{ - if (type & BUNDLE_TYPE_MEASURABLE) - return 1; - return 0; -} - -keyval_type_measure_size_func_t keyval_type_get_measure_size_func(int type) -{ - switch (type) { - case BUNDLE_TYPE_STR: - case BUNDLE_TYPE_STR_ARRAY: - return keyval_type_measure_size_str; - default: - return NULL; - } - return NULL; -} - -size_t keyval_type_measure_size_str(void *val) -{ - if (!val) - return 0; - return strlen((char *)val) + 1; -} diff --git a/src/keyval_type.h b/src/keyval_type.h deleted file mode 100644 index 786cf1c..0000000 --- a/src/keyval_type.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2000 - 2016 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. - */ - -#ifndef __KEYVAL_TYPE_H__ -#define __KEYVAL_TYPE_H__ - -/** - * keyval_type.h - * - * Definitions & short funcs for keyval type - */ - -#include -#include - -#include "bundle.h" - -#ifdef __cplusplus -extern "C" { -# endif - -/* measure_size function type */ -typedef size_t (*keyval_type_measure_size_func_t) (void *val); - -void _type_init_measure_size_func(void); -int keyval_type_is_array(int type); -int keyval_type_is_measurable(int type); -keyval_type_measure_size_func_t keyval_type_get_measure_size_func(int type); - -/* Measure functions for each 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/src/log-private.h b/src/log-private.h new file mode 100644 index 0000000..29e99da --- /dev/null +++ b/src/log-private.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef LOG_PRIVATE_H_ +#define LOG_PRIVATE_H_ + +#include + +#undef LOG_TAG +#define LOG_TAG "BUNDLE" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // LOG_PRIVATE_H_ diff --git a/src/stub.cc b/src/stub.cc new file mode 100644 index 0000000..aff0955 --- /dev/null +++ b/src/stub.cc @@ -0,0 +1,664 @@ +/* + * Copyright (c) 2020 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/bundle.h" +#include "include/bundle_internal.h" + +#include "bundle-internal.h" +#include "exception-internal.h" +#include "export-api-internal.h" +#include "json-internal.h" + +using namespace tizen_base::internal; + +extern "C" EXPORT_API bundle* bundle_create(void) { + auto* h = new (std::nothrow) Bundle(); + if (h == nullptr) { + set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); + return nullptr; + } + + set_last_result(BUNDLE_ERROR_NONE); + return reinterpret_cast(h); +} + +extern "C" EXPORT_API int bundle_free(bundle* b) { + if (b == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + delete h; + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_add_str(bundle* b, + const char* key, const char* str) { + if (b == nullptr || key == nullptr || str == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + std::vector value(str, str + (strlen(str) + 1)); + std::shared_ptr key_info( + new (std::nothrow) KeyInfo(BUNDLE_TYPE_STR, key, value)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + try { + h->Add(key_info); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_get_str(bundle* b, + const char* key, char** str) { + if (b == nullptr || key == nullptr || str == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + std::shared_ptr key_info; + try { + key_info = h->Get(key); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + if (key_info->GetType() != BUNDLE_TYPE_STR) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto& values = key_info->GetValues(); + auto& value = const_cast&>(values[0]); + *str = reinterpret_cast(&value[0]); + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_add(bundle* b, const char* key, + const char* val) { + return bundle_add_str(b, key, val); +} + +extern "C" EXPORT_API int bundle_del(bundle* b, const char* key) { + if (b == nullptr || key == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + try { + h->Remove(key); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API const char* bundle_get_val(bundle* b, const char* key) { + char* val = nullptr; + int ret = bundle_get_str(b, key, &val); + set_last_result(ret); + return val; +} + +extern "C" EXPORT_API int bundle_get_count(bundle* b) { + if (b == nullptr) + return 0; + + auto* h = reinterpret_cast(b); + set_last_result(BUNDLE_ERROR_NONE); + return h->GetSize(); +} + +extern "C" EXPORT_API void bundle_iterate(bundle* b, + bundle_iterate_cb_t callback, void* user_data) { + if (b == nullptr || callback == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return; + } + + auto* h = reinterpret_cast(b); + for (const auto& kv : h->GetMap()) { + auto& key_info = kv.second; + auto& values = key_info->GetValues(); + auto& value = const_cast&>(values[0]); + auto* val = reinterpret_cast(&value[0]); + callback(key_info->GetKey().c_str(), val, user_data); + } + + set_last_result(BUNDLE_ERROR_NONE); +} + +extern "C" EXPORT_API void bundle_foreach(bundle* b, + bundle_iterator_t callback, void* user_data) { + if (b == nullptr || callback == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return; + } + + auto* h = reinterpret_cast(b); + for (const auto& kv : h->GetMap()) { + auto& key_info = kv.second; + callback(key_info->GetKey().c_str(), key_info->GetType(), + reinterpret_cast(key_info.get()), user_data); + } + + set_last_result(BUNDLE_ERROR_NONE); +} + +extern "C" EXPORT_API int bundle_keyval_get_type(bundle_keyval_t* kv) { + if (kv == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return -1; + } + + auto* key_info = reinterpret_cast(kv); + set_last_result(BUNDLE_ERROR_NONE); + return key_info->GetType(); +} + +extern "C" EXPORT_API int bundle_keyval_type_is_array(bundle_keyval_t* kv) { + int type = bundle_keyval_get_type(kv); + if (type == -1) + return -1; + + set_last_result(BUNDLE_ERROR_NONE); + if (type & BUNDLE_TYPE_ARRAY) + return 1; + + return 0; +} + +extern "C" EXPORT_API int bundle_keyval_type_is_measurable( + bundle_keyval_t* kv) { + int type = bundle_keyval_get_type(kv); + if (type == -1) + return -1; + + set_last_result(BUNDLE_ERROR_NONE); + if (type & BUNDLE_TYPE_MEASURABLE) + return 1; + + return 0; +} + +extern "C" EXPORT_API int bundle_keyval_get_basic_val(bundle_keyval_t* kv, + void** val, size_t* size) { + if (kv == nullptr || val == nullptr || size == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* key_info = reinterpret_cast(kv); + auto& values = key_info->GetValues(); + auto& value = const_cast&>(values[0]); + *val = reinterpret_cast(&value[0]); + auto& values_size = key_info->GetValuesSize(); + *size = reinterpret_cast(values_size[0]); + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_keyval_get_array_val(bundle_keyval_t* kv, + void*** array_val, unsigned int* array_len, size_t** array_item_size) { + if (kv == nullptr || array_val == nullptr || array_len == nullptr || + array_item_size == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* key_info = reinterpret_cast(kv); + auto& values = const_cast>&>( + key_info->GetValues()); + auto& values_size = const_cast&>( + key_info->GetValuesSize()); + *array_val = reinterpret_cast(&values[0]); + *array_len = reinterpret_cast(values.size()); + *array_item_size = reinterpret_cast(&values_size[0]); + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API bundle_keyval_t* bundle_keyval_dup( + const bundle_keyval_t* kv) { + if (kv == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + auto* keyval = const_cast(kv); + auto* key_info = reinterpret_cast(keyval); + auto* k = new (std::nothrow) KeyInfo(*key_info); + if (k == nullptr) { + set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); + return nullptr; + } + + set_last_result(BUNDLE_ERROR_NONE); + return reinterpret_cast(k); +} + +extern "C" EXPORT_API int bundle_keyval_free(bundle_keyval_t* kv) { + if (kv == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* key_info = reinterpret_cast(kv); + delete key_info; + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API bundle* bundle_dup(bundle* b_from) { + if (b_from == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + auto* h = reinterpret_cast(b_from); + auto* b = new (std::nothrow) Bundle(*h); + if (b == nullptr) { + set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); + return nullptr; + } + + set_last_result(BUNDLE_ERROR_NONE); + return reinterpret_cast(b); +} + +extern "C" EXPORT_API int bundle_encode(bundle *b, bundle_raw** raw, int* len) { + if (b == nullptr || raw == nullptr || len == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + *raw = reinterpret_cast(h->Encode()); + *len = strlen(reinterpret_cast(*raw)); + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_free_encoded_rawdata(bundle_raw **r) { + if (r == nullptr || *r == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + free(*r); + *r = nullptr; + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API bundle* bundle_decode(const bundle_raw* r, + const int data_size) { + if (r == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + Bundle* b = nullptr; + try { + auto* raw = const_cast(r); + b = new (std::nothrow) Bundle(static_cast(raw), data_size); + } catch (Exception& e) { + set_last_result(e.GetErrorCode()); + return nullptr; + } + + set_last_result(BUNDLE_ERROR_NONE); + return reinterpret_cast(b); +} + +extern "C" EXPORT_API int bundle_encode_raw(bundle* b, bundle_raw** r, + int* len) { + return bundle_encode(b, r, len); +} + +extern "C" EXPORT_API bundle* bundle_decode_raw(const bundle_raw* r, + const int data_size) { + return bundle_decode(r, data_size); +} + +extern "C" EXPORT_API int bundle_get_type(bundle* b, const char* key) { + if (b == nullptr || key == nullptr) { + set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE); + return BUNDLE_TYPE_NONE; + } + + auto* h = reinterpret_cast(b); + std::shared_ptr key_info; + try { + key_info = h->Get(key); + } catch (Exception& e) { + set_last_result(e.GetErrorCode()); + return BUNDLE_TYPE_NONE; + } + + set_last_result(BUNDLE_ERROR_NONE); + return key_info->GetType(); +} + +extern "C" EXPORT_API int bundle_add_str_array(bundle* b, const char* key, + const char** str_array, const int len) { + if (b == nullptr || key == nullptr || len <= 0) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + std::vector> values(len); + if (str_array) { + for (int i = 0; i < len; ++i) { + std::vector value(str_array[i], + str_array[i] + (strlen(str_array[i]) + 1)); + values[i] = std::move(value); + } + } + + std::shared_ptr key_info( + new (std::nothrow) KeyInfo( + (BUNDLE_TYPE_STR_ARRAY | BUNDLE_TYPE_ARRAY), key, values)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + try { + h->Add(std::move(key_info)); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API const char** bundle_get_str_array(bundle* b, + const char* key, int* len) { + if (b == nullptr || key == nullptr || len == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + auto* h = reinterpret_cast(b); + std::shared_ptr key_info; + try { + key_info = h->Get(key); + } catch (Exception& e) { + set_last_result(e.GetErrorCode()); + return nullptr; + } + + if (key_info->GetType() != BUNDLE_TYPE_STR_ARRAY) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + auto& raw_values = const_cast>&>( + key_info->GetValues()); + auto** values = reinterpret_cast(&raw_values[0]); + *len = static_cast(raw_values.size()); + + set_last_result(BUNDLE_ERROR_NONE); + return const_cast(reinterpret_cast(values)); +} + +extern "C" EXPORT_API int bundle_add_byte(bundle* b, const char* key, + const void* bytes, const size_t size) { + if (b == nullptr || key == nullptr || bytes == nullptr || size == 0) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + auto* p = reinterpret_cast(bytes); + std::vector value(p, p + size); + + std::shared_ptr key_info( + new (std::nothrow) KeyInfo(BUNDLE_TYPE_BYTE, key, value)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + try { + h->Add(std::move(key_info)); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_get_byte(bundle* b, const char* key, + void** bytes, size_t* size) { + if (b == nullptr || key == nullptr || bytes == nullptr || size == 0) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + std::shared_ptr key_info; + try { + key_info = h->Get(key); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + if (key_info->GetType() != BUNDLE_TYPE_BYTE) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto& values = const_cast>&>( + key_info->GetValues()); + auto& value = values[0]; + *bytes = reinterpret_cast(&value[0]); + auto& values_size = key_info->GetValuesSize(); + *size = reinterpret_cast(values_size[0]); + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_export_to_argv(bundle* b, char*** argv) { + if (b == nullptr || argv == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return -1; + } + + auto* h = reinterpret_cast(b); + std::vector exported_vt; + try { + exported_vt = h->Export(); + } catch (Exception& e) { + set_last_result(e.GetErrorCode()); + return -1; + } + + int argc = exported_vt.size(); + auto** exported_argv = reinterpret_cast( + calloc(argc + 1, sizeof(char*))); + if (exported_argv == nullptr) { + set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); + return -1; + } + + exported_argv[1] = const_cast(TAG_IMPORT_EXPORT_CHECK); + for (unsigned int idx = 2; idx < exported_vt.size(); idx += 2) { + exported_argv[idx] = strdup(exported_vt[idx].c_str()); + if (exported_argv[idx] == nullptr) { + set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); + bundle_free_exported_argv(argc, &exported_argv); + return -1; + } + + exported_argv[idx + 1] = strdup(exported_vt[idx + 1].c_str()); + if (exported_argv[idx + 1] == nullptr) { + set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY); + bundle_free_exported_argv(argc, &exported_argv); + return -1; + } + } + + *argv = exported_argv; + set_last_result(BUNDLE_ERROR_NONE); + return argc; +} + +extern "C" EXPORT_API int bundle_free_exported_argv(int argc, char*** argv) { + if (argc < 2 || !argv || !*argv) + return BUNDLE_ERROR_INVALID_PARAMETER; + + for (int i = 2; i < argc; i++) + std::free((*argv)[i]); + + std::free(*argv); + *argv = nullptr; + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API bundle* bundle_import_from_argv(int argc, char** argv) { + if (argv == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + Bundle* b = nullptr; + try { + b = new (std::nothrow) Bundle(argc, argv); + } catch (Exception& e) { + set_last_result(e.GetErrorCode()); + return nullptr; + } + + set_last_result(BUNDLE_ERROR_NONE); + return reinterpret_cast(b); +} + +extern "C" EXPORT_API int bundle_compare(bundle* b1, bundle* b2) { + if (b1 == nullptr || b2 == nullptr) + return -1; + + auto* h1 = reinterpret_cast(b1); + auto* h2 = reinterpret_cast(b2); + if (*h1 == *h2) + return 0; + + return 1; +} + +extern "C" EXPORT_API int bundle_set_str_array_element(bundle* b, + const char* key, const unsigned int idx, const char* val) { + if (b == nullptr || key == nullptr || val == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto len = strlen(val) + 1; + auto* p = reinterpret_cast(const_cast(val)); + std::vector value(p, p + len); + + auto* h = reinterpret_cast(b); + try { + h->Set(key, idx, value); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_add_byte_array(bundle* b, + const char* key, const unsigned int len) { + return bundle_init_byte_array(b, key, len); +} + +extern "C" EXPORT_API int bundle_init_byte_array(bundle* b, + const char* key, const unsigned int len) { + if (b == nullptr || key == nullptr || len <= 0) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + std::vector> values(len); + auto key_info = std::shared_ptr( + new (std::nothrow) KeyInfo(Bundle::Type::ByteArray, key, values)); + if (key_info.get() == nullptr) + return BUNDLE_ERROR_OUT_OF_MEMORY; + + try { + h->Add(key_info); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_get_byte_array(bundle* b, + const char* key, void*** bytes_array, unsigned int* len, + unsigned int** array_element_size) { + if (b == nullptr || key == nullptr || bytes_array == nullptr || + len == nullptr || array_element_size == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + std::shared_ptr key_info; + try { + key_info = h->Get(key); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + if (key_info->GetType() != BUNDLE_TYPE_BYTE_ARRAY) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto& raw_values = const_cast>&>( + key_info->GetValues()); + auto** values = reinterpret_cast(&raw_values[0]); + *bytes_array = reinterpret_cast(values); + *len = reinterpret_cast(raw_values.size()); + + auto& raw_values_size = const_cast&>( + key_info->GetValuesSize()); + *array_element_size = reinterpret_cast(&raw_values_size[0]); + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_set_byte_array_element(bundle* b, + const char* key, const unsigned int idx, + const void* bytes, const size_t size) { + if (b == nullptr || key == nullptr || bytes == nullptr || size <= 0) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* p = reinterpret_cast(const_cast(bytes)); + std::vector value(p, p + size); + + auto* h = reinterpret_cast(b); + try { + h->Set(key, idx, value); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_to_json(bundle* b, char** json) { + if (b == nullptr || json == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + Json js(h); + try { + *json = strdup(js.ToString().c_str()); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} + +extern "C" EXPORT_API int bundle_from_json(const char* json, bundle** b) { + if (json == nullptr || b == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + Json js(json); + try { + *b = reinterpret_cast(js.ToBundle()); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return BUNDLE_ERROR_NONE; +} diff --git a/tools/check-coding-style b/tools/check-coding-style new file mode 100755 index 0000000..fd60481 --- /dev/null +++ b/tools/check-coding-style @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if [ ! `which cpplint.py` ]; then + echo -e "\nPlease make sure cpplint.py is in your PATH. It is part of depot_tools inside Chromium repository." + exit 1 +fi + +OLDPWD=$PWD +BASE=`dirname $0` +cd $BASE/.. + +# filters +FILTERS="-readability/streams,-build/c++11" + +cpplint.py --root=src --filter="$FILTERS" $(find . \( -name '*.h' -o -name '*.cc' \) ) +RET=$? + +JS_RET_VAL=$? +cd $OLDPWD + +if [ "x$RET" == "x0" ]; then + exit 0 +else + exit 1 +fi diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt index f96ee7e..064f946 100644 --- a/unit_tests/CMakeLists.txt +++ b/unit_tests/CMakeLists.txt @@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(bundle_unittests C CXX) INCLUDE(FindPkgConfig) -pkg_check_modules(bundle_unittests REQUIRED +PKG_CHECK_MODULES(bundle_unittests REQUIRED dlog gmock glib-2.0 @@ -19,15 +19,19 @@ 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}/../) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../bundle) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src UNITTESTS_SOURCES) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../src BUNDLE_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../bundle BUNDLE_INTERNAL_SOURCES) ADD_EXECUTABLE(${PROJECT_NAME} ${BUNDLE_SOURCES} + ${BUNDLE_INTERNAL_SOURCES} ${UNITTESTS_SOURCES} ) diff --git a/unit_tests/src/test_bundle.cc b/unit_tests/src/test_bundle.cc index c94b080..6bde750 100644 --- a/unit_tests/src/test_bundle.cc +++ b/unit_tests/src/test_bundle.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2020 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. @@ -19,145 +19,1172 @@ #include #include -#include "bundle_cpp.h" +#include "include/bundle.h" +#include "include/bundle_internal.h" -using ::testing::AtLeast; -using namespace tizen_base; -using namespace std; +class BundleTest : public ::testing::Test { + public: + virtual void SetUp() { + b_ = bundle_create(); + } + virtual void TearDown() { + if (b_) + bundle_free(b_); + } + + bundle* GetHandle() { + return b_; + } + + void SetHandle(bundle* b) { + b_ = b; + } + + private: + bundle* b_ = nullptr; +}; -TEST(Bundle, CtorDtor) { - Bundle bundle; +TEST_F(BundleTest, bundle_create_P) { + bundle* b = bundle_create(); + std::unique_ptr b_ptr(b, bundle_free); + ASSERT_NE(b, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); } -TEST(Bundle, CopyCtor) { - Bundle bundle; - bundle.Add("TestKey", "TestVal"); +TEST_F(BundleTest, bundle_free_P) { + bundle* b = GetHandle(); + int ret = bundle_free(b); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + SetHandle(nullptr); +} - Bundle b2(bundle); - EXPECT_EQ(b2.GetString("TestKey"), "TestVal"); +TEST_F(BundleTest, bundle_free_N) { + int ret = bundle_free(nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); } -TEST(Bundle, MoveCtor) { - Bundle bundle; - bundle.Add("TestKey", "TestVal"); +TEST_F(BundleTest, bundle_add_str_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_add_str(b, "KEY2", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - Bundle b2(std::move(bundle)); - EXPECT_EQ(b2.GetString("TestKey"), "TestVal"); + char* str = nullptr; + ret = bundle_get_str(b, "KEY1", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(std::string(str), "VALUE1"); + + str = nullptr; + ret = bundle_get_str(b, "KEY2", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(std::string(str), "VALUE2"); } -TEST(Bundle, AddStringGetString) { - Bundle bundle; - bundle.Add("TestKey", "TestVal"); +TEST_F(BundleTest, bundle_add_str_N) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); - EXPECT_EQ(bundle.GetString("TestKey"), "TestVal"); + ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add_str(b, "KEY1", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_EXISTS); } -TEST(Bundle, AddByteGetByte) { - Bundle bundle; - std::vector v = { 0, 1, 2, 3}; - bundle.Add("TestKey", v); - auto v2 = bundle.GetByte("TestKey"); +TEST_F(BundleTest, bundle_get_str_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - 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); + char* str = nullptr; + ret = bundle_get_str(b, "KEY", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(std::string(str), "VALUE"); } -TEST(Bundle, AddStringArrayGetStringArray) { - Bundle bundle; - bundle.Add("TestKey", { "TestVal1", "TestVal2", "TestVal3" }); +TEST_F(BundleTest, bundle_get_str_N) { + bundle* b = GetHandle(); + int ret = bundle_get_str(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + char* str = nullptr; + ret = bundle_get_str(b, "KEY", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_NOT_AVAILABLE); +} + +TEST_F(BundleTest, bundle_add_P) { + bundle* b = GetHandle(); + int ret = bundle_add(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add(b, "KEY2", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char* str = nullptr; + ret = bundle_get_str(b, "KEY1", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(std::string(str), "VALUE1"); - auto v = bundle.GetStringArray("TestKey"); + str = nullptr; + ret = bundle_get_str(b, "KEY2", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(std::string(str), "VALUE2"); +} + +TEST_F(BundleTest, bundle_add_N) { + bundle* b = GetHandle(); + int ret = bundle_add(b, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); - EXPECT_EQ(v.size(), 3); - EXPECT_EQ(v[0], "TestVal1"); - EXPECT_EQ(v[1], "TestVal2"); - EXPECT_EQ(v[2], "TestVal3"); + ret = bundle_add(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add(b, "KEY1", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_EXISTS); } -TEST(Bundle, ToRaw) { - Bundle bundle; - bundle.Add("TestKey", "TestVal"); +TEST_F(BundleTest, bundle_get_val_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - auto r = bundle.ToRaw(); - Bundle b2(std::move(r)); - EXPECT_EQ(bundle.GetString("TestKey"), "TestVal"); + const char* val = bundle_get_val(b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE"); } -TEST(Bundle, GetCount) { - Bundle bundle; - bundle.Add("TestKey1", "TestVal1"); - bundle.Add("TestKey2", "TestVal2"); +TEST_F(BundleTest, bundle_get_val_N) { + bundle* b = GetHandle(); + const char* val = bundle_get_val(nullptr, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(val, nullptr); - EXPECT_EQ(bundle.GetCount(), 2); + val = bundle_get_val(b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_KEY_NOT_AVAILABLE); + ASSERT_EQ(val, nullptr); } -TEST(Bundle, Delete) { - Bundle bundle; - int r = bundle.Add("TestKey1", "TestVal1"); - EXPECT_EQ(r, 0); +TEST_F(BundleTest, bundle_del_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - r = bundle.Delete("TestKey1"); - EXPECT_EQ(r, 0); + int count = bundle_get_count(b); + ASSERT_EQ(count, 1); - EXPECT_EQ(bundle.GetString("TestKey1"), ""); + ret = bundle_del(b, "KEY"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + count = bundle_get_count(b); + ASSERT_EQ(count, 0); } -TEST(Bundle, GetKeys) { - Bundle bundle; - bundle.Add("TestKey1", "TestVal1"); - bundle.Add("TestKey2", "TestVal2"); - bundle.Add("TestKey3", "TestVal3"); +TEST_F(BundleTest, bundle_del_N) { + bundle* b = GetHandle(); + int ret = bundle_del(nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); - auto v = bundle.GetKeys(); + ret = bundle_del(b, "KEY"); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_NOT_AVAILABLE); +} - EXPECT_EQ(bundle.GetCount(), 3); +TEST_F(BundleTest, bundle_get_count_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + int count = bundle_get_count(b); + ASSERT_EQ(count, 1); - for (auto& i : v) { - EXPECT_EQ(i.GetType(), BUNDLE_TYPE_STR); - } + ret = bundle_add_str(b, "KEY2", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + count = bundle_get_count(b); + ASSERT_EQ(count, 2); + + ret = bundle_del(b, "KEY2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + count = bundle_get_count(b); + ASSERT_EQ(count, 1); } -TEST(Bundle, GetKeysCopy) { - Bundle bundle; - bundle.Add("TestKey1", "TestVal1"); - bundle.Add("TestKey2", "TestVal2"); - bundle.Add("TestKey3", "TestVal3"); +TEST_F(BundleTest, bundle_get_count_N) { + bundle* b = GetHandle(); + int count = bundle_get_count(b); + ASSERT_EQ(count, 0); + + count = bundle_get_count(nullptr); + ASSERT_EQ(count, 0); +} - auto v = bundle.GetKeys(); +TEST_F(BundleTest, bundle_iterate_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add_str(b, "KEY2", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - EXPECT_EQ(bundle.GetCount(), 3); + int count = 0; + bundle_iterate(b, + [](const char* key, const char* val, void* data) { + int* count = reinterpret_cast(data); + if (std::string(key) == "KEY1") { + if (std::string(val) == "VALUE1") + (*count)++; + } else if (std::string(key) == "KEY2") { + if (std::string(val) == "VALUE2") + (*count)++; + } + }, reinterpret_cast(&count)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(count, 2); +} - for (auto& i : v) { - Bundle::KeyInfo copied = i; - EXPECT_EQ(copied.GetType(), BUNDLE_TYPE_STR); - EXPECT_EQ(copied.GetName(), i.GetName()); - } +TEST_F(BundleTest, bundle_iterate_N) { + bundle* b = GetHandle(); + bundle_iterate(b, nullptr, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + bundle_iterate(nullptr, + [](const char* key, const char* val, void* data) { + }, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); } -TEST(Bundle, GetKeysMove) { - Bundle bundle; - bundle.Add("TestKey1", "TestVal1"); - bundle.Add("TestKey2", "TestVal2"); - bundle.Add("TestKey3", "TestVal3"); +TEST_F(BundleTest, bundle_foreach_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add_str(b, "KEY2", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add_str(b, "KEY3", "VALUE3"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); - auto v = bundle.GetKeys(); + int count = 0; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + int* count = reinterpret_cast(user_data); + if (type == BUNDLE_TYPE_STR) { + void* val = nullptr; + size_t size = 0; + int ret = bundle_keyval_get_basic_val( + const_cast(kv), &val, &size); + if (ret != BUNDLE_ERROR_NONE) + return; - EXPECT_EQ(bundle.GetCount(), 3); + std::string value(reinterpret_cast(val)); + if (std::string(key) == "KEY1") { + if (value == "VALUE1") + (*count)++; + } else if (std::string(key) == "KEY2") { + if (value == "VALUE2") + (*count)++; + } else if (std::string(key) == "KEY3") { + if (value == "VALUE3") + (*count)++; + } + } + }, reinterpret_cast(&count)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(count, 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); - } +TEST_F(BundleTest, bundle_foreach_N) { + bundle* b = GetHandle(); + bundle_foreach(b, nullptr, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + bundle_foreach(nullptr, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + }, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_keyval_get_type_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bool matched = false; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bool* matched = reinterpret_cast(user_data); + if (type == BUNDLE_TYPE_STR) { + int keyval_type = bundle_keyval_get_type( + const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(keyval_type, type); + *matched = true; + } + }, reinterpret_cast(&matched)); + ASSERT_EQ(matched, true); +} + +TEST_F(BundleTest, bundle_keyval_get_type_N) { + int type = bundle_keyval_get_type(nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(type, -1); +} + +TEST_F(BundleTest, bundle_keyval_type_is_array_P) { + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + + int ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bool is_array = false; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bool* is_array = reinterpret_cast(user_data); + if (type == BUNDLE_TYPE_STR_ARRAY) { + int ret = bundle_keyval_type_is_array( + const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(ret, 1); + *is_array = true; + } + }, reinterpret_cast(&is_array)); + ASSERT_EQ(is_array, true); +} + +TEST_F(BundleTest, bundle_keyval_type_is_array_N) { + int ret = bundle_keyval_type_is_array(nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(ret, -1); + + bundle* b = GetHandle(); + ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bool is_array = false; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bool* is_array = reinterpret_cast(user_data); + if (std::string(key) == "KEY") { + int ret = bundle_keyval_type_is_array( + const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(ret, 0); + if (ret == 1) + *is_array = true; + } + }, reinterpret_cast(&is_array)); + ASSERT_NE(is_array, true); +} + +TEST_F(BundleTest, bundle_keyval_type_is_measurable_P) { + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + + int ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bool is_measurable = false; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bool* is_measurable = reinterpret_cast(user_data); + int ret = bundle_keyval_type_is_measurable( + const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(ret, 1); + *is_measurable = true; + }, reinterpret_cast(&is_measurable)); + ASSERT_EQ(is_measurable, true); +} + +TEST_F(BundleTest, bundle_keyval_type_is_measurable_N) { + int ret = bundle_keyval_type_is_measurable(nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(ret, -1); + + bundle* b = GetHandle(); + ret = bundle_add_byte(b, "KEY", "VALUE", sizeof("VALUE")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bool is_measurable = false; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bool* is_measurable = reinterpret_cast(user_data); + if (std::string(key) == "KEY") { + int ret = bundle_keyval_type_is_measurable( + const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(ret, 0); + if (ret == 1) + *is_measurable = true; + } + }, reinterpret_cast(&is_measurable)); + ASSERT_NE(is_measurable, true); +} + +TEST_F(BundleTest, bundle_keyval_get_basic_val_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char* val = nullptr; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + char** val = reinterpret_cast(user_data); + if (std::string(key) == "KEY") { + size_t size = 0; + int ret = bundle_keyval_get_basic_val( + const_cast(kv), + reinterpret_cast(val), + &size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + } + }, reinterpret_cast(&val)); + ASSERT_EQ(std::string(val), "VALUE"); +} + +TEST_F(BundleTest, bundle_keyval_get_basic_val_N) { + int ret = bundle_keyval_get_basic_val(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_keyval_get_array_val_P) { + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + int ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char** array_val = nullptr; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + char*** array_val = reinterpret_cast(user_data); + if (std::string(key) == "KEY") { + unsigned int array_len = 0; + size_t* array_item_size = nullptr; + int ret = bundle_keyval_get_array_val( + const_cast(kv), + reinterpret_cast(array_val), + &array_len, + &array_item_size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(array_len, 2); + ASSERT_EQ(array_item_size[0], sizeof("VALUE1")); + ASSERT_EQ(array_item_size[1], sizeof("VALUE2")); + } + }, reinterpret_cast(&array_val)); + ASSERT_EQ(std::string(array_val[0]), "VALUE1"); + ASSERT_EQ(std::string(array_val[1]), "VALUE2"); +} + +TEST_F(BundleTest, bundle_keyval_get_array_val_N) { + int ret = bundle_keyval_get_array_val(nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_keyval_dup_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle_keyval_t* kv = nullptr; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bundle_keyval_t** kv_dup = reinterpret_cast( + user_data); + *kv_dup = bundle_keyval_dup(const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + }, reinterpret_cast(&kv)); + std::unique_ptr keyval_ptr( + kv, bundle_keyval_free); + ASSERT_NE(kv, nullptr); + + size_t size = 0; + char* val = nullptr; + ret = bundle_keyval_get_basic_val(kv, reinterpret_cast(&val), &size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_EQ(std::string(val), "VALUE"); + ASSERT_EQ(size, sizeof("VALUE")); +} + +TEST_F(BundleTest, bundle_keyval_dup_N) { + bundle_keyval_t* kv = bundle_keyval_dup(nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(kv, nullptr); +} + +TEST_F(BundleTest, bundle_keyval_free_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle_keyval_t* kv = nullptr; + bundle_foreach(b, + [](const char* key, const int type, const bundle_keyval_t* kv, + void* user_data) { + bundle_keyval_t** kv_dup = reinterpret_cast( + user_data); + *kv_dup = bundle_keyval_dup(const_cast(kv)); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + }, reinterpret_cast(&kv)); + ASSERT_NE(kv, nullptr); + + ret = bundle_keyval_free(kv); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); +} + +TEST_F(BundleTest, bundle_keyval_free_N) { + int ret = bundle_keyval_free(nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_dup_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle* b_dup = bundle_dup(b); + std::unique_ptr b_ptr(b_dup, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(b_dup, nullptr); + + const char* val = bundle_get_val(b_dup, "KEY"); + ASSERT_EQ(std::string(val), "VALUE"); +} + +TEST_F(BundleTest, bundle_dup_N) { + bundle* b_dup = bundle_dup(nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(b_dup, nullptr); +} + +TEST_F(BundleTest, bundle_encode_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle_raw* raw = nullptr; + int len = 0; + ret = bundle_encode(b, &raw, &len); + std::unique_ptr raw_ptr( + &raw, bundle_free_encoded_rawdata); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(raw, nullptr); + ASSERT_NE(len, 0); + + bundle* decoded_b = bundle_decode(raw, len); + std::unique_ptr b_ptr(decoded_b, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(decoded_b, nullptr); + + const char* val = bundle_get_val(decoded_b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE"); +} + +TEST_F(BundleTest, bundle_encode_N) { + int ret = bundle_encode(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_free_encoded_rawdata_P) { + bundle* b = GetHandle(); + bundle_raw* raw = nullptr; + int len = 0; + int ret = bundle_encode(b, &raw, &len); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_free_encoded_rawdata(&raw); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); +} + +TEST_F(BundleTest, bundle_free_encoded_rawdata_N) { + int ret = bundle_free_encoded_rawdata(nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_decode_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle_raw* raw = nullptr; + int len = 0; + ret = bundle_encode(b, &raw, &len); + std::unique_ptr raw_ptr( + &raw, bundle_free_encoded_rawdata); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(raw, nullptr); + ASSERT_NE(len, 0); + + bundle* decoded_b = bundle_decode(raw, len); + std::unique_ptr b_ptr(decoded_b, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(decoded_b, nullptr); + + const char* val = bundle_get_val(decoded_b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE"); +} + +TEST_F(BundleTest, bundle_decode_N) { + bundle* b = bundle_decode(nullptr, 0); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(b, nullptr); +} + +TEST_F(BundleTest, bundle_encode_raw_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle_raw* raw = nullptr; + int len = 0; + ret = bundle_encode_raw(b, &raw, &len); + std::unique_ptr raw_ptr( + &raw, bundle_free_encoded_rawdata); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(raw, nullptr); + ASSERT_NE(len, 0); + + bundle* decoded_b = bundle_decode(raw, len); + std::unique_ptr b_ptr(decoded_b, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(decoded_b, nullptr); + + const char* val = bundle_get_val(decoded_b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE1"); +} + +TEST_F(BundleTest, bundle_encode_raw_N) { + int ret = bundle_encode_raw(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_decode_raw_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE2"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle_raw* raw = nullptr; + int len = 0; + ret = bundle_encode_raw(b, &raw, &len); + std::unique_ptr raw_ptr( + &raw, bundle_free_encoded_rawdata); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(raw, nullptr); + ASSERT_NE(len, 0); + + bundle* decoded_b = bundle_decode_raw(raw, len); + std::unique_ptr b_ptr(decoded_b, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(decoded_b, nullptr); + + const char* val = bundle_get_val(decoded_b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE2"); +} + +TEST_F(BundleTest, bundle_decode_raw_N) { + bundle* b = bundle_decode_raw(nullptr, 0); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(b, nullptr); +} + +TEST_F(BundleTest, bundle_get_type_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + const char* str_array[] = { + "VALUE2", + "VALUE3", + }; + ret = bundle_add_str_array(b, "KEY2", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add_byte(b, "KEY3", "VALUE3", sizeof("VALUE4")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_add_byte_array(b, "KEY4", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_set_byte_array_element(b, "KEY4", 0, + "VALUE5", sizeof("VALUE5")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_set_byte_array_element(b, "KEY4", 1, + "VALUE6", sizeof("VALUE6")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + int type = bundle_get_type(b, "KEY1"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(type, BUNDLE_TYPE_STR); + + type = bundle_get_type(b, "KEY2"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(type, BUNDLE_TYPE_STR_ARRAY); + + type = bundle_get_type(b, "KEY3"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(type, BUNDLE_TYPE_BYTE); + + type = bundle_get_type(b, "KEY4"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_EQ(type, BUNDLE_TYPE_BYTE_ARRAY); +} + +TEST_F(BundleTest, bundle_get_type_N) { + int type = bundle_get_type(nullptr, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_KEY_NOT_AVAILABLE); + ASSERT_EQ(type, BUNDLE_TYPE_NONE); + + bundle* b = GetHandle(); + type = bundle_get_type(b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_KEY_NOT_AVAILABLE); + ASSERT_EQ(type, BUNDLE_TYPE_NONE); +} + +TEST_F(BundleTest, bundle_add_str_array_P) { + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + int ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + int len = 0; + const char** val_array = bundle_get_str_array(b, "KEY", &len); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val_array, nullptr); + ASSERT_EQ(std::string(val_array[0]), "VALUE1"); + ASSERT_EQ(std::string(val_array[1]), "VALUE2"); + ASSERT_EQ(len, 2); +} + +TEST_F(BundleTest, bundle_add_str_array_N) { + int ret = bundle_add_str_array(nullptr, nullptr, nullptr, 0); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_EXISTS); +} + +TEST_F(BundleTest, bundle_get_str_array_P) { + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + int ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + int len = 0; + const char** val_array = bundle_get_str_array(b, "KEY", &len); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val_array, nullptr); + ASSERT_EQ(std::string(val_array[0]), "VALUE1"); + ASSERT_EQ(std::string(val_array[1]), "VALUE2"); + ASSERT_EQ(len, 2); +} + +TEST_F(BundleTest, bundle_get_str_array_N) { + const char** val_array = bundle_get_str_array(nullptr, nullptr, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(val_array, nullptr); + + bundle* b = GetHandle(); + int len = 0; + val_array = bundle_get_str_array(b, "KEY", &len); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_KEY_NOT_AVAILABLE); + ASSERT_EQ(val_array, nullptr); +} + +TEST_F(BundleTest, bundle_add_byte_P) { + bundle* b = GetHandle(); + int ret = bundle_add_byte(b, "KEY", "VALUE", sizeof("VALUE")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + void* bytes = nullptr; + size_t size = 0; + ret = bundle_get_byte(b, "KEY", &bytes, &size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(bytes, nullptr); + ASSERT_NE(size, 0); + ASSERT_EQ(std::string(reinterpret_cast(bytes)), "VALUE"); +} + +TEST_F(BundleTest, bundle_add_byte_N) { + int ret = bundle_add_byte(nullptr, nullptr, nullptr, 0); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + ret = bundle_add_byte(b, "KEY", "VALUE", sizeof("VALUE")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_add_byte(b, "KEY", "VALUE1", sizeof("VALUE1")); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_EXISTS); +} + +TEST_F(BundleTest, bundle_get_byte_P) { + bundle* b = GetHandle(); + int ret = bundle_add_byte(b, "KEY", "VALUE", sizeof("VALUE")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + void* bytes = nullptr; + size_t size = 0; + ret = bundle_get_byte(b, "KEY", &bytes, &size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(bytes, nullptr); + ASSERT_NE(size, 0); + ASSERT_EQ(std::string(reinterpret_cast(bytes)), "VALUE"); +} + +TEST_F(BundleTest, bundle_get_byte_N) { + int ret = bundle_get_byte(nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + void* bytes = nullptr; + size_t size = 0; + ret = bundle_get_byte(b, "KEY", &bytes, &size); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_NOT_AVAILABLE); +} + +TEST_F(BundleTest, bundle_export_to_argv_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char** argv = nullptr; + int argc = bundle_export_to_argv(b, &argv); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(argv, nullptr); + ASSERT_NE(argc, 0); + + bundle* imported_b = bundle_import_from_argv(argc, argv); + bundle_free_exported_argv(argc, &argv); + std::unique_ptr b_ptr(imported_b, + bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(imported_b, nullptr); + + const char* val = bundle_get_val(imported_b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE"); +} + +TEST_F(BundleTest, bundle_export_to_argv_N) { + int argc = bundle_export_to_argv(nullptr, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(argc, -1); +} + +TEST_F(BundleTest, bundle_free_exported_argv_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char** argv = nullptr; + int argc = bundle_export_to_argv(b, &argv); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(argv, nullptr); + ASSERT_NE(argc, 0); + + ret = bundle_free_exported_argv(argc, &argv); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); +} + +TEST_F(BundleTest, bundle_free_exported_argv_N) { + int ret = bundle_free_exported_argv(0, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_import_from_argv_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char** argv = nullptr; + int argc = bundle_export_to_argv(b, &argv); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(argv, nullptr); + ASSERT_NE(argc, 0); + + bundle* imported_b = bundle_import_from_argv(argc, argv); + bundle_free_exported_argv(argc, &argv); + std::unique_ptr b_ptr(imported_b, + bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(imported_b, nullptr); + + const char* val = bundle_get_val(imported_b, "KEY"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE"); +} + +TEST_F(BundleTest, bundle_import_from_argv_N) { + bundle* b = bundle_import_from_argv(0, nullptr); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_INVALID_PARAMETER); + ASSERT_EQ(b, nullptr); +} + +TEST_F(BundleTest, bundle_compare_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle* b_dup = bundle_dup(b); + std::unique_ptr b_ptr(b_dup, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(b_dup, nullptr); + + ret = bundle_compare(b, b_dup); + ASSERT_EQ(ret, 0); +} + +TEST_F(BundleTest, bundle_compare_N) { + int ret = bundle_compare(nullptr, nullptr); + ASSERT_EQ(ret, -1); + + bundle* b = GetHandle(); + ret = bundle_add_str(b, "KEY", "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + bundle* b_dup = bundle_dup(b); + std::unique_ptr b_ptr(b_dup, bundle_free); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(b_dup, nullptr); + + ret = bundle_del(b, "KEY"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_compare(b, b_dup); + ASSERT_EQ(ret, 1); +} + +TEST_F(BundleTest, bundle_set_str_array_element_P) { + bundle* b = GetHandle(); + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + int ret = bundle_add_str_array(b, "KEY", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_set_str_array_element(b, "KEY", 1, "VALUE3"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + int len = 0; + const char** val_array = bundle_get_str_array(b, "KEY", &len); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val_array, nullptr); + ASSERT_NE(len, 0); + ASSERT_EQ(std::string(val_array[0]), "VALUE1"); + ASSERT_EQ(std::string(val_array[1]), "VALUE3"); +} + +TEST_F(BundleTest, bundle_set_str_array_element_N) { + int ret = bundle_set_str_array_element(nullptr, nullptr, 0, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + ret = bundle_set_str_array_element(b, "KEY", 0, "VALUE"); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_NOT_AVAILABLE); +} + +TEST_F(BundleTest, bundle_add_byte_array_P) { + bundle* b = GetHandle(); + int ret = bundle_add_byte_array(b, "KEY", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); +} + +TEST_F(BundleTest, bundle_add_byte_array_N) { + int ret = bundle_add_byte_array(nullptr, nullptr, 0); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + ret = bundle_add_byte_array(b, "KEY", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_add_byte_array(b, "KEY", 3); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_EXISTS); +} + +TEST_F(BundleTest, bundle_init_byte_array_P) { + bundle* b = GetHandle(); + int ret = bundle_init_byte_array(b, "KEY", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); +} + +TEST_F(BundleTest, bundle_init_byte_array_N) { + int ret = bundle_init_byte_array(nullptr, nullptr, 0); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + ret = bundle_init_byte_array(b, "KEY", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = bundle_init_byte_array(b, "KEY", 3); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_EXISTS); +} + +TEST_F(BundleTest, bundle_get_byte_array_P) { + bundle* b = GetHandle(); + int ret = bundle_add_byte_array(b, "KEY", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_set_byte_array_element(b, "KEY", 0, "VALUE1", sizeof("VALUE1")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_set_byte_array_element(b, "KEY", 1, "VALUE2", sizeof("VALUE2")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + void** bytes_array = nullptr; + unsigned int len = 0; + unsigned int* array_element_size = nullptr; + ret = bundle_get_byte_array(b, "KEY", &bytes_array, &len, + &array_element_size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(bytes_array, nullptr); + ASSERT_NE(len, 0); + ASSERT_NE(array_element_size, nullptr); + ASSERT_EQ(std::string(reinterpret_cast(bytes_array[0])), "VALUE1"); + ASSERT_EQ(std::string(reinterpret_cast(bytes_array[1])), "VALUE2"); + ASSERT_EQ(array_element_size[0], sizeof("VALUE1")); + ASSERT_EQ(array_element_size[1], sizeof("VALUE2")); +} + +TEST_F(BundleTest, bundle_get_byte_array_N) { + int ret = bundle_get_byte_array(nullptr, nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + void** bytes_array = nullptr; + unsigned int len = 0; + unsigned int* array_element_size = nullptr; + bundle* b = GetHandle(); + ret = bundle_get_byte_array(b, "KEY", &bytes_array, &len, + &array_element_size); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_NOT_AVAILABLE); +} + +TEST_F(BundleTest, bundle_set_byte_array_element_P) { + bundle* b = GetHandle(); + int ret = bundle_add_byte_array(b, "KEY", 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_set_byte_array_element(b, "KEY", 0, "VALUE1", sizeof("VALUE1")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ret = bundle_set_byte_array_element(b, "KEY", 1, "VALUE2", sizeof("VALUE2")); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + void** bytes_array = nullptr; + unsigned int len = 0; + unsigned int* array_element_size = nullptr; + ret = bundle_get_byte_array(b, "KEY", &bytes_array, &len, + &array_element_size); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(bytes_array, nullptr); + ASSERT_NE(len, 0); + ASSERT_NE(array_element_size, nullptr); + ASSERT_EQ(std::string(reinterpret_cast(bytes_array[0])), "VALUE1"); + ASSERT_EQ(std::string(reinterpret_cast(bytes_array[1])), "VALUE2"); + ASSERT_EQ(array_element_size[0], sizeof("VALUE1")); + ASSERT_EQ(array_element_size[1], sizeof("VALUE2")); +} + +TEST_F(BundleTest, bundle_set_byte_array_element_N) { + int ret = bundle_set_byte_array_element(nullptr, nullptr, 0, nullptr, 0); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); + + bundle* b = GetHandle(); + ret = bundle_set_byte_array_element(b, "KEY", 0, "VALUE", sizeof("VALUE")); + ASSERT_EQ(ret, BUNDLE_ERROR_KEY_NOT_AVAILABLE); +} + +TEST_F(BundleTest, bundle_to_json_P) { + bundle* b = GetHandle(); + int ret = bundle_add_str(b, "KEY1", "VALUE1"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + const char* str_array[] = { + "VALUE1", + "VALUE2", + }; + ret = bundle_add_str_array(b, "KEY2", str_array, 2); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + char* json = nullptr; + ret = bundle_to_json(b, &json); + std::unique_ptr json_ptr(json, std::free); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_NE(json, nullptr); + + bundle* json_b = nullptr; + ret = bundle_from_json(json, &json_b); + std::unique_ptr b_ptr(json_b, bundle_free); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + const char* val = bundle_get_val(json_b, "KEY1"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE1"); + + int len = 0; + const char** val_array = bundle_get_str_array(json_b, "KEY2", &len); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val_array, nullptr); + ASSERT_NE(len, 0); + ASSERT_EQ(std::string(val_array[0]), "VALUE1"); + ASSERT_EQ(std::string(val_array[1]), "VALUE2"); +} + +TEST_F(BundleTest, bundle_to_json_N) { + int ret = bundle_to_json(nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); +} + +TEST_F(BundleTest, bundle_from_json_P) { + const char json[] = "{\"KEY1\":\"VALUE1\",\"KEY2\":[\"VALUE0\",\"VALUE1\"]}"; + bundle* json_b = nullptr; + int ret = bundle_from_json(json, &json_b); + std::unique_ptr b_ptr(json_b, bundle_free); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + const char* val = bundle_get_val(json_b, "KEY1"); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val, nullptr); + ASSERT_EQ(std::string(val), "VALUE1"); + + int len = 0; + const char** val_array = bundle_get_str_array(json_b, "KEY2", &len); + ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); + ASSERT_NE(val_array, nullptr); + ASSERT_NE(len, 0); + ASSERT_EQ(std::string(val_array[0]), "VALUE0"); + ASSERT_EQ(std::string(val_array[1]), "VALUE1"); } -TEST(Bundle, IsEmpty) { - Bundle bundle; - EXPECT_TRUE(bundle.IsEmpty()); - bundle.Add("TestKey1", "TestVal"); - EXPECT_FALSE(bundle.IsEmpty()); +TEST_F(BundleTest, bundle_from_json_N) { + int ret = bundle_from_json(nullptr, nullptr); + ASSERT_EQ(ret, BUNDLE_ERROR_INVALID_PARAMETER); } diff --git a/unit_tests/src/test_bundle_cpp.cc b/unit_tests/src/test_bundle_cpp.cc new file mode 100644 index 0000000..97ee62b --- /dev/null +++ b/unit_tests/src/test_bundle_cpp.cc @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019 - 2020 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 "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); + } +} + +TEST(Bundle, IsEmpty) { + Bundle bundle; + EXPECT_TRUE(bundle.IsEmpty()); + bundle.Add("TestKey1", "TestVal"); + EXPECT_FALSE(bundle.IsEmpty()); +} diff --git a/unit_tests/src/test_main.cc b/unit_tests/src/test_main.cc index 22cae75..a3e19d3 100644 --- a/unit_tests/src/test_main.cc +++ b/unit_tests/src/test_main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2019 - 2020 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.