*.settings/
*.cproject
*.project
+
+# Ignore dependencies folder, which should be generated
+/dependencies
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-/// The purpose of this server is to simulate a refridgerator that contains a device resource for
+/// The purpose of this server is to simulate a refrigerator that contains a device resource for
/// its description, a light resource for the internal light, and 2 door resources for the purpose
/// of representing the doors attached to this fridge. This is used by the fridgeclient to
/// demonstrate using std::bind to attach to instances of a class as well as using
private:
OCRepresentation get()
{
- m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refridgerator"));
+ m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator"));
return m_rep;
}
// setting json string
std::string json = "{\"num\":10,\"rno\":23.5,\"aoa\":[[1,2],[3]],\"str\":\"john\",\
\"object\":{\"bl1\":false,\"ar\":[2,3]}, \"objects\":[{\"bl2\":true,\"nl\":null},{\"ar1\":[1,2]}]}";
- m_garageRep.setValue("json", escapeString(json));
+ m_garageRep.setValue("json", json);
}
/* Note that this does not need to be a member function: for classes you do not have
#CXX := clang
OUT_DIR := $(BUILD)
+DEPEND_DIR:= ../dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
CXX_FLAGS.debug := -O0 -g3 -std=c++0x -Wall -pthread
CXX_FLAGS.release := -O3 -std=c++0x -Wall -pthread
CXX_INC += -I../csdk/ocrandom/include
CXX_INC += -I../csdk/logger/include
CXX_INC += -I../csdk/libcoap
+CXX_INC += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a
-I../../csdk/stack/include \
-I../../csdk/ocsocket/include \
-I../../csdk/ocrandom/include \
- -I../../csdk/logger/include
+ -I../../csdk/logger/include \
+ -I../../dependencies/cereal/include
BOOST_LIBS=-lboost_program_options
#BOOST_LIBS=-L/usr/local/boost/lib/ -lboost_program_options # for boost libraries at the specified path
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// This contains the Boost MPL defines required for the boost_variant
+// serialization, so it must go before the boost/program_options
+#include "OCApi.h"
+
#include <map>
#include <string>
#include <memory>
#include <boost/program_options.hpp>
-#include "OCApi.h"
#include "OCResource.h"
#include "OCPlatform.h"
return;
}
- std::cout << "input attributes:\n" << rep.getAttributeMap() << '\n';
+ std::cout << "input attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
// Now, make a change to the light representation (replacing, rather than parsing):
- OC::AttributeMap attrs {
- { "state", { "true" } },
- { "power", { "10" } }
- };
+ bool state = true;
+ int power = 10;
- std::cout << "output attributes:\n" << attrs << '\n';
+ std::cout << "output attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< state<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< power<<"; \n";
call_timer.mark("put_resource");
OC::OCRepresentation out_rep;
- out_rep.setAttributeMap(attrs);
+ out_rep.setValue("state", state);
+ out_rep.setValue("power", power);
resource->put(out_rep, OC::QueryParamsMap(),
std::bind(&resource_handle::onResourcePut, this, std::placeholders::_1,
throw OC::OCException(os.str());
}
- std::cout << "input attributes:\n" << rep.getAttributeMap() << '\n';
+ std::cout << "input attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
call_timer.mark("observe_resource");
call_timer.report_and_reset("observe_resource");
- std::cout << rep.getAttributeMap() << '\n';
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
const auto oc = observe_count();
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include "exec.hpp"
#include "utility.hpp"
+#include "exec.hpp"
#include "light_resource.hpp"
namespace Intel { namespace OCDemo {
namespace Intel { namespace OCDemo {
-// Prettyprinter for AttributeMaps:
-inline std::ostream& operator<<(std::ostream& os, const OC::AttributeMap& attrs)
-{
- for(const auto& attr : attrs)
- os << "Attribute \"" << attr.first << "\": " << attr.second << "; ";
-
- return os;
-}
-
/* A static observation counter: */
int observe_count();
/* Helpers for measuring request times: */
-typedef std::pair<
- std::chrono::time_point<std::chrono::high_resolution_clock>,
- std::chrono::time_point<std::chrono::high_resolution_clock>
+typedef std::pair<
+ std::chrono::time_point<std::chrono::high_resolution_clock>,
+ std::chrono::time_point<std::chrono::high_resolution_clock>
> clock_interval;
struct call_times
call_times(const bool& display_reports_)
: display_reports(display_reports_)
{}
-
+
public:
void reset(const std::string& entry);
void mark(const std::string& name);
void report_and_reset(const std::string& name);
};
-extern call_times call_timer;
-
+extern call_times call_timer;
+
}} // namespace Intel::OCDemo
#endif
OCRepresentation getRoomRepresentation(void)
{
- std::vector<OCRepresentation> children;
-
- OCRepresentation light = getLightRepresentation();
- children.push_back(light);
-
- OCRepresentation fan = getFanRepresentation();
- children.push_back(fan);
-
- m_roomRep.setChildren(children);
+ m_roomRep.clearChildren();
+ m_roomRep.addChild(getLightRepresentation());
+ m_roomRep.addChild(getFanRepresentation());
return m_roomRep;
}
OCPlatform::Configure(cfg);
try
{
+ // makes it so that all boolean values are printed as 'true/false' in this stream
+ std::cout.setf(std::ios::boolalpha);
// Find all resources
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
--- /dev/null
+
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file AttributeValue.h
+
+/// @brief This file contains the definition of the internally used
+// type AttributeValue
+
+#ifndef __ATTRIBUTEVALUE_H
+#define __ATTRIBUTEVALUE_H
+
+// These defines are required to get the boost::variant to hold more than 20 items.
+// documentation requires that you use a power of 10
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_LIST_SIZE 30
+#define BOOST_MPL_LIMIT_VECTOR_SIZE 30
+#include <boost/variant.hpp>
+#include <cereal/external/rapidjson/document.h>
+
+namespace OC
+{
+ class OCRepresentation;
+
+ struct NullType{};
+ // Since null needs to be encoded in a special fashion in JSON, the encoder
+ // needs to know the index of the NullType Sentinel Any time the code does a special
+ // case for the NullType, we use the AttributeValueNullIndex. This MUST be kept up to date
+ // with the variant's which() for NullType.
+ static const int AttributeValueNullIndex = 0;
+ typedef boost::variant<
+
+ // Base values:
+ NullType, // Note: this handles the null-type and must match the above static const
+ int,
+ double,
+ bool,
+ std::string,
+ OC::OCRepresentation,
+
+ // Sequences:
+ std::vector<int>,
+ std::vector<double>,
+ std::vector<bool>,
+ std::vector<std::string>,
+ std::vector<OC::OCRepresentation>,
+
+ // Nested sequences:
+ std::vector<std::vector<int>>,
+ std::vector<std::vector<std::vector<int>>>,
+
+ std::vector<std::vector<double>>,
+ std::vector<std::vector<std::vector<double>>>,
+
+ std::vector<std::vector<bool>>,
+ std::vector<std::vector<std::vector<bool>>>,
+
+ std::vector<std::vector<std::string>>,
+ std::vector<std::vector<std::vector<std::string>>>,
+
+ std::vector<std::vector<OC::OCRepresentation>>,
+ std::vector<std::vector<std::vector<OC::OCRepresentation>>>
+ > AttributeValue;
+
+}
+#endif // __ATTRIBUTEVALUE_H
class IClientWrapper : public std::enable_shared_from_this<IClientWrapper>
{
protected:
- OCPlatform_impl& m_owner;
public:
typedef std::shared_ptr<IClientWrapper> Ptr;
- IClientWrapper(OCPlatform_impl& owner)
- : m_owner(owner)
+ IClientWrapper()
{}
virtual OCStackResult ListenForResource(const std::string& serviceUrl,
virtual OCStackResult GetDefaultQos(QualityOfService& qos) = 0;
virtual ~IClientWrapper(){}
-
-
- // Note: this should never be called by anyone but the handler for the listen command.
- // It is public becuase that needs to be a non-instance callback
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
- OCDevAddr& addr, const boost::property_tree::ptree resourceNode)=0;
- private:
};
}
class IServerWrapper
{
protected:
- OCPlatform_impl& m_owner;
public:
typedef std::shared_ptr<IServerWrapper> Ptr;
- IServerWrapper(OCPlatform_impl& owner)
- : m_owner(owner)
+ IServerWrapper()
{}
virtual ~IServerWrapper(){};
#include <sstream>
#include <iostream>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
#include <OCApi.h>
#include <ocstack.h>
#include <IClientWrapper.h>
namespace OC
{
- class InProcClientWrapper : public IClientWrapper
+ namespace ClientCallbackContext
{
+ struct GetContext
+ {
+ GetCallback callback;
+ };
- public:
- enum OCSecureType
+ struct SetContext
+ {
+ PutCallback callback;
+ };
+
+ struct ListenContext
+ {
+ FindCallback callback;
+ IClientWrapper::Ptr clientWrapper;
+ };
+
+ struct SubscribePresenceContext
{
- IPV4Secure,
- IPV4
+ SubscribeCallback callback;
};
- InProcClientWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+ struct DeleteContext
+ {
+ DeleteCallback callback;
+ };
+
+ struct ObserveContext
+ {
+ ObserveCallback callback;
+ };
+ }
+
+ class InProcClientWrapper : public IClientWrapper
+ {
+
+ public:
+
+ InProcClientWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
PlatformConfig cfg);
virtual ~InProcClientWrapper();
const std::string& resourceType, SubscribeCallback& presenceHandler);
virtual OCStackResult UnsubscribePresence(OCDoHandle handle);
- // Note: this should never be called by anyone but the handler for the listen command.
- // It is public becuase that needs to be a non-instance callback
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
- OCDevAddr& addr, const boost::property_tree::ptree resourceNode);
-
OCStackResult GetDefaultQos(QualityOfService& QoS);
private:
- std::string convertOCAddrToString(OCDevAddr& addr,
- OCSecureType type, const std::string &portStr = std::string());
void listeningFunc();
std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams);
std::string assembleSetResourcePayload(const OCRepresentation& attributes);
std::weak_ptr<std::recursive_mutex> m_csdkLock;
private:
- OC::OCPlatform_impl& m_owner;
PlatformConfig m_cfg;
};
}
class InProcServerWrapper : public IServerWrapper
{
public:
- InProcServerWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+ InProcServerWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
PlatformConfig cfg);
virtual ~InProcServerWrapper();
#include <memory>
#include <iterator>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-#include <boost/variant.hpp>
-
#include "ocstack.h"
#include "OCHeaderOption.h"
#include <OCException.h>
#include "StringConstants.h"
#include "oc_logger.hpp"
+#include <OCRepresentation.h>
+
namespace OC
{
class OCResource;
Observe,
ObserveAll
};
-
- // Helper function to escape character in a string.
- std::string escapeString(const std::string& value);
-
- typedef std::map<std::string, std::string> AttributeMap;
-
- class OCRepresentation
- {
- private:
- std::string m_uri;
- AttributeMap m_attributeMap;
- std::vector<std::string> m_resourceTypes;
- std::vector<std::string> m_resourceInterfaces;
- int errorCode;
-
- std::vector<OCRepresentation> m_children;
-
- public:
- OCRepresentation() {}
-
- bool erase(const std::string& str)
- {
- return m_attributeMap.erase(str) != 0;
- }
-
- std::string getUri(void) const
- {
- return m_uri;
- }
-
- template <typename T>
- void setValue(const std::string& str, const T& val);
-
- template <typename T>
- bool getValue(const std::string& str, T& val) const;
-
- template <typename T>
- T getValue(const std::string& str) const;
-
- bool hasAttribute(const std::string& str) const
- {
- return m_attributeMap.find(str) != m_attributeMap.end();
- }
-
- void setNULL(const std::string& str)
- {
- m_attributeMap[str] = "null";
- }
-
- bool isNULL(const std::string& str) const
- {
- auto x = m_attributeMap.find(str);
-
- if(m_attributeMap.end() != x)
- {
- return x->second.compare("null") == 0;
- }
- else
- {
- std::ostringstream message;
- message << "attribute: " << str << " doesn't exist\n";
- throw OCException(message.str());
- }
-
- return false;
- }
-
- int numberOfAttributes() const
- {
- return m_attributeMap.size();
- }
-
- void setUri(std::string uri)
- {
- m_uri = uri;
- }
-
- std::vector<OCRepresentation> getChildren(void) const
- {
- return m_children;
- }
-
- void setChildren(const std::vector<OCRepresentation>& children)
- {
- m_children = children;
- }
-
- std::weak_ptr<OCResource> getResource() const
- {
- // TODO Needs to be implemented
- std::weak_ptr<OCResource> wp;
- return wp;
- }
-
- AttributeMap getAttributeMap() const
- {
- return m_attributeMap;
- }
-
- void setAttributeMap(const AttributeMap& map)
- {
- m_attributeMap = map;
- }
-
- std::string getJSONRepresentation(void) const
- {
- std::ostringstream json;
-
- json << "{";
-
- for(auto itr = m_attributeMap.begin(); itr!= m_attributeMap.end(); ++ itr)
- {
- if(itr != m_attributeMap.begin())
- {
- json << ',';
- }
- json << "\""<<itr->first<<"\":"<< itr->second;
- }
- json << "}";
-
- return json.str();
- }
-
- std::vector<std::string> getResourceTypes() const
- {
- return m_resourceTypes;
- }
-
- void setResourceTypes(const std::vector<std::string>& resourceTypes)
- {
- m_resourceTypes = resourceTypes;
- }
-
- std::vector<std::string> getResourceInterfaces(void) const
- {
- return m_resourceInterfaces;
- }
-
- void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
- {
- m_resourceInterfaces = resourceInterfaces;
- }
- };
-
- OCRepresentation parseJSONToRepresentation(const std::string& str);
-
- inline OCRepresentation parseJSONToRepresentation(const std::string& str)
- {
- OCRepresentation rep;
-
- AttributeMap attributeMap;
-
- std::stringstream requestStream;
- requestStream << str;
- boost::property_tree::ptree payload;
- try
- {
- boost::property_tree::read_json(requestStream, payload);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
- {
- throw OCException(OC::Exception::GENERAL_JSON_PARSE_FAILED);
- }
-
- for(auto& item: payload)
- {
- std::string name = item.first.data();
- std::string value = item.second.data();
-
- attributeMap[name] = value;
- }
-
- rep.setAttributeMap(attributeMap);
-
- return rep;
- }
-
- typedef boost::variant<
- int,
- double,
- bool,
- OCRepresentation,
- std::string,
- std::vector<int>,
- std::vector<double>,
- std::vector<bool>,
- std::vector<std::string>,
- std::vector<OCRepresentation>
- > AttributeValue;
-
- template <typename T>
- inline std::string getJSONFromVector(const std::vector<T>& v)
- {
- std::ostringstream json;
-
- json << "\"[";
- if(v.size() != 0)
- {
- std::copy(v.begin(), v.end() - 1, std::ostream_iterator<T>(json, ","));
- json << v.back();
- }
- json << "]\"";
-
- return json.str();
- }
-
- class ComposeVisitor : public boost::static_visitor<std::string>
- {
- public:
-
- // TODO different int sizes
- std::string operator() (const int i) const
- {
- return std::to_string(i);
- }
-
- std::string operator() (const double d) const
- {
- return std::to_string(d);
- }
-
- std::string operator() (const std::string& str) const
- {
- std::ostringstream json;
- json << "\"";
- json << str;
- json << "\"";
-
- return json.str();
- }
-
- std::string operator() (const bool b) const
- {
- if(b)
- {
- return "true";
- }
- else
- {
- return "false";
- }
- }
-
- std::string operator() (const std::vector<int>& numbers) const
- {
- return getJSONFromVector(numbers);
- }
-
- std::string operator() (const std::vector<double>& numbers) const
- {
- return getJSONFromVector(numbers);
- }
-
- std::string operator() (const std::vector<bool>& bools) const
- {
- std::ostringstream json;
- int first = 1;
-
- json << "\"[";
- for(auto b: bools)
- {
- if(first)
- {
- b ? json << "true" : json << "false";
- first = 0;
- }
- else
- {
- b ? json << ",true" : json << ",false";
- }
- }
- json << "]\"";
-
- return json.str();
- }
-
- std::string operator() (const std::vector<std::string>& strings) const
- {
- return getJSONFromVector(strings);
- }
-
- std::string operator() (const OCRepresentation& rep) const
- {
- std::ostringstream json;
-
- json << "\"";
-
- json << escapeString(rep.getJSONRepresentation());
-
- json << "\"";
-
- return json.str();
- }
-
- std::string operator() (const std::vector<OCRepresentation>& reps) const
- {
- std::ostringstream json;
- int first = 1;
-
- json << "\"[";
- for(auto rep: reps)
- {
- if(first)
- {
- first = 0;
- json << escapeString(rep.getJSONRepresentation());
- }
- else
- {
- json << ",";
- json << escapeString(rep.getJSONRepresentation());
- }
- }
- json << "]\"";
-
- return json.str();
- }
-
-
- };
-
- inline void split(std::string input, char delimiter, std::vector<std::string>& tokens)
- {
- std::stringstream ss(input);
- std::string item;
-
- while(std::getline(ss, item, delimiter))
- {
- tokens.push_back(item);
- }
- }
-
- class ParseVisitor : public boost::static_visitor<void>
- {
- public:
-
- ParseVisitor(std::string str): m_str(str)
- {
- }
-
- void operator() (int& i) const
- {
- i = std::stoi(m_str);
- }
-
- void operator() (double& d) const
- {
- d = std::stod(m_str);
- }
-
- void operator() (std::string& str) const
- {
- str = m_str;
- }
-
- void operator() (bool& b) const
- {
- b = m_str.compare("true") == 0;
- }
-
- void operator() (std::vector<int>& numbers) const
- {
- numbers.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- numbers.push_back(std::stoi(s));
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
-
- }
-
- void operator() (std::vector<double>& numbers) const
- {
- numbers.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- numbers.push_back(std::stod(s));
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
- }
-
- void operator() (std::vector<bool>& bools) const
- {
- bools.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(2, m_str.length()-3);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- bools.push_back(s.compare("true") == 0);
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
-
- }
-
- void operator() (std::vector<std::string>& strings) const
- {
- strings.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- strings.push_back(s);
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
- }
-
- void operator() (std::vector<OCRepresentation>& reps) const
- {
- reps.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- reps.push_back(parseJSONToRepresentation(s));
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
- }
-
- void operator() (OCRepresentation& rep) const
- {
- rep = parseJSONToRepresentation(m_str);
- }
-
- private:
- std::string m_str;
- };
-
-
- inline std::string getJSON(const AttributeValue& v)
- {
- return boost::apply_visitor(ComposeVisitor(), v);
- }
-
- inline void parseJSON(AttributeValue& v, std::string str)
- {
- boost::apply_visitor(ParseVisitor(str), v);
- }
-
- template <typename T>
- void OCRepresentation::setValue(const std::string& str, const T& val)
- {
- m_attributeMap[str] = getJSON(val);
- }
-
- template <typename T>
- T OCRepresentation::getValue(const std::string& str) const
- {
- T val = T();
-
- auto x = m_attributeMap.find(str);
-
- if(m_attributeMap.end() != x)
- {
- AttributeValue v = val;
- parseJSON(v, x->second);
- val = boost::get<T>(v);
- }
-
- return val;
- }
-
- template <typename T>
- bool OCRepresentation::getValue(const std::string& str, T& val) const
- {
- auto x = m_attributeMap.find(str);
-
- if(m_attributeMap.end() != x)
- {
- AttributeValue v = val;
- parseJSON(v, x->second);
- val = boost::get<T>(v);
- return true;
- }
- else
- {
- return false;
- }
- }
-
+ //
// Typedef for header option vector
// OCHeaderOption class is in HeaderOption namespace
typedef std::vector<HeaderOption::OCHeaderOption> HeaderOptions;
/// @file OCRepresentation.h
-/// @brief This file contains the declaration of classes and its members
+/// @brief This file contains the declaration of classes and its members
/// related to OCRepresentation
#ifndef __OCREPRESENTATION_H
#define __OCREPRESENTATION_H
-#include <OCApi.h>
-#include <OCResource.h>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <AttributeValue.h>
+#include <StringConstants.h>
+
+// note: is there any way to move this later so that the implementers don't need to
+// reference them?
+#include <cereal/cereal.hpp>
+#include <cereal/types/map.hpp>
+#include <cereal/types/vector.hpp>
+#include <OicJsonSerializer.hpp>// Customized Cereal serializer, required for a few functions
+#include <cereal/types/utility.hpp>
+
+#include <OCException.h>
namespace OC
{
-
+
+ enum class InterfaceType
+ {
+ None,
+ LinkParent,
+ BatchParent,
+ DefaultParent,
+ LinkChild,
+ BatchChild,
+ DefaultChild
+ };
+
+ // The consumer requires resource info to be printed in 2 different ways, both with the "oc":[]
+ // and without. This enum is used to differentiate between the two situations. When the
+ // serialize is called with Include OC, we encode OC, otherwise we skip it and return just the
+ // contents of the array.
+ enum class OCInfoFormat
+ {
+ IncludeOC,
+ ExcludeOC
+ };
+
+ class MessageContainer
+ {
+ public:
+ void setJSONRepresentation(const std::string& payload);
+
+ void setJSONRepresentation(const unsigned char* payload);
+
+ std::string getJSONRepresentation(OCInfoFormat f) const;
+
+ const std::vector<OCRepresentation>& representations() const;
+
+ void addRepresentation(const OCRepresentation& rep);
+
+ const OCRepresentation& operator[](int index) const
+ {
+ return m_reps[index];
+ }
+
+ const OCRepresentation& back() const
+ {
+ return m_reps.back();
+ }
+ private:
+ std::vector<OCRepresentation> m_reps;
+ };
+ class OCRepresentation
+ {
+ public:
+ OCRepresentation();
+ std::string getJSONRepresentation() const;
+
+ void addChild(const OCRepresentation&);
+
+ void clearChildren();
+
+ const std::vector<OCRepresentation>& getChildren() const;
+
+ void setChildren(const std::vector<OCRepresentation>& children);
+
+ void setUri(const std::string& uri);
+
+ std::string getUri() const;
+
+ const std::vector<std::string>& getResourceTypes() const;
+
+ void setResourceTypes(const std::vector<std::string>& resourceTypes);
+
+ const std::vector<std::string>& getResourceInterfaces() const;
+
+ void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces);
+
+ bool empty() const;
+
+ int numberOfAttributes() const;
+
+ bool erase(const std::string& str);
+
+ template <typename T>
+ void setValue(const std::string& str, const T& val)
+ {
+ m_values[str] = val;
+ }
+
+ template <typename T>
+ bool getValue(const std::string& str, T& val) const
+ {
+ auto x = m_values.find(str);
+
+ if(x!= m_values.end())
+ {
+ val = boost::get<T>(x->second);
+ return true;
+ }
+ else
+ {
+ val = T();
+ return false;
+ }
+ }
+
+ template <typename T>
+ T getValue(const std::string& str) const
+ {
+ T val = T();
+ auto x = m_values.find(str);
+ if(x != m_values.end())
+ {
+ val = boost::get<T>(x->second);
+ }
+ return val;
+ }
+
+ bool hasAttribute(const std::string& str) const;
+
+ void setNULL(const std::string& str);
+
+ bool isNULL(const std::string& str) const;
+ private:
+ friend class OCResourceResponse;
+ friend class cereal::access;
+
+ // the root node has a slightly different JSON version
+ // based on the interface type configured in ResourceResponse.
+ // This allows ResourceResponse to set it, so that the save function
+ // doesn't serialize things that it isn't supposed to serialize.
+ void setInterfaceType(InterfaceType ift)
+ {
+ m_interfaceType = ift;
+ }
+
+ // class used to wrap the 'prop' feature of the save/load
+ class Prop
+ {
+ public:
+ Prop(std::vector<std::string>& resourceTypes,
+ std::vector<std::string>& interfaces)
+ : m_types(resourceTypes), m_interfaces(interfaces)
+ {}
+
+ /* Prop(const std::vector<std::string>& resourceTypes,
+ const std::vector<std::string>& interfaces)
+ :m_types(resourceTypes),
+ m_interfaces(interfaces)
+ {}*/
+ private:
+ friend class cereal::access;
+ template <class Archive>
+ void save(Archive& ar) const
+ {
+ if(m_types.size() > 0)
+ {
+ ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+ }
+
+ if(m_interfaces.size()>0)
+ {
+ ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+ }
+ }
+
+ template<class Archive>
+ void load(Archive& ar)
+ {
+ optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+ optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+ }
+
+ std::vector<std::string>& m_types;
+ std::vector<std::string>& m_interfaces;
+ };
+ template<class Archive, class Val>
+ static void optional_load(Archive& ar, Val&& v)
+ {
+ try
+ {
+ ar(v);
+ }
+ catch(cereal::Exception& e)
+ {
+ ar.setNextName(nullptr);
+ // Loading a key that doesn't exist results in an exception
+ // Since "Not Found" is a valid condition for us, we swallow
+ // this exception and the archive will not load anything
+ }
+ }
+ template<class Archive>
+ void save(Archive& ar) const
+ {
+ // printed for all interface types
+ if(!m_uri.empty())
+ {
+ ar(cereal::make_nvp(Key::URIKEY, m_uri));
+ }
+
+ if((m_interfaceType == InterfaceType::None
+ || m_interfaceType==InterfaceType::DefaultChild
+ || m_interfaceType==InterfaceType::LinkChild)
+ && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+ {
+ // The Prop object requires that it refer to non-const vectors
+ // so that it can alter them in the 'load' case. In the save case
+ // (initiated here) it will not modify the object. So, to keep the
+ // compiler happy, removing the 'const' context here is necessary.
+ const std::vector<std::string>& rt(m_resourceTypes);
+ const std::vector<std::string>& intf(m_interfaces);
+ Prop temp(const_cast<std::vector<std::string>&>(rt),
+ const_cast<std::vector<std::string>&>(intf));
+ ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
+ }
+
+ // printed only for BatchChildren and DefaultParent
+ if((m_interfaceType == InterfaceType::None
+ || m_interfaceType == InterfaceType::BatchChild
+ || m_interfaceType == InterfaceType::DefaultParent)
+ && m_values.size()>0)
+ {
+ ar(cereal::make_nvp(Key::REPKEY, m_values));
+ }
+ }
+
+ template<class Archive>
+ void load(Archive& ar)
+ {
+ optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
+ {
+ Prop temp(m_resourceTypes, m_interfaces);
+ optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
+ }
+ optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
+ }
+
+ private:
+ std::string m_uri;
+ std::vector<OCRepresentation> m_children;
+ std::map<std::string, AttributeValue> m_values;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_interfaces;
+
+ InterfaceType m_interfaceType;
+ };
} // namespace OC
+// code needed to serialize a string::Attribute value map
+namespace OC
+{
+ namespace detail
+ {
+ template<class Archive>
+ class WriteAttributeValue : public boost::static_visitor<>
+ {
+ public:
+ WriteAttributeValue(const std::string& name, Archive& ar)
+ :m_name(name), m_archive(ar)
+ {}
+
+ template<class T>
+ void operator()(const T& value) const
+ {
+ m_archive(cereal::make_nvp(m_name, value));
+ }
+ private:
+ std::string m_name;
+ Archive& m_archive;
+ };
+ }
+}
+
+namespace cereal
+{
+ // take no action when serializing the null type, because the 'save' below
+ // doesn't use the visitor for this type.
+ template <class Archive>
+ void serialize(Archive&, OC::NullType t)
+ {}
+
+ template<class Archive>
+ void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
+ {
+ for(const auto& kv : vals)
+ {
+ const auto& k = kv.first;
+ const auto& v = kv.second;
+
+ if(v.which() != OC::AttributeValueNullIndex)
+ {
+ OC::detail::WriteAttributeValue<Archive> writer(k,ar);
+ boost::apply_visitor(writer, v);
+ }
+ else
+ {
+ ar.setNextName(k.c_str());
+ ar.writeName();
+ ar.saveValue();
+ }
+ }
+ }
+
+ template<class Archive>
+ void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
+ {
+ ar.loadAttributeValues(vals);
+ }
+}
+
#endif //__OCREPRESENTATION_H
#include <random>
#include <algorithm>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
#include <OCApi.h>
#include <ResourceInitException.h>
#include <IClientWrapper.h>
class OCResource
{
friend class OCPlatform_impl;
- friend class InProcClientWrapper;
-
+ friend class ListenOCContainer;
public:
typedef std::shared_ptr<OCResource> Ptr;
/**
#ifndef __OCRESOURCEREQUEST_H
#define __OCRESOURCEREQUEST_H
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
#include "OCApi.h"
#include "OCRepresentation.h"
+void formResourceRequest(OCEntityHandlerFlag,
+ OCEntityHandlerRequest*,
+ std::shared_ptr<OC::OCResourceRequest>);
+
+
namespace OC
{
/**
ObservationInfo m_observationInfo;
HeaderOptions m_headerOptions;
- public:
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
+ private:
+ friend void (::formResourceRequest)(OCEntityHandlerFlag, OCEntityHandlerRequest*,
+ std::shared_ptr<OC::OCResourceRequest>);
void setRequestType(const std::string& requestType)
{
m_requestType = requestType;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setPayload(const std::string& requestPayload)
{
- AttributeMap attributeMap;
- // TODO: The following JSON Parse implementation should be seperated into utitilites
- // and used wherever required.
- // e.g. parse(std::string& payload, Attributemap& attributeMap)
-
- std::stringstream requestStream;
- requestStream << requestPayload;
- boost::property_tree::ptree root;
- try
- {
- boost::property_tree::read_json(requestStream, root);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
+ MessageContainer info;
+ info.setJSONRepresentation(requestPayload);
+
+ const std::vector<OCRepresentation>& reps = info.representations();
+ if(reps.size() >0)
{
- //TOD: log this
- return;
+ std::vector<OCRepresentation>::const_iterator itr = reps.begin();
+ std::vector<OCRepresentation>::const_iterator back = reps.end();
+ m_representation = *itr;
+ ++itr;
+
+ for(;itr != back; ++itr)
+ {
+ m_representation.addChild(*itr);
+ }
}
-
- // TODO this expects the representation oc:{} and not oc:[{}]
- // this representation is fine when setting for simple resource.
- boost::property_tree::ptree payload = root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
-
- for(auto& item: payload)
+ else
{
- std::string name = item.first.data();
- std::string value = item.second.data();
-
- attributeMap[name] = value;
+ throw OCException(OC::Exception::INVALID_REPRESENTATION);
}
-
- m_representation.setAttributeMap(attributeMap);
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setQueryParams(QueryParamsMap& queryParams)
{
m_queryParameters = queryParams;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setRequestHandlerFlag(int requestHandlerFlag)
{
m_requestHandlerFlag = requestHandlerFlag;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setObservationInfo(const ObservationInfo& observationInfo)
{
m_observationInfo = observationInfo;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setHeaderOptions(const HeaderOptions& headerOptions)
{
m_headerOptions = headerOptions;
using namespace std;
+
+void (processResourceResponse)(OCEntityHandlerFlag,
+ OCEntityHandlerRequest*,
+ std::shared_ptr<OC::OCResourceResponse> pResponse);
+
+
namespace OC
{
/**
public:
typedef std::shared_ptr<OCResourceResponse> Ptr;
- /**
- * Default destructor
- */
- OCResourceResponse() {}
+ OCResourceResponse()
+ {}
- /**
- * Virtual destructor
- */
virtual ~OCResourceResponse(void) {}
/**
* @param interface specifies the interface
*/
void setResourceRepresentation(OCRepresentation& rep, std::string interface) {
- if(!interface.compare(LINK_INTERFACE))
- {
- setResourceRepresentationLL(rep);
- }
- else if(!interface.compare(BATCH_INTERFACE))
- {
- setResourceRepresentationBatch(rep);
- }
- else
- {
- setResourceRepresentationDefault(rep);
- }
- // TODO other interfaces
+ m_interface = interface;
+ m_representation = rep;
}
/**
*/
void setResourceRepresentation(OCRepresentation& rep) {
// Call the default
- setResourceRepresentationDefault(rep);
+ m_interface = DEFAULT_INTERFACE;
+ m_representation = rep;
}
/**
// Call the above function
setResourceRepresentation(rep);
}
+ private:
+ std::string m_newResourceUri;
+ int m_errorCode;
+ HeaderOptions m_headerOptions;
+ std::string m_interface;
+ OCRepresentation m_representation;
+ private:
+ friend void (::processResourceResponse)(OCEntityHandlerFlag,
+ OCEntityHandlerRequest*,
+ std::shared_ptr<OC::OCResourceResponse> pResponse);
+ std::string getPayload() const
+ {
+ MessageContainer inf;
+ OCRepresentation first(m_representation);
- /**
- * API to set the entire resource attribute representation (Linked List Interface))
- * @param attributeMap reference containing the name value pairs representing the resource's
- * attributes
- */
- void setResourceRepresentationLL(OCRepresentation& rep) {
-
- // Default Set
-
- ostringstream payload;
-
- // Parent
- payload << "{";
- payload << "\"href\":";
- payload << "\"" ;
- payload << rep.getUri();
- payload << "\"" ;
- payload << "}";
-
- // Children stuff
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
+ if(m_interface==LINK_INTERFACE)
{
- payload << ",{\"href\":";
-
- payload << "\"" ;
- payload << oitr->getUri();
- payload << "\"" ;
-
- payload << ",\"prop\":{";
-
- payload << "\"rt\":[";
- std::vector<std::string> types = oitr->getResourceTypes();
- for(auto itr = types.begin(); itr != types.end(); ++itr)
- {
- if(itr != types.begin())
- {
- payload << ',';
- }
-
- payload << *itr;
- }
- payload << "],";
-
- payload << "\"if\":[";
- std::vector<std::string> interfaces = oitr->getResourceInterfaces();
- for(auto itr = interfaces.begin(); itr != interfaces.end(); ++itr)
- {
- if(itr != interfaces.begin())
- {
- payload << ',';
- }
-
- payload << "\"" << *itr << "\"";
- }
- payload << "]";
-
- payload << "}}";
+ first.setInterfaceType(InterfaceType::LinkParent);
}
-
- m_payload = payload.str();
- }
-
- /**
- * API to set the entire resource attribute representation (Default))
- * @param attributeMap reference containing the name value pairs representing the resource's
- * attributes
- */
- void setResourceRepresentationDefault(OCRepresentation& rep) {
-
- // Default Set
-
- ostringstream payload;
-
- // Parent
- payload << "{";
- payload << "\"href\":";
- payload << "\"" ;
- payload << rep.getUri();
- payload << "\"" ;
-
- payload << ",\"rep\":";
-
- payload << rep.getJSONRepresentation();
-
- payload << "}";
-
- // Children stuff
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
+ else if(m_interface==BATCH_INTERFACE)
{
- payload << ",{\"href\":";
+ first.setInterfaceType(InterfaceType::BatchParent);
+ }
+ else
+ {
+ first.setInterfaceType(InterfaceType::DefaultParent);
+ }
- payload << "\"" ;
- payload << oitr->getUri();
- payload << "\"" ;
+ inf.addRepresentation(first);
- payload << ",\"prop\":{";
+ for(const OCRepresentation& rep : m_representation.getChildren())
+ {
+ OCRepresentation cur(rep);
- payload << "\"rt\":[";
- std::vector<std::string> types = oitr->getResourceTypes();
- for(auto itr = types.begin(); itr != types.end(); ++itr)
+ if(m_interface==LINK_INTERFACE)
{
- if(itr != types.begin())
- {
- payload << ',';
- }
-
- payload << "\"" << *itr << "\"";
+ cur.setInterfaceType(InterfaceType::LinkChild);
}
- payload << "],";
-
- payload << "\"if\":[";
- std::vector<std::string> interfaces = oitr->getResourceInterfaces();
- for(auto itr = interfaces.begin(); itr != interfaces.end(); ++itr)
+ else if(m_interface==BATCH_INTERFACE)
{
- if(itr != interfaces.begin())
- {
- payload << ',';
- }
-
- payload << "\"" << *itr << "\"";
+ cur.setInterfaceType(InterfaceType::BatchChild);
+ }
+ else
+ {
+ cur.setInterfaceType(InterfaceType::DefaultChild);
}
- payload << "]";
-
- payload << "}}";
- }
-
- m_payload = payload.str();
- }
-
- /**
- * API to set the entire resource attribute representation (BATCH)
- * @param attributeMap reference containing the name value pairs representing the resource's
- * attributes
- */
- void setResourceRepresentationBatch(OCRepresentation& rep) {
- ostringstream payload;
-
- // Parent
- payload << "{";
- payload << "\"href\":";
- payload << "\"" ;
- payload << rep.getUri();
- payload << "\"" ;
- payload << "}";
-
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
- {
- payload << ',';
-
- payload << "{";
-
- payload << "\"href\":";
-
- payload << "\"" ;
- payload << oitr->getUri();
- payload << "\"" ;
-
- payload << ",\"rep\":";
- payload << oitr->getJSONRepresentation();
+ inf.addRepresentation(cur);
- payload << "}";
}
- m_payload = payload.str();
+ return inf.getJSONRepresentation(OCInfoFormat::ExcludeOC);
}
-
- private:
- std::string m_newResourceUri;
- std::string m_payload;
- int m_errorCode;
- HeaderOptions m_headerOptions;
-
- // TODO only stack should have visibility and apps should not
public:
/**
int getErrorCode() const;
/**
- * This API allows to retrieve headerOptions from a response
- */
- const HeaderOptions& getHeaderOptions() const
+ * Get the Response Representation
+ */
+ const OCRepresentation& getResourceRepresentation() const
{
- return m_headerOptions;
+ return m_representation;
}
-
/**
- * Get the resource attribute representation
+ * This API allows to retrieve headerOptions from a response
*/
- AttributeMap& getResourceRepresentation() const;
-
- // TODO This should go away & just use getResourceRepresentation
- std::string getPayload()
+ const HeaderOptions& getHeaderOptions() const
{
- return m_payload;
+ return m_headerOptions;
}
};
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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 <cereal/cereal.hpp>
+#include <cereal/types/memory.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/archives/json.hpp>
+
+#include <StringConstants.h>
+
+namespace OC
+{
+ class ListenOCContainer
+ {
+ private:
+ enum class OCSecureType
+ {
+ IPv4Secure,
+ IPv4
+ };
+
+ class ListenResourceContainer
+ {
+ class ListenResourcePropertiesContainer
+ {
+ friend class cereal::access;
+ friend class ListenResourceContainer;
+
+ template<class Archive>
+ void serialize(Archive& ar)
+ {
+ try
+ {
+ m_observable=false;
+ int obsTemp;
+ ar(cereal::make_nvp(OC::Key::OBSERVABLEKEY, obsTemp));
+ m_observable = obsTemp != 0;
+ }
+ catch(cereal::Exception&)
+ {
+ // we swallow this exception, since it means the key
+ // doesn't exist, allowing these to be optional
+ }
+
+ try
+ {
+ m_secure = false;
+ int secureTemp;
+ ar(cereal::make_nvp(OC::Key::SECUREKEY, secureTemp));
+ m_secure = secureTemp != 0;
+
+ m_port = -1;
+ ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
+ }
+ catch(cereal::Exception&)
+ {}
+
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
+ }
+ catch(cereal::Exception&)
+ {}
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
+ }
+ catch(cereal::Exception&)
+ {}
+ }
+
+ bool m_observable;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_interfaces;
+ bool m_secure;
+ int m_port;
+ };
+
+ public:
+ ListenResourceContainer() : m_loaded(false)
+ {}
+
+ private:
+ friend class cereal::access;
+ friend class ListenOCContainer;
+
+ template <class Archive>
+ void serialize(Archive& ar)
+ {
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::URIKEY, m_uri));
+ m_loaded=true;
+ }
+ catch(cereal::Exception&)
+ {}
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
+ m_loaded=true;
+ }
+ catch(cereal::Exception&)
+ {}
+ }
+
+
+ std::string m_uri;
+ bool m_loaded;
+ ListenResourcePropertiesContainer m_props;
+
+ bool loaded() const
+ {
+ return m_loaded;
+ }
+
+ bool observable() const
+ {
+ return m_props.m_observable;
+ }
+
+ OCSecureType secureType() const
+ {
+ return m_props.m_secure?OCSecureType::IPv4Secure :OCSecureType::IPv4;
+ }
+
+ int port() const
+ {
+ return m_props.m_port;
+ }
+
+ std::vector<std::string> resourceTypes() const
+ {
+ return m_props.m_resourceTypes;
+ }
+
+ std::vector<std::string> interfaces() const
+ {
+ return m_props.m_interfaces;
+ }
+ };
+
+ private:
+ friend class cereal::access;
+ template <class Archive>
+ void serialize(Archive& ar)
+ {
+ std::vector<ListenResourceContainer> resources;
+ ar(resources);
+ }
+ public:
+ ListenOCContainer(std::weak_ptr<IClientWrapper> cw, const OCDevAddr& address,
+ std::stringstream& json):
+ m_clientWrapper(cw), m_address(address)
+ {
+ LoadFromJson(json);
+ }
+
+ const std::vector<std::shared_ptr<OCResource>>& Resources() const
+ {
+ return m_resources;
+ }
+
+ private:
+ std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
+ {
+ uint8_t addr1;
+ uint8_t addr2;
+ uint8_t addr3;
+ uint8_t addr4;
+ uint16_t port;
+
+ ostringstream os;
+
+ if(sec== OCSecureType::IPv4)
+ {
+ os<<"coap://";
+ }
+ else if(sec == OCSecureType::IPv4Secure)
+ {
+ os<<"coaps://";
+ }
+ else
+ {
+ oclog() << "ConvertOCAddrToString(): invalid SecureType"<<std::flush;
+ throw ResourceInitException(false, false, false, false, false, true);
+ }
+
+ if(0== OCDevAddrToIPv4Addr(&m_address, &addr1, &addr2, &addr3, &addr4))
+ {
+ // nothing to do, successful case.
+ }
+ else
+ {
+ oclog() << "ConvertOCAddrToString(): Invalid Ip"
+ << std::flush;
+ throw ResourceInitException(false, false, false, false, false, true);
+ }
+
+ os<<static_cast<int>(addr1)<<'.'
+ <<static_cast<int>(addr2)<<'.'
+ <<static_cast<int>(addr3)<<'.'
+ <<static_cast<int>(addr4);
+
+ if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
+ {
+ port = static_cast<uint16_t>(secureport);
+ }
+ else if(sec == OCSecureType::IPv4 && 0==OCDevAddrToPort(&m_address, &port))
+ {
+ // nothing to do, this is a successful case
+ }
+ else
+ {
+ oclog() << "ConvertOCAddrToString() : Invalid Port"
+ <<std::flush;
+ throw ResourceInitException(false, false, false, false, true, false);
+ }
+
+ os <<":"<< static_cast<int>(port);
+
+ return os.str();
+ }
+
+ void LoadFromJson(std::stringstream& json)
+ {
+ cereal::JSONInputArchive archive(json);
+
+ std::vector<ListenResourceContainer> resources;
+ archive(cereal::make_nvp(OC::Key::OCKEY, resources));
+
+ m_resources.clear();
+
+ for(const auto& res : resources)
+ {
+ try
+ {
+ if(res.loaded())
+ {
+ m_resources.push_back(std::shared_ptr<OCResource>(
+ new OCResource(m_clientWrapper,
+ ConvertOCAddrToString(res.secureType(),res.port()),
+ res.m_uri, res.observable(), res.resourceTypes(),
+ res.interfaces())));
+ }
+
+ }
+ catch(ResourceInitException& e)
+ {
+ oclog() << "listenCallback(): failed to create resource: " << e.what()
+ << std::flush;
+ }
+ }
+ }
+ std::vector<std::shared_ptr<OC::OCResource>> m_resources;
+ std::weak_ptr<IClientWrapper> m_clientWrapper;
+ OCDevAddr m_address;
+ };
+}
--- /dev/null
+/*! \file OicJsonSerializer.hpp
+ \brief JSON input and output archives.
+Note: this has been customized by Intel(R) for usage in the OIC project.
+Nearly the entire file is from Cereal (see copyright notice below) other than specified
+below
+Added:
+#include of AttributeValue Type
+JSONOutputArchive::saveValue() to add JSON null value
+loadAttributeValues to get attribute values out of a map (implemented in OCRepresentation)
+
+*/
+/*
+ Copyright (c) 2014, Randolph Voorhies, Shane Grant
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of cereal nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CEREAL_ARCHIVES_JSON_HPP_
+#define CEREAL_ARCHIVES_JSON_HPP_
+
+#include <AttributeValue.h>
+#include <cereal/cereal.hpp>
+#include <cereal/details/util.hpp>
+namespace cereal
+{
+ //! An exception thrown when rapidjson fails an internal assertion
+ /*! @ingroup Utility */
+ struct RapidJSONException : Exception
+ { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
+}
+
+// Override rapidjson assertions to throw exceptions by default
+#ifndef RAPIDJSON_ASSERT
+#define RAPIDJSON_ASSERT(x) if(!(x)){ \
+ throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
+#endif // RAPIDJSON_ASSERT
+
+#include <cereal/external/rapidjson/writer.h>
+#include <cereal/external/rapidjson/genericstream.h>
+#include <cereal/external/rapidjson/reader.h>
+#include <cereal/external/rapidjson/document.h>
+#include <cereal/external/base64.hpp>
+
+#include <limits>
+#include <sstream>
+#include <stack>
+#include <vector>
+#include <string>
+
+namespace cereal
+{
+ // ######################################################################
+ //! An output archive designed to save data to JSON
+ /*! This archive uses RapidJSON to build serialie data to JSON.
+
+ JSON archives provides a human readable output but at decreased
+ performance (both in time and space) compared to binary archives.
+
+ JSON benefits greatly from name-value pairs, which if present, will
+ name the nodes in the output. If these are not present, each level
+ of the output will be given an automatically generated delimited name.
+
+ The precision of the output archive controls the number of decimals output
+ for floating point numbers and should be sufficiently large (i.e. at least 20)
+ if there is a desire to have binary equality between the numbers output and
+ those read in. In general you should expect a loss of precision when going
+ from floating point to text and back.
+
+ JSON archives do not output the size information for any dynamically sized structure
+ and instead infer it from the number of children for a node. This means that data
+ can be hand edited for dynamic sized structures and will still be readable. This
+ is accomplished through the cereal::SizeTag object, which will cause the archive
+ to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates
+ that the container is variable sized and may be edited.
+
+ \ingroup Archives */
+ class JSONOutputArchive : public OutputArchive<JSONOutputArchive>
+ {
+ enum class NodeType { StartObject, InObject, StartArray, InArray };
+
+ typedef rapidjson::GenericWriteStream WriteStream;
+ typedef rapidjson::Writer<WriteStream> JSONWriter;
+
+ public:
+ /*! @name Common Functionality
+ Common use cases for directly interacting with an JSONOutputArchive */
+ //! @{
+
+ //! A class containing various advanced options for the JSON archive
+ class Options
+ {
+ public:
+ //! Default options
+ static Options Default(){ return Options(); }
+
+ //! Specify specific options for the JSONOutputArchive
+ /*! @param precision The precision used for floating point numbers*/
+ explicit Options( int precision = std::numeric_limits<double>::max_digits10) :
+ itsPrecision( precision ) { }
+
+ private:
+ friend class JSONOutputArchive;
+ int itsPrecision;
+ };
+
+ //! Construct, outputting to the provided stream
+ /*! @param stream The stream to output to.
+ @param options The JSON specific options to use. See the Options struct
+ for the values of default parameters */
+ JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
+ OutputArchive<JSONOutputArchive>(this),
+ itsWriteStream(stream),
+ itsWriter(itsWriteStream, options.itsPrecision),
+ itsNextName(nullptr)
+ {
+ itsNameCounter.push(0);
+ itsNodeStack.push(NodeType::StartObject);
+ }
+
+ //! Destructor, flushes the JSON
+ ~JSONOutputArchive()
+ {
+ itsWriter.EndObject();
+ }
+
+ //! Saves some binary data, encoded as a base64 string, with an optional name
+ /*! This will create a new node, optionally named, and insert a value that consists of
+ the data encoded as a base64 string */
+ void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
+ {
+ setNextName( name );
+ writeName();
+
+ auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
+ saveValue( base64string );
+ };
+
+ //! @}
+ /*! @name Internal Functionality
+ Functionality designed for use by those requiring control over the inner mechanisms of
+ the JSONOutputArchive */
+ //! @{
+
+ //! Starts a new node in the JSON output
+ /*! The node can optionally be given a name by calling setNextName prior
+ to creating the node
+
+ Nodes only need to be started for types that are themselves objects or arrays */
+ void startNode()
+ {
+ writeName();
+ itsNodeStack.push(NodeType::StartObject);
+ itsNameCounter.push(0);
+ }
+
+ //! Designates the most recently added node as finished
+ void finishNode()
+ {
+ // if we ended up serializing an empty object or array, writeName
+ // will never have been called - so start and then immediately end
+ // the object/array.
+ //
+ // We'll also end any object/arrays we happen to be in
+ switch(itsNodeStack.top())
+ {
+ case NodeType::StartArray:
+ itsWriter.StartArray();
+ case NodeType::InArray:
+ itsWriter.EndArray();
+ break;
+ case NodeType::StartObject:
+ itsWriter.StartObject();
+ case NodeType::InObject:
+ itsWriter.EndObject();
+ break;
+ }
+
+ itsNodeStack.pop();
+ itsNameCounter.pop();
+ }
+
+ //! Sets the name for the next node created with startNode
+ void setNextName( const char * name )
+ {
+ itsNextName = name;
+ }
+
+ //! Saves a null to the current node, added by Intel
+ void saveValue() { itsWriter.Null_(); }
+ //! Saves a bool to the current node
+ void saveValue(bool b) { itsWriter.Bool_(b); }
+ //! Saves an int to the current node
+ void saveValue(int i) { itsWriter.Int(i); }
+ //! Saves a uint to the current node
+ void saveValue(unsigned u) { itsWriter.Uint(u); }
+ //! Saves an int64 to the current node
+ void saveValue(int64_t i64) { itsWriter.Int64(i64); }
+ //! Saves a uint64 to the current node
+ void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
+ //! Saves a double to the current node
+ void saveValue(double d) { itsWriter.Double(d); }
+ //! Saves a string to the current node
+ void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
+ //! Saves a const char * to the current node
+ void saveValue(char const * s) { itsWriter.String(s); }
+
+ private:
+ // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
+ // special overloads to handle these cases.
+
+ //! 32 bit signed long saving to current node
+ template <class T> inline
+ typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
+ saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
+
+ //! non 32 bit signed long saving to current node
+ template <class T> inline
+ typename std::enable_if<sizeof(T) != sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
+ saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
+
+ //! 32 bit unsigned long saving to current node
+ template <class T> inline
+ typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
+ saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
+
+ //! non 32 bit unsigned long saving to current node
+ template <class T> inline
+ typename std::enable_if<sizeof(T) != sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
+ saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
+
+ public:
+#ifdef _MSC_VER
+ //! MSVC only long overload to current node
+ void saveValue( unsigned long lu ){ saveLong( lu ); };
+#else // _MSC_VER
+ //! Serialize a long if it would not be caught otherwise
+ template <class T> inline
+ typename std::enable_if<std::is_same<T, long>::value &&
+ !std::is_same<T, std::int32_t>::value &&
+ !std::is_same<T, std::int64_t>::value, void>::type
+ saveValue( T t ){ saveLong( t ); }
+
+ //! Serialize an unsigned long if it would not be caught otherwise
+ template <class T> inline
+ typename std::enable_if<std::is_same<T, unsigned long>::value &&
+ !std::is_same<T, std::uint32_t>::value &&
+ !std::is_same<T, std::uint64_t>::value, void>::type
+ saveValue( T t ){ saveLong( t ); }
+#endif // _MSC_VER
+
+ //! Save exotic arithmetic as strings to current node
+ /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ !std::is_same<T, long>::value &&
+ !std::is_same<T, unsigned long>::value &&
+ !std::is_same<T, std::int64_t>::value &&
+ !std::is_same<T, std::uint64_t>::value &&
+ (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
+ saveValue(T const & t)
+ {
+ std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
+ ss << t;
+ saveValue( ss.str() );
+ }
+
+ //! Write the name of the upcoming node and prepare object/array state
+ /*! Since writeName is called for every value that is output, regardless of
+ whether it has a name or not, it is the place where we will do a deferred
+ check of our node state and decide whether we are in an array or an object.
+
+ The general workflow of saving to the JSON archive is:
+
+ 1. (optional) Set the name for the next node to be created, usually done by an NVP
+ 2. Start the node
+ 3. (if there is data to save) Write the name of the node (this function)
+ 4. (if there is data to save) Save the data (with saveValue)
+ 5. Finish the node
+ */
+ void writeName()
+ {
+ NodeType const & nodeType = itsNodeStack.top();
+
+ // Start up either an object or an array, depending on state
+ if(nodeType == NodeType::StartArray)
+ {
+ itsWriter.StartArray();
+ itsNodeStack.top() = NodeType::InArray;
+ }
+ else if(nodeType == NodeType::StartObject)
+ {
+ itsNodeStack.top() = NodeType::InObject;
+ itsWriter.StartObject();
+ }
+
+ // Array types do not output names
+ if(nodeType == NodeType::InArray) return;
+
+ if(itsNextName == nullptr)
+ {
+ std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
+ saveValue(name);
+ }
+ else
+ {
+ saveValue(itsNextName);
+ itsNextName = nullptr;
+ }
+ }
+
+ //! Designates that the current node should be output as an array, not an object
+ void makeArray()
+ {
+ itsNodeStack.top() = NodeType::StartArray;
+ }
+
+ //! @}
+
+ private:
+ WriteStream itsWriteStream; //!< Rapidjson write stream
+ JSONWriter itsWriter; //!< Rapidjson writer
+ char const * itsNextName; //!< The next name
+ std::stack<uint32_t> itsNameCounter; //!< Counter for creating unique names for unnamed nodes
+ std::stack<NodeType> itsNodeStack;
+ }; // JSONOutputArchive
+
+ // ######################################################################
+ //! An input archive designed to load data from JSON
+ /*! This archive uses RapidJSON to read in a JSON archive.
+
+ Input JSON should have been produced by the JSONOutputArchive. Data can
+ only be added to dynamically sized containers (marked by JSON arrays) -
+ the input archive will determine their size by looking at the number of child nodes.
+ Only JSON originating from a JSONOutputArchive is officially supported, but data
+ from other sources may work if properly formatted.
+
+ The JSONInputArchive does not require that nodes are loaded in the same
+ order they were saved by JSONOutputArchive. Using name value pairs (NVPs),
+ it is possible to load in an out of order fashion or otherwise skip/select
+ specific nodes to load.
+
+ The default behavior of the input archive is to read sequentially starting
+ with the first node and exploring its children. When a given NVP does
+ not match the read in name for a node, the archive will search for that
+ node at the current level and load it if it exists. After loading an out of
+ order node, the archive will then proceed back to loading sequentially from
+ its new position.
+
+ Consider this simple example where loading of some data is skipped:
+
+ @code{cpp}
+ // imagine the input file has someData(1-9) saved in order at the top level node
+ ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file
+ ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not
+ // match expected NVP name, so we search
+ // for the given NVP and load that value
+ ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its
+ // current location, proceeding sequentially
+ @endcode
+
+ \ingroup Archives */
+ class JSONInputArchive : public InputArchive<JSONInputArchive>
+ {
+ private:
+ typedef rapidjson::GenericReadStream ReadStream;
+ typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
+ typedef JSONValue::ConstMemberIterator MemberIterator;
+ typedef JSONValue::ConstValueIterator ValueIterator;
+ typedef rapidjson::Document::GenericValue GenericValue;
+
+ public:
+ /*! @name Common Functionality
+ Common use cases for directly interacting with an JSONInputArchive */
+ //! @{
+
+ //! Construct, reading from the provided stream
+ /*! @param stream The stream to read from */
+ JSONInputArchive(std::istream & stream) :
+ InputArchive<JSONInputArchive>(this),
+ itsNextName( nullptr ),
+ itsReadStream(stream)
+ {
+ itsDocument.ParseStream<0>(itsReadStream);
+ itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
+ }
+
+ //! Loads some binary data, encoded as a base64 string
+ /*! This will automatically start and finish a node to load the data, and can be called directly by
+ users.
+
+ Note that this follows the same ordering rules specified in the class description in regards
+ to loading in/out of order */
+ void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
+ {
+ itsNextName = name;
+
+ std::string encoded;
+ loadValue( encoded );
+ auto decoded = base64::decode( encoded );
+
+ if( size != decoded.size() )
+ throw Exception("Decoded binary data size does not match specified size");
+
+ std::memcpy( data, decoded.data(), decoded.size() );
+ itsNextName = nullptr;
+ };
+
+ // Intel Added this as a custom parsing hook for the AttributeValue map
+ void loadAttributeValues(std::map<std::string, OC::AttributeValue>& map);
+
+ private:
+ //! @}
+ /*! @name Internal Functionality
+ Functionality designed for use by those requiring control over the inner mechanisms of
+ the JSONInputArchive */
+ //! @{
+
+ //! An internal iterator that handles both array and object types
+ /*! This class is a variant and holds both types of iterators that
+ rapidJSON supports - one for arrays and one for objects. */
+ class Iterator
+ {
+ public:
+ friend class cereal::JSONInputArchive;
+ Iterator() : itsIndex( 0 ), itsType(Null_) {}
+
+ Iterator(MemberIterator begin, MemberIterator end) :
+ itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
+ { }
+
+ Iterator(ValueIterator begin, ValueIterator end) :
+ itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
+ { }
+
+ //! Advance to the next node
+ Iterator & operator++()
+ {
+ ++itsIndex;
+ return *this;
+ }
+
+ //! Get the value of the current node
+ GenericValue const & value()
+ {
+ switch(itsType)
+ {
+ case Value : return itsValueItBegin[itsIndex];
+ case Member: return itsMemberItBegin[itsIndex].value;
+ default: throw cereal::Exception("Invalid Iterator Type!");
+ }
+ }
+
+ //! Get the name of the current node, or nullptr if it has no name
+ const char * name() const
+ {
+ if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
+ return itsMemberItBegin[itsIndex].name.GetString();
+ else
+ return nullptr;
+ }
+
+ //! Adjust our position such that we are at the node with the given name
+ /*! @throws Exception if no such named node exists */
+ inline void search( const char * searchName )
+ {
+ const auto len = std::strlen( searchName );
+ size_t index = 0;
+ for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
+ if( std::strncmp( searchName, it->name.GetString(), len ) == 0 )
+ {
+ itsIndex = index;
+ return;
+ }
+
+ throw Exception("JSON Parsing failed - provided NVP not found");
+ }
+
+ private:
+ MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
+ ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array)
+ size_t itsIndex; //!< The current index of this iterator
+ enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing
+ };
+
+ //! Searches for the expectedName node if it doesn't match the actualName
+ /*! This needs to be called before every load or node start occurs. This function will
+ check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual
+ next name given. If the names do not match, it will search in the current level of the JSON for that name.
+ If the name is not found, an exception will be thrown.
+
+ Resets the NVP name after called.
+
+ @throws Exception if an expectedName is given and not found */
+ inline void search()
+ {
+ // The name an NVP provided with setNextName()
+ if( itsNextName )
+ {
+ // The actual name of the current node
+ auto const actualName = itsIteratorStack.back().name();
+
+ // Do a search if we don't see a name coming up, or if the names don't match
+ if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
+ itsIteratorStack.back().search( itsNextName );
+ }
+
+ itsNextName = nullptr;
+ }
+
+ public:
+ //! Starts a new node, going into its proper iterator
+ /*! This places an iterator for the next node to be parsed onto the iterator stack. If the next
+ node is an array, this will be a value iterator, otherwise it will be a member iterator.
+
+ By default our strategy is to start with the document root node and then recursively iterate through
+ all children in the order they show up in the document.
+ We don't need to know NVPs to do this; we'll just blindly load in the order things appear in.
+
+ If we were given an NVP, we will search for it if it does not match our the name of the next node
+ that would normally be loaded. This functionality is provided by search(). */
+ void startNode()
+ {
+ search();
+
+ if(itsIteratorStack.back().value().IsArray())
+ itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
+ else
+ itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
+ }
+
+ //! Finishes the most recently started node
+ void finishNode()
+ {
+ itsIteratorStack.pop_back();
+ ++itsIteratorStack.back();
+ }
+
+ //! Sets the name for the next node created with startNode
+ void setNextName( const char * name )
+ {
+ itsNextName = name;
+ }
+
+ //! Loads a value from the current node - small signed overload
+ template<class T> inline
+ typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int64_t), void>::type
+ loadValue(T & val)
+ {
+ search();
+
+ val = itsIteratorStack.back().value().GetInt();
+ ++itsIteratorStack.back();
+ }
+
+ //! Loads a value from the current node - small unsigned overload
+ template<class T> inline
+ typename std::enable_if<(std::is_unsigned<T>::value && sizeof(T) < sizeof(uint64_t)) &&
+ !std::is_same<bool, T>::value, void>::type
+ loadValue(T & val)
+ {
+ search();
+
+ val = itsIteratorStack.back().value().GetUint();
+ ++itsIteratorStack.back();
+ }
+
+ //! Loads a value from the current node - bool overload
+ void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - int64 overload
+ void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - uint64 overload
+ void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - float overload
+ void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - double overload
+ void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - string overload
+ void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
+
+ private:
+ //! Convert a string to a long long
+ void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
+ //! Convert a string to an unsigned long long
+ void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
+ //! Convert a string to a long double
+ void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
+
+ public:
+ //! Loads a value from the current node - long double and long long overloads
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ !std::is_same<T, long>::value &&
+ !std::is_same<T, unsigned long>::value &&
+ !std::is_same<T, std::int64_t>::value &&
+ !std::is_same<T, std::uint64_t>::value &&
+ (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
+ loadValue(T & val)
+ {
+ std::string encoded;
+ loadValue( encoded );
+ stringToNumber( encoded, val );
+ }
+
+ //! Loads the size for a SizeTag
+ void loadSize(size_type & size)
+ {
+ size = (itsIteratorStack.rbegin() + 1)->value().Size();
+ }
+
+ //! @}
+
+ private:
+ const char * itsNextName; //!< Next name set by NVP
+ ReadStream itsReadStream; //!< Rapidjson write stream
+ std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
+ rapidjson::Document itsDocument; //!< Rapidjson document
+ };
+
+ // ######################################################################
+ // JSONArchive prologue and epilogue functions
+ // ######################################################################
+
+ // ######################################################################
+ //! Prologue for NVPs for JSON archives
+ /*! NVPs do not start or finish nodes - they just set up the names */
+ template <class T> inline
+ void prologue( JSONOutputArchive &, NameValuePair<T> const & )
+ { }
+
+ //! Prologue for NVPs for JSON archives
+ template <class T> inline
+ void prologue( JSONInputArchive &, NameValuePair<T> const & )
+ { }
+
+ // ######################################################################
+ //! Epilogue for NVPs for JSON archives
+ /*! NVPs do not start or finish nodes - they just set up the names */
+ template <class T> inline
+ void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
+ { }
+
+ //! Epilogue for NVPs for JSON archives
+ /*! NVPs do not start or finish nodes - they just set up the names */
+ template <class T> inline
+ void epilogue( JSONInputArchive &, NameValuePair<T> const & )
+ { }
+
+ // ######################################################################
+ //! Prologue for SizeTags for JSON archives
+ /*! SizeTags are strictly ignored for JSON, they just indicate
+ that the current node should be made into an array */
+ template <class T> inline
+ void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
+ {
+ ar.makeArray();
+ }
+
+ //! Prologue for SizeTags for JSON archives
+ template <class T> inline
+ void prologue( JSONInputArchive &, SizeTag<T> const & )
+ { }
+
+ // ######################################################################
+ //! Epilogue for SizeTags for JSON archives
+ /*! SizeTags are strictly ignored for JSON */
+ template <class T> inline
+ void epilogue( JSONOutputArchive &, SizeTag<T> const & )
+ { }
+
+ //! Epilogue for SizeTags for JSON archives
+ template <class T> inline
+ void epilogue( JSONInputArchive &, SizeTag<T> const & )
+ { }
+
+ // ######################################################################
+ //! Prologue for all other types for JSON archives (except minimal types)
+ /*! Starts a new node, named either automatically or by some NVP,
+ that may be given data by the type about to be archived
+
+ Minimal types do not start or finish nodes */
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
+ prologue( JSONOutputArchive & ar, T const & )
+ {
+ ar.startNode();
+ }
+
+ //! Prologue for all other types for JSON archives
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
+ prologue( JSONInputArchive & ar, T const & )
+ {
+ ar.startNode();
+ }
+
+ // ######################################################################
+ //! Epilogue for all other types other for JSON archives (except minimal types
+ /*! Finishes the node created in the prologue
+
+ Minimal types do not start or finish nodes */
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
+ epilogue( JSONOutputArchive & ar, T const & )
+ {
+ ar.finishNode();
+ }
+
+ //! Epilogue for all other types other for JSON archives
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
+ epilogue( JSONInputArchive & ar, T const & )
+ {
+ ar.finishNode();
+ }
+
+ // ######################################################################
+ //! Prologue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ prologue( JSONOutputArchive & ar, T const & )
+ {
+ ar.writeName();
+ }
+
+ //! Prologue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ prologue( JSONInputArchive &, T const & )
+ { }
+
+ // ######################################################################
+ //! Epilogue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ epilogue( JSONOutputArchive &, T const & )
+ { }
+
+ //! Epilogue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ epilogue( JSONInputArchive &, T const & )
+ { }
+
+ // ######################################################################
+ //! Prologue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
+ {
+ ar.writeName();
+ }
+
+ //! Prologue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+ { }
+
+ // ######################################################################
+ //! Epilogue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+ { }
+
+ //! Epilogue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+ { }
+
+ // ######################################################################
+ // Common JSONArchive serialization functions
+ // ######################################################################
+
+ //! Serializing NVP types to JSON
+ template <class T> inline
+ void save( JSONOutputArchive & ar, NameValuePair<T> const & t )
+ {
+ ar.setNextName( t.name );
+ ar( t.value );
+ }
+
+ template <class T> inline
+ void load( JSONInputArchive & ar, NameValuePair<T> & t )
+ {
+ ar.setNextName( t.name );
+ ar( t.value );
+ }
+
+ //! Saving for arithmetic to JSON
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ save(JSONOutputArchive & ar, T const & t)
+ {
+ ar.saveValue( t );
+ }
+
+ //! Loading arithmetic from JSON
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ load(JSONInputArchive & ar, T & t)
+ {
+ ar.loadValue( t );
+ }
+
+ //! saving string to JSON
+ template<class CharT, class Traits, class Alloc> inline
+ void save(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
+ {
+ ar.saveValue( str );
+ }
+
+ //! loading string from JSON
+ template<class CharT, class Traits, class Alloc> inline
+ void load(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
+ {
+ ar.loadValue( str );
+ }
+
+ // ######################################################################
+ //! Saving SizeTags to JSON
+ template <class T> inline
+ void save( JSONOutputArchive &, SizeTag<T> const & )
+ {
+ // nothing to do here, we don't explicitly save the size
+ }
+
+ //! Loading SizeTags from JSON
+ template <class T> inline
+ void load( JSONInputArchive & ar, SizeTag<T> & st )
+ {
+ ar.loadSize( st.size );
+ }
+} // namespace cereal
+
+// register archives for polymorphic support
+CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
+CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
+
+#endif // CEREAL_ARCHIVES_JSON_HPP_
class OutOfProcClientWrapper : public IClientWrapper
{
public:
- OutOfProcClientWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+ OutOfProcClientWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
PlatformConfig cfg)
- : IClientWrapper(owner)
{}
virtual OCStackResult ListenForResource(const std::string& serviceUrl,
const std::string& uri,
const HeaderOptions& headerOptions, QualityOfService QoS){return OC_STACK_NOTIMPL;}
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
- OCDevAddr& addr, const boost::property_tree::ptree resourceNode)
- {
- return nullptr;
- }
-
virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host,
const std::string& resourceType, SubscribeCallback& presenceHandler)
{return OC_STACK_NOTIMPL;}
class OutOfProcServerWrapper : public IServerWrapper
{
public:
- OutOfProcServerWrapper(OC::OCPlatform_impl& owner, PlatformConfig cfg)
- : IServerWrapper(owner)
- {};
+ OutOfProcServerWrapper(PlatformConfig cfg)
+ {}
virtual OCStackResult registerResource(
OCResourceHandle& resourceHandle,
class ResourceInitException : public std::exception
{
public:
- ResourceInitException(bool missingUri, bool missingType, bool missingInterface, bool missingClientWrapper)
- : m_missingUri(missingUri), m_missingType(missingType), m_missingInterface(missingInterface), m_missingClientWrapper(missingClientWrapper)
+ ResourceInitException(
+ bool missingUri,
+ bool missingType,
+ bool missingInterface,
+ bool missingClientWrapper,
+ bool invalidPort,
+ bool invalidIp)
+ : m_missingUri(missingUri),
+ m_missingType(missingType),
+ m_missingInterface(missingInterface),
+ m_missingClientWrapper(missingClientWrapper),
+ m_invalidPort(invalidPort),
+ m_invalidIp(invalidIp)
{
}
+ bool isInvalidPort() const
+ {
+ return m_invalidPort;
+ }
+
+ bool isInvalidIp() const
+ {
+ return m_invalidIp;
+ }
+
bool isClientWrapperMissing() const
{
return m_missingClientWrapper;
ret += OC::InitException::MISSING_CLIENT_WRAPPER;
}
+ if(isInvalidPort())
+ {
+ ret += OC::InitException::INVALID_PORT;
+ }
+
+ if(isInvalidIp())
+ {
+ ret += OC::InitException::INVALID_IP;
+ }
+
return ret.c_str();
}
bool m_missingType;
bool m_missingInterface;
bool m_missingClientWrapper;
+ bool m_invalidPort;
+ bool m_invalidIp;
};
}
static const std::string GENERAL_FAULT = "General Fault";
static const std::string MALFORMED_STACK_RESPONSE = "Response from OC_STACK is malformed";
static const std::string UNKNOWN_ERROR = "Unknown Error";
-
+ static const std::string INVALID_REPRESENTATION = "Invalid Payload JSON";
+ static const std::string INVALID_JSON_TYPE = "Unrecognized JSON Type ";
+ static const std::string INVALID_JSON_NUMERIC = "Unrecognized JSON Numeric ";
+ static const std::string INVALID_JSON_ARRAY_DEPTH = "Max JSON Array Depth exceeded";
+ static const std::string INVALID_JSON_TYPE_TAG = "Invalid JSON Type Tag";
+ static const std::string INVALID_ATTRIBUTE = "Invalid Attribute: ";
}
namespace Error
public:
typedef std::shared_ptr<IWrapperFactory> Ptr;
- virtual IClientWrapper::Ptr CreateClientWrapper(OC::OCPlatform_impl& owner,
+ virtual IClientWrapper::Ptr CreateClientWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0;
- virtual IServerWrapper::Ptr CreateServerWrapper(OC::OCPlatform_impl& owner,
+ virtual IServerWrapper::Ptr CreateServerWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0;
virtual ~IWrapperFactory(){}
};
public:
WrapperFactory(){}
- virtual IClientWrapper::Ptr CreateClientWrapper(OC::OCPlatform_impl& owner,
+ virtual IClientWrapper::Ptr CreateClientWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
{
switch(cfg.serviceType)
{
case ServiceType::InProc:
- return std::make_shared<InProcClientWrapper>(owner, csdkLock, cfg);
+ return std::make_shared<InProcClientWrapper>(csdkLock, cfg);
break;
case ServiceType::OutOfProc:
- return std::make_shared<OutOfProcClientWrapper>(owner, csdkLock, cfg);
+ return std::make_shared<OutOfProcClientWrapper>(csdkLock, cfg);
break;
}
return nullptr;
}
- virtual IServerWrapper::Ptr CreateServerWrapper(OC::OCPlatform_impl& owner,
+ virtual IServerWrapper::Ptr CreateServerWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
{
switch(cfg.serviceType)
{
case ServiceType::InProc:
- return std::make_shared<InProcServerWrapper>(owner, csdkLock, cfg);
+ return std::make_shared<InProcServerWrapper>(csdkLock, cfg);
break;
case ServiceType::OutOfProc:
throw OC::OCException(OC::Exception::SVCTYPE_OUTOFPROC, OC_STACK_NOTIMPL);
PLATFORM := "linux"
endif
+DEPEND_DIR:= $(ROOT_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
OUT_DIR := $(ROOT_DIR)/$(BUILD)
OBJ_DIR := $(OUT_DIR)/obj
CXX_INC += -I./csdk/ocrandom/include
CXX_INC += -I./csdk/logger/include
CXX_INC += -I./csdk/libcoap
-
+CXX_INC += -I$(CEREAL_DIR)/include
# Force metatargets to build:
-all.PHONY: prep_dirs c_sdk oc_logger_target liboc.a examples
+all.PHONY: applyDepPatches prep_dirs c_sdk oc_logger_target liboc.a examples
-buildScript_all.PHONY: prep_dirs oc_logger_target liboc.a
+buildScript_all.PHONY: applyDepPatches prep_dirs oc_logger_target liboc.a
all: all.PHONY
buildScript_all: buildScript_all.PHONY
-prep_dirs:
+prep_dirs: deps
-mkdir -p $(OUT_DIR)
-mkdir -p $(OBJ_DIR)
+# used to fetch all dependencies
+deps:
+ -mkdir -p $(DEPEND_DIR)
+#cereal fetch
+ if [ ! -d "$(CEREAL_DIR)" ]; then\
+ cd $(DEPEND_DIR) && git clone https://github.com/USCiLab/cereal.git;\
+ cd $(CEREAL_DIR) && git checkout 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;\
+ fi
+
+applyDepPatches: deps
+#reset git to the 'base version', so we can apply our patch without issues
+ cd $(CEREAL_DIR) && git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;
+ cd $(CEREAL_DIR) && git apply $(ROOT_DIR)/patches/cereal_gcc46.patch
+
c_sdk:
cd csdk && $(MAKE) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)"
examples: liboc.a
cd examples && $(MAKE) apps "BUILD=$(BUILD)"
-liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o
- ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o
+liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o OCRepresentation.o
+ ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o $(OBJ_DIR)/OCRepresentation.o
OCPlatform_impl.o: src/OCPlatform_impl.cpp
$(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform_impl.cpp $(CXX_INC)
OCPlatform.o: src/OCPlatform.cpp
$(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform.cpp $(CXX_INC)
+OCRepresentation.o: src/OCRepresentation.cpp
+ $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCRepresentation.cpp $(CXX_INC)
+
OCResource.o: src/OCResource.cpp
$(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCResource.cpp $(CXX_INC)
--- /dev/null
+From 17300ee96e42f8848d27db6fc97f04de293662d8 Mon Sep 17 00:00:00 2001
+From: Erich Keane <erich.keane@intel.com>
+Date: Thu, 6 Nov 2014 14:37:00 -0800
+Subject: [PATCH] Get this to work on g++4.6.3
+
+---
+ include/cereal/cereal.hpp | 2 +-
+ include/cereal/details/helpers.hpp | 32 ++++++++--------
+ include/cereal/details/traits.hpp | 61 +++++++++++++++++-------------
+ include/cereal/external/rapidjson/reader.h | 13 ++-----
+ include/cereal/external/rapidjson/writer.h | 12 ++----
+ include/cereal/types/common.hpp | 19 +++++++---
+ include/cereal/types/memory.hpp | 10 ++---
+ 7 files changed, 77 insertions(+), 72 deletions(-)
+
+diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp
+index b2858af..a219729 100644
+--- a/include/cereal/cereal.hpp
++++ b/include/cereal/cereal.hpp
+@@ -856,7 +856,7 @@ namespace cereal
+ std::uint32_t version;
+
+ process( make_nvp<ArchiveType>("cereal_class_version", version) );
+- itsVersionedTypes.emplace_hint( lookupResult, hash, version );
++ itsVersionedTypes.insert( lookupResult, std::pair<std::size_t, std::uint32_t>(hash, version) );
+
+ return version;
+ }
+diff --git a/include/cereal/details/helpers.hpp b/include/cereal/details/helpers.hpp
+index e792d44..60e13c8 100644
+--- a/include/cereal/details/helpers.hpp
++++ b/include/cereal/details/helpers.hpp
+@@ -55,7 +55,7 @@ namespace cereal
+ /*! To ensure compatability between 32, 64, etc bit machines, we need to use
+ * a fixed size type instead of size_t, which may vary from machine to
+ * machine. */
+- using size_type = uint64_t;
++ typedef uint64_t size_type;
+
+ // forward decls
+ class BinaryOutputArchive;
+@@ -138,12 +138,12 @@ namespace cereal
+ // otherwise, we store a reference. If we were passed an array, don't
+ // decay the type - keep it as an array, and then proceed as normal
+ // with the RValue business
+- using DT = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
++ typedef typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
+ typename std::remove_cv<T>::type,
+- typename std::decay<T>::type>::type;
+- using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
++ typename std::decay<T>::type>::type DT;
++ typedef typename std::conditional<std::is_rvalue_reference<T>::value,
+ DT,
+- typename std::add_lvalue_reference<DT>::type>::type;
++ typename std::add_lvalue_reference<DT>::type>::type Type;
+ // prevent nested nvps
+ static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
+ "Cannot pair a name to a NameValuePair" );
+@@ -207,9 +207,9 @@ namespace cereal
+ {
+ //! Internally store the pointer as a void *, keeping const if created with
+ //! a const pointer
+- using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
++ typedef typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
+ const void *,
+- void *>::type;
++ void *>::type PT;
+
+ BinaryData( T && d, uint64_t s ) : data(d), size(s) {}
+
+@@ -248,10 +248,10 @@ namespace cereal
+ private:
+ // If we get passed an RValue, we'll just make a local copy if it here
+ // otherwise, we store a reference
+- using DT = typename std::decay<T>::type;
+- using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
++ typedef typename std::decay<T>::type DT;
++ typedef typename std::conditional<std::is_rvalue_reference<T>::value,
+ DT,
+- typename std::add_lvalue_reference<DT>::type>::type;
++ typename std::add_lvalue_reference<DT>::type>::type Type;
+
+ public:
+ SizeTag( T && sz ) : size(const_cast<Type>(sz)) {}
+@@ -283,17 +283,17 @@ namespace cereal
+ template <class Key, class Value>
+ struct MapItem
+ {
+- using DecayKey = typename std::decay<Key>::type;
+- using KeyType = typename std::conditional<
++ typedef typename std::decay<Key>::type DecayKey;
++ typedef typename std::conditional<
+ std::is_rvalue_reference<Key>::value,
+ DecayKey,
+- typename std::add_lvalue_reference<DecayKey>::type>::type;
++ typename std::add_lvalue_reference<DecayKey>::type>::type KeyType;
+
+- using DecayValue = typename std::decay<Value>::type;
+- using ValueType = typename std::conditional<
++ typedef typename std::decay<Value>::type DecayValue;
++ typedef typename std::conditional<
+ std::is_rvalue_reference<Value>::value,
+ DecayValue,
+- typename std::add_lvalue_reference<DecayValue>::type>::type;
++ typename std::add_lvalue_reference<DecayValue>::type>::type ValueType;
+
+ //! Construct a MapItem from a key and a value
+ /*! @internal */
+diff --git a/include/cereal/details/traits.hpp b/include/cereal/details/traits.hpp
+index 871886f..011054b 100644
+--- a/include/cereal/details/traits.hpp
++++ b/include/cereal/details/traits.hpp
+@@ -411,12 +411,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_member_save_minimal_type { using type = void; };
++ struct get_member_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_member_save_minimal_type<T, A, true>
+ {
+- using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>() ) );
++ typedef decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>() ) ) type;
+ };
+ } // end namespace detail
+
+@@ -428,7 +428,7 @@ namespace cereal
+ "cereal detected a non-const member save_minimal. "
+ "save_minimal member functions must always be const" );
+
+- using type = typename detail::get_member_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_member_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a member save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -473,12 +473,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_member_versioned_save_minimal_type { using type = void; };
++ struct get_member_versioned_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_member_versioned_save_minimal_type<T, A, true>
+ {
+- using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) );
++ typedef decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) ) type;
+ };
+ } // end namespace detail
+
+@@ -490,7 +490,7 @@ namespace cereal
+ "cereal detected a versioned non-const member save_minimal. "
+ "save_minimal member functions must always be const" );
+
+- using type = typename detail::get_member_versioned_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_member_versioned_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a versioned member save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -519,12 +519,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_non_member_save_minimal_type { using type = void; };
++ struct get_non_member_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_non_member_save_minimal_type <T, A, true>
+ {
+- using type = decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>() ) );
++ typedef decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>() ) ) type;
+ };
+ } // end namespace detail
+
+@@ -536,7 +536,7 @@ namespace cereal
+ "cereal detected a non-const type parameter in non-member save_minimal. "
+ "save_minimal non-member functions must always pass their types as const" );
+
+- using type = typename detail::get_non_member_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_non_member_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a non-member save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -565,12 +565,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_non_member_versioned_save_minimal_type { using type = void; };
++ struct get_non_member_versioned_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_non_member_versioned_save_minimal_type <T, A, true>
+ {
+- using type = decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) );
++ typedef decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) ) type;
+ };
+ } // end namespace detail
+
+@@ -582,7 +582,7 @@ namespace cereal
+ "cereal detected a non-const type parameter in versioned non-member save_minimal. "
+ "save_minimal non-member functions must always pass their types as const" );
+
+- using type = typename detail::get_non_member_versioned_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_non_member_versioned_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a non-member versioned save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -608,7 +608,7 @@ namespace cereal
+ template <class Source>
+ struct NoConvertConstRef : NoConvertBase
+ {
+- using type = Source; //!< Used to get underlying type easily
++ typedef Source type; //!< Used to get underlying type easily
+
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
+ operator Dest () = delete;
+@@ -626,7 +626,7 @@ namespace cereal
+ template <class Source>
+ struct NoConvertRef : NoConvertBase
+ {
+- using type = Source; //!< Used to get underlying type easily
++ typedef Source type; //!< Used to get underlying type easily
+
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
+ operator Dest () = delete;
+@@ -698,7 +698,7 @@ namespace cereal
+ "cereal detected member load_minimal but no valid member save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_member_save_minimal_type<T, A, true>::type;
++ typedef typename detail::get_member_save_minimal_type<T, A, true>::type SaveType;
+ const static bool value = has_member_load_minimal_impl<T, A>::value;
+ const static bool valid = has_member_load_minimal_type_impl<T, A, SaveType>::value;
+
+@@ -759,7 +759,7 @@ namespace cereal
+ "cereal detected member versioned load_minimal but no valid member versioned save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_member_versioned_save_minimal_type<T, A, true>::type;
++ typedef typename detail::get_member_versioned_save_minimal_type<T, A, true>::type SaveType;
+ const static bool value = has_member_versioned_load_minimal_impl<T, A>::value;
+ const static bool valid = has_member_versioned_load_minimal_type_impl<T, A, SaveType>::value;
+
+@@ -814,8 +814,8 @@ namespace cereal
+ "cereal detected non-member load_minimal but no valid non-member save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_non_member_save_minimal_type<T, A, true>::type;
+- using check = has_non_member_load_minimal_impl<T, A, SaveType>;
++ typedef typename detail::get_non_member_save_minimal_type<T, A, true>::type SaveType;
++ typedef has_non_member_load_minimal_impl<T, A, SaveType> check;
+ static const bool value = check::exists;
+
+ static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member load_minimal and save_minimal functions. "
+@@ -866,8 +866,8 @@ namespace cereal
+ "cereal detected non-member versioned load_minimal but no valid non-member versioned save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_non_member_versioned_save_minimal_type<T, A, true>::type;
+- using check = has_non_member_versioned_load_minimal_impl<T, A, SaveType>;
++ typedef typename detail::get_non_member_versioned_save_minimal_type<T, A, true>::type SaveType;
++ typedef has_non_member_versioned_load_minimal_impl<T, A, SaveType> check;;
+ static const bool value = check::exists;
+
+ static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member versioned load_minimal and save_minimal functions. "
+@@ -1182,9 +1182,16 @@ namespace cereal
+ };
+ }
+
++ // works around the lack of decltype inheritance in GCC 4.6
++ template<class T>
++ struct shared_wrapper
++ {
++ typedef decltype(detail::shared_from_this_wrapper::check(std::declval<T>())) type;
++
++ };
+ //! Determine if T or any base class of T has inherited from std::enable_shared_from_this
+ template<class T>
+- struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>()))
++ struct has_shared_from_this : shared_wrapper<T>::type
+ { };
+
+ //! Get the type of the base class of T which inherited from std::enable_shared_from_this
+@@ -1192,10 +1199,10 @@ namespace cereal
+ struct get_shared_from_this_base
+ {
+ private:
+- using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
++ typedef decltype(detail::shared_from_this_wrapper::get(std::declval<T>())) PtrType;
+ public:
+ //! The type of the base of T that inherited from std::enable_shared_from_this
+- using type = typename std::decay<typename PtrType::element_type>::type;
++ typedef typename std::decay<typename PtrType::element_type>::type type;
+ };
+
+ // ######################################################################
+@@ -1209,14 +1216,14 @@ namespace cereal
+ template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
+ struct strip_minimal
+ {
+- using type = T;
++ typedef T type;
+ };
+
+ //! Specialization for types wrapped in a NoConvert
+ template <class T>
+ struct strip_minimal<T, true>
+ {
+- using type = typename T::type;
++ typedef typename T::type type;
+ };
+ } // namespace traits
+
+@@ -1232,10 +1239,12 @@ namespace cereal
+ { return nullptr; }
+ };
+
++ template<class T>
++ struct is_default_constructible : std::is_constructible<T>{};
+ template <class T, class A>
+ struct Construct<T, A, false, false>
+ {
+- static_assert( std::is_default_constructible<T>::value,
++ static_assert( is_default_constructible<T>::value,
+ "Trying to serialize a an object with no default constructor. \n\n "
+ "Types must either be default constructible or define either a member or non member Construct function. \n "
+ "Construct functions generally have the signature: \n\n "
+diff --git a/include/cereal/external/rapidjson/reader.h b/include/cereal/external/rapidjson/reader.h
+index 7790907..3ee838c 100644
+--- a/include/cereal/external/rapidjson/reader.h
++++ b/include/cereal/external/rapidjson/reader.h
+@@ -402,20 +402,13 @@ private:
+ }
+
+ // cereal Temporary until constexpr support is added in RTM
+-#ifdef _MSC_VER
++//#ifdef _MSC_VER
+ template <class Ch>
+ bool characterOk( Ch c )
+ {
+ return c < 256;
+ }
+-
+- template <>
+- bool characterOk<char>( Ch )
+- {
+- return true;
+- }
+-
+-#else
++/*#else
+ // As part of a fix for GCC 4.7
+ template <class T>
+ static constexpr int to_int( T t ){ return t; }
+@@ -432,7 +425,7 @@ private:
+ characterOk(Ch c)
+ { return c < 256; }
+ #endif
+-
++*/
+ // Parse string, handling the prefix and suffix double quotes and escaping.
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseString(Stream& stream, Handler& handler) {
+diff --git a/include/cereal/external/rapidjson/writer.h b/include/cereal/external/rapidjson/writer.h
+index 0f87255..e02c27a 100644
+--- a/include/cereal/external/rapidjson/writer.h
++++ b/include/cereal/external/rapidjson/writer.h
+@@ -177,20 +177,14 @@ protected:
+ }
+
+ // cereal Temporary until constexpr support is added in RTM
+-#ifdef _MSC_VER
++//#ifdef _MSC_VER
+ template <class Ch>
+ bool characterOk( Ch c )
+ {
+ return c < 256;
+ }
+
+- template <>
+- bool characterOk<char>( Ch )
+- {
+- return true;
+- }
+-
+-#else
++/*#else
+ // As part of a fix for GCC 4.7
+ template <class T>
+ static constexpr int to_int( T t ){ return t; }
+@@ -206,7 +200,7 @@ protected:
+ typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type
+ characterOk(Ch c)
+ { return c < 256; }
+-#endif
++#endif*/
+
+ //! \todo Optimization with custom double-to-string converter.
+ void WriteDouble(double d) {
+diff --git a/include/cereal/types/common.hpp b/include/cereal/types/common.hpp
+index abb8bfd..5c014cd 100644
+--- a/include/cereal/types/common.hpp
++++ b/include/cereal/types/common.hpp
+@@ -55,6 +55,15 @@ namespace cereal
+
+ namespace
+ {
++ template<class en>
++ struct underlying_type
++ {
++ typedef typename std::conditional<
++ en(-1)<en(0),
++ typename std::make_signed<en>::type,
++ typename std::make_unsigned<en>::type
++ > ::type type;
++ };
+ //! Gets the underlying type of an enum
+ /*! @internal */
+ template <class T, bool IsEnum>
+@@ -64,7 +73,7 @@ namespace cereal
+ /*! Specialization for when we actually have an enum
+ @internal */
+ template <class T>
+- struct enum_underlying_type<T, true> { using type = typename std::underlying_type<T>::type; };
++ struct enum_underlying_type<T, true> { typedef typename underlying_type<T>::type type; };
+ } // anon namespace
+
+ //! Checks if a type is an enum
+@@ -78,13 +87,13 @@ namespace cereal
+ class is_enum
+ {
+ private:
+- using DecayedT = typename std::decay<T>::type;
+- using StrippedT = typename ::cereal::traits::strip_minimal<DecayedT>::type;
++ typedef typename std::decay<T>::type DecayedT;
++ typedef typename ::cereal::traits::strip_minimal<DecayedT>::type StrippedT;
+
+ public:
+ static const bool value = std::is_enum<StrippedT>::value;
+- using type = StrippedT;
+- using base_type = typename enum_underlying_type<StrippedT, value>::type;
++ typedef StrippedT type;
++ typedef typename enum_underlying_type<StrippedT, value>::type base_type;
+ };
+ }
+
+diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp
+index bf56c92..d2357ff 100644
+--- a/include/cereal/types/memory.hpp
++++ b/include/cereal/types/memory.hpp
+@@ -115,9 +115,9 @@ namespace cereal
+ class EnableSharedStateHelper
+ {
+ // typedefs for parent type and storage type
+- using BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type;
+- using ParentType = std::enable_shared_from_this<BaseType>;
+- using StorageType = typename std::aligned_storage<sizeof(ParentType)>::type;
++ typedef typename ::cereal::traits::get_shared_from_this_base<T>::type BaseType;
++ typedef std::enable_shared_from_this<BaseType> ParentType;
++ typedef typename std::aligned_storage<sizeof(ParentType)>::type StorageType;
+
+ public:
+ //! Saves the state of some type inheriting from enable_shared_from_this
+@@ -257,7 +257,7 @@ namespace cereal
+ {
+ // Storage type for the pointer - since we can't default construct this type,
+ // we'll allocate it using std::aligned_storage and use a custom deleter
+- using ST = typename std::aligned_storage<sizeof(T)>::type;
++ typedef typename std::aligned_storage<sizeof(T)>::type ST;
+
+ // Valid flag - set to true once construction finishes
+ // This prevents us from calling the destructor on
+@@ -345,7 +345,7 @@ namespace cereal
+ {
+ // Storage type for the pointer - since we can't default construct this type,
+ // we'll allocate it using std::aligned_storage
+- using ST = typename std::aligned_storage<sizeof(T)>::type;
++ typedef typename std::aligned_storage<sizeof(T)>::type ST;
+
+ // Allocate storage - note the ST type so that deleter is correct if
+ // an exception is thrown before we are initialized
+--
+1.9.3
+
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include <new>
-
#include "InProcClientWrapper.h"
#include "ocstack.h"
#include "OCPlatform.h"
#include "OCResource.h"
-
+#include <OCSerialization.h>
using namespace std;
namespace OC
{
- InProcClientWrapper::InProcClientWrapper(OC::OCPlatform_impl& owner,
+ InProcClientWrapper::InProcClientWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
- : IClientWrapper(owner),
- m_threadRun(false), m_csdkLock(csdkLock),
- m_owner(owner),
+ : m_threadRun(false), m_csdkLock(csdkLock),
m_cfg { cfg }
{
// if the config type is server, we ought to never get called. If the config type
}
}
- std::string InProcClientWrapper::convertOCAddrToString(OCDevAddr& addr,
- OCSecureType type, const std::string &portStr)
- {
- // TODO: we currently assume this is a IPV4 address, need to figure out the actual value
-
- uint8_t a, b, c, d;
- uint16_t port;
-
- if(OCDevAddrToIPv4Addr(&addr, &a, &b, &c, &d) ==0 && OCDevAddrToPort(&addr, &port)==0)
- {
- ostringstream os;
- if(type == OCSecureType::IPV4)
- {
- os << "coap://" << static_cast<int>(a) << '.' <<
- static_cast<int>(b) << '.' << static_cast<int>(c) <<
- '.' << static_cast<int>(d) << ':' <<static_cast<int>(port);
- }
- else if(type == OCSecureType::IPV4Secure)
- {
- os << "coaps://" << static_cast<int>(a) <<'.' <<
- static_cast<int>(b) <<'.' << static_cast<int>(c) <<
- '.' << static_cast<int>(d) << ':' << portStr;
- }
- return os.str();
- }
- else
- {
- return OC::Error::INVALID_IP;
- }
- }
-
- struct ListenContext
- {
- FindCallback callback;
- IClientWrapper::Ptr clientWrapper;
- };
-
-
- std::shared_ptr<OCResource> InProcClientWrapper::parseOCResource(
- IClientWrapper::Ptr clientWrapper, OCDevAddr& addr,
- const boost::property_tree::ptree resourceNode)
- {
- std::string uri = resourceNode.get<std::string>(OC::Key::URIKEY, "");
- bool obs = resourceNode.get<int>(OC::Key::OBSERVABLEKEY,0) == 1;
- std::vector<std::string> rTs;
- std::vector<std::string> ifaces;
-
- boost::property_tree::ptree properties =
- resourceNode.get_child(OC::Key::PROPERTYKEY, boost::property_tree::ptree());
-
- boost::property_tree::ptree rT =
- properties.get_child(OC::Key::RESOURCETYPESKEY, boost::property_tree::ptree());
- for(auto itr : rT)
- {
- rTs.push_back(itr.second.data());
- }
- bool secure = properties.get<int>(OC::Key::SECUREKEY,0) == 1;
-
- boost::property_tree::ptree iF =
- properties.get_child(OC::Key::INTERFACESKEY, boost::property_tree::ptree());
- for(auto itr : iF)
- {
- ifaces.push_back(itr.second.data());
- }
-
- std::string host;
- if(secure)
- {
- string port = properties.get<string>(OC::Key::PORTKEY,"");
- host= convertOCAddrToString(addr, OCSecureType::IPV4Secure, port);
- }
- else
- {
- host= convertOCAddrToString(addr, OCSecureType::IPV4);
- }
-
- return std::shared_ptr<OCResource>(
- new OCResource(clientWrapper, host, uri, obs, rTs, ifaces));
- }
-
OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- ListenContext* context = static_cast<ListenContext*>(ctx);
+ ClientCallbackContext::ListenContext* context =
+ static_cast<ClientCallbackContext::ListenContext*>(ctx);
if(clientResponse->result != OC_STACK_OK)
{
std::stringstream requestStream;
requestStream << clientResponse->resJSONPayload;
- boost::property_tree::ptree root;
-
try
{
- boost::property_tree::read_json(requestStream, root);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
- {
- oclog() << "listenCallback(): read_json() failed: " << e.what()
- << std::flush;
+ ListenOCContainer container(context->clientWrapper, *clientResponse->addr,
+ requestStream);
- return OC_STACK_KEEP_TRANSACTION;
- }
-
- boost::property_tree::ptree payload =
- root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
+ // loop to ensure valid construction of all resources
+ for(auto resource : container.Resources())
+ {
+ std::thread exec(context->callback, resource);
+ exec.detach();
+ }
- for(auto payloadItr : payload)
+ }
+ catch(const std::exception& e)
{
- try
- {
- std::shared_ptr<OCResource> resource =
- context->clientWrapper->parseOCResource(context->clientWrapper,
- *clientResponse->addr,
- payloadItr.second);
-
- // Note: the call to detach allows the underlying thread to continue until
- // completion and allows us to destroy the exec object. This is apparently NOT
- // a memory leak, as the thread will apparently take care of itself.
- // Additionally, the only parameter here is a shared ptr, so OCResource will be
- // disposed of properly upon completion of the callback handler.
- std::thread exec(context->callback,resource);
- exec.detach();
- }
- catch(ResourceInitException& e)
- {
- oclog() << "listenCallback(): failed to create resource: " << e.what()
- << std::flush;
- }
+ oclog() << "listenCallback failed to parse a malformed message: "
+ << e.what()
+ << std::endl <<std::endl
+ << clientResponse->result
+ << std::flush;
+ return OC_STACK_KEEP_TRANSACTION;
}
return OC_STACK_KEEP_TRANSACTION;
+
}
OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl,
OCCallbackData cbdata = {0};
- ListenContext* context = new ListenContext();
+ ClientCallbackContext::ListenContext* context = new ClientCallbackContext::ListenContext();
context->callback = callback;
context->clientWrapper = shared_from_this();
cbdata.context = static_cast<void*>(context);
cbdata.cb = listenCallback;
- cbdata.cd = [](void* c){delete static_cast<ListenContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ListenContext*>(c);};
auto cLock = m_csdkLock.lock();
if(cLock)
return result;
}
- struct GetContext
- {
- GetCallback callback;
- };
-
- struct SetContext
- {
- PutCallback callback;
- };
-
-
OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
{
- std::stringstream requestStream;
- requestStream<<clientResponse->resJSONPayload;
- if(strlen((char*)clientResponse->resJSONPayload) == 0)
+ if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0')
{
return OCRepresentation();
}
- boost::property_tree::ptree root;
- try
- {
- boost::property_tree::read_json(requestStream, root);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
+ MessageContainer oc;
+ oc.setJSONRepresentation(clientResponse->resJSONPayload);
+
+ std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
+ if(it == oc.representations().end())
{
return OCRepresentation();
}
- boost::property_tree::ptree payload = root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
- OCRepresentation root_resource;
- std::vector<OCRepresentation> children;
- bool isRoot = true;
- for ( auto payloadItr : payload)
- {
- OCRepresentation child;
- try
- {
- auto resourceNode = payloadItr.second;
- std::string uri = resourceNode.get<std::string>(OC::Key::URIKEY, "");
-
- if (isRoot)
- {
- root_resource.setUri(uri);
- }
- else
- {
- child.setUri(uri);
- }
-
- if( resourceNode.count(OC::Key::PROPERTYKEY) != 0 )
- {
- std::vector<std::string> rTs;
- std::vector<std::string> ifaces;
- boost::property_tree::ptree properties =
- resourceNode.get_child(OC::Key::PROPERTYKEY, boost::property_tree::ptree());
-
- boost::property_tree::ptree rT =
- properties.get_child(OC::Key::RESOURCETYPESKEY,
- boost::property_tree::ptree());
- for(auto itr : rT)
- {
- rTs.push_back(itr.second.data());
- }
-
- boost::property_tree::ptree iF =
- properties.get_child(OC::Key::INTERFACESKEY, boost::property_tree::ptree());
- for(auto itr : iF)
- {
- ifaces.push_back(itr.second.data());
- }
- if (isRoot)
- {
- root_resource.setResourceInterfaces(ifaces);
- root_resource.setResourceTypes(rTs);
- }
- else
- {
- child.setResourceInterfaces(ifaces);
- child.setResourceTypes(rTs);
- }
- }
-
- if( resourceNode.count(OC::Key::REPKEY) != 0 )
- {
- boost::property_tree::ptree rep =
- resourceNode.get_child(OC::Key::REPKEY, boost::property_tree::ptree());
- AttributeMap attrs;
- for( auto item : rep)
- {
- std::string name = item.first.data();
- std::string value = item.second.data();
- attrs[name] = value;
- }
- if (isRoot)
- {
- root_resource.setAttributeMap(attrs);
- }
- else
- {
- child.setAttributeMap(attrs);
- }
- }
-
- if (!isRoot)
- children.push_back(child);
- }
- catch (...)
- {
- // TODO
- }
- isRoot = false;
- }
+ // first one is considered the root, everything else is considered a child of this one.
+ OCRepresentation root = *it;
+ ++it;
- root_resource.setChildren(children);
+ std::for_each(it, oc.representations().end(),
+ [&root](const OCRepresentation& repItr)
+ {root.addChild(repItr);});
+ return root;
- return root_resource;
}
void parseServerHeaderOptions(OCClientResponse* clientResponse,
OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- GetContext* context = static_cast<GetContext*>(ctx);
+ ClientCallbackContext::GetContext* context =
+ static_cast<ClientCallbackContext::GetContext*>(ctx);
OCRepresentation rep;
HeaderOptions serverHeaderOptions;
OCStackResult result;
OCCallbackData cbdata = {0};
- GetContext* ctx = new GetContext();
+ ClientCallbackContext::GetContext* ctx = new ClientCallbackContext::GetContext();
ctx->callback = callback;
cbdata.context = static_cast<void*>(ctx);
cbdata.cb = &getResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<GetContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::GetContext*>(c);};
auto cLock = m_csdkLock.lock();
OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- SetContext* context = static_cast<SetContext*>(ctx);
+ ClientCallbackContext::SetContext* context =
+ static_cast<ClientCallbackContext::SetContext*>(ctx);
OCRepresentation attrs;
HeaderOptions serverHeaderOptions;
std::string InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
{
- ostringstream payload;
- // TODO need to change the format to "{"oc":[]}"
- payload << "{\"oc\":";
-
- payload << rep.getJSONRepresentation();
-
- payload << "}";
- return payload.str();
+ MessageContainer ocInfo;
+ ocInfo.addRepresentation(rep);
+ return ocInfo.getJSONRepresentation(OCInfoFormat::IncludeOC);
}
OCStackResult InProcClientWrapper::PostResourceRepresentation(const std::string& host,
OCStackResult result;
OCCallbackData cbdata = {0};
- SetContext* ctx = new SetContext();
+ ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
ctx->callback = callback;
cbdata.cb = &setResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
cbdata.context = static_cast<void*>(ctx);
// TODO: in the future the cstack should be combining these two strings!
OCStackResult result;
OCCallbackData cbdata = {0};
- SetContext* ctx = new SetContext();
+ ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
ctx->callback = callback;
cbdata.cb = &setResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
cbdata.context = static_cast<void*>(ctx);
// TODO: in the future the cstack should be combining these two strings!
return result;
}
- struct DeleteContext
- {
- DeleteCallback callback;
- };
-
OCStackApplicationResult deleteResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- DeleteContext* context = static_cast<DeleteContext*>(ctx);
- OCRepresentation attrs;
+ ClientCallbackContext::DeleteContext* context =
+ static_cast<ClientCallbackContext::DeleteContext*>(ctx);
HeaderOptions serverHeaderOptions;
if(clientResponse->result == OC_STACK_OK)
OCStackResult result;
OCCallbackData cbdata = {0};
- DeleteContext* ctx = new DeleteContext();
+ ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext();
ctx->callback = callback;
cbdata.cb = &deleteResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<DeleteContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::DeleteContext*>(c);};
cbdata.context = static_cast<void*>(ctx);
ostringstream os;
return result;
}
- struct ObserveContext
- {
- ObserveCallback callback;
- };
-
OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- ObserveContext* context = static_cast<ObserveContext*>(ctx);
+ ClientCallbackContext::ObserveContext* context =
+ static_cast<ClientCallbackContext::ObserveContext*>(ctx);
OCRepresentation attrs;
HeaderOptions serverHeaderOptions;
uint32_t sequenceNumber = clientResponse->sequenceNumber;
OCStackResult result;
OCCallbackData cbdata = {0};
- ObserveContext* ctx = new ObserveContext();
+ ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext();
ctx->callback = callback;
cbdata.context = static_cast<void*>(ctx);
cbdata.cb = &observeResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<ObserveContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ObserveContext*>(c);};
OCMethod method;
if (observeType == ObserveType::Observe)
OCHeaderOption options[MAX_HEADER_OPTIONS];
assembleHeaderOptions(options, headerOptions);
- result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options, headerOptions.size());
+ result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options,
+ headerOptions.size());
}
else
{
return result;
}
- struct SubscribePresenceContext
- {
- SubscribeCallback callback;
- };
-
OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- SubscribePresenceContext* context = static_cast<SubscribePresenceContext*>(ctx);
+ ClientCallbackContext::SubscribePresenceContext* context =
+ static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
std::thread exec(context->callback, clientResponse->result, clientResponse->sequenceNumber);
exec.detach();
{
OCCallbackData cbdata = {0};
- SubscribePresenceContext* ctx = new SubscribePresenceContext();
+ ClientCallbackContext::SubscribePresenceContext* ctx =
+ new ClientCallbackContext::SubscribePresenceContext();
ctx->callback = presenceHandler;
cbdata.cb = &subscribePresenceCallback;
cbdata.context = static_cast<void*>(ctx);
- cbdata.cd = [](void* c){delete static_cast<SubscribePresenceContext*>(c);};
+ cbdata.cd = [](void* c)
+ {delete static_cast<ClientCallbackContext::SubscribePresenceContext*>(c);};
auto cLock = m_csdkLock.lock();
std::ostringstream os;
namespace OC
{
- InProcServerWrapper::InProcServerWrapper(OC::OCPlatform_impl& owner,
+ InProcServerWrapper::InProcServerWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
- : IServerWrapper(owner),
- m_csdkLock(csdkLock)
+ : m_csdkLock(csdkLock)
{
OCMode initType;
switch(config.mode)
{
case ModeType::Server:
- m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config);
+ m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
break;
case ModeType::Client:
- m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config);
+ m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
break;
case ModeType::Both:
- m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config);
- m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config);
+ m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
+ m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
break;
}
}
return result_guard(OC_STACK_ERROR);
}
- std::string payload(pResponse->getPayload());
+ std::string payload(pResponse->getResourceRepresentation().getJSONRepresentation());
return result_guard(
OCNotifyListOfObservers(resourceHandle,
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCRepresentation.cpp
+
+/// @brief This file contains the implementation of classes and its members
+/// related to OCRepresentation
+
+#include <cereal/cereal.hpp>
+#include <cereal/types/map.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/types/utility.hpp>
+#include <algorithm>
+#include <OCRepresentation.h>
+namespace OC
+{
+ typedef cereal::JSONOutputArchive OutputArchiveType;
+ typedef cereal::JSONInputArchive InputArchiveType;
+
+ void MessageContainer::setJSONRepresentation(const std::string& payload)
+ {
+ std::stringstream os(payload);
+ {
+ InputArchiveType archive(os);
+ archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+ }
+ }
+
+ void MessageContainer::setJSONRepresentation(const unsigned char* payload)
+ {
+ setJSONRepresentation(std::string(reinterpret_cast<const char*>(payload)));
+ }
+
+ std::string MessageContainer::getJSONRepresentation(OCInfoFormat f) const
+ {
+ std::stringstream os;
+
+ // note: the block is required because cereal closes the JSON string
+ // upon destruction, so the archive needs to be destroyed before accessing
+ // the data
+ {
+ if(f == OCInfoFormat::IncludeOC)
+ {
+ OutputArchiveType archive(os);
+ archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+ }
+ else if(f== OCInfoFormat::ExcludeOC)
+ {
+ bool firstPrinted = false;
+ for(std::vector<OCRepresentation>::size_type i = 0; i< m_reps.size();++i)
+ {
+ if(!m_reps[i].empty())
+ {
+ if(firstPrinted)
+ {
+ os<<',';
+ }
+ firstPrinted=true;
+ os << m_reps[i].getJSONRepresentation();
+ }
+ }
+ }
+ }
+ return os.str();
+ }
+
+ const std::vector<OCRepresentation>& MessageContainer::representations() const
+ {
+ return m_reps;
+ }
+
+ void MessageContainer::addRepresentation(const OCRepresentation& rep)
+ {
+ m_reps.push_back(rep);
+ }
+}
+
+namespace OC
+{
+ OCRepresentation::OCRepresentation()
+ :m_interfaceType(InterfaceType::None)
+ { }
+ std::string OCRepresentation::getJSONRepresentation() const
+ {
+ std::stringstream os;
+
+ // note: the block is required because cereal closes the JSON string
+ // upon destruction, so the archive needs to be destroyed before accessing
+ // the data
+ {
+ OutputArchiveType archive (os);
+ save(archive);
+ }
+
+ return os.str();
+ }
+
+ void OCRepresentation::addChild(const OCRepresentation& rep)
+ {
+ m_children.push_back(rep);
+ }
+
+ void OCRepresentation::clearChildren()
+ {
+ m_children.clear();
+ }
+
+ const std::vector<OCRepresentation>& OCRepresentation::getChildren() const
+ {
+ return m_children;
+ }
+
+ void OCRepresentation::setUri(const std::string& uri)
+ {
+ m_uri = uri;
+ }
+
+ std::string OCRepresentation::getUri() const
+ {
+ return m_uri;
+ }
+
+ const std::vector<std::string>& OCRepresentation::getResourceTypes() const
+ {
+ return m_resourceTypes;
+ }
+
+ void OCRepresentation::setResourceTypes(const std::vector<std::string>& resourceTypes)
+ {
+ m_resourceTypes = resourceTypes;
+ }
+
+ const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
+ {
+ return m_interfaces;
+ }
+
+ void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
+ {
+ m_interfaces = resourceInterfaces;
+ }
+
+ bool OCRepresentation::hasAttribute(const std::string& str) const
+ {
+ return m_values.find(str) != m_values.end();
+ }
+
+ bool OCRepresentation::empty() const
+ {
+ // This logic is meant to determine whether based on the JSON serialization rules
+ // if this object will result in empty JSON. URI is only serialized if there is valid
+ // data, ResourceType and Interfaces are only serialized if we are a nothing, a
+ // child of a default or link item.
+ // Our values array is only printed in the if we are the child of a Batch resource,
+ // the parent in a 'default' situation, or not in a child/parent relationship.
+ if(!m_uri.empty())
+ {
+ return false;
+ }
+ else if ((m_interfaceType == InterfaceType::None
+ || m_interfaceType==InterfaceType::DefaultChild
+ || m_interfaceType==InterfaceType::LinkChild)
+ && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+ {
+ return false;
+ }
+ else if((m_interfaceType == InterfaceType::None
+ || m_interfaceType == InterfaceType::BatchChild
+ || m_interfaceType == InterfaceType::DefaultParent)
+ && m_values.size()>0)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ int OCRepresentation::numberOfAttributes() const
+ {
+ return m_values.size();
+ }
+
+ bool OCRepresentation::erase(const std::string& str)
+ {
+ return m_values.erase(str);
+ }
+
+ void OCRepresentation::setNULL(const std::string& str)
+ {
+ m_values[str] = OC::NullType();
+ }
+
+ bool OCRepresentation::isNULL(const std::string& str) const
+ {
+ auto x = m_values.find(str);
+
+ if(m_values.end() != x)
+ {
+ return x->second.which() == AttributeValueNullIndex;
+ }
+ else
+ {
+ throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str);
+ }
+ }
+}
+
+// note: the below is used to load an AttributeValue map out of JSON
+namespace OC
+{
+ namespace detail
+ {
+ enum class typeTag:uint8_t
+ {
+ NOTHING = 0,
+ _string,
+ _int,
+ _double,
+ _bool,
+ _representation
+ };
+
+ typedef rapidjson::Document::GenericValue GenericValue;
+
+ AttributeValue parseAttributeValue(const GenericValue& v);
+ AttributeValue parseAttributeValue(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t);
+ AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t);
+ AttributeValue parseAttributeValueArray(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t);
+ AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t);
+
+ AttributeValue parseAttributeValue(const GenericValue& v)
+ {
+ // base entrance, start everything at '0'
+ unsigned int max_depth {0};
+ typeTag t {typeTag::NOTHING};
+
+ return parseAttributeValue(v, 0, max_depth, t);
+ }
+
+ AttributeValue parseAttributeValue(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+ {
+ if(v.IsObject())
+ {
+ return parseAttributeValueObject(v, t);
+ }
+ else if(v.IsArray())
+ {
+ return parseAttributeValueArray(v, curLevel + 1, maxDepth, t);
+ }
+ else
+ {
+ return parseAttributeValuePrimitive(v,t);
+ }
+ }
+
+ AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t)
+ {
+ typedef rapidjson::Value::ConstMemberIterator CMI;
+ t = typeTag::_representation;
+ OC::OCRepresentation rep;
+
+ for(CMI itr = v.MemberBegin(); itr!= v.MemberEnd(); ++itr)
+ {
+ std::string keyName = itr->name.GetString();
+
+ if(keyName == OC::Key::URIKEY)
+ {
+ rep.setUri(boost::get<std::string>(parseAttributeValue(itr->value)));
+ }
+ else if (keyName == OC::Key::PROPERTYKEY)
+ {
+ for(CMI itr2 = itr->value.MemberBegin();
+ itr->value.MemberEnd()!=itr2;
+ ++itr2)
+ {
+ if(keyName == OC::Key::RESOURCETYPESKEY)
+ {
+ rep.setResourceTypes(
+ boost::get<std::vector<std::string>>(
+ parseAttributeValue(itr->value)));
+ }
+ else if(keyName == OC::Key::PROPERTYKEY)
+ {
+ rep.setResourceInterfaces(
+ boost::get<std::vector<std::string>>(
+ parseAttributeValue(itr->value)));
+ }
+ }
+ }
+ else if (keyName == OC::Key::REPKEY)
+ {
+ for(CMI itr2 = itr->value.MemberBegin();
+ itr->value.MemberEnd()!=itr2;
+ ++itr2)
+ {
+ rep.setValue(itr2->name.GetString(),
+ parseAttributeValue(itr2->value));
+ }
+ }
+ }
+
+ return rep;
+ }
+
+ AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t)
+ {
+ if(v.IsString())
+ {
+ t = typeTag::_string;
+ return std::string(v.GetString());
+ }
+ else if (v.IsNumber())
+ {
+ if(v.IsDouble())
+ {
+ t = typeTag::_double;
+ return double(v.GetDouble());
+ }
+ else if (v.IsInt())
+ {
+ t = typeTag::_int;
+ return int(v.GetInt());
+ }
+ else
+ {
+ throw OC::OCException(OC::Exception::INVALID_JSON_NUMERIC
+ + std::to_string(v.GetType()));
+ }
+ }
+ else if(v.IsBool_())
+ {
+ t=typeTag::_bool;
+ return bool(v.GetBool_());
+ }
+ else if(v.IsNull_())
+ {
+ return OC::NullType();
+ }
+ else
+ {
+ throw OC::OCException(OC::Exception::INVALID_JSON_TYPE
+ + std::to_string(v.GetType()));
+ }
+ }
+
+ std::vector<AttributeValue> gatherArrayContents(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+ {
+ std::vector<AttributeValue> out;
+
+ std::transform(v.Begin(), v.End(), back_inserter(out),
+ [curLevel, &maxDepth, &t](const GenericValue& x)
+ {
+ return parseAttributeValue(x, curLevel, maxDepth, t);
+ });
+ return out;
+ }
+
+ template<class OutT>
+ struct valueToConcrete
+ {
+ OutT operator()(const AttributeValue& v)
+ {
+ return boost::get<OutT>(v);
+ }
+
+ };
+
+ template <class OutSeqT>
+ OutSeqT valuesToConcreteVectors(const std::vector<AttributeValue>& vs)
+ {
+ OutSeqT ret;
+
+ std::transform(begin(vs),end(vs), back_inserter(ret),
+ valueToConcrete<typename OutSeqT::value_type>());
+ return ret;
+ }
+
+ template<class valueType>
+ AttributeValue remapArrayDepth(const unsigned int curLevel,
+ const std::vector<OC::AttributeValue>& vs)
+ {
+ switch(curLevel)
+ {
+ default:
+ throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH);
+ break;
+ case 1:
+ return valuesToConcreteVectors<std::vector<valueType>>(vs);
+ break;
+ case 2:
+ return valuesToConcreteVectors<std::vector<std::vector<valueType>>>(vs);
+ break;
+ case 3:
+ return valuesToConcreteVectors
+ <std::vector<std::vector<std::vector<valueType>>>>(vs);
+ break;
+ }
+ }
+
+ AttributeValue convertArrayToConcretes(const typeTag t,
+ const unsigned int curLevel, const std::vector<OC::AttributeValue>& vs)
+ {
+ // This function converts a std::vector of AttributeValue to a std::vector
+ // of concrete types. Since we don't use a recursive Variant, we need
+ // to get back to a 'base' primitive type
+ switch(t)
+ {
+ default:
+ case typeTag::NOTHING:
+ throw OC::OCException(OC::Exception::INVALID_JSON_TYPE_TAG);
+ break;
+ case typeTag::_string:
+ return remapArrayDepth<std::string>(curLevel, vs);
+ break;
+ case typeTag::_int:
+ return remapArrayDepth<int>(curLevel, vs);
+ break;
+ case typeTag::_double:
+ return remapArrayDepth<double>(curLevel, vs);
+ break;
+ case typeTag::_bool:
+ return remapArrayDepth<bool>(curLevel, vs);
+ break;
+ case typeTag::_representation:
+ return remapArrayDepth<OCRepresentation>(curLevel, vs);
+ break;
+ }
+ }
+
+ AttributeValue parseAttributeValueArray(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+ {
+ const unsigned int max_level = 3;
+
+ if(curLevel > max_level)
+ {
+ throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH);
+ }
+
+ if(curLevel > maxDepth)
+ {
+ maxDepth = curLevel;
+ }
+
+ auto arrayItems = gatherArrayContents(v, curLevel, maxDepth, t);
+ const int remapLevel = maxDepth - (curLevel -1);
+ return convertArrayToConcretes(t, remapLevel, arrayItems);
+ }
+ }
+}
+
+namespace cereal
+{
+ void JSONInputArchive::loadAttributeValues(std::map<std::string, OC::AttributeValue>& map)
+ {
+ for(auto&b = itsIteratorStack.back();
+ b.Member && b.itsMemberItEnd != b.itsMemberItBegin+b.itsIndex;
+ ++b)
+ {
+ std::string key = b.itsMemberItBegin[b.itsIndex].name.GetString();
+ const GenericValue& v = itsIteratorStack.back().value();
+ map[key] = OC::detail::parseAttributeValue(v);
+ }
+ }
+}
m_clientWrapper.expired())
{
throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
- interfaces.empty(), m_clientWrapper.expired());
+ interfaces.empty(), m_clientWrapper.expired(), false, false);
}
}
OUT_DIR := $(BUILD)
+ifeq ($(ROOT_DIR),)
+ ROOT_DIR:=$(PWD)
+endif
+
+DEPEND_DIR:=$(ROOT_DIR)/../dependencies
+CEREAL_DIR:=$(DEPEND_DIR)/cereal
+
INC_DIRS := -I../include/
INC_DIRS += -I../oc_logger/include
INC_DIRS += -I../csdk/stack/include
INC_DIRS += -I../csdk/logger/include
INC_DIRS += -I../csdk/libcoap
INC_DIRS += -I$(GTEST_DIR)/include
+INC_DIRS += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a