xref: /php-src/ext/intl/intl_convertcpp.cpp (revision 44fa68b0)
1 /*
2    +----------------------------------------------------------------------+
3    | This source file is subject to version 3.01 of the PHP license,      |
4    | that is bundled with this package in the file LICENSE, and is        |
5    | available through the world-wide-web at the following url:           |
6    | https://www.php.net/license/3_01.txt                                 |
7    | If you did not receive a copy of the PHP license and are unable to   |
8    | obtain it through the world-wide-web, please send a note to          |
9    | license@php.net so we can mail you a copy immediately.               |
10    +----------------------------------------------------------------------+
11    | Authors: Gustavo Lopes <cataphract@php.net>                          |
12    +----------------------------------------------------------------------+
13 */
14 
15 #include "intl_cppshims.h"
16 
17 #include "intl_convertcpp.h"
18 #include <unicode/ustring.h>
19 extern "C" {
20 #include <php.h>
21 }
22 
23 /* {{{ intl_stringFromChar */
intl_stringFromChar(UnicodeString & ret,char * str,size_t str_len,UErrorCode * status)24 int intl_stringFromChar(UnicodeString &ret, char *str, size_t str_len, UErrorCode *status)
25 {
26 	if(UNEXPECTED(str_len > INT32_MAX)) {
27 		*status = U_BUFFER_OVERFLOW_ERROR;
28 		ret.setToBogus();
29 		return FAILURE;
30 	}
31 	//the number of UTF-16 code units is not larger than that of UTF-8 code
32 	//units, + 1 for the terminator
33 	int32_t capacity = (int32_t)str_len + 1;
34 
35 	//no check necessary -- if NULL will fail ahead
36 	UChar	*utf16 = ret.getBuffer(capacity);
37 	int32_t utf16_len = 0;
38 	*status = U_ZERO_ERROR;
39 	u_strFromUTF8WithSub(utf16, ret.getCapacity(), &utf16_len,
40 		str, str_len, U_SENTINEL /* no substitution */, NULL,
41 		status);
42 	ret.releaseBuffer(utf16_len);
43 	if (U_FAILURE(*status)) {
44 		ret.setToBogus();
45 		return FAILURE;
46 	}
47 	return SUCCESS;
48 }
49 /* }}} */
50 
51 /* {{{ intl_charFromString
52  * faster than doing intl_convert_utf16_to_utf8(
53  *		from.getBuffer(), from.length(), &status),
54  * but consumes more memory */
intl_charFromString(const UnicodeString & from,UErrorCode * status)55 zend_string* intl_charFromString(const UnicodeString &from, UErrorCode *status)
56 {
57 	zend_string *u8res;
58 
59 	if (UNEXPECTED(from.isBogus())) {
60 		return NULL;
61 	}
62 
63 	//the number of UTF-8 code units is not larger than that of UTF-16 code
64 	//units * 3
65 	int32_t capacity = from.length() * 3;
66 
67 	if (from.isEmpty()) {
68 		return ZSTR_EMPTY_ALLOC();
69 	}
70 
71 	u8res = zend_string_alloc(capacity, 0);
72 
73 	const UChar *utf16buf = from.getBuffer();
74 	int32_t actual_len;
75 	u_strToUTF8WithSub(ZSTR_VAL(u8res), capacity, &actual_len, utf16buf, from.length(),
76 		U_SENTINEL, NULL, status);
77 
78 	if (U_FAILURE(*status)) {
79 		zend_string_free(u8res);
80 		return NULL;
81 	}
82 	u8res = zend_string_truncate(u8res, actual_len, 0);
83 
84 	return u8res;
85 }
86 /* }}} */
87