Add Parcel Library 00/249500/13
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 14 Dec 2020 06:45:49 +0000 (15:45 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Wed, 23 Dec 2020 23:14:58 +0000 (08:14 +0900)
This library is only for appfw internally.

Adds:
 - parcel_create()
 - parcel_destroy()
 - parcel_clone()
 - parcel_burst_write()
 - parcel_burst_read()
 - parcel_write_bool()
 - parcel_write_byte()
 - parcel_write_uint16()
 - parcel_write_uint32()
 - parcel_write_uint64()
 - parcel_write_int16()
 - parcel_write_int32()
 - parcel_write_int64()
 - parcel_write_float()
 - parcel_write_double()
 - parcel_write_string()
 - parcel_write_bundle()
 - parcel_read_bool()
 - parcel_read_byte()
 - parcel_read_uint16()
 - parcel_read_uint32()
 - parcel_read_uint64()
 - parcel_read_int16()
 - parcel_read_int32()
 - parcel_read_int64()
 - parcel_read_float()
 - parcel_read_double()
 - parcel_read_string()
 - parcel_read_bundle()
 - parcel_reset_reader()
 - parcel_clear()
 - parcel_reset()
 - parcel_write()
 - parcel_read()
 - parcel_get_raw()

Change-Id: I322faee040ca95c4cb8e4b7356e33a9af5daeb8c
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
22 files changed:
CMakeLists.txt
packaging/bundle.spec
packaging/parcel.manifest [new file with mode: 0644]
parcel/CMakeLists.txt [new file with mode: 0644]
parcel/api/parcel.h [new file with mode: 0644]
parcel/common.hh [new file with mode: 0644]
parcel/log_private.hh [new file with mode: 0644]
parcel/parcel.cc [new file with mode: 0644]
parcel/parcel.hh [new file with mode: 0644]
parcel/parcel.pc.in [new file with mode: 0644]
parcel/parcel_implementation.hh [new file with mode: 0644]
parcel/parcelable.hh [new file with mode: 0644]
parcel/stub.cc [new file with mode: 0644]
tests/CMakeLists.txt [new file with mode: 0644]
tests/bundle_unittests/CMakeLists.txt [moved from unit_tests/CMakeLists.txt with 69% similarity]
tests/bundle_unittests/src/test_bundle.cc [moved from unit_tests/src/test_bundle.cc with 100% similarity]
tests/bundle_unittests/src/test_bundle_cpp.cc [moved from unit_tests/src/test_bundle_cpp.cc with 100% similarity]
tests/bundle_unittests/src/test_main.cc [moved from unit_tests/src/test_main.cc with 100% similarity]
tests/parcel_unittests/CMakeLists.txt [new file with mode: 0644]
tests/parcel_unittests/test_main.cc [new file with mode: 0644]
tests/parcel_unittests/test_parcel.cc [new file with mode: 0644]
tests/parcel_unittests/test_parcel_cpp.cc [new file with mode: 0644]

index 0eaa0a8..92b009e 100644 (file)
@@ -46,12 +46,21 @@ 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/)
 
+ADD_SUBDIRECTORY(parcel)
+ADD_DEPENDENCIES(parcel bundle)
+
 IF(NOT DEFINED MINIMUM_BUILD)
 ENABLE_TESTING()
 SET(BUNDLE_UNITTESTS bundle_unittests)
 ADD_TEST(NAME ${BUNDLE_UNITTESTS} COMMAND ${BUNDLE_UNITTESTS}
-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unit_tests)
+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/bundle_unittests)
 
-ADD_SUBDIRECTORY(unit_tests)
+ADD_SUBDIRECTORY(tests)
 ADD_DEPENDENCIES(bundle_unittests bundle)
+
+SET(PARCEL_UNITTESTS parcel_unittests)
+ADD_TEST(NAME ${PARCEL_UNITTESTS} COMMAND ${PARCEL_UNITTESTS}
+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/parcel_unittests)
+
+ADD_DEPENDENCIES(parcel_unittests parcel)
 ENDIF(NOT DEFINED MINIMUM_BUILD)
index 5dd1a66..d39d5c8 100644 (file)
@@ -6,6 +6,7 @@ Group:      System/Libraries
 License:    Apache-2.0
 Source0:        bundle-%{version}.tar.gz
 Source1001:     bundle.manifest
+Source1002:     parcel.manifest
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(dlog)
@@ -51,9 +52,38 @@ Group:      Application Framework/Testing
 Simple string key-val dictionary ADT gcov objects
 %endif
 
+#################################################
+## parcel
+#################################################
+%package -n parcel
+Summary:    Parcel Library
+Group:      Development/Libraries
+
+%description -n parcel
+Parcel Library
+
+%package -n parcel-devel
+Summary:    Parcel Library (devel)
+Group:      Development/Libraries
+Requires:   parcel = %{version}-%{release}
+
+%description -n parcel-devel
+Parcel Library (devel)
+
+#################################################
+# parcel-unittests
+#################################################
+%package -n parcel-unittests
+Summary:    GTest for parcel
+Group:      Development/Libraries
+
+%description -n parcel-unittests
+GTest for parcel
+
 %prep
 %setup -q -n %{name}-%{version}
 cp %{SOURCE1001} .
+cp %{SOURCE1002} .
 
 %build
 %if 0%{?gcov:1}
@@ -92,6 +122,12 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
 
 %postun -p /sbin/ldconfig
 
+%post -n parcel
+/sbin/ldconfig
+
+%postun -n parcel
+/sbin/ldconfig
+
 %post unittests
 %if 0%{?gcov:1}
 %{_bindir}/bundle_unittests
