diff options
| author | kx <kx@radix-linux.su> | 2026-10-01 12:02:28 +0300 |
|---|---|---|
| committer | kx <kx@radix-linux.su> | 2026-10-01 12:02:28 +0300 |
| commit | ba1b04d64bdfaf377915b22f77520216ebe47674 (patch) | |
| tree | 044343035c28b2b04ca9725f26e9b7c39342d19c /src/mcpp-text.c | |
| parent | 124b140798456778e2a96851cc7268aa9a726698 (diff) | |
| download | mcpu-cpp-1.0.2.tar.xz | |
Version 1.0.21.0.2
Diffstat (limited to 'src/mcpp-text.c')
| -rw-r--r-- | src/mcpp-text.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/mcpp-text.c b/src/mcpp-text.c new file mode 100644 index 0000000..febbd3b --- /dev/null +++ b/src/mcpp-text.c @@ -0,0 +1,237 @@ +#include <defs.h> + +void +mcpu_text_init( mcpu_text *text ) +{ + if( text == NULL ) + return; + + text->data = NULL; + text->length = 0; + text->capacity = 0; +} + +void +mcpu_text_free( mcpu_text *text ) +{ + if( text == NULL ) + return; + + free( text->data ); + text->data = NULL; + text->length = 0; + text->capacity = 0; +} + +int +mcpu_text_reserve( mcpu_text *text, size_t need ) +{ + __mpu_char16_t *p; + size_t capacity; + + if( text == NULL ) + return( -1 ); + + if( need <= text->capacity ) + return( 0 ); + + capacity = text->capacity ? text->capacity : 256; + while( capacity < need ) + { + if( capacity > (SIZE_MAX / 2) ) + { + errno = EOVERFLOW; + return( -1 ); + } + capacity *= 2; + } + + if( capacity > (SIZE_MAX / sizeof(__mpu_char16_t)) ) + { + errno = EOVERFLOW; + return( -1 ); + } + + p = (__mpu_char16_t *)realloc( text->data, + capacity * sizeof(__mpu_char16_t) ); + if( p == NULL ) + return( -1 ); + + text->data = p; + text->capacity = capacity; + + return( 0 ); +} + +int +mcpu_text_append( mcpu_text *text, + const __mpu_char16_t *data, size_t length ) +{ + if( text == NULL || (data == NULL && length != 0) ) + { + errno = EINVAL; + return( -1 ); + } + + if( length > SIZE_MAX - text->length - 1 ) + { + errno = EOVERFLOW; + return( -1 ); + } + + if( mcpu_text_reserve( text, text->length + length + 1 ) != 0 ) + return( -1 ); + + if( length != 0 ) + memcpy( text->data + text->length, data, + length * sizeof(__mpu_char16_t) ); + + text->length += length; + text->data[text->length] = 0; + + return( 0 ); +} + +int +mcpu_text_append_char( mcpu_text *text, __mpu_char16_t ch ) +{ + return( mcpu_text_append( text, &ch, 1 ) ); +} + +int +mcpu_text_append_ascii( mcpu_text *text, const char *s ) +{ + if( text == NULL || s == NULL ) + { + errno = EINVAL; + return( -1 ); + } + + while( *s ) + { + unsigned char c = (unsigned char)*s++; + + if( c > 0x7f ) + { + errno = EILSEQ; + return( -1 ); + } + + if( mcpu_text_append_char( text, (__mpu_char16_t)c ) != 0 ) + return( -1 ); + } + + return( 0 ); +} + +int +mcpu_text_append_utf8( mcpu_text *text, const char *s ) +{ + __mpu_char16_t *u; + __mpu_size_t n; + int rc; + + if( text == NULL || s == NULL ) + { + errno = EINVAL; + return( -1 ); + } + + n = mpu_utf8_to_ucs2( NULL, (const __mpu_char8_t *)s, 0 ); + if( n == (__mpu_size_t)-1 ) + return( -1 ); + + u = (__mpu_char16_t *)calloc( (size_t)n + 1, sizeof(__mpu_char16_t) ); + if( u == NULL ) + return( -1 ); + + if( mpu_utf8_to_ucs2( u, (const __mpu_char8_t *)s, + (size_t)n + 1 ) == (__mpu_size_t)-1 ) + { + free( u ); + return( -1 ); + } + + rc = mcpu_text_append( text, u, (size_t)n ); + free( u ); + + return( rc ); +} + +int +mcpu_text_from_utf8( mcpu_text *text, const char *s ) +{ + if( text == NULL || s == NULL ) + { + errno = EINVAL; + return( -1 ); + } + + mcpu_text_free( text ); + mcpu_text_init( text ); + + return( mcpu_text_append_utf8( text, s ) ); +} + +char * +mcpu_text_to_utf8( const __mpu_char16_t *data, size_t length ) +{ + __mpu_char16_t *tmp; + __mpu_char8_t *out; + __mpu_size_t n; + + if( data == NULL && length != 0 ) + { + errno = EINVAL; + return( NULL ); + } + + tmp = (__mpu_char16_t *)calloc( length + 1, sizeof(__mpu_char16_t) ); + if( tmp == NULL ) + return( NULL ); + + if( length != 0 ) + memcpy( tmp, data, length * sizeof(__mpu_char16_t) ); + + n = mpu_ucs2_to_utf8( NULL, tmp, 0 ); + if( n == (__mpu_size_t)-1 ) + { + free( tmp ); + return( NULL ); + } + + out = (__mpu_char8_t *)calloc( (size_t)n + 1, 1 ); + if( out == NULL ) + { + free( tmp ); + return( NULL ); + } + + if( mpu_ucs2_to_utf8( out, tmp, (size_t)n + 1 ) == (__mpu_size_t)-1 ) + { + free( out ); + free( tmp ); + return( NULL ); + } + + free( tmp ); + return( (char *)out ); +} + +int +mcpu_text_equal_ascii( const __mpu_char16_t *data, + size_t length, const char *s ) +{ + size_t i; + + if( data == NULL || s == NULL ) + return( 0 ); + + for( i = 0; i < length && s[i]; ++i ) + { + if( data[i] != (__mpu_char16_t)(unsigned char)s[i] ) + return( 0 ); + } + + return( i == length && s[i] == 0 ); +} |
