field_view.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 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. #ifndef BOOST_MYSQL_IMPL_FIELD_VIEW_HPP
  8. #define BOOST_MYSQL_IMPL_FIELD_VIEW_HPP
  9. #pragma once
  10. #include <boost/mysql/bad_field_access.hpp>
  11. #include <boost/mysql/field_view.hpp>
  12. #include <boost/assert.hpp>
  13. #include <boost/throw_exception.hpp>
  14. #include <cstring>
  15. #include <limits>
  16. namespace boost {
  17. namespace mysql {
  18. namespace detail {
  19. inline bool blobs_equal(blob_view b1, blob_view b2)
  20. {
  21. if (b1.size() != b2.size())
  22. return false;
  23. return b1.empty() || std::memcmp(b1.data(), b2.data(), b2.size()) == 0;
  24. }
  25. } // namespace detail
  26. } // namespace mysql
  27. } // namespace boost
  28. BOOST_CXX14_CONSTEXPR inline boost::mysql::field_kind boost::mysql::field_view::kind() const noexcept
  29. {
  30. switch (impl_.ikind)
  31. {
  32. case internal_kind::null: return field_kind::null;
  33. case internal_kind::int64: return field_kind::int64;
  34. case internal_kind::uint64: return field_kind::uint64;
  35. case internal_kind::string: return field_kind::string;
  36. case internal_kind::blob: return field_kind::blob;
  37. case internal_kind::float_: return field_kind::float_;
  38. case internal_kind::double_: return field_kind::double_;
  39. case internal_kind::date: return field_kind::date;
  40. case internal_kind::datetime: return field_kind::datetime;
  41. case internal_kind::time: return field_kind::time;
  42. case internal_kind::field_ptr: return impl_.repr.field_ptr->kind();
  43. // sv_offset values must be converted via offset_to_string_view before calling any other fn
  44. default: return field_kind::null;
  45. }
  46. }
  47. BOOST_CXX14_CONSTEXPR std::int64_t boost::mysql::field_view::as_int64() const
  48. {
  49. if (is_field_ptr())
  50. return impl_.repr.field_ptr->as<std::int64_t>();
  51. check_kind(internal_kind::int64);
  52. return impl_.repr.int64;
  53. }
  54. BOOST_CXX14_CONSTEXPR std::uint64_t boost::mysql::field_view::as_uint64() const
  55. {
  56. if (is_field_ptr())
  57. return impl_.repr.field_ptr->as<std::uint64_t>();
  58. check_kind(internal_kind::uint64);
  59. return impl_.repr.uint64;
  60. }
  61. BOOST_CXX14_CONSTEXPR boost::mysql::string_view boost::mysql::field_view::as_string() const
  62. {
  63. if (is_field_ptr())
  64. return impl_.repr.field_ptr->as<std::string>();
  65. check_kind(internal_kind::string);
  66. return impl_.repr.string;
  67. }
  68. BOOST_CXX14_CONSTEXPR boost::mysql::blob_view boost::mysql::field_view::as_blob() const
  69. {
  70. if (is_field_ptr())
  71. return impl_.repr.field_ptr->as<blob>();
  72. check_kind(internal_kind::blob);
  73. return impl_.repr.blob;
  74. }
  75. BOOST_CXX14_CONSTEXPR float boost::mysql::field_view::as_float() const
  76. {
  77. if (is_field_ptr())
  78. return impl_.repr.field_ptr->as<float>();
  79. check_kind(internal_kind::float_);
  80. return impl_.repr.float_;
  81. }
  82. BOOST_CXX14_CONSTEXPR double boost::mysql::field_view::as_double() const
  83. {
  84. if (is_field_ptr())
  85. return impl_.repr.field_ptr->as<double>();
  86. check_kind(internal_kind::double_);
  87. return impl_.repr.double_;
  88. }
  89. BOOST_CXX14_CONSTEXPR boost::mysql::date boost::mysql::field_view::as_date() const
  90. {
  91. if (is_field_ptr())
  92. return impl_.repr.field_ptr->as<date>();
  93. check_kind(internal_kind::date);
  94. return impl_.repr.date_;
  95. }
  96. BOOST_CXX14_CONSTEXPR boost::mysql::datetime boost::mysql::field_view::as_datetime() const
  97. {
  98. if (is_field_ptr())
  99. return impl_.repr.field_ptr->as<datetime>();
  100. check_kind(internal_kind::datetime);
  101. return impl_.repr.datetime_;
  102. }
  103. BOOST_CXX14_CONSTEXPR boost::mysql::time boost::mysql::field_view::as_time() const
  104. {
  105. if (is_field_ptr())
  106. return impl_.repr.field_ptr->as<time>();
  107. check_kind(internal_kind::time);
  108. return impl_.repr.time_;
  109. }
  110. BOOST_CXX14_CONSTEXPR void boost::mysql::field_view::check_kind(internal_kind expected) const
  111. {
  112. if (impl_.ikind != expected)
  113. BOOST_THROW_EXCEPTION(bad_field_access());
  114. }
  115. BOOST_CXX14_CONSTEXPR bool boost::mysql::field_view::operator==(const field_view& rhs) const noexcept
  116. {
  117. // Make operator== work for types not representable by field_kind
  118. if (impl_.ikind == internal_kind::sv_offset_string || impl_.ikind == internal_kind::sv_offset_blob)
  119. {
  120. return rhs.impl_.ikind == impl_.ikind && impl_.repr.sv_offset_ == rhs.impl_.repr.sv_offset_;
  121. }
  122. auto k = kind(), rhs_k = rhs.kind();
  123. switch (k)
  124. {
  125. case field_kind::null: return rhs_k == field_kind::null;
  126. case field_kind::int64:
  127. if (rhs_k == field_kind::int64)
  128. return get_int64() == rhs.get_int64();
  129. else if (rhs_k == field_kind::uint64)
  130. {
  131. std::int64_t this_val = get_int64();
  132. if (this_val < 0)
  133. return false;
  134. else
  135. return static_cast<std::uint64_t>(this_val) == rhs.get_uint64();
  136. }
  137. else
  138. return false;
  139. case field_kind::uint64:
  140. if (rhs_k == field_kind::uint64)
  141. return get_uint64() == rhs.get_uint64();
  142. else if (rhs_k == field_kind::int64)
  143. {
  144. std::int64_t rhs_val = rhs.get_int64();
  145. if (rhs_val < 0)
  146. return false;
  147. else
  148. return static_cast<std::uint64_t>(rhs_val) == get_uint64();
  149. }
  150. else
  151. return false;
  152. case field_kind::string: return rhs_k == field_kind::string && get_string() == rhs.get_string();
  153. case field_kind::blob:
  154. return rhs_k == field_kind::blob && detail::blobs_equal(get_blob(), rhs.get_blob());
  155. case field_kind::float_: return rhs_k == field_kind::float_ && get_float() == rhs.get_float();
  156. case field_kind::double_: return rhs_k == field_kind::double_ && get_double() == rhs.get_double();
  157. case field_kind::date: return rhs_k == field_kind::date && get_date() == rhs.get_date();
  158. case field_kind::datetime: return rhs_k == field_kind::datetime && get_datetime() == rhs.get_datetime();
  159. case field_kind::time: return rhs_k == field_kind::time && get_time() == rhs.get_time();
  160. default: BOOST_ASSERT(false); return false;
  161. }
  162. }
  163. #endif