@@ -123,3 +159,20 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
 %files gcov
 %{_datadir}/gcov/*
 %endif
+
+#################################################
+# parcel
+#################################################
+%files -n parcel
+%manifest parcel.manifest
+%license LICENSE
+%{_libdir}/libparcel.so.*
+
+%files -n parcel-devel
+%manifest parcel.manifest
+%{_includedir}/*
+%{_libdir}/pkgconfig/parcel.pc
+%{_libdir}/libparcel.so
+
+%files -n parcel-unittests
+%{_bindir}/parcel_unittests
diff --git a/packaging/parcel.manifest b/packaging/parcel.manifest
new file mode 100644 (file)
index 0000000..017d22d
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+    <domain name="_"/>
+ </request>
+</manifest>
diff --git a/parcel/CMakeLists.txt b/parcel/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d8b9d2b
--- /dev/null
@@ -0,0 +1,51 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(parcel C CXX)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(pkgs REQUIRED dlog capi-base-common)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -flto -Wall -Werror -Winline")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++14")
+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}/api)
+
+AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/parcel PARCEL_SRCS)
+
+ADD_LIBRARY (${PROJECT_NAME} SHARED ${PARCEL_SRCS})
+
+SET_TARGET_PROPERTIES(parcel PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(parcel PROPERTIES VERSION "${VERSION}")
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIE")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-pie")
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} bundle)
+
+### Make pkgconfig file
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/parcel.pc.in
+  ${CMAKE_BINARY_DIR}/parcel.pc @ONLY)
+
+### Install
+INSTALL(TARGETS parcel DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(FILES ${CMAKE_BINARY_DIR}/parcel.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig/)
+
+SET(HEADER_PARCEL
+  common.hh
+  parcel.hh
+  parcelable.hh
+)
+
+FOREACH(hfile ${HEADER_PARCEL})
+  INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} DESTINATION include/parcel)
+ENDFOREACH(hfile)
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/api/parcel.h
+  DESTINATION include/parcel)
diff --git a/parcel/api/parcel.h b/parcel/api/parcel.h
new file mode 100644 (file)
index 0000000..886aa1a
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * 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 __PARCEL_H__
+#define __PARCEL_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <bundle.h>
+#include <tizen.h>
+
+/**
+ * @addtogroup CORE_LIB_PARCEL_MODULE
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief The parcel handle.
+ * @since_tizen 6.5
+ */
+typedef void *parcel_h;
+
+/**
+ * @brief The interface for converting data to/from a parcel.
+ * @since_tizen 6.5
+ */
+typedef struct {
+       void (*to)(parcel_h parcel, void *data);
+       void (*from)(parcel_h parcel, void *data);
+} parcelable_t;
+
+/**
+ * @brief Enumeration for error codes for a parcel.
+ * @since_tizen 6.5
+ */
+typedef enum {
+       PARCEL_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+       PARCEL_ERROR_ILLEGAL_BYTE_SEQ = TIZEN_ERROR_ILLEGAL_BYTE_SEQ, /**< Illegal byte sequence */
+       PARCEL_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+       PARCEL_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data available */
+       PARCEL_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+} parcel_error_e;
+
+/**
+ * @brief Creates a parcel handle.
+ * @since_tizen 6.5
+ * @remarks You MUST release @a parcel using parcel_destroy().
+ * @param[out] parcel The parcel handle that is newly created
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see parcel_destroy()
+ */
+int parcel_create(parcel_h *parcel);
+
+/**
+ * @brief Destroys a parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER
+ * @see parcel_create()
+ */
+int parcel_destroy(parcel_h parcel);
+
+/**
+ * @brief Creates and returns a copy of the given parcel handle.
+ * @since_tizen 6.5
+ * @remarks A newly created parcel should be destroyed by calling the parcel_destroy() if it is no longer needed.
+ * @param[in] parcel The parcel handle
+ * @param[out] If successful, a newly created parcel handle will be returned
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_destroy()
+ */
+int parcel_clone(parcel_h parcel, parcel_h *clone);
+
+/**
+ * @brief Writes bytes to the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] buf The array buffer to write
+ * @param[in] size The size of bytes to write
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_burst_read()
+ */
+int parcel_burst_write(parcel_h parcel, const void *buf, uint32_t size);
+
+/**
+ * @brief Reads bytes from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] buf The array buffer to read
+ * @param[in] size The size of bytes to read
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_burst_write()
+ */
+int parcel_burst_read(parcel_h parcel, void *buf, uint32_t size);
+
+/**
+ * @brief Writes a boolean value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The boolean value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_bool()
+ */
+int parcel_write_bool(parcel_h parcel, bool val);
+
+/**
+ * @brief Writes a byte value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The byte value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_uint8()
+ */
+int parcel_write_byte(parcel_h parcel, char val);
+
+/**
+ * @brief Writes an unsigned short value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The unsigned short value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_uint16()
+ */
+int parcel_write_uint16(parcel_h parcel, uint16_t val);
+
+/**
+ * @brief Writes an unsigned integer value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The unsigned integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_uint32()
+ */
+int parcel_write_uint32(parcel_h parcel, uint32_t val);
+
+/**
+ * @brief Writes an unsigned long long integer value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The unsigned long long interger value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_uint64()
+ */
+int parcel_write_uint64(parcel_h parcel, uint64_t val);
+
+/**
+ * @brief Writes a signed short value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The signed short value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_int16()
+ */
+int parcel_write_int16(parcel_h parcel, int16_t val);
+
+/**
+ * @brief Writes a signed integer value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The signed integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_int32()
+ */
+int parcel_write_int32(parcel_h parcel, int32_t val);
+
+/**
+ * @brief Writes a signed long long integer value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The signedi long long integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_int64()
+ */
+int parcel_write_int64(parcel_h parcel, int64_t val);
+
+/**
+ * @brief Writes a floating point value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The floating point value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCLE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_float()
+ */
+int parcel_write_float(parcel_h parcel, float val);
+
+/**
+ * @brief Writes a double precision floating point value into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] val The double precision floating point value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCLE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_double()
+ */
+int parcel_write_double(parcel_h parcel, double val);
+
+/**
+ * @brief Writes a string data into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] str The string data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_string()
+ */
+int parcel_write_string(parcel_h parcel, const char *str);
+
+/**
+ * @brief Writes a bundle data into the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] b The bundle data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read_bundle()
+ */
+int parcel_write_bundle(parcel_h parcel, bundle* b);
+
+/**
+ * @brief Reads a boolean value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The boolean value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_bool()
+ */
+int parcel_read_bool(parcel_h parcel, bool *val);
+
+/**
+ * @brief Reads a byte value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The byte value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_uint8()
+ */
+int parcel_read_byte(parcel_h parcel, char *val);
+
+/**
+ * @brief Reads an unsigned short value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The unsigned short value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_uint16()
+ */
+int parcel_read_uint16(parcel_h parcel, uint16_t *val);
+
+/**
+ * @brief Reads an unsigned integer value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The unsigned integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_uint32()
+ */
+int parcel_read_uint32(parcel_h parcel, uint32_t *val);
+
+/**
+ * @brief Reads an unsigned long long integer value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The unsigned long long integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_uint64()
+ */
+int parcel_read_uint64(parcel_h parcel, uint64_t *val);
+
+/**
+ * @brief Reads a signed short value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The signed short value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_int16()
+ */
+int parcel_read_int16(parcel_h parcel, int16_t *val);
+
+/**
+ * @brief Reads a signed integer value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The signed integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_int32()
+ */
+int parcel_read_int32(parcel_h parcel, int32_t *val);
+
+/**
+ * @brief Reads a signed long long integer value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The signed long long integer value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_int64()
+ */
+int parcel_read_int64(parcel_h parcel, int64_t *val);
+
+/**
+ * @brief Reads a floating point value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The floating point value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_uint8()
+ */
+int parcel_read_float(parcel_h parcel, float *val);
+
+/**
+ * @brief Reads a double precision floating point value from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The double precision floating point value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @see parcel_write_uint8()
+ */
+int parcel_read_double(parcel_h parcel, double *val);
+
+/**
+ * @brief Reads a string data from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] str The string data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @retval #PARCEL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see parcel_write_uint8()
+ */
+int parcel_read_string(parcel_h parcel, char **str);
+
+/**
+ * @brief Reads a bundle data from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[out] val The bundle data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PARCEL_ERROR_NO_DATA No data available
+ * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence
+ * @retval #PARCEL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see parcel_write_uint8()
+ */
+int parcel_read_bundle(parcel_h parcel, bundle **b);
+
+/**
+ * @brief Resets the reader pointer of the parcel handle to the start.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int parcel_reset_reader(parcel_h parcel);
+
+/**
+ * @brief Clears the data of the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int parcel_clear(parcel_h parcel);
+
+/**
+ * @brief Resets the data of the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] buf The array buffer to write
+ * @param[in] size The size of bytes to write
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int parcel_reset(parcel_h parcel, const void *buf, uint32_t size);
+
+/**
+ * @brief Writes the data using @a parcelable to the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] parcelable The interface to write the data into the parcel handle
+ * @param[in] data The user data which writes into the parcel handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_read()
+ */
+int parcel_write(parcel_h parcel, parcelable_t *parcelable, void *data);
+
+/**
+ * @brief Reads the data using @a parcelable from the parcel handle.
+ * @since_tizen 6.5
+ * @param[in] parcel The parcel handle
+ * @param[in] parcelable The interface to read the data from the parcel handle
+ * @param[in] data The user data which reads from the parcel handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see parcel_write()
+ */
+int parcel_read(parcel_h parcel, parcelable_t *parcelable, void *data);
+
+/**
+ * @brief Gets the raw data of the parcel handle.
+ * @since_tizen 6.5
+ * @remarks You MUST NOT release @a raw using free(). It's managed by platform.
+ * @param[in] parcel The parcel handle
+ * @param[out] raw The raw data
+ * @param[out] size The size of the raw data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int parcel_get_raw(parcel_h parcel, void **raw, uint32_t *size);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __PARCEL_H__ */
diff --git a/parcel/common.hh b/parcel/common.hh
new file mode 100644 (file)
index 0000000..91f3535
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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 PARCEL_COMMON_HH_
+#define PARCEL_COMMON_HH_
+
+#undef EXPORT
+#define EXPORT __attribute__((visibility("default")))
+
+#endif  // PARCEL_COMMON_HH_
diff --git a/parcel/log_private.hh b/parcel/log_private.hh
new file mode 100644 (file)
index 0000000..a005add
--- /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 PARCEL_LOG_PRIVATE_HH_
+#define PARCEL_LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "PARCEL"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif  // PARCEL_LOG_PRIVATE_HH_
diff --git a/parcel/parcel.cc b/parcel/parcel.cc
new file mode 100644 (file)
index 0000000..e310654
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/bundle_cpp.h"
+#include "parcel/common.hh"
+#include "parcel/log_private.hh"
+#include "parcel/parcel.hh"
+#include "parcel/parcel_implementation.hh"
+#include "parcel/parcelable.hh"
+
+namespace tizen_base {
+
+Parcel::Impl::Impl(Parcel* parent) : parent_(parent) {
+}
+
+Parcel::Impl::~Impl() = default;
+
+void Parcel::Impl::Write(const void* buf, uint32_t size) {
+  auto* p = reinterpret_cast<const uint8_t*>(buf);
+  std::copy(p, p + size, std::back_inserter(data_));
+}
+
+int Parcel::Impl::Read(void* buf, uint32_t size) {
+  if (data_.size() == 0)
+    return TIZEN_ERROR_NO_DATA;
+
+  if (reader_ + size > data_.size())
+    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+
+  auto* p = reinterpret_cast<uint8_t*>(buf);
+  std::copy(&data_[reader_], &data_[reader_] + size, p);
+  reader_ += size;
+  set_last_result(TIZEN_ERROR_NONE);
+  return TIZEN_ERROR_NONE;
+}
+
+const std::vector<uint8_t>& Parcel::Impl::GetRaw() {
+  return data_;
+}
+
+void Parcel::Impl::ResetReader() {
+  reader_ = 0;
+}
+
+void Parcel::Impl::Clear() {
+  data_.clear();
+  reader_ = 0;
+}
+
+void Parcel::Impl::Reset(const void* buf, uint32_t size) {
+  Clear();
+  Write(buf, size);
+}
+
+bool Parcel::Impl::IsEmpty() {
+  return data_.size() == 0;
+}
+
+void Parcel::Impl::WriteSize(uint32_t size) {
+  auto* p = reinterpret_cast<uint8_t*>(&size);
+  std::copy(p, p + sizeof(size), std::back_inserter(data_));
+}
+
+template <typename T>
+void Parcel::Impl::Write(T d) {
+  WriteSize(sizeof(T));
+  auto* p = reinterpret_cast<uint8_t*>(&d);
+  std::copy(p, p + sizeof(T), std::back_inserter(data_));
+}
+
+int Parcel::Impl::ReadSize(uint32_t* size) {
+  if (data_.size() == 0)
+    return TIZEN_ERROR_NO_DATA;
+
+  if (reader_ + sizeof(uint32_t) > data_.size())
+    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+
+  auto* p = reinterpret_cast<uint8_t*>(size);
+  std::copy(&data_[reader_], &data_[reader_] + sizeof(uint32_t), p);
+  reader_ += sizeof(uint32_t);
+  return TIZEN_ERROR_NONE;
+}
+
+template <typename T>
+int Parcel::Impl::Read(T* d) {
+  uint32_t size = 0;
+  int ret = ReadSize(&size);
+  if (ret != TIZEN_ERROR_NONE)
+    return ret;
+
+  if (size == 0 || size != sizeof(T))
+    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+
+  if (reader_ + size > data_.size())
+    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+
+  auto* p = reinterpret_cast<uint8_t*>(d);
+  std::copy(&data_[reader_], &data_[reader_] + size, p);
+  reader_ += size;
+  return TIZEN_ERROR_NONE;
+}
+
+Parcel::Parcel() : impl_(new Impl(this)) {
+}
+
+Parcel::Parcel(const void* buf, uint32_t size) : impl_(new Impl(this)) {
+  impl_->Write(buf, size);
+}
+
+Parcel::~Parcel() = default;
+
+Parcel::Parcel(const Parcel& p)
+  : impl_(new Impl(this)) {
+  std::copy(p.impl_->data_.begin(), p.impl_->data_.end(),
+      std::back_inserter(impl_->data_));
+  impl_->reader_ = p.impl_->reader_;
+}
+
+Parcel& Parcel::operator = (const Parcel& p) {
+  if (this != &p) {
+    std::copy(p.impl_->data_.begin(), p.impl_->data_.end(),
+        std::back_inserter(impl_->data_));
+    impl_->reader_ = p.impl_->reader_;
+  }
+  return *this;
+}
+
+Parcel::Parcel(Parcel&& p) noexcept {
+  impl_ = std::move(p.impl_);
+  impl_->parent_ = this;
+}
+
+Parcel& Parcel::operator = (Parcel&& p) noexcept {
+  if (this != &p) {
+    impl_->data_ = std::move(p.impl_->data_);
+    impl_->reader_ = p.impl_->reader_;
+    p.impl_->reader_ = 0;
+  }
+  return *this;
+}
+
+bool Parcel::IsEmpty() const noexcept {
+  return impl_->IsEmpty();
+}
+
+void Parcel::Write(const void* buf, uint32_t size) {
+  impl_->Write(buf, size);
+}
+
+int Parcel::Read(void* buf, uint32_t size) {
+  return impl_->Read(buf, size);
+}
+
+void Parcel::WriteBool(bool val) {
+  impl_->Write<bool>(val);
+}
+
+void Parcel::WriteByte(char val) {
+  impl_->Write<char>(val);
+}
+
+void Parcel::WriteUInt16(uint16_t val) {
+  impl_->Write<uint16_t>(val);
+}
+
+void Parcel::WriteUInt32(uint32_t val) {
+  impl_->Write<uint32_t>(val);
+}
+
+void Parcel::WriteUInt64(uint64_t val) {
+  impl_->Write<uint64_t>(val);
+}
+
+void Parcel::WriteInt16(int16_t val) {
+  impl_->Write<int16_t>(val);
+}
+
+void Parcel::WriteInt32(int32_t val) {
+  impl_->Write<int32_t>(val);
+}
+
+void Parcel::WriteInt64(int64_t val) {
+  impl_->Write<int64_t>(val);
+}
+
+void Parcel::WriteFloat(float val) {
+  impl_->Write<float>(val);
+}
+
+void Parcel::WriteDouble(double val) {
+  impl_->Write<double>(val);
+}
+
+void Parcel::WriteString(const std::string& str) {
+  impl_->WriteSize(str.length() + 1);
+  impl_->Write(str.c_str(), str.length() + 1);
+}
+
+void Parcel::WriteCString(const char* str) {
+  impl_->WriteSize(strlen(str) + 1);
+  impl_->Write(str, strlen(str) + 1);
+}
+
+void Parcel::WriteCBundle(bundle* b) {
+  bundle_raw* raw = nullptr;
+  int len = 0;
+  bundle_encode(b, &raw, &len);
+  auto ptr = std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free);
+
+  auto* p = reinterpret_cast<void*>(raw);
+  impl_->WriteSize(len + 1);
+  impl_->Write(p, len + 1);
+}
+
+void Parcel::WriteBundle(const Bundle& b) {
+  auto raw = const_cast<Bundle&>(b).ToRaw();
+  auto* p = reinterpret_cast<void*>(raw.first.get());
+  impl_->WriteSize(raw.second + 1);
+  impl_->Write(p, raw.second + 1);
+}
+
+int Parcel::ReadBool(bool* val) {
+  return impl_->Read<bool>(val);
+}
+
+int Parcel::ReadByte(char* val) {
+  return impl_->Read<char>(val);
+}
+
+int Parcel::ReadUInt16(uint16_t* val) {
+  return impl_->Read<uint16_t>(val);
+}
+
+int Parcel::ReadUInt32(uint32_t* val) {
+  return impl_->Read<uint32_t>(val);
+}
+
+int Parcel::ReadUInt64(uint64_t* val) {
+  return impl_->Read<uint64_t>(val);
+}
+
+int Parcel::ReadInt16(int16_t* val) {
+  return impl_->Read<int16_t>(val);
+}
+
+int Parcel::ReadInt32(int32_t* val) {
+  return impl_->Read<int32_t>(val);
+}
+
+int Parcel::ReadInt64(int64_t* val) {
+  return impl_->Read<int64_t>(val);
+}
+
+int Parcel::ReadFloat(float* val) {
+  return impl_->Read<float>(val);
+}
+
+int Parcel::ReadDouble(double* val) {
+  return impl_->Read<double>(val);
+}
+
+std::string Parcel::ReadString() {
+  uint32_t len = 0;
+  int ret = impl_->ReadSize(&len);
+  if (ret != TIZEN_ERROR_NONE) {
+    set_last_result(ret);
+    return {};
+  }
+
+  char* str = new (std::nothrow) char [len];
+  if (str == nullptr) {
+    set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
+    return {};
+  }
+
+  auto ptr = std::unique_ptr<char[]>(str);
+  ret = impl_->Read(str, len);
+  if (ret != TIZEN_ERROR_NONE) {
+    set_last_result(ret);
+    return {};
+  }
+
+  set_last_result(TIZEN_ERROR_NONE);
+  return std::string(str);
+}
+
+int Parcel::ReadCString(char** str) {
+  uint32_t len = 0;
+  int ret = impl_->ReadSize(&len);
+  if (ret != TIZEN_ERROR_NONE)
+    return ret;
+
+  char* val = static_cast<char*>(calloc(len, sizeof(char)));
+  if (val == nullptr)
+    return TIZEN_ERROR_OUT_OF_MEMORY;
+
+  ret = impl_->Read(val, len);
+  if (ret != TIZEN_ERROR_NONE) {
+    free(val);
+    return ret;
+  }
+
+  *str = val;
+  return TIZEN_ERROR_NONE;
+}
+
+int Parcel::ReadCBundle(bundle** b) {
+  uint32_t len = 0;
+  int ret = impl_->ReadSize(&len);
+  if (ret != TIZEN_ERROR_NONE)
+    return ret;
+
+  uint8_t* raw = new (std::nothrow) uint8_t [len];
+  if (raw == nullptr)
+    return TIZEN_ERROR_OUT_OF_MEMORY;
+
+  auto ptr = std::unique_ptr<uint8_t[]>(raw);
+  ret = impl_->Read(raw, len);
+  if (ret != TIZEN_ERROR_NONE)
+    return ret;
+
+  *b = bundle_decode(reinterpret_cast<bundle_raw*>(raw), len);
+  if (*b == nullptr)
+    return get_last_result();
+
+  return TIZEN_ERROR_NONE;
+}
+
+Bundle Parcel::ReadBundle() {
+  uint32_t len = 0;
+  int ret = impl_->ReadSize(&len);
+  if (ret != TIZEN_ERROR_NONE) {
+    set_last_result(ret);
+    return {};
+  }
+
+  uint8_t* raw = new (std::nothrow) uint8_t [len];
+  if (raw == nullptr) {
+    set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
+    return {};
+  }
+
+  auto ptr = std::unique_ptr<uint8_t[]>(raw);
+  ret = impl_->Read(raw, len);
+  if (ret != TIZEN_ERROR_NONE) {
+    set_last_result(ret);
+    return {};
+  }
+
+  bundle* b = bundle_decode(reinterpret_cast<bundle_raw*>(raw), len);
+  if (b == nullptr)
+    return {};
+
+  set_last_result(TIZEN_ERROR_NONE);
+  return Bundle(b, false, true);
+}
+
+const std::vector<uint8_t>& Parcel::GetRaw() {
+  return impl_->GetRaw();
+}
+
+void Parcel::ResetReader() {
+  impl_->ResetReader();
+}
+
+void Parcel::Clear() {
+  impl_->Clear();
+}
+
+void Parcel::Reset(const void* buf, uint32_t size) {
+  impl_->Reset(buf, size);
+}
+
+void Parcel::WriteParcelable(const Parcelable& parcelable) {
+  impl_->Write<int32_t>(1);
+  parcelable.WriteToParcel(this);
+}
+
+int Parcel::ReadParcelable(Parcelable* parcelable) {
+  int32_t has_parcelable = 0;
+  int ret = impl_->Read<int32_t>(&has_parcelable);
+  if (ret != TIZEN_ERROR_NONE)
+    return ret;
+
+  if (has_parcelable != 1)
+    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+
+  parcelable->ReadFromParcel(this);
+  return TIZEN_ERROR_NONE;
+}
+
+}  // naemspace tizen_base
diff --git a/parcel/parcel.hh b/parcel/parcel.hh
new file mode 100644 (file)
index 0000000..1b5f731
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * 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 PARCEL_PARCEL_HH_
+#define PARCEL_PARCEL_HH_
+
+/**
+ * @addtogroup CORE_LIB_PARCEL_MODULE
+ * @{
+ */
+
+#include <bundle_cpp.h>
+#include <tizen.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "parcel/common.hh"
+#include "parcel/parcelable.hh"
+
+namespace tizen_base {
+
+/**
+ * @brief The class for Parcel API.
+ * @since_tizen 6.5
+ */
+class EXPORT Parcel final {
+ public:
+  /**
+   * @brief Enumeration for parcel error.
+   * @since_tizen 6.5
+   */
+  enum Error {
+    None = TIZEN_ERROR_NONE, /**< Successful */
+    IllegalByteSeq = TIZEN_ERROR_ILLEGAL_BYTE_SEQ, /**< Illegal byte sequence */
+    InvalidParameter = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+    NoData = TIZEN_ERROR_NO_DATA, /**< No data available */
+    OutOfMemory = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+  };
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 6.5
+   */
+  Parcel();
+
+  /**
+   * @brief Constructor
+   * @since_tizen 6.5
+   * @param[in] buf The bytes to write
+   * @param[in] size the size of bytes to write
+   */
+  Parcel(const void* buf, uint32_t size);
+
+  /**
+   * @brief Destructor
+   * @since_tizen 6.5
+   */
+  ~Parcel();
+
+  /**
+   * @brief Copy-constructor.
+   * @since_tizen 6.5
+   * @param[in] p The object to copy
+   */
+  Parcel(const Parcel& p);
+
+  /**
+   * @brief Assignment.
+   * @since_tizen 6.5
+   * @param[in] b The object to copy
+   */
+  Parcel& operator = (const Parcel& p);
+
+  /**
+   * @brief Move-constructor.
+   * @since_tizen 6.5
+   * @param[in] p The object to move
+   */
+  Parcel(Parcel&& p) noexcept;
+
+  /**
+   * @brief Assignment.
+   * @since_tizen 6.5
+   * @param[in] p The object to move
+   */
+  Parcel& operator = (Parcel&& p) noexcept;
+
+  /**
+   * @brief Checks the parcel is empty or not.
+   * @since_tizen 6.5
+   * @return true if the parcel is empty
+   */
+  bool IsEmpty() const noexcept;
+
+  /**
+   * @brief Writes bytes into the parcel.
+   * @since_tizen 6.5
+   * @param[in] buf The bytes to write
+   * @param[in] size The size of bytes to write
+   */
+  void Write(const void* buf, uint32_t size);
+
+  /**
+   * @brief Reads bytes from the parcel.
+   * @since_tizen 6.5
+   * @param[out] buf The bytes to read
+   * @param[in] size The size of bytes to read
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int Read(void* buf, uint32_t size);
+
+  /**
+   * @brief Writes a boolean value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The boolean value
+   */
+  void WriteBool(bool val);
+
+  /**
+   * @brief Writes a byte value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The unsigned byte value
+   */
+  void WriteByte(char byte);
+
+  /**
+   * @brief Writes an unsigned short value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The unsigned short value
+   */
+  void WriteUInt16(uint16_t val);
+
+  /**
+   * @brief Writes an unsigned integer value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The unsigned integer value
+   */
+  void WriteUInt32(uint32_t val);
+
+  /**
+   * @brief Writes an unsigned long long integer into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The unsigned long long integer value
+   */
+  void WriteUInt64(uint64_t val);
+
+  /**
+   * @brief Writes a signed short value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The signed short value
+   */
+  void WriteInt16(int16_t val);
+
+  /**
+   * @brief Writes a signed integer value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The signed integer value
+   */
+  void WriteInt32(int32_t val);
+
+  /**
+   * @brief Writes a signed long long integer value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The signed long long integer value
+   */
+  void WriteInt64(int64_t val);
+
+  /**
+   * @brief Writes a floating point value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The floating point value
+   */
+  void WriteFloat(float val);
+
+  /**
+   * @brief Writes a double precision floating point value into the parcel.
+   * @since_tizen 6.5
+   * @param[in] val The double precision floating point value
+   */
+  void WriteDouble(double val);
+
+  /**
+   * @brief Writes a string data into the parcel.
+   * @since_tizen 6.5
+   * @param[in] str The string data
+   */
+  void WriteString(const std::string& str);
+
+  /**
+   * @brief Writes a string data into the parcel.
+   * @since_tizen 6.5
+   * @param[in] str The string data
+   */
+  void WriteCString(const char* str);
+
+  /**
+   * @brief Writes a bundle data into the parcel.
+   * @since_tizen 6.5
+   * @param[in] b The bundle data
+   */
+  void WriteCBundle(bundle* b);
+
+  /**
+   * @brief Writes a bundle data into the parcel.
+   * @since_tizen 6.5
+   * @param[in] b The bundle data
+   */
+  void WriteBundle(const Bundle& b);
+
+  /**
+   * @brief Reads a boolean value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The boolean value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadBool(bool* val);
+
+  /**
+   * @brief Reads a byte value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The unsigned byte value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadByte(char* val);
+
+  /**
+   * @breif Reads an unsigned short value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The unsigned short value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadUInt16(uint16_t* val);
+
+  /**
+   * @brief Reads an unsigned integer value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The unsigned integer value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadUInt32(uint32_t* val);
+
+  /**
+   * @brief Reads an unsigned long long integer value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The unsigned long long integer value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadUInt64(uint64_t* val);
+
+  /**
+   * @brief Reads a signed byte value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The signed byte value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadInt8(int8_t* val);
+
+  /**
+   * @brief Reads a signed short value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The signed short value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadInt16(int16_t* val);
+
+  /**
+   * @brief Reads a signed integer value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The signed integer value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadInt32(int32_t* val);
+
+  /**
+   * @brief Reads a signed long long integer value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The signed long long integer value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadInt64(int64_t* val);
+
+  /**
+   * @brief Reads a floating point value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The floating point value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadFloat(float* val);
+
+  /**
+   * @brief Reads a double precision floating point value from the parcel.
+   * @since_tizen 6.5
+   * @param[out] val The double precision floating point value
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadDouble(double* val);
+
+  /**
+   * @brief Reads a string data from the parcel.
+   * @since_tizen 6.5
+   * @return The string data
+   * @remarks Before using the returned value, you should check the result using get_last_result().
+   * @see get_last_result()
+   */
+  std::string ReadString();
+
+  /**
+   * @brief Reads a string data from the parcel.
+   * @since_tizen 6.5
+   * @remarks You should release @a str using free().
+   * @param[out] str The string data
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadCString(char** str);
+
+  /**
+   * @brief Reads a bundle data from the parcel.
+   * @since_tizen 6.5
+   * @remarks You should release @a b using bundle_free().
+   * @param[out] b The bundle data
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadCBundle(bundle** b);
+
+  /**
+   * @brief Reads a bundle data from the parcel.
+   * @since_tizen 6.5
+   * @return The bundle data
+   * @remarks Before using the returned value, you should check the result using get_last_result().
+   * @see get_last_result();
+   */
+  Bundle ReadBundle();
+
+  /**
+   * @brief Gets the raw data of the parcel.
+   * @since_tizen 6.5
+   * @return The raw data
+   */
+  const std::vector<uint8_t>& GetRaw();
+
+  /**
+   * @brief Resets the reader pointer of the parcel to the start.
+   * @since_tizen 6.5
+   */
+  void ResetReader();
+
+  /**
+   * @brief Clears the data of the parcel.
+   * @since_tizen 6.5
+   */
+  void Clear();
+
+  /**
+   * @brief Resets the parcel.
+   * @since_tizen 6.5
+   * @param[in] buf The bytes to write
+   * @param[in] size The size of bytes to write
+   */
+  void Reset(const void* buf, uint32_t size);
+
+  /**
+   * @brief Writes the data using @a parcelable into the parcel.
+   * @since_tizen 6.5
+   * @param[in] parcelable The interface to write the data into the parcel
+   */
+  void WriteParcelable(const Parcelable& parcelable);
+
+  /**
+   * @brief Reads the data using @a parcelable from the parcel.
+   * @since_tizen 6.5
+   * @param[out] parcelable The interface to get data from the parcel
+   * @return @c 0 on success,
+   *         otherwise a negative error value
+   */
+  int ReadParcelable(Parcelable* parcelable);
+
+ private:
+  class Impl;
+  std::unique_ptr<Impl> impl_;
+};
+
+}  // naemspace tizen_base
+
+/**
+ * @}
+ */
+
+#endif  // PARCEL_PARCEL_HH_
diff --git a/parcel/parcel.pc.in b/parcel/parcel.pc.in
new file mode 100644 (file)
index 0000000..56f44e8
--- /dev/null
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=${prefix}
+libdir=@LIB_INSTALL_DIR@
+includedir=${prefix}/include
+
+Name: parcel
+Description: Parcel library
+Version: @VERSION@
+Requires: capi-base-common
+Libs: -L${libdir} -lparcel -lbundle
+Cflags: -I${includedir} -I${includedir}/parcel
+cppflags: -I${includedir} -I${includedir}/parcel
diff --git a/parcel/parcel_implementation.hh b/parcel/parcel_implementation.hh
new file mode 100644 (file)
index 0000000..5ae09c5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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 PARCEL_PARCEL_IMPLEMENTATION_HH_
+#define PARCEL_PARCEL_IMPLEMENTATION_HH_
+
+#include <string>
+#include <vector>
+
+#include "parcel/parcel.hh"
+#include "parcel/parcelable.hh"
+
+namespace tizen_base {
+
+class Parcel::Impl {
+ public:
+  virtual ~Impl();
+
+  void Write(const void* buf, uint32_t size);
+  int Read(void* buf, uint32_t size);
+  const std::vector<uint8_t>& GetRaw();
+  void ResetReader();
+  void Clear();
+  void Reset(const void* buf, uint32_t size);
+  bool IsEmpty();
+  void WriteSize(uint32_t size);
+  int ReadSize(uint32_t* size);
+
+  template <typename T>
+  void Write(T d);
+  template <typename T>
+  int Read(T* d);
+
+ private:
+  friend class Parcel;
+  explicit Impl(Parcel* parent);
+
+ private:
+  Parcel* parent_;
+  std::vector<uint8_t> data_;
+  uint64_t reader_ = 0;
+};
+
+}  // naemspace tizen_base
+
+#endif  // PARCEL_PARCEL_IMPLEMENTATION_HH_
diff --git a/parcel/parcelable.hh b/parcel/parcelable.hh
new file mode 100644 (file)
index 0000000..6dc9471
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 PARCEL_PARCELABLE_HH_
+#define PARCEL_PARCELABLE_HH_
+
+/**
+ * @addtogroup CORE_LIB_PARCEL_MODULE
+ * @{
+ */
+
+#include "parcel/common.hh"
+
+namespace tizen_base {
+
+class Parcel;
+
+/**
+ * @brief The Parcelable interface.
+ * @since_tizen 6.5
+ */
+class EXPORT Parcelable {
+ public:
+  /**
+   * @brief Constructor.
+   * @since_tizen 6.5
+   */
+  Parcelable() = default;
+
+  /**
+   * @brief Copy constructor.
+   * @since_tizen 6.5
+   */
+  Parcelable(const Parcelable&) = default;
+
+  /**
+   * @brief Destructor.
+   * @since_tizen 6.5
+   */
+  virtual ~Parcelable() = default;
+
+  /**
+   * @brief Writes the data into the parcel.
+   * @since_tizen 6.5
+   * @param[in] parcel The parcel object
+   */
+  virtual void WriteToParcel(Parcel* parcel) const = 0;
+
+  /**
+   * @brief Reads the data from the parcel.
+   * @since_tizen 6.5
+   * @param[in] parcel The parcel object
+   */
+  virtual void ReadFromParcel(Parcel* parcel) = 0;
+};
+
+}  // naemspace tizen_base
+
+/**
+ * @}
+ */
+
+#endif  // PARCEL_PARCELABLE_HH_
diff --git a/parcel/stub.cc b/parcel/stub.cc
new file mode 100644 (file)
index 0000000..24ec529
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * 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 "parcel/api/parcel.h"
+#include "parcel/common.hh"
+#include "parcel/log_private.hh"
+#include "parcel/parcel.hh"
+#include "parcel/parcelable.hh"
+
+using namespace tizen_base;
+
+extern "C" EXPORT int parcel_create(parcel_h *parcel) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = new (std::nothrow) Parcel();
+  if (h == nullptr) {
+    _E("Out of memory");
+    return PARCEL_ERROR_OUT_OF_MEMORY;
+  }
+
+  *parcel = static_cast<parcel_h>(h);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_destroy(parcel_h parcel) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  delete h;
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_clone(parcel_h parcel, parcel_h* clone) {
+  if (parcel == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  auto* c = new (std::nothrow) Parcel(*h);
+  if (c == nullptr) {
+    _E("Out of memory");
+    return PARCEL_ERROR_OUT_OF_MEMORY;
+  }
+
+  *clone = static_cast<parcel_h>(c);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_burst_write(parcel_h parcel, const void *buf,
+    uint32_t size) {
+  if (parcel == nullptr || buf == nullptr || size == 0) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->Write(buf, size);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_burst_read(parcel_h parcel, void *buf,
+    uint32_t size) {
+  if (parcel == nullptr || buf == nullptr || size == 0) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->Read(buf, size);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_bool(parcel_h parcel, bool val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteBool(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_byte(parcel_h parcel, char val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteByte(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_uint16(parcel_h parcel, uint16_t val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteUInt16(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_uint32(parcel_h parcel, uint32_t val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteUInt32(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_uint64(parcel_h parcel, uint64_t val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteUInt64(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_int16(parcel_h parcel, int16_t val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteInt16(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_int32(parcel_h parcel, int32_t val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteInt32(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_int64(parcel_h parcel, int64_t val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteInt64(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_float(parcel_h parcel, float val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteFloat(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_double(parcel_h parcel, double val) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteDouble(val);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_string(parcel_h parcel, const char* str) {
+  if (parcel == nullptr || str == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteCString(str);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write_bundle(parcel_h parcel, bundle* b) {
+  if (parcel == nullptr || b == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->WriteCBundle(b);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_read_bool(parcel_h parcel, bool* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadBool(val);
+}
+
+extern "C" EXPORT int parcel_read_byte(parcel_h parcel, char* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadByte(val);
+}
+
+extern "C" EXPORT int parcel_read_uint16(parcel_h parcel, uint16_t* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadUInt16(val);
+}
+
+extern "C" EXPORT int parcel_read_uint32(parcel_h parcel, uint32_t* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadUInt32(val);
+}
+
+extern "C" EXPORT int parcel_read_uint64(parcel_h parcel, uint64_t* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadUInt64(val);
+}
+
+extern "C" EXPORT int parcel_read_int16(parcel_h parcel, int16_t* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadInt16(val);
+}
+
+extern "C" EXPORT int parcel_read_int32(parcel_h parcel, int32_t* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadInt32(val);
+}
+
+extern "C" EXPORT int parcel_read_int64(parcel_h parcel, int64_t* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadInt64(val);
+}
+
+extern "C" EXPORT int parcel_read_float(parcel_h parcel, float* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadFloat(val);
+}
+
+extern "C" EXPORT int parcel_read_double(parcel_h parcel, double* val) {
+  if (parcel == nullptr || val == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadDouble(val);
+}
+
+extern "C" EXPORT int parcel_read_string(parcel_h parcel, char** str) {
+  if (parcel == nullptr || str == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadCString(str);
+}
+
+extern "C" EXPORT int parcel_read_bundle(parcel_h parcel, bundle** b) {
+  if (parcel == nullptr || b == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  return h->ReadCBundle(b);
+}
+
+extern "C" EXPORT int parcel_reset_reader(parcel_h parcel) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->ResetReader();
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_clear(parcel_h parcel) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->Clear();
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_reset(parcel_h parcel, const void* buf,
+    uint32_t size) {
+  if (parcel == nullptr || buf == nullptr || size == 0) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->Reset(buf, size);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_write(parcel_h parcel, parcelable_t* parcelable,
+    void* data) {
+  if (parcel == nullptr || parcelable == nullptr || parcelable->to == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  parcelable->to(parcel, data);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_read(parcel_h parcel, parcelable_t* parcelable,
+    void* data) {
+  if (parcel == nullptr || parcelable == nullptr ||
+      parcelable->from == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  parcelable->from(parcel, data);
+  return PARCEL_ERROR_NONE;
+}
+
+extern "C" EXPORT int parcel_get_raw(parcel_h parcel, void** raw,
+    uint32_t* size) {
+  if (parcel == nullptr || raw == nullptr || size == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  auto& raw_data = h->GetRaw();
+  *raw = reinterpret_cast<void*>(const_cast<uint8_t*>(&raw_data[0]));
+  *size = raw_data.size();
+  return PARCEL_ERROR_NONE;
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..30c8c6f
--- /dev/null
@@ -0,0 +1,2 @@
+ADD_SUBDIRECTORY(bundle_unittests)
+ADD_SUBDIRECTORY(parcel_unittests)
similarity index 69%
rename from unit_tests/CMakeLists.txt
rename to tests/bundle_unittests/CMakeLists.txt
index 064f946..a7eb6d5 100644 (file)
@@ -19,19 +19,17 @@ 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)
+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)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src BUNDLE_SOURCES)
 
 ADD_EXECUTABLE(${PROJECT_NAME}
     ${BUNDLE_SOURCES}
-    ${BUNDLE_INTERNAL_SOURCES}
     ${UNITTESTS_SOURCES}
 )
 
diff --git a/tests/parcel_unittests/CMakeLists.txt b/tests/parcel_unittests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d481e02
--- /dev/null
@@ -0,0 +1,42 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(parcel_unittests C CXX)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(parcel_unittests REQUIRED
+    capi-base-common
+    dlog
+    glib-2.0
+    gmock
+    json-glib-1.0
+)
+
+FOREACH(flag ${parcel_unittests_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++14")
+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}/../../parcel)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../parcel/api)
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ UNITTESTS_SOURCES)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src BUNDLE_SOURCES)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../parcel PARCEL_SOURCES)
+
+ADD_EXECUTABLE(${PROJECT_NAME}
+  ${BUNDLE_SOURCES}
+  ${PARCEL_SOURCES}
+  ${UNITTESTS_SOURCES}
+)
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}")
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${parcel_unittests_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/)
diff --git a/tests/parcel_unittests/test_main.cc b/tests/parcel_unittests/test_main.cc
new file mode 100644 (file)
index 0000000..acd5cd8
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include <exception>
+
+int main(int argc, char** argv) {
+  try {
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+  } catch (std::exception const &e) {
+    std::cout << "test_main caught exception: " << e.what() << std::endl;
+    return -1;
+  }
+}
diff --git a/tests/parcel_unittests/test_parcel.cc b/tests/parcel_unittests/test_parcel.cc
new file mode 100644 (file)
index 0000000..2605c93
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <stdexcept>
+#include <string>
+
+#include "parcel/api/parcel.h"
+
+class ParcelTest : public ::testing::Test {
+ public:
+  virtual void SetUp() {
+    parcel_create(&parcel_);
+  }
+
+  virtual void TearDown() {
+    if (parcel_)
+      parcel_destroy(parcel_);
+  }
+
+  parcel_h GetHandle() {
+    return parcel_;
+  }
+
+  void SetHandle(parcel_h* parcel) {
+    parcel_ = parcel;
+  }
+
+ private:
+  parcel_h parcel_ = nullptr;
+};
+
+TEST_F(ParcelTest, parcel_create_P) {
+  parcel_h parcel = nullptr;
+  int ret = parcel_create(&parcel);
+  auto ptr = std::unique_ptr<std::remove_pointer<parcel_h>::type,
+       decltype(parcel_destroy)*>(parcel, parcel_destroy);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_NE(parcel, nullptr);
+}
+
+TEST_F(ParcelTest, parcel_create_N) {
+  int ret = parcel_create(nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_destroy_P) {
+  int ret = parcel_destroy(GetHandle());
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  SetHandle(nullptr);
+}
+
+TEST_F(ParcelTest, parcel_destroy_N) {
+  int ret = parcel_destroy(nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_clone_P) {
+  parcel_h clone = nullptr;
+  int ret = parcel_clone(GetHandle(), &clone);
+  auto ptr = std::unique_ptr<std::remove_pointer<parcel_h>::type,
+       decltype(parcel_destroy)*>(clone, parcel_destroy);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_NE(clone, nullptr);
+}
+
+TEST_F(ParcelTest, parcel_clone_N) {
+  int ret = parcel_clone(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_burst_write_P) {
+  char buf[1024] = { 1, };
+  int ret = parcel_burst_write(GetHandle(), buf, sizeof(buf));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char read_buf[1024];
+  ret = parcel_burst_read(GetHandle(), read_buf, sizeof(read_buf));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(read_buf[0], 1);
+}
+
+TEST_F(ParcelTest, parcel_burst_write_N) {
+  int ret = parcel_burst_write(nullptr, nullptr, 0);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_burst_read_P) {
+  char buf[1024] = { 2, };
+  int ret = parcel_burst_write(GetHandle(), buf, sizeof(buf));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char read_buf[1024];
+  ret = parcel_burst_read(GetHandle(), read_buf, sizeof(read_buf));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(read_buf[0], 2);
+}
+
+TEST_F(ParcelTest, parcel_burst_read_N) {
+  int ret = parcel_burst_read(nullptr, nullptr, 0);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_bool_P) {
+  int ret = parcel_write_bool(GetHandle(), true);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  bool val = false;
+  ret = parcel_read_bool(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, true);
+}
+
+TEST_F(ParcelTest, parcel_write_bool_N) {
+  int ret = parcel_write_bool(nullptr, false);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_byte_P) {
+  int ret = parcel_write_byte(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char val = 0;
+  ret = parcel_read_byte(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_byte_N) {
+  int ret = parcel_write_byte(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_uint16_P) {
+  int ret = parcel_write_uint16(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint16_t val = 0;
+  ret = parcel_read_uint16(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_uint16_N) {
+  int ret = parcel_write_uint16(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_uint32_P) {
+  int ret = parcel_write_uint32(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint32_t val = 0;
+  ret = parcel_read_uint32(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_uint32_N) {
+  int ret = parcel_write_uint32(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_uint64_P) {
+  int ret = parcel_write_uint64(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint64_t val = 0;
+  ret = parcel_read_uint64(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_uint64_N) {
+  int ret = parcel_write_uint64(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_int16_P) {
+  int ret = parcel_write_int16(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int16_t val = 0;
+  ret = parcel_read_int16(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_int16_N) {
+  int ret = parcel_write_int16(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_int32_P) {
+  int ret = parcel_write_int32(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int32_t val = 0;
+  ret = parcel_read_int32(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_int32_N) {
+  int ret = parcel_write_int32(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_int64_P) {
+  int ret = parcel_write_int64(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int64_t val = 0;
+  ret = parcel_read_int64(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_int64_N) {
+  int ret = parcel_write_int64(nullptr, 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_float_P) {
+  int ret = parcel_write_float(GetHandle(), 0.1f);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  float val = 0.0f;
+  ret = parcel_read_float(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 0.1f);
+}
+
+TEST_F(ParcelTest, parcel_write_float_N) {
+  int ret = parcel_write_float(nullptr, 0.1f);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_double_P) {
+  int ret = parcel_write_double(GetHandle(), 0.1f);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  double val = 0.0f;
+  ret = parcel_read_double(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 0.1f);
+}
+
+TEST_F(ParcelTest, parcel_write_double_N) {
+  int ret = parcel_write_double(nullptr, 0.1f);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_string_P) {
+  int ret = parcel_write_string(GetHandle(), "TestString");
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char* str = nullptr;
+  ret = parcel_read_string(GetHandle(), &str);
+  ASSERT_NE(str, nullptr);
+  auto ptr = std::unique_ptr<char, decltype(std::free)*>(str, std::free);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(std::string(str), "TestString");
+}
+
+TEST_F(ParcelTest, parcel_write_string_N) {
+  int ret = parcel_write_string(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_write_bundle_P) {
+  bundle* b = bundle_create();
+  bundle_add_str(b, "Key", "Value");
+  int ret = parcel_write_bundle(GetHandle(), b);
+  bundle_free(b);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  b = nullptr;
+  ret = parcel_read_bundle(GetHandle(), &b);
+  ASSERT_NE(b, nullptr);
+  auto ptr = std::unique_ptr<std::remove_pointer<bundle>::type,
+       decltype(bundle_free)*>(b, bundle_free);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char* str = nullptr;
+  bundle_get_str(b, "Key", &str);
+  ASSERT_EQ(std::string(str), "Value");
+}
+
+TEST_F(ParcelTest, parcel_write_bundle_N) {
+  int ret = parcel_write_bundle(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_bool_P) {
+  int ret = parcel_write_bool(GetHandle(), false);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  bool val = true;
+  ret = parcel_read_bool(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, false);
+}
+
+TEST_F(ParcelTest, parcel_read_bool_N) {
+  int ret = parcel_read_bool(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_byte_P) {
+  int ret = parcel_write_byte(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char val = 0;
+  ret = parcel_read_byte(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_byte_N) {
+  int ret = parcel_read_byte(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_uint16_P) {
+  int ret = parcel_write_uint16(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint16_t val = 0;
+  ret = parcel_read_uint16(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_uint16_N) {
+  int ret = parcel_read_uint16(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_uint32_P) {
+  int ret = parcel_write_uint32(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint32_t val = 0;
+  ret = parcel_read_uint32(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_uint32_N) {
+  int ret = parcel_read_uint32(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_uint64_P) {
+  int ret = parcel_write_uint64(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint64_t val = 0;
+  ret = parcel_read_uint64(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_uint64_N) {
+  int ret = parcel_read_uint64(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_int16_P) {
+  int ret = parcel_write_int16(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int16_t val = 0;
+  ret = parcel_read_int16(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_int16_N) {
+  int ret = parcel_read_int16(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_int32_P) {
+  int ret = parcel_write_int32(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int32_t val = 0;
+  ret = parcel_read_int32(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_int32_N) {
+  int ret = parcel_read_int32(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_int64_P) {
+  int ret = parcel_write_int64(GetHandle(), 2);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int64_t val = 0;
+  ret = parcel_read_int64(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 2);
+}
+
+TEST_F(ParcelTest, parcel_read_int64_N) {
+  int ret = parcel_read_int64(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_float_P) {
+  int ret = parcel_write_float(GetHandle(), 0.2f);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  float val = 0.0f;
+  ret = parcel_read_float(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 0.2f);
+}
+
+TEST_F(ParcelTest, parcel_read_float_N) {
+  int ret = parcel_read_float(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_double_P) {
+  int ret = parcel_write_double(GetHandle(), 0.2f);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  double val = 0.0f;
+  ret = parcel_read_double(GetHandle(), &val);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 0.2f);
+}
+
+TEST_F(ParcelTest, parcel_read_double_N) {
+  int ret = parcel_read_double(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_string_P) {
+  int ret = parcel_write_string(GetHandle(), "ReadCString");
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char* str = nullptr;
+  ret = parcel_read_string(GetHandle(), &str);
+  ASSERT_NE(str, nullptr);
+  auto ptr = std::unique_ptr<char, decltype(std::free)*>(str, std::free);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(std::string(str), "ReadCString");
+}
+
+TEST_F(ParcelTest, parcel_read_string_N) {
+  int ret = parcel_read_string(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_bundle_P) {
+  bundle* b = bundle_create();
+  bundle_add_str(b, "Key", "Value");
+  int ret = parcel_write_bundle(GetHandle(), b);
+  bundle_free(b);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  b = nullptr;
+  ret = parcel_read_bundle(GetHandle(), &b);
+  ASSERT_NE(b, nullptr);
+  auto ptr = std::unique_ptr<std::remove_pointer<bundle>::type,
+       decltype(bundle_free)*>(b, bundle_free);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char* str = nullptr;
+  bundle_get_str(b, "Key", &str);
+  ASSERT_EQ(std::string(str), "Value");
+}
+
+TEST_F(ParcelTest, parcel_read_bundle_N) {
+  int ret = parcel_read_bundle(nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_reset_reader_P) {
+  int ret = parcel_reset_reader(GetHandle());
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+}
+
+TEST_F(ParcelTest, parcel_reset_reader_N) {
+  int ret = parcel_reset_reader(nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_clear_P) {
+  int ret = parcel_clear(GetHandle());
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+}
+
+TEST_F(ParcelTest, parcel_clear_N) {
+  int ret = parcel_clear(nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_reset_P) {
+  char buf[1024] = { 128, };
+  int ret = parcel_reset(GetHandle(), buf, sizeof(buf));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  char read_buf[1024] = { 0, };
+  ret = parcel_burst_read(GetHandle(), read_buf, sizeof(read_buf));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(read_buf[0], buf[0]);
+}
+
+TEST_F(ParcelTest, parcel_reset_N) {
+  int ret = parcel_reset(nullptr, nullptr, 0);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+static void __write_to_parcel(parcel_h parcel, void* data) {
+  parcel_write_int32(parcel, 1);
+}
+
+static void __read_from_parcel(parcel_h parcel, void* data) {
+  int32_t* val = static_cast<int32_t*>(data);
+  parcel_read_int32(parcel, val);
+}
+
+TEST_F(ParcelTest, parcel_write_P) {
+  parcelable_t parcelable = {
+    .to = __write_to_parcel,
+    .from = __read_from_parcel
+  };
+  int ret = parcel_write(GetHandle(), &parcelable, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int32_t val = 0;
+  ret = parcel_read(GetHandle(), &parcelable, static_cast<void*>(&val));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_write_N) {
+  int ret = parcel_write(nullptr, nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_read_P) {
+  parcelable_t parcelable = {
+    .to = __write_to_parcel,
+    .from = __read_from_parcel
+  };
+  int ret = parcel_write(GetHandle(), &parcelable, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  int32_t val = 0;
+  ret = parcel_read(GetHandle(), &parcelable, static_cast<void*>(&val));
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelTest, parcel_read_N) {
+  int ret = parcel_read(nullptr, nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(ParcelTest, parcel_get_raw_P) {
+  int ret = parcel_write_int32(GetHandle(), 1);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  uint8_t* raw = nullptr;
+  uint32_t size = 0;
+  ret = parcel_get_raw(GetHandle(), reinterpret_cast<void**>(&raw), &size);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  ASSERT_NE(raw, nullptr);
+  ASSERT_EQ(size, sizeof(uint32_t) + sizeof(int32_t));
+}
+
+TEST_F(ParcelTest, parcel_get_raw_N) {
+  int ret = parcel_get_raw(nullptr, nullptr, nullptr);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
diff --git a/tests/parcel_unittests/test_parcel_cpp.cc b/tests/parcel_unittests/test_parcel_cpp.cc
new file mode 100644 (file)
index 0000000..52c0c90
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <iostream>
+#include <stdexcept>
+
+#include "parcel/parcel.hh"
+
+using ::testing::AtLeast;
+using namespace tizen_base;
+
+class ParcelCppTest : public ::testing::Test {
+ public:
+  virtual void SetUp() {
+  }
+
+  virtual void TearDown() {
+    parcel_.Clear();
+  }
+
+  Parcel& GetHandle() {
+    return parcel_;
+  }
+
+ private:
+  Parcel parcel_;
+};
+
+class Student : public Parcelable {
+ public:
+  Student(std::string name, uint32_t age)
+      : name_(std::move(name)), age_(age) {
+  }
+
+  Student() = default;
+  virtual ~Student() = default;
+
+  const std::string& GetName() const {
+    return name_;
+  }
+
+  uint32_t GetAge() const {
+    return age_;
+  }
+
+  virtual void WriteToParcel(Parcel* parcel) const {
+    parcel->WriteString(name_);
+    parcel->WriteUInt32(age_);
+  }
+
+  virtual void ReadFromParcel(Parcel* parcel) {
+    name_ = parcel->ReadString();
+    parcel->ReadUInt32(&age_);
+  }
+
+ private:
+  std::string name_;
+  uint32_t age_;
+};
+
+TEST_F(ParcelCppTest, Ctor_AND_Dtor) {
+  Parcel parcel;
+}
+
+TEST_F(ParcelCppTest, Write_AND_Read) {
+  char buf[1024] = { 128, };
+  GetHandle().Write(buf, sizeof(buf));
+  char read_buf[1024] = { 0, };
+  int ret = GetHandle().Read(read_buf, sizeof(read_buf));
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(buf[0], read_buf[0]);
+}
+
+TEST_F(ParcelCppTest, WriteBool_AND_ReadBool) {
+  GetHandle().WriteBool(true);
+  bool val = false;
+  int ret = GetHandle().ReadBool(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, true);
+}
+
+TEST_F(ParcelCppTest, WriteByte_AND_ReadByte) {
+  GetHandle().WriteByte(1);
+  char val = 0;
+  int ret = GetHandle().ReadByte(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteUInt16_AND_ReadUInt16) {
+  GetHandle().WriteUInt16(1);
+  uint16_t val = 0;
+  int ret = GetHandle().ReadUInt16(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteUInt32_AND_ReadUInt32) {
+  GetHandle().WriteUInt32(1);
+  uint32_t val = 0;
+  int ret = GetHandle().ReadUInt32(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteUInt64_AND_ReadUInt64) {
+  GetHandle().WriteUInt64(1);
+  uint64_t val = 0;
+  int ret = GetHandle().ReadUInt64(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteInt16_AND_ReadInt16) {
+  GetHandle().WriteInt16(1);
+  int16_t val = 0;
+  int ret = GetHandle().ReadInt16(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteInt32_AND_ReadInt32) {
+  GetHandle().WriteInt32(1);
+  int32_t val = 0;
+  int ret = GetHandle().ReadInt32(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteInt64_AND_ReadInt64) {
+  GetHandle().WriteInt64(1);
+  int64_t val = 0;
+  int ret = GetHandle().ReadInt64(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, WriteFloat_AND_ReadFloat) {
+  GetHandle().WriteFloat(0.1f);
+  float val = 0.0f;
+  int ret = GetHandle().ReadFloat(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 0.1f);
+}
+
+TEST_F(ParcelCppTest, WriteDouble_AND_ReadDouble) {
+  GetHandle().WriteDouble(0.1f);
+  double val = 0.0f;
+  int ret = GetHandle().ReadDouble(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 0.1f);
+}
+
+TEST_F(ParcelCppTest, WriteString_AND_ReadString) {
+  GetHandle().WriteString("TestString");
+  auto val = GetHandle().ReadString();
+  ASSERT_EQ(get_last_result(), Parcel::Error::None);
+  ASSERT_EQ(val, "TestString");
+}
+
+TEST_F(ParcelCppTest, WriteCString_AND_ReadCString) {
+  GetHandle().WriteCString("TestCString");
+  char* str = nullptr;
+  int ret = GetHandle().ReadCString(&str);
+  auto ptr = std::unique_ptr<char, decltype(std::free)*>(str, std::free);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_NE(str, nullptr);
+  ASSERT_EQ(std::string(str), "TestCString");
+}
+
+TEST_F(ParcelCppTest, WriteCBundle_AND_ReadCBundle) {
+  bundle* b = bundle_create();
+  bundle_add_str(b, "Key", "Value");
+  GetHandle().WriteCBundle(b);
+  bundle_free(b);
+  bundle* val = nullptr;
+  int ret = GetHandle().ReadCBundle(&val);
+  auto ptr = std::unique_ptr<bundle, decltype(bundle_free)*>(val, bundle_free);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_NE(val, nullptr);
+  char* str = nullptr;
+  bundle_get_str(b, "Key", &str);
+  ASSERT_EQ(std::string(str), "Value");
+}
+
+TEST_F(ParcelCppTest, WriteBundle_AND_ReadBundle) {
+  Bundle b;
+  b.Add("Key", "Value");
+  GetHandle().WriteBundle(b);
+  auto val = GetHandle().ReadBundle();
+  ASSERT_EQ(get_last_result(), Parcel::Error::None);
+  auto str = val.GetString("Key");
+  ASSERT_EQ(str, "Value");
+}
+
+TEST_F(ParcelCppTest, GetRaw) {
+  GetHandle().WriteInt32(0);
+  auto& raw = GetHandle().GetRaw();
+  ASSERT_EQ(raw.size(), sizeof(uint32_t) + sizeof(int32_t));
+}
+
+TEST_F(ParcelCppTest, ResetReader) {
+  GetHandle().WriteInt32(1);
+  GetHandle().WriteInt32(2);
+  int32_t val = 0;
+  int ret = GetHandle().ReadInt32(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+  GetHandle().ResetReader();
+  val = 0;
+  ret = GetHandle().ReadInt32(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}
+
+TEST_F(ParcelCppTest, Clear) {
+  GetHandle().WriteInt32(1);
+  GetHandle().Clear();
+  int32_t val = 0;
+  int ret = GetHandle().ReadInt32(&val);
+  ASSERT_NE(ret, Parcel::Error::None);
+  ASSERT_NE(val, 1);
+}
+
+TEST_F(ParcelCppTest, Reset) {
+  GetHandle().WriteByte(1);
+  char buf[1024] = { 128, };
+  GetHandle().Reset(buf, sizeof(buf));
+  char read_buf[1024] = { 0, };
+  int ret = GetHandle().Read(read_buf, sizeof(read_buf));
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(buf[0], read_buf[0]);
+}
+
+TEST_F(ParcelCppTest, WriteParcelable_AND_ReadParcelable) {
+  Student s1("s1", 8);
+  GetHandle().WriteParcelable(s1);
+  Student s2;
+  GetHandle().ReadParcelable(&s2);
+  ASSERT_EQ(s1.GetName(), s2.GetName());
+  ASSERT_EQ(s1.GetAge(), s2.GetAge());
+}
+
+TEST_F(ParcelCppTest, IsEmpty) {
+  ASSERT_EQ(GetHandle().IsEmpty(), true);
+  GetHandle().WriteInt32(1);
+  ASSERT_EQ(GetHandle().IsEmpty(), false);
+}