Add string functions :
* string_it_get_pos to return the position in the steam * string_it_pos to start iterating from a given position.
This commit is contained in:
1 parent
cfeedf19f8
commit
41c4f5fe5c
2 files changed
+69
-9
No files matched your search
+61
-9
@@ -67,6 +67,20 @@ typedef enum {
|
||||
M_STR1NG_UTF8_ERROR = 32
|
||||
} m_str1ng_utf8_state_e;
|
||||
|
||||
/* Maximum number of bytes per UTF8 code point */
|
||||
#define M_STR1NG_MAX_BYTE_UTF8 4
|
||||
|
||||
/* Contract for a string iterator */
|
||||
#define M_STR1NG_IT_CONTRACT(it) do { \
|
||||
M_ASSERT( (it) != NULL); \
|
||||
M_ASSERT( (it)->ptr != NULL); \
|
||||
M_ASSERT( 0 <= (it)->next_ptr && (it)->next_ptr <= M_STR1NG_MAX_BYTE_UTF8); \
|
||||
M_ASSERT( (it)->string != NULL); \
|
||||
M_ASSERT( m_string_get_cstr((it)->string) <= (it)->ptr); \
|
||||
M_ASSERT( (it)->ptr <= &m_string_get_cstr((it)->string)[m_string_size((it)->string)]); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/****************************** EXTERNAL *******************************/
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -117,6 +131,7 @@ typedef struct m_string_it_s {
|
||||
m_string_unicode_t u; // Decoded Unicode code point for the iterator
|
||||
int next_ptr; // Offset to the next code point
|
||||
const char *ptr;
|
||||
m_string_srcptr string;
|
||||
} m_string_it_t[1];
|
||||
|
||||
/* PREFIX:
|
||||
@@ -995,7 +1010,7 @@ m_string_set_ui(m_string_t v, unsigned int n)
|
||||
#elif UINT_MAX <= 18446744073709551615UL
|
||||
const size_t max_size = 20+1;
|
||||
#else
|
||||
# error Unexpected UINT_MAX value.
|
||||
# error Unexpected UINT_MAX value (workaround: Define M_USE_FAST_STRING_CONV to 0).
|
||||
#endif
|
||||
char buffer[max_size];
|
||||
m_str1ng_fit2size(v, max_size);
|
||||
@@ -1025,7 +1040,7 @@ m_string_set_si(m_string_t v, int n)
|
||||
#elif INT_MAX <= 9223372036854775807LL
|
||||
const size_t max_size = 1+20+1;
|
||||
#else
|
||||
# error Unexpected INT_MAX value.
|
||||
# error Unexpected UINT_MAX value (workaround: Define M_USE_FAST_STRING_CONV to 0).
|
||||
#endif
|
||||
char buffer[max_size];
|
||||
m_str1ng_fit2size(v, max_size);
|
||||
@@ -1703,6 +1718,8 @@ m_string_it(m_string_it_t it, const m_string_t str)
|
||||
it->ptr = m_string_get_cstr(str);
|
||||
it->next_ptr = 0;
|
||||
it->u = 0;
|
||||
it->string = str;
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
}
|
||||
|
||||
/* Set the iterator to the end of string
|
||||
@@ -1716,6 +1733,8 @@ m_string_it_end(m_string_it_t it, const m_string_t str)
|
||||
it->ptr = &m_string_get_cstr(str)[m_string_size(str)];
|
||||
it->next_ptr = 0;
|
||||
it->u = 0;
|
||||
it->string = str;
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
}
|
||||
|
||||
/* Set the iterator to the same position than the other one */
|
||||
@@ -1726,6 +1745,37 @@ m_string_it_set(m_string_it_t it, const m_string_it_t itsrc)
|
||||
it->ptr = itsrc->ptr;
|
||||
it->next_ptr = itsrc->next_ptr;
|
||||
it->u = itsrc->u;
|
||||
it->string = itsrc->string;
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
}
|
||||
|
||||
/* Set the iterator to the given position in the string.
|
||||
The given position shall reference a valide code point in the string.
|
||||
*/
|
||||
static inline void
|
||||
m_string_it_pos(m_string_it_t it, const m_string_t str, const size_t n)
|
||||
{
|
||||
M_ASSERT(it != NULL);
|
||||
M_STR1NG_CONTRACT(str);
|
||||
// The offset shall be within the string
|
||||
M_ASSERT(n <= m_string_size(str));
|
||||
// The offset shall reference the first Byte of an UTF 8 Code point
|
||||
M_ASSERT(m_str1ng_utf8_start_p ((unsigned char)m_string_get_cstr(str)[n]));
|
||||
it->ptr = &m_string_get_cstr(str)[n];
|
||||
it->next_ptr = 0;
|
||||
it->u = 0;
|
||||
it->string = str;
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
}
|
||||
|
||||
/* Return the current offset in the string referenced by the iterator.
|
||||
This references avalid code point.
|
||||
*/
|
||||
static inline size_t
|
||||
m_string_it_get_pos(m_string_it_t it)
|
||||
{
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
return (size_t) (it->ptr - m_string_get_cstr(it->string));
|
||||
}
|
||||
|
||||
/* Test if the iterator has reached the end of the string.
|
||||
@@ -1736,7 +1786,7 @@ m_string_it_set(m_string_it_t it, const m_string_it_t itsrc)
|
||||
static inline bool
|
||||
m_string_end_p (m_string_it_t it)
|
||||
{
|
||||
M_ASSERT (it != NULL);
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
if (M_UNLIKELY (*it->ptr == 0))
|
||||
return true;
|
||||
m_str1ng_utf8_state_e state = M_STR1NG_UTF8_STARTING;
|
||||
@@ -1747,8 +1797,7 @@ m_string_end_p (m_string_it_t it)
|
||||
str++;
|
||||
} while (state != M_STR1NG_UTF8_STARTING && state != M_STR1NG_UTF8_ERROR && *str != 0);
|
||||
// Save where the current unicode value ends in the UTF8 steam
|
||||
// UTF-8 is maximum 4 characters
|
||||
M_ASSERT( (str > it->ptr) && (str - it->ptr) <= 4);
|
||||
M_ASSERT( (str > it->ptr) && (str - it->ptr) <= M_STR1NG_MAX_BYTE_UTF8);
|
||||
it->next_ptr = (int) (str - it->ptr);
|
||||
// Save the decoded unicode value
|
||||
it->u = M_UNLIKELY (state == M_STR1NG_UTF8_ERROR) ? M_STRING_UNICODE_ERROR : u;
|
||||
@@ -1759,7 +1808,8 @@ m_string_end_p (m_string_it_t it)
|
||||
static inline bool
|
||||
m_string_it_equal_p(const m_string_it_t it1, const m_string_it_t it2)
|
||||
{
|
||||
M_ASSERT(it1 != NULL && it2 != NULL);
|
||||
M_STR1NG_IT_CONTRACT(it1);
|
||||
M_STR1NG_IT_CONTRACT(it2);
|
||||
// IT1.ptr == IT2.ptr ==> IT1 == IT2 ==> All fields are equal
|
||||
M_ASSERT(it1->ptr != it2->ptr || (it1->next_ptr == it2->next_ptr && it1->u == it2->u));
|
||||
return it1->ptr == it2->ptr;
|
||||
@@ -1769,7 +1819,7 @@ m_string_it_equal_p(const m_string_it_t it1, const m_string_it_t it2)
|
||||
static inline void
|
||||
m_string_next (m_string_it_t it)
|
||||
{
|
||||
M_ASSERT (it != NULL);
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
// We already decoded the UTF8 stream
|
||||
it->ptr += it->next_ptr;
|
||||
}
|
||||
@@ -1778,7 +1828,7 @@ m_string_next (m_string_it_t it)
|
||||
static inline m_string_unicode_t
|
||||
m_string_get_cref (const m_string_it_t it)
|
||||
{
|
||||
M_ASSERT (it != NULL);
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
return it->u;
|
||||
}
|
||||
|
||||
@@ -1786,7 +1836,7 @@ m_string_get_cref (const m_string_it_t it)
|
||||
static inline const m_string_unicode_t *
|
||||
m_string_cref (const m_string_it_t it)
|
||||
{
|
||||
M_ASSERT (it != NULL);
|
||||
M_STR1NG_IT_CONTRACT(it);
|
||||
return &it->u;
|
||||
}
|
||||
|
||||
@@ -2604,6 +2654,8 @@ namespace m_lib {
|
||||
#define string_utf8_p m_string_utf8_p
|
||||
#define string_set_ui m_string_set_ui
|
||||
#define string_set_si m_string_set_si
|
||||
#define string_it_pos m_string_it_pos
|
||||
#define string_it_get_pos m_string_it_get_pos
|
||||
|
||||
#define STRING_CTE M_STRING_CTE
|
||||
#define STRING_DECL_INIT M_STRING_DECL_INIT
|
||||
|
||||
@@ -84,6 +84,7 @@ static void test_utf8_it(void)
|
||||
|
||||
string_init(s);
|
||||
string_it_end(it2, s);
|
||||
assert( string_it_get_pos(it2) == 0);
|
||||
|
||||
for(string_it(it, s) ; !string_end_p(it); string_next(it)) {
|
||||
assert(0); // Shall not be called
|
||||
@@ -98,6 +99,13 @@ static void test_utf8_it(void)
|
||||
assert (i < 5);
|
||||
assert (string_get_cref(it) == tab[i]);
|
||||
}
|
||||
assert(i == 5);
|
||||
assert( string_it_get_pos(it) == 9);
|
||||
string_it_pos(it2, s, 9);
|
||||
assert( string_end_p(it2) );
|
||||
string_it_pos(it2, s, 0);
|
||||
assert( !string_end_p(it2) );
|
||||
assert( string_get_cref(it2) == 45);
|
||||
|
||||
string_set_str (s, "H€llo René Chaînôr¬");
|
||||
assert(string_length_u(s) == 19);
|
||||
|
||||
Reference in new issue
Block a user