From 8eef1ad691baff3d770183ecccf3927a394ca528 Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Fri, 6 Mar 2020 08:49:59 +0100
Subject: [PATCH 01/10] Refs #7837. Remove friend class ParameterList from
 QosPolicies

---
 include/fastrtps/qos/QosPolicies.h | 46 ------------------------------
 1 file changed, 46 deletions(-)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index af90ce7bad3..7f004ccd4c4 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -108,8 +108,6 @@ typedef enum DurabilityQosPolicyKind : rtps::octet
  */
 class DurabilityQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI DurabilityQosPolicy()
@@ -199,8 +197,6 @@ class DurabilityQosPolicy : public Parameter_t, public QosPolicy
  */
 class DeadlineQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI DeadlineQosPolicy()
@@ -258,8 +254,6 @@ class DeadlineQosPolicy : public Parameter_t, public QosPolicy
  */
 class LatencyBudgetQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI LatencyBudgetQosPolicy()
@@ -332,8 +326,6 @@ typedef enum LivelinessQosPolicyKind : rtps::octet
  */
 class LivelinessQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI LivelinessQosPolicy()
@@ -404,8 +396,6 @@ typedef enum ReliabilityQosPolicyKind : rtps::octet
  */
 class ReliabilityQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI ReliabilityQosPolicy()
@@ -492,8 +482,6 @@ enum OwnershipQosPolicyKind : rtps::octet
  */
 class OwnershipQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI OwnershipQosPolicy()
@@ -562,8 +550,6 @@ enum DestinationOrderQosPolicyKind : rtps::octet
  */
 class DestinationOrderQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI DestinationOrderQosPolicy()
