File indexing completed on 2025-07-12 08:21:21
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_ROW_IMPL_IPP
0009 #define BOOST_MYSQL_IMPL_ROW_IMPL_IPP
0010
0011 #pragma once
0012
0013 #include <boost/mysql/detail/row_impl.hpp>
0014
0015 namespace boost {
0016 namespace mysql {
0017 namespace detail {
0018
0019 inline std::size_t get_string_size(field_view f)
0020 {
0021 switch (f.kind())
0022 {
0023 case field_kind::string: return f.get_string().size();
0024 case field_kind::blob: return f.get_blob().size();
0025 default: return 0;
0026 }
0027 }
0028
0029 inline unsigned char* copy_string(unsigned char* buffer_it, field_view& f)
0030 {
0031 auto str = f.get_string();
0032 if (!str.empty())
0033 {
0034 std::memcpy(buffer_it, str.data(), str.size());
0035 f = field_view(string_view(reinterpret_cast<const char*>(buffer_it), str.size()));
0036 buffer_it += str.size();
0037 }
0038 return buffer_it;
0039 }
0040
0041 inline unsigned char* copy_blob(unsigned char* buffer_it, field_view& f)
0042 {
0043 auto b = f.get_blob();
0044 if (!b.empty())
0045 {
0046 std::memcpy(buffer_it, b.data(), b.size());
0047 f = field_view(blob_view(buffer_it, b.size()));
0048 buffer_it += b.size();
0049 }
0050 return buffer_it;
0051 }
0052
0053 inline std::size_t copy_string_as_offset(unsigned char* buffer_first, std::size_t offset, field_view& f)
0054 {
0055 auto str = f.get_string();
0056 if (!str.empty())
0057 {
0058 std::memcpy(buffer_first + offset, str.data(), str.size());
0059 f = detail::access::construct<field_view>(detail::string_view_offset{offset, str.size()}, false);
0060 return str.size();
0061 }
0062 return 0;
0063 }
0064
0065 inline std::size_t copy_blob_as_offset(unsigned char* buffer_first, std::size_t offset, field_view& f)
0066 {
0067 auto str = f.get_blob();
0068 if (!str.empty())
0069 {
0070 std::memcpy(buffer_first + offset, str.data(), str.size());
0071 f = detail::access::construct<field_view>(detail::string_view_offset{offset, str.size()}, true);
0072 return str.size();
0073 }
0074 return 0;
0075 }
0076
0077 inline void copy_strings(std::vector<field_view>& fields, std::vector<unsigned char>& string_buffer)
0078 {
0079
0080 std::size_t size = 0;
0081 for (auto f : fields)
0082 {
0083 size += get_string_size(f);
0084 }
0085
0086
0087 string_buffer.resize(string_buffer.size() + size);
0088
0089
0090 unsigned char* buffer_it = string_buffer.data();
0091 for (auto& f : fields)
0092 {
0093 switch (f.kind())
0094 {
0095 case field_kind::string: buffer_it = copy_string(buffer_it, f); break;
0096 case field_kind::blob: buffer_it = copy_blob(buffer_it, f); break;
0097 default: break;
0098 }
0099 }
0100 BOOST_ASSERT(buffer_it == string_buffer.data() + size);
0101 }
0102
0103 inline field_view offset_to_string_view(field_view fv, const std::uint8_t* buffer_first)
0104 {
0105 auto& impl = detail::access::get_impl(fv);
0106 if (impl.is_string_offset())
0107 {
0108 return field_view(string_view(
0109 reinterpret_cast<const char*>(buffer_first) + impl.repr.sv_offset_.offset,
0110 impl.repr.sv_offset_.size
0111 ));
0112 }
0113 else if (impl.is_blob_offset())
0114 {
0115 return field_view(blob_view(buffer_first + impl.repr.sv_offset_.offset, impl.repr.sv_offset_.size));
0116 }
0117 else
0118 {
0119 return fv;
0120 }
0121 }
0122
0123 }
0124 }
0125 }
0126
0127 boost::mysql::detail::row_impl::row_impl(const field_view* fields, std::size_t size)
0128 : fields_(fields, fields + size)
0129 {
0130 copy_strings(fields_, string_buffer_);
0131 }
0132
0133 boost::mysql::detail::row_impl::row_impl(const row_impl& rhs) : fields_(rhs.fields_)
0134 {
0135 copy_strings(fields_, string_buffer_);
0136 }
0137
0138 boost::mysql::detail::row_impl& boost::mysql::detail::row_impl::operator=(const row_impl& rhs)
0139 {
0140 assign(rhs.fields_.data(), rhs.fields_.size());
0141 return *this;
0142 }
0143
0144 void boost::mysql::detail::row_impl::assign(const field_view* fields, std::size_t size)
0145 {
0146
0147
0148 if (fields_.data() == fields)
0149 {
0150 BOOST_ASSERT(fields_.size() == size);
0151 }
0152 else
0153 {
0154 fields_.assign(fields, fields + size);
0155 string_buffer_.clear();
0156 copy_strings(fields_, string_buffer_);
0157 }
0158 }
0159
0160 void boost::mysql::detail::row_impl::copy_strings_as_offsets(std::size_t first, std::size_t num_fields)
0161 {
0162
0163 BOOST_ASSERT(first <= fields_.size());
0164 BOOST_ASSERT(first + num_fields <= fields_.size());
0165
0166
0167 std::size_t size = 0;
0168 for (std::size_t i = first; i < first + num_fields; ++i)
0169 {
0170 size += get_string_size(fields_[i]);
0171 }
0172
0173
0174 std::size_t old_string_buffer_size = string_buffer_.size();
0175 string_buffer_.resize(old_string_buffer_size + size);
0176
0177
0178 std::size_t offset = old_string_buffer_size;
0179 for (std::size_t i = first; i < first + num_fields; ++i)
0180 {
0181 auto& f = fields_[i];
0182 switch (f.kind())
0183 {
0184 case field_kind::string: offset += copy_string_as_offset(string_buffer_.data(), offset, f); break;
0185 case field_kind::blob: offset += copy_blob_as_offset(string_buffer_.data(), offset, f); break;
0186 default: break;
0187 }
0188 }
0189 BOOST_ASSERT(offset == string_buffer_.size());
0190 }
0191
0192 void boost::mysql::detail::row_impl::offsets_to_string_views()
0193 {
0194 for (auto& f : fields_)
0195 f = offset_to_string_view(f, string_buffer_.data());
0196 }
0197
0198 #endif