Skip to content

Commit

Permalink
Permit conversion to string of std::string_view. (#730)
Browse files Browse the repository at this point in the history
Fixes #728.

I've been reluctant to implement this because it could pose a larger
runtime cost than the caller might expect.  We need to copy the whole
underlying string into the available buffer just to ensure termination.

But as the bug shows, users may need the conversion in order to pass
arrays of `string_view` as statement parameters.
  • Loading branch information
jtv committed Sep 6, 2023
1 parent 1e02a1a commit 9847c82
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
7.8.2
- Fix broken `to_buf()` on `zview`. (#728)
- Support `PQfsize()` and `PQfmod()`. (#727)
- Implement conversion from `string_view` to string. (#728)
7.8.1
- Regenerate build files. Should fix ARM Mac build. (#715)
- Reinstate `<ciso646>` that MSVC can't live with or without. (#713)
Expand Down
7 changes: 7 additions & 0 deletions include/pqxx/internal/conversions.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,13 @@ template<> struct string_traits<std::string_view>
return begin + std::size(value) + 1;
}

static zview to_buf(char *begin, char *end, std::string_view const &value)
{
// You'd think we could just return the same view but alas, there's no
// zero-termination on a string_view.
return generic_to_buf(begin, end, value);
}

/// Don't convert to this type; it has nowhere to store its contents.
static std::string_view from_string(std::string_view) = delete;
};
Expand Down
38 changes: 38 additions & 0 deletions test/unit/test_string_conversion.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

#include "../test_helpers.hxx"

using namespace std::literals;


// Some enums with string conversions.
enum EnumA
{
Expand Down Expand Up @@ -171,8 +174,43 @@ void test_convert_null()
}


void test_string_view_conversion()
{
using traits = pqxx::string_traits<std::string_view>;

PQXX_CHECK_EQUAL(
pqxx::to_string("view here"sv),
"view here"s,
"Bad conversion from string_view.");

char buf[200];

char *end{traits::into_buf(std::begin(buf), std::end(buf), "more view"sv)};
PQXX_CHECK(
std::begin(buf) < end and end < std::end(buf),
"string_view into_buf did not stay within its buffer.");
PQXX_CHECK(
*(end - 1) == '\0', "string_view into_buf did not zero-terminate.");
PQXX_CHECK_EQUAL(
(std::string{buf, static_cast<std::size_t>(end - std::begin(buf) - 1)}),
"more view"s,
"string_view into_buf wrote wrong data.");
PQXX_CHECK(
*(end - 2) == 'w', "string_view into_buf is in the wrong place.");

std::string_view org{"another!"sv};
pqxx::zview out{traits::to_buf(std::begin(buf), std::end(buf), org)};
PQXX_CHECK_EQUAL(
std::string{out}, "another!"s, "string_view to_buf returned wrong data.");
PQXX_CHECK(
std::data(out) != std::data(org),
"string_view to_buf returned original view, which may not be terminated.");
}


PQXX_REGISTER_TEST(test_string_conversion);
PQXX_REGISTER_TEST(test_convert_variant_to_string);
PQXX_REGISTER_TEST(test_integer_conversion);
PQXX_REGISTER_TEST(test_convert_null);
PQXX_REGISTER_TEST(test_string_view_conversion);
} // namespace

0 comments on commit 9847c82

Please sign in to comment.