mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Optimisation of strings
This commit is contained in:
parent
15ba2b71cb
commit
0428118553
@ -675,7 +675,7 @@ namespace etl
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
append_impl(begin(), other.begin(), other.end(), other.is_truncated(), other.is_secure());
|
||||
append_impl<T>(begin(), other.begin(), other.end(), other.is_truncated(), other.is_secure());
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,7 +697,7 @@ namespace etl
|
||||
|
||||
ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds));
|
||||
|
||||
append_impl(begin(), other.begin() + subposition, other.begin() + subposition + sublength, other.is_truncated(), other.is_secure());
|
||||
append_impl<T>(begin(), other.begin() + subposition, other.begin() + subposition + sublength, other.is_truncated(), other.is_secure());
|
||||
}
|
||||
}
|
||||
|
||||
@ -711,7 +711,7 @@ namespace etl
|
||||
template <typename TIterator>
|
||||
void assign(TIterator first, TIterator last)
|
||||
{
|
||||
append_impl(begin(), first, last, false, false);
|
||||
append_impl<T>(begin(), first, last, false, false);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
@ -721,7 +721,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
void assign(const_pointer str)
|
||||
{
|
||||
append_impl(begin(), str, false, false);
|
||||
append_impl<T>(begin(), str, false, false);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
@ -732,7 +732,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
void assign(const_pointer str, size_type n)
|
||||
{
|
||||
append_impl(begin(), str, str + n, false, false);
|
||||
append_impl<T>(begin(), str, str + n, false, false);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
@ -741,7 +741,7 @@ namespace etl
|
||||
template <typename TOtherTraits>
|
||||
void assign(const etl::basic_string_view<T, TOtherTraits>& view)
|
||||
{
|
||||
append_impl(begin(), view.begin(), view.end(), false, false);
|
||||
append_impl<T>(begin(), view.begin(), view.end(), false, false);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
@ -820,7 +820,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
ibasic_string& append(const ibasic_string& str)
|
||||
{
|
||||
append_impl(end(), str.begin(), str.end(), str.is_truncated(), str.is_secure());
|
||||
append_impl<T>(end(), str.begin(), str.end(), str.is_truncated(), str.is_secure());
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -840,7 +840,7 @@ namespace etl
|
||||
|
||||
ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds));
|
||||
|
||||
append_impl(end(), str.begin() + subposition, str.begin() + subposition + sublength, str.is_truncated(), str.is_secure());
|
||||
append_impl<T>(end(), str.begin() + subposition, str.begin() + subposition + sublength, str.is_truncated(), str.is_secure());
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -853,7 +853,7 @@ namespace etl
|
||||
template <class TIterator>
|
||||
ibasic_string& append(TIterator first, TIterator last)
|
||||
{
|
||||
append_impl(end(), first, last, false, false);
|
||||
append_impl<T>(end(), first, last, false, false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -864,7 +864,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
ibasic_string& append(const_pointer str)
|
||||
{
|
||||
append_impl(end(), str, false, false);
|
||||
append_impl<T>(end(), str, false, false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -876,7 +876,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
ibasic_string& append(const_pointer str, size_type n)
|
||||
{
|
||||
append_impl(end(), str, str + n, false, false);
|
||||
append_impl<T>(end(), str, str + n, false, false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -888,7 +888,7 @@ namespace etl
|
||||
template <typename TOtherTraits>
|
||||
ibasic_string& append(const etl::basic_string_view<T, TOtherTraits>& view)
|
||||
{
|
||||
append_impl(end(), view.begin(), view.end(), false, false);
|
||||
append_impl<T>(end(), view.begin(), view.end(), false, false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -2697,7 +2697,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
/// Common implementation for 'assign' and 'append' for iterators.
|
||||
//*********************************************************************
|
||||
template <typename TIterator>
|
||||
template <typename TChar, typename TIterator>
|
||||
void append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure)
|
||||
{
|
||||
difference_type start = etl::distance(p_buffer, position);
|
||||
@ -2733,20 +2733,76 @@ namespace etl
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Common implementation for 'assign' and 'append' for single pointer.
|
||||
/// Common implementation for 'assign' and 'append' for single C string pointer.
|
||||
/// Enabled for char.
|
||||
//*********************************************************************
|
||||
void append_impl(iterator position, const_pointer first, bool truncated, bool secure)
|
||||
template <typename TChar>
|
||||
typename etl::enable_if<etl::is_same<TChar, char>::value, void>::type
|
||||
append_impl(iterator position, const TChar* src, bool truncated, bool secure)
|
||||
{
|
||||
if (src == ETL_NULLPTR)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
difference_type start = etl::distance(p_buffer, position);
|
||||
difference_type free_space = etl::distance(position, p_buffer + CAPACITY);
|
||||
|
||||
etl::str_n_copy_result result = etl::str_n_copy(first, size_t(free_space), position);
|
||||
pointer dst = position;
|
||||
size_t length = ::strlen(src);
|
||||
size_t count = (length < size_t(free_space)) ? length : size_t(free_space);
|
||||
etl::mem_copy(src, count, dst);
|
||||
|
||||
current_size = size_t(start) + result.count;
|
||||
truncated |= (src[count] != 0);
|
||||
current_size = size_t(start) + count;
|
||||
p_buffer[current_size] = 0;
|
||||
|
||||
#if ETL_HAS_STRING_TRUNCATION_CHECKS
|
||||
set_truncated(result.truncated || truncated);
|
||||
set_truncated(truncated);
|
||||
#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
|
||||
ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ETL_HAS_STRING_CLEAR_AFTER_USE
|
||||
if (secure)
|
||||
{
|
||||
set_secure();
|
||||
}
|
||||
#endif
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Common implementation for 'assign' and 'append' for single C string pointer.
|
||||
/// Enabled for wchar, char8_t, char16_t or char32_t.
|
||||
//*********************************************************************
|
||||
template <typename TChar>
|
||||
typename etl::enable_if<!etl::is_same<TChar, char>::value, void>::type
|
||||
append_impl(iterator position, const TChar* src, bool truncated, bool secure)
|
||||
{
|
||||
if (src == ETL_NULLPTR)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
difference_type start = etl::distance(p_buffer, position);
|
||||
difference_type free_space = etl::distance(position, p_buffer + CAPACITY);
|
||||
|
||||
pointer dst = position;
|
||||
size_t length = etl::strlen(src, free_space);
|
||||
size_t count = (length < size_t(free_space)) ? length : size_t(free_space);
|
||||
etl::mem_copy(src, count, dst);
|
||||
|
||||
truncated |= (src[count] != 0);
|
||||
current_size = size_t(start) + count;
|
||||
p_buffer[current_size] = 0;
|
||||
|
||||
#if ETL_HAS_STRING_TRUNCATION_CHECKS
|
||||
set_truncated(truncated);
|
||||
#if ETL_HAS_ERROR_ON_STRING_TRUNCATION
|
||||
ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation));
|
||||
#endif
|
||||
|
||||
@ -903,31 +903,77 @@ namespace etl
|
||||
{
|
||||
if ((src == ETL_NULLPTR) || (dst == ETL_NULLPTR))
|
||||
{
|
||||
str_n_copy_result result = { 0, false, false };
|
||||
return result;
|
||||
return { 0, false, false };
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
|
||||
while ((count != n) && (*src != 0))
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
// Use restrict if available, for better optimization
|
||||
const T* __restrict s = src;
|
||||
T* __restrict d = dst;
|
||||
#else
|
||||
const T* s = src;
|
||||
T* d = dst;
|
||||
#endif
|
||||
|
||||
// Copy in blocks of 4 for loop unrolling
|
||||
count += 4;
|
||||
while (count <= n)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
if (s[0] == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
d[0] = s[0];
|
||||
|
||||
if (s[1] == 0)
|
||||
{
|
||||
count += 1;
|
||||
d[1] = 0;
|
||||
return { count, false, true };
|
||||
}
|
||||
|
||||
d[1] = s[1];
|
||||
|
||||
if (s[2] == 0)
|
||||
{
|
||||
count += 2; d[2] = 0;
|
||||
return { count, false, true };
|
||||
}
|
||||
|
||||
d[2] = s[2];
|
||||
|
||||
if (s[3] == 0)
|
||||
{
|
||||
count += 3;
|
||||
d[3] = 0;
|
||||
return { count, false, true };
|
||||
}
|
||||
|
||||
d[3] = s[3];
|
||||
s += 4;
|
||||
d += 4;
|
||||
count += 4;
|
||||
}
|
||||
|
||||
// Copy remaining
|
||||
while ((count < n) && (*s != 0))
|
||||
{
|
||||
*d++ = *s++;
|
||||
++count;
|
||||
}
|
||||
|
||||
// Did we stop because of a terminating zero?
|
||||
if (count != n)
|
||||
//
|
||||
if (count <= n)
|
||||
{
|
||||
// Yes we did.
|
||||
*dst = 0;
|
||||
str_n_copy_result result = { count, false, true };
|
||||
return result;
|
||||
}
|
||||
else
|
||||
*d = 0;
|
||||
return { count, false, true };
|
||||
}
|
||||
else
|
||||
{
|
||||
// No. Truncation depends on the next src character being a terminating zero or not.
|
||||
str_n_copy_result result = { count, *src != 0, false };
|
||||
return result;
|
||||
return { count, *s != 0, false };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,6 +165,20 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
Text text(shorter_text.c_str());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -219,6 +219,21 @@ namespace
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextBuffer buffer{0};
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
Text text(shorter_text.c_str(), buffer.data(), buffer.size());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer)
|
||||
{
|
||||
|
||||
@ -179,6 +179,20 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
Text text(shorter_text.c_str());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -248,6 +248,21 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
TextBuffer buffer{0};
|
||||
Text text(shorter_text.c_str(), buffer.data(), buffer.size());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -179,6 +179,20 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
Text text(shorter_text.c_str());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -248,6 +248,21 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
TextBuffer buffer{0};
|
||||
Text text(shorter_text.c_str(), buffer.data(), buffer.size());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -182,6 +182,20 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
Text text(shorter_text.c_str());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -251,6 +251,21 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
TextBuffer buffer{0};
|
||||
Text text(shorter_text.c_str(), buffer.data(), buffer.size());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -1784,81 +1784,5 @@ namespace
|
||||
|
||||
CHECK(text == expected);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_str_n_copy_destination_larger)
|
||||
{
|
||||
STR_PTR src = STR("Hello World");
|
||||
STR_TYPE dst[15];
|
||||
|
||||
etl::str_n_copy_result result = etl::str_n_copy(src, 15, dst);
|
||||
CHECK_EQUAL(etl::strlen(src), result.count);
|
||||
CHECK_FALSE(result.truncated);
|
||||
CHECK_TRUE(result.terminated);
|
||||
CHECK(dst[11] == 0);
|
||||
|
||||
bool are_equal = etl::equal(src, src + 12, dst);
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_str_n_copy_destination_exact_include_space_for_terminator)
|
||||
{
|
||||
STR_PTR src = STR("Hello World");
|
||||
STR_TYPE dst[12];
|
||||
|
||||
etl::str_n_copy_result result = etl::str_n_copy(src, 12, dst);
|
||||
CHECK_EQUAL(11, result.count);
|
||||
CHECK_FALSE(result.truncated);
|
||||
CHECK_TRUE(result.terminated);
|
||||
CHECK(dst[11] == 0);
|
||||
|
||||
bool are_equal = etl::equal(src, src + 12, dst);
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_str_n_copy_destination_exclude_space_for_terminator_exact_no_termination)
|
||||
{
|
||||
STR_PTR src = STR("Hello World");
|
||||
STR_TYPE dst[11];
|
||||
|
||||
etl::str_n_copy_result result = etl::str_n_copy(src, 11, dst);
|
||||
CHECK_EQUAL(11, result.count);
|
||||
CHECK_FALSE(result.truncated);
|
||||
CHECK_FALSE(result.terminated);
|
||||
CHECK(dst[10] != 0);
|
||||
|
||||
bool are_equal = etl::equal(src, src + 11, dst);
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_str_n_copy_destination_smaller_no_termination)
|
||||
{
|
||||
STR_PTR src = STR("Hello World");
|
||||
STR_TYPE dst[9];
|
||||
|
||||
etl::str_n_copy_result result = etl::str_n_copy(src, 9, dst);
|
||||
CHECK_EQUAL(9, result.count);
|
||||
CHECK_TRUE(result.truncated);
|
||||
CHECK_FALSE(result.terminated);
|
||||
CHECK(dst[8] != 0);
|
||||
|
||||
bool are_equal = etl::equal(src, src + 9, dst);
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_str_n_copy_zero_sized_destination)
|
||||
{
|
||||
STR_PTR src = STR("Hello World");
|
||||
STR_TYPE dst[15];
|
||||
|
||||
etl::str_n_copy_result result = etl::str_n_copy(src, 0, dst);
|
||||
CHECK_EQUAL(0, result.count);
|
||||
CHECK_TRUE(result.truncated);
|
||||
CHECK_FALSE(result.terminated);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -180,6 +180,20 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
Text text(shorter_text.c_str());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
@ -251,6 +251,21 @@ namespace
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_shorter_string)
|
||||
{
|
||||
TextSTD compare_text(shorter_text.c_str());
|
||||
|
||||
TextBuffer buffer{0};
|
||||
Text text(shorter_text.c_str(), buffer.data(), buffer.size());
|
||||
|
||||
CHECK(!text.empty());
|
||||
|
||||
bool is_equal = Equal(compare_text, text);
|
||||
CHECK(is_equal);
|
||||
CHECK_FALSE(text.is_truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_char_pointer_excess)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user