@@ -620,7 +606,6 @@ class DestinationOrderQosPolicy : public Parameter_t, public QosPolicy
  */
 class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceLimitedVector<rtps::octet>
 {
-    friend class ParameterList;
     using ResourceLimitedOctetVector = ResourceLimitedVector<rtps::octet>;
 
 public:
@@ -817,8 +802,6 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
  */
 class TimeBasedFilterQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI TimeBasedFilterQosPolicy()
@@ -890,8 +873,6 @@ enum PresentationQosPolicyAccessScopeKind : rtps::octet
  */
 class PresentationQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI PresentationQosPolicy()
@@ -1004,7 +985,6 @@ class Partition_t
  */
 class PartitionQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
     friend class rtps::EDP;
 
 public:
@@ -1285,8 +1265,6 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy
  */
 class TopicDataQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI TopicDataQosPolicy()
@@ -1387,8 +1365,6 @@ class TopicDataQosPolicy : public Parameter_t, public QosPolicy
  */
 class GroupDataQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI GroupDataQosPolicy()
@@ -1500,8 +1476,6 @@ enum HistoryQosPolicyKind : rtps::octet
  */
 class HistoryQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI HistoryQosPolicy()
@@ -1564,8 +1538,6 @@ class HistoryQosPolicy : public Parameter_t, public QosPolicy
  */
 class ResourceLimitsQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     int32_t max_samples;
@@ -1627,8 +1599,6 @@ class ResourceLimitsQosPolicy : public Parameter_t, public QosPolicy
  */
 class DurabilityServiceQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI DurabilityServiceQosPolicy()
@@ -1699,8 +1669,6 @@ class DurabilityServiceQosPolicy : public Parameter_t, public QosPolicy
  */
 class LifespanQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI LifespanQosPolicy()
@@ -1757,8 +1725,6 @@ class LifespanQosPolicy : public Parameter_t, public QosPolicy
  */
 class OwnershipStrengthQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI OwnershipStrengthQosPolicy()
@@ -1818,8 +1784,6 @@ class OwnershipStrengthQosPolicy : public Parameter_t, public QosPolicy
  */
 class TransportPriorityQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     uint32_t value;
@@ -1909,8 +1873,6 @@ typedef enum DataRepresentationId : int16_t
  */
 class DataRepresentationQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     std::vector<DataRepresentationId_t> m_value;
@@ -1958,8 +1920,6 @@ enum TypeConsistencyKind : uint16_t
  */
 class TypeConsistencyEnforcementQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     TypeConsistencyKind m_kind;
@@ -2016,8 +1976,6 @@ class TypeConsistencyEnforcementQosPolicy : public Parameter_t, public QosPolicy
  */
 class DisablePositiveACKsQosPolicy : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     RTPS_DllAPI DisablePositiveACKsQosPolicy()
@@ -2077,8 +2035,6 @@ class DisablePositiveACKsQosPolicy : public Parameter_t, public QosPolicy
  */
 class TypeIdV1 : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     types::TypeIdentifier m_type_identifier;
@@ -2166,8 +2122,6 @@ class TypeIdV1 : public Parameter_t, public QosPolicy
  */
 class TypeObjectV1 : public Parameter_t, public QosPolicy
 {
-    friend class ParameterList;
-
 public:
 
     types::TypeObject m_type_object;

From 0031338f3b4a283983f8c68f021fa36bf89e91ca Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Fri, 6 Mar 2020 10:03:30 +0100
Subject: [PATCH 02/10] Refs #7837. Added octet vector (de)serialization
 methods to QosPolicy.

---
 include/fastrtps/qos/QosPolicies.h | 11 +++++++
 src/cpp/qos/QosPolicies.cpp        | 50 ++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index 7f004ccd4c4..0fa8f427665 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -79,6 +79,17 @@ class QosPolicy
     static uint32_t get_cdr_serialized_size(
             const std::vector<rtps::octet>& data);
 
+    static bool serialize_generic_data(
+            rtps::CDRMessage_t* msg,
+            uint16_t pid,
+            const std::vector<rtps::octet>& data);
+
+    static bool deserialize_generic_data(
+            rtps::CDRMessage_t* msg,
+            uint16_t size,
+            size_t max_size,
+            std::vector<rtps::octet>& data);
+
 public:
 
     bool hasChanged;
diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp
index 94149d2f8e2..ac2eb238b6e 100644
--- a/src/cpp/qos/QosPolicies.cpp
+++ b/src/cpp/qos/QosPolicies.cpp
@@ -39,6 +39,56 @@ uint32_t QosPolicy::get_cdr_serialized_size(
     return 2 + 2 + 4 + data_size;
 }
 
+bool QosPolicy::serialize_generic_data(
+        rtps::CDRMessage_t* msg,
+        uint16_t pid,
+        const std::vector<rtps::octet>& data)
+{
+    bool valid = CDRMessage::addUInt16(msg, pid);
+    uint16_t siz = static_cast<uint16_t>(data.size());
+    siz = (siz + 3) & ~3;
+    valid &= CDRMessage::addUInt16(msg, static_cast<uint16_t>(4 + siz));
+    valid &= CDRMessage::addUInt32(msg, siz);
+    valid &= CDRMessage::addOctetVector(msg, &data, true);
+    return valid;
+}
+
+bool QosPolicy::deserialize_generic_data(
+        rtps::CDRMessage_t* msg,
+        uint16_t size,
+        size_t max_size,
+        std::vector<rtps::octet>& data)
+{
+    uint32_t pos_ref = msg->pos;
+
+    // Read size of data
+    uint32_t len;
+    if (!CDRMessage::readUInt32(msg, &len))
+    {
+        return false;
+    }
+
+    if ( (len + sizeof(uint32_t) > size)  // Exceeds parameter length
+        || (len > max_size) )             // Exceeds size limit
+    {
+        return false;
+    }
+
+    // Either the data is size limited and already has max_size() allocated
+    // or it is not limited and we resize if needed
+    data.resize(len);
+    if (!CDRMessage::readData(msg, data.data(), len))
+    {
+        return false;
+    }
+
+    // Skip padding
+    msg->pos += (len - (len + 3) & ~3);
+
+    // Should have consumed whole size
+    return (pos_ref + size == msg->pos);
+}
+
 bool DurabilityQosPolicy::addToCDRMessage(
         CDRMessage_t* msg) const
 {

From d97650c3f18e2241266cd8da8a34e3ede475d913 Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Fri, 6 Mar 2020 10:06:25 +0100
Subject: [PATCH 03/10] Refs #7837. Templatization of UserDataQosPolicy into
 GenericDataQosPolicy

---
 include/fastrtps/qos/QosPolicies.h | 62 ++++++++++++++++++------------
 src/cpp/qos/QosPolicies.cpp        | 32 ---------------
 2 files changed, 38 insertions(+), 56 deletions(-)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index 0fa8f427665..14b9787944e 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -613,40 +613,41 @@ class DestinationOrderQosPolicy : public Parameter_t, public QosPolicy
 
 
 /**
- * Class UserDataQosPolicy, to transmit user data during the discovery phase.
+ * Class GenericDataQosPolicy, base class to transmit user data during the discovery phase.
  */
-class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceLimitedVector<rtps::octet>
+template<ParameterId_t TPid>
+class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceLimitedVector<rtps::octet>
 {
     using ResourceLimitedOctetVector = ResourceLimitedVector<rtps::octet>;
 
 public:
 
-    RTPS_DllAPI UserDataQosPolicy()
-        : Parameter_t(PID_USER_DATA, 0)
+    RTPS_DllAPI GenericDataQosPolicy()
+        : Parameter_t(TPid, 0)
         , QosPolicy(false)
         , ResourceLimitedOctetVector()
     {
     }
 
-    RTPS_DllAPI UserDataQosPolicy(
+    RTPS_DllAPI GenericDataQosPolicy(
             uint16_t in_length)
-        : Parameter_t(PID_USER_DATA, in_length)
+        : Parameter_t(TPid, in_length)
         , QosPolicy(false)
         , ResourceLimitedOctetVector()
     {
     }
 
     /**
-     * Construct from another UserDataQosPolicy.
+     * Construct from another GenericDataQosPolicy.
      *
-     * The resulting UserDataQosPolicy will have the same size limits
+     * The resulting GenericDataQosPolicy will have the same size limits
      * as the input attribute
      *
      * @param data data to copy in the newly created object
      */
-    RTPS_DllAPI UserDataQosPolicy(
-            const UserDataQosPolicy& data)
-        : Parameter_t(PID_USER_DATA, data.length)
+    RTPS_DllAPI GenericDataQosPolicy(
+            const GenericDataQosPolicy& data)
+        : Parameter_t(TPid, data.length)
         , QosPolicy(false)
         , ResourceLimitedOctetVector(data)
     {
@@ -656,20 +657,20 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
      * Construct from underlying collection type.
      *
      * Useful to easy integration on old APIs where a traditional container was used.
-     * The resulting UserDataQosPolicy will always be unlimited in size
+     * The resulting GenericDataQosPolicy will always be unlimited in size
      *
      * @param data data to copy in the newly created object
      */
-    RTPS_DllAPI UserDataQosPolicy(
+    RTPS_DllAPI GenericDataQosPolicy(
             const collection_type& data)
-        : Parameter_t(PID_USER_DATA, 0)
+        : Parameter_t(TPid, 0)
         , QosPolicy(false)
         , ResourceLimitedOctetVector()
     {
         assign(data.begin(), data.end());
     }
 
-    virtual RTPS_DllAPI ~UserDataQosPolicy()
+    virtual RTPS_DllAPI ~GenericDataQosPolicy()
     {
     }
 
@@ -677,14 +678,14 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
      * Copies data from underlying collection type.
      *
      * Useful to easy integration on old APIs where a traditional container was used.
-     * The resulting UserDataQosPolicy will keep the current size limit.
+     * The resulting GenericDataQosPolicy will keep the current size limit.
      * If the input data is larger than the current limit size, the elements exceeding
      * that maximum will be silently discarded.
      *
      * @param b object to be copied
      * @return reference to the current object.
      */
-    UserDataQosPolicy& operator =(
+    GenericDataQosPolicy& operator =(
             const collection_type& b)
     {
         if (collection_ != b)
@@ -698,16 +699,16 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
     }
 
     /**
-     * Copies another UserDataQosPolicy.
+     * Copies another GenericDataQosPolicy.
      *
-     * The resulting UserDataQosPolicy will have the same size limit
+     * The resulting GenericDataQosPolicy will have the same size limit
      * as the input parameter, so all data in the input will be copied.
      *
      * @param b object to be copied
      * @return reference to the current object.
      */
-    UserDataQosPolicy& operator =(
-            const UserDataQosPolicy& b)
+    GenericDataQosPolicy& operator =(
+            const GenericDataQosPolicy& b)
     {
         QosPolicy::operator=(b);
         Parameter_t::operator=(b);
@@ -718,7 +719,7 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
     }
 
     bool operator ==(
-            const UserDataQosPolicy& b) const
+            const GenericDataQosPolicy& b) const
     {
         return collection_ == b.collection_ &&
                Parameter_t::operator ==(b) &&
@@ -774,7 +775,10 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
      * @return True if the modified CDRMessage is valid.
      */
     bool addToCDRMessage(
-            rtps::CDRMessage_t* msg) const override;
+            rtps::CDRMessage_t* msg) const override
+    {
+        return QosPolicy::serialize_generic_data(msg, Pid, collection_);
+    }
 
     /**
      * Reads QoS from the specified CDR message
@@ -784,7 +788,16 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
      */
     bool readFromCDRMessage(
             rtps::CDRMessage_t* msg,
-            uint16_t size) override;
+            uint16_t size) override
+    {
+        if (QosPolicy::deserialize_generic_data(msg, size, max_size(), collection_))
+        {
+            length = size;
+            return true;
+        }
+
+        return false;
+    }
 
     /**
      * Returns raw data vector.
@@ -806,6 +819,7 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceL
     }
 };
 
+using UserDataQosPolicy = GenericDataQosPolicy<PID_USER_DATA>;
 /**
  * Class TimeBasedFilterQosPolicy, to indicate the Time Based Filter Qos.
  * This QosPolicy can be defined and is transmitted to the rest of the network but is not implemented in this version.
diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp
index ac2eb238b6e..6ec11dbb922 100644
--- a/src/cpp/qos/QosPolicies.cpp
+++ b/src/cpp/qos/QosPolicies.cpp
@@ -421,38 +421,6 @@ bool PartitionQosPolicy::readFromCDRMessage(
     return valid;
 }
 
-bool UserDataQosPolicy::addToCDRMessage(
-        CDRMessage_t* msg) const
-{
-    bool valid = CDRMessage::addUInt16(msg, Pid);
-    uint32_t siz = (uint32_t)size();
-    uint32_t align = ((siz + 3) & ~3) - siz;
-    valid &= CDRMessage::addUInt16(msg, static_cast<uint16_t>(4 + siz));
-    valid &= CDRMessage::addUInt32(msg, siz);
-    valid &= CDRMessage::addData(msg, collection_.data(), siz);
-    for (uint32_t count = 0; count < align; ++count)
-    {
-        valid &= CDRMessage::addOctet(msg, 0);
-    }
-
-    return valid;
-}
-
-bool UserDataQosPolicy::readFromCDRMessage(
-        CDRMessage_t* msg,
-        uint16_t size)
-{
-    if (size > max_size())
-    {
-        return false;
-    }
-    length = size;
-
-    //Either the data is size limited and already has max_size() allocated
-    // or it is not limited and readOctedVector will resize if needed
-    return CDRMessage::readOctetVector(msg, &collection_);
-}
-
 bool TopicDataQosPolicy::addToCDRMessage(
         CDRMessage_t* msg) const
 {

From 66fa4fe0afebd86f3664cbdcef98118ff593462c Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Fri, 6 Mar 2020 10:07:34 +0100
Subject: [PATCH 04/10] Refs #7837. Converting TopicDataQosPolicy and
 GroupDataQosPolicy.

---
 include/fastrtps/qos/QosPolicies.h | 223 +++--------------------------
 src/cpp/qos/QosPolicies.cpp        |  44 ------
 2 files changed, 22 insertions(+), 245 deletions(-)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index 14b9787944e..e69470c316b 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -817,9 +817,31 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
     {
         assign(vec.begin(), vec.end());
     }
+
+    /**
+     * Returns raw data vector.
+     * @return raw data as vector of octets.
+     * */
+    RTPS_DllAPI inline std::vector<rtps::octet> getValue() const
+    {
+        return collection_;
+    }
+
+    /**
+     * Sets raw data vector.
+     * @param vec raw data to set.
+     * */
+    RTPS_DllAPI inline void setValue(
+            const std::vector<rtps::octet>& vec)
+    {
+        assign(vec.begin(), vec.end());
+    }
 };
 
 using UserDataQosPolicy = GenericDataQosPolicy<PID_USER_DATA>;
+using TopicDataQosPolicy = GenericDataQosPolicy<PID_TOPIC_DATA>;
+using GroupDataQosPolicy = GenericDataQosPolicy<PID_GROUP_DATA>;
+
 /**
  * Class TimeBasedFilterQosPolicy, to indicate the Time Based Filter Qos.
  * This QosPolicy can be defined and is transmitted to the rest of the network but is not implemented in this version.
@@ -1284,207 +1306,6 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy
     uint32_t Npartitions_;
 };
 
-
-/**
- * Class TopicDataQosPolicy, to indicate the Topic Data.
- */
-class TopicDataQosPolicy : public Parameter_t, public QosPolicy
-{
-public:
-
-    RTPS_DllAPI TopicDataQosPolicy()
-        : Parameter_t(PID_TOPIC_DATA, 0)
-        , QosPolicy(false)
-        , value{}
-    {
-    }
-
-    RTPS_DllAPI TopicDataQosPolicy(
-            uint16_t in_length)
-        : Parameter_t(PID_TOPIC_DATA, in_length)
-        , QosPolicy(false)
-        , value{}
-    {
-    }
-
-    virtual RTPS_DllAPI ~TopicDataQosPolicy()
-    {
-    }
-
-    bool operator ==(
-            const TopicDataQosPolicy& b) const
-    {
-        return (this->value == b.value) &&
-               Parameter_t::operator ==(b) &&
-               QosPolicy::operator ==(b);
-    }
-
-    virtual uint32_t cdr_serialized_size() const override
-    {
-        return QosPolicy::get_cdr_serialized_size(value);
-    }
-
-    /**
-     * Appends QoS to the specified CDR message.
-     * @param msg Message to append the QoS Policy to.
-     * @return True if the modified CDRMessage is valid.
-     */
-    bool addToCDRMessage(
-            rtps::CDRMessage_t* msg) const override;
-
-    /**
-     * Reads QoS from the specified CDR message
-     * @param msg Message from where the QoS Policy has to be taken.
-     * @param size Size of the QoS Policy field to read
-     * @return True if the parameter was correctly taken.
-     */
-    bool readFromCDRMessage(
-            rtps::CDRMessage_t* msg,
-            uint16_t size) override;
-
-    /**
-     * Appends topic data.
-     * @param oc Data octet.
-     */
-    RTPS_DllAPI inline void push_back(
-            rtps::octet oc)
-    {
-        value.push_back(oc);
-    }
-
-    /**
-     * Clears all topic data.
-     */
-    RTPS_DllAPI inline void clear() override
-    {
-        value.clear();
-        hasChanged = true;
-    }
-
-    /**
-     * Overrides topic data vector.
-     * @param ocv Topic data octet vector.
-     */
-    RTPS_DllAPI inline void setValue(
-            std::vector<rtps::octet> ocv)
-    {
-        value = ocv;
-    }
-
-    /**
-     * Returns topic data
-     * @return Vector of data octets.
-     */
-    RTPS_DllAPI inline std::vector<rtps::octet> getValue() const
-    {
-        return value;
-    }
-
-private:
-
-    std::vector<rtps::octet> value;
-};
-
-/**
- * Class GroupDataQosPolicy, to indicate the Group Data.
- */
-class GroupDataQosPolicy : public Parameter_t, public QosPolicy
-{
-public:
-
-    RTPS_DllAPI GroupDataQosPolicy()
-        : Parameter_t(PID_GROUP_DATA, 0)
-        , QosPolicy(false)
-        , value{}
-    {
-    }
-
-    RTPS_DllAPI GroupDataQosPolicy(
-            uint16_t in_length)
-        : Parameter_t(PID_GROUP_DATA, in_length)
-        , QosPolicy(false)
-        , value{}
-    {
-    }
-
-    virtual RTPS_DllAPI ~GroupDataQosPolicy()
-    {
-    }
-
-    bool operator ==(
-            const GroupDataQosPolicy& b) const
-    {
-        return (this->value == b.value) &&
-               Parameter_t::operator ==(b) &&
-               QosPolicy::operator ==(b);
-    }
-
-    virtual uint32_t cdr_serialized_size() const override
-    {
-        return QosPolicy::get_cdr_serialized_size(value);
-    }
-
-    /**
-     * Appends QoS to the specified CDR message.
-     * @param msg Message to append the QoS Policy to.
-     * @return True if the modified CDRMessage is valid.
-     */
-    bool addToCDRMessage(
-            rtps::CDRMessage_t* msg) const override;
-
-    /**
-     * Reads QoS from the specified CDR message
-     * @param msg Message from where the QoS Policy has to be taken.
-     * @param size Size of the QoS Policy field to read
-     * @return True if the parameter was correctly taken.
-     */
-    bool readFromCDRMessage(
-            rtps::CDRMessage_t* msg,
-            uint16_t size) override;
-
-    /**
-     * Appends group data.
-     * @param oc Data octet.
-     */
-    RTPS_DllAPI inline void push_back(
-            rtps::octet oc)
-    {
-        value.push_back(oc);
-    }
-
-    /**
-     * Clears all group data.
-     */
-    RTPS_DllAPI inline void clear() override
-    {
-        value.clear();
-        hasChanged = true;
-    }
-
-    /**
-     * Overrides group data vector.
-     * @param ocv Group data octet vector.
-     */
-    RTPS_DllAPI inline void setValue(
-            std::vector<rtps::octet> ocv)
-    {
-        value = ocv;
-    }
-
-    /**
-     * Returns group data
-     * @return Vector of data octets.
-     */
-    RTPS_DllAPI inline std::vector<rtps::octet> getValue() const
-    {
-        return value;
-    }
-
-private:
-
-    std::vector<rtps::octet> value;
-};
-
 /**
  * Enum HistoryQosPolicyKind, different kinds of History Qos for HistoryQosPolicy.
  */
diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp
index 6ec11dbb922..b905dc29823 100644
--- a/src/cpp/qos/QosPolicies.cpp
+++ b/src/cpp/qos/QosPolicies.cpp
@@ -421,50 +421,6 @@ bool PartitionQosPolicy::readFromCDRMessage(
     return valid;
 }
 
-bool TopicDataQosPolicy::addToCDRMessage(
-        CDRMessage_t* msg) const
-{
-    bool valid = CDRMessage::addUInt16(msg, this->Pid);
-    valid &= CDRMessage::addUInt16(msg, this->length);
-    valid &= CDRMessage::addOctetVector(msg, &value);
-    return valid;
-}
-
-bool TopicDataQosPolicy::readFromCDRMessage(
-        CDRMessage_t* msg,
-        uint16_t size)
-{
-    length = size;
-
-    uint32_t pos_ref = msg->pos;
-    bool valid = CDRMessage::readOctetVector(msg, &value);
-    uint32_t length_diff = msg->pos - pos_ref;
-    valid &= (size == length_diff);
-    return valid;
-}
-
-bool GroupDataQosPolicy::addToCDRMessage(
-        CDRMessage_t* msg) const
-{
-    bool valid = CDRMessage::addUInt16(msg, this->Pid);
-    valid &= CDRMessage::addUInt16(msg, this->length);
-    valid &= CDRMessage::addOctetVector(msg, &value);
-    return valid;
-}
-
-bool GroupDataQosPolicy::readFromCDRMessage(
-        CDRMessage_t* msg,
-        uint16_t size)
-{
-    length = size;
-
-    uint32_t pos_ref = msg->pos;
-    bool valid = CDRMessage::readOctetVector(msg, &value);
-    uint32_t length_diff = msg->pos - pos_ref;
-    valid &= (size == length_diff);
-    return valid;
-}
-
 bool HistoryQosPolicy::addToCDRMessage(
         CDRMessage_t* msg) const
 {

From 70cb9734593d56013fbbc6c01f75c7fda3a4c9c8 Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Fri, 6 Mar 2020 10:54:12 +0100
Subject: [PATCH 05/10] Refs #7837. Middle class to avoid linker problems.

---
 include/fastrtps/qos/QosPolicies.h | 77 +++++++++++++++++++++++++-----
 1 file changed, 66 insertions(+), 11 deletions(-)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index e69470c316b..42b52f08da9 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -615,23 +615,24 @@ class DestinationOrderQosPolicy : public Parameter_t, public QosPolicy
 /**
  * Class GenericDataQosPolicy, base class to transmit user data during the discovery phase.
  */
-template<ParameterId_t TPid>
 class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public ResourceLimitedVector<rtps::octet>
 {
     using ResourceLimitedOctetVector = ResourceLimitedVector<rtps::octet>;
 
 public:
 
-    RTPS_DllAPI GenericDataQosPolicy()
-        : Parameter_t(TPid, 0)
+    RTPS_DllAPI GenericDataQosPolicy(
+            ParameterId_t pid)
+        : Parameter_t(pid, 0)
         , QosPolicy(false)
         , ResourceLimitedOctetVector()
     {
     }
 
     RTPS_DllAPI GenericDataQosPolicy(
+            ParameterId_t pid,
             uint16_t in_length)
-        : Parameter_t(TPid, in_length)
+        : Parameter_t(pid, in_length)
         , QosPolicy(false)
         , ResourceLimitedOctetVector()
     {
@@ -647,7 +648,7 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
      */
     RTPS_DllAPI GenericDataQosPolicy(
             const GenericDataQosPolicy& data)
-        : Parameter_t(TPid, data.length)
+        : Parameter_t(data.Pid, data.length)
         , QosPolicy(false)
         , ResourceLimitedOctetVector(data)
     {
@@ -662,12 +663,14 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
      * @param data data to copy in the newly created object
      */
     RTPS_DllAPI GenericDataQosPolicy(
+            ParameterId_t pid,
             const collection_type& data)
-        : Parameter_t(TPid, 0)
+        : Parameter_t(pid, 0)
         , QosPolicy(false)
         , ResourceLimitedOctetVector()
     {
         assign(data.begin(), data.end());
+        length = (size() + 7) & ~3;
     }
 
     virtual RTPS_DllAPI ~GenericDataQosPolicy()
@@ -774,7 +777,7 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
      * @param msg Message to append the QoS Policy to.
      * @return True if the modified CDRMessage is valid.
      */
-    bool addToCDRMessage(
+    bool inline addToCDRMessage(
             rtps::CDRMessage_t* msg) const override
     {
         return QosPolicy::serialize_generic_data(msg, Pid, collection_);
@@ -786,7 +789,7 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
      * @param size Size of the QoS Policy field to read
      * @return True if the parameter was correctly taken.
      */
-    bool readFromCDRMessage(
+    bool inline readFromCDRMessage(
             rtps::CDRMessage_t* msg,
             uint16_t size) override
     {
@@ -838,9 +841,61 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
     }
 };
 
-using UserDataQosPolicy = GenericDataQosPolicy<PID_USER_DATA>;
-using TopicDataQosPolicy = GenericDataQosPolicy<PID_TOPIC_DATA>;
-using GroupDataQosPolicy = GenericDataQosPolicy<PID_GROUP_DATA>;
+/**
+ * Class TemplateDataQosPolicy, base template for user data qos policies.
+ */
+template<ParameterId_t TPid>
+class TemplateDataQosPolicy : public GenericDataQosPolicy
+{
+public:
+
+    RTPS_DllAPI TemplateDataQosPolicy()
+        : GenericDataQosPolicy(TPid)
+    {
+    }
+
+    RTPS_DllAPI TemplateDataQosPolicy(
+            uint16_t in_length)
+        : GenericDataQosPolicy(TPid, in_length)
+    {
+    }
+
+    /**
+     * Construct from another TemplateDataQosPolicy.
+     *
+     * The resulting TemplateDataQosPolicy will have the same size limits
+     * as the input attribute
+     *
+     * @param data data to copy in the newly created object
+     */
+    RTPS_DllAPI TemplateDataQosPolicy(
+            const TemplateDataQosPolicy& data)
+        : GenericDataQosPolicy(data)
+    {
+    }
+
+    /**
+     * Construct from underlying collection type.
+     *
+     * Useful to easy integration on old APIs where a traditional container was used.
+     * The resulting TemplateDataQosPolicy will always be unlimited in size
+     *
+     * @param data data to copy in the newly created object
+     */
+    RTPS_DllAPI TemplateDataQosPolicy(
+            const collection_type& data)
+        : GenericDataQosPolicy(TPid, data)
+    {
+    }
+
+    virtual RTPS_DllAPI ~TemplateDataQosPolicy()
+    {
+    }
+};
+
+using UserDataQosPolicy = TemplateDataQosPolicy<PID_USER_DATA>;
+using TopicDataQosPolicy = TemplateDataQosPolicy<PID_TOPIC_DATA>;
+using GroupDataQosPolicy = TemplateDataQosPolicy<PID_GROUP_DATA>;
 
 /**
  * Class TimeBasedFilterQosPolicy, to indicate the Time Based Filter Qos.

From 0f4e5ce01e1cc9e3ead5f3099db8a53f797f3d68 Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Fri, 6 Mar 2020 12:16:27 +0100
Subject: [PATCH 06/10] Refs #7837. Fixing DataRepresentationQosPolicy.

---
 include/fastrtps/qos/QosPolicies.h |  2 ++
 src/cpp/qos/QosPolicies.cpp        | 37 +++++++++++++++++++++++++-----
 2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index 42b52f08da9..7bf5971da31 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -1791,6 +1791,8 @@ class DataRepresentationQosPolicy : public Parameter_t, public QosPolicy
         std::swap(*this, reset);
     }
 
+    virtual uint32_t cdr_serialized_size() const override;
+
     /**
      * Appends QoS to the specified CDR message.
      * @param msg Message to append the QoS Policy to.
diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp
index b905dc29823..2614d0e7f36 100644
--- a/src/cpp/qos/QosPolicies.cpp
+++ b/src/cpp/qos/QosPolicies.cpp
@@ -584,13 +584,33 @@ bool TransportPriorityQosPolicy::readFromCDRMessage(
     return CDRMessage::readUInt32(msg, &value);
 }
 
+uint32_t DataRepresentationQosPolicy::cdr_serialized_size() const
+{
+    // Size of data
+    uint32_t data_size = static_cast<uint32_t>(m_value.size() * sizeof(uint16_t));
+    // Align to next 4 byte
+    data_size = (data_size + 3) & ~3;
+    // p_id + p_length + data_size + data
+    return 2 + 2 + 4 + data_size;
+}
+
 bool DataRepresentationQosPolicy::addToCDRMessage(
         CDRMessage_t* msg) const
 {
-    bool valid = CDRMessage::addUInt32(msg, (uint32_t)m_value.size());
-    for (const DataRepresentationId_t& it : m_value)
+    bool valid = CDRMessage::addUInt16(msg, this->Pid);
+
+    uint16_t len = static_cast<uint16_t>(m_value.size() * sizeof(uint16_t)) + 4;
+    len = (len + 3) & ~3;
+
+    valid &= CDRMessage::addUInt16(msg, len);
+    valid &= CDRMessage::addUInt32(msg, static_cast<uint32_t>(m_value.size()));
+    for (const DataRepresentationId_t& id : m_value)
+    {
+        valid &= CDRMessage::addUInt16(msg, static_cast<uint16_t>(id));
+    }
+    if (m_value.size() % 2 == 1) // Odd, we must align
     {
-        valid &= CDRMessage::addUInt16(msg, it);
+        valid &= CDRMessage::addUInt16(msg, uint16_t(0));
     }
     return valid;
 }
@@ -605,13 +625,18 @@ bool DataRepresentationQosPolicy::readFromCDRMessage(
     int16_t temp(0);
     uint32_t datasize(0);
     bool valid = CDRMessage::readUInt32(msg, &datasize);
-    for (uint32_t i = 0; i < datasize; ++i)
+    valid &= (datasize * sizeof(uint16_t)) <= (size - sizeof(uint32_t));
+
+    for (uint32_t i = 0; valid && (i < datasize); ++i)
     {
         valid &= CDRMessage::readInt16(msg, &temp);
         m_value.push_back(static_cast<DataRepresentationId_t>(temp));
     }
-    uint32_t length_diff = msg->pos - pos_ref;
-    valid &= (size == length_diff);
+    if (valid)
+    {
+        msg->pos = pos_ref + size;
+    }
+
     return valid;
 }
 

From a37a12c4126d2eaaf6c59e9a85079ae8946d25a8 Mon Sep 17 00:00:00 2001
From: Miguel Company <miguelcompany@eprosima.com>
Date: Fri, 6 Mar 2020 15:25:15 +0100
Subject: [PATCH 07/10] Avoid duplicate serialization of length

---
 src/cpp/qos/QosPolicies.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp
index 2614d0e7f36..9015ec48633 100644
--- a/src/cpp/qos/QosPolicies.cpp
+++ b/src/cpp/qos/QosPolicies.cpp
@@ -48,7 +48,6 @@ bool QosPolicy::serialize_generic_data(
     uint16_t siz = static_cast<uint16_t>(data.size());
     siz = (siz + 3) & ~3;
     valid &= CDRMessage::addUInt16(msg, static_cast<uint16_t>(4 + siz));
-    valid &= CDRMessage::addUInt32(msg, siz);
     valid &= CDRMessage::addOctetVector(msg, &data, true);
     return valid;
 }

From 8b8244ee596b2dac57a3edfd9b94a5aaaa0d92de Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Mon, 9 Mar 2020 07:54:43 +0100
Subject: [PATCH 08/10] Refs #7837. Fixed padding skip.

---
 src/cpp/qos/QosPolicies.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp
index 9015ec48633..bf75fc1c988 100644
--- a/src/cpp/qos/QosPolicies.cpp
+++ b/src/cpp/qos/QosPolicies.cpp
@@ -82,7 +82,7 @@ bool QosPolicy::deserialize_generic_data(
     }
 
     // Skip padding
-    msg->pos += (len - (len + 3) & ~3);
+    msg->pos += ( (len + 3) & ~3) - len;
 
     // Should have consumed whole size
     return (pos_ref + size == msg->pos);

From b7a64746e7e61d2b76c07588a8871dc99d183e91 Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Mon, 9 Mar 2020 08:01:02 +0100
Subject: [PATCH 09/10] Refs #7837. Fixing Doxygen.

---
 include/fastrtps/qos/QosPolicies.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h
index 7bf5971da31..6edce8754d4 100644
--- a/include/fastrtps/qos/QosPolicies.h
+++ b/include/fastrtps/qos/QosPolicies.h
@@ -660,7 +660,8 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
      * Useful to easy integration on old APIs where a traditional container was used.
      * The resulting GenericDataQosPolicy will always be unlimited in size
      *
-     * @param data data to copy in the newly created object
+     * @param pid Id of the parameter
+     * @param data Data to copy in the newly created object
      */
     RTPS_DllAPI GenericDataQosPolicy(
             ParameterId_t pid,
@@ -755,7 +756,7 @@ class GenericDataQosPolicy : public Parameter_t, public QosPolicy, public Resour
 
     /**
      * @return const reference to the internal raw data.
-     * */
+     */
     inline const std::vector<rtps::octet>& dataVec() const
     {
         return collection_;

From 83fc44501f7e0cb8094e64c5333b7a8491595a61 Mon Sep 17 00:00:00 2001
From: Miguel Company <MiguelCompany@eprosima.com>
Date: Mon, 9 Mar 2020 08:52:06 +0100
Subject: [PATCH 10/10] Refs #7837. Fixing blackbox tests.

---
 test/blackbox/BlackboxTestsPubSubBasic.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/blackbox/BlackboxTestsPubSubBasic.cpp b/test/blackbox/BlackboxTestsPubSubBasic.cpp
index 0df9fa77792..d58f56945c3 100644
--- a/test/blackbox/BlackboxTestsPubSubBasic.cpp
+++ b/test/blackbox/BlackboxTestsPubSubBasic.cpp
@@ -336,7 +336,7 @@ TEST_P(PubSubBasic, ReceivedDynamicDataWithinSizeLimit)
             R"(<profiles>
                 <participant><rtps>
                     <allocation>
-                        <max_user_data> 8 </max_user_data>
+                        <max_user_data> 4 </max_user_data>
                         <max_partitions> 28 </max_partitions>
                     </allocation>
                 </rtps></participant>
@@ -378,7 +378,7 @@ TEST_P(PubSubBasic, ReceivedUserDataExceedsSizeLimit)
             R"(<profiles>
                 <participant><rtps>
                     <allocation>
-                        <max_user_data> 8 </max_user_data>
+                        <max_user_data> 4 </max_user_data>
                     </allocation>
                 </rtps></participant>
             </profiles>)";