Brucey 3 лет назад
Родитель
Сommit
bc7545882a

+ 4 - 0
blitz.mod/blitz_classes.i

@@ -65,6 +65,10 @@ String^Object{
 	-ToUTF8StringBuffer:Byte Ptr(buf:Byte Ptr, length:Size_T Var)="bbStringToUTF8StringBuffer"
 	-Hash:ULong()="bbStringHash"
 
+	-ToUTF32String:UInt Ptr()="bbStringToUTF32String"
+	+FromUTF32String:String( utf32String:UInt Ptr )="bbStringFromUTF32String"
+	+FromUTF32Bytes:String( utf32String:UInt Ptr, count )="bbStringFromUTF32Bytes"
+
 }AF="bbStringClass"
 
 ___Array^Object{

+ 5 - 1
blitz.mod/blitz_classes.win32.i

@@ -69,7 +69,11 @@ String^Object{
 
 	-ToUTF8StringBuffer:Byte Ptr(buf:Byte Ptr, length:Size_T Var)="bbStringToUTF8StringBuffer"
 	-Hash:ULong()="bbStringHash"
-		
+
+	-ToUTF32String:UInt Ptr()="bbStringToUTF32String"
+	+FromUTF32String:String( utf32String:UInt Ptr )="bbStringFromUTF32String"
+	+FromUTF32Bytes:String( utf32String:UInt Ptr, count )="bbStringFromUTF32Bytes"
+
 }AF="bbStringClass"
 
 ___Array^Object{

+ 71 - 1
blitz.mod/blitz_string.c

@@ -91,7 +91,11 @@ struct BBClass_String bbStringClass={
 #endif
 
 	bbStringToUTF8StringBuffer,
-	bbStringHash
+	bbStringHash,
+
+	bbStringToUTF32String,
+	bbStringFromUTF32String,
+	bbStringFromUTF32Bytes
 };
 
 BBString bbEmptyString={
@@ -106,6 +110,12 @@ static int wstrlen( const BBChar *p ){
 	return t-p;
 }
 
+static int utf32strlen( const BBUINT *p ){
+	const BBUINT *t=p;
+	while( *t ) ++t;
+	return t-p;
+}
+
 static int charsEqual( unsigned short *a,unsigned short *b,int n ){
 	while( n-- ){
 		if (*a!=*b) return 0;
@@ -1032,3 +1042,63 @@ BBULONG bbStringHash( BBString * x ) {
 }
 
 #endif
+
+BBUINT* bbStringToUTF32String( BBString *str ) {
+	int len=str->length;
+	int n = 0;
+	size_t buflen = len * 4 + 4;
+	BBUINT *buf=(BBUINT*)bbMemAlloc( buflen );
+
+	BBChar *p=str->buf;
+	BBUINT *bp = buf;
+	while( *p ) {
+		n++;
+		BBChar c = *p++;
+		if (!((c - 0xd800u) < 2048u)) {
+			*bp++ = c;
+		} else {
+			if (((c & 0xfffffc00) == 0xd800) && n < len && ((*p & 0xfffffc00) == 0xdc00)) {
+				*bp++ = (c << 10) + (*p++) - 0x35fdc00;
+			} else {
+				bbExThrowCString( "Failed to create UTF32. Invalid surrogate pair." );
+			}
+		}
+	}
+	*bp = 0;
+	return buf;
+}
+
+BBString* bbStringFromUTF32String( const BBUINT *p ) {
+	return p ? bbStringFromUTF32Bytes(p, utf32strlen(p)) : &bbEmptyString;
+}
+
+BBString* bbStringFromUTF32Bytes( const BBUINT *p, int n ) {
+	if( !p || n <= 0 ) return &bbEmptyString;
+	
+	int len = n * 2;
+	unsigned short * d=(unsigned short*)malloc( n * sizeof(BBChar) * 2 );
+	unsigned short * q=d;
+
+	BBUINT* bp = p;
+
+	int i = 0;
+	while (i++ < n) {
+		BBUINT c = *bp++;
+		if (c <= 0xffffu) {
+			if (c >= 0xd800u && c <= 0xdfffu) {
+				*q++ = 0xfffd;
+			} else {
+          		*q++ = c;
+			}
+		} else if (c > 0x0010ffffu) {
+			*q++ = 0xfffd;
+		} else {
+			c -= 0x0010000u;
+        	*q++ = (BBChar)((c >> 10) + 0xd800);
+        	*q++ = (BBChar)((c & 0x3ffu) + 0xdc00);
+		}
+	}
+	BBString * str=bbStringFromShorts( d,q-d );
+	free( d );
+	return str;
+}

+ 7 - 0
blitz.mod/blitz_string.h

@@ -95,6 +95,9 @@ struct BBClass_String{
 
 	unsigned char* (*bbStringToUTF8StringBuffer)( BBString *str, unsigned char * buf, size_t * length );
 	BBULONG (*bbStringHash)( BBString * x );
+	BBUINT* (*bbStringToUTF32String)( BBString *str );
+	BBString* (*bbStringFromUTF32String)( const BBUINT *p );
+	BBString* (*bbStringFromUTF32Bytes)( const BBUINT *p, int n );
 };
 
 extern	struct BBClass_String bbStringClass;
@@ -149,6 +152,10 @@ unsigned char* bbStringToCString( BBString *str );
 BBChar*	bbStringToWString( BBString *str );
 unsigned char* bbStringToUTF8String( BBString *str );
 
+BBUINT* bbStringToUTF32String( BBString *str );
+BBString* bbStringFromUTF32String( const BBUINT *p );
+BBString* bbStringFromUTF32Bytes( const BBUINT *p, int n );
+
 #ifdef _WIN32
 WPARAM  bbStringToWParam( BBString *str );
 LPARAM  bbStringToLParam( BBString *str );

+ 27 - 0
blitz.mod/tests/test.bmx

@@ -0,0 +1,27 @@
+SuperStrict
+
+Framework brl.standardio
+Import BRL.MaxUnit
+
+New TTestSuite.run()
+
+Type TStringTest Extends TTest
+
+	Field bigUnicode:UInt[] = [$10300, $10301, $10302, $10303, $10304, $10305, 0]
+	Field unicode:Int[] = [1055, 1088, 1080, 1074, 1077, 1090]
+	Field utf8:Byte[] = [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 0]
+	
+	Method setup() { before }
+	End Method
+
+	Method testUTF32() { test }
+		Local s:String = String.FromUTF32String(bigUnicode);
+		assertEquals(12, s.Length)
+		
+		Local buf:UInt Ptr = s.ToUTF32String()
+		For Local i:Int = 0 Until 7
+			assertEquals( bigUnicode[i], buf[i] )
+		Next
+	End Method
+
+End Type