Add ResultParcelable (#59)
author김일호/Tizen Platform Lab(SR)/Engineer/삼성전자 <ilho159.kim@samsung.com>
Thu, 18 Feb 2021 03:47:10 +0000 (12:47 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Thu, 18 Feb 2021 03:47:10 +0000 (12:47 +0900)
* Add ResultParcelable

Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
src/CMakeLists.txt
src/common/parcel/result_parcelable.cc [new file with mode: 0644]
src/common/parcel/result_parcelable.hh [new file with mode: 0644]
src/server/CMakeLists.txt
test/unit_tests/CMakeLists.txt
test/unit_tests/test_parcel.cc

index 0b06e0b..e2e712b 100644 (file)
@@ -16,7 +16,7 @@ ADD_LIBRARY(pkgmgr-info SHARED
 )
 
 ## Compile flags
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpic -std=c++14")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpic -std=c++17")
 
 SET_TARGET_PROPERTIES(pkgmgr-info PROPERTIES SOVERSION ${MAJORVER})
 SET_TARGET_PROPERTIES(pkgmgr-info PROPERTIES VERSION ${FULLVER})
diff --git a/src/common/parcel/result_parcelable.cc b/src/common/parcel/result_parcelable.cc
new file mode 100644 (file)
index 0000000..151aeb8
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2021 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 "result_parcelable.hh"
+
+#include <vector>
+
+namespace pkgmgr_common {
+namespace parcel {
+
+void RemoveArgs() {}
+
+void RemoveArg(char *str) {
+  if (str == nullptr)
+    return;
+
+  free(str);
+}
+
+void RemoveArg(int n) {}
+
+template<typename T, typename... SubArgs>
+void RemoveArgs(T t, SubArgs... args) {
+  RemoveArg(t);
+  RemoveArgs(args...);
+}
+
+template<typename... Args>
+ResultParcelable<Args...>::ResultParcelable(
+    std::vector<std::tuple<Args...>>&& args) : args_(std::move(args)) {}
+
+template<typename... Args>
+ResultParcelable<Args...>::~ResultParcelable() {
+  for (auto& arg : args_) {
+    std::apply([](auto&... xs) {
+                  (RemoveArgs(xs), ...);
+                 }, arg);
+  }
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::WriteToParcel(
+    tizen_base::Parcel* parcel) const {
+  WriteInt(parcel, args_.size());
+
+  for (const std::tuple<Args...>& arg : args_) {
+    auto tmp_tuple = std::tuple_cat(std::make_tuple(this, parcel), arg);
+    std::apply([](const ResultParcelable<Args...> *a,
+                      tizen_base::Parcel *parcel, auto&... xs) {
+                  (a->WriteArgs(parcel, xs), ...);
+                 }, tmp_tuple);
+  }
+}
+
+template <std::size_t... Ns , typename... Ts>
+auto tail_impl(std::index_sequence<Ns...> , std::tuple<Ts...> t) {
+  return  std::make_tuple(std::get<Ns+2u>(t)...);
+}
+
+template <typename... Ts>
+auto tail(std::tuple<Ts...> t) {
+  return  tail_impl(std::make_index_sequence<sizeof...(Ts) - 2u>(), t);
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::ReadFromParcel(tizen_base::Parcel* parcel) {
+  int len = 0;
+  ReadInt(parcel, &len);
+
+  for (int i = 0; i < len ; ++i) {
+    std::tuple<ResultParcelable<Args...> *, tizen_base::Parcel *, Args...> tmp_tuple;
+    std::get<0>(tmp_tuple) = this;
+    std::get<1>(tmp_tuple) = parcel;
+    std::apply([](ResultParcelable<Args...> *a,
+                      tizen_base::Parcel *parcel, auto&... xs) {
+                  (a->ReadArgs(parcel, &xs), ...);
+                 }, tmp_tuple);
+    auto result = tail(tmp_tuple);
+    args_.emplace_back(std::move(result));
+  }
+}
+
+template<typename... Args>
+const std::vector<std::tuple<Args...>>& ResultParcelable<Args...>::GetResult() {
+  return args_;
+}
+
+template<typename... Args>
+template<typename T, typename... SubArgs>
+void ResultParcelable<Args...>::WriteArgs(
+    tizen_base::Parcel* parcel, const T& t, const SubArgs&... args) const {
+  WriteArg(parcel, t);
+  WriteArgs(parcel, args...);
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::WriteArgs(tizen_base::Parcel *parcel) const {}
+
+template<typename... Args>
+void ResultParcelable<Args...>::WriteArg(
+    tizen_base::Parcel* parcel, const char *str) const {
+  WriteString(parcel, str);
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::WriteArg(
+    tizen_base::Parcel* parcel, const int n) const {
+  WriteInt(parcel, n);
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::ReadArgs(tizen_base::Parcel* parcel) {}
+
+template<typename... Args>
+template<typename T, typename... SubArgs>
+void ResultParcelable<Args...>::ReadArgs(
+    tizen_base::Parcel* parcel, T* t, SubArgs*... args) {
+  ReadArg(parcel, t);
+  ReadArgs(parcel, args...);
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::ReadArg(
+    tizen_base::Parcel* parcel, char **str) {
+  ReadString(parcel, str);
+}
+
+template<typename... Args>
+void ResultParcelable<Args...>::ReadArg(
+    tizen_base::Parcel* parcel, int* n) {
+  ReadInt(parcel, n);
+}
+
+// for unit test
+template class ResultParcelable<char *, int>;
+
+}  // namespace parcel
+}  // namespace pkgmgr_common
diff --git a/src/common/parcel/result_parcelable.hh b/src/common/parcel/result_parcelable.hh
new file mode 100644 (file)
index 0000000..4d63099
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef RESULT_PARCELABLE_HH_
+#define RESULT_PARCELABLE_HH_
+
+#include "abstract_parcelable.hh"
+
+#include <vector>
+#include <tuple>
+
+namespace pkgmgr_common {
+namespace parcel {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+template <typename... Args>
+class EXPORT_API ResultParcelable : public AbstractParcelable {
+ public:
+  class EXPORT_API Factory : IFactory {
+   public:
+    std::unique_ptr<AbstractParcelable> CreateParcel();
+  };
+
+  ResultParcelable() = default;
+  ResultParcelable(std::vector<std::tuple<Args...>>&& args);
+  ~ResultParcelable();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+  template<typename T, typename... SubArgs>
+  void WriteArgs(tizen_base::Parcel* parcel, const T& t, const SubArgs&... arg) const;
+  void WriteArgs(tizen_base::Parcel* parcel) const;
+
+  template<typename T, typename... SubArgs>
+  void ReadArgs(tizen_base::Parcel* parcel, T* t, SubArgs*... args);
+  void ReadArgs(tizen_base::Parcel* parcel);
+
+  const std::vector<std::tuple<Args...>>& GetResult();
+
+ private:
+  void WriteArg(tizen_base::Parcel* parcel, const char *str) const;
+  void WriteArg(tizen_base::Parcel* parcel, int n) const;
+  void ReadArg(tizen_base::Parcel* parcel, char **str);
+  void ReadArg(tizen_base::Parcel* parcel, int* n);
+
+  std::vector<std::tuple<Args...>> args_;
+};
+
+}  // namespace parcel
+}  // namespace pkgmgr_common
+
+#endif  // RESULT_PARCELABLE_HH_
index 5066bfc..df4f893 100644 (file)
@@ -11,7 +11,7 @@ INCLUDE_DIRECTORIES(
 )
 
 ADD_EXECUTABLE(${PKGINFO_SERVER} ${PKGINFO_SERVER_SRCS})
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpic -std=c++14 -pthread")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpic -std=c++17 -pthread")
 
 TARGET_LINK_LIBRARIES(${PKGINFO_SERVER} ${libpkgs_LDFLAGS})
 TARGET_LINK_LIBRARIES(${PKGINFO_SERVER} ${libpkgmgr-parser_LDFLAGS})
index c129f1b..c8f70f0 100644 (file)
@@ -10,14 +10,14 @@ ADD_EXECUTABLE(${TARGET_PKGMGR_INFO_UNIT_TEST}
 )
 
 include(FindPkgConfig)
-pkg_check_modules(unit_test_pkgs REQUIRED dlog glib-2.0 gio-2.0 sqlite3 gmock)
+pkg_check_modules(unit_test_pkgs REQUIRED dlog glib-2.0 gio-2.0 sqlite3 gmock parcel)
 
 FOREACH(flag ${unit_test_pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
 ## Compile flags
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpic -std=c++14")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpic -std=c++17")
 
 TARGET_LINK_LIBRARIES(${TARGET_PKGMGR_INFO_UNIT_TEST} ${libpkgs_LDFLAGS})
 TARGET_LINK_LIBRARIES(${TARGET_PKGMGR_INFO_UNIT_TEST} ${libpkgmgr-parser_LDFLAGS})
index 8e9a237..b588b51 100644 (file)
 #include <cstdio>
 #include <parcel.hh>
 #include <iostream>
+#include <tuple>
 
 #include "common/parcel/abstract_parcelable.hh"
 #include "common/parcel/appinfo_parcelable.hh"
 #include "common/parcel/certinfo_parcelable.hh"
 #include "common/parcel/filter_parcelable.hh"
 #include "common/parcel/pkginfo_parcelable.hh"
+#include "common/parcel/result_parcelable.hh"
 #include "common/parcel/string_parcelable.hh"
 
 #include "pkgmgrinfo_basic.h"
@@ -168,3 +170,26 @@ TEST_F(ParcelTest, CertInfoParcelable) {
   EXPECT_TRUE(IsEqualCertInfo(
       origin_parcelable.GetCertInfo(), new_parcelable.GetCertInfo()));
 }
+
+TEST_F(ParcelTest, ResultParcelable) {
+  tizen_base::Parcel parcel;
+  std::vector<std::tuple<char *, int>> vt;
+  vt.emplace_back(std::make_tuple(strdup("a"), 1));
+  vt.emplace_back(std::make_tuple(strdup("c"), 2));
+
+  pp::ResultParcelable<char *, int> origin_parcelable(std::move(vt));
+  pp::ResultParcelable<char *, int> new_parcelable;
+  parcel.WriteParcelable(origin_parcelable);
+  parcel.ReadParcelable(&new_parcelable);
+
+  const std::vector<std::tuple<char *, int>>& origin_result = origin_parcelable.GetResult();
+  const std::vector<std::tuple<char *, int>>& new_result = new_parcelable.GetResult();
+
+  EXPECT_EQ(origin_result.size(), new_result.size());
+  for (unsigned int i = 0; i < origin_result.size(); ++i) {
+    const std::tuple<char *, int> a = origin_result[i];
+    const std::tuple<char *, int> b = new_result[i];
+    EXPECT_EQ(strcmp(std::get<0>(a), std::get<0>(b)), 0);
+    EXPECT_EQ(std::get<1>(a), std::get<1>(b));
+  }
+}