From be6cce5530eac99c8b9c6291e01f600a42ac18f5 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Tue, 25 Aug 2020 17:23:18 +0300 Subject: [PATCH] AK: Add String::copy_characters_to_buffer() This is a strcpy()-like method with actually sane semantics: * It accepts a non-empty buffer along with its size in bytes. * It copies as much of the string as fits into the buffer. * It always null-terminates the result. * It returns, as a non-discardable boolean, whether the whole string has been copied. Intended usage looks like this: bool fits = string.copy_characters_to_buffer(buffer, sizeof(buffer)); and then either if (!fits) { fprintf(stderr, "The name does not fit!!11"); return nullptr; } or, if you're sure the buffer is large enough, // I'm totally sure it fits because [reasons go here]. ASSERT(fits); or if you're feeling extremely adventurous, (void)fits; but don't do that, please. --- AK/String.cpp | 12 ++++++++++++ AK/String.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/AK/String.cpp b/AK/String.cpp index ab7f3dbcc0e..4cb7f874eab 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -106,6 +106,18 @@ String String::empty() return StringImpl::the_empty_stringimpl(); } +bool String::copy_characters_to_buffer(char* buffer, size_t buffer_size) const +{ + // We must fit at least the NUL-terminator. + ASSERT(buffer_size > 0); + + size_t characters_to_copy = min(length(), buffer_size - 1); + __builtin_memcpy(buffer, characters(), characters_to_copy); + buffer[characters_to_copy] = 0; + + return characters_to_copy == length(); +} + String String::isolated_copy() const { if (!m_impl) diff --git a/AK/String.h b/AK/String.h index 1fcd6de7f1d..1ddbd9b40ee 100644 --- a/AK/String.h +++ b/AK/String.h @@ -146,6 +146,8 @@ public: // Includes NUL-terminator, if non-nullptr. ALWAYS_INLINE const char* characters() const { return m_impl ? m_impl->characters() : nullptr; } + [[nodiscard]] bool copy_characters_to_buffer(char* buffer, size_t buffer_size) const; + ALWAYS_INLINE ReadonlyBytes bytes() const { return m_impl ? m_impl->bytes() : nullptr; } ALWAYS_INLINE const char& operator[](size_t i) const