common.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /*
  2. * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License, version 2.0, as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is also distributed with certain software (including
  9. * but not limited to OpenSSL) that is licensed under separate terms,
  10. * as designated in a particular file or component or in included license
  11. * documentation. The authors of MySQL hereby grant you an
  12. * additional permission to link the program and your derivative works
  13. * with the separately licensed software that they have included with
  14. * MySQL.
  15. *
  16. * Without limiting anything contained in the foregoing, this file,
  17. * which is part of MySQL Connector/C++, is also subject to the
  18. * Universal FOSS Exception, version 1.0, a copy of which can be found at
  19. * http://oss.oracle.com/licenses/universal-foss-exception.
  20. *
  21. * This program is distributed in the hope that it will be useful, but
  22. * WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  24. * See the GNU General Public License, version 2.0, for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software Foundation, Inc.,
  28. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #ifndef MYSQLX_COMMON_H
  31. #define MYSQLX_COMMON_H
  32. #include "../common.h"
  33. #include <string>
  34. #include <stdexcept>
  35. #include <ostream>
  36. #include <memory>
  37. #include <forward_list>
  38. #include <string.h> // for memcpy
  39. #include <utility> // std::move etc
  40. namespace cdk {
  41. namespace foundation {
  42. class bytes;
  43. class string;
  44. }} // cdk::foundation
  45. namespace mysqlx {
  46. using std::out_of_range;
  47. using common::byte;
  48. class Value;
  49. /**
  50. A wrapper around std::wstring that can perform
  51. conversions from/to different character encodings
  52. used by MySQL.
  53. Currently only utf-8 encoding is supported.
  54. @ingroup devapi_aux
  55. */
  56. class string : public std::wstring
  57. {
  58. struct Impl
  59. {
  60. PUBLIC_API static std::string to_utf8(const string&);
  61. PUBLIC_API static void from_utf8(string&, const std::string&);
  62. };
  63. public:
  64. string() {}
  65. string(const wchar_t *other)
  66. {
  67. if (other)
  68. assign(other);
  69. }
  70. string(const std::wstring &other) : std::wstring(other) {}
  71. string(std::wstring &&other) : std::wstring(std::move(other)) {}
  72. // TODO: make utf8 conversions explicit
  73. string(const char *other)
  74. {
  75. if (!other)
  76. return;
  77. std::string utf8(other);
  78. Impl::from_utf8(*this, utf8);
  79. }
  80. string(const std::string &other)
  81. {
  82. Impl::from_utf8(*this, other);
  83. }
  84. string(const common::Value&);
  85. string(const Value &val);
  86. // conversion to utf-8
  87. operator std::string() const
  88. {
  89. return Impl::to_utf8(*this);
  90. }
  91. };
  92. inline
  93. string::string(const common::Value &val)
  94. {
  95. switch (val.get_type())
  96. {
  97. case common::Value::STRING:
  98. Impl::from_utf8(*this, val.get_string());
  99. return;
  100. default:
  101. assign(val.get_wstring());
  102. }
  103. }
  104. inline
  105. std::ostream& operator<<(std::ostream &out, const string &str)
  106. {
  107. const std::string utf8(str);
  108. out << utf8;
  109. return out;
  110. }
  111. typedef unsigned long col_count_t;
  112. typedef unsigned long row_count_t;
  113. /**
  114. Class representing a region of memory holding raw bytes.
  115. Method `begin()` returns pointer to the first byte in the
  116. region, `end()` to one past the last byte in the region.
  117. @note An instance of `bytes` does not store the bytes -
  118. it merely describes a region of memory and is equivalent
  119. to a pair of pointers. It is very cheap to copy `bytes` and
  120. pass them by value.
  121. @note This class extends std::pair<byte *, size_t> to make
  122. it consistent with how memory regions are described by
  123. std::get_temporary_buffer(). It is also possible to initialize
  124. a `bytes` instance by buffer returned from
  125. std::get_temporary_buffer(), as follows:
  126. bytes buf = std::get_temporary_buffer<byte>(size);
  127. @ingroup devapi_aux
  128. */
  129. class bytes : public std::pair<const byte*, size_t>
  130. {
  131. public:
  132. bytes(const byte *beg_, const byte *end_)
  133. : pair(beg_, end_ - beg_)
  134. {}
  135. bytes(const byte *beg, size_t len) : pair(beg, len)
  136. {}
  137. bytes(const char *str) : pair((const byte*)str, 0)
  138. {
  139. if (nullptr != str)
  140. second = strlen(str);
  141. }
  142. bytes(std::pair<const byte*, size_t> buf) : pair(buf)
  143. {}
  144. bytes() : pair(nullptr, 0)
  145. {}
  146. bytes(const bytes &) = default;
  147. virtual const byte* begin() const { return first; }
  148. virtual const byte* end() const { return first + second; }
  149. size_t length() const { return second; }
  150. size_t size() const { return length(); }
  151. class Access;
  152. friend Access;
  153. };
  154. /**
  155. Base class for connector errors.
  156. @internal
  157. TODO: Derive from std::system_error and introduce proper
  158. error codes.
  159. @endinternal
  160. @ingroup devapi
  161. */
  162. // TODO: Make it header-only class somehow...
  163. DLL_WARNINGS_PUSH
  164. class PUBLIC_API Error : public common::Error
  165. {
  166. DLL_WARNINGS_POP
  167. public:
  168. Error(const char *msg)
  169. : common::Error(msg)
  170. {}
  171. };
  172. #define CATCH_AND_WRAP \
  173. catch (const ::mysqlx::Error&) { throw; } \
  174. catch (const std::out_of_range&) { throw; } \
  175. catch (const std::exception &e) \
  176. { throw ::mysqlx::Error(e.what()); } \
  177. catch (const char *e) \
  178. { throw ::mysqlx::Error(e); } \
  179. catch (...) \
  180. { throw ::mysqlx::Error("Unknown exception"); } \
  181. inline
  182. void throw_error(const char *msg)
  183. {
  184. throw ::mysqlx::Error(msg);
  185. }
  186. /*
  187. Infrastructure for type-agnostic handling of lists
  188. ==================================================
  189. Template internal::List_initializer<> defined below is used to return lists
  190. of values from public API method so that user can store this list in
  191. a container of his choice. The only requirement is that the container instance
  192. should be constructible from two iterators defining a range of elements
  193. (such constructors exists for standard STL containers, for example).
  194. Thus, given a public API method foo() which returns a List_initializer<> for
  195. lists of elements of type X, user can do the following:
  196. My_container cont = foo();
  197. The container will be constructed as if this code was executed:
  198. My_container cont = My_container(begin, end);
  199. where begin and end are STL iterators defining a range of elements of type X.
  200. This is implemented by defining templated conversion operator.
  201. Apart from initializing containers, values of List_initializer<> type can
  202. be iterated using a range loop:
  203. for(X &el : foo()) { ... }
  204. Otherwise, user should not be able to use List_initializer<> values directly.
  205. */
  206. namespace internal {
  207. /*
  208. Iterator template.
  209. It defines an STL input iterator which is implemented using an
  210. implementation object of some type Impl. It is assumed that Impl
  211. has the following methods:
  212. void iterator_start() - puts iterator in "before begin" position;
  213. bool iterator_next() - moves iterator to next position, returns
  214. false if it was not possible;
  215. Value_type iterator_get() - gets current value.
  216. An implementation object must be passed to iterator constructor. Iterator
  217. stores only a pointer to this implementation (so it must exist as long as
  218. iterator is used).
  219. */
  220. template<
  221. typename Impl,
  222. typename T = typename std::iterator_traits<Impl>::value_type,
  223. typename Distance = typename std::iterator_traits<T*>::difference_type,
  224. typename Pointer = typename std::iterator_traits<T*>::pointer,
  225. typename Reference = typename std::iterator_traits<T*>::reference
  226. >
  227. struct Iterator
  228. : std::iterator < std::input_iterator_tag, T, Distance, Pointer, Reference >
  229. {
  230. protected:
  231. typename std::remove_reference<Impl>::type *m_impl = NULL;
  232. bool m_at_end = false;
  233. public:
  234. Iterator(Impl& impl)
  235. : m_impl(&impl)
  236. {
  237. m_impl->iterator_start();
  238. m_at_end = !m_impl->iterator_next();
  239. }
  240. Iterator()
  241. : m_at_end(true)
  242. {}
  243. bool operator !=(const Iterator &other) const
  244. {
  245. /*
  246. Compares only if both iterators are at the end
  247. of the sequence.
  248. */
  249. return !(m_at_end && other.m_at_end);
  250. }
  251. Iterator& operator++()
  252. {
  253. try {
  254. if (m_impl && !m_at_end)
  255. m_at_end = !m_impl->iterator_next();
  256. return *this;
  257. }
  258. CATCH_AND_WRAP
  259. }
  260. T operator*() const
  261. {
  262. if (!m_impl || m_at_end)
  263. THROW("Attempt to dereference null iterator");
  264. try {
  265. return m_impl->iterator_get();
  266. }
  267. CATCH_AND_WRAP
  268. }
  269. friend Impl;
  270. };
  271. /*
  272. List_initializer object can be used to initialize a container of
  273. arbitrary type U with list of items taken from a source object.
  274. It is assumed that the source object type Source defines iterator
  275. type and that std::begin/end() return iterators to the beginning
  276. and end of the sequence. The container type U is assumed to have
  277. a constructor from begin/end iterator.
  278. List_iterator defines begin/end() methods, so it is possible to
  279. iterate over the sequence without storing it in any container.
  280. */
  281. template <class Source>
  282. class List_initializer
  283. {
  284. protected:
  285. Source m_src;
  286. friend Source;
  287. public:
  288. typedef typename std::remove_reference<Source>::type::iterator iterator;
  289. /*
  290. Arguments given to the constructor are passed to the internal
  291. m_src object.
  292. */
  293. template <typename... Ty>
  294. List_initializer(Ty&&... args)
  295. : m_src(std::forward<Ty>(args)...)
  296. {}
  297. /*
  298. Narrow the set of types for which this template is instantiated
  299. to avoid ambiguous conversion errors. It is important to disallow
  300. conversion to std::initializer_list<> because this conversion path
  301. is considered when assigning to STL containers.
  302. */
  303. template <
  304. typename U
  305. , typename std::is_constructible<
  306. U, const iterator&, const iterator&
  307. >::type* = nullptr
  308. , typename std::enable_if<
  309. ! std::is_same< U, std::initializer_list<typename U::value_type> >::value
  310. >::type* = nullptr
  311. >
  312. operator U()
  313. {
  314. try {
  315. return U(std::begin(m_src), std::end(m_src));
  316. }
  317. CATCH_AND_WRAP
  318. }
  319. iterator begin()
  320. {
  321. try {
  322. return std::begin(m_src);
  323. }
  324. CATCH_AND_WRAP
  325. }
  326. iterator end() const
  327. {
  328. try {
  329. return std::end(m_src);
  330. }
  331. CATCH_AND_WRAP
  332. }
  333. };
  334. template <typename T>
  335. struct iterator_traits
  336. {
  337. using value_type = typename std::remove_reference<T>::type;
  338. using difference_type
  339. = typename std::iterator_traits<value_type*>::difference_type;
  340. using pointer
  341. = typename std::iterator_traits<value_type*>::pointer;
  342. using reference
  343. = typename std::iterator_traits<value_type*>::reference;
  344. };
  345. /*
  346. This helper template adapts class Impl to be used as a source for
  347. List_initializer<> template.
  348. Class Impl should be suitable for the Iterator<> template which is used to
  349. build iterators required by List_initializer<>. That is, Impl should
  350. implement iterator_start(), iteratore_next() etc (see Iterator<>).
  351. */
  352. template<
  353. typename Impl,
  354. typename Value_type = typename Impl::Value,
  355. typename Distance = typename iterator_traits<Value_type>::difference_type,
  356. typename Pointer = typename iterator_traits<Value_type>::pointer,
  357. typename Reference = typename iterator_traits<Value_type>::reference
  358. >
  359. class List_source
  360. {
  361. protected:
  362. Impl m_impl;
  363. public:
  364. template <typename... Ty>
  365. List_source(Ty&&... args)
  366. : m_impl(std::forward<Ty>(args)...)
  367. {}
  368. using iterator = Iterator<Impl, Value_type, Distance, Pointer, Reference>;
  369. iterator begin()
  370. {
  371. return iterator(m_impl);
  372. }
  373. iterator end() const
  374. {
  375. return iterator();
  376. }
  377. };
  378. /*
  379. A template used to adapt an object of class Impl that represents an array of
  380. values accessed via operator[] to be used as source for List_initializer<>
  381. template. This template uses instance of Impl to implement the iterator
  382. methods iterator_start(), so that it can be used with Iterator<> template.
  383. */
  384. template <typename Impl, typename Value_type = typename Impl::Value>
  385. class Array_src_impl
  386. {
  387. protected:
  388. Impl m_impl;
  389. size_t m_pos = 0;
  390. bool m_at_begin = true;
  391. public:
  392. template <typename... Ty>
  393. Array_src_impl(Ty&&... args)
  394. : m_impl(std::forward<Ty>(args)...)
  395. {}
  396. void iterator_start()
  397. {
  398. m_pos = 0;
  399. m_at_begin = true;
  400. }
  401. bool iterator_next()
  402. {
  403. if (m_at_begin)
  404. m_at_begin = false;
  405. else
  406. m_pos++;
  407. return m_pos < size();
  408. }
  409. Value_type iterator_get()
  410. {
  411. return operator[](m_pos);
  412. }
  413. Value_type operator[](size_t pos)
  414. {
  415. return m_impl[pos];
  416. }
  417. size_t size() const
  418. {
  419. return m_impl.size();
  420. }
  421. };
  422. /*
  423. This template adapts an object of type Impl holding an array of values as
  424. a source for List_initializer<> template. It combines List_source<> and
  425. Array_src_impl<> adapters.
  426. */
  427. template<
  428. typename Impl,
  429. typename Value_type = typename Impl::Value,
  430. typename Distance = typename iterator_traits<Value_type>::difference_type,
  431. typename Pointer = typename iterator_traits<Value_type>::pointer,
  432. typename Reference = typename iterator_traits<Value_type>::reference
  433. >
  434. class Array_source
  435. : public List_source<
  436. Array_src_impl<Impl, Value_type>,
  437. Value_type,
  438. Distance,
  439. Pointer,
  440. Reference
  441. >
  442. {
  443. using Base = List_source<
  444. Array_src_impl<Impl, Value_type>,
  445. Value_type,
  446. Distance,
  447. Pointer,
  448. Reference
  449. >;
  450. using Base::m_impl;
  451. public:
  452. using
  453. List_source<
  454. Array_src_impl<Impl, Value_type>,
  455. Value_type,
  456. Distance,
  457. Pointer,
  458. Reference
  459. >::List_source;
  460. Value_type operator[](size_t pos)
  461. {
  462. return m_impl[pos];
  463. }
  464. size_t size() const
  465. {
  466. return m_impl.size();
  467. }
  468. };
  469. }
  470. /*
  471. Infrastructure for handling variable argument lists
  472. ===================================================
  473. See documentation of Args_processor<> template.
  474. */
  475. namespace internal {
  476. /*
  477. Type trait which checks if std::begin()/end() work on objects of given
  478. class C, so that it can be used as a range to iterate over.
  479. TODO: Make it work also with user-defined begin()/end() functions.
  480. TODO: Make it work with plain C arrays. For example:
  481. int vals[] = { 1, 2, 3 }
  482. process_args(data, vals)
  483. */
  484. template <class C>
  485. class is_range
  486. {
  487. /*
  488. Note: This overload is taken into account only if std::begin(X) and
  489. std::end(X) expressions are valid.
  490. */
  491. template <class X>
  492. static std::true_type
  493. test(
  494. decltype(std::begin(*((X*)nullptr)))*,
  495. decltype(std::end(*((X*)nullptr)))*
  496. );
  497. template <class X>
  498. static std::false_type test(...);
  499. public:
  500. static const bool value = std::is_same<
  501. std::true_type,
  502. decltype(test<C>(nullptr, nullptr))
  503. >::value;
  504. };
  505. /*
  506. Class template to be used for uniform processing of variable argument lists
  507. in public API methods. This template handles the cases where arguments
  508. are specified directly as a list:
  509. method(arg1, arg2, ..., argN)
  510. or they are taken from a container such as std::list:
  511. method(container)
  512. or they are taken from a range of items described by two iterators:
  513. method(begin, end)
  514. A class B that is using this template to define a varargs method 'foo'
  515. should define it as follows:
  516. template <typename... T>
  517. X foo(T... args)
  518. {
  519. Args_processor<B>::process_args(m_impl, args...);
  520. return ...;
  521. }
  522. Process_args() is a static method of Args_processor<> and therefore
  523. additional context data is passed to it as the first argument. By default
  524. this context is a pointer to internal implementation object, as defined
  525. by the base class B. The process_args() methods does all the necessary
  526. processing of the variable argument list, passing the resulting items
  527. one-by-one to B::process_one() method. Base class B must define this
  528. static method, which takes the context and one data item as arguments.
  529. B::process_one() method can have overloads that handle different types
  530. of data items.
  531. See devapi/detail/crud.h for usage examples.
  532. */
  533. template <class Base, class D = typename Base::Impl*>
  534. class Args_processor
  535. {
  536. public:
  537. /*
  538. Check if item of type T can be passed to Base::process_one()
  539. */
  540. template <typename T>
  541. class can_process
  542. {
  543. template <typename X>
  544. static std::true_type
  545. test(decltype(Base::process_one(*(D*)nullptr,*(X*)nullptr))*);
  546. template <typename X>
  547. static std::false_type test(...);
  548. public:
  549. static const bool value
  550. = std::is_same< std::true_type, decltype(test<T>(nullptr)) >::value;
  551. };
  552. public:
  553. /*
  554. Process items from a container.
  555. */
  556. template <
  557. typename C,
  558. typename std::enable_if<is_range<C>::value>::type* = nullptr,
  559. typename std::enable_if<!can_process<C>::value>::type* = nullptr
  560. >
  561. static void process_args(D data, C container)
  562. {
  563. // TODO: use (const) reference to avoid copying instances?
  564. for (auto el : container)
  565. {
  566. Base::process_one(data, el);
  567. }
  568. }
  569. /*
  570. If process_args(data, a, b) is called and a,b are of the same type It
  571. which can not be passed to Base::process_one() then we assume that a and
  572. b are iterators that describe a range of elements to process.
  573. */
  574. template <
  575. typename It,
  576. typename std::enable_if<!can_process<It>::value>::type* = nullptr
  577. >
  578. static void process_args(D data, const It &begin, const It &end)
  579. {
  580. for (It it = begin; it != end; ++it)
  581. {
  582. Base::process_one(data, *it);
  583. }
  584. }
  585. /*
  586. Process elements given as a varargs list.
  587. */
  588. template <
  589. typename T,
  590. typename... R,
  591. typename std::enable_if<can_process<T>::value>::type* = nullptr
  592. >
  593. static void process_args(D data, T first, R&&... rest)
  594. {
  595. process_args1(data, first, std::forward<R>(rest)...);
  596. }
  597. private:
  598. template <
  599. typename T,
  600. typename... R,
  601. typename std::enable_if<can_process<T>::value>::type* = nullptr
  602. >
  603. static void process_args1(D data, T first, R&&... rest)
  604. {
  605. Base::process_one(data, first);
  606. process_args1(data, std::forward<R>(rest)...);
  607. }
  608. static void process_args1(D)
  609. {}
  610. };
  611. } // internal namespace
  612. } // mysqlx
  613. #endif