Add constructor to make sub parcel from origin parcel 43/319443/8
authorpjh9216 <jh9216.park@samsung.com>
Wed, 23 Oct 2024 07:11:05 +0000 (16:11 +0900)
committerJunghoon Park <jh9216.park@samsung.com>
Wed, 30 Oct 2024 04:04:15 +0000 (04:04 +0000)
Change-Id: Ib560bf5af7117d3e3991d0bbad9d1d5d9655654a
Signed-off-by: pjh9216 <jh9216.park@samsung.com>
src/parcel/parcel.cc
src/parcel/parcel.hh
src/parcel/parcel_implementation.hh
tests/parcel_unittests/test_parcel_cpp.cc

index fc1e873515b5c80ca4d3f8b0ecaa8b760b684e7a..7ad28b91d18abdafbf9b99d4b7bac3025256cdc0 100644 (file)
  * limitations under the License.
  */
 
+#include "parcel/parcel.hh"
+
 #include <glib.h>
 
-#include <iostream>
 #include <exception>
+#include <iostream>
 #include <mutex>
 
 #include "parcel/common.hh"
 #include "parcel/log_private.hh"
-#include "parcel/parcel.hh"
 #include "parcel/parcel_implementation.hh"
 #include "parcel/parcelable.hh"
 
@@ -41,16 +42,24 @@ Parcel::Impl::Impl(Parcel* parent, size_t data_capacity, uint8_t* data)
     data_ = static_cast<uint8_t*>(malloc(data_capacity_));
 }
 
