8#ifndef CLASSDESC_RESTPROCESS_EPILOGUE_H
9#define CLASSDESC_RESTPROCESS_EPILOGUE_H
10#include "RESTProcess_base.h"
12#include "multiArray.h"
13#include "polyPackBase.h"
14#include "polyRESTProcess.h"
15#include "RESTProcess-allCDs.h"
28 void operator()(cd::RESTProcess_t& repo,
const std::string& d, U& a)
29 {repo.add(d,
new cd::RESTProcessObject<U>(a));}
32 template <
class F,
class S>
36 void operator()(cd::RESTProcess_t& repo,
const std::string& d, U& a)
38 RESTProcess(repo,d+
".first", a.first);
39 RESTProcess(repo,d+
".second", a.second);
45 public cd::NullDescriptor<cd::RESTProcess_t> {};
49 public cd::NullDescriptor<cd::RESTProcess_t> {};
53 public cd::NullDescriptor<cd::RESTProcess_t> {};
61 auto tn=typeName<T>();
62 return std::vector<Signature>{{
tn,{}},{
tn,{
tn}}};
68 auto tn=typeName<typename T::element_type>();
69 return {{
tn,{}},{
tn,{
tn}}};
75 auto tn=typeName<T>();
76 return {{
tn,{}},{
tn,{
tn}}};
82 auto tn=typeName<T>();
83 return {{
tn,{}},{
tn,{
tn}}};
89 auto tn=typeName<T>();
90 return {{
tn,{}},{
tn,{
tn}}};
96 return {{
"std::string",{}},{
"std::string",{
"std::string"}}};
100 std::vector<Signature> EnumerateEnumerators<E>::signature()
const
102 return {{
"vector<string>",{}}};
110 obj.RESTProcess(map,
"");
132 map.emplace(
".@elem", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessSequence<T>::elem)));
133 map.emplace(
".@elemNoThrow", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessSequence<T>::elemNoThrow)));
134 map.emplace(
".@erase", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessSequence<T>::eraseElem)));
135 map.emplace(
".@insert", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessSequence<T>::pushBack)));
136 map.emplace(
".@size", makeRESTProcessFunction(functional::bindMethod(obj,&T::size)));
144 map.emplace(
".@elem", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessAssociativeContainer<T>::elem)));
145 map.emplace(
".@elemNoThrow", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessAssociativeContainer<T>::elem)));
146 map.emplace(
".@insert", makeRESTProcessFunction(functional::bindMethod(*
this,&RESTProcessAssociativeContainer<T>::elem)));
148 map.emplace(
".@size", makeRESTProcessFunction(functional::bindMethod(obj,&T::size)));
157 template <class F, int N=functional::Arity<F>::value >
158 struct Args:
public std::vector<string>
160 Args(): std::vector<string>(Args<F,N-1>()) {
165 template <
class F>
struct Args<F,0>:
public std::vector<string> {};
171 return {typeName<typename functional::Return<F>::T>(),
Args<F>()};
180 typename enable_if<is_classdescGenerated<T>,
void>::T
181 RESTProcessp(RESTProcess_t& repo,
string d, T& obj)
184 if (!is_excluded<T>::value) repo.add(d,
new RESTProcessObject<T>(obj));
189 if (overloadedFunctions.empty())
return std::make_shared<RESTProcessVoid>();
190 auto bestOverload=overloadedFunctions.front();
191 auto bestScore=RESTProcessFunctionBase::maxMatchScore;
193 for (
auto& i: overloadedFunctions)
195 auto score=i->matchScore(arguments);
202 else if (score==bestScore)
205 if (bestOverload->matchScore(arguments) >=
206 RESTProcessFunctionBase::maxMatchScore)
207 throw std::runtime_error(
"No suitable matching overload found");
209 throw std::runtime_error(
"Ambiguous resolution of overloaded function");
210 return bestOverload->process(remainder, arguments);
214 RPPtr sequenceProcess(
T& obj,
const string& remainder,
const REST_PROCESS_BUFFER& arguments)
216 if (remainder.empty())
218 switch (arguments.type())
220 case RESTProcessType::null:
break;
221 case RESTProcessType::array:
223 auto& arr=arguments.array();
224 if (!arr.empty()) convert(obj, REST_PROCESS_BUFFER(arr[0]));
228 convert(obj, arguments);
233 else if (startsWith(remainder,
".@size"))
234 return makeRESTProcessValueObject(obj.size());
241 using iterator=
typename T::const_iterator;
245 using iterator=
typename T::iterator;
249 template <
class T> std::tuple<typename IteratorSelector<T,is_const<T>::value>::iterator, string::size_type>
250 elemImpl(
T& obj,
const string& remainder,
const REST_PROCESS_BUFFER& arguments)
253 assert(remainder.length()>2);
254 auto idxStart=remainder.find(
'.',1);
255 if (idxStart==string::npos)
256 throw std::runtime_error(
"no index");
257 auto idxEnd=remainder.find(
'.', idxStart+1);
258 if (idxEnd==string::npos) idxEnd=remainder.length();
259 size_t idx=stoi(remainder.substr(idxStart+1, idxEnd));
263 if (startsWith(remainder,
".@elemNoThrow"))
264 return {obj.end(),string::npos};
265 throw std::runtime_error(
"idx out of bounds");
268 std::advance(i,
idx);
274 if (startsWith(remainder,
".@elem"))
276 auto [i, idxEnd]=elemImpl(obj,remainder,arguments);
277 if (i==obj.end())
return std::make_shared<RESTProcessVoid>();
278 return mapAndProcess(remainder.substr(idxEnd), arguments, *i);
280 if (startsWith(remainder,
".@insert"))
282 insert(obj, arguments);
285 if (startsWith(remainder,
".@erase"))
287 erase(obj, arguments);
290 return sequenceProcess(obj,remainder,arguments);
295 if (startsWith(remainder,
".@elem"))
297 auto [i, idxEnd]=elemImpl(actual,remainder,arguments);
298 if (i==actual.end())
return std::make_shared<RESTProcessVoid>();
299 auto r=mapAndProcess(remainder.substr(idxEnd), arguments, *i);
300 if (idxEnd==remainder.length() && T::rank>1)
302 return copyMultiArrayIterator(*i);
305 return sequenceProcess(actual,remainder,arguments);
311 if (remainder.empty())
312 switch (arguments.type())
314 case RESTProcessType::null:
break;
315 case RESTProcessType::array:
317 auto& arr=arguments.array();
318 if (!arr.empty()) convert(obj, REST_PROCESS_BUFFER(arr[0]));
322 convert(obj, arguments);
325 else if (startsWith(remainder,
".@elem"))
328 auto keyStart=find(remainder.begin()+1, remainder.end(),
'.');
329 if (keyStart!=remainder.end())
332 auto keyEnd=keyStart;
333 typename T::key_type key;
334 if (strchr(
"\"'{[",*keyStart))
337 read_range(keyEnd,remainder.end(),
static_cast<json5_parser::mValue&
>(jsonKey));
342 keyEnd=find(keyStart, remainder.end(),
'.');
343 assignRawStringToKey(key, std::string(keyStart, keyEnd));
346 string tail(keyEnd,remainder.end());
347 if (tail.empty() && arguments.type()!=RESTProcessType::null)
349 auto i=obj.find(key);
352 if (startsWith(remainder,
".@elemNoThrow"))
353 return mapAndProcessDummy<typename T::value_type>(tail, arguments);
355 throw std::runtime_error(
"key "+std::string(keyStart, keyEnd)+
" not found");
357 else if (tail.empty())
358 return makeRESTProcessValueObject(elem_of(i));
360 return mapAndProcess(tail, arguments, eoi);
363 else if (startsWith(remainder,
".@insert"))
365 else if (startsWith(remainder,
".@erase"))
366 RPAC_erase(obj,arguments);
367 else if (startsWith(remainder,
".@size"))
368 return makeRESTProcessValueObject(obj.size());
369 else if (startsWith(remainder,
".@keys"))
371 std::vector<typename T::key_type>
keys;
374 return makeRESTProcessValueObject(std::move(
keys));
378 return std::make_shared<RESTProcessAssociativeContainer>(obj);
385 return rProcess(*ptr, remainder, arguments);
387 return std::make_shared<RESTProcessVoid>();
391 RPPtr EnumerateEnumerators<E>::process
392 (
const string& remainder,
const REST_PROCESS_BUFFER& arguments)
394 auto& enumerators=enum_keys<E>();
395 return makeRESTProcessValueObject(std::vector<string>(enumerators.sbegin(), enumerators.send()));
401 (
const string& remainder,
const REST_PROCESS_BUFFER& arguments)
403 if (
auto p=ptr.lock())
404 return rProcess(*p, remainder, arguments);
406 return std::make_shared<RESTProcessVoid>();
409 inline RPPtr RESTProcess_t::process(
const std::string& query,
const REST_PROCESS_BUFFER& jin)
413 if (cmd==
"@enum.@list")
415 std::vector<string> enums;
417 if (i.first.find(
"@enum")==0)
418 enums.push_back(i.first.substr(6));
419 return makeRESTProcessValueObject(std::move(enums));
422 for (
auto cmdEnd=query.length(); ;
423 cmdEnd=cmd.rfind(
'.'), cmd=cmd.substr(0,cmdEnd))
425 if (cmdEnd==string::npos)
430 auto tail=query.substr(cmdEnd);
437 throw std::runtime_error(
"Command not found: "+query);
441 if (tail==
".@signature")
442 return makeRESTProcessValueObject(r->second->signature());
443 else if (tail==
".@list")
445 auto map=r->second->list();
446 std::vector<string> array;
448 if (!i.first.empty())
449 array.emplace_back(i.first);
450 return makeRESTProcessValueObject(std::move(array));
452 else if (tail==
".@type")
453 return makeRESTProcessValueObject(r->second->type());
454 else if (cmdEnd ||
dynamic_cast<RESTProcessWrapperBase*
>(r->second.get()))
455 return r->second->process(tail, jin);
457 throw std::runtime_error(
"Command not found: "+query);
461 auto r=equal_range(cmd);
462 if (tail==
".@signature")
464 std::vector<Signature> array;
465 for (; r.first!=r.second; ++r.first)
467 auto sig=r.first->second->signature();
468 array.insert(array.end(), sig.begin(), sig.end());
470 return makeRESTProcessValueObject(std::move(array));
473 auto cmp=[&](RESTProcessFunctionBase*x, RESTProcessFunctionBase*y)
474 {
return x->matchScore(jin)<y->matchScore(jin);};
475 std::set<RESTProcessFunctionBase*,
decltype(cmp)> sortedOverloads{cmp};
476 for (
auto i=r.first; i!=r.second; ++i)
477 if (
auto j=
dynamic_cast<RESTProcessFunctionBase*
>(i->second.get()))
478 sortedOverloads.insert(j);
479 auto& bestOverload=*sortedOverloads.begin();
480 if (bestOverload->matchScore(jin) >=
481 RESTProcessFunctionBase::maxMatchScore)
482 throw std::runtime_error(
"No suitable matching overload found");
483 if (sortedOverloads.size()>1)
485 auto i=sortedOverloads.begin(); i++;
486 if ((*i)->matchScore(jin)==bestOverload->matchScore(jin))
487 throw std::runtime_error(
"Ambiguous resolution of overloaded function");
491 auto map=bestOverload->list();
492 std::vector<std::string> list;
494 if (!i.first.empty())
495 list.push_back(i.first);
496 return makeRESTProcessValueObject(list);
499 return makeRESTProcessValueObject(bestOverload->type());
500 return bestOverload->process(tail, jin);
507 RPPtr mapAndProcess(
const string& query,
const REST_PROCESS_BUFFER& arguments,
T& a)
514 return i->second->process(
"",arguments);
518 return map.process(query,arguments);
524 {classdesc_access::access_RESTProcess<T>()(r,
"",obj);}
530 template <
class T> RESTProcess_t::RESTProcess_t(
T&obj) {populateFromObj(*
this,obj);}
533 (
const string& typeName,
const std::function<
void(
const std::string& objName)>& callback)
535 std::function<void(
const std::string& name, A... args)> factory=
536 [
this,callback](
const std::string& name, A... args) {
537 auto rp=make_unique<RESTProcessHeapObject<T>>();
538 rp->obj=make_unique<T>(std::forward<A>(args)...);
539 add(name,rp.release());
552 {
return std::make_shared<RESTProcessObject<T>>(obj);}
558 Not<is_base_of<MultiArrayBase,T>>
561 {
return std::make_shared<RESTProcessSequence<T>>(obj);}
566 {
return std::make_shared<RESTProcessMultiArray<T>>(obj);}
571 {
return std::make_shared<RESTProcessPtr<T>>(obj);}
577#if defined(__cplusplus) && __cplusplus>=201103L
581 void operator()(cd::RESTProcess_t& r,
const cd::string& d,
const std::function<F>& a)
582 {r.add(d,
new cd::RESTProcessFunction<std::function<F>>(a));}
586#ifdef CLASSDESC_JSON_PACK_BASE_H
RPPtr keys() const override
returns a list of keys if this is an associative container, otherwise void
Definition RESTProcess_base.h:1019
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:309
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:141
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:87
void erase(const REST_PROCESS_BUFFER &index) override
erase an element - by position for sequences, by key for associative containers
Definition RESTProcess_base.h:1014
Signature functionSignature() const
return signature for a function type F
Definition RESTProcess_epilogue.h:169
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:94
Definition RESTProcess_base.h:1480
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:272
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:130
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:80
Definition json_pack_base.h:99
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
const T & keyOf(const T &x)
utility key extraction function for associative containers
Definition classdesc.h:526
std::string idx(const std::string &prefix, size_t i)
utility for generating index keys (for use with arrays)
Definition xml_common.h:14
enable_if< And< Not< is_const< T > >, is_pair< typenameT::value_type > >, void >::T assignElem(T &obj, const K &k, const REST_PROCESS_BUFFER &x)
assign x if T is a map
Definition RESTProcess_base.h:903
enable_if< And< Not< is_container< T > >, Not< is_smart_ptr< T > > >, RPPtr >::T makeRESTProcessRef(T &obj)
create an appropriate RESTProcess object referring to the argument.
Definition RESTProcess_epilogue.h:551
void RPAC_insert(T &obj, const REST_PROCESS_BUFFER &arguments)
insert element into an associative container
Definition RESTProcess_base.h:846
enable_if< Not< functional::is_nonmember_function_ptr< T > >, void >::T RESTProcess(RESTProcess_t &, const std::string &, T &)
descriptor for generating building REST processing registry
Definition RESTProcess_epilogue.h:177
Definition classdesc.h:420
Definition RESTProcess_epilogue.h:159
Definition RESTProcess_epilogue.h:238
Definition classdesc.h:405
helper for constructing null descriptors
Definition classdesc.h:1106
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:293
handle setting and getting of objects
Definition RESTProcess_base.h:449
std::string type() const override
return type name of this
Definition RESTProcess_epilogue.h:154
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:124
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:59
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:187
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:127
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:382
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:66
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:401
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:73
REST processor registry.
Definition RESTProcess_base.h:351
void addFactory(const std::string &typeName, const std::function< void(const std::string &objName)> &callback=nullptr)
Definition RESTProcess_epilogue.h:533
void add(string d, RESTProcessBase *rp)
ownership of rp is passed
Definition RESTProcess_base.h:360
Definition signature.h:18
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
determines if T is a container
Definition classdesc.h:358
Definition classdesc.h:571
Definition RESTProcess_base.h:1693