cd csdk && $(MAKE) clean
cd csdk && $(MAKE) deepclean
-
void InProcServerWrapper::registerResource(const std::string& resourceURI,
const std::string& resourceTypeName,
- named_property_binding_vector& properties)
+ property_binding_vector properties)
{
using OC::OCReflect::property_type;
- using OC::OCReflect::named_property_binding;
+ using OC::OCReflect::property_binding;
using namespace OC::OCReflect::to_OCStack;
std::vector<std::string> reps { convert(properties) };
void OCPlatform::registerResource(const std::string& resourceURI, const std::string& resourceTypeName,
- named_property_binding_vector properties)
+ property_binding_vector properties)
{
if(m_server)
{
return os;
}
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_binding& pb)
+{
+ os << "property binding \"" << std::get<0>(pb) << "\": " << std::get<1>(pb);
+ return os;
+}
+
std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property& p)
{
using std::get;
}}} // namespace OC::OCReflect::to_property
+namespace OC { namespace OCReflect {
+
pd_iter_tuple consume_typecheck(const property_type expected_pt, const OC::OCReflect::property_data& in)
{
OC::OCReflect::property_data::const_iterator begin = in.begin();
return std::forward_as_tuple(++begin, in.end());
}
+}} // namespace OC::OCReflect
+
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
#include <string>
+#include <vector>
#include <cstring>
+#include <iterator>
+
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
#include "OCReflect.h"
return OC::OCReflect::entity();
}
-namespace OC { namespace OCReflect { namespace to_OCStack {
+namespace OC { namespace OCReflect { namespace OCStack {
+
+// Free a char *:
+void release(char *in)
+{
+ if(nullptr == in)
+ return;
+
+ free(in);
+}
// Free a C array of char *:
void release(char **in)
return;
for(char **cursor = in; nullptr != *cursor; ++cursor)
- {
- if(nullptr != *cursor)
- free(*cursor);
- }
+ release(*cursor);
free(in);
}
size_t i = 0;
for(; vs.size() != i; ++i)
{
- out[i] = to_OCStack::strdup(vs[i]);
+ out[i] = OCStack::strdup(vs[i]);
if(nullptr == out[i])
throw;
return nullptr;
}
-std::string convert(const OC::OCReflect::named_property_binding& npb)
+std::string convert(const OC::OCReflect::property_binding& npb)
{
const std::string& name = std::get<0>(npb);
const OC::OCReflect::property_signature ps = std::get<1>(npb);
{
case property_type::nil:
case property_type::rational:
- case property_type::string:
case property_type::list:
+ case property_type::string:
+ os << "convert(): request to convert valid, but unimplemented type: " << ps.type;
+ throw std::runtime_error(os.str());
+ break;
+
case property_type::INVALID:
- throw std::runtime_error("not implemented");
+ throw std::runtime_error("convert(): request to convert invalid type");
break;
case property_type::boolean: os << "bt." << 'b';
return os.str();
}
-std::vector<std::string> convert(const OC::OCReflect::named_property_binding_vector& psv)
+OC::OCReflect::property_type as_property_type(const std::string& pb_code)
+{
+ // We expect: "oc.bt.<char typecode>":
+ const size_t code_length = 7,
+ code_pos = 6;
+
+ if(code_length != pb_code.length())
+ return OC::OCReflect::property_type::INVALID;
+
+ switch(pb_code[code_pos])
+ {
+ default: break;
+
+ case 'b': return OC::OCReflect::property_type::boolean;
+ case 'i': return OC::OCReflect::property_type::integer;
+
+/* These don't have codes yet:
+ case property_type::nil:
+ case property_type::rational:
+ case property_type::string:
+ case property_type::list:
+*/
+ }
+
+ return OC::OCReflect::property_type::INVALID;
+}
+
+OC::OCReflect::property_binding as_property_binding(const std::string& pb_rep)
+{
+ auto delim_pos = pb_rep.find_first_of(':');
+
+ if(pb_rep.length() == delim_pos)
+ throw OC::OCReflect::reflection_exception("convert(): invalid property string (missing delimiter)");
+
+ std::string pname { pb_rep.substr(0, delim_pos) };
+
+ auto ptype = as_property_type(pb_rep.substr(1 + delim_pos));
+
+ auto pattr = OC::OCReflect::property_attribute::rw; // We aren't handling attributes right now...
+
+ return OC::OCReflect::property_binding { pname, { ptype, pattr } };
+}
+
+OC::OCReflect::property_binding_vector as_property_binding_vector(const std::vector<std::string>& pb_reps)
+{
+ OC::OCReflect::property_binding_vector pbv;
+
+ for(const auto& s : pb_reps)
+ pbv.emplace_back(as_property_binding(s));
+
+ return pbv;
+}
+
+std::vector<std::string> convert(const OC::OCReflect::property_binding_vector& psv)
{
std::vector<std::string> out;
for(const auto& ps : psv)
- out.emplace_back(convert(ps));
+ out.push_back(convert(ps));
return out;
}
char *flatten(const std::vector<std::string>& input, const std::string& delim)
+try
{
std::string out;
out += input[i];
if(i < input.size() - 1)
- out += ";";
+ out += delim;
}
- return OC::OCReflect::to_OCStack::strdup(out);
+ return OC::OCReflect::OCStack::strdup(out);
+}
+catch(...)
+{
+ return nullptr;
+}
+
+// Note: expects output of flatten():
+std::vector<std::string> expand(const char *flattened_string, const std::string& delim)
+{
+ if(nullptr == flattened_string)
+ throw OC::OCReflect::reflection_exception("nullptr passed to expand()");
+
+ std::vector<std::string> ret;
+ std::string flattened = flattened_string;
+ boost::split(ret, flattened, boost::is_any_of(delim));
+
+ return ret;
}
-}}} // namespace OC::OCReflect::to_OCStack
+}}} // namespace OC::OCReflect::OCStack
#include "OCServer.h"
#include "OCReflect.h"
+#include "OCProperties.h"
namespace OC {
+
OCServer::OCServer(void)
{
}
void OCServer::stop() {
}
+ // Method and property wrangling:
void OCServer::bind(const OC::OCReflect::method_binding& mb)
{
- method_bindings[mb.name] = mb;
+ method_bindings[mb.name] = mb;
+ }
+
+ void OCServer::bind(const OC::OCReflect::property_binding& pb)
+ {
+std::cout << "OCServer::bind() property " << std::get<0>(pb) << '\n';
+ property_bindings[std::get<0>(pb)] = pb;
}
}
{
bool bResult = true;
PlatformConfig cfg;
- named_property_binding_vector vc;
+ property_binding_vector vc;
try
{
{
bool bResult = true;
PlatformConfig cfg;
- named_property_binding_vector vc;
+ property_binding_vector vc;
try
{
bool bResult = false;
PlatformConfig cfg;
string resType, hostName;
- named_property_binding_vector vc;
+ property_binding_vector vc;
try
{
bool bResult = false;
PlatformConfig cfg;
string serviceURL, resourceType;
- named_property_binding_vector vc;
+ property_binding_vector vc;
try
{
{
bool bResult = false;
string resourceURI, resourceTypeName;
- named_property_binding_vector vc;
+ property_binding_vector vc;
try
{
{
bool bResult = true;
string resName, resType;
- named_property_binding_vector vc;
+ property_binding_vector vc;
try
{
void Test_OCFunction_3(int functionIndex)
{
bool bResult = true;
- string resName, resType;
- named_property_binding_vector vc;
+ string resName, resType;
+ property_binding_vector vc;
try
{
-
-CXX=g++
-#CXX=clang -lstdc++ -g
+CXX=g++ -g -O0
+#CXX=clang -lstdc++ -g -O0
CXX_FLAGS=-std=c++11 -Wall -pthread
CXX_INC=-I../include/ -I./client/ -I../csdk/stack/include -I../csdk/ocsocket/include -I../csdk/ocrandom/include -I../csdk/logger/include
-LIB_SRC0=../OCLib/OCReflect.cpp ../OCLib/OCProperties.cpp ../OCLib/OCObserver.cpp ../OCLib/OCResource.cpp
+LIB_SRC0=../OCLib/OCReflect.cpp ../OCLib/OCProperties.cpp ../OCLib/OCObserver.cpp ../OCLib/OCResource.cpp ./client/MyObserverHandler.cpp ../OCLib/OCServer.cpp
+
+LIB_SRC1=../OCLib/OCReflect.cpp ../OCLib/OCObserver.cpp ./client/MyObserverHandler.cpp ../OCLib/OCResource.cpp ../OCLib/OCSecurityModel.cpp ../OCLib/InProcClientWrapper.cpp ../OCLib/OCPlatform.cpp ../OCLib/InProcServerWrapper.cpp ../csdk/liboctbstack.a ../OCLib/OCServer.cpp
-LIB_SRC1=../OCLib/OCReflect.cpp ../OCLib/OCObserver.cpp ./client/MyObserverHandler.cpp ../OCLib/OCResource.cpp ../OCLib/OCSecurityModel.cpp ../OCLib/InProcClientWrapper.cpp ../OCLib/OCPlatform.cpp ../OCLib/InProcServerWrapper.cpp ../csdk/liboctbstack.a
+CXX_LIBS=-lboost_regex
-all: ocreflect
+.PHONY: ocreflect resources test_OCReflect test_OCClient test_properties
+
+all: .PHONY
ocreflect: test_properties test_OCClient
test_properties:
- $(CXX) $(CXX_FLAGS) -o test_properties reflect/test_properties.cpp $(LIB_SRC0) $(CXX_INC)
+
+ $(CXX) $(CXX_FLAGS) -o test_properties reflect/test_properties.cpp $(LIB_SRC0) $(CXX_INC) $(CXX_LIBS)
test_OCReflect:
- $(CXX) $(CXX_FLAGS) -o test_OCReflect reflect/test_OCReflect.cpp ../OCLib/OCReflect.cpp ../OCLib/OCProperties.cpp $(CXX_INC)
+ $(CXX) $(CXX_FLAGS) -o test_OCReflect reflect/test_OCReflect.cpp ../OCLib/OCReflect.cpp ../OCLib/OCProperties.cpp ../OCLib/OCServer.cpp $(CXX_INC) $(CXX_LIBS)
test_OCClient:
- $(CXX) $(CXX_FLAGS) -o test_OCClient reflect/test_OCClient.cpp $(LIB_SRC0) $(CXX_INC)
+ $(CXX) $(CXX_FLAGS) -o test_OCClient reflect/test_OCClient.cpp $(LIB_SRC0) $(CXX_INC) $(CXX_LIBS)
+
+resources: single_resource multiple_resources
+
+single_resource:
+ $(CXX) $(CXX_FLAGS) -o single_resource ./server/single_resource.cpp $(LIB_SRC1) $(CXX_INC) $(CXX_LIBS)
+
+multiple_resources:
+ #$(CXX) $(CXX_FLAGS) -o multiple_resources ./server/multiple_resources.cpp $(LIB_SRC1) $(CXX_INC) $(CXX_LIBS)
clean:
rm -f -v test_properties test_OCReflect test_OCClient
void bindTo(OC::OCPlatform& platform)
{
using OC::OCReflect::property_type;
- using OC::OCReflect::named_property_binding;
+ using OC::OCReflect::property_binding;
- named_property_binding_vector properties {
- named_property_binding("state", property_type::boolean),
- named_property_binding("power", property_type::integer)
+ property_binding_vector properties {
+ property_binding("state", property_type::boolean),
+ property_binding("power", property_type::integer)
};
std::string resourceURI = "/a/light";
return_type, property_type_vector { param_types... });
server.bind(fmb);
-
-/*
- call_through<decltype(b)> ct(b, return_type, ptypes);
-
- // then, at the call site...
- auto r = ct(1); // call the function
-
- std::function<property_type(ParameterT...)> f = ct;
-*/
}
template <typename PropertyT>
-void bind_property(OC::OCServer& server, PropertyT& property, const std::string& binding_name, const property_type& pt, const property_attribute& pas)
+void bind_property(OC::OCServer& server, PropertyT& property, const std::string& binding_name, const property_type& pt, const property_attribute& pa)
{
+
+ OC::OCReflect::property_binding npb { binding_name, { pt, pa } };
+ OC::OCReflect::property_binding pb { binding_name,
+ npb }; //{ binding_name, { pt, pa } } };
+
+ server.bind(pb);
+
+/*
+ server.bind({ binding_name,
+ { binding_name, { pt, pa } } });
+*/
}
}} // namespace OC::OCReflect
// Example to bind a read-only property in individual steps:
property_signature p_manufacturer_signature(property_type::string, OC::OCReflect::property_attribute::r); // read-only
- OC::OCReflect::named_property_binding p_manufacturer("manufacturer", p_manufacturer_signature);
+ OC::OCReflect::property_binding p_manufacturer("manufacturer", p_manufacturer_signature);
property_binding b_manufacturer(
this->manufacturer,
p_manufacturer);
server.bind(b_manufacturer);
-
+*/
// The canonical way to bind a property to a server in one step:
bind_property(
server, // server to bind to
OC::OCReflect::property_type::string, // property
OC::OCReflect::property_attribute::r // type decoration
);
-*/
}
};
using namespace OC::OCReflect;
+using std::cout;
+
+template <class InputT>
+void convert_and_compare(const InputT& input, const std::string name = "property")
+{
+ auto p = make_property::apply(input, name);
+
+ cout << p << '\n';
+
+ auto x = concretize<InputT>(p);
+
+ cout << x << '\n';
+
+ assert(input == x);
+}
+
// Convert a native type to a property:
void convert_test()
{
// Nil (JSON: null):
{
property_signature ps(property_type::nil);
- named_property_binding npb("nil_property", ps);
+ property_binding npb("nil_property", ps);
}
*/
// Boolean:
{
- OC::OCReflect::property my_bool = OC::OCReflect::make_property::apply(true, "my_bool");
- OC::OCReflect::property my_bool_too = make_property::apply(false, "my_bool_too");
-
- cout << my_bool << '\n' << my_bool_too << '\n';
-
- auto x = concretize<bool>(my_bool);
- auto y = concretize<bool>(my_bool_too);
-
- cout << "got back: " << x << '\n';
- cout << "got back: " << y << '\n';
-
- assert(x == true);
- assert(y == false);
+ convert_and_compare(true, "bool");
+ convert_and_compare(false, "bool");
}
// Integer:
{
const int64_t input { 1024 };
- auto my_int = make_property::apply(input, "my int");
-
- cout << my_int << '\n';
-
- auto x = concretize<int64_t>(my_int);
-
- cout << x << '\n';
-
- assert(input == x);
+ convert_and_compare(input, "int64_t");
}
// Rational (JSON: number):
{
const double input { 1024.0 };
- auto my_float = make_property::apply(input, "my float");
-
- cout << my_float << '\n';
-
- auto x = concretize<double>(my_float);
-
- cout << x << '\n';
-
- assert(input == x);
+ convert_and_compare(input, "double");
}
// String:
{
const std::string input { "Hello, World!" };
-
- auto my_string = make_property::apply(input, "my string");
-
- cout << my_string << '\n';
-
- auto x = concretize<std::string>(my_string);
-
- cout << x << '\n';
-
- assert(input == x);
+ convert_and_compare(input, "string");
}
/*
*/
}
-// Demo of how to generate OCStack stuff:
+// Demo of how to generate OCStack stuff (talk to the C library):
void rep_test()
{
using OC::OCReflect::property_type;
- using OC::OCReflect::named_property_binding;
+ using OC::OCReflect::property_binding;
- named_property_binding_vector sigs {
- named_property_binding("state", property_type::boolean),
- named_property_binding("power", property_type::integer)
+ property_binding_vector sigs {
+ property_binding("state", property_type::boolean),
+ property_binding("power", property_type::integer)
};
- using namespace OC::OCReflect::to_OCStack;
+ using namespace OC::OCReflect::OCStack;
/* JFW: note:
char *LEDrep[] = { "state;b", "power;i", NULL};
CREATE_RESOURCE_TYPE(LED, "core.led", LEDrep);
*/
-std::vector<std::string> reps { convert(sigs) };
+
+ std::vector<std::string> reps { convert(sigs) };
for(const auto& r : reps)
- std::cout << r << '\n';
+ std::cout << "converted representation: " << r << '\n';
// Example of flattening to a single string:
char *flattened = flatten(reps);
+ if(nullptr == flattened)
+ throw std::runtime_error("couldn't flatten");
+
std::cout << "FLATTENED: " << flattened << '\n';
// Example of converting to an array of char*s:
char **handle = convert(reps);
if(nullptr == handle)
- throw std::runtime_error("handle is a nullptr");
+ {
+ release(flattened);
+ throw std::runtime_error("handle is a nullptr");
+ }
std::for_each(handle, handle + length(handle), [](const char *s) { std::cout << s << '\n'; });
printf("%s\n", *cursor);
*/
- release(handle); // remember to free the memory!
+ release(handle); // remember to free the memory! (Note: nobody said you couldn't wrap this in a smart ptr --JFW)
+ release(flattened);
}
+// Convert to and from OCStack representation:
void from_rep_test()
{
- using std::cout;
+ property_binding_vector sigs {
+ property_binding("state", property_type::boolean),
+ property_binding("power", property_type::integer)
+ };
- std::cout << "from_rep_test() doesn't do much yet :-)\n";
-/*
- const char *LEDrep[] = { "state;b", "power;i", NULL };
+ using OC::OCReflect::OCStack::length;
+ using OC::OCReflect::OCStack::convert;
- named_property_binding_vector npbv(LEDrep);
+ using OC::OCReflect::OCStack::expand;
+ using OC::OCReflect::OCStack::flatten;
- cout << npbv << '\n';
-*/
+ using OC::OCReflect::OCStack::as_property_binding_vector;
+
+ std::vector<std::string> reps { convert(sigs) }; // convert a property_binding_vector to a std::vector of std::string
+
+ /* First, let's make some C data from OCReflect stuff:
+ IMPORTANT: error checking is ignored below, DO NOT do this in real code. :-) */
+ char *flattened = flatten(reps); // convert a vector of std::string to a single C string
+ char **handle = convert(reps); // convert a vector of std::string into a C array of C strings
+
+ /* Great, now let's convert back to OCReflect: */
+ // C array to std::vector of std::string (just normal C++):
+ std::vector<std::string> reps_in1 { handle, length(handle) + handle };
+
+ std::cout << "Retreived from C array:\n";
+ for(const auto& s : reps_in1)
+ std::cout << s << '\n';
+
+ // C string into std::vector of std::string:
+ std::vector<std::string> reps_in2 { expand(flattened) };
+
+ std::cout << "Retrieved from flattened C string:\n";
+ for(const auto& s : reps_in2)
+ std::cout << s << '\n';
+
+ /* Now, convert a std::vector of std::string into a vector of property bindings: */
+ property_binding_vector sigs_in1 { as_property_binding_vector(reps_in1) };
+ std::cout << "Retreived properties from vector<string>:\n";
+ for(const auto sig : sigs_in1)
+ std::cout << sig << '\n';
+
+ // Notice that either representation /source/ is fine, it's just a vector of strings!
+ property_binding_vector sigs_in2 { as_property_binding_vector(reps_in2) };
+ for(const auto sig : sigs_in1)
+ std::cout << sig << '\n';
+}
+
+void simple_test()
+{
+ using namespace std;
+
+ OC::OCReflect::property p = make_property::apply("Sashi", "p_first_name");
+
+ string lname = "Penta";
+
+ auto p2 = make_property::apply(lname, "p_last_name");
+
+ cout << p << '\n';
+
+ std::string fname = concretize<std::string>(p);
+ cout << "string back from property: " << fname << '\n';
}
+/* Note:
+template <class OutT>
+void concretize(const property& p, OutT& out)
+{
+ out = concretize<OutT>(p);
+}
+*/
+
int main()
{
- using namespace OC::OCReflect;
convert_test();
call_test();
+ simple_test();
+
rep_test();
from_rep_test();
void createResourceWithPropeties(OC::OCPlatform& platform)
{
/*
- We could typedef to simpler namers! :)
+ We could typedef to simpler names! :)
typedef named_property_binding_vector OCPropertyBindings;
typedef named_property_binding OCPropertyBinding;
OCPropertyBindings properties {
OCPropertyBinding("state", property_type::boolean),
OCPropertyBidning("power", property_type::integer)
+
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::property_binding;
+
+ property_binding_vector properties {
+ property_binding("state", property_type::boolean),
+ property_binding("power", property_type::integer)
};
*/
virtual void registerResource( const std::string& resourceURI,
const std::string& resourceTypeName,
- named_property_binding_vector& properties) = 0;
+ property_binding_vector properties) = 0;
};
}
void registerResource( const std::string& resourceURI,
const std::string& resourceTypeName,
- named_property_binding_vector& properties);
+ property_binding_vector properties);
private:
void processFunc();
namespace OC
{
using OC::OCReflect::property_type;
- using OC::OCReflect::named_property_binding;
+ using OC::OCReflect::property_binding;
/**
* @brief The core OC platform object initialized by the application or service via a static accessor.
*
*/
void registerResource(const std::string& resourceURI, const std::string& resourceTypeName,
- named_property_binding_vector properties);
+ property_binding_vector properties);
private:
std::unique_ptr<WrapperFactory> m_WrapperInstance;
// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
#ifndef __INTEL_OCPROPERTIES_H_20140708
#define __INTEL_OCPROPERTIES_H_20140708
#include <type_traits>
#include "OCException.h"
-
-namespace OC { namespace OCReflect {
-
-enum class property_type : uint8_t {
- nil = 1,
- boolean,
- integer,
- rational,
- string,
- list,
-
- INVALID
-};
-
-enum class property_attribute : uint8_t {
- r,
- w,
- rw
-};
-
-struct property_signature
-{
- OC::OCReflect::property_type type;
- OC::OCReflect::property_attribute attribute;
-
- public:
- property_signature()
- : type(OC::OCReflect::property_type::nil),
- attribute(OC::OCReflect::property_attribute::rw)
- {}
-
- property_signature(const OC::OCReflect::property_type& type_)
- : type(type_),
- attribute(OC::OCReflect::property_attribute::rw)
- {}
-
- property_signature(const OC::OCReflect::property_type type_, const OC::OCReflect::property_attribute attribute_)
- : type(type_),
- attribute(attribute_)
- {}
-};
-
-typedef std::vector<property_type> property_type_vector;
-
-typedef std::vector<property_signature> property_signature_vector;
-
-typedef std::vector<char> property_data;
-
-typedef std::tuple<std::string, property_signature> named_property_binding;
-typedef std::vector<named_property_binding> named_property_binding_vector;
-
-typedef std::tuple<named_property_binding, property_data> property;
-typedef std::tuple<property_signature, property_data> tagged_property; // eg. a return value
-
-typedef std::vector<property> property_vector;
-
-typedef std::function<property(property_vector)> bound_function;
-
-namespace detail {
-
-// Great name, huh? Must be late in the day:
-inline property_signature_vector typev2signaturev(const property_type_vector& ptv, const property_attribute pa = property_attribute::rw)
-{
- property_signature_vector psv(ptv.size());
-
- std::transform(std::begin(ptv), std::end(ptv), std::back_inserter(psv),
- [&pa](const property_type& pt) -> property_signature { return property_signature(pt, pa); });
-
- return psv;
-}
-
-}
-
-namespace detail {
-
-// Helper for constructing sequences (like vector<property>) from a parameter pack:
-template <typename SeqT, typename T>
-SeqT make_seq(const T& x)
-{
- return SeqT { x };
-}
-
-template <typename SeqT, typename T, typename ...TS>
-SeqT make_seq(const T& x, const TS&... xs)
-{
- SeqT s { x };
-
- auto vs = make_seq<SeqT>(xs...);
-
- s.insert(s.end(), std::make_move_iterator(vs.begin()), std::make_move_iterator(vs.end()));
-
- return s;
-}
-
-} // namespace OC::OCReflect::detail
-
-}} // namespace OC::OCReflect
+#include "OCPropertyTypes.h"
// Prettyprinters:
namespace OC { namespace OCReflect {
std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_type& pt);
std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_attribute& pa);
std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_signature& ps);
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_binding& pb);
std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property& p);
std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_type_vector& pv);
}} // namespace OC::OCReflect
-/* JFW: I wonder if I can do this...
-constexpr OC::OCReflect::property_type map_property_type(bool)
-{
- return OC::OCReflect::property_type::boolean;
-}
-*/
-
-// Map concerete to property type enumerations:
-namespace OC { namespace OCReflect {
-
-template <typename T>
-struct map_property_type
-{
- static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::INVALID);
-};
-
-template <>
-struct map_property_type<bool>
-{
- static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::boolean);
-};
-
-template <>
-struct map_property_type<int64_t>
-{
- static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::integer);
-};
-
-template <>
-struct map_property_type<double>
-{
- static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::rational);
-};
-
-template <>
-struct map_property_type<std::string>
-{
- static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
-};
-
-template <>
-struct map_property_type<const char *>
-{
- static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
-};
-
-}} // namespace OC::OCReflect
-
-/*
-// Sequence containers:
-template <>
-struct map_property_type< template <class T, class A> >
-{
- static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
-};
-
-template <>
-struct map_property_type<std::vector>
-{
- static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
-};
-
-template <>
-struct map_property_type<std::list>
-{
- static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
-};
-
-template <>
-struct map_property_type<std::forward_list>
-{
- static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
-};
-
-template <>
-struct map_property_type<std::deque>
-{
- static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
-};
-*/
-
+// Convert from a concrete type to a property:
namespace OC { namespace OCReflect { namespace to_property {
OC::OCReflect::tagged_property convert(const bool& in);
}}} // namespace OC::OCReflect::to_property
-typedef std::tuple<OC::OCReflect::property_data::const_iterator, OC::OCReflect::property_data::const_iterator> pd_iter_tuple;
-
-pd_iter_tuple consume_typecheck(const OC::OCReflect::property_type expected_pt, const OC::OCReflect::property_data& in);
-
+// Convert from a property to a concrete type:
namespace OC { namespace OCReflect { namespace from_property {
typedef OC::OCReflect::property_data::const_iterator pdci;
out.assign(std::get<0>(in), std::get<1>(in));
}
-/*
-template <template <class T, class AllocT> class SeqT>
-static void convert(const pd_iter_pair& in, SeqT& out)
-{
- std::copy(std::get<0>(in), std::get<1>(in), std::back_inserter(out));
-}
-*/
-
};
}}} // namespace OC::OCReflect::from_property
+// Run-time typechecking:
+namespace OC { namespace OCReflect {
+
+typedef std::tuple<OC::OCReflect::property_data::const_iterator, OC::OCReflect::property_data::const_iterator> pd_iter_tuple;
+pd_iter_tuple consume_typecheck(const OC::OCReflect::property_type expected_pt, const OC::OCReflect::property_data& in);
+
+}} // namespace OC::OCReflect
+
+// Property binding factory:
namespace OC { namespace OCReflect {
-inline OC::OCReflect::named_property_binding make_named_property_binding(const std::string& name, const OC::OCReflect::property_type pt, const OC::OCReflect::property_attribute pa = OC::OCReflect::property_attribute::rw)
+inline OC::OCReflect::property_binding make_property_binding(const std::string& name, const OC::OCReflect::property_signature ps)
{
- return OC::OCReflect::named_property_binding { name, { pt, pa } };
+ return OC::OCReflect::property_binding { name, ps };
+}
+
+inline OC::OCReflect::property_binding make_property_binding(const std::string& name, const OC::OCReflect::property_type pt, const OC::OCReflect::property_attribute pa = OC::OCReflect::property_attribute::rw)
+{
+ return OC::OCReflect::property_binding { name, { pt, pa } };
}
}} // namespace OC::OCReflect
template <class InT>
static OC::OCReflect::property apply(const InT& in, const std::string& name)
{
-/* JFW:
- static_assert(property_valid(InT, OC::OCReflect::property_type::INVALID),
- "invalid input type for make_property()");
-*/
-
- OC::OCReflect::tagged_property tp { OC::OCReflect::to_property::convert(in) };
- OC::OCReflect::named_property_binding npb { name, { std::get<0>(tp) } };
+ OC::OCReflect::tagged_property tp { OC::OCReflect::to_property::convert(in) };
+ OC::OCReflect::property_binding npb { OC::OCReflect::make_property_binding(name, std::get<0>(tp)) };
OC::OCReflect::property_data& tp_data = std::get<1>(tp);
return OC::OCReflect::property(npb, encoded_data);
}
-/*
-// Pretend you didn't see this, and I won't tell anyone where you hide the bodies:
-template <class InT>
-make_property(const InT& in, const std::string& name, OC::OCReflect::property& out)
-{
- out = detail::make_property::apply(in, name, out);
-}
-*/
-
}; // struct make_property
}} // namespace OC::OCReflect
}} // namespace OC::OCReflect
+/* JFW: We are using concretize<> to fill this niche-- candidate for removal:
namespace OC { namespace OCReflect {
// Runtime dynamic cast from entities to concrete types:
return OutT(); // placeholder
}
-struct method_signature
-{
- property_signature ret_signature;
- property_signature_vector param_signatures;
-
- public:
- method_signature(const property_type& return_type, const property_signature_vector& param_types_)
- : ret_signature(return_type, OC::OCReflect::property_attribute::r),
- param_signatures(param_types_)
- {}
-
- method_signature(const property_type& return_type, const property_type_vector& param_types_)
- : ret_signature(return_type, OC::OCReflect::property_attribute::r),
- param_signatures(detail::typev2signaturev(param_types_))
- {}
-
- template <typename ...ParameterT>
- method_signature(const property_type& return_type, const ParameterT& ...params_)
- : ret_signature(return_type, OC::OCReflect::property_attribute::r),
- param_signatures { detail::make_seq<property_signature_vector>(params_...) }
- {}
-};
-
-}} // namespace OC::OCReflect
-
-namespace OC { namespace OCReflect {
-
-struct method_binding
-{
- friend std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb);
-
- public:
- std::string name;
- bound_function f;
- method_signature signature;
-
- private:
- static unsigned long long anon;
-
- public:
- method_binding()
- : name("__ANONYMOUS__"),
- signature { property_type::nil, {{ property_type::nil, property_attribute::r }} }
- {}
-
- method_binding(bound_function& f,
- method_signature& signature_)
- : signature(signature_)
- {}
-
- method_binding(const std::string& name_, bound_function& f_,
- const property_type& return_type_, const property_type_vector& param_types_)
- : name(name_),
- f(f_),
- signature { return_type_, param_types_ }
- {}
-
- method_binding(const std::string& name_, bound_function& f_,
- const method_signature& signature_)
- : name(name_),
- f(f_),
- signature(signature_)
- {}
-};
-
-struct property_binding
-{
- template <typename PropertyT>
- property_binding(PropertyT& property, const named_property_binding& pb)
- {
- }
-};
-
}} // namespace OC::OCReflect
+*/
#endif
--- /dev/null
+
+#ifndef __INTEL_OCPROPERTY_TYPES_H_20140723
+ #define __INTEL_OCPROPERTY_TYPES_H_20140723
+
+#include <tuple>
+#include <vector>
+#include <algorithm>
+#include <functional>
+
+namespace OC { namespace OCReflect {
+
+enum class property_type : uint8_t {
+ nil = 1,
+ boolean,
+ integer,
+ rational,
+ string,
+ list,
+
+ INVALID
+};
+
+enum class property_attribute : uint8_t {
+ r,
+ w,
+ rw
+};
+
+struct property_signature
+{
+ OC::OCReflect::property_type type;
+ OC::OCReflect::property_attribute attribute;
+
+ public:
+ property_signature()
+ : type(OC::OCReflect::property_type::nil),
+ attribute(OC::OCReflect::property_attribute::rw)
+ {}
+
+ property_signature(const OC::OCReflect::property_type& type_)
+ : type(type_),
+ attribute(OC::OCReflect::property_attribute::rw)
+ {}
+
+ property_signature(const OC::OCReflect::property_type type_, const OC::OCReflect::property_attribute attribute_)
+ : type(type_),
+ attribute(attribute_)
+ {}
+};
+
+typedef std::vector<property_type> property_type_vector;
+
+typedef std::vector<property_signature> property_signature_vector;
+
+typedef std::vector<char> property_data;
+
+typedef std::tuple<std::string, property_signature> property_binding; // ie. name + signature
+typedef std::vector<property_binding> property_binding_vector;
+
+typedef std::tuple<property_binding, property_data> property;
+typedef std::tuple<property_signature, property_data> tagged_property; // eg. a return value
+
+typedef std::vector<property> property_vector;
+
+typedef std::function<property(property_vector)> bound_function;
+
+
+}} // namespace OC::OCReflect
+
+namespace OC { namespace OCReflect {
+
+namespace detail {
+
+// zip a property type vector against an attribute:
+inline property_signature_vector typev2signaturev(const property_type_vector& ptv, const property_attribute pa = property_attribute::rw)
+{
+ property_signature_vector psv(ptv.size());
+
+ std::transform(std::begin(ptv), std::end(ptv), std::back_inserter(psv),
+ [&pa](const property_type& pt) -> property_signature { return property_signature(pt, pa); });
+
+ return psv;
+}
+
+// Helper for constructing sequences (like vector<property>) from a parameter pack:
+template <typename SeqT, typename T>
+SeqT make_seq(const T& x)
+{
+ return SeqT { x };
+}
+
+template <typename SeqT, typename T, typename ...TS>
+SeqT make_seq(const T& x, const TS&... xs)
+{
+ SeqT s { x };
+
+ auto vs = make_seq<SeqT>(xs...);
+
+ s.insert(s.end(), std::make_move_iterator(vs.begin()), std::make_move_iterator(vs.end()));
+
+ return s;
+}
+
+} // namespace OC::OCReflect::detail
+
+struct method_signature
+{
+ property_signature ret_signature;
+ property_signature_vector param_signatures;
+
+ public:
+ method_signature(const property_type& return_type, const property_signature_vector& param_types_)
+ : ret_signature(return_type, OC::OCReflect::property_attribute::r),
+ param_signatures(param_types_)
+ {}
+
+ method_signature(const property_type& return_type, const property_type_vector& param_types_)
+ : ret_signature(return_type, OC::OCReflect::property_attribute::r),
+ param_signatures(detail::typev2signaturev(param_types_))
+ {}
+
+ template <typename ...ParameterT>
+ method_signature(const property_type& return_type, const ParameterT& ...params_)
+ : ret_signature(return_type, OC::OCReflect::property_attribute::r),
+ param_signatures { detail::make_seq<property_signature_vector>(params_...) }
+ {}
+};
+
+}} // namespace OC::OCReflect
+
+namespace OC { namespace OCReflect {
+
+struct method_binding
+{
+ friend std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb);
+
+ public:
+ std::string name;
+ bound_function f;
+ method_signature signature;
+
+ private:
+ static unsigned long long anon;
+
+ public:
+ method_binding()
+ : name("__ANONYMOUS__"),
+ signature { property_type::nil, {{ property_type::nil, property_attribute::r }} }
+ {}
+
+ method_binding(bound_function& f,
+ method_signature& signature_)
+ : signature(signature_)
+ {}
+
+ method_binding(const std::string& name_, bound_function& f_,
+ const property_type& return_type_, const property_type_vector& param_types_)
+ : name(name_),
+ f(f_),
+ signature { return_type_, param_types_ }
+ {}
+
+ method_binding(const std::string& name_, bound_function& f_,
+ const method_signature& signature_)
+ : name(name_),
+ f(f_),
+ signature(signature_)
+ {}
+};
+
+}} // namespace OC::OCReflect
+
+
+// Map concerete to property type enumerations (used for returning runtime types from compile time types):
+namespace OC { namespace OCReflect {
+
+template <typename T>
+struct map_property_type
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::INVALID);
+};
+
+template <>
+struct map_property_type<bool>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::boolean);
+};
+
+template <>
+struct map_property_type<int64_t>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::integer);
+};
+
+template <>
+struct map_property_type<double>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::rational);
+};
+
+template <>
+struct map_property_type<std::string>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
+};
+
+template <>
+struct map_property_type<const char *>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
+};
+
+/*
+// Sequence containers:
+template <>
+struct map_property_type< template <class T, class A> >
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::vector>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::list>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::forward_list>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::deque>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+*/
+
+}} // namespace OC::OCReflect
+
+#endif
}} // namespace OC::OCReflect
// Convert to underlying OCStack C API (and, some handy C-wrangling utilities):
-namespace OC { namespace OCReflect { namespace to_OCStack {
+namespace OC { namespace OCReflect { namespace OCStack {
+void release(char *in);
void release(char **in);
char *strdup(const char *s);
char *strdup(const std::string& s);
size_t length(char **in);
char **convert(const std::vector<std::string>& vs);
-std::string convert(const named_property_binding& npb);
-std::vector<std::string> convert(const named_property_binding_vector& psv);
+
+std::string convert(const property_binding& npb);
+std::vector<std::string> convert(const property_binding_vector& psv);
+
+OC::OCReflect::property_type as_property_type(const std::string& pt_rep);
+OC::OCReflect::property_binding as_property_binding(const std::string& pb_rep);
+OC::OCReflect::property_binding_vector as_property_binding_vector(const std::vector<std::string>& pb_reps);
char *flatten(const std::vector<std::string>& input, const std::string& delim = ";");
+std::vector<std::string> expand(const char *flattened_string, const std::string& delim = ";");
-}}} // namespace OC::OCReflect::to_OCStack
+}}} // namespace OC::OCReflect::OCStack
#endif
#include <string>
#include "OCObject.h"
+#include "OCPropertyTypes.h"
#include "OCSecurityModel.h"
-namespace OC { namespace OCReflect {
-
-struct method_binding;
-struct property_binding;
-
-}} // namespace OC::OCReflect
-
namespace OC
{
/**
*/
class OCServer
{
+ /* 1) It may be worth considering Boost's lock-free containers here;
+ 2) The only reason bindings rather than the "real things" are shown in this case is because of
+ an assumption that the real things lie within the C layer. In practice, there's no firm reason
+ why it needs to be one way or the other-- in fact, a pure C++ implementation might as well
+ just store all the actual methods and properties in one place: */
private:
- std::map<std::string, OC::OCReflect::method_binding> method_bindings;
+ std::map<std::string, OC::OCReflect::method_binding> method_bindings;
+ std::map<std::string, OC::OCReflect::property_binding> property_bindings;
public:
OCServer(void);
public:
void bind(const OC::OCReflect::method_binding& mb);
-
- void bind(const OC::OCReflect::property_binding& pb)
- {}
+ void bind(const OC::OCReflect::property_binding& pb);
template <class T>
void registerResource(T *object, const std::string& base_URI)
{}
+ // Note that these transfer the /binding information/ (signatures, etc.) not data (which could be /very/ expensive):
public:
- const std::map<std::string, OC::OCReflect::method_binding>& methods() const { return method_bindings; }
+ const std::map<std::string, OC::OCReflect::method_binding>& methods() const { return method_bindings; }
+ const std::map<std::string, OC::OCReflect::property_binding>& properties() const { return property_bindings; }
+
+ // Transfer data:
+ public:
+ // Look up the method from the binding, call the function, return a full property as result:
+ // OC::OCReflect::property call(const std::pair<std::string, OC::OCReflect::method_binding>& method); // other signatures possible, this is an example
+
+ // Look up the property from the binding, return a full property (ie. with a data value):
+ OC::OCReflect::property get(const std::string& p_name);
+ OC::OCReflect::property get(const OC::OCReflect::property_binding& pb);
+
+ // Set a property's value:
+ void set(const OC::OCReflect::property& p);
};
}
void registerResource( const std::string& resourceURI,
const std::string& resourceTypeName,
- named_property_binding_vector properties)
+ property_binding_vector properties)
{
}