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