pos_map.hpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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_DETAIL_TYPING_POS_MAP_HPP
  8. #define BOOST_MYSQL_DETAIL_TYPING_POS_MAP_HPP
  9. #include <boost/mysql/field_view.hpp>
  10. #include <boost/mysql/metadata.hpp>
  11. #include <boost/mysql/metadata_collection_view.hpp>
  12. #include <boost/mysql/string_view.hpp>
  13. #include <boost/assert.hpp>
  14. #include <boost/config.hpp>
  15. #include <boost/core/span.hpp>
  16. #include <cstddef>
  17. namespace boost {
  18. namespace mysql {
  19. namespace detail {
  20. // These functions map C++ type positions to positions to positions in the DB query
  21. BOOST_INLINE_CONSTEXPR std::size_t pos_absent = static_cast<std::size_t>(-1);
  22. using name_table_t = boost::span<const string_view>;
  23. inline bool has_field_names(name_table_t name_table) noexcept { return !name_table.empty(); }
  24. inline void pos_map_reset(span<std::size_t> self) noexcept
  25. {
  26. for (std::size_t i = 0; i < self.size(); ++i)
  27. self.data()[i] = pos_absent;
  28. }
  29. inline void pos_map_add_field(
  30. span<std::size_t> self,
  31. name_table_t name_table,
  32. std::size_t db_index,
  33. string_view field_name
  34. ) noexcept
  35. {
  36. if (has_field_names(name_table))
  37. {
  38. BOOST_ASSERT(self.size() == name_table.size());
  39. // We're mapping fields by name. Try to find where in our target struct
  40. // is the current field located
  41. auto it = std::find(name_table.begin(), name_table.end(), field_name);
  42. if (it != name_table.end())
  43. {
  44. std::size_t cpp_index = it - name_table.begin();
  45. self[cpp_index] = db_index;
  46. }
  47. }
  48. else
  49. {
  50. // We're mapping by position. Any extra trailing fields are discarded
  51. if (db_index < self.size())
  52. {
  53. self[db_index] = db_index;
  54. }
  55. }
  56. }
  57. inline field_view map_field_view(
  58. span<const std::size_t> self,
  59. std::size_t cpp_index,
  60. span<const field_view> array
  61. ) noexcept
  62. {
  63. BOOST_ASSERT(cpp_index < self.size());
  64. return array[self[cpp_index]];
  65. }
  66. inline const metadata& map_metadata(
  67. span<const std::size_t> self,
  68. std::size_t cpp_index,
  69. metadata_collection_view meta
  70. ) noexcept
  71. {
  72. BOOST_ASSERT(cpp_index < self.size());
  73. return meta[self[cpp_index]];
  74. }
  75. } // namespace detail
  76. } // namespace mysql
  77. } // namespace boost
  78. #endif