Support byte order setting 19/256019/9
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 26 Mar 2021 11:43:04 +0000 (20:43 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 29 Mar 2021 01:35:35 +0000 (10:35 +0900)
The platform byte order is little-endian. The network byte order is
defined to be always big-endian. The developer can change
byte order of the parcel using parcel_set_byte_order().

Adds:
 - Parcel.SetByteOrder()
 - parcel_set_byte_order()

Change-Id: I1f6b7166eec508862fe4771355a1a4a53093b3c6
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
parcel/CMakeLists.txt
parcel/api/parcel.h
parcel/parcel.cc
parcel/parcel.hh
parcel/parcel_implementation.hh
parcel/stub.cc
tests/parcel_unittests/test_parcel.cc
tests/parcel_unittests/test_parcel_cpp.cc

index d8b9d2b..cac7578 100644 (file)
@@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 PROJECT(parcel C CXX)
 
 INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(pkgs REQUIRED dlog capi-base-common)
+PKG_CHECK_MODULES(pkgs REQUIRED dlog capi-base-common glib-2.0)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
index 6338030..640b3b1 100644 (file)
@@ -513,6 +513,22 @@ int parcel_read(parcel_h parcel, parcelable_t *parcelable, void *data);
  */
 int parcel_get_raw(parcel_h parcel, void **raw, uint32_t *size);
 
+/**
+ * @brief Sets byte order of the parcel handle.
+ * @since_tizen 6.5
+ * @remarks The platform byte order is little-endian.
+ *          The network byte order is defined to always be big-endian.
+ *          If you want to change byte order of the raw data of the parcel handle,
+ *          you set byte order of the parcel handle using the function.
+ * @param[in] parcel The parcel handle
+ * @param[in] big_endian @ true, if byte order of the parcel is big-endian
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #PARCEL_ERROR_NONE Successful
+ * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int parcel_set_byte_order(parcel_h parcle, bool big_endian);
+
 #ifdef __cplusplus
 }
 #endif
index f74f9dd..322f377 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <glib.h>
+
 #include "parcel/common.hh"
 #include "parcel/log_private.hh"
 #include "parcel/parcel.hh"
@@ -22,7 +24,8 @@
 
 namespace tizen_base {
 
-Parcel::Impl::Impl(Parcel* parent) : parent_(parent) {
+Parcel::Impl::Impl(Parcel* parent, bool big_endian)
+    : parent_(parent), big_endian_(big_endian) {
 }
 
 Parcel::Impl::~Impl() = default;
@@ -69,6 +72,9 @@ bool Parcel::Impl::IsEmpty() {
 }
 
 void Parcel::Impl::WriteSize(uint32_t size) {
+  if (IsBigEndian())
+    size = GUINT32_TO_BE(size);
+
   auto* p = reinterpret_cast<uint8_t*>(&size);
   std::copy(p, p + sizeof(size), std::back_inserter(data_));
 }
@@ -89,6 +95,10 @@ int Parcel::Impl::ReadSize(uint32_t* size) {
   auto* p = reinterpret_cast<uint8_t*>(size);
   std::copy(&data_[reader_], &data_[reader_] + sizeof(uint32_t), p);
   reader_ += sizeof(uint32_t);
+
+  if (IsBigEndian())
+    *size = GUINT32_FROM_BE(*size);
+
   return TIZEN_ERROR_NONE;
 }
 
@@ -104,10 +114,19 @@ int Parcel::Impl::Read(T* d) {
   return TIZEN_ERROR_NONE;
 }
 
-Parcel::Parcel() : impl_(new Impl(this)) {
+void Parcel::Impl::SetByteOrder(bool big_endian) {
+  big_endian_ = big_endian;
 }
 
-Parcel::Parcel(const void* buf, uint32_t size) : impl_(new Impl(this)) {
+bool Parcel::Impl::IsBigEndian() {
+  return big_endian_;
+}
+
+Parcel::Parcel(bool big_endian) : impl_(new Impl(this, big_endian)) {
+}
+
+Parcel::Parcel(const void* buf, uint32_t size, bool big_endian)
+    : impl_(new Impl(this, big_endian)) {
   impl_->Write(buf, size);
 }
 
@@ -115,6 +134,7 @@ Parcel::~Parcel() = default;
 
 Parcel::Parcel(const Parcel& p)
   : impl_(new Impl(this)) {
+  impl_->big_endian_ = p.impl_->big_endian_;
   std::copy(p.impl_->data_.begin(), p.impl_->data_.end(),
       std::back_inserter(impl_->data_));
   impl_->reader_ = p.impl_->reader_;
@@ -122,6 +142,7 @@ Parcel::Parcel(const Parcel& p)
 
 Parcel& Parcel::operator = (const Parcel& p) {
   if (this != &p) {
+    impl_->big_endian_ = p.impl_->big_endian_;
     std::copy(p.impl_->data_.begin(), p.impl_->data_.end(),
         std::back_inserter(impl_->data_));
     impl_->reader_ = p.impl_->reader_;
@@ -136,6 +157,7 @@ Parcel::Parcel(Parcel&& p) noexcept {
 
 Parcel& Parcel::operator = (Parcel&& p) noexcept {
   if (this != &p) {
+    impl_->big_endian_ = p.impl_->big_endian_;
     impl_->data_ = std::move(p.impl_->data_);
     impl_->reader_ = p.impl_->reader_;
     p.impl_->reader_ = 0;
@@ -164,34 +186,58 @@ void Parcel::WriteByte(char val) {
 }
 
 void Parcel::WriteUInt16(uint16_t val) {
+  if (impl_->IsBigEndian())
+    val = GUINT16_TO_BE(val);
+
   impl_->Write<uint16_t>(val);
 }
 
 void Parcel::WriteUInt32(uint32_t val) {
+  if (impl_->IsBigEndian())
+    val = GUINT32_TO_BE(val);
+
   impl_->Write<uint32_t>(val);
 }
 
 void Parcel::WriteUInt64(uint64_t val) {
+  if (impl_->IsBigEndian())
+    val = GUINT64_TO_BE(val);
+
   impl_->Write<uint64_t>(val);
 }
 
 void Parcel::WriteInt16(int16_t val) {
+  if (impl_->IsBigEndian())
+    val = GINT16_TO_BE(val);
+
   impl_->Write<int16_t>(val);
 }
 
 void Parcel::WriteInt32(int32_t val) {
+  if (impl_->IsBigEndian())
+    val = GINT32_TO_BE(val);
+
   impl_->Write<int32_t>(val);
 }
 
 void Parcel::WriteInt64(int64_t val) {
+  if (impl_->IsBigEndian())
+    val = GINT64_TO_BE(val);
+
   impl_->Write<int64_t>(val);
 }
 
 void Parcel::WriteFloat(float val) {
+  if (impl_->IsBigEndian())
+    val = static_cast<float>(GINT32_TO_BE(val));
+
   impl_->Write<float>(val);
 }
 
 void Parcel::WriteDouble(double val) {
+  if (impl_->IsBigEndian())
+    val = static_cast<double>(GINT64_TO_BE(val));
+
   impl_->Write<double>(val);
 }
 
@@ -214,35 +260,67 @@ int Parcel::ReadByte(char* val) {
 }
 
 int Parcel::ReadUInt16(uint16_t* val) {
-  return impl_->Read<uint16_t>(val);
+  int ret = impl_->Read<uint16_t>(val);
+  if (impl_->IsBigEndian())
+    *val = GUINT16_FROM_BE(*val);
+
+  return ret;
 }
 
 int Parcel::ReadUInt32(uint32_t* val) {
-  return impl_->Read<uint32_t>(val);
+  int ret = impl_->Read<uint32_t>(val);
+  if (impl_->IsBigEndian())
+    *val = GUINT32_FROM_BE(*val);
+
+  return ret;
 }
 
 int Parcel::ReadUInt64(uint64_t* val) {
-  return impl_->Read<uint64_t>(val);
+  int ret = impl_->Read<uint64_t>(val);
+  if (impl_->IsBigEndian())
+    *val = GUINT64_FROM_BE(*val);
+
+  return ret;
 }
 
 int Parcel::ReadInt16(int16_t* val) {
-  return impl_->Read<int16_t>(val);
+  int ret = impl_->Read<int16_t>(val);
+  if (impl_->IsBigEndian())
+    *val = GINT16_FROM_BE(*val);
+
+  return ret;
 }
 
 int Parcel::ReadInt32(int32_t* val) {
-  return impl_->Read<int32_t>(val);
+  int ret = impl_->Read<int32_t>(val);
+  if (impl_->IsBigEndian())
+    *val = GINT32_FROM_BE(*val);
+
+  return ret;
 }
 
 int Parcel::ReadInt64(int64_t* val) {
-  return impl_->Read<int64_t>(val);
+  int ret = impl_->Read<int64_t>(val);
+  if (impl_->IsBigEndian())
+    *val = GINT64_FROM_BE(*val);
+
+  return ret;
 }
 
 int Parcel::ReadFloat(float* val) {
-  return impl_->Read<float>(val);
+  int ret = impl_->Read<float>(val);
+  if (impl_->IsBigEndian())
+    *val = static_cast<float>(GINT32_FROM_BE(*val));
+
+  return ret;
 }
 
 int Parcel::ReadDouble(double* val) {
-  return impl_->Read<double>(val);
+  int ret = impl_->Read<double>(val);
+  if (impl_->IsBigEndian())
+    *val = static_cast<double>(GINT64_FROM_BE(*val));
+
+  return ret;
 }
 
 std::string Parcel::ReadString() {
@@ -315,4 +393,8 @@ int Parcel::ReadParcelable(Parcelable* parcelable) {
   return TIZEN_ERROR_NONE;
 }
 
+void Parcel::SetByteOrder(bool big_endian) {
+  impl_->SetByteOrder(big_endian);
+}
+
 }  // naemspace tizen_base
index d924c93..87af7d7 100644 (file)
@@ -54,16 +54,18 @@ class EXPORT Parcel final {
   /**
    * @brief Constructor.
    * @since_tizen 6.5
+   * @param[in] big_endian @c true, if byte order of the parcel is big-endian
    */
-  Parcel();
+  Parcel(bool big_endian = false);
 
   /**
    * @brief Constructor
    * @since_tizen 6.5
    * @param[in] buf The bytes to write
    * @param[in] size the size of bytes to write
+   * @param[in] big_endian @c true, if byte order of the parcel is big-endian
    */
-  Parcel(const void* buf, uint32_t size);
+  Parcel(const void* buf, uint32_t size, bool big_endian = false);
 
   /**
    * @brief Destructor
@@ -369,6 +371,13 @@ class EXPORT Parcel final {
    */
   int ReadParcelable(Parcelable* parcelable);
 
+  /**
+   * @brief Sets byte order of the parcel.
+   * @since_tizen 6.5
+   * @param[in] big_endian @c true, if byte order of the parcel is big-endian
+   */
+  void SetByteOrder(bool big_endian);
+
  private:
   class Impl;
   std::unique_ptr<Impl> impl_;
index 5ae09c5..ed6c62f 100644 (file)
@@ -44,12 +44,16 @@ class Parcel::Impl {
   template <typename T>
   int Read(T* d);
 
+  void SetByteOrder(bool big_endian);
+  bool IsBigEndian();
+
  private:
   friend class Parcel;
-  explicit Impl(Parcel* parent);
+  explicit Impl(Parcel* parent, bool big_endian = false);
 
  private:
   Parcel* parent_;
+  bool big_endian_;
   std::vector<uint8_t> data_;
   uint64_t reader_ = 0;
 };
index da80f8c..ce62584 100644 (file)
@@ -391,3 +391,15 @@ extern "C" EXPORT int parcel_get_raw(parcel_h parcel, void** raw,
   *size = raw_data.size();
   return PARCEL_ERROR_NONE;
 }
+
+extern "C" EXPORT int parcel_set_byte_order(parcel_h parcel,
+    bool big_endian) {
+  if (parcel == nullptr) {
+    _E("Invalid parameter");
+    return PARCEL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<Parcel*>(parcel);
+  h->SetByteOrder(big_endian);
+  return PARCEL_ERROR_NONE;
+}
index a8aaa97..e05f553 100644 (file)
@@ -522,3 +522,19 @@ TEST_F(ParcelTest, parcel_get_raw_N) {
   int ret = parcel_get_raw(nullptr, nullptr, nullptr);
   ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
 }
+
+TEST_F(ParcelTest, parcel_set_byte_order_P) {
+  int ret = parcel_set_byte_order(GetHandle(), true);
+  ASSERT_EQ(ret, PARCEL_ERROR_NONE);
+  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_set_byte_order_N) {
+  int ret = parcel_set_byte_order(nullptr, false);
+  ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER);
+}
index d3e5af0..ff52fb1 100644 (file)
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
 #include <iostream>
 #include <stdexcept>
 
@@ -236,3 +237,12 @@ TEST_F(ParcelCppTest, IsEmpty) {
   GetHandle().WriteInt32(1);
   ASSERT_EQ(GetHandle().IsEmpty(), false);
 }
+
+TEST_F(ParcelCppTest, SetByteOrder) {
+  GetHandle().SetByteOrder(true);
+  GetHandle().WriteInt32(1);
+  int32_t val = 0;
+  int ret = GetHandle().ReadInt32(&val);
+  ASSERT_EQ(ret, Parcel::Error::None);
+  ASSERT_EQ(val, 1);
+}