Skip to content

Commit ae0b74c

Browse files
committed
Add null_safe_string_view(const char*, std::size_t)
[why] There are use cases for constructing a string_view with a specified size that is still protected against null pointers. This is different from safe_string_view(const char*, std::size_t) which terminates the string at a null byte. Signed-off-by: Lars Froehlich <lars.froehlich@desy.de>
1 parent 32041ec commit ae0b74c

3 files changed

Lines changed: 50 additions & 1 deletion

File tree

include/gul17/string_util.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ std::string null_safe_string(const char* char_ptr);
256256
* auto c = safe_string_view("AB\0CD"); // c == "AB"sv
257257
* \endcode
258258
*
259-
* \param char_ptr Pointer to a null-terminated string or a null pointer
259+
* \param char_ptr Pointer to a string that has at least \c length accessible bytes, or a
260+
* null pointer
260261
*
261262
* \see safe_string_view(), null_safe_string()
262263
*
@@ -265,6 +266,30 @@ std::string null_safe_string(const char* char_ptr);
265266
GUL_EXPORT
266267
std::string_view null_safe_string_view(const char* char_ptr);
267268

269+
/**
270+
* Safely construct a string_view from a char pointer and a length.
271+
*
272+
* If the pointer is null, an empty string_view is constructed. Otherwise, the function
273+
* constructs a std::string_view with the specified length from it. Zero bytes in the
274+
* input range do not terminate the string_view.
275+
*
276+
* \code
277+
* auto a = safe_string_view(nullptr, 10); // a == ""sv
278+
* auto b = safe_string_view("ABC", 4); // b == "ABC\0"sv
279+
* auto c = safe_string_view("AB\0CD", 4); // c == "AB\0C"sv
280+
* \endcode
281+
*
282+
* \param char_ptr Pointer to a string with at least \c length accessible bytes, or a
283+
* null pointer
284+
* \param length Length of the generated string_view (unless the pointer is null)
285+
*
286+
* \see safe_string_view(), null_safe_string()
287+
*
288+
* \since version UNRELEASED
289+
*/
290+
GUL_EXPORT
291+
std::string_view null_safe_string_view(const char* char_ptr, std::size_t length);
292+
268293
/**
269294
* Repeat a string N times.
270295
* \code

src/string_util.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ std::string_view null_safe_string_view(const char* char_ptr)
5050
return result;
5151
}
5252

53+
std::string_view null_safe_string_view(const char* char_ptr, std::size_t length)
54+
{
55+
std::string_view result;
56+
57+
if (char_ptr)
58+
result = std::string_view(char_ptr, length);
59+
60+
return result;
61+
}
62+
5363
std::string repeat(std::string_view str, std::size_t n)
5464
{
5565
std::string result;

tests/test_string_util.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,20 @@ TEST_CASE("null_safe_string_view(const char*)", "[string_util]")
134134
REQUIRE(null_safe_string_view("hi\0there") == "hi"sv);
135135
}
136136

137+
TEST_CASE("null_safe_string_view(const char*, std::size_t)", "[string_util]")
138+
{
139+
using gul17::null_safe_string_view;
140+
141+
REQUIRE(null_safe_string_view(nullptr, 0ull) == std::string_view{});
142+
REQUIRE(null_safe_string_view(nullptr, 10ull) == std::string_view{});
143+
REQUIRE(null_safe_string_view("", 0ull) == ""sv);
144+
REQUIRE(null_safe_string_view("", 1ull) == "\0"sv);
145+
REQUIRE(null_safe_string_view("hello", 5ull) == "hello"sv);
146+
REQUIRE(null_safe_string_view("hello", 2ull) == "he"sv);
147+
REQUIRE(null_safe_string_view("hi\0there", 2ull) == "hi"sv);
148+
REQUIRE(null_safe_string_view("hi\0there", 4ull) == "hi\0t"sv);
149+
}
150+
137151
TEST_CASE("repeat()", "[string_util]")
138152
{
139153
REQUIRE(repeat("du", 3) == "dududu");

0 commit comments

Comments
 (0)