Add ByteString type at the Value of RCSResourceAttributes.
authorKIM JungYong <jyong2.kim@samsung.com>
Thu, 15 Dec 2016 09:09:36 +0000 (18:09 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 30 Dec 2016 08:10:58 +0000 (08:10 +0000)
ByteString(Binary) was added in the Value of OCRepresentation.
But, RE layer does not covered ByteString type.
In this patch, ByteString type is added in RE layer
for synchronization with OC.

patchset #2
handling of OC::AttributeType::Binary is added.
toString method of RCSByteString is fixed.

patchset #4
Description of RCSByteString is added.

patchset #5
Server sample application is update for including byte string
on GET response of custom interface.

Change-Id: If293954c64fe1b072b1bdff967681d6c6e774671
Signed-off-by: KIM JungYong <jyong2.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15695
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/resource-encapsulation/examples/linux/SampleResourceServer.cpp
service/resource-encapsulation/include/RCSResourceAttributes.h
service/resource-encapsulation/src/common/primitiveResource/include/ResourceAttributesConverter.h
service/resource-encapsulation/src/common/primitiveResource/src/RCSResourceAttributes.cpp
service/resource-encapsulation/src/common/primitiveResource/unittests/ResourceAttributesTest.cpp

index 4ac4038..3561cd5 100644 (file)
@@ -19,6 +19,7 @@
  ******************************************************************/
 
 #include "RCSResourceObject.h"
+#include "RCSRequest.h"
 #include "OCPlatform.h"
 
 using namespace OC::OCPlatform;
@@ -102,7 +103,7 @@ void printAttributes(const RCSResourceAttributes& attrs)
     }
 }
 
