bootstrap_stl.hpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. // This file is distributed under the BSD License.
  2. // See "license.txt" for details.
  3. // Copyright 2009-2012, Jonathan Turner ([email protected])
  4. // Copyright 2009-2017, Jason Turner ([email protected])
  5. // http://www.chaiscript.com
  6. // This is an open source non-commercial project. Dear PVS-Studio, please check it.
  7. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
  8. /// \file
  9. /// This file contains utility functions for registration of STL container
  10. /// classes. The methodology used is based on the SGI STL concepts.
  11. /// http://www.sgi.com/tech/stl/table_of_contents.html
  12. #ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
  13. #define CHAISCRIPT_BOOTSTRAP_STL_HPP_
  14. #include <functional>
  15. #include <memory>
  16. #include <stdexcept>
  17. #include <typeinfo>
  18. #include <vector>
  19. #include "bootstrap.hpp"
  20. #include "boxed_value.hpp"
  21. #include "dispatchkit.hpp"
  22. #include "operators.hpp"
  23. #include "proxy_constructors.hpp"
  24. #include "register_function.hpp"
  25. #include "type_info.hpp"
  26. namespace chaiscript
  27. {
  28. namespace bootstrap
  29. {
  30. namespace standard_library
  31. {
  32. /// Bidir_Range, based on the D concept of ranges.
  33. /// \todo Update the Range code to base its capabilities on
  34. /// the user_typetraits of the iterator passed in
  35. template<typename Container, typename IterType>
  36. struct Bidir_Range
  37. {
  38. typedef Container container_type;
  39. Bidir_Range(Container &c)
  40. : m_begin(c.begin()), m_end(c.end())
  41. {
  42. }
  43. bool empty() const
  44. {
  45. return m_begin == m_end;
  46. }
  47. void pop_front()
  48. {
  49. if (empty())
  50. {
  51. throw std::range_error("Range empty");
  52. }
  53. ++m_begin;
  54. }
  55. void pop_back()
  56. {
  57. if (empty())
  58. {
  59. throw std::range_error("Range empty");
  60. }
  61. --m_end;
  62. }
  63. decltype(auto) front() const
  64. {
  65. if (empty())
  66. {
  67. throw std::range_error("Range empty");
  68. }
  69. return (*m_begin);
  70. }
  71. decltype(auto) back() const
  72. {
  73. if (empty())
  74. {
  75. throw std::range_error("Range empty");
  76. }
  77. auto pos = m_end;
  78. --pos;
  79. return (*(pos));
  80. }
  81. IterType m_begin;
  82. IterType m_end;
  83. };
  84. namespace detail {
  85. template<typename T>
  86. size_t count(const T &t_target, const typename T::key_type &t_key)
  87. {
  88. return t_target.count(t_key);
  89. }
  90. template<typename T>
  91. void insert(T &t_target, const T &t_other)
  92. {
  93. t_target.insert(t_other.begin(), t_other.end());
  94. }
  95. template<typename T>
  96. void insert_ref(T &t_target, const typename T::value_type &t_val)
  97. {
  98. t_target.insert(t_val);
  99. }
  100. /// Add Bidir_Range support for the given ContainerType
  101. template<typename Bidir_Type>
  102. void input_range_type_impl(const std::string &type, Module& m)
  103. {
  104. m.add(user_type<Bidir_Type>(), type + "_Range");
  105. copy_constructor<Bidir_Type>(type + "_Range", m);
  106. m.add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
  107. m.add(fun(&Bidir_Type::empty), "empty");
  108. m.add(fun(&Bidir_Type::pop_front), "pop_front");
  109. m.add(fun(&Bidir_Type::front), "front");
  110. m.add(fun(&Bidir_Type::pop_back), "pop_back");
  111. m.add(fun(&Bidir_Type::back), "back");
  112. }
  113. /// Algorithm for inserting at a specific position into a container
  114. template<typename Type>
  115. void insert_at(Type &container, int pos, const typename Type::value_type &v)
  116. {
  117. auto itr = container.begin();
  118. auto end = container.end();
  119. if (pos < 0 || std::distance(itr, end) < pos)
  120. {
  121. throw std::range_error("Cannot insert past end of range");
  122. }
  123. std::advance(itr, pos);
  124. container.insert(itr, v);
  125. }
  126. /// Algorithm for erasing a specific position from a container
  127. template<typename Type>
  128. void erase_at(Type &container, int pos)
  129. {
  130. auto itr = container.begin();
  131. auto end = container.end();
  132. if (pos < 0 || std::distance(itr, end) < (pos-1))
  133. {
  134. throw std::range_error("Cannot erase past end of range");
  135. }
  136. std::advance(itr, pos);
  137. container.erase(itr);
  138. }
  139. }
  140. template<typename ContainerType>
  141. void input_range_type(const std::string &type, Module& m)
  142. {
  143. detail::input_range_type_impl<Bidir_Range<ContainerType, typename ContainerType::iterator> >(type,m);
  144. detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator> >("Const_" + type,m);
  145. }
  146. template<typename ContainerType>
  147. ModulePtr input_range_type(const std::string &type)
  148. {
  149. auto m = std::make_shared<Module>();
  150. input_range_type<ContainerType>(type, *m);
  151. return m;
  152. }
  153. /// Add random_access_container concept to the given ContainerType
  154. /// http://www.sgi.com/tech/stl/RandomAccessContainer.html
  155. template<typename ContainerType>
  156. void random_access_container_type(const std::string &/*type*/, Module& m)
  157. {
  158. //In the interest of runtime safety for the m, we prefer the at() method for [] access,
  159. //to throw an exception in an out of bounds condition.
  160. m.add(
  161. fun(
  162. [](ContainerType &c, int index) -> typename ContainerType::reference {
  163. /// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
  164. /// during dispatch. reevaluate
  165. return c.at(static_cast<typename ContainerType::size_type>(index));
  166. }), "[]");
  167. m.add(
  168. fun(
  169. [](const ContainerType &c, int index) -> typename ContainerType::const_reference {
  170. /// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
  171. /// during dispatch. reevaluate
  172. return c.at(static_cast<typename ContainerType::size_type>(index));
  173. }), "[]");
  174. }
  175. template<typename ContainerType>
  176. ModulePtr random_access_container_type(const std::string &type)
  177. {
  178. auto m = std::make_shared<Module>();
  179. random_access_container_type<ContainerType>(type, *m);
  180. return m;
  181. }
  182. /// Add assignable concept to the given ContainerType
  183. /// http://www.sgi.com/tech/stl/Assignable.html
  184. template<typename ContainerType>
  185. void assignable_type(const std::string &type, Module& m)
  186. {
  187. copy_constructor<ContainerType>(type, m);
  188. operators::assign<ContainerType>(m);
  189. }
  190. template<typename ContainerType>
  191. ModulePtr assignable_type(const std::string &type)
  192. {
  193. auto m = std::make_shared<Module>();
  194. assignable_type<ContainerType>(type, *m);
  195. return m;
  196. }
  197. /// Add container resize concept to the given ContainerType
  198. /// http://www.cplusplus.com/reference/stl/
  199. template<typename ContainerType>
  200. void resizable_type(const std::string &/*type*/, Module& m)
  201. {
  202. m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize");
  203. m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize");
  204. }
  205. template<typename ContainerType>
  206. ModulePtr resizable_type(const std::string &type)
  207. {
  208. auto m = std::make_shared<Module>();
  209. resizable_type<ContainerType>(type, *m);
  210. return m;
  211. }
  212. /// Add container reserve concept to the given ContainerType
  213. /// http://www.cplusplus.com/reference/stl/
  214. template<typename ContainerType>
  215. void reservable_type(const std::string &/*type*/, Module& m)
  216. {
  217. m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
  218. m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
  219. }
  220. template<typename ContainerType>
  221. ModulePtr reservable_type(const std::string &type)
  222. {
  223. auto m = std::make_shared<Module>();
  224. reservable_type<ContainerType>(type, *m);
  225. return m;
  226. }
  227. /// Add container concept to the given ContainerType
  228. /// http://www.sgi.com/tech/stl/Container.html
  229. template<typename ContainerType>
  230. void container_type(const std::string &/*type*/, Module& m)
  231. {
  232. m.add(fun([](const ContainerType *a) { return a->size(); } ), "size");
  233. m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
  234. m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
  235. }
  236. template <typename ContainerType>
  237. ModulePtr container_type(const std::string& type)
  238. {
  239. auto m = std::make_shared<Module>();
  240. container_type<ContainerType>(type, *m);
  241. return m;
  242. }
  243. /// Add default constructable concept to the given Type
  244. /// http://www.sgi.com/tech/stl/DefaultConstructible.html
  245. template<typename Type>
  246. void default_constructible_type(const std::string &type, Module& m)
  247. {
  248. m.add(constructor<Type ()>(), type);
  249. }
  250. template <typename Type>
  251. ModulePtr default_constructible_type(const std::string& type)
  252. {
  253. auto m = std::make_shared<Module>();
  254. default_constructible_type<Type>(type, *m);
  255. return m;
  256. }
  257. /// Add sequence concept to the given ContainerType
  258. /// http://www.sgi.com/tech/stl/Sequence.html
  259. template<typename ContainerType>
  260. void sequence_type(const std::string &/*type*/, Module& m)
  261. {
  262. m.add(fun(&detail::insert_at<ContainerType>),
  263. []()->std::string{
  264. if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
  265. return "insert_ref_at";
  266. } else {
  267. return "insert_at";
  268. }
  269. }());
  270. m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
  271. }
  272. template <typename ContainerType>
  273. ModulePtr sequence_type(const std::string &type)
  274. {
  275. auto m = std::make_shared<Module>();
  276. sequence_type<ContainerType>(type, *m);
  277. return m;
  278. }
  279. /// Add back insertion sequence concept to the given ContainerType
  280. /// http://www.sgi.com/tech/stl/BackInsertionSequence.html
  281. template<typename ContainerType>
  282. void back_insertion_sequence_type(const std::string &type, Module& m)
  283. {
  284. m.add(fun([](ContainerType &container)->decltype(auto){
  285. if (container.empty()) {
  286. throw std::range_error("Container empty");
  287. } else {
  288. return (container.back());
  289. }
  290. }
  291. )
  292. , "back");
  293. m.add(fun([](const ContainerType &container)->decltype(auto){
  294. if (container.empty()) {
  295. throw std::range_error("Container empty");
  296. } else {
  297. return (container.back());
  298. }
  299. }
  300. )
  301. , "back");
  302. typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
  303. m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
  304. [&]()->std::string{
  305. if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
  306. m.eval(
  307. "# Pushes the second value onto the container while making a clone of the value\n"
  308. "def push_back(" + type + " container, x)\n"
  309. "{ \n"
  310. " if (x.is_var_return_value()) {\n"
  311. " x.reset_var_return_value() \n"
  312. " container.push_back_ref(x) \n"
  313. " } else { \n"
  314. " container.push_back_ref(clone(x)); \n"
  315. " }\n"
  316. "} \n"
  317. );
  318. return "push_back_ref";
  319. } else {
  320. return "push_back";
  321. }
  322. }());
  323. m.add(fun(&ContainerType::pop_back), "pop_back");
  324. }
  325. template<typename ContainerType>
  326. ModulePtr back_insertion_sequence_type(const std::string &type)
  327. {
  328. auto m = std::make_shared<Module>();
  329. back_insertion_sequence_type<ContainerType>(type, *m);
  330. return m;
  331. }
  332. /// Front insertion sequence
  333. /// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
  334. template<typename ContainerType>
  335. void front_insertion_sequence_type(const std::string &type, Module& m)
  336. {
  337. typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
  338. typedef void (ContainerType::*pop_ptr)();
  339. m.add(fun([](ContainerType &container)->decltype(auto){
  340. if (container.empty()) {
  341. throw std::range_error("Container empty");
  342. } else {
  343. return (container.front());
  344. }
  345. }
  346. )
  347. , "front");
  348. m.add(fun([](const ContainerType &container)->decltype(auto){
  349. if (container.empty()) {
  350. throw std::range_error("Container empty");
  351. } else {
  352. return (container.front());
  353. }
  354. }
  355. )
  356. , "front");
  357. m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
  358. [&]()->std::string{
  359. if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
  360. m.eval(
  361. "# Pushes the second value onto the front of container while making a clone of the value\n"
  362. "def push_front(" + type + " container, x)\n"
  363. "{ \n"
  364. " if (x.is_var_return_value()) {\n"
  365. " x.reset_var_return_value() \n"
  366. " container.push_front_ref(x) \n"
  367. " } else { \n"
  368. " container.push_front_ref(clone(x)); \n"
  369. " }\n"
  370. "} \n"
  371. );
  372. return "push_front_ref";
  373. } else {
  374. return "push_front";
  375. }
  376. }());
  377. m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
  378. }
  379. template<typename ContainerType>
  380. ModulePtr front_insertion_sequence_type(const std::string &type)
  381. {
  382. auto m = std::make_shared<Module>();
  383. front_insertion_sequence_type<ContainerType>(type, *m);
  384. return m;
  385. }
  386. /// bootstrap a given PairType
  387. /// http://www.sgi.com/tech/stl/pair.html
  388. template<typename PairType>
  389. void pair_type(const std::string &type, Module& m)
  390. {
  391. m.add(user_type<PairType>(), type);
  392. m.add(fun(&PairType::first), "first");
  393. m.add(fun(&PairType::second), "second");
  394. basic_constructors<PairType>(type, m);
  395. m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
  396. }
  397. template<typename PairType>
  398. ModulePtr pair_type(const std::string &type)
  399. {
  400. auto m = std::make_shared<Module>();
  401. pair_type<PairType>(type, *m);
  402. return m;
  403. }
  404. /// Add pair associative container concept to the given ContainerType
  405. /// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
  406. template<typename ContainerType>
  407. void pair_associative_container_type(const std::string &type, Module& m)
  408. {
  409. pair_type<typename ContainerType::value_type>(type + "_Pair", m);
  410. }
  411. template<typename ContainerType>
  412. ModulePtr pair_associative_container_type(const std::string &type)
  413. {
  414. auto m = std::make_shared<Module>();
  415. pair_associative_container_type<ContainerType>(type, *m);
  416. return m;
  417. }
  418. /// Add unique associative container concept to the given ContainerType
  419. /// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
  420. template<typename ContainerType>
  421. void unique_associative_container_type(const std::string &/*type*/, Module& m)
  422. {
  423. m.add(fun(detail::count<ContainerType>), "count");
  424. typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
  425. m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
  426. m.add(fun(&detail::insert<ContainerType>), "insert");
  427. m.add(fun(&detail::insert_ref<ContainerType>),
  428. []()->std::string{
  429. if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
  430. return "insert_ref";
  431. } else {
  432. return "insert";
  433. }
  434. }());
  435. }
  436. template<typename ContainerType>
  437. ModulePtr unique_associative_container_type(const std::string &type)
  438. {
  439. auto m = std::make_shared<Module>();
  440. unique_associative_container_type<ContainerType>(type, *m);
  441. return m;
  442. }
  443. /// Add a MapType container
  444. /// http://www.sgi.com/tech/stl/Map.html
  445. template<typename MapType>
  446. void map_type(const std::string &type, Module& m)
  447. {
  448. m.add(user_type<MapType>(), type);
  449. typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
  450. typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const;
  451. m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
  452. m.add(fun(static_cast<elem_access>(&MapType::at)), "at");
  453. m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
  454. if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
  455. {
  456. m.eval(R"(
  457. def Map::`==`(Map rhs) {
  458. if ( rhs.size() != this.size() ) {
  459. return false;
  460. } else {
  461. auto r1 = range(this);
  462. auto r2 = range(rhs);
  463. while (!r1.empty())
  464. {
  465. if (!eq(r1.front().first, r2.front().first) || !eq(r1.front().second, r2.front().second))
  466. {
  467. return false;
  468. }
  469. r1.pop_front();
  470. r2.pop_front();
  471. }
  472. true;
  473. }
  474. } )"
  475. );
  476. }
  477. container_type<MapType>(type, m);
  478. default_constructible_type<MapType>(type, m);
  479. assignable_type<MapType>(type, m);
  480. unique_associative_container_type<MapType>(type, m);
  481. pair_associative_container_type<MapType>(type, m);
  482. input_range_type<MapType>(type, m);
  483. }
  484. template<typename MapType>
  485. ModulePtr map_type(const std::string &type)
  486. {
  487. auto m = std::make_shared<Module>();
  488. map_type<MapType>(type, *m);
  489. return m;
  490. }
  491. /// http://www.sgi.com/tech/stl/List.html
  492. template<typename ListType>
  493. void list_type(const std::string &type, Module& m)
  494. {
  495. m.add(user_type<ListType>(), type);
  496. front_insertion_sequence_type<ListType>(type, m);
  497. back_insertion_sequence_type<ListType>(type, m);
  498. sequence_type<ListType>(type, m);
  499. resizable_type<ListType>(type, m);
  500. container_type<ListType>(type, m);
  501. default_constructible_type<ListType>(type, m);
  502. assignable_type<ListType>(type, m);
  503. input_range_type<ListType>(type, m);
  504. }
  505. template<typename ListType>
  506. ModulePtr list_type(const std::string &type)
  507. {
  508. auto m = std::make_shared<Module>();
  509. list_type<ListType>(type, m);
  510. return m;
  511. }
  512. /// Create a vector type with associated concepts
  513. /// http://www.sgi.com/tech/stl/Vector.html
  514. template<typename VectorType>
  515. void vector_type(const std::string &type, Module& m)
  516. {
  517. m.add(user_type<VectorType>(), type);
  518. m.add(fun([](VectorType &container)->decltype(auto){
  519. if (container.empty()) {
  520. throw std::range_error("Container empty");
  521. } else {
  522. return (container.front());
  523. }
  524. }
  525. )
  526. , "front");
  527. m.add(fun([](const VectorType &container)->decltype(auto){
  528. if (container.empty()) {
  529. throw std::range_error("Container empty");
  530. } else {
  531. return (container.front());
  532. }
  533. }
  534. )
  535. , "front");
  536. back_insertion_sequence_type<VectorType>(type, m);
  537. sequence_type<VectorType>(type, m);
  538. random_access_container_type<VectorType>(type, m);
  539. resizable_type<VectorType>(type, m);
  540. reservable_type<VectorType>(type, m);
  541. container_type<VectorType>(type, m);
  542. default_constructible_type<VectorType>(type, m);
  543. assignable_type<VectorType>(type, m);
  544. input_range_type<VectorType>(type, m);
  545. if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
  546. {
  547. m.eval(R"(
  548. def Vector::`==`(Vector rhs) {
  549. if ( rhs.size() != this.size() ) {
  550. return false;
  551. } else {
  552. auto r1 = range(this);
  553. auto r2 = range(rhs);
  554. while (!r1.empty())
  555. {
  556. if (!eq(r1.front(), r2.front()))
  557. {
  558. return false;
  559. }
  560. r1.pop_front();
  561. r2.pop_front();
  562. }
  563. true;
  564. }
  565. } )"
  566. );
  567. }
  568. }
  569. template<typename VectorType>
  570. ModulePtr vector_type(const std::string &type)
  571. {
  572. auto m = std::make_shared<Module>();
  573. vector_type<VectorType>(type, *m);
  574. return m;
  575. }
  576. /// Add a String container
  577. /// http://www.sgi.com/tech/stl/basic_string.html
  578. template<typename String>
  579. void string_type(const std::string &type, Module& m)
  580. {
  581. m.add(user_type<String>(), type);
  582. operators::addition<String>(m);
  583. operators::assign_sum<String>(m);
  584. opers_comparison<String>(m);
  585. random_access_container_type<String>(type, m);
  586. sequence_type<String>(type, m);
  587. default_constructible_type<String>(type, m);
  588. // container_type<String>(type, m);
  589. assignable_type<String>(type, m);
  590. input_range_type<String>(type, m);
  591. //Special case: add push_back to string (which doesn't support other back_insertion operations
  592. m.add(fun(&String::push_back),
  593. []()->std::string{
  594. if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
  595. return "push_back_ref";
  596. } else {
  597. return "push_back";
  598. }
  599. }());
  600. m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
  601. m.add(fun([](const String *s, typename String::value_type c, size_t pos) { return s->find(c, pos); } ), "find");
  602. m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
  603. m.add(fun([](const String *s, typename String::value_type c, size_t pos) { return s->rfind(c, pos); } ), "rfind");
  604. m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
  605. m.add(fun([](const String *s, ypename String::value_type, size_t pos) { return s->find_first_of(c, pos); } ), "find_first_of");
  606. m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
  607. m.add(fun([](const String *s, ypename String::value_type, size_t pos) { return s->find_last_of(c, pos); } ), "find_last_of");
  608. m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
  609. m.add(fun([](const String *s, ypename String::value_type, size_t pos) { return s->find_last_not_of(c, pos); } ), "find_last_not_of");
  610. m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
  611. m.add(fun([](const String *s, ypename String::value_type, size_t pos) { return s->find_first_not_of(c, pos); } ), "find_first_not_of");
  612. m.add(fun([](String *s, typename String::value_type c) -> decltype(auto) { return (*s += c); } ), "+=");
  613. m.add(fun([](String *s) { s->clear(); } ), "clear");
  614. m.add(fun([](const String *s) { return s->empty(); } ), "empty");
  615. m.add(fun([](const String *s) { return s->size(); } ), "size");
  616. m.add(fun([](const String *s) { return s->c_str(); } ), "c_str");
  617. m.add(fun([](const String *s) { return s->data(); } ), "data");
  618. m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
  619. }
  620. template<typename String>
  621. ModulePtr string_type(const std::string &type)
  622. {
  623. auto m = std::make_shared<Module>();
  624. string_type<String>(type, *m);
  625. return m;
  626. }
  627. /// Add a MapType container
  628. /// http://www.sgi.com/tech/stl/Map.html
  629. template<typename FutureType>
  630. void future_type(const std::string &type, Module& m)
  631. {
  632. m.add(user_type<FutureType>(), type);
  633. m.add(fun([](const FutureType &t) { return t.valid(); }), "valid");
  634. m.add(fun(&FutureType::get), "get");
  635. m.add(fun(&FutureType::wait), "wait");
  636. }
  637. template<typename FutureType>
  638. ModulePtr future_type(const std::string &type)
  639. {
  640. auto m = std::make_shared<Module>();
  641. future_type<FutureType>(type, *m);
  642. return m;
  643. }
  644. }
  645. }
  646. }
  647. #endif