Add +m_string_it_set_ref

This commit is contained in:
Patrick Pelissier committed 2023-06-10 01:50:14 +02:00
1 parent ecfa4a9152
commit 2628536d20
3 files changed
+105

No files matched your search

+8
View File
@@ -5709,6 +5709,14 @@ It returns -1 in case of error in decoding the UTF8 string.
Return the position in the stream of the iterator 'it'.
##### void string\_it\_set\_ref(string\_it\_t it, string\_t str, string\_unicode\_t u)
Replace the unicode code point referenced by 'it' to the unicode code point 'u'
in the string 'str'.
If 'u' is 0, then it will resize the string to the size of the referenced iterator
only keeping the unicode code points before the iterator.
'it' shall be a valid iterator of 'str'.
##### bool string\_it\_equal\_p (const string\_it\_t it1, const string\_it\_t it2)
Return true if both iterators reference the same position, false otherwise.
+51
View File
@@ -1863,6 +1863,56 @@ m_string_cref (m_string_it_t it)
return &it->u;
}
/* Update the value referenced by the iterator to the given value */
static inline void
m_string_it_set_ref(m_string_it_t it, m_string_t s, m_string_unicode_t new_u)
{
M_STR1NG_IT_CONTRACT(it);
M_STR1NG_CONTRACT(s);
M_ASSERT(s == it->string);
char *ptr = m_str1ng_get_cstr(s);
M_ASSUME( it->ptr >= ptr);
size_t offset = (size_t) (it->ptr - ptr);
// Special case if the unicode codepoint is 0
if (new_u == 0) {
// Null the string
m_str1ng_set_size(s, offset);
ptr[offset] = 0;
M_STR1NG_IT_CONTRACT(it);
M_STR1NG_CONTRACT(s);
return;
}
// Encode the new unicode code point & compute its size
char buffer[4+1];
m_str1ng_utf8_encode(buffer, new_u);
size_t new_u_size = strlen(buffer);
// Compute the size of the old unicode code point
m_str1ng_utf8_state_e state = M_STR1NG_UTF8_STARTING;
m_string_unicode_t old_u = 0;
const char *str = it->ptr;
do {
m_str1ng_utf8_decode(*str, &state, &old_u);
str++;
} while (state != M_STR1NG_UTF8_STARTING && state != M_STR1NG_UTF8_ERROR && *str != 0);
M_ASSUME( str > it->ptr);
size_t old_u_size = (size_t) (str - it->ptr);
// We need to replace old_u by new_u. Both are variable length
size_t str_size = m_string_size(s);
m_str1ng_fit2size(s, str_size + new_u_size - old_u_size + 1);
ptr = m_str1ng_get_cstr(s); // ptr may be reallocated!
if (new_u_size != old_u_size) {
M_ASSUME( str_size+1 > (offset + old_u_size) );
memmove(&ptr[offset+new_u_size], &ptr[offset + old_u_size],
str_size+1 - offset - old_u_size);
}
memcpy(&ptr[offset], &buffer[0], new_u_size);
m_str1ng_set_size(s, str_size + new_u_size - old_u_size);
it->ptr = &ptr[offset];
M_STR1NG_IT_CONTRACT(it);
M_STR1NG_CONTRACT(s);
return;
}
/* Push unicode code point into string, encoding it in UTF8 */
static inline void
m_string_push_u (m_string_t str, m_string_unicode_t u)
@@ -2714,6 +2764,7 @@ namespace m_lib {
#define string_it_pos m_string_it_pos
#define string_it_get_pos m_string_it_get_pos
#define string_previous m_string_previous
#define string_it_set_ref m_string_it_set_ref
#define STRING_CTE M_STRING_CTE
#define STRING_DECL_INIT M_STRING_DECL_INIT
+46
View File
@@ -172,6 +172,52 @@ static void test_utf8_it(void)
assert(!string_it_equal_p(it, it2));
string_clear(s);
/* Test replacing of unicode */
string_init(s);
for (string_unicode_t u = 1; u < 0x10ffff; u+=3) {
if (u < 0xD800U || u > 0xDFFFU) {
for(int c1 = 0 ; c1 <= 3; c1+=2) {
for(int c2 = 0 ; c2 <= 20; c2+=5) {
const string_unicode_t u_tab[] = { 0, 'B', 300, 45215, 0x10fffe};
for(int c3 = 0 ; c3 < 5; c3++) {
// Generate string
string_reset(s);
for(int j = 0; j < c1; j++)
string_push_back(s, 'A');
string_push_u(s, u);
for(int j = 0; j < c2; j++)
string_push_back(s, 'C');
// Replace iterator in string
string_it(it, s);
for(int j = 0; j < c1; j++)
string_next(it);
assert( string_get_cref(it) == u);
string_it_set_ref(it, s, u_tab[c3]);
if (u_tab[c3] != 0) {
assert( string_get_cref(it) == u_tab[c3]);
}
// Check constructed string
string_it(it, s);
for(int j = 0; j < c1; j++) {
assert( string_get_cref(it) == 'A');
string_next(it);
}
if (u_tab[c3] != 0) {
assert( *string_cref(it) == u_tab[c3]);
string_next(it);
for(int j = 0; j < c2; j++) {
assert( string_get_cref(it) == 'C');
string_next(it);
}
}
assert(string_end_p(it));
}
}
}
}
}
string_clear(s);
}
static void call_string_cat_vprintf(string_t s, const char format[], ...)