ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

308 lines
10 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU Lesser General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public License
  16. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #ifndef CPPCMS_URL_DISPATCHER_H
  20. #define CPPCMS_URL_DISPATCHER_H
  21. #include <booster/noncopyable.h>
  22. #include <cppcms/defs.h>
  23. #include <booster/function.h>
  24. #include <booster/hold_ptr.h>
  25. #include <booster/traits/enable_if.h>
  26. #include <booster/traits/is_base_of.h>
  27. #include <cppcms/application.h>
  28. #include <string>
  29. #include <list>
  30. namespace cppcms {
  31. class application;
  32. ///
  33. /// \brief This class is used to glue between member function of application class and urls
  34. ///
  35. /// This class is used in context of \a cppcms::application with its \a url member function.
  36. /// It uses regular expression to bind between url and callbacks that actually process the
  37. /// request. It also allows mount sub-applications to the root of
  38. /// the primary application. For example:
  39. ///
  40. /// \code
  41. /// class my_web_project : public cppcms::application {
  42. /// users_app users_;
  43. /// void display_page(std::string)
  44. /// ...
  45. /// public:
  46. /// my_web_project() {
  47. /// url().assign("^/page/(\\d+)/?$",bind1st(mem_fun(&my_web_project::display_page),this),1);
  48. /// ...
  49. /// \endcode
  50. ///
  51. class CPPCMS_API url_dispatcher : public booster::noncopyable {
  52. public:
  53. // Handlers
  54. typedef booster::function<void()> handler;
  55. typedef booster::function<void(std::string)> handler1;
  56. typedef booster::function<void(std::string,std::string)> handler2;
  57. typedef booster::function<void(std::string,std::string,std::string)> handler3;
  58. typedef booster::function<void(std::string,std::string,std::string,std::string)> handler4;
  59. ///
  60. /// Assign \a handler to pattern \a regex thus if URL that matches
  61. /// this pattern requested, \a handler is called
  62. ///
  63. void assign(std::string const &regex,handler handler);
  64. ///
  65. /// Assign \a handler to pattern \a regex thus if URL that matches
  66. /// this pattern requested, \a handler is called with first parameters
  67. /// the string that was matched at position \a exp1.
  68. ///
  69. /// For example: if
  70. /// regular expression is "^/page/(\\d+)/(\\w+)$" , exp1=2, and the url is
  71. /// "/page/13/to_be_or_not", then handler would be called with "to_be_or_not"
  72. /// as its first parameter
  73. ///
  74. void assign(std::string const &regex,handler1 handler,int exp1);
  75. ///
  76. /// Assign \a handler to pattern \a regex thus if URL that matches
  77. /// this pattern requested, \a handler is called with 1st and 2nd parameters
  78. /// the string that was matched at position \a exp1 and \a exp2
  79. ///
  80. void assign(std::string const &regex,handler2 handler,int exp1,int exp2);
  81. ///
  82. /// Assign \a handler to pattern \a regex thus if URL that matches
  83. /// this pattern requested, \a handler is called with 1st, 2nd and 3rd parameters
  84. /// the string that was matched at position \a exp1, \a exp2 and \a exp2
  85. ///
  86. void assign(std::string const &regex,handler3 handler,int exp1,int exp2,int exp3);
  87. ///
  88. /// Assign \a handler to pattern \a regex thus if URL that matches
  89. /// this pattern requested, \a handler is called with 1st, 2nd, 3rd and 4th parameters
  90. /// the string that was matched at position \a exp1, \a exp2, \a exp3 and \a exp4
  91. ///
  92. void assign(std::string const &regex,handler4 handler,int exp1,int exp2,int exp3,int exp4);
  93. ///
  94. /// Try to find match between \a url and registered handlers and applications.
  95. /// If the match was found, it returns the method, how handler should bd dispatched
  96. /// synchronous or asynchronous, meaning the handler would be executed in thread pool
  97. /// or in the main non-blocking loop
  98. ///
  99. bool dispatch(std::string url);
  100. url_dispatcher();
  101. ~url_dispatcher();
  102. ///
  103. /// This template function is a shortcut to assign(regex,callback). It allows
  104. /// assignment of \a member function of an \a object with signature void handler()
  105. /// as simple as assign(expr,&bar::foo,this);
  106. ///
  107. /// In addition to calling \a member function it calls object->init() before call
  108. /// and object->clean() after the call of the C is derived from cppcms::application
  109. ///
  110. template<typename C>
  111. void assign(std::string const &regex,void (C::*member)(),C *object)
  112. {
  113. assign(regex,binder0<C>(member,object));
  114. }
  115. ///
  116. /// This template function is a shortcut to assign(regex,callback,int). It allows
  117. /// assignment of \a member function of an \a object with signature void handler(string)
  118. ///
  119. /// In addition to calling \a member function it calls object->init() before call
  120. /// and object->clean() after the call of the C is derived from cppcms::application
  121. ///
  122. template<typename C>
  123. void assign(std::string const &regex,void (C::*member)(std::string),C *object,int e1)
  124. {
  125. assign(regex,binder1<C>(member,object),e1);
  126. }
  127. ///
  128. /// This template function is a shortcut to assign(regex,callback,int,int). It allows
  129. /// assignment of \a member function of an \a object with signature void handler(string,string)
  130. ///
  131. /// In addition to calling \a member function it calls object->init() before call
  132. /// and object->clean() after the call of the C is derived from cppcms::application
  133. ///
  134. template<typename C>
  135. void assign(std::string const &regex,void (C::*member)(std::string,std::string),C *object,int e1,int e2)
  136. {
  137. assign(regex,binder2<C>(member,object),e1,e2);
  138. }
  139. template<typename C>
  140. ///
  141. /// This template function is a shortcut to assign(regex,callback,int,int,int). It allows
  142. /// assignment of \a member function of an \a object with signature void handler(string,string,string)
  143. ///
  144. /// In addition to calling \a member function it calls object->init() before call
  145. /// and object->clean() after the call of the C is derived from cppcms::application
  146. ///
  147. void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string),C *object,int e1,int e2,int e3)
  148. {
  149. assign(regex,binder3<C>(member,object),e1,e2,e3);
  150. }
  151. ///
  152. /// This template function is a shortcut to assign(regex,callback,int,int,int,int). It allows
  153. /// assignment of \a member function of an \a object with signature void handler(string,string,string,string)
  154. ///
  155. /// In addition to calling \a member function it calls object->init() before call
  156. /// and object->clean() after the call of the C is derived from cppcms::application
  157. ///
  158. template<typename C>
  159. void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string,std::string),C *object,int e1,int e2,int e3,int e4)
  160. {
  161. assign(regex,binder4<C>(member,object),e1,e2,e3,e4);
  162. }
  163. ///
  164. /// Mount a sub application \a app to the URL dispatcher, using regular expression match.
  165. ///
  166. /// When mounted the URL is checked against match expression and then calls app.main(substr) where
  167. /// substr is the matched subexpression part. For example:
  168. ///
  169. /// \code
  170. /// dispatcher().mount("/formums((/.*)?)",forums,1);
  171. /// \endcode
  172. ///
  173. /// For example: for url /forums/page/3 it would call \c forums::main with value "/page/3"
  174. ///
  175. void mount(std::string const &match,application &app,int part);
  176. private:
  177. template<typename C,typename Enable = void>
  178. class page_guard {
  179. public:
  180. page_guard(C * /*o*/) {}
  181. };
  182. template<typename C>
  183. class page_guard<C,typename booster::enable_if<booster::is_base_of< cppcms::application,C> >::type > {
  184. public:
  185. page_guard(C *o) :
  186. object_(o)
  187. {
  188. object_->init();
  189. }
  190. ~page_guard()
  191. {
  192. object_->clear();
  193. }
  194. private:
  195. application *object_;
  196. };
  197. template<typename C>
  198. struct binder0{
  199. typedef void (C::*member_type)();
  200. member_type member;
  201. C *object;
  202. binder0(member_type m,C *o) :
  203. member(m),
  204. object(o)
  205. {
  206. }
  207. void operator()() const
  208. {
  209. page_guard<C> guard(object);
  210. (object->*member)();
  211. }
  212. };
  213. template<typename C>
  214. struct binder1{
  215. typedef void (C::*member_type)(std::string);
  216. member_type member;
  217. C *object;
  218. binder1(member_type m,C *o) :
  219. member(m),
  220. object(o)
  221. {
  222. }
  223. void operator()(std::string p1) const
  224. {
  225. page_guard<C> guard(object);
  226. (object->*member)(p1);
  227. }
  228. };
  229. template<typename C>
  230. struct binder2{
  231. typedef void (C::*member_type)(std::string,std::string);
  232. member_type member;
  233. C *object;
  234. binder2(member_type m,C *o) :
  235. member(m),
  236. object(o)
  237. {
  238. }
  239. void operator()(std::string p1,std::string p2) const
  240. {
  241. page_guard<C> guard(object);
  242. (object->*member)(p1,p2);
  243. }
  244. };
  245. template<typename C>
  246. struct binder3{
  247. typedef void (C::*member_type)(std::string,std::string,std::string);
  248. member_type member;
  249. C *object;
  250. binder3(member_type m,C *o) :
  251. member(m),
  252. object(o)
  253. {
  254. }
  255. void operator()(std::string p1,std::string p2,std::string p3) const
  256. {
  257. page_guard<C> guard(object);
  258. (object->*member)(p1,p2,p3);
  259. }
  260. };
  261. template<typename C>
  262. struct binder4{
  263. typedef void (C::*member_type)(std::string,std::string,std::string,std::string);
  264. member_type member;
  265. C *object;
  266. binder4(member_type m,C *o) :
  267. member(m),
  268. object(o)
  269. {
  270. }
  271. void operator()(std::string p1,std::string p2,std::string p3,std::string p4) const
  272. {
  273. page_guard<C> guard(object);
  274. (object->*member)(p1,p2,p3,p4);
  275. }
  276. };
  277. struct _data;
  278. booster::hold_ptr<_data> d;
  279. };
  280. } // cppcms
  281. #endif