+Parcel::Impl::Impl(Parcel* parent, uint8_t* start_pos, size_t data_size) {
+  data_ = start_pos;
+  data_capacity_ = data_size;
+  data_size_ = 0;
+  ownership_ = false;
+  pin_ = true;
+}
+
 Parcel::Impl::~Impl() {
-  free(data_);
+  if (ownership_) free(data_);
 }
 
 void Parcel::Impl::Write(const void* buf, uint32_t size) {
   if (data_size_ + size > data_capacity_) {
+    if (!ownership_ || pin_) throw std::bad_alloc();
     size_t new_size = (data_capacity_ + size) * 3 / 2;
     uint8_t* data = static_cast<uint8_t*>(realloc(data_, new_size));
-    if (data == nullptr)
-      throw std::bad_alloc();
+    if (data == nullptr) throw std::bad_alloc();
 
     data_ = data;
     data_capacity_ = new_size;
@@ -60,12 +69,24 @@ void Parcel::Impl::Write(const void* buf, uint32_t size) {
   data_size_ += size;
 }
 
+void Parcel::Impl::Reserve(uint32_t size) {
+  if (data_size_ + size > data_capacity_) {
+    if (!ownership_ || pin_) throw std::bad_alloc();
+    size_t new_size = (data_capacity_ + size) * 3 / 2;
+    uint8_t* data = static_cast<uint8_t*>(realloc(data_, new_size));
+    if (data == nullptr) throw std::bad_alloc();
+
+    data_ = data;
+    data_capacity_ = new_size;
+  }
+
+  data_size_ += size;
+}
+
 int Parcel::Impl::Read(void* buf, uint32_t size) {
-  if (data_size_ == 0)
-    return TIZEN_ERROR_NO_DATA;
+  if (data_size_ == 0) return TIZEN_ERROR_NO_DATA;
 
-  if (reader_ + size > data_size_)
-    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+  if (reader_ + size > data_size_) return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
 
   memcpy(buf, data_ + reader_, size);
   reader_ += size;
@@ -73,13 +94,10 @@ int Parcel::Impl::Read(void* buf, uint32_t size) {
   return TIZEN_ERROR_NONE;
 }
 
-void Parcel::Impl::ResetReader() {
-  reader_ = 0;
-}
+void Parcel::Impl::ResetReader() { reader_ = 0; }
 
 bool Parcel::Impl::SetReader(uint32_t pos) {
-  if (pos > data_size_)
-    return false;
+  if (pos > data_size_) return false;
   reader_ = pos;
   return true;
 }
@@ -94,13 +112,10 @@ void Parcel::Impl::Reset(const void* buf, uint32_t size) {
   Write(buf, size);
 }
 
-bool Parcel::Impl::IsEmpty() {
-  return data_size_ == 0;
-}
+bool Parcel::Impl::IsEmpty() { return data_size_ == 0; }
 
 void Parcel::Impl::WriteSize(uint32_t size) {
-  if (IsBigEndian())
-    size = GUINT32_TO_BE(size);
+  if (IsBigEndian()) size = GUINT32_TO_BE(size);
 
   Write<uint32_t>(size);
 }
@@ -108,10 +123,10 @@ void Parcel::Impl::WriteSize(uint32_t size) {
 template <typename T>
 void Parcel::Impl::Write(T d) {
   if (data_size_ + sizeof(T) > data_capacity_) {
+    if (!ownership_ || pin_) throw std::bad_alloc();
     size_t new_size = (data_capacity_ + sizeof(T)) * 3 / 2;
     uint8_t* data = static_cast<uint8_t*>(realloc(data_, new_size));
-    if (data == nullptr)
-      throw std::bad_alloc();
+    if (data == nullptr) throw std::bad_alloc();
 
     data_ = data;
     data_capacity_ = new_size;
@@ -123,27 +138,22 @@ void Parcel::Impl::Write(T d) {
 }
 
 int Parcel::Impl::ReadSize(uint32_t* size) {
-  if (data_size_ == 0)
-    return TIZEN_ERROR_NO_DATA;
+  if (data_size_ == 0) return TIZEN_ERROR_NO_DATA;
 
   int ret = Read<uint32_t>(size);
-  if (ret != TIZEN_ERROR_NONE)
-    return ret;
+  if (ret != TIZEN_ERROR_NONE) return ret;
 
-  if (IsBigEndian())
-    *size = GUINT32_FROM_BE(*size);
+  if (IsBigEndian()) *size = GUINT32_FROM_BE(*size);
 
   return TIZEN_ERROR_NONE;
 }
 
 template <typename T>
 int Parcel::Impl::Read(T* d) {
-  if (data_size_ == 0)
-    return TIZEN_ERROR_NO_DATA;
+  if (data_size_ == 0) return TIZEN_ERROR_NO_DATA;
 
   uint32_t size = static_cast<uint32_t>(sizeof(T));
-  if (reader_ + size > data_size_)
-    return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
+  if (reader_ + size > data_size_) return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
 
   auto* p = reinterpret_cast<uint8_t*>(d);
   memcpy(p, data_ + reader_, size);
@@ -152,38 +162,34 @@ int Parcel::Impl::Read(T* d) {
 }
 
 void* Parcel::Impl::ReadPtr(uint32_t size) {
-  if (reader_ + size > data_size_)
-    return nullptr;
+  if (reader_ + size > data_size_) return nullptr;
   auto* ptr = data_ + reader_;
   reader_ += size;
 
   return ptr;
 }
 
-void Parcel::Impl::SetByteOrder(bool big_endian) {
-  big_endian_ = big_endian;
-}
+void Parcel::Impl::SetByteOrder(bool big_endian) { big_endian_ = big_endian; }
 
-bool Parcel::Impl::IsBigEndian() const {
-  return big_endian_;
-}
+bool Parcel::Impl::IsBigEndian() const { return big_endian_; }
 
-uint8_t* Parcel::Impl::GetData() const {
-  return data_;
-}
+uint8_t* Parcel::Impl::GetData() const { return data_; }
 
-size_t Parcel::Impl::GetDataSize() const {
-  return data_size_;
-}
+size_t Parcel::Impl::GetDataSize() const { return data_size_; }
+
+bool Parcel::Impl::SetDataSize(size_t size) {
+  if (size > data_capacity_) return false;
 
-size_t Parcel::Impl::GetDataCapacity() const {
-  return data_capacity_;
+  data_size_ = size;
+  return true;
 }
 
+size_t Parcel::Impl::GetDataCapacity() const { return data_capacity_; }
+
 void Parcel::Impl::SetDataCapacity(size_t size) {
+  if (!ownership_) throw std::bad_alloc();
   uint8_t* data = static_cast<uint8_t*>(realloc(data_, size));
-  if (data == nullptr)
-    throw std::bad_alloc();
+  if (data == nullptr) throw std::bad_alloc();
 
   data_ = data;
   data_capacity_ = size;
@@ -199,70 +205,80 @@ uint8_t* Parcel::Impl::Detach(size_t* size) {
   return data;
 }
 
-uint32_t Parcel::Impl::GetReader() const {
-  return reader_;
-}
+uint32_t Parcel::Impl::GetReader() const { return reader_; }
 
 std::vector<uint8_t> Parcel::Impl::ToRaw() {
   return std::vector<uint8_t>(data_, data_ + data_size_);
 }
 
-Parcel::Parcel()
-    : impl_(new Impl(this, kDataCapacity, nullptr)) {
-  if (impl_->data_ == nullptr)
-    throw std::bad_alloc();
+void Parcel::Impl::Pin() { pin_ = true; }
+
+Parcel::Parcel() : impl_(new Impl(this, kDataCapacity, nullptr)) {
+  if (impl_->data_ == nullptr) throw std::bad_alloc();
 }
 
 Parcel::Parcel(const void* buf, uint32_t size, bool copy)
-    : impl_(new Impl(this, size,
+    : impl_(new Impl(
+          this, size,
           copy ? nullptr : static_cast<uint8_t*>(const_cast<void*>(buf)))) {
-  if (impl_->data_ == nullptr)
-    throw std::bad_alloc();
+  if (impl_->data_ == nullptr) throw std::bad_alloc();
 
-  if (copy)
-    impl_->Write(buf, size);
+  if (copy) impl_->Write(buf, size);
+}
+
+Parcel::Parcel(const Parcel& parcel, uint32_t start_pos, uint32_t size)
+    : impl_(new Impl(this, parcel.GetData() + start_pos, size)) {
+  if (!parcel.impl_->pin_) throw std::bad_alloc();
 }
 
 Parcel::~Parcel() {}
 
-Parcel::Parcel(const Parcel& p)
-  : impl_(new Impl(this, kDataCapacity)) {
+Parcel::Parcel(const Parcel& p) : impl_(new Impl(this, kDataCapacity)) {
   impl_->big_endian_ = p.impl_->big_endian_;
   impl_->data_capacity_ = p.impl_->data_capacity_;
   impl_->data_size_ = p.impl_->data_size_;
+  impl_->ownership_ = p.impl_->ownership_;
+  impl_->pin_ = p.impl_->pin_;
 
-  uint8_t* data = static_cast<uint8_t*>(
-      realloc(impl_->data_, impl_->data_capacity_));
-  if (data == nullptr)
-    throw std::bad_alloc();
+  if (impl_->ownership_) {
+    uint8_t* data =
+        static_cast<uint8_t*>(realloc(impl_->data_, impl_->data_capacity_));
+    if (data == nullptr) throw std::bad_alloc();
 
-  impl_->data_ = data;
-  memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
+    impl_->data_ = data;
+    memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
+  } else {
+    impl_->data_ = p.impl_->data_;
+  }
 
   impl_->reader_ = p.impl_->reader_;
 }
 
-Parcel& Parcel::operator = (const Parcel& p) {
+Parcel& Parcel::operator=(const Parcel& p) {
   if (this != &p) {
     impl_->big_endian_ = p.impl_->big_endian_;
     impl_->data_capacity_ = p.impl_->data_capacity_;
     impl_->data_size_ = p.impl_->data_size_;
+    impl_->ownership_ = p.impl_->ownership_;
+    impl_->pin_ = p.impl_->pin_;
 
-    uint8_t* data = static_cast<uint8_t*>(
-        realloc(impl_->data_, impl_->data_capacity_));
-    if (data == nullptr)
-      throw std::bad_alloc();
+    if (impl_->ownership_) {
+      uint8_t* data =
+          static_cast<uint8_t*>(realloc(impl_->data_, impl_->data_capacity_));
+      if (data == nullptr) throw std::bad_alloc();
 
-    impl_->data_ = data;
-    memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
+      impl_->data_ = data;
+      memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
+    } else {
+      impl_->data_ = p.impl_->data_;
+    }
 
     impl_->reader_ = p.impl_->reader_;
   }
   return *this;
 }
 
-Parcel::Parcel(Parcel&& p) noexcept
-    : impl_(new Impl(this, kDataCapacity)) {
+Parcel::Parcel(Parcel&& p) noexcept : impl_(new Impl(this, kDataCapacity)) {
   impl_->big_endian_ = p.impl_->big_endian_;
 
   impl_->data_size_ = p.impl_->data_size_;
@@ -279,9 +295,12 @@ Parcel::Parcel(Parcel&& p) noexcept
 
   impl_->reader_ = p.impl_->reader_;
   p.impl_->reader_ = 0;
+  impl_->ownership_ = p.impl_->ownership_;
+  impl_->pin_ = p.impl_->pin_;
+  p.impl_->pin_ = false;
 }
 
-Parcel& Parcel::operator = (Parcel&& p) noexcept {
+Parcel& Parcel::operator=(Parcel&& p) noexcept {
   if (this != &p) {
     impl_->big_endian_ = p.impl_->big_endian_;
 
@@ -299,86 +318,71 @@ Parcel& Parcel::operator = (Parcel&& p) noexcept {
 
     impl_->reader_ = p.impl_->reader_;
     p.impl_->reader_ = 0;
+    impl_->ownership_ = p.impl_->ownership_;
+    impl_->pin_ = p.impl_->pin_;
+    p.impl_->pin_ = false;
   }
   return *this;
 }
 
-bool Parcel::IsEmpty() const noexcept {
-  return impl_->IsEmpty();
-}
+bool Parcel::IsEmpty() const noexcept { return impl_->IsEmpty(); }
 
-void Parcel::Write(const void* buf, uint32_t size) {
-  impl_->Write(buf, size);
-}
+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::Reserve(uint32_t size) { impl_->Reserve(size); }
 
-void* Parcel::ReadPtr(uint32_t size) {
-  return impl_->ReadPtr(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::ReadPtr(uint32_t size) { return impl_->ReadPtr(size); }
 
-void Parcel::WriteByte(char val) {
-  impl_->Write<char>(val);
-}
+void Parcel::WriteBool(bool val) { impl_->Write<bool>(val); }
+
+void Parcel::WriteByte(char val) { impl_->Write<char>(val); }
 
 void Parcel::WriteUInt16(uint16_t val) {
-  if (impl_->IsBigEndian())
-    val = GUINT16_TO_BE(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);
+  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);
+  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);
+  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);
+  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);
+  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));
+  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));
+  if (impl_->IsBigEndian()) val = static_cast<double>(GINT64_TO_BE(val));
 
   impl_->Write<double>(val);
 }
@@ -393,74 +397,62 @@ void Parcel::WriteCString(const char* str) {
   impl_->Write(str, strlen(str) + 1);
 }
 
-int Parcel::ReadBool(bool* val) {
-  return impl_->Read<bool>(val);
-}
+int Parcel::ReadBool(bool* val) { return impl_->Read<bool>(val); }
 
-int Parcel::ReadByte(char* val) {
-  return impl_->Read<char>(val);
-}
+int Parcel::ReadByte(char* val) { return impl_->Read<char>(val); }
 
 int Parcel::ReadUInt16(uint16_t* val) {
   int ret = impl_->Read<uint16_t>(val);
-  if (impl_->IsBigEndian())
-    *val = GUINT16_FROM_BE(*val);
+  if (impl_->IsBigEndian()) *val = GUINT16_FROM_BE(*val);
 
   return ret;
 }
 
 int Parcel::ReadUInt32(uint32_t* val) {
   int ret = impl_->Read<uint32_t>(val);
-  if (impl_->IsBigEndian())
-    *val = GUINT32_FROM_BE(*val);
+  if (impl_->IsBigEndian()) *val = GUINT32_FROM_BE(*val);
 
   return ret;
 }
 
 int Parcel::ReadUInt64(uint64_t* val) {
   int ret = impl_->Read<uint64_t>(val);
-  if (impl_->IsBigEndian())
-    *val = GUINT64_FROM_BE(*val);
+  if (impl_->IsBigEndian()) *val = GUINT64_FROM_BE(*val);
 
   return ret;
 }
 
 int Parcel::ReadInt16(int16_t* val) {
   int ret = impl_->Read<int16_t>(val);
-  if (impl_->IsBigEndian())
-    *val = GINT16_FROM_BE(*val);
+  if (impl_->IsBigEndian()) *val = GINT16_FROM_BE(*val);
 
   return ret;
 }
 
 int Parcel::ReadInt32(int32_t* val) {
   int ret = impl_->Read<int32_t>(val);
-  if (impl_->IsBigEndian())
-    *val = GINT32_FROM_BE(*val);
+  if (impl_->IsBigEndian()) *val = GINT32_FROM_BE(*val);
 
   return ret;
 }
 
 int Parcel::ReadInt64(int64_t* val) {
   int ret = impl_->Read<int64_t>(val);
-  if (impl_->IsBigEndian())
-    *val = GINT64_FROM_BE(*val);
+  if (impl_->IsBigEndian()) *val = GINT64_FROM_BE(*val);
 
   return ret;
 }
 
 int Parcel::ReadFloat(float* val) {
   int ret = impl_->Read<float>(val);
-  if (impl_->IsBigEndian())
-    *val = static_cast<float>(GINT32_FROM_BE(*val));
+  if (impl_->IsBigEndian()) *val = static_cast<float>(GINT32_FROM_BE(*val));
 
   return ret;
 }
 
 int Parcel::ReadDouble(double* val) {
   int ret = impl_->Read<double>(val);
-  if (impl_->IsBigEndian())
-    *val = static_cast<double>(GINT64_FROM_BE(*val));
+  if (impl_->IsBigEndian()) *val = static_cast<double>(GINT64_FROM_BE(*val));
 
   return ret;
 }
@@ -493,12 +485,10 @@ std::string Parcel::ReadString() {
 int Parcel::ReadCString(char** str) {
   uint32_t len = 0;
   int ret = impl_->ReadSize(&len);
-  if (ret != TIZEN_ERROR_NONE)
-    return ret;
+  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;
+  if (val == nullptr) return TIZEN_ERROR_OUT_OF_MEMORY;
 
   ret = impl_->Read(val, len);
   if (ret != TIZEN_ERROR_NONE) {
@@ -510,21 +500,13 @@ int Parcel::ReadCString(char** str) {
   return TIZEN_ERROR_NONE;
 }
 
-void Parcel::ResetReader() {
-  impl_->ResetReader();
-}
+void Parcel::ResetReader() { impl_->ResetReader(); }
 
-bool Parcel::SetReader(uint32_t pos) {
-  return impl_->SetReader(pos);
-}
+bool Parcel::SetReader(uint32_t pos) { return impl_->SetReader(pos); }
 
-void Parcel::Clear() {
-  impl_->Clear();
-}
+void Parcel::Clear() { impl_->Clear(); }
 
-void Parcel::Reset(const void* buf, uint32_t size) {
-  impl_->Reset(buf, size);
-}
+void Parcel::Reset(const void* buf, uint32_t size) { impl_->Reset(buf, size); }
 
 void Parcel::WriteParcelable(const Parcelable& parcelable) {
   parcelable.WriteToParcel(this);
@@ -535,36 +517,24 @@ int Parcel::ReadParcelable(Parcelable* parcelable) {
   return TIZEN_ERROR_NONE;
 }
 
-void Parcel::SetByteOrder(bool big_endian) {
-  impl_->SetByteOrder(big_endian);
-}
+void Parcel::SetByteOrder(bool big_endian) { impl_->SetByteOrder(big_endian); }
 
-uint8_t* Parcel::GetData() const {
-  return impl_->GetData();
-}
+uint8_t* Parcel::GetData() const { return impl_->GetData(); }
 
-size_t Parcel::GetDataSize() const {
-  return impl_->GetDataSize();
-}
+size_t Parcel::GetDataSize() const { return impl_->GetDataSize(); }
 
-size_t Parcel::GetDataCapacity() const {
-  return impl_->GetDataCapacity();
-}
+bool Parcel::SetDataSize(size_t size) { return impl_->SetDataSize(size); }
 
-void Parcel::SetDataCapacity(size_t size) {
-  impl_->SetDataCapacity(size);
-}
+size_t Parcel::GetDataCapacity() const { return impl_->GetDataCapacity(); }
 
-uint8_t* Parcel::Detach(size_t* size) {
-  return impl_->Detach(size);
-}
+void Parcel::SetDataCapacity(size_t size) { impl_->SetDataCapacity(size); }
 
-uint32_t Parcel::GetReader() const {
-  return impl_->GetReader();
-}
+uint8_t* Parcel::Detach(size_t* size) { return impl_->Detach(size); }
 
-std::vector<uint8_t> Parcel::ToRaw() {
-  return impl_->ToRaw();
-}
+uint32_t Parcel::GetReader() const { return impl_->GetReader(); }
+
+std::vector<uint8_t> Parcel::ToRaw() { return impl_->ToRaw(); }
+
+void Parcel::Pin() { return impl_->Pin(); }
 
 }  // namespace tizen_base
index e934f3fe4545ef70b5364f4f761acd390a55a650..1fc1e381bea0ce8f72410313d8fa984e04428c55 100644 (file)
@@ -67,6 +67,15 @@ class EXPORT Parcel final {
    */
   Parcel(const void* buf, uint32_t size, bool copy = true);
 
+  /**
+   * @brief Construct from Parcel object.
+   * @since_tizen 10.0
+   * @param[in] parcel Fixed source parcel
+   * @param[in] start_pos The start position
+   * @param[in] size The size
+   */
+  Parcel(const Parcel& parcel, uint32_t start_pos, uint32_t size);
+
   /**
    * @brief Destructor
    * @since_tizen 6.5
@@ -116,6 +125,13 @@ class EXPORT Parcel final {
    */
   void Write(const void* buf, uint32_t size);
 
+  /**
+   * @brief Reserves bytes to write later.
+   * @since_tizen 10.0
+   * @param[in] size The size of bytes to reserve
+   */
+  void Reserve(uint32_t size);
+
   /**
    * @brief Reads bytes from the parcel.
    * @since_tizen 6.5
@@ -403,6 +419,14 @@ class EXPORT Parcel final {
    */
   size_t GetDataSize() const;
 
+  /**
+   * @breif Sets the size of the raw data of the parcel.
+   * @since_tizen 10.0
+   * @return @c true on success,
+   * otherwise false
+   */
+  bool SetDataSize(size_t size);
+
   /**
    * @brief Gets the size of the data capacity of the parcel.
    * @since_tizen 7.0
@@ -439,6 +463,12 @@ class EXPORT Parcel final {
    */
   std::vector<uint8_t> ToRaw();
 
+  /**
+   * @brief Pin the memory. Once it is called, the capacity would not be changed.
+   * @since_tizen 10.0
+   */
+  void Pin();
+
  private:
   class Impl;
   std::unique_ptr<Impl> impl_;
index dbf076a366e2167036b2fc25edcfc32c05889414..fbedc0844daa01470a835a812efd359d9a1e6f74 100644 (file)
@@ -44,20 +44,24 @@ class Parcel::Impl {
   template <typename T>
   int Read(T* d);
 
+  void Reserve(uint32_t size);
   void* ReadPtr(uint32_t size);
   void SetByteOrder(bool big_endian);
   bool IsBigEndian() const;
   uint8_t* GetData() const;
   size_t GetDataSize() const;
+  bool SetDataSize(size_t size);
   size_t GetDataCapacity() const;
   void SetDataCapacity(size_t size);
   uint8_t* Detach(size_t* size);
   uint32_t GetReader() const;
   std::vector<uint8_t> ToRaw();
+  void Pin();
 
  private:
   friend class Parcel;
   explicit Impl(Parcel* parent, size_t data_capacity, uint8_t* data = nullptr);
+  explicit Impl(Parcel* parent, uint8_t* start_pos, size_t data_size);
 
  private:
   Parcel* parent_;
@@ -66,6 +70,8 @@ class Parcel::Impl {
   size_t data_size_ = 0;
   uint8_t* data_ = nullptr;
   uint32_t reader_ = 0;
+  bool ownership_ = true;
+  bool pin_ = false;
 };
 
 }  // naemspace tizen_base
index 3c6b73a7320b887dc5e5ca9d5c2ae2acf3b3fbdc..ff872d906e00f4aa84439aa5f36ef314728b8786 100644 (file)
@@ -287,3 +287,92 @@ TEST_F(ParcelCppTest, ToRaw) {
   auto raw = GetHandle().ToRaw();
   ASSERT_EQ(raw.size(), sizeof(int32_t));
 }
+
+TEST_F(ParcelCppTest, SubParcel) {
+  auto& p = GetHandle();
+
+  p.Reserve(400);
+  p.Pin();
+
+  Parcel w1(p, 0, 100);
+  Parcel w2(p, 100, 100);
+  Parcel w3(p, 200, 100);
+  Parcel w4(p, 300, 100);
+
+  w1.WriteString("Test subparcel1 1");
+  w2.WriteString("Test subparcel2 1");
+  w3.WriteString("Test subparcel3 1");
+  w4.WriteString("Test subparcel4 1");
+  w1.WriteString("Test subparcel1 2");
+  w2.WriteString("Test subparcel2 2");
+  w3.WriteString("Test subparcel3 2");
+  w4.WriteString("Test subparcel4 2");
+
+  Parcel r1(p, 0, 100);
+  Parcel r2(p, 100, 100);
+  Parcel r3(p, 200, 100);
+  Parcel r4(p, 300, 100);
+  r1.Reserve(100);
+  r2.Reserve(100);
+  r3.Reserve(100);
+  r4.Reserve(100);
+
+  ASSERT_EQ(r1.ReadString(), "Test subparcel1 1");
+  ASSERT_EQ(r1.ReadString(), "Test subparcel1 2");
+
+  ASSERT_EQ(r3.ReadString(), "Test subparcel3 1");
+  ASSERT_EQ(r3.ReadString(), "Test subparcel3 2");
+
+  ASSERT_EQ(r2.ReadString(), "Test subparcel2 1");
+  ASSERT_EQ(r2.ReadString(), "Test subparcel2 2");
+
+  ASSERT_EQ(r4.ReadString(), "Test subparcel4 1");
+  ASSERT_EQ(r4.ReadString(), "Test subparcel4 2");
+}
+
+TEST_F(ParcelCppTest, SubParcel2) {
+  auto& p = GetHandle();
+  int pos0 = p.GetDataSize();
+
+  p.WriteString("Test subparcel1 1");
+  p.WriteString("Test subparcel1 2");
+  int pos1 = p.GetDataSize();
+  p.WriteString("Test subparcel2 1");
+  p.WriteString("Test subparcel2 2");
+  int pos2 = p.GetDataSize();
+  p.WriteString("Test subparcel3 1");
+  p.WriteString("Test subparcel3 2");
+  int pos3 = p.GetDataSize();
+  p.WriteString("Test subparcel4 1");
+  p.WriteString("Test subparcel4 2");
+  int pos4 = p.GetDataSize();
+  p.Pin();
+
+  Parcel r1(p, pos0, pos1 - pos0);
+  Parcel r2(p, pos1, pos2 - pos1);
+  Parcel r3(p, pos2, pos3 - pos2);
+  Parcel r4(p, pos3, pos4 - pos3);
+  r1.Reserve(pos1 - pos0);
+  r2.Reserve(pos2 - pos1);
+  r3.Reserve(pos3 - pos2);
+  r4.Reserve(pos4 - pos3);
+
+  ASSERT_EQ(r1.ReadString(), "Test subparcel1 1");
+  ASSERT_EQ(r1.ReadString(), "Test subparcel1 2");
+
+  ASSERT_EQ(r3.ReadString(), "Test subparcel3 1");
+  ASSERT_EQ(r3.ReadString(), "Test subparcel3 2");
+
+  ASSERT_EQ(r2.ReadString(), "Test subparcel2 1");
+  ASSERT_EQ(r2.ReadString(), "Test subparcel2 2");
+
+  ASSERT_EQ(r4.ReadString(), "Test subparcel4 1");
+  ASSERT_EQ(r4.ReadString(), "Test subparcel4 2");
+}
+
+TEST_F(ParcelCppTest, SubParcel_N) {
+  auto& p = GetHandle();
+  p.Reserve(400);
+
+  EXPECT_THROW(Parcel w1(p, 0, 100), std::bad_alloc);
+}