ObjFW  Check-in [02ca89285f]

Overview
Comment:Improve API for UTF-16 strings.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 02ca89285f0531120ab219ca6eda96bcd97e58331f0303f951dff6c772abcfc1
User & Date: js on 2013-01-07 13:35:12
Other Links: manifest | tags
Context
2013-01-07
13:36
Fix compilation on Win32. check-in: 2965720dbc user: js tags: trunk
13:35
Improve API for UTF-16 strings. check-in: 02ca89285f user: js tags: trunk
2013-01-03
22:26
OFMapTable: Rotate hashes randomly. check-in: 7cebeaa808 user: js tags: trunk
Changes

Modified configure.ac from [8917dc30b2] to [6f34bfbc74].

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
		])
	])
])

AS_IF([test x"$GOBJC" = x"yes"], [
	OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror"

	AC_MSG_CHECKING(whether gcc has bug objc/27438)
	AC_TRY_COMPILE([
		@interface OFConstantString
		{
			struct objc_class *isa;
			const char *string;
			unsigned long size;
		}







|







664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
		])
	])
])

AS_IF([test x"$GOBJC" = x"yes"], [
	OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror"

	AC_MSG_CHECKING(whether we have gcc bug objc/27438)
	AC_TRY_COMPILE([
		@interface OFConstantString
		{
			struct objc_class *isa;
			const char *string;
			unsigned long size;
		}

Modified src/OFString.h from [931dc2b046] to [ad8cbdf010].

832
833
834
835
836
837
838
839











840
841
842
843
844

845
846
847








848
849
850
851
852
853
854
 * copy it.
 *
 * @return The string as an array of Unicode characters
 */
- (const of_unichar_t*)characters OF_RETURNS_INNER_POINTER;

/*!
 * @brief Returns the string in big endian UTF-16 encoding.











 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *

 * @return The string in big endian UTF-16 encoding
 */
- (const uint16_t*)UTF16String OF_RETURNS_INNER_POINTER;









/*!
 * @brief Writes the string into the specified file using UTF-8 encoding.
 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString*)path;







|
>
>
>
>
>
>
>
>
>
>
>





>
|

|
>
>
>
>
>
>
>
>







832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
 * copy it.
 *
 * @return The string as an array of Unicode characters
 */
- (const of_unichar_t*)characters OF_RETURNS_INNER_POINTER;

/*!
 * @brief Returns the string in UTF-16 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * @return The string in UTF-16 encoding with native byte order
 */
- (const uint16_t*)UTF16String OF_RETURNS_INNER_POINTER;

/*!
 * @brief Returns the string in UTF-16 encoding with the specified byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * @param byteOrder The byte order for the UTF-16 encoding
 * @return The string in UTF-16 encoding with the specified byte order
 */
- (const uint16_t*)UTF16StringWithByteOrder: (of_byte_order_t)byteOrder
    OF_RETURNS_INNER_POINTER;

/*!
 * @brief Returns the length of the string in UTF-16 characters.
 *
 * @return The length of string in UTF-16 characters
 */
- (size_t)UTF16StringLength;

/*!
 * @brief Writes the string into the specified file using UTF-8 encoding.
 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString*)path;

Modified src/OFString.m from [e59e2f0949] to [9b71ee7ecc].

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
}

- initWithUTF16String: (const uint16_t*)string
	       length: (size_t)length
{
	return [self initWithUTF16String: string
				  length: length
			       byteOrder: OF_BYTE_ORDER_BIG_ENDIAN];
}

- initWithUTF16String: (const uint16_t*)string
	       length: (size_t)length
	    byteOrder: (of_byte_order_t)byteOrder
{
	@try {







|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
}

- initWithUTF16String: (const uint16_t*)string
	       length: (size_t)length
{
	return [self initWithUTF16String: string
				  length: length
			       byteOrder: OF_BYTE_ORDER_NATIVE];
}

- initWithUTF16String: (const uint16_t*)string
	       length: (size_t)length
	    byteOrder: (of_byte_order_t)byteOrder
{
	@try {
1994
1995
1996
1997
1998
1999
2000





2001
2002
2003
2004
2005
2006

2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020

2021
2022



2023




2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040














2041
2042
2043
2044
2045
2046
2047
		    inRange: of_range(0, length)];

	return ret;
}

- (const uint16_t*)UTF16String
{





	OFObject *object = [[[OFObject alloc] init] autorelease];
	void *pool = objc_autoreleasePoolPush();
	const of_unichar_t *characters = [self characters];
	size_t length = [self length];
	uint16_t *ret;
	size_t i, j;


	/* Allocate memory for the worst case */
	ret = [object allocMemoryWithSize: sizeof(uint16_t)
				    count: length * 2];

	j = 0;

	for (i = 0; i < length; i++) {
		of_unichar_t c = characters[i];

		if (c > 0x10FFFF)
			@throw [OFInvalidEncodingException
			    exceptionWithClass: [self class]];


		if (c > 0xFFFF) {
			c -= 0x10000;



			ret[j++] = OF_BSWAP16_IF_LE(0xD800 | (c >> 10));




			ret[j++] = OF_BSWAP16_IF_LE(0xDC00 | (c & 0x3FF));
		} else
			ret[j++] = OF_BSWAP16_IF_LE(c);

	}

	@try {
		ret = [object resizeMemory: ret
				      size: sizeof(uint16_t)
				     count: j];
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only tried to make it smaller */
	}

	objc_autoreleasePoolPop(pool);

	return ret;
}















- (void)writeToFile: (OFString*)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file;

	file = [OFFile fileWithPath: path







>
>
>
>
>






>














>
|
|
>
>
>
|
>
>
>
>
|
|
|
>














>
>
>
>
>
>
>
>
>
>
>
>
>
>







1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
		    inRange: of_range(0, length)];

	return ret;
}

- (const uint16_t*)UTF16String
{
	return [self UTF16StringWithByteOrder: OF_BYTE_ORDER_NATIVE];
}

- (const uint16_t*)UTF16StringWithByteOrder: (of_byte_order_t)byteOrder
{
	OFObject *object = [[[OFObject alloc] init] autorelease];
	void *pool = objc_autoreleasePoolPush();
	const of_unichar_t *characters = [self characters];
	size_t length = [self length];
	uint16_t *ret;
	size_t i, j;
	BOOL swap = (byteOrder != OF_BYTE_ORDER_NATIVE);

	/* Allocate memory for the worst case */
	ret = [object allocMemoryWithSize: sizeof(uint16_t)
				    count: length * 2];

	j = 0;

	for (i = 0; i < length; i++) {
		of_unichar_t c = characters[i];

		if (c > 0x10FFFF)
			@throw [OFInvalidEncodingException
			    exceptionWithClass: [self class]];

		if (swap) {
			if (c > 0xFFFF) {
				c -= 0x10000;
				ret[j++] = OF_BSWAP16(0xD800 | (c >> 10));
				ret[j++] = OF_BSWAP16(0xDC00 | (c & 0x3FF));
			} else
				ret[j++] = OF_BSWAP16(c);
		} else {
			if (c > 0xFFFF) {
				c -= 0x10000;
				ret[j++] = 0xD800 | (c >> 10);
				ret[j++] = 0xDC00 | (c & 0x3FF);
			} else
				ret[j++] = c;
		}
	}

	@try {
		ret = [object resizeMemory: ret
				      size: sizeof(uint16_t)
				     count: j];
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only tried to make it smaller */
	}

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (size_t)UTF16StringLength
{
	const of_unichar_t *characters = [self characters];
	size_t i, length, UTF16StringLength;

	length = UTF16StringLength = [self length];

	for (i = 0; i < length; i++)
		if (characters[i] > 0xFFFF)
			UTF16StringLength++;

	return UTF16StringLength;
}

- (void)writeToFile: (OFString*)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file;

	file = [OFFile fileWithPath: path

Modified src/OFTLSSocket.h from [9e3217c031] to [dcdc2accee].

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 * @return Whether the TLS socket should accept the received keychain
 */
-	  (BOOL)socket: (id <OFTLSSocket>)socket
  shouldAcceptKeychain: (OFArray*)keychain;
@end

/*!
 * @brief A protocol that should be implemented by 3rd party libraries
 *	  implementing TLS.
 */
@protocol OFTLSSocket
#ifdef OF_HAVE_PROPERTIES
@property (assign) id <OFTLSSocketDelegate> delegate;
@property (copy) OFString *certificateFile, *privateKeyFile;
@property const char *privateKeyPassphrase;







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 * @return Whether the TLS socket should accept the received keychain
 */
-	  (BOOL)socket: (id <OFTLSSocket>)socket
  shouldAcceptKeychain: (OFArray*)keychain;
@end

/*!
 * @brief A protocol that should be implemented by 3rd-party libraries
 *	  implementing TLS.
 */
@protocol OFTLSSocket
#ifdef OF_HAVE_PROPERTIES
@property (assign) id <OFTLSSocketDelegate> delegate;
@property (copy) OFString *certificateFile, *privateKeyFile;
@property const char *privateKeyPassphrase;

Modified tests/OFStringTests.m from [e613d6ae06] to [101fcea2a5].

410
411
412
413
414
415
416
417
418




419


420
421

422
423
424
425
426
427
428
	     @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
	    hexadecimalValue])

	TEST(@"-[characters]", (ua = [@"fööbär🀺" characters]) &&
	    !memcmp(ua, ucstr + 1, sizeof(ucstr) / sizeof(*ucstr)))

	TEST(@"-[UTF16String]", (u16a = [@"fööbär🀺" UTF16String]) &&
#ifdef OF_BIG_ENDIAN
	    !memcmp(u16a, utf16str + 1, sizeof(utf16str) - sizeof(uint16_t)))




#else


	    !memcmp(u16a, sutf16str + 1, sizeof(sutf16str) - sizeof(uint16_t)))
#endif


	TEST(@"-[MD5Hash]", [[@"asdfoobar" MD5Hash]
	    isEqual: @"184dce2ec49b5422c7cfd8728864db4c"])

	TEST(@"-[SHA1Hash]", [[@"asdfoobar" SHA1Hash]
	    isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"])








<

>
>
>
>

>
>

|
>







410
411
412
413
414
415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
	     @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
	    hexadecimalValue])

	TEST(@"-[characters]", (ua = [@"fööbär🀺" characters]) &&
	    !memcmp(ua, ucstr + 1, sizeof(ucstr) / sizeof(*ucstr)))

	TEST(@"-[UTF16String]", (u16a = [@"fööbär🀺" UTF16String]) &&

	    !memcmp(u16a, utf16str + 1, sizeof(utf16str) - sizeof(uint16_t)))

	TEST(@"-[UTF16String]", (u16a = [@"fööbär🀺"
#ifdef OF_BIG_ENDIAN
	    UTF16StringWithByteOrder: OF_BYTE_ORDER_LITTLE_ENDIAN]) &&
#else
	    UTF16StringWithByteOrder: OF_BYTE_ORDER_BIG_ENDIAN]) &&
#endif
	    !memcmp(u16a, sutf16str + 1, sizeof(sutf16str) - sizeof(uint16_t)))

	TEST(@"-[UTF16StringLength]", [@"fööbär🀺" UTF16StringLength] == 8)

	TEST(@"-[MD5Hash]", [[@"asdfoobar" MD5Hash]
	    isEqual: @"184dce2ec49b5422c7cfd8728864db4c"])

	TEST(@"-[SHA1Hash]", [[@"asdfoobar" SHA1Hash]
	    isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"])