Classdesc 3.44
RESTProcess_base.h
1/*
2 @copyright Russell Standish 2019
3 @author Russell Standish
4 This file is part of Classdesc
5
6 Open source licensed under the MIT license. See LICENSE for details.
7*/
8
9#ifndef CLASSDESC_RESTPROCESS_BASE_H
10#define CLASSDESC_RESTPROCESS_BASE_H
12#include "function.h"
13#include "multiArray.h"
14#include "object.h"
15#include "polyRESTProcessBase.h"
16#include "signature.h"
17
18#include <map>
19#include <stdexcept>
20#include <string>
21#include <vector>
22#include <assert.h>
23
24#ifndef REST_PROCESS_BUFFER
25#include "json_pack_base.h"
26#define REST_PROCESS_BUFFER json_pack_t
27#endif
28
29namespace classdesc
30{
31 class RESTProcessBase;
32 using RPPtr=std::shared_ptr<RESTProcessBase>;
33
34 struct RESTProcess_t;
35
36 template <class T>
38 RESTProcess(RESTProcess_t&, const std::string&, T&);
39
42 {
43 protected:
45 template <class T> typename enable_if<is_base_of<object,T>, const object*>::T
46 getClassdescObjectImpl(T& obj) {return &obj;}
47 template <class T> typename enable_if<Not<is_base_of<object,T>>, const object*>::T
48 getClassdescObjectImpl(T& obj) {return nullptr;}
49 public:
50 virtual ~RESTProcessBase() {}
53 virtual RPPtr process(const string& path, const REST_PROCESS_BUFFER& arguments)=0;
54 virtual REST_PROCESS_BUFFER asBuffer() const=0;
56 virtual std::vector<Signature> signature() const=0;
58 virtual RESTProcess_t list() const=0;
60 virtual std::string type() const=0;
62 virtual void populate(RESTProcess_t& map) const {}
64 template <class F> Signature functionSignature() const;
66 template <class T> T* getObject();
68 virtual object* getClassdescObject() {return nullptr;}
69 virtual const object* getConstClassdescObject() {return nullptr;}
72 virtual bool isObject() const {return false;}
74 virtual bool isConst() const {return false;}
76 virtual unsigned arity() const {return 0;}
78 virtual size_t size() const {return 0; }
80 virtual RPPtr getElem(const REST_PROCESS_BUFFER&);
83 virtual RPPtr setElem(const REST_PROCESS_BUFFER& index, const REST_PROCESS_BUFFER& value)
84 {return getElem(index);}
85
86 virtual void insert(const REST_PROCESS_BUFFER& value) {}
88 virtual void erase(const REST_PROCESS_BUFFER& index) {}
90 virtual bool contains(const REST_PROCESS_BUFFER& key) const {return false;}
92 virtual RPPtr keys() const;
93 };
94
95
97 template <class T>
98 typename enable_if<
99 And<
100 Not<is_container<T>>,
101 Not<is_smart_ptr<T>>
102 >, RPPtr>::T makeRESTProcessRef(T& obj);
103
104 template <class T>
105 typename enable_if<
106 And<
107 is_sequence<T>,
108 Not<is_base_of<MultiArrayBase,T>>
109 >, RPPtr>::T
110 makeRESTProcessRef(T& obj);
111
112 template <class T>
113 typename enable_if<is_base_of<MultiArrayBase,T>, RPPtr>::T
114 makeRESTProcessRef(T& obj);
115
116 template <class T>
117 typename enable_if<is_smart_ptr<T>, RPPtr>::T
118 makeRESTProcessRef(T& obj);
120
123
124 // used to mark function types that can be overloaded
126 {
127 public:
128 // match score if argument match impossible
129 static const unsigned maxMatchScore=1000000;
130
131 virtual ~RESTProcessFunctionBase() {}
133 virtual unsigned matchScore(const REST_PROCESS_BUFFER& arguments) const=0;
134 REST_PROCESS_BUFFER asBuffer() const override {return {};}
135 };
136
138 {
139 std::vector<std::shared_ptr<RESTProcessFunctionBase>> overloadedFunctions;
140 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
141 REST_PROCESS_BUFFER asBuffer() const override {return {};}
142 std::vector<Signature> signature() const override {
143 std::vector<Signature> r;
144 for (auto& i: overloadedFunctions) {
145 auto s=i->signature();
146 r.insert(r.end(),s.begin(),s.end());
147 }
148 return r;
149 }
150 RESTProcess_t list() const override;
151 std::string type() const override {return "overloaded function";}
152 };
153
154 inline void convert(char& y, const string& x)
155 {
156 if (x.size()!=1)
157 throw std::runtime_error("can only assign a single character string to a character variable");
158 y=x[0];
159 }
160
161 inline void convert(const char* y, const string& x)
162 {
163 y=x.c_str();
164 }
165
166 template <class X, class Y>
168 convert(Y& y, const X& x)
169 {y=x;}
170
171 template <class X, class Y>
172 typename enable_if<And<Not<is_assignable<Y,X>>, is_convertible<X,Y>, std::is_move_assignable<Y>, Not<is_const<Y>>>, void>::T
173 convert(Y& y, const X& x)
174 {y=std::move(Y(x));}
175
176 template <class X, class Y>
177 typename enable_if<And<
179 Not<And<is_convertible<X,Y>, std::is_move_assignable<Y>>>,
182 >, void>::T
183 convert(Y& y, const X& x)
184 {throw std::runtime_error(typeName<X>()+" cannot be converted to "+typeName<Y>());}
185
186 template <class X, class Y>
187 void convert(const Y&, const X&)
188 {throw std::runtime_error("attempt to alter a const variable");}
189
190 template <class X>
191 typename enable_if<
192 And<
197 >, void>::T
198 convert(X& x, const REST_PROCESS_BUFFER& j)
199 {
200 switch (j.type())
201 {
202 case RESTProcessType::object:
203 j>>x;
204 break;
205 case RESTProcessType::array:
206 {
207 auto arr=j.array();
208 if (arr.size()>0)
209 REST_PROCESS_BUFFER(arr[0])>>x;
210 }
211 break;
212 case RESTProcessType::string:
213 {
214 string tmp;
215 j>>tmp;
216 convert(x,tmp);
217 }
218 break;
219 case RESTProcessType::boolean:
220 {
221 bool tmp{};
222 j>>tmp;
223 convert(x,tmp);
224 }
225 break;
226 case RESTProcessType::int_number:
227 {
228 int64_t tmp{};
229 j>>tmp;
230 convert(x,tmp);
231 }
232 break;
233 case RESTProcessType::float_number:
234 {
235 double tmp{};
236 j>>tmp;
237 convert(x,tmp);
238 }
239 break;
240 case RESTProcessType::null:
241 break;
242 }
243 }
244
245 template <class X>
246 typename enable_if<
247 And<
251 >, void>::T
252 convert(X& x, const REST_PROCESS_BUFFER& j)
253 {
254 if (j.type()==RESTProcessType::array)
255 {
256 auto arr=j.array();
257 resize(x, arr.size());
258 auto xi=x.begin();
259 for (auto& ai: arr)
260 {
261 if (xi==x.end()) break;
262 REST_PROCESS_BUFFER(ai) >> *xi++;
263 }
264 }
265 }
266
267 template <class T,int R>
268 void convert(MultiArray<T,R>& x, const REST_PROCESS_BUFFER& j)
269 {
270 if (j.type()==RESTProcessType::array)
271 {
272 auto arr=j.array();
273 auto xi=x.begin();
274 for (auto& ai: arr)
275 {
276 if (xi==x.end()) break;
277 auto target=*xi++;
278 convert(target, REST_PROCESS_BUFFER(ai));
279 }
280 }
281 }
282
283 template <class T>
284 void convert(MultiArray<T,1>& x, const REST_PROCESS_BUFFER& j)
285 {
286 if (j.type()==RESTProcessType::array)
287 {
288 auto arr=j.array();
289 auto xi=x.begin();
290 for (auto& ai: arr)
291 {
292 if (xi==x.end()) break;
293 REST_PROCESS_BUFFER(ai) >> *xi++;
294 }
295 }
296 }
297
298 template <class X>
300 convert(X& x, const REST_PROCESS_BUFFER& j)
301 {
302 switch (j.type())
303 {
304 case RESTProcessType::array:
305 {
306 auto arr=j.array();
307 x.clear();
308 for (auto& ai: arr)
309 {
310 typename X::value_type v;
311 REST_PROCESS_BUFFER(ai) >> v;
312 x.insert(v);
313 }
314 }
315 break;
316 case RESTProcessType::object: // special case for StringKeys
317 j>>x;
318 break;
319 default: break;
320 }
321 }
322
323 template <class X>
324 void convert(std::shared_ptr<X>& x, const REST_PROCESS_BUFFER& j)
325 {
326 if (x) convert(*x,j);
327 }
328
329 template <class X>
330 void convert(std::weak_ptr<X>& x, const REST_PROCESS_BUFFER& j)
331 {
332 if (auto s=x.lock()) convert(*s,j);
333 }
334
335 template <class E>
336 typename enable_if<And<is_enum<E>,Not<is_const<E>>>, void>::T
337 convert(E& x, const REST_PROCESS_BUFFER& j)
338 {
339 string tmp; j>>tmp;
340 x=enum_keys<E>()(tmp);
341 }
342
343 template <class X>
344 void convert(const X* x, const REST_PROCESS_BUFFER& j)
345 {}
346
347 template <class F, int N> struct DefineFunctionArgTypes;
348
350 struct RESTProcess_t: public std::map<std::string, RPPtr >
351 {
352 RESTProcess_t()=default;
356 template <class T> RESTProcess_t(T& obj);
358 RESTProcess_t(const RPPtr& p) {p->populate(*this);}
360 void add(string d, RESTProcessBase* rp)
361 {
362 // for objects, ensure any previous entries of this key are deleted
363 erase(d);
364 emplace(d,rp);
365 }
366
367 void add(string d, RESTProcessFunctionBase* rp)
368 {
369 auto i=find(d);
370 if (i==end())
371 emplace(d,rp);
372 else if (auto functions=dynamic_cast<RESTProcessOverloadedFunction*>(i->second.get()))
373 {
374 // replace if signature the same
375 for (auto& f: functions->overloadedFunctions)
376 if (f->signature()==rp->signature())
377 {
378 i->second.reset(rp);
379 return;
380 }
381 functions->overloadedFunctions.emplace_back(rp);
382 }
383 else if (auto firstFunction=dynamic_pointer_cast<RESTProcessFunctionBase>(i->second))
384 {
385 // replace if signature the same
386 if (firstFunction->signature()==rp->signature())
387 {
388 i->second.reset(rp);
389 return;
390 }
391 auto functs=std::make_shared<RESTProcessOverloadedFunction>();
392 if (firstFunction) functs->overloadedFunctions.push_back(std::move(firstFunction));
393 functs->overloadedFunctions.emplace_back(rp);
394 i->second=functs;
395 }
396 else // overloading something that is not a function
397 i->second.reset(rp);
398 }
399
400 inline RPPtr process(const std::string& query, const REST_PROCESS_BUFFER& jin);
401
403 template <class F> void defineFunctionArgTypes()
404 {
406 }
407
417 template <class T, class... Args> void addFactory
418 (const std::string& typeName,const std::function<void(const std::string& objName)>& callback=nullptr);
419 };
420
421 template <class T>
422 RPPtr mapAndProcess(const string& query, const REST_PROCESS_BUFFER& arguments, T& a);
423
424 template <class T>
425 inline typename enable_if<is_default_constructible<T>,RPPtr>::T
426 mapAndProcessDummy(const string& query, const REST_PROCESS_BUFFER& arguments)
427 {
428 T dummy{};
429 return mapAndProcess(query,arguments,dummy);
430 }
431
432 template <class T>
433 inline typename enable_if<Not<is_default_constructible<T>>,RPPtr>::T
434 mapAndProcessDummy(const string& query, const REST_PROCESS_BUFFER& arguments)
435 {
436 throw std::runtime_error(typeName<T>()+" is not default constructible, but requested element doesn't exist");
437 }
438
439 template <class T> struct RESTProcessObject;
440 template <class T> inline
441 typename enable_if<is_copy_constructible<T>,RPPtr>::T
442 toObjectValueImpl(const RESTProcessObject<T>&);
443 template <class T> inline
445 toObjectValueImpl(const RESTProcessObject<T>&) {return nullptr;}
446
448 template <class T> struct RESTProcessObject: public RESTProcessBase
449 {
450 T& obj;
451 RESTProcessObject(T& obj): obj(obj) {}
452 std::shared_ptr<classdesc::RESTProcessBase> process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override
453 {
454 if (remainder.empty())
455 {
456 switch (arguments.type())
457 {
458 case RESTProcessType::null: break;
459 case RESTProcessType::array:
460 {
461 auto& arr=arguments.array();
462 if (!arr.empty()) convert(obj, REST_PROCESS_BUFFER(arr[0]));
463 break;
464 }
465 default:
466 convert(obj, arguments);
467 break;
468 }
469 return std::make_shared<RESTProcessObject>(obj);
470 }
471 return mapAndProcess(remainder, arguments, obj);
472 }
473 REST_PROCESS_BUFFER asBuffer() const override {REST_PROCESS_BUFFER r; return r<<obj;}
474 std::vector<Signature> signature() const override;
475 RESTProcess_t list() const override;
476 std::string type() const override;
477 void populate(RESTProcess_t& map) const override {RESTProcess(map,"",obj);}
478 object* getClassdescObject() override {
479 if (is_const<T>::value) return nullptr;
480 return const_cast<object*>(getClassdescObjectImpl(obj));
481 }
482 bool isObject() const override {return true;}
483 const object* getConstClassdescObject() override {return getClassdescObjectImpl(obj);}
484 bool isConst() const override {return std::is_const<T>::value;}
485 size_t size() const override {
486 if constexpr (is_class<T>::value)
487 if constexpr (has_size<T>::value)
488 return obj.size();
489 return 0;
490 }
491 RPPtr getElem(const REST_PROCESS_BUFFER& b) override {
492 if constexpr (is_class<T>::value)
493 if constexpr (has_index_operator<T>::value)
494 {
495 size_t index; b>>index;
496 return makeRESTProcessRef(obj[index]);
497 }
498 return RESTProcessBase::getElem(b);
499 }
500
502 RPPtr setElem(const REST_PROCESS_BUFFER& b, const REST_PROCESS_BUFFER& value) override
503 {
504 if constexpr (is_class<T>::value && !is_const<T>::value)
505 if constexpr (has_index_operator<T>::value)
506 {
507 size_t index; b>>index;
508 value>>obj[index];
509 return makeRESTProcessRef(obj[index]);
510 }
511 return RESTProcessBase::setElem(b,value);
512 }
513
514
515 };
516
518 template <class T> struct RESTProcessValueObject: public RESTProcessObject<T>
519 {
520 T actual;
521 public:
522 template <class... Args>
523 RESTProcessValueObject(Args&&... args): RESTProcessObject<T>(actual), actual(std::forward<Args>(args)...) {}
524 };
525
526 template <class T> inline
528 toObjectValueImpl(const RESTProcessObject<T>& x)
529 {return std::make_shared<RESTProcessValueObject<T>>(x.obj);}
530
531 template <class T>
532 RPPtr makeRESTProcessValueObject(T&& obj)
533 {return std::make_shared<RESTProcessValueObject<typename std::remove_reference<T>::type>>(std::forward<T>(obj));}
534 // specialization for string and string vector to allow
535 inline RPPtr makeRESTProcessValueObject(const char* s)
536 {return std::make_shared<RESTProcessValueObject<std::string>>(s);}
537 inline RPPtr makeRESTProcessValueObject(const std::initializer_list<std::string>& init)
538 {return std::make_shared<RESTProcessValueObject<std::vector<std::string>>>(init);}
539
542 {
543 std::shared_ptr<RESTProcessBase> process(const string&, const REST_PROCESS_BUFFER&) override
544 {return std::make_shared<RESTProcessVoid>();}
545 REST_PROCESS_BUFFER asBuffer() const override {return {};}
546 std::vector<Signature> signature() const override {return {};}
547 RESTProcess_t list() const override {return {};}
548 std::string type() const override {return "void";}
549 bool isConst() const override {return true;}
550 };
551
552 inline RPPtr RESTProcessBase::getElem(const REST_PROCESS_BUFFER&)
553 {return std::make_shared<RESTProcessVoid>();}
554
555 inline RPPtr RESTProcessBase::keys() const
556 {return std::make_shared<RESTProcessVoid>();}
557
558 template <class T> T* RESTProcessBase::getObject()
559 {
560 if (auto p=dynamic_cast<RESTProcessObject<T>*>(this))
561 return &p->obj;
562 else
563 return nullptr;
564 }
565
566 template <class T>
568 public And<
569 is_class<T>,
570 Not<is_container<T>>,
571 Not<is_smart_ptr<T>>,
572 Not<is_string<T>>,
573 Not<is_excluded<T>>
574 > {};
575
576
577 template <class T>
578 typename enable_if<is_excluded<T>,void>::T
579 RESTProcessp(RESTProcess_t& repo, const string& d, T& a)
580 {}
581
582 template <class T>
583 typename enable_if<Or<is_fundamental<T>,is_string<T>>, void>::T
584 RESTProcessp(RESTProcess_t& repo, const string& d, T& a)
585 {repo.emplace(d, makeRESTProcessRef(a));}
586
587 template <class T>
588 void RESTProcessp(RESTProcess_t& repo, const string& d, T* a)
589 {/* pointers ignored */}
590
591 template <class T>
592 void RESTProcess(RESTProcess_t& repo, const string& d, is_const_static, T& a)
593 {RESTProcess(repo,d,a);}
594
595 template <class T>
596 void RESTProcess(RESTProcess_t& r, const string& d, is_const_static, T* a)
597 {RESTProcess(r,d,*a);}
598
599 inline bool startsWith(const std::string& x, const std::string& prefix)
600 {return x.size()>=prefix.size() && equal(prefix.begin(), prefix.end(), x.begin());}
601
602 template <class U>
604 dummyRef() {
605 static U dummy{};
606 return dummy;
607 }
608
609 template <class U>
611 dummyRef() {
612 throw std::runtime_error(typeName<U>()+" is not default constructible, but requested element doesn't exist");
613 }
614
615 // sequences
616 template <class T> class RESTProcessSequence: public RESTProcessWrapperBase
617 {
618 T& obj;
619
620 template <class U>
621 struct Insertable: public
622 And<
623 And<
624 has_member_push_back<T,void (T::*)(const typename T::value_type&)>,
625 is_default_constructible<typename T::value_type>>,
626 Not<is_const<U>>> {};
627
628 template <class U>
629 typename enable_if<Insertable<U>, void>::T
630 insert(U& o, const REST_PROCESS_BUFFER& j) {
631 typename U::value_type v;
632 convert(v,j);
633 push_back(o,v);
634 }
635
636 template <class U>
637 typename enable_if<Not<Insertable<U> >, void>::T insert(U&, const REST_PROCESS_BUFFER&)
638 {
639 throw std::runtime_error("cannot insert into this sequence");
640 }
641
642 template <class U>
643 struct Erasable: public
644 And<
645 Or<
646 has_member_erase<T,typename T::iterator (T::*)(typename T::iterator)>,
647 has_member_erase<T,typename T::iterator (T::*)(typename T::const_iterator)>
648 >,
649 Not<is_const<U>>> {};
650
651
652 template <class U>
653 typename enable_if<Erasable<U>,void>::T
654 erase(U& seq, const REST_PROCESS_BUFFER& j)
655 {
656 size_t idx{}; convert(idx,j);
657 if (idx<seq.size())
658 {
659 auto i=seq.begin();
660 std::advance(i, idx);
661 seq.erase(i);
662 }
663 }
664
665 template <class U>
666 typename enable_if<Not<Erasable<U>>,void>::T
667 erase(U& seq, const REST_PROCESS_BUFFER& j)
668 {
669 throw std::runtime_error("cannot erase from this sequence");
670 }
671
672 // common element extraction code - assumes index is in bounds
673 typename transfer_const<T, typename T::value_type>::type& elemCommon(size_t idx) {
674 auto i=obj.begin();
675 std::advance(i, idx);
676 return *i;
677 }
678
679 typename transfer_const<T, typename T::value_type>::type& elemNoThrow(size_t idx) {
680 if (idx<obj.size()) return elemCommon(idx);
681 return dummyRef<typename T::value_type>();
682 }
683
684 void pushBack(const typename T::value_type& v) {
685 push_back(obj, v);
686 }
687
688 template <class U>
689 typename enable_if<has_member_erase<U,typename U::iterator(U::*)(typename U::const_iterator)>,void>::T
690 erase(U& o,typename U::iterator i) {o.erase(i);}
691
692 template <class U>
694 erase(U& o,typename U::const_iterator i) {}
695
696 template <class U>
697 typename enable_if<Not<has_member_erase<U,typename U::iterator(U::*)(typename U::const_iterator)>>,void>::T
698 erase(U& o,typename U::iterator i) {}
699
700
701 void eraseElem(size_t idx) {
702 if (idx>=size()) return;
703 auto i=obj.begin();
704 std::advance(i, idx);
705 erase(obj,i);
706 }
707
708
709 protected:
711 if (idx<obj.size()) return elemCommon(idx);
712 throw std::runtime_error("idx out of bounds");
713 }
714
715
716 public:
717 RESTProcessSequence(T& obj): obj(obj) {}
718 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
719 std::vector<Signature> signature() const override;
720 RESTProcess_t list() const override;
721 std::string type() const override {return typeName<T>();}
722 REST_PROCESS_BUFFER asBuffer() const override {REST_PROCESS_BUFFER r; return r<<obj;}
723 bool isObject() const override {return true;}
724 RPPtr getElem(const REST_PROCESS_BUFFER& index) override {
725 size_t idx; index>>idx;
726 return makeRESTProcessRef(elem(idx));
727 }
728 RPPtr setElem(const REST_PROCESS_BUFFER& index, const REST_PROCESS_BUFFER& value) override {
729 size_t idx; index>>idx;
730 auto& v=elem(idx);
731 value>>v;
732 return makeRESTProcessRef(v);
733 }
734 size_t size() const override {return obj.size();}
735 void insert(const REST_PROCESS_BUFFER& value) override {insert(obj,value);}
736 void erase(const REST_PROCESS_BUFFER& index) override {
737 size_t idx; index>>idx;
738 eraseElem(idx);
739 }
740 };
741
742 template <class T> struct RESTProcessValueSequence: public RESTProcessSequence<T>
743 {
744 T actual;
745 public:
746 template <class... Args>
747 RESTProcessValueSequence(Args&&... args): RESTProcessSequence<T>(actual), actual(std::forward<Args>(args)...) {}
748 };
749
750 template <class T, int R> RPPtr copyMultiArrayIterator(MultiArray<T,R>& x);
751 template <class T, int R> RPPtr copyMultiArrayIterator(const MultiArray<T,R>& x);
752
753 template <class T> RPPtr copyMultiArrayIterator(T& x)
754 {return std::make_shared<RESTProcessObject<T>>(x);}
755
756 template <class T> struct RESTProcessMultiArray: public RESTProcessBase
757 {
758 T actual;
759 public:
760 template <class... Args>
761 RESTProcessMultiArray(Args&&... args): actual(std::forward<Args>(args)...) {}
762 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
763 REST_PROCESS_BUFFER asBuffer() const override {
764 REST_PROCESS_BUFFER r;
765 return r<<actual;
766 }
767 std::vector<Signature> signature() const override {return {};}
768 RESTProcess_t list() const override {return {};}
769 std::string type() const override {return "typeName<T>()";}
770 bool isObject() const override {return true;}
771 RPPtr getElem(const REST_PROCESS_BUFFER& index) override {
772 size_t idx; index>>idx;
773 if (idx<actual.size())
774 return copyMultiArrayIterator(actual[idx]);
775 return std::make_shared<RESTProcessVoid>();
776 }
777 RPPtr setElem(const REST_PROCESS_BUFFER& index, const REST_PROCESS_BUFFER& value) override {
778 size_t idx; index>>idx;
779 if (idx<actual.size())
780 {
781 auto elem=actual[idx];
782 convert(elem,value);
783 return copyMultiArrayIterator(elem);
784 }
785 return std::make_shared<RESTProcessVoid>();
786 }
787 size_t size() const override {return actual.size();}
788 };
789
790 template <class T, int R> RPPtr copyMultiArrayIterator(MultiArray<T,R>& x)
791 {return std::make_shared<RESTProcessMultiArray<MultiArray<T,R>>>(x);}
792 template <class T, int R> RPPtr copyMultiArrayIterator(const MultiArray<T,R>& x)
793 {return std::make_shared<RESTProcessMultiArray<MultiArray<T,R>>>(x);}
794
795 template <class T> struct RESTProcessMultiArray<classdesc::MultiArray<T,1>>:
796 public RESTProcessSequence<classdesc::MultiArray<T,1>>
797 {
798 MultiArray<T,1> actual;
799 public:
800 template <class... Args>
801 RESTProcessMultiArray(Args&&... args): RESTProcessSequence<classdesc::MultiArray<T,1>>(actual), actual(std::forward<Args>(args)...) {}
802 RPPtr getElem(const REST_PROCESS_BUFFER& index) {
803 size_t idx; index>>idx;
804 return std::make_shared<RESTProcessObject<T>>(this->elem(idx));
805 }
806 RPPtr setElem(const REST_PROCESS_BUFFER& index, const REST_PROCESS_BUFFER& value) {
807 size_t idx; index>>idx;
808 auto& v=this->elem(idx);
809 value>>v;
810 return std::make_shared<RESTProcessObject<T>>(v);
811 }
812 size_t size() const override {return actual.size();}
813 };
814
815
816
817 template <class T>
818 typename enable_if<
819 And<
820 is_sequence<T>,
821 Not<is_base_of<MultiArrayBase,T>>
822 >, void>::T
823 RESTProcessp(RESTProcess_t& repo, const string& d, T& a)
824 {repo.add(d, new RESTProcessSequence<T>(a));}
825
826 template <class T>
828 RESTProcessp(RESTProcess_t& repo, const string& d, T& a)
829 {repo.add(d, new RESTProcessValueSequence<T>(a));}
830
832 template <class T>
834 {
835 typedef typename std::remove_const<T>::type type;
836 };
837
838 template <class K, class V>
839 struct MutableValueType<std::pair<const K, V> >
840 {
841 typedef std::pair<K, V> type;
842 };
843
845 template <class T>
846 void RPAC_insert(T& obj, const REST_PROCESS_BUFFER& arguments)
847 {
848 typename MutableValueType<typename T::value_type>::type v;
849 convert(v,arguments);
850 if (!obj.insert(v).second)
851 throw std::runtime_error("key already exists, not inserted");
852 }
853
855 template <class T>
856 void RPAC_insert(const T&, const REST_PROCESS_BUFFER& argument)
857 {
858 throw std::runtime_error("cannot insert data into a constant container");
859 }
860
861 template <class T>
862 void RPAC_erase(T& obj, const REST_PROCESS_BUFFER& arguments)
863 {
864 typename T::key_type k;
865 convert(k,arguments);
866 obj.erase(k);
867 }
868
870 template <class T>
871 void RPAC_erase(const T&, const REST_PROCESS_BUFFER& argument)
872 {
873 throw std::runtime_error("cannot erase data from a constant container");
874 }
875
876 template <class U>
877 inline typename enable_if<is_fundamental<U>, void>::T
878 assignRawStringToKey(U& key, const std::string& x)
879 {
880 std::istringstream is(x); is>>key;
881 }
882
883 template <class U>
884 inline typename enable_if<Not<is_fundamental<U>>, void>::T
885 assignRawStringToKey(U& key, const std::string& x)
886 {
887 throw std::runtime_error("key "+x+" needs to be JSON encoded");
888 }
889
890 template <>
891 inline void assignRawStringToKey(std::string& key, const std::string& x)
892 {
893 key=x;
894 }
895
897 template <class T,class K>
898 typename enable_if<
899 And<
902 >, void>::T
903 assignElem(T& obj, const K& k, const REST_PROCESS_BUFFER& x)
904 {
905 auto iter=obj.emplace(k, typename T::mapped_type()).first;
906 convert(iter->second,x);
907 }
908
910 template <class T,class K>
911 typename enable_if<
912 And<
913 Not<is_const<T>>,
914 Not<is_pair<typename T::value_type>>
915 >, void>::T
916 assignElem(T& obj, const K& k,const REST_PROCESS_BUFFER& x)
917 {
918 bool v; x>>v;
919 if (v)
920 obj.insert(k);
921 else
922 obj.erase(k);
923 }
924
925 template <class T,class K>
926 typename enable_if<is_const<T>, void>::T
927 assignElem(T& obj, const K& k,const REST_PROCESS_BUFFER& x) {}
928
929 template <class T, class Enable=void> struct MappedType;
930 template <class T> struct MappedType // for maps
931 <T, typename enable_if<is_pair<typename T::value_type>, void>::T>
932 {
933 using type=typename transfer_const<
934 T,
935 typename T::value_type::second_type,
936 Or<is_const<T>, is_const<typename T::value_type>,
937 is_const<typename T::value_type::second_type>>::value
938 >::type;
939 };
940
941 template <class T> struct MappedType // for sets
942 <T, typename enable_if<Not<is_pair<typename T::value_type>>, void>::T>
943 {using type=const typename T::value_type;};
944
945
946 template <class T>
947 typename enable_if<is_pair<typename T::value_type>, typename T::value_type>::T
948 makeElement(const typename T::key_type& k) {return {k,{}};}
949 template <class T>
950 typename enable_if<Not<is_pair<typename T::value_type>>, typename T::value_type>::T
951 makeElement(const typename T::key_type& k) {return k;}
952
953 template <class T> class RESTProcessAssociativeContainer: public RESTProcessWrapperBase
954 {
955 T& obj;
956
958 template <class I>
959 typename enable_if<
961 // in C++20, std::iterator_traits<I>::value_type has any const
962 // attribute stripped off, hence this convoluted mouthful
963 typename transfer_const<
964 typename std::remove_reference<
965 typename std::iterator_traits<I>::reference
966 >::type,
967 typename std::iterator_traits<I>::value_type::second_type
968 >::type&
969 >::T
970 elem_of(const I& i) const {return i->second;}
971
973 template <class I>
975 const typename std::iterator_traits<I>::value_type&>::T
976 elem_of(const I& i) const {return *i;}
977
978 template <class U>
979 typename enable_if<Not<is_const<U>>, typename MappedType<U>::type&>::T elemImpl(const typename U::key_type& k)
980 {return elem_of(obj.emplace(makeElement<T>(k)).first);}
981
982 template <class U>
983 typename enable_if<is_const<U>, typename MappedType<U>::type&>::T elemImpl(const typename U::key_type& k)
984 {
985 auto i=obj.find(k);
986 if (i==obj.end()) return dummyRef<typename MappedType<U>::type>();
987 return elem_of(i);
988 }
989
990 typename MappedType<T>::type& elem(const typename T::key_type& k)
991 {return elemImpl<T>(k);}
992
993
994 public:
995 RESTProcessAssociativeContainer(T& obj): obj(obj) {}
996 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
997 std::vector<Signature> signature() const override;
998 RESTProcess_t list() const override;
999 std::string type() const override {return typeName<T>();}
1000 REST_PROCESS_BUFFER asBuffer() const override {REST_PROCESS_BUFFER r; return r<<obj;}
1001 bool isObject() const override {return true;}
1002 RPPtr getElem(const REST_PROCESS_BUFFER& index) override {
1003 typename T::key_type idx; index>>idx;
1004 return makeRESTProcessRef(elem(idx));
1005 }
1006 RPPtr setElem(const REST_PROCESS_BUFFER& index, const REST_PROCESS_BUFFER& value) override {
1007 typename T::key_type idx; index>>idx;
1008 auto& v=elem(idx);
1009 value>>v;
1010 return makeRESTProcessRef(v);
1011 }
1012 size_t size() const override {return obj.size();}
1013 void insert(const REST_PROCESS_BUFFER& value) override {RPAC_insert(obj,value);}
1014 void erase(const REST_PROCESS_BUFFER& index) override {RPAC_erase(obj,index);}
1015 bool contains(const REST_PROCESS_BUFFER& index) const override {
1016 typename T::key_type k; convert(k,index);
1017 return obj.count(k);
1018 }
1019 RPPtr keys() const override {
1020 std::vector<typename T::key_type> k;
1021 for (auto& i: obj)
1022 k.emplace_back(keyOf(i));
1023 return makeRESTProcessValueObject(std::move(k));
1024 }
1025 };
1026
1027 template <class T> struct RESTProcessValueAssociativeContainer: public RESTProcessAssociativeContainer<T>
1028 {
1029 T actual;
1030 public:
1031 template <class... Args>
1032 RESTProcessValueAssociativeContainer(Args&&... args):
1033 RESTProcessAssociativeContainer<T>(actual), actual(std::forward<Args>(args)...) {}
1034 };
1035
1036 template <class T>
1038 RESTProcessp(RESTProcess_t& repo, const string& d, T& a)
1039 {
1041 }
1042
1043 template <class T>
1044 typename enable_if<is_base_of<PolyRESTProcessBase, T>, RESTProcess_t>::T
1045 rMap(T& x) {
1046 RESTProcess_t r;
1047 x.RESTProcess(r,"");
1048 return r;
1049 }
1050
1051 template <class T>
1053 rMap(T& x) {
1054 RESTProcess_t r;
1055 RESTProcess(r,"",x);
1056 return r;
1057 }
1058
1059 template <class T>
1060 struct RESTProcessPtr: public RESTProcessWrapperBase
1061 {
1062 T& ptr;
1063 RESTProcessPtr(T& ptr): ptr(ptr) {}
1064 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
1065 std::vector<Signature> signature() const override;
1066 RESTProcess_t list() const override {
1067 if (ptr)
1068 return rMap(*ptr);
1069 else
1070 return {};
1071 }
1072 std::string type() const override {return typeName<T>();}
1073 object* getClassdescObject() override {
1074 if (!ptr || is_const<typename T::element_type>::value) return nullptr;
1075 return const_cast<object*>(getClassdescObjectImpl(*ptr));
1076 }
1077 const object* getConstClassdescObject() override {return ptr? getClassdescObjectImpl(*ptr): nullptr;}
1078 REST_PROCESS_BUFFER asBuffer() const override {
1079 REST_PROCESS_BUFFER r;
1080 return ptr? (r<<*ptr): r;
1081 }
1082 bool isObject() const override {return true;}
1083 };
1084
1085 template <class T>
1086 struct RESTProcessWeakPtr: public RESTProcessWrapperBase
1087 {
1088 T& ptr;
1089 RESTProcessWeakPtr(T& ptr): ptr(ptr) {}
1090 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
1091 std::vector<Signature> signature() const override;
1092 RESTProcess_t list() const override {
1093 if (auto p=ptr.lock())
1095 return {};
1096 }
1097 std::string type() const override {return typeName<std::weak_ptr<T> >();}
1098 object* getClassdescObject() override {
1099 auto p=ptr.lock();
1100 if (!p || is_const<typename T::element_type>::value) return nullptr;
1101 return const_cast<object*>(getClassdescObjectImpl(*p));
1102 }
1103 const object* getConstClassdescObject() override {
1104 auto p=ptr.lock();
1105 return p? getClassdescObjectImpl(*p): nullptr;
1106 }
1107 REST_PROCESS_BUFFER asBuffer() const override {
1108 REST_PROCESS_BUFFER r;
1109 auto p=ptr.lock();
1110 return p? (r<<*p): r;
1111 }
1112 bool isObject() const override {return true;}
1113 };
1114
1115
1116 template <class T>
1117 struct RESTProcessPtr<classdesc::weak_ptr<T>>: public RESTProcessWeakPtr<classdesc::weak_ptr<T>>
1118 {RESTProcessPtr(classdesc::weak_ptr<T>& x): RESTProcessWeakPtr<classdesc::weak_ptr<T>>(x) {}};
1119
1120 template <class T>
1121 struct RESTProcessPtr<const classdesc::weak_ptr<T>>: public RESTProcessWeakPtr<const classdesc::weak_ptr<T>>
1122 {RESTProcessPtr(const classdesc::weak_ptr<T>& x): RESTProcessWeakPtr<const classdesc::weak_ptr<T>>(x) {}};
1123
1124
1125 // buffer adaptor for a vector of REST_PROCESS_BUFFER objects
1126 class JSONBuffer
1127 {
1128 std::vector<REST_PROCESS_BUFFER> values;
1129 std::vector<REST_PROCESS_BUFFER>::iterator it;
1130 public:
1131 JSONBuffer(const REST_PROCESS_BUFFER& j) {
1132 if (j.type()==RESTProcessType::array)
1133 for (auto& i: j.array())
1134 values.push_back(REST_PROCESS_BUFFER(i));
1135 else if (j.type()!=RESTProcessType::null)
1136 values.push_back(j);
1137 it=values.begin();
1138 }
1139 JSONBuffer(const JSONBuffer& x): values(x.values), it(values.begin()+(x.it-x.values.begin())) {}
1140 JSONBuffer& operator=(const JSONBuffer& x) {
1141 values=x.values;
1142 it=values.begin()+(x.it-x.values.begin());
1143 return *this;
1144 }
1145 template <class T>
1146 JSONBuffer& operator>>(T& x) {
1147 if (it<values.end()) (*it++) >> x;
1148 return *this;
1149 }
1150 template <class T>
1151 JSONBuffer& operator>>(const T& x) {
1152 if (it<values.end()) ++it;
1153 return *this;
1154 }
1155 };
1156
1157 template <class F>
1158 typename enable_if<
1160 is_reference<typename functional::Return<F>::T>>,
1161 RPPtr>::T
1162 callFunction(const string& remainder, const REST_PROCESS_BUFFER& arguments, F f)
1163 {
1164 JSONBuffer argBuf(arguments);
1165 auto& r=functional::callOnBuffer(argBuf,f);
1166 if (remainder.empty())
1167 {
1168 // if there are arguments left over, assign the first of the
1169 // remaining arguments to the result
1170 switch (arguments.type())
1171 {
1172 case RESTProcessType::null: break;
1173 case RESTProcessType::array:
1174 {
1175 auto arr=arguments.array();
1176 if (arr.size()>functional::Arity<F>::value)
1177 convert(r,REST_PROCESS_BUFFER(arr[functional::Arity<F>::value]));
1178 break;
1179 }
1180 default:
1181 if (functional::Arity<F>::value==0)
1182 convert(r,arguments);
1183 break;
1184 }
1185 return std::make_shared<RESTProcessObject<typename functional::Return<F>::T>>(r);
1186 }
1187 RESTProcess_t map;
1188 RESTProcess(map,"",r);
1189 return map.process(remainder, arguments);
1190 }
1191
1192 template <class F>
1193 typename enable_if<
1195 And<
1198 RPPtr>::T
1199 callFunction(const string& remainder, const REST_PROCESS_BUFFER& arguments, F f)
1200 {
1201 JSONBuffer argBuf(arguments);
1202 auto r=functional::callOnBuffer(argBuf,f);
1203 if (remainder.empty())
1204 return makeRESTProcessValueObject(std::move(r));
1205 RESTProcess_t map;
1206 RESTProcess(map,"",r);
1207 return map.process(remainder, arguments);
1208 }
1209
1210 template <class F>
1211 typename enable_if<
1213 is_void<typename functional::Return<F>::T>>,
1214 RPPtr>::T
1215 callFunction(const string& remainder, const REST_PROCESS_BUFFER& arguments, F f)
1216 {
1217 JSONBuffer argBuf(arguments);
1218 functional::callOnBuffer(argBuf,f);
1219 return std::make_shared<RESTProcessVoid>();
1220 }
1221
1222
1223 // don't do anything if we cannot create or copy an argument
1224 template <class F>
1226 callFunction(const string& remainder, const REST_PROCESS_BUFFER& arguments, F f)
1227 {throw std::runtime_error("cannot call this function");}
1228
1231
1232 template <class T, class V>
1234 matches(const V& x)
1235 {return false;}
1236
1237 template <class T, class V>
1238 typename enable_if<is_same<T,bool>,bool>::T
1239 matches(const V& x)
1240 {return x.type()==RESTProcessType::boolean;}
1241
1242 template <class T>
1243 typename enable_if<is_same<T,string>,bool>::T matches(const REST_PROCESS_BUFFER& x)
1244 {return x.type()==RESTProcessType::string;}
1245
1246 template <class T>
1247 typename enable_if<is_same<T,const char*>, bool>::T
1248 matches(const REST_PROCESS_BUFFER& x)
1249 {return x.type()==RESTProcessType::string;}
1250
1251 template <class T>
1252 typename enable_if<And<is_integral<T>,Not<is_same<T,bool>>>, bool>::T matches(const REST_PROCESS_BUFFER& x)
1253 {return x.type()==RESTProcessType::int_number;}
1254
1255 template <class T>
1256 typename enable_if<is_floating_point<T>, bool>::T matches(const REST_PROCESS_BUFFER& x)
1257 {return x.type()==RESTProcessType::float_number;}
1258
1259 template <class T>
1260 typename enable_if<is_enum<T>, bool>::T matches(const REST_PROCESS_BUFFER& x)
1261 {return x.type()==RESTProcessType::string;}
1262
1263 template <class T>
1264 typename enable_if<
1265 And<
1266 And<
1267 And<is_class<T>, is_default_constructible<T> >,
1269 >,
1271 >, bool>::T
1272 matches(const REST_PROCESS_BUFFER& x)
1273 {
1274 if (x.type()!=RESTProcessType::object) return false;
1275 try // to convert the json object to a T
1276 {
1277 T test;
1278 REST_PROCESS_BUFFER(x)>>test;
1279 }
1280 catch(const std::exception&)
1281 {return false;}
1282 return true;
1283 }
1284
1285 template <class T>
1286 typename enable_if<is_container<T>, bool>::T matches(const REST_PROCESS_BUFFER& x)
1287 {
1288 if (x.type()==RESTProcessType::array)
1289 {
1290 auto arr=x.array();
1291 bool r=true;
1292 for (auto& i: arr) r &= matches<typename T::value_type>(REST_PROCESS_BUFFER(i));
1293 return r;
1294 }
1295 return matches<typename T::value_type>(x); // treat a single json object as a single element sequence
1296 }
1297
1298 template <class T> struct remove_const_ref
1299 {
1300 using type=typename remove_const<typename remove_reference<T>::type>::type;
1301 };
1302
1303 template <class T>
1304 typename enable_if<is_abstract<T>, bool>::T
1305 matches(const REST_PROCESS_BUFFER&) {return false;}
1306
1307 template <class T>
1308 typename enable_if<
1309 And<is_const<typename remove_reference<T>::type>, is_reference<T>>, bool>::T
1310 matches(const REST_PROCESS_BUFFER& x)
1311 {return matches<typename remove_const_ref<T>::type>(x);}
1312
1313 template <class T>
1314 typename enable_if<
1315 And<
1316 is_object<T>,
1320 >, bool>::T
1321 matches(const REST_PROCESS_BUFFER& x)
1322 {return false;}
1323
1324 template <class T>
1326 {
1327 static const bool value = !is_integral<T>::value && !is_floating_point<T>::value &&
1328 !is_container<T>::value && !is_object<T>::value && !is_pointer<T>::value;
1329 };
1330
1331 template <class T>
1333 matches(const REST_PROCESS_BUFFER&) {return false;}
1334
1335 template <class T>
1336 typename enable_if<And<is_reference<T>, Not<is_const<typename remove_reference<T>::type>>>, bool>::T
1337 matches(const REST_PROCESS_BUFFER&) {return false;}
1338
1340 //template <class T> bool partiallyMatchable(const json5_parser::mValue& x);
1341
1342 template <class T>
1343 typename enable_if<is_floating_point<T>, bool>::T partiallyMatchable(const REST_PROCESS_BUFFER& x)
1344 {return x.type()==RESTProcessType::float_number||x.type()==RESTProcessType::int_number||x.type()==RESTProcessType::null;}
1345
1346 template <class T>
1347 typename enable_if<
1348 And<is_const<typename remove_reference<T>::type>, is_reference<T>>, bool>::T
1349 partiallyMatchable(const REST_PROCESS_BUFFER& x);
1350
1351 template <class T>
1352 typename enable_if<
1353 And<
1354 Not<is_floating_point<T>>,
1355 Not<is_container<T>>,
1356 Not<And<is_reference<T>,is_const<typename remove_reference<T>::type>>>
1357 >, bool>::T
1358 partiallyMatchable(const REST_PROCESS_BUFFER& x);
1359
1360 template <class T>
1361 typename enable_if<is_container<T>, bool>::T partiallyMatchable(const REST_PROCESS_BUFFER& x)
1362 {
1363 if (x.type()==RESTProcessType::array)
1364 {
1365 auto arr=x.array();
1366 bool r=true;
1367 for (auto& i: arr) r &= partiallyMatchable<typename T::value_type>(REST_PROCESS_BUFFER(i));
1368 return r;
1369 }
1370 return partiallyMatchable<typename T::value_type>(x); // treat a single json object as a single element sequence
1371 }
1372
1373 template <class T>
1374 typename enable_if<
1375 And<
1378 Not<And<is_reference<T>,is_const<typename remove_reference<T>::type>>>
1379 >, bool>::T
1380 partiallyMatchable(const REST_PROCESS_BUFFER& x)
1381 {return matches<T>(x);}
1382
1383 template <class T>
1384 typename enable_if<
1385 And<is_const<typename remove_reference<T>::type>, is_reference<T>>, bool>::T
1386 partiallyMatchable(const REST_PROCESS_BUFFER& x)
1388
1389 template <class T> unsigned argMatchScore(const REST_PROCESS_BUFFER& x)
1390 {
1391 if (matches<T>(x)) return 0;
1392 if (partiallyMatchable<T>(x)) return 1;
1393 return RESTProcessFunctionBase::maxMatchScore;
1394 }
1395
1396
1397 template <class F, int N, int NN=N>
1399 {
1400 static unsigned score(const REST_PROCESS_BUFFER& x)
1401 {
1402 if (x.type()!=RESTProcessType::array) return RESTProcessFunctionBase::maxMatchScore;
1403 auto arr=x.array();
1404 if (arr.size()<N) return RESTProcessFunctionBase::maxMatchScore;
1405 return argMatchScore<typename functional::Arg<F,N>::T>(REST_PROCESS_BUFFER(arr[N-1])) +
1406 MatchScore<F,N-1,NN>::score(x);
1407 }
1408 };
1409
1410 template <class F, int NN>
1411 struct MatchScore<F,2,NN>
1412 {
1413 static unsigned score(const REST_PROCESS_BUFFER& x)
1414 {
1415 if (x.type()!=RESTProcessType::array) return RESTProcessFunctionBase::maxMatchScore;
1416 auto arr=x.array();
1417 if (arr.size()<2) return RESTProcessFunctionBase::maxMatchScore;
1418 return argMatchScore<typename functional::Arg<F,1>::T>(REST_PROCESS_BUFFER(arr[0])) +
1419 argMatchScore<typename functional::Arg<F,2>::T>(REST_PROCESS_BUFFER(arr[1]))+
1420 10*(arr.size()-NN); // penalize for supplying more arguments than needed
1421 }
1422 };
1423
1424 template <class F,int NN>
1425 struct MatchScore<F,1,NN>
1426 {
1427 static unsigned score(const REST_PROCESS_BUFFER& x)
1428 {
1429 switch (x.type())
1430 {
1431 case RESTProcessType::null:
1432 return RESTProcessFunctionBase::maxMatchScore;
1433 case RESTProcessType::array:
1434 {
1435 auto arr=x.array();
1436 if (arr.empty()) return RESTProcessFunctionBase::maxMatchScore;
1437 return argMatchScore<typename functional::Arg<F,1>::T>(REST_PROCESS_BUFFER(arr[0]))+
1438 10*(arr.size()-NN); // penalize for supplying more arguments than needed
1439 }
1440 default:
1441 return argMatchScore<typename functional::Arg<F,1>::T>(x);
1442 }
1443 }
1444 };
1445
1446 template <class F,int NN>
1447 struct MatchScore<F,0,NN>
1448 {
1449 static unsigned score(const REST_PROCESS_BUFFER& x)
1450 {
1451 switch (x.type())
1452 {
1453 case RESTProcessType::null:
1454 return 0;
1455 case RESTProcessType::array:
1456 {
1457 auto arr=x.array();
1458 return 10*arr.size()-NN; // penalize for supplying more arguments than needed
1459 }
1460 default:
1461 return 10; // penalize for supplying more arguments than needed
1462 }
1463 }
1464 };
1465
1466 template <class F, int N=functional::Arity<F>::value>
1467 unsigned matchScore(const REST_PROCESS_BUFFER& x)
1468 {return MatchScore<F,N>::score(x);}
1469
1470 // static and free functions are const
1471 template <class F> struct FunctionalIsConst {static const bool value=true;};
1472 // only const bounrd methods are const
1473 template <class O, class M, class R>
1476
1477 // member functions
1478 template <class F, class R=typename functional::Return<F>::T>
1479 class RESTProcessFunction: public RESTProcessFunctionBase
1480 {
1481 public:
1482 F f;
1483 RESTProcessFunction(F f): f(f) {}
1484
1485
1486 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override
1487 {return callFunction(remainder, arguments, f);}
1488
1489 std::vector<Signature> signature() const override {return {functionSignature<F>()};}
1490
1491 unsigned matchScore(const REST_PROCESS_BUFFER& arguments) const override
1492 {return classdesc::matchScore<F>(arguments);}
1493
1494 template <class U>
1495 typename enable_if<
1496 And<
1497 is_default_constructible<typename remove_reference<U>::type>,
1500 slist() const {
1501 typename remove_const<typename remove_reference<U>::type>::type x;
1502 return RESTProcessObject<U>(x).list();
1503 }
1504 // for now, we cannot extract the lists of a non-default constructible return type
1505 template <class U>
1506 typename enable_if<
1507 Not<
1508 And<
1509 is_default_constructible<typename remove_reference<U>::type>,
1510 Not<is_void<U>>
1511 >>,RESTProcess_t>::T
1512 slist() const {return {};}
1513
1514 RESTProcess_t list() const override {return slist<R>();}
1515 std::string type() const override {return typeName<R>();}
1516 bool isObject() const override {return false;}
1517 bool isConst() const override {return FunctionalIsConst<F>::value;}
1518 unsigned arity() const override {return functional::Arity<F>::value;}
1519 };
1520
1521 template <class F, class R>
1522 class RESTProcessFunction<F, std::unique_ptr<R>>: public RESTProcessFunctionBase
1523 {
1524 public:
1525 F f;
1526 RESTProcessFunction(F f): f(f) {}
1527 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override
1528 {
1529 throw std::runtime_error("currently unable to call functions returning unique_ptr");
1530 }
1531 std::vector<Signature> signature() const override
1532 {return {functionSignature<F>()};}
1533 unsigned matchScore(const REST_PROCESS_BUFFER& arguments) const override
1534 {return classdesc::matchScore<F>(arguments);}
1535 RESTProcess_t list() const override {return {};}
1536 std::string type() const override {return typeName<F>();}
1537 };
1538
1539 template <class T, class F>
1540 typename enable_if<functional::is_member_function_ptr<F>, void>::T
1541 RESTProcess(RESTProcess_t& repo, const string& d, T& obj, F f)
1542 {
1543 auto bm=functional::bindMethod(obj,f);
1544 repo.add(d, new RESTProcessFunction<decltype(bm)>(bm));
1545 repo.defineFunctionArgTypes<F>();
1546 }
1547
1548 template <class F>
1550 RESTProcess(RESTProcess_t& repo, const string& d, F f)
1551 {
1552 repo.add(d, new RESTProcessFunction<F>(f));
1553 repo.defineFunctionArgTypes<F>();
1554 }
1555
1556 template <class F> std::shared_ptr<RESTProcessFunction<F>>
1557 makeRESTProcessFunction(F f)
1558 {return std::make_shared<RESTProcessFunction<F>>(f);}
1559
1560 inline void RESTProcess(RESTProcess_t& repo, const string& d, const char*& a)
1561 {repo.add(d,new RESTProcessObject<const char*>(a));}
1562
1563 template <class E>
1564 class RESTProcessEnum: public RESTProcessBase
1565 {
1566 E& e;
1567 public:
1568 RESTProcessEnum(E& e): e(e) {}
1569 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override
1570 {
1571 if (remainder=="@type")
1572 return makeRESTProcessValueObject(typeName<E>());
1573 else if (remainder=="@signature")
1574 return makeRESTProcessValueObject(signature());
1575 else if (arguments.type()==RESTProcessType::string)
1576 {
1577 string tmp; arguments>>tmp;
1578 convert(e, enum_keys<E>()(tmp));
1579 }
1580 else if (arguments.type()==RESTProcessType::array && !arguments.array().empty())
1581 {
1582 string tmp; json_pack_t(arguments.array()[0])>>tmp;
1583 convert(e, enum_keys<E>()(tmp));
1584 }
1585 return makeRESTProcessValueObject(enum_keys<E>()(e));
1586 }
1587 std::vector<Signature> signature() const override;
1588 RESTProcess_t list() const override {return {};}
1589 std::string type() const override {return typeName<E>();}
1590 REST_PROCESS_BUFFER asBuffer() const override {return REST_PROCESS_BUFFER(enum_keys<E>()(e));}
1591 };
1592
1593 template <class E>
1595 {
1596 RPPtr process(const string& remainder, const REST_PROCESS_BUFFER& arguments) override;
1597 std::vector<Signature> signature() const override;
1598 RESTProcess_t list() const override {return {};}
1599 std::string type() const override {return "function";}
1600 REST_PROCESS_BUFFER asBuffer() const override {return {};}
1601 };
1602
1604 template <class E>
1605 typename enable_if<is_enum<E>, void>::T
1607 {r.add("@enum."+typeName<E>(), new EnumerateEnumerators<E>());}
1608
1609 template <class T>
1610 typename enable_if<Not<is_enum<T>>, void>::T
1611 defineType(RESTProcess_t&)
1612 {/* for now, we don't do anything with regular types */}
1614
1615 template <class F, int N> struct DefineFunctionArgTypes
1616 {
1617 static void define(RESTProcess_t& r)
1618 {
1620 DefineFunctionArgTypes<F,N-1>::define(r);
1621 }
1622 };
1623
1624 template <class F> struct DefineFunctionArgTypes<F,0>
1625 {
1626 static void define(RESTProcess_t& r)
1627 {
1629 }
1630 };
1631
1632 template <class E>
1633 typename enable_if<is_enum<E>, void>::T
1634 RESTProcessp(RESTProcess_t& repo, const string& d, E& e)
1635 {
1636 repo.add(d, new RESTProcessEnum<E>(e));
1637 defineType<E>(repo);
1638 }
1639
1640 template <class T>
1641 void RESTProcess_onbase(RESTProcess_t& r, const string& d, T& a)
1642 {RESTProcess(r,d,a);}
1643
1644 template <class T, class F>
1645 void RESTProcess(RESTProcess_t&, const string&, T&, is_constructor, F)
1646 {}
1647
1648
1649 template <class... Args> struct NumArgs
1650 {
1651 static const size_t value=functional::Arity<void(*)(Args...)>::value;
1652 };
1653
1654
1655 template <class T, class... Args>
1656 struct RESTProcessMultiArrayFromC: public RESTProcessMultiArray<MultiArray<T,NumArgs<Args...>::value>>
1657 {
1658 static const size_t rank=NumArgs<Args...>::value;
1659 RESTProcessMultiArrayFromC(T* data, Args... dims):
1660 RESTProcessMultiArray<MultiArray<T,rank>>(data,dims...) {}
1661 };
1662
1663 template <class T, class... Args>
1664 void RESTProcess(RESTProcess_t& r, const string& d, is_array, T& a, int dims, Args... args)
1665 {
1666 r.add(d, new RESTProcessMultiArrayFromC<T,Args...>(&a, args...));
1667 }
1668
1669 template <class T>
1670 void RESTProcess(RESTProcess_t& r, const string& d, is_constructor, T& a) {}
1671
1672 template <class T>
1673 typename enable_if<is_smart_ptr<T>, void>::T
1674 RESTProcessp(RESTProcess_t& repo, const std::string& d, T& a)
1675 {repo.add(d, new RESTProcessPtr<T>(a));}
1676
1677 template <class T> struct RESTProcessHeapObject: public RESTProcessPtr<std::unique_ptr<T>>
1678 {
1679 std::unique_ptr<T> obj;
1680 RESTProcessHeapObject(): RESTProcessPtr<std::unique_ptr<T>>(obj) {}
1681 RESTProcessHeapObject(std::unique_ptr<T>&& o): RESTProcessPtr<std::unique_ptr<T>>(obj), obj(std::move(o)) {}
1682 bool isObject() const override {return true;}
1683 };
1684
1685 template <class T> std::shared_ptr<RESTProcessHeapObject<T>>
1686 makeRESTProcessHeapObject(std::unique_ptr<T>&& obj)
1687 {return std::make_shared<RESTProcessHeapObject<T>>(std::move(obj));}
1688
1689}
1690
1691namespace classdesc_access
1692{
1693 template <class T, class Enable=void> struct access_RESTProcess;
1694}
1695
1696namespace std
1697{
1698 template <class T, size_t N>
1699 void advance(typename classdesc::MultiArray<T,N>::iterator& i, size_t n)
1700 {i+=n;}
1701}
1702
1703#include "use_mbr_pointers.h"
1704CLASSDESC_USE_OLDSTYLE_MEMBER_OBJECTS(RESTProcess);
1705
1707using classdesc::RESTProcess_onbase;
1708
1709#endif
Definition RESTProcess_base.h:1595
Definition RESTProcess_base.h:1127
Definition multiArray.h:25
Definition RESTProcess_base.h:954
RPPtr setElem(const REST_PROCESS_BUFFER &index, const REST_PROCESS_BUFFER &value) override
Definition RESTProcess_base.h:1006
RPPtr keys() const override
returns a list of keys if this is an associative container, otherwise void
Definition RESTProcess_base.h:1019
bool contains(const REST_PROCESS_BUFFER &index) const override
returns true if an associative container contains key
Definition RESTProcess_base.h:1015
std::string type() const override
return type name of this
Definition RESTProcess_base.h:999
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:309
void insert(const REST_PROCESS_BUFFER &value) override
append to end of a sequence, or inserts key into an associative container
Definition RESTProcess_base.h:1013
RPPtr getElem(const REST_PROCESS_BUFFER &index) override
get element by position for sequences, by key for associative containers
Definition RESTProcess_base.h:1002
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:141
size_t size() const override
size if this is a container, 0 otherwise
Definition RESTProcess_base.h:1012
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
bool isObject() const override
Definition RESTProcess_base.h:1001
interface for the REST processor
Definition RESTProcess_base.h:42
virtual RPPtr keys() const
returns a list of keys if this is an associative container, otherwise void
Definition RESTProcess_base.h:555
virtual void erase(const REST_PROCESS_BUFFER &index)
erase an element - by position for sequences, by key for associative containers
Definition RESTProcess_base.h:88
virtual RPPtr setElem(const REST_PROCESS_BUFFER &index, const REST_PROCESS_BUFFER &value)
Definition RESTProcess_base.h:83
T * getObject()
returns a pointer to the underlying object if it is one of type T, otherwise null
Definition RESTProcess_base.h:558
virtual RESTProcess_t list() const =0
return list of subcommands to this
virtual bool isObject() const
Definition RESTProcess_base.h:72
enable_if< is_base_of< object, T >, constobject * >::T getClassdescObjectImpl(T &obj)
implementation of upcasting to a classdesc::object
Definition RESTProcess_base.h:46
virtual bool contains(const REST_PROCESS_BUFFER &key) const
returns true if an associative container contains key
Definition RESTProcess_base.h:90
virtual unsigned arity() const
arity if this is a function, 0 otherwise
Definition RESTProcess_base.h:76
virtual object * getClassdescObject()
returns a classdesc object if referring to an object derived from classdesc::object
Definition RESTProcess_base.h:68
virtual size_t size() const
size if this is a container, 0 otherwise
Definition RESTProcess_base.h:78
virtual void insert(const REST_PROCESS_BUFFER &value)
append to end of a sequence, or inserts key into an associative container
Definition RESTProcess_base.h:86
Signature functionSignature() const
return signature for a function type F
Definition RESTProcess_epilogue.h:169
virtual RPPtr process(const string &path, const REST_PROCESS_BUFFER &arguments)=0
virtual std::vector< Signature > signature() const =0
return signature(s) of the operations
virtual bool isConst() const
true if this is a const object, a const member function or static/free function
Definition RESTProcess_base.h:74
virtual std::string type() const =0
return type name of this
virtual RPPtr getElem(const REST_PROCESS_BUFFER &)
get element by position for sequences, by key for associative containers
Definition RESTProcess_base.h:552
virtual void populate(RESTProcess_t &map) const
populate map from the object wrapped by this, if any
Definition RESTProcess_base.h:62
Definition RESTProcess_base.h:1565
std::string type() const override
return type name of this
Definition RESTProcess_base.h:1589
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_base.h:1569
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:1588
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:94
Definition RESTProcess_base.h:126
virtual unsigned matchScore(const REST_PROCESS_BUFFER &arguments) const =0
returns how good the match is with arguments, less is best
std::string type() const override
return type name of this
Definition RESTProcess_base.h:1536
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_base.h:1527
unsigned matchScore(const REST_PROCESS_BUFFER &arguments) const override
returns how good the match is with arguments, less is best
Definition RESTProcess_base.h:1533
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:1535
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_base.h:1531
Definition RESTProcess_base.h:1480
std::string type() const override
return type name of this
Definition RESTProcess_base.h:1515
unsigned arity() const override
arity if this is a function, 0 otherwise
Definition RESTProcess_base.h:1518
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_base.h:1486
unsigned matchScore(const REST_PROCESS_BUFFER &arguments) const override
returns how good the match is with arguments, less is best
Definition RESTProcess_base.h:1491
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:1514
bool isConst() const override
true if this is a const object, a const member function or static/free function
Definition RESTProcess_base.h:1517
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_base.h:1489
bool isObject() const override
Definition RESTProcess_base.h:1516
RPPtr setElem(const REST_PROCESS_BUFFER &index, const REST_PROCESS_BUFFER &value) override
Definition RESTProcess_base.h:728
std::string type() const override
return type name of this
Definition RESTProcess_base.h:721
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:272
void insert(const REST_PROCESS_BUFFER &value) override
append to end of a sequence, or inserts key into an associative container
Definition RESTProcess_base.h:735
RPPtr getElem(const REST_PROCESS_BUFFER &index) override
get element by position for sequences, by key for associative containers
Definition RESTProcess_base.h:724
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:130
size_t size() const override
size if this is a container, 0 otherwise
Definition RESTProcess_base.h:734
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:80
void erase(const REST_PROCESS_BUFFER &index) override
erase an element - by position for sequences, by key for associative containers
Definition RESTProcess_base.h:736
bool isObject() const override
Definition RESTProcess_base.h:723
marker for containers and pointers that wrap
Definition RESTProcess_base.h:122
Definition function.h:84
Definition classdesc.h:920
Definition classdesc.h:923
Definition classdesc.h:926
Definition json_pack_base.h:99
Metaprogramming support for processing functions of multiple arguments.
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< is_enum< E >, void >::T defineType(RESTProcess_t &r)
define type dependent information in repository
Definition RESTProcess_base.h:1606
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
enable_if< is_floating_point< T >, bool >::T partiallyMatchable(const REST_PROCESS_BUFFER &x)
testing for not quite so good matches between json type and C++ type
Definition RESTProcess_base.h:1343
void RPAC_insert(T &obj, const REST_PROCESS_BUFFER &arguments)
insert element into an associative container
Definition RESTProcess_base.h:846
enable_if< And< is_pointer< T >, Not< is_same< T, constchar * > > >, bool >::T matches(const V &x)
Definition RESTProcess_base.h:1234
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
STL namespace.
Definition classdesc.h:420
Definition RESTProcess_epilogue.h:159
Definition RESTProcess_base.h:1616
Definition RESTProcess_base.h:1471
Definition RESTProcess_base.h:929
Definition RESTProcess_base.h:1399
Definition multiArray.h:94
used for removing const attributes of an associative container's value_type
Definition RESTProcess_base.h:834
Definition classdesc.h:405
Definition RESTProcess_base.h:1650
Definition classdesc.h:423
bool isObject() const override
Definition RESTProcess_base.h:1682
Definition RESTProcess_base.h:1657
RPPtr setElem(const REST_PROCESS_BUFFER &index, const REST_PROCESS_BUFFER &value)
Definition RESTProcess_base.h:806
RPPtr getElem(const REST_PROCESS_BUFFER &index)
get element by position for sequences, by key for associative containers
Definition RESTProcess_base.h:802
size_t size() const override
size if this is a container, 0 otherwise
Definition RESTProcess_base.h:812
RPPtr setElem(const REST_PROCESS_BUFFER &index, const REST_PROCESS_BUFFER &value) override
Definition RESTProcess_base.h:777
std::string type() const override
return type name of this
Definition RESTProcess_base.h:769
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:293
RPPtr getElem(const REST_PROCESS_BUFFER &index) override
get element by position for sequences, by key for associative containers
Definition RESTProcess_base.h:771
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:768
size_t size() const override
size if this is a container, 0 otherwise
Definition RESTProcess_base.h:787
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_base.h:767
bool isObject() const override
Definition RESTProcess_base.h:770
handle setting and getting of objects
Definition RESTProcess_base.h:449
void populate(RESTProcess_t &map) const override
populate map from the object wrapped by this, if any
Definition RESTProcess_base.h:477
std::string type() const override
return type name of this
Definition RESTProcess_epilogue.h:154
std::shared_ptr< classdesc::RESTProcessBase > process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_base.h:452
object * getClassdescObject() override
returns a classdesc object if referring to an object derived from classdesc::object
Definition RESTProcess_base.h:478
RPPtr getElem(const REST_PROCESS_BUFFER &b) override
get element by position for sequences, by key for associative containers
Definition RESTProcess_base.h:491
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:124
bool isConst() const override
true if this is a const object, a const member function or static/free function
Definition RESTProcess_base.h:484
RPPtr setElem(const REST_PROCESS_BUFFER &b, const REST_PROCESS_BUFFER &value) override
Definition RESTProcess_base.h:502
size_t size() const override
size if this is a container, 0 otherwise
Definition RESTProcess_base.h:485
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:59
bool isObject() const override
Definition RESTProcess_base.h:482
Definition RESTProcess_base.h:138
std::string type() const override
return type name of this
Definition RESTProcess_base.h:151
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
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_base.h:142
Definition RESTProcess_base.h:1061
std::string type() const override
return type name of this
Definition RESTProcess_base.h:1072
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:382
object * getClassdescObject() override
returns a classdesc object if referring to an object derived from classdesc::object
Definition RESTProcess_base.h:1073
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:1066
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:66
bool isObject() const override
Definition RESTProcess_base.h:1082
Definition RESTProcess_base.h:743
class that represents the void, or null object
Definition RESTProcess_base.h:542
std::string type() const override
return type name of this
Definition RESTProcess_base.h:548
std::shared_ptr< RESTProcessBase > process(const string &, const REST_PROCESS_BUFFER &) override
Definition RESTProcess_base.h:543
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:547
bool isConst() const override
true if this is a const object, a const member function or static/free function
Definition RESTProcess_base.h:549
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_base.h:546
std::string type() const override
return type name of this
Definition RESTProcess_base.h:1097
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:401
object * getClassdescObject() override
returns a classdesc object if referring to an object derived from classdesc::object
Definition RESTProcess_base.h:1098
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_base.h:1092
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:73
bool isObject() const override
Definition RESTProcess_base.h:1112
REST processor registry.
Definition RESTProcess_base.h:351
void add(string d, RESTProcessFunctionBase *rp)
ownership of rp is passed
Definition RESTProcess_base.h:367
void defineFunctionArgTypes()
define all arguments of F
Definition RESTProcess_base.h:403
void addFactory(const std::string &typeName, const std::function< void(const std::string &objName)> &callback=nullptr)
Definition RESTProcess_epilogue.h:533
RESTProcess_t(const RPPtr &p)
Construct from an object that RPPPtr wraps.
Definition RESTProcess_base.h:358
void add(string d, RESTProcessBase *rp)
ownership of rp is passed
Definition RESTProcess_base.h:360
Definition signature.h:18
Definition classdesc.h:299
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
Definition function.h:50
Arity::V (or ::value) is the number of arguments of
Definition function.h:43
Definition classdesc.h:505
Definition classdesc.h:490
Definition RESTProcess_base.h:1326
Definition RESTProcess_base.h:574
true_type if T is a std::pair
Definition classdesc.h:367
determines if T is a standard sequence container
Definition classdesc.h:302
Definition RESTProcess_base.h:1299
transfer the constness property of T to U
Definition classdesc.h:431
Definition RESTProcess_base.h:1693