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>
******************************************************************/
#include "RCSResourceObject.h"
+#include "RCSRequest.h"
#include "OCPlatform.h"
using namespace OC::OCPlatform;
}
}
-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);
{
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)
{
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.
* @see RCSDiscoveryManager
* @see RCSRemoteResourceObject
* @see RCSResourceObject
+ * @see RCSByteString
*/
class RCSResourceAttributes
{
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 > >,
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;
DOUBLE, /**< double */
BOOL, /**< bool */
STRING, /**< std::string */
+ BYTESTRING, /**< RCSByteString */
ATTRIBUTES, /**< RCSResourceAttributes */
VECTOR /**< std::vector */
};
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 > >
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
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 >
{};
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);
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;
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;
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);
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);
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 << "{";
};
template< >
+ struct TypeInfoConverter< RCSByteString >
+ {
+ static constexpr RCSResourceAttributes::TypeId typeId =
+ RCSResourceAttributes::TypeId::BYTESTRING;
+ };
+
+ template< >
struct TypeInfoConverter< RCSResourceAttributes >
{
static constexpr RCSResourceAttributes::TypeId typeId =
return typeInfos[which];
}
-
} // unnamed namespace
{
namespace Service
{
-
RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
m_valueRef(v)
{
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)
{