Add +m_string_it_set_ref
This commit is contained in:
1 parent
ecfa4a9152
commit
2628536d20
3 files changed
+105
No files matched your search
@@ -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
@@ -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
|
||||
|
||||
@@ -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[], ...)
|
||||
|
||||
Reference in new issue
Block a user