-RCSGetResponse requestHandlerForGet(const RCSRequest&, RCSResourceAttributes& attrs)
+RCSGetResponse requestHandlerForGet(const RCSRequest & req, RCSResourceAttributes& attrs)
 {
     std::cout << "Received a Get request from Client" << std::endl;
     printAttributes(attrs);
@@ -110,10 +111,21 @@ RCSGetResponse requestHandlerForGet(const RCSRequest&, RCSResourceAttributes& at
     {
         RCSResourceObject::LockGuard lock(g_resource);
         std::cout << "\nSending response to Client : " << std::endl;
-        printAttributes(g_resource->getAttributes());
+        if (req.getInterface() == CUSTOM_INTERFACE)
+        {
+            auto attr = g_resource->getAttributes();
+            static RCSByteString::DataType binval {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
+                                                   0x9, 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
+            attr["blob"] = RCSByteString {binval};
+            printAttributes(attr);
+            return RCSGetResponse::create(attr);
+        }
+        else
+        {
+            printAttributes(g_resource->getAttributes());
+            return RCSGetResponse::defaultAction();
+        }
     }
-
-    return RCSGetResponse::defaultAction();
 }
 
 RCSSetResponse requestHandlerForSet(const RCSRequest&, RCSResourceAttributes& attrs)
index 6fcff21..3a1c4c9 100644 (file)
@@ -49,6 +49,128 @@ namespace OIC
 {
     namespace Service
     {
+        /**
+        * This RCSByteString the one of RCSResourceAttributes value for Byte String (Binary).
+        *
+        * It provides similar usage to c++ standard vector.<br/>
+        * An RCSByteString can be one of various attribute value type.
+        *
+        * @see Value
+        * @see Type
+        * @see RCSRemoteResourceObject
+        * @see RCSResourceObject
+        * @see RCSResourceAttributes
+        */
+        class RCSByteString
+        {
+        public:
+            typedef std::vector<uint8_t> DataType;
+
+            /**
+             * Returns a vector<uint8_t> type of byte string.
+             *
+             * @return A stored byte string with std::vector<uint8_t>
+             */
+            DataType getByteString() const
+            {
+                return {m_data};
+            }
+
+            /**
+             * Returns a size of stored vector<uint8_t>.
+             *
+             * @return A size of stored byte string.
+             */
+            size_t size() const
+            {
+                return m_data.size();
+            }
+
+            /**
+              * @relates RCSByteString
+              *
+              * Checks if the byte string is same contents, or not.
+              *
+              * @return true if the byte string are equal, false otherwise.
+              */
+            inline bool operator==(const RCSByteString& rhs) const
+            {
+                return this->m_data == rhs.getByteString();
+            }
+
+            /**
+             * @relates RCSByteString
+             *
+             * Checks if the byte string is not same contents, or is same.
+             *
+             * @return true if the byte string are not equal, false otherwise.
+             */
+            inline bool operator!=(const RCSByteString& rhs) const
+            {
+                return this->m_data != rhs.getByteString();
+            }
+
+            /**
+             * Return a value of indexed byte string.
+             *
+             * @param it location of the element.
+             *
+             * @return A copied value of indexed byte string.
+             */
+            inline uint8_t operator[](size_t it) const
+            {
+                return this->m_data[it];
+            }
+
+            RCSByteString()
+            {
+            }
+            RCSByteString(DataType && rhs)
+            : m_data {std::move(rhs)}
+            {
+            }
+            RCSByteString(const DataType & rhs)
+            : m_data {rhs}
+            {
+            }
+            RCSByteString(RCSByteString && rhs)
+            : m_data {DataType{rhs.getByteString()}}
+            {
+            }
+            RCSByteString(const RCSByteString & rhs)
+            : m_data {DataType{rhs.getByteString()}}
+            {
+            }
+
+            RCSByteString(::OCByteString && rhs)
+            : m_data {DataType{rhs.bytes, rhs.bytes + rhs.len}}
+            {
+            }
+            RCSByteString(const ::OCByteString & rhs)
+            : m_data {DataType{rhs.bytes, rhs.bytes + rhs.len}}
+            {
+            }
+
+            RCSByteString(uint8_t* bytes, size_t size)
+            : m_data {DataType{bytes, bytes + size}}
+            {
+            }
+            inline RCSByteString& operator=(RCSByteString&& rhs)
+            {
+                return operator =(rhs);
+            }
+            inline RCSByteString& operator=(const RCSByteString& rhs)
+            {
+                if (!m_data.empty())
+                {
+                    m_data.clear();
+                }
+                m_data = DataType{rhs.getByteString()};
+                return *this;
+            }
+        private:
+            DataType m_data;
+        };
 
         /**
         * This represents the attributes for a resource.
@@ -65,6 +187,7 @@ namespace OIC
         * @see RCSDiscoveryManager
         * @see RCSRemoteResourceObject
         * @see RCSResourceObject
+        * @see RCSByteString
         */
         class RCSResourceAttributes
         {
@@ -77,12 +200,14 @@ namespace OIC
                 double,
                 bool,
                 std::string,
+                RCSByteString,
                 RCSResourceAttributes,
 
                 std::vector< int >,
                 std::vector< double >,
                 std::vector< bool >,
                 std::vector< std::string >,
+                std::vector< RCSByteString >,
                 std::vector< RCSResourceAttributes >,
 
                 std::vector< std::vector< int > >,
@@ -97,6 +222,9 @@ namespace OIC
                 std::vector< std::vector< std::string > >,
                 std::vector< std::vector< std::vector< std::string > > >,
 
+                std::vector< std::vector< RCSByteString > >,
+                std::vector< std::vector< std::vector< RCSByteString > > >,
+
                 std::vector< std::vector< RCSResourceAttributes > >,
                 std::vector< std::vector< std::vector< RCSResourceAttributes > > >
             > ValueVariant;
@@ -159,6 +287,7 @@ namespace OIC
                 DOUBLE, /**< double */
                 BOOL, /**< bool */
                 STRING, /**< std::string */
+                BYTESTRING, /**< RCSByteString */
                 ATTRIBUTES, /**< RCSResourceAttributes */
                 VECTOR /**< std::vector */
             };
@@ -264,12 +393,14 @@ namespace OIC
                 double
                 bool
                 std::string
+                RCSByteString
                 RCSResourceAttributes
 
                 std::vector< int >
                 std::vector< double >
                 std::vector< bool >
                 std::vector< std::string >
+                std::vector< RCSByteString >
                 std::vector< RCSResourceAttributes >
 
                 std::vector< std::vector< int > >
@@ -284,6 +415,9 @@ namespace OIC
                 std::vector< std::vector< std::string > >
                 std::vector< std::vector< std::vector< std::string > > >
 
+                std::vector< std::vector< RCSByteString > >
+                std::vector< std::vector< std::vector< RCSByteString > > >
+
                 std::vector< std::vector< RCSResourceAttributes > >
                 std::vector< std::vector< std::vector< RCSResourceAttributes > > >
              * @endcode
index b4c5b63..10f59e0 100644 (file)
@@ -56,6 +56,12 @@ namespace OIC
             struct OCBaseType< OC::AttributeType::String > : TypeDef< std::string > { };
 
             template< >
+            struct OCBaseType< OC::AttributeType::Binary > : TypeDef< RCSByteString::DataType > { };
+
+            template< >
+            struct OCBaseType< OC::AttributeType::OCByteString > : TypeDef< OCByteString > { };
+
+            template< >
             struct OCBaseType< OC::AttributeType::OCRepresentation >
                 : TypeDef< OC::OCRepresentation >
             {};
@@ -124,6 +130,16 @@ namespace OIC
                         case OC::AttributeType::String:
                             return insertItem< DEPTH, OC::AttributeType::String >(item);
 
+                        case OC::AttributeType::Binary:
+                            // OCRep support only 0-depth for binary type.
+                            // If RI changed, this line should be changed to DEPTH.
+                            return insertOcBinary< OC::AttributeType::Binary >
+                            (Detail::Int2Type< 0 >{ }, item);
+
+                        case OC::AttributeType::OCByteString:
+                            return insertOcBinary< OC::AttributeType::OCByteString >
+                            (Detail::Int2Type< DEPTH >{ }, item);
+
                         case OC::AttributeType::OCRepresentation:
                             return insertOcRep(Detail::Int2Type< DEPTH >{ }, item);
 
@@ -170,6 +186,37 @@ namespace OIC
                             insertOcRep(Detail::Int2Type< DEPTH >{ }, item.getValue< ItemType >()));
                 }
 
+                template< typename OCREP >
+                RCSByteString insertOcBinary(Detail::Int2Type< 0 >, const OCREP& ocBinary)
+                {
+                    return RCSByteString(ocBinary);
+                }
+
+                template< int DEPTH, typename OCREPS,
+                    typename ATTRS = typename Detail::SeqType< DEPTH, RCSByteString >::type >
+                ATTRS insertOcBinary(Detail::Int2Type< DEPTH >, const OCREPS& ocBinaryVec)
+                {
+                    ATTRS result;
+
+                    for (const auto& nested : ocBinaryVec)
+                    {
+                        result.push_back(insertOcBinary(Detail::Int2Type< DEPTH - 1 >{ }, nested));
+                    }
+
+                    return result;
+                }
+
+                template< OC::AttributeType BASE_TYPE, int DEPTH >
+                void insertOcBinary(Detail::Int2Type< DEPTH >,
+                        const OC::OCRepresentation::AttributeItem& item)
+                {
+                    typedef typename Detail::OCItemType< DEPTH, BASE_TYPE >::type ItemType;
+
+                    putValue(item.attrname(),
+                             insertOcBinary(Detail::Int2Type< DEPTH >{ },
+                                            item.getValue< ItemType >()));
+                }
+
             public:
                 ResourceAttributesBuilder() = default;
 
@@ -213,7 +260,10 @@ namespace OIC
                 OCRepresentationBuilder() = default;
 
                 template< typename T, typename B = typename Detail::TypeInfo< T >::base_type >
-                typename std::enable_if< !std::is_same< B, RCSResourceAttributes >::value >::type
+                typename std::enable_if< (
+                !std::is_same< B, RCSResourceAttributes >::value &&
+                !std::is_same< B, RCSByteString >::value
+                )>::type
                 operator()(const std::string& key, const T& value)
                 {
                     m_target[key] = value;
@@ -227,6 +277,14 @@ namespace OIC
                     m_target[key] = convertAttributes(Detail::Int2Type< I::depth >{ }, value);
                 }
 
+                template< typename T, typename I = Detail::TypeInfo< T > >
+                typename std::enable_if< std::is_same< typename I::base_type,
+                                                RCSByteString >::value >::type
+                operator()(const std::string& key, const T& value)
+                {
+                    m_target[key] = convertByteString(Detail::Int2Type< I::depth >{ }, value);
+                }
+
                 void operator()(const std::string& key, const std::nullptr_t&)
                 {
                     m_target.setNULL(key);
@@ -253,6 +311,35 @@ namespace OIC
                     return result;
                 }
 
+                OCByteString convertByteString(Detail::Int2Type< 0 >,
+                        const RCSByteString& byteString)
+                {
+                    OCByteString blob;
+                    blob.len = byteString.size();
+                    blob.bytes = new uint8_t[blob.len];
+                    for (size_t i = 0; i < blob.len; ++i)
+                    {
+                        blob.bytes[i] = byteString[i];
+                    }
+
+                    return blob;
+                }
+
+                template< int DEPTH, typename ATTRS, typename OCREPS = typename Detail::SeqType<
+                        DEPTH, OCByteString >::type >
+                OCREPS convertByteString(Detail::Int2Type< DEPTH >, const ATTRS& byteStringVec)
+                {
+                    OCREPS result;
+
+                    for (const auto& nested : byteStringVec)
+                    {
+                        result.push_back(
+                                convertByteString(Detail::Int2Type< DEPTH - 1 >{ }, nested));
+                    }
+
+                    return result;
+                }
+
                 OC::OCRepresentation&& extract()
                 {
                     return std::move(m_target);
index 4997208..75e9d56 100644 (file)
@@ -78,6 +78,14 @@ namespace
             m_stream << "\"" + value + "\"";
         }
 
+        void operator()(const RCSByteString& value)
+        {
+            for (size_t i = 0; i < value.size(); ++i)
+            {
+                m_stream << "\\x" << std::hex << (int)value[i];
+            }
+        }
+
         void operator()(const RCSResourceAttributes& attrs)
         {
             m_stream << "{";
@@ -155,6 +163,13 @@ namespace
     };
 
     template< >
+    struct TypeInfoConverter< RCSByteString >
+    {
+        static constexpr RCSResourceAttributes::TypeId typeId =
+                RCSResourceAttributes::TypeId::BYTESTRING;
+    };
+
+    template< >
     struct TypeInfoConverter< RCSResourceAttributes >
     {
         static constexpr RCSResourceAttributes::TypeId typeId =
@@ -231,7 +246,6 @@ namespace
 
         return typeInfos[which];
     }
-
 } // unnamed namespace
 
 
@@ -239,7 +253,6 @@ namespace OIC
 {
     namespace Service
     {
-
         RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
                 m_valueRef(v)
         {
index a2a7876..37f4bca 100644 (file)
@@ -343,6 +343,48 @@ TEST(ResourceAttributesConverterTest, OCRepresentationCanBeConvertedIntoResource
     ASSERT_TRUE(value == resourceAttributes[KEY]);
 }
 
+TEST(ResourceAttributesConverterTest, OCRepresentationCanBeConvertedIntoResourceAttributesTypeBinary)
+{
+    static uint8_t binval[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
+                               0x9, 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
+
+    OCByteString value {binval, sizeof(binval)};
+    OC::OCRepresentation ocRep;
+    ocRep[KEY] = value;
+
+    RCSResourceAttributes resourceAttributes{
+        ResourceAttributesConverter::fromOCRepresentation(ocRep) };
+
+    auto rcsValue = resourceAttributes[KEY].get<RCSByteString>();
+    for (size_t i = 0; i < rcsValue.size(); ++i)
+    {
+        ASSERT_EQ(binval[i], rcsValue[i]);
+    }
+}
+
+TEST(ResourceAttributesConverterTest, ResourceAttributesCanBeConvertedIntoOCRepresentationTypeBinary)
+{
+    static RCSByteString::DataType binval {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
+                                           0x9, 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
+    RCSResourceAttributes resourceAttributes;
+    RCSByteString value {binval};
+    resourceAttributes[KEY] = value;
+
+    OC::OCRepresentation ocRep{
+        ResourceAttributesConverter::toOCRepresentation(resourceAttributes) };
+
+    auto rcsValue = resourceAttributes[KEY].get<RCSByteString>();
+    auto ocValue = ocRep[KEY].getValue<OCByteString>();
+
+    ASSERT_EQ(rcsValue.size(), ocValue.len);
+    ASSERT_EQ(rcsValue.size(), binval.size());
+    ASSERT_EQ(binval.size(), ocValue.len);
+
+    for (size_t i = 0; i < rcsValue.size(); ++i)
+    {
+        ASSERT_EQ(ocValue.bytes[i], rcsValue[i]);
+    }
+}
 
 TEST(ResourceAttributesConverterTest, NestedOCRepresentationCanBeConvertedIntoResourceAttributes)
 {