Refactor Bundle 10/237310/6
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 29 Jun 2020 05:10:31 +0000 (14:10 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 29 Jun 2020 10:12:32 +0000 (19:12 +0900)
Change-Id: I64565f92a4d204198e07cf3ef6c50e2b66717c9b
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
32 files changed:
CMakeLists.txt
include/SLP_bundle_PG.h
include/bundle.h
include/bundle_cpp.h
include/bundle_internal.h
packaging/bundle.spec
src/bundle-internal.cc [new file with mode: 0644]
src/bundle-internal.h [new file with mode: 0644]
src/bundle.c [deleted file]
src/bundle_cpp.cc
src/bundle_cpp_implementation.h
src/bundle_json.c [deleted file]
src/bundle_log.h [deleted file]
src/exception-internal.h [new file with mode: 0644]
src/export-api-internal.h [moved from src/bundle_private.h with 58% similarity]
src/json-internal.cc [new file with mode: 0644]
src/json-internal.h [new file with mode: 0644]
src/key-info-internal.cc [new file with mode: 0644]
src/key-info-internal.h [new file with mode: 0644]
src/keyval.c [deleted file]
src/keyval.h [deleted file]
src/keyval_array.c [deleted file]
src/keyval_array.h [deleted file]
src/keyval_type.c [deleted file]
src/keyval_type.h [deleted file]
src/log-private.h [new file with mode: 0644]
src/stub.cc [new file with mode: 0644]
tools/check-coding-style [new file with mode: 0755]
unit_tests/CMakeLists.txt
unit_tests/src/test_bundle.cc
unit_tests/src/test_bundle_cpp.cc [new file with mode: 0644]
unit_tests/src/test_main.cc

index 631c50f..0eaa0a8 100644 (file)
@@ -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()
index a6b316f..2420441 100644 (file)
@@ -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.
index ada3158..bdd6ff2 100644 (file)
@@ -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.
index bcab268..241fa98 100644 (file)
@@ -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.
index a1b8676..0fb5f68 100644 (file)
@@ -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
index 94964a6..43797c2 100644 (file)
@@ -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 (file)
index 0000000..12fea42
--- /dev/null
@@ -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 <errno.h>
+#include <glib.h>
+
+#include <cstring>
+
+#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<KeyInfo> 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<unsigned char> value) {
+  auto iter = map_.find(key);
+  if (iter == map_.end())
+    THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
+
+  iter->second->SetValue(index, value);
+}
+
+std::shared_ptr<KeyInfo>& 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<unsigned char> 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<char*>(
+      g_compute_checksum_for_string(G_CHECKSUM_MD5,
+        reinterpret_cast<gchar*>(&bytes[0]),
+        static_cast<gssize>(bytes.size())));
+  if (checksum == nullptr)
+    THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
+
+  std::unique_ptr<char, decltype(std::free)*> ptr(checksum, std::free);
+  unsigned char* p = reinterpret_cast<unsigned char*>(checksum);
+  bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH);
+
+  char* encoded_data = reinterpret_cast<char*>(
+      g_base64_encode(
+        reinterpret_cast<guchar*>(&bytes[0]),
+        reinterpret_cast<gsize>(bytes.size())));
+  if (encoded_data == nullptr)
+    THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
+
+  return reinterpret_cast<unsigned char*>(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<unsigned char[]> d_ptr(d_str);
+  gint state = 0;
+  guint save = 0;
+  unsigned int d_len_raw = g_base64_decode_step(reinterpret_cast<char*>(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<char[]> extract_ptr(extract_checksum);
+  strncpy(extract_checksum, reinterpret_cast<char*>(d_str), CHECKSUM_LENGTH);
+  extract_checksum[CHECKSUM_LENGTH] = '\0';
+
+  char* compute_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
+      reinterpret_cast<char*>(d_str + CHECKSUM_LENGTH),
+      d_len_raw - CHECKSUM_LENGTH);
+  if (compute_checksum == nullptr)
+    return BUNDLE_ERROR_OUT_OF_MEMORY;
+
+  std::unique_ptr<char, decltype(std::free)*> 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<unsigned char> bytes(d_r, d_r + d_len);
+
+  while (reader < bytes.size()) {
+    std::size_t total_size = -1;
+    unsigned char* p = reinterpret_cast<unsigned char*>(&total_size);
+    std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p);
+
+    std::vector<unsigned char> encoded_bytes;
+    std::copy(&bytes[reader], &bytes[reader] + total_size,
+        std::back_inserter(encoded_bytes));
+    reader += total_size;
+
+    auto key_info = std::shared_ptr<KeyInfo>(
+        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<std::string, std::shared_ptr<KeyInfo>>& Bundle::GetMap() {
+  return map_;
+}
+
+std::vector<std::string> Bundle::Export() {
+  std::vector<std::string> 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<unsigned char*>(&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<char, decltype(std::free)*> 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<unsigned char*>(argv[idx +1]);
+      auto len = strlen(argv[idx + 1]) + 1;
+      std::vector<unsigned char> value;
+      std::copy(p, p + len, std::back_inserter(value));
+      auto key_info = std::shared_ptr<KeyInfo>(
+          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<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
+
+    if (out_len < sizeof(std::size_t))
+      continue;
+
+    auto* p = reinterpret_cast<unsigned char*>(bytes);
+    std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
+    auto key_info = std::shared_ptr<KeyInfo>(
+        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 (file)
index 0000000..c73e5e2
--- /dev/null
@@ -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 <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#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<KeyInfo> key_info);
+  void Set(const std::string& key, int index, std::vector<unsigned char> value);
+
+  std::shared_ptr<KeyInfo>& Get(const std::string& key);
+  int GetSize();
+  int GetType(const std::string& key);
+
+  unsigned char* Encode();
+  const std::map<std::string, std::shared_ptr<KeyInfo>>& GetMap();
+  std::vector<std::string> Export();
+
+ private:
+  int Decode(unsigned char* raw, int size);
+  int Import(int argc, char** argv);
+
+ private:
+  std::map<std::string, std::shared_ptr<KeyInfo>> map_;
+};
+
+}  // namespace internal
+}  // namespace tizen_base
+
+#endif  // BUNDLE_INTERNAL_H_
diff --git a/src/bundle.c b/src/bundle.c
deleted file mode 100644 (file)
index 0ffa3fb..0000000
+++ /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 <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#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);
-}
index 6d1163c..f23f4d6 100644 (file)
@@ -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.
  * limitations under the License.
  */
 
-#include <dlog.h>
-
 #include <memory>
 
-#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)
index 71bce84..907b9de 100644 (file)
@@ -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 <memory>
 #include <list>
 
-#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 (file)
index 38be1a4..0000000
+++ /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 <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <json-glib/json-glib.h>
-
-#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 (file)
index b3bda77..0000000
+++ /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 <dlog/dlog.h>
-
-#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/exception-internal.h b/src/exception-internal.h
new file mode 100644 (file)
index 0000000..2020fbe
--- /dev/null
@@ -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 <string>
+#include <exception>
+
+#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_
similarity index 58%
rename from src/bundle_private.h
rename to src/export-api-internal.h
index 486d513..cd0299d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 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.
  * limitations under the License.
  */
 
-#ifndef __BUNDLE_PRIVATE_H__
-#define __BUNDLE_PRIVATE_H__
+#ifndef EXPORT_API_INTERNAL_H_
+#define EXPORT_API_INTERNAL_H_
 
-#ifdef API
-#undef API
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
 #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__ */
+#endif  // EXPORT_API_INTERNAL_H_
diff --git a/src/json-internal.cc b/src/json-internal.cc
new file mode 100644 (file)
index 0000000..bb63639
--- /dev/null
@@ -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<JsonParser, decltype(g_object_unref)*> 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<JsonObject, decltype(json_object_unref)*> 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<const char*>(reinterpret_cast<char*>(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<const char*>(
+            reinterpret_cast<char*>(
+              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<JsonNode, decltype(json_node_free)*> 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<JsonGenerator, decltype(g_object_unref)*> 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<Bundle*>(user_data);
+  std::shared_ptr<KeyInfo> 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<std::vector<unsigned char>> 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<unsigned char*>(const_cast<char*>(val));
+      std::vector<unsigned char> 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<unsigned char*>(const_cast<char*>(val));
+    std::vector<unsigned char> 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 (file)
index 0000000..61572da
--- /dev/null
@@ -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 <glib.h>
+#include <json-glib/json-glib.h>
+
+#include <memory>
+#include <string>
+
+#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 (file)
index 0000000..155a65a
--- /dev/null
@@ -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 <cstring>
+
+#include "key-info-internal.h"
+#include "log-private.h"
+
+namespace tizen_base {
+namespace internal {
+
+KeyInfo::KeyInfo(int type, std::string key,
+    std::vector<unsigned char> value)
+  : type_(type),
+    key_(std::move(key)) {
+  SetValue(value);
+}
+
+KeyInfo::KeyInfo(int type, std::string key,
+    std::vector<std::vector<unsigned char>> values)
+  : type_(type),
+    key_(std::move(key)) {
+  SetValues(values);
+}
+
+KeyInfo::KeyInfo(std::vector<unsigned char> 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<std::unique_ptr<unsigned char[]>>& KeyInfo::GetValues() {
+  return values_;
+}
+
+const std::vector<std::size_t>& KeyInfo::GetValuesSize() {
+  return values_size_;
+}
+
+void KeyInfo::SetValue(const std::vector<unsigned char>& 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<std::vector<unsigned char>>& 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<unsigned char> KeyInfo::Encode() {
+  std::size_t encoded_size = GetEncodedSize();
+  if (encoded_size == 0)
+    return {};
+
+  std::vector<unsigned char> bytes;
+
+  // total size
+  unsigned char* p = reinterpret_cast<unsigned char*>(&encoded_size);
+  std::copy(p, p + sizeof(encoded_size), std::back_inserter(bytes));
+
+  // type
+  p = reinterpret_cast<unsigned char*>(&type_);
+  std::copy(p, p + sizeof(type_), std::back_inserter(bytes));
+
+  // key size
+  std::size_t key_length = key_.length() + 1;
+  p = reinterpret_cast<unsigned char*>(&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<unsigned char*>(&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<unsigned char*>(&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<unsigned char>& 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<unsigned char*>(&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<unsigned char*>(&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<unsigned char*>(&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<unsigned char> key(&bytes[reader], &bytes[reader] + key_size);
+  p = reinterpret_cast<unsigned char*>(&key[0]);
+  key_ = std::string(reinterpret_cast<char*>(p));
+  reader += key_size;
+
+  // values size
+  std::size_t values_size = 0;
+  if ((reader + sizeof(values_size)) > bytes.size())
+    return;
+
+  p = reinterpret_cast<unsigned char*>(&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<unsigned char*>(&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<unsigned char>& 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 (file)
index 0000000..217371d
--- /dev/null
@@ -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 <string>
+#include <vector>
+#include <memory>
+
+namespace tizen_base {
+namespace internal {
+
+class KeyInfo {
+ public:
+  KeyInfo(int type, std::string key,
+          std::vector<unsigned char> value);
+  KeyInfo(int type, std::string key,
+          std::vector<std::vector<unsigned char>> values);
+  explicit KeyInfo(std::vector<unsigned char> 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<std::unique_ptr<unsigned char[]>>& GetValues();
+  const std::vector<std::size_t>& GetValuesSize();
+  std::vector<unsigned char> Encode();
+
+  void SetValue(int index, const std::vector<unsigned char>& value);
+  int GetSize() const;
+
+ private:
+  std::size_t GetEncodedSize();
+  void SetValuesSize();
+  void SetValue(const std::vector<unsigned char>& value);
+  void SetValues(const std::vector<std::vector<unsigned char>>& values);
+  void Decode(const std::vector<unsigned char>& bytes);
+
+ private:
+  int type_;
+  std::string key_;
+  std::vector<std::unique_ptr<unsigned char[]>> values_;
+  std::vector<std::size_t> 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 (file)
index 6be41a2..0000000
+++ /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 <stdlib.h>
-
-#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 (file)
index bd8441b..0000000
+++ /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 <stddef.h>
-
-#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 (file)
index 843cd7b..0000000
+++ /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 <stdlib.h>
-#include <string.h>
-
-#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 (file)
index dd23946..0000000
+++ /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 (file)
index 8365c7c..0000000
+++ /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 <stddef.h>
-
-#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 (file)
index 786cf1c..0000000
+++ /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 <stddef.h>
-#include <string.h>
-
-#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 (file)
index 0000000..29e99da
--- /dev/null
@@ -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 <dlog.h>
+
+#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 (file)
index 0000000..aff0955
--- /dev/null
@@ -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 <tizen.h>
+#include <glib.h>
+
+#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<bundle*>(h);
+}
+
+extern "C" EXPORT_API int bundle_free(bundle* b) {
+  if (b == nullptr)
+    return BUNDLE_ERROR_INVALID_PARAMETER;
+
+  auto* h = reinterpret_cast<Bundle*>(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<Bundle*>(b);
+  std::vector<unsigned char> value(str, str + (strlen(str) + 1));
+  std::shared_ptr<KeyInfo> 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<Bundle*>(b);
+  std::shared_ptr<KeyInfo> 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<std::unique_ptr<unsigned char[]>&>(values[0]);
+  *str = reinterpret_cast<char*>(&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<Bundle*>(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<Bundle*>(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<Bundle*>(b);
+  for (const auto& kv : h->GetMap()) {
+    auto& key_info = kv.second;
+    auto& values = key_info->GetValues();
+    auto& value = const_cast<std::unique_ptr<unsigned char[]>&>(values[0]);
+    auto* val = reinterpret_cast<char*>(&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<Bundle*>(b);
+  for (const auto& kv : h->GetMap()) {
+    auto& key_info = kv.second;
+    callback(key_info->GetKey().c_str(), key_info->GetType(),
+        reinterpret_cast<bundle_keyval_t*>(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<KeyInfo*>(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<KeyInfo*>(kv);
+  auto& values = key_info->GetValues();
+  auto& value = const_cast<std::unique_ptr<unsigned char[]>&>(values[0]);
+  *val = reinterpret_cast<void*>(&value[0]);
+  auto& values_size = key_info->GetValuesSize();
+  *size = reinterpret_cast<size_t>(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<KeyInfo*>(kv);
+  auto& values = const_cast<std::vector<std::unique_ptr<unsigned char[]>>&>(
+      key_info->GetValues());
+  auto& values_size = const_cast<std::vector<std::size_t>&>(
+      key_info->GetValuesSize());
+  *array_val = reinterpret_cast<void**>(&values[0]);
+  *array_len = reinterpret_cast<unsigned int>(values.size());
+  *array_item_size = reinterpret_cast<size_t*>(&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<bundle_keyval_t*>(kv);
+  auto* key_info = reinterpret_cast<KeyInfo*>(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<bundle_keyval_t*>(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<KeyInfo*>(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<Bundle*>(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<bundle*>(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<Bundle*>(b);
+  *raw = reinterpret_cast<bundle_raw*>(h->Encode());
+  *len = strlen(reinterpret_cast<char*>(*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<bundle_raw*>(r);
+    b = new (std::nothrow) Bundle(static_cast<unsigned char*>(raw), data_size);
+  } catch (Exception& e) {
+    set_last_result(e.GetErrorCode());
+    return nullptr;
+  }
+
+  set_last_result(BUNDLE_ERROR_NONE);
+  return reinterpret_cast<bundle*>(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<Bundle*>(b);
+  std::shared_ptr<KeyInfo> 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<Bundle*>(b);
+  std::vector<std::vector<unsigned char>> values(len);
+  if (str_array) {
+    for (int i = 0; i < len; ++i) {
+      std::vector<unsigned char> value(str_array[i],
+          str_array[i] + (strlen(str_array[i]) + 1));
+      values[i] = std::move(value);
+    }
+  }
+
+  std::shared_ptr<KeyInfo> 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<Bundle*>(b);
+  std::shared_ptr<KeyInfo> 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<std::vector<std::unique_ptr<unsigned char[]>>&>(
+      key_info->GetValues());
+  auto** values = reinterpret_cast<unsigned char**>(&raw_values[0]);
+  *len = static_cast<int>(raw_values.size());
+
+  set_last_result(BUNDLE_ERROR_NONE);
+  return const_cast<const char**>(reinterpret_cast<char**>(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<Bundle*>(b);
+  auto* p = reinterpret_cast<const unsigned char*>(bytes);
+  std::vector<unsigned char> value(p, p + size);
+
+  std::shared_ptr<KeyInfo> 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<Bundle*>(b);
+  std::shared_ptr<KeyInfo> 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<std::vector<std::unique_ptr<unsigned char[]>>&>(
+      key_info->GetValues());
+  auto& value = values[0];
+  *bytes = reinterpret_cast<void*>(&value[0]);
+  auto& values_size = key_info->GetValuesSize();
+  *size = reinterpret_cast<size_t>(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<Bundle*>(b);
+  std::vector<std::string> 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<char**>(
+      calloc(argc + 1, sizeof(char*)));
+  if (exported_argv == nullptr) {
+    set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
+    return -1;
+  }
+
+  exported_argv[1] = const_cast<char*>(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<bundle*>(b);
+}
+
+extern "C" EXPORT_API int bundle_compare(bundle* b1, bundle* b2) {
+  if (b1 == nullptr || b2 == nullptr)
+    return -1;
+
+  auto* h1 = reinterpret_cast<Bundle*>(b1);
+  auto* h2 = reinterpret_cast<Bundle*>(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<unsigned char*>(const_cast<char*>(val));
+  std::vector<unsigned char> value(p, p + len);
+
+  auto* h = reinterpret_cast<Bundle*>(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<Bundle*>(b);
+  std::vector<std::vector<unsigned char>> values(len);
+  auto key_info = std::shared_ptr<KeyInfo>(
+      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<Bundle*>(b);
+  std::shared_ptr<KeyInfo> 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<std::vector<std::unique_ptr<unsigned char[]>>&>(
+      key_info->GetValues());
+  auto** values = reinterpret_cast<unsigned char**>(&raw_values[0]);
+  *bytes_array = reinterpret_cast<void**>(values);
+  *len = reinterpret_cast<unsigned int>(raw_values.size());
+
+  auto& raw_values_size = const_cast<std::vector<std::size_t>&>(
+      key_info->GetValuesSize());
+  *array_element_size = reinterpret_cast<unsigned int*>(&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<unsigned char*>(const_cast<void*>(bytes));
+  std::vector<unsigned char> value(p, p + size);
+
+  auto* h = reinterpret_cast<Bundle*>(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<Bundle*>(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<bundle*>(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 (executable)
index 0000000..fd60481
--- /dev/null
@@ -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
index f96ee7e..064f946 100644 (file)
@@ -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}
 )
 
index c94b080..6bde750 100644 (file)
@@ -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.
 #include <iostream>
 #include <stdexcept>
 
-#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<bundle, decltype(bundle_free)*> 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<unsigned char> 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<int*>(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<void*>(&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<int*>(user_data);
+        if (type == BUNDLE_TYPE_STR) {
+          void* val = nullptr;
+          size_t size = 0;
+          int ret = bundle_keyval_get_basic_val(
+              const_cast<bundle_keyval_t*>(kv), &val, &size);
+          if (ret != BUNDLE_ERROR_NONE)
+            return;
 
-  EXPECT_EQ(bundle.GetCount(), 3);
+          std::string value(reinterpret_cast<char*>(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<void*>(&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<bool*>(user_data);
+        if (type == BUNDLE_TYPE_STR) {
+          int keyval_type = bundle_keyval_get_type(
+              const_cast<bundle_keyval_t*>(kv));
+          ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+          ASSERT_EQ(keyval_type, type);
+          *matched = true;
+        }
+      }, reinterpret_cast<void*>(&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<bool*>(user_data);
+        if (type == BUNDLE_TYPE_STR_ARRAY) {
+          int ret = bundle_keyval_type_is_array(
+              const_cast<bundle_keyval_t*>(kv));
+          ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+          ASSERT_EQ(ret, 1);
+          *is_array = true;
+        }
+      }, reinterpret_cast<void*>(&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<bool*>(user_data);
+        if (std::string(key) == "KEY") {
+          int ret = bundle_keyval_type_is_array(
+              const_cast<bundle_keyval_t*>(kv));
+          ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+          ASSERT_EQ(ret, 0);
+          if (ret == 1)
+            *is_array = true;
+        }
+      }, reinterpret_cast<void*>(&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<bool*>(user_data);
+        int ret = bundle_keyval_type_is_measurable(
+              const_cast<bundle_keyval_t*>(kv));
+        ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+        ASSERT_EQ(ret, 1);
+        *is_measurable = true;
+      }, reinterpret_cast<void*>(&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<bool*>(user_data);
+        if (std::string(key) == "KEY") {
+          int ret = bundle_keyval_type_is_measurable(
+              const_cast<bundle_keyval_t*>(kv));
+          ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+          ASSERT_EQ(ret, 0);
+          if (ret == 1)
+            *is_measurable = true;
+        }
+      }, reinterpret_cast<void*>(&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<char**>(user_data);
+        if (std::string(key) == "KEY") {
+          size_t size = 0;
+          int ret = bundle_keyval_get_basic_val(
+              const_cast<bundle_keyval_t*>(kv),
+              reinterpret_cast<void**>(val),
+              &size);
+          ASSERT_EQ(ret, BUNDLE_ERROR_NONE);
+        }
+      }, reinterpret_cast<void*>(&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<char***>(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<bundle_keyval_t*>(kv),
+              reinterpret_cast<void***>(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<void*>(&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<bundle_keyval_t**>(
+            user_data);
+        *kv_dup = bundle_keyval_dup(const_cast<bundle_keyval_t*>(kv));
+        ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+      }, reinterpret_cast<void*>(&kv));
+  std::unique_ptr<bundle_keyval_t, decltype(bundle_keyval_free)*> 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<void**>(&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<bundle_keyval_t**>(
+            user_data);
+        *kv_dup = bundle_keyval_dup(const_cast<bundle_keyval_t*>(kv));
+        ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+      }, reinterpret_cast<void*>(&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<bundle, decltype(bundle_free)*> 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<bundle_raw*, decltype(bundle_free_encoded_rawdata)*> 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<bundle, decltype(bundle_free)*> 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<bundle_raw*, decltype(bundle_free_encoded_rawdata)*> 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<bundle, decltype(bundle_free)*> 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<bundle_raw*, decltype(bundle_free_encoded_rawdata)*> 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<bundle, decltype(bundle_free)*> 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<bundle_raw*, decltype(bundle_free_encoded_rawdata)*> 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<bundle, decltype(bundle_free)*> 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<char*>(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<char*>(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<bundle, decltype(bundle_free)*> 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<bundle, decltype(bundle_free)*> 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<bundle, decltype(bundle_free)*> 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<bundle, decltype(bundle_free)*> 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<char*>(bytes_array[0])), "VALUE1");
+  ASSERT_EQ(std::string(reinterpret_cast<char*>(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<char*>(bytes_array[0])), "VALUE1");
+  ASSERT_EQ(std::string(reinterpret_cast<char*>(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<char, decltype(std::free)*> 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<bundle, decltype(bundle_free)*> 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<bundle, decltype(bundle_free)*> 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 (file)
index 0000000..97ee62b
--- /dev/null
@@ -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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <iostream>
+#include <stdexcept>
+
+#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<unsigned char> v = { 0, 1, 2, 3};
+  bundle.Add("TestKey", v);
+  auto v2 = bundle.GetByte("TestKey");
+
+  EXPECT_EQ(v2.size(), 4);
+  EXPECT_EQ(v2[0], 0);
+  EXPECT_EQ(v2[1], 1);
+  EXPECT_EQ(v2[2], 2);
+  EXPECT_EQ(v2[3], 3);
+}
+
+TEST(Bundle, AddStringArrayGetStringArray) {
+  Bundle bundle;
+  bundle.Add("TestKey", { "TestVal1", "TestVal2", "TestVal3" });
+
+  auto v = bundle.GetStringArray("TestKey");
+
+  EXPECT_EQ(v.size(), 3);
+  EXPECT_EQ(v[0], "TestVal1");
+  EXPECT_EQ(v[1], "TestVal2");
+  EXPECT_EQ(v[2], "TestVal3");
+}
+
+TEST(Bundle, ToRaw) {
+  Bundle bundle;
+  bundle.Add("TestKey", "TestVal");
+
+  auto r = bundle.ToRaw();
+  Bundle b2(std::move(r));
+  EXPECT_EQ(bundle.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, GetCount) {
+  Bundle bundle;
+  bundle.Add("TestKey1", "TestVal1");
+  bundle.Add("TestKey2", "TestVal2");
+
+  EXPECT_EQ(bundle.GetCount(), 2);
+}
+
+TEST(Bundle, Delete) {
+  Bundle bundle;
+  int r = bundle.Add("TestKey1", "TestVal1");
+  EXPECT_EQ(r, 0);
+
+  r = bundle.Delete("TestKey1");
+  EXPECT_EQ(r, 0);
+
+  EXPECT_EQ(bundle.GetString("TestKey1"), "");
+}
+
+TEST(Bundle, GetKeys) {
+  Bundle bundle;
+  bundle.Add("TestKey1", "TestVal1");
+  bundle.Add("TestKey2", "TestVal2");
+  bundle.Add("TestKey3", "TestVal3");
+
+  auto v = bundle.GetKeys();
+
+  EXPECT_EQ(bundle.GetCount(), 3);
+
+  for (auto& i : v) {
+    EXPECT_EQ(i.GetType(), BUNDLE_TYPE_STR);
+  }
+}
+
+TEST(Bundle, GetKeysCopy) {
+  Bundle bundle;
+  bundle.Add("TestKey1", "TestVal1");
+  bundle.Add("TestKey2", "TestVal2");
+  bundle.Add("TestKey3", "TestVal3");
+
+  auto v = bundle.GetKeys();
+
+  EXPECT_EQ(bundle.GetCount(), 3);
+
+  for (auto& i : v) {
+    Bundle::KeyInfo copied = i;
+    EXPECT_EQ(copied.GetType(), BUNDLE_TYPE_STR);
+    EXPECT_EQ(copied.GetName(), i.GetName());
+  }
+}
+
+TEST(Bundle, GetKeysMove) {
+  Bundle bundle;
+  bundle.Add("TestKey1", "TestVal1");
+  bundle.Add("TestKey2", "TestVal2");
+  bundle.Add("TestKey3", "TestVal3");
+
+  auto v = bundle.GetKeys();
+
+  EXPECT_EQ(bundle.GetCount(), 3);
+
+  for (auto& i : v) {
+    string name = i.GetName();
+    Bundle::KeyInfo copied = move(i);
+    EXPECT_EQ(copied.GetType(), BUNDLE_TYPE_STR);
+    EXPECT_EQ(copied.GetName(), name);
+  }
+}
+
+TEST(Bundle, IsEmpty) {
+  Bundle bundle;
+  EXPECT_TRUE(bundle.IsEmpty());
+  bundle.Add("TestKey1", "TestVal");
+  EXPECT_FALSE(bundle.IsEmpty());
+}
index 22cae75..a3e19d3 100644 (file)
@@ -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.