verb.ipp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. //
  2. // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_HTTP_IMPL_VERB_IPP
  10. #define BOOST_BEAST_HTTP_IMPL_VERB_IPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/throw_exception.hpp>
  13. #include <stdexcept>
  14. namespace boost {
  15. namespace beast {
  16. namespace http {
  17. namespace detail {
  18. template<class = void>
  19. inline
  20. string_view
  21. verb_to_string(verb v)
  22. {
  23. switch(v)
  24. {
  25. case verb::delete_: return "DELETE";
  26. case verb::get: return "GET";
  27. case verb::head: return "HEAD";
  28. case verb::post: return "POST";
  29. case verb::put: return "PUT";
  30. case verb::connect: return "CONNECT";
  31. case verb::options: return "OPTIONS";
  32. case verb::trace: return "TRACE";
  33. case verb::copy: return "COPY";
  34. case verb::lock: return "LOCK";
  35. case verb::mkcol: return "MKCOL";
  36. case verb::move: return "MOVE";
  37. case verb::propfind: return "PROPFIND";
  38. case verb::proppatch: return "PROPPATCH";
  39. case verb::search: return "SEARCH";
  40. case verb::unlock: return "UNLOCK";
  41. case verb::bind: return "BIND";
  42. case verb::rebind: return "REBIND";
  43. case verb::unbind: return "UNBIND";
  44. case verb::acl: return "ACL";
  45. case verb::report: return "REPORT";
  46. case verb::mkactivity: return "MKACTIVITY";
  47. case verb::checkout: return "CHECKOUT";
  48. case verb::merge: return "MERGE";
  49. case verb::msearch: return "M-SEARCH";
  50. case verb::notify: return "NOTIFY";
  51. case verb::subscribe: return "SUBSCRIBE";
  52. case verb::unsubscribe: return "UNSUBSCRIBE";
  53. case verb::patch: return "PATCH";
  54. case verb::purge: return "PURGE";
  55. case verb::mkcalendar: return "MKCALENDAR";
  56. case verb::link: return "LINK";
  57. case verb::unlink: return "UNLINK";
  58. case verb::unknown:
  59. return "<unknown>";
  60. }
  61. BOOST_THROW_EXCEPTION(std::invalid_argument{"unknown verb"});
  62. }
  63. template<class = void>
  64. verb
  65. string_to_verb(string_view v)
  66. {
  67. /*
  68. ACL
  69. BIND
  70. CHECKOUT
  71. CONNECT
  72. COPY
  73. DELETE
  74. GET
  75. HEAD
  76. LINK
  77. LOCK
  78. M-SEARCH
  79. MERGE
  80. MKACTIVITY
  81. MKCALENDAR
  82. MKCOL
  83. MOVE
  84. NOTIFY
  85. OPTIONS
  86. PATCH
  87. POST
  88. PROPFIND
  89. PROPPATCH
  90. PURGE
  91. PUT
  92. REBIND
  93. REPORT
  94. SEARCH
  95. SUBSCRIBE
  96. TRACE
  97. UNBIND
  98. UNLINK
  99. UNLOCK
  100. UNSUBSCRIBE
  101. */
  102. if(v.size() < 3)
  103. return verb::unknown;
  104. // s must be null terminated
  105. auto const eq =
  106. [](string_view sv, char const* s)
  107. {
  108. auto p = sv.data();
  109. for(;;)
  110. {
  111. if(*s != *p)
  112. return false;
  113. ++s;
  114. ++p;
  115. if(! *s)
  116. return p == sv.end();
  117. }
  118. };
  119. auto c = v[0];
  120. v.remove_prefix(1);
  121. switch(c)
  122. {
  123. case 'A':
  124. if(v == "CL")
  125. return verb::acl;
  126. break;
  127. case 'B':
  128. if(v == "IND")
  129. return verb::bind;
  130. break;
  131. case 'C':
  132. c = v[0];
  133. v.remove_prefix(1);
  134. switch(c)
  135. {
  136. case 'H':
  137. if(eq(v, "ECKOUT"))
  138. return verb::checkout;
  139. break;
  140. case 'O':
  141. if(eq(v, "NNECT"))
  142. return verb::connect;
  143. if(eq(v, "PY"))
  144. return verb::copy;
  145. BOOST_FALLTHROUGH;
  146. default:
  147. break;
  148. }
  149. break;
  150. case 'D':
  151. if(eq(v, "ELETE"))
  152. return verb::delete_;
  153. break;
  154. case 'G':
  155. if(eq(v, "ET"))
  156. return verb::get;
  157. break;
  158. case 'H':
  159. if(eq(v, "EAD"))
  160. return verb::head;
  161. break;
  162. case 'L':
  163. if(eq(v, "INK"))
  164. return verb::link;
  165. if(eq(v, "OCK"))
  166. return verb::lock;
  167. break;
  168. case 'M':
  169. c = v[0];
  170. v.remove_prefix(1);
  171. switch(c)
  172. {
  173. case '-':
  174. if(eq(v, "SEARCH"))
  175. return verb::msearch;
  176. break;
  177. case 'E':
  178. if(eq(v, "RGE"))
  179. return verb::merge;
  180. break;
  181. case 'K':
  182. if(eq(v, "ACTIVITY"))
  183. return verb::mkactivity;
  184. if(v[0] == 'C')
  185. {
  186. v.remove_prefix(1);
  187. if(eq(v, "ALENDAR"))
  188. return verb::mkcalendar;
  189. if(eq(v, "OL"))
  190. return verb::mkcol;
  191. break;
  192. }
  193. break;
  194. case 'O':
  195. if(eq(v, "VE"))
  196. return verb::move;
  197. BOOST_FALLTHROUGH;
  198. default:
  199. break;
  200. }
  201. break;
  202. case 'N':
  203. if(eq(v, "OTIFY"))
  204. return verb::notify;
  205. break;
  206. case 'O':
  207. if(eq(v, "PTIONS"))
  208. return verb::options;
  209. break;
  210. case 'P':
  211. c = v[0];
  212. v.remove_prefix(1);
  213. switch(c)
  214. {
  215. case 'A':
  216. if(eq(v, "TCH"))
  217. return verb::patch;
  218. break;
  219. case 'O':
  220. if(eq(v, "ST"))
  221. return verb::post;
  222. break;
  223. case 'R':
  224. if(eq(v, "OPFIND"))
  225. return verb::propfind;
  226. if(eq(v, "OPPATCH"))
  227. return verb::proppatch;
  228. break;
  229. case 'U':
  230. if(eq(v, "RGE"))
  231. return verb::purge;
  232. if(eq(v, "T"))
  233. return verb::put;
  234. BOOST_FALLTHROUGH;
  235. default:
  236. break;
  237. }
  238. break;
  239. case 'R':
  240. if(v[0] != 'E')
  241. break;
  242. v.remove_prefix(1);
  243. if(eq(v, "BIND"))
  244. return verb::rebind;
  245. if(eq(v, "PORT"))
  246. return verb::report;
  247. break;
  248. case 'S':
  249. if(eq(v, "EARCH"))
  250. return verb::search;
  251. if(eq(v, "UBSCRIBE"))
  252. return verb::subscribe;
  253. break;
  254. case 'T':
  255. if(eq(v, "RACE"))
  256. return verb::trace;
  257. break;
  258. case 'U':
  259. if(v[0] != 'N')
  260. break;
  261. v.remove_prefix(1);
  262. if(eq(v, "BIND"))
  263. return verb::unbind;
  264. if(eq(v, "LINK"))
  265. return verb::unlink;
  266. if(eq(v, "LOCK"))
  267. return verb::unlock;
  268. if(eq(v, "SUBSCRIBE"))
  269. return verb::unsubscribe;
  270. break;
  271. default:
  272. break;
  273. }
  274. return verb::unknown;
  275. }
  276. } // detail
  277. inline
  278. string_view
  279. to_string(verb v)
  280. {
  281. return detail::verb_to_string(v);
  282. }
  283. inline
  284. verb
  285. string_to_verb(string_view s)
  286. {
  287. return detail::string_to_verb(s);
  288. }
  289. } // http
  290. } // beast
  291. } // boost
  292. #endif