summaryrefslogtreecommitdiff
path: root/src/mcpp-text.c
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-10-01 12:02:28 +0300
committerkx <kx@radix-linux.su>2026-10-01 12:02:28 +0300
commitba1b04d64bdfaf377915b22f77520216ebe47674 (patch)
tree044343035c28b2b04ca9725f26e9b7c39342d19c /src/mcpp-text.c
parent124b140798456778e2a96851cc7268aa9a726698 (diff)
downloadmcpu-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.c237
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 );
+}