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 #include "intl_cppshims.h"
18
19 #include "intl_convertcpp.h"
20 #include <unicode/ustring.h>
21 extern "C" {
22 #include <php.h>
23 }
24
25 /* {{{ intl_stringFromChar */
intl_stringFromChar(UnicodeString & ret,char * str,size_t str_len,UErrorCode * status)26 int intl_stringFromChar(UnicodeString &ret, char *str, size_t str_len, UErrorCode *status)
27 {
28 if(str_len > INT32_MAX) {
29 *status = U_BUFFER_OVERFLOW_ERROR;
30 ret.setToBogus();
31 return FAILURE;
32 }
33 //the number of UTF-16 code units is not larger than that of UTF-8 code
34 //units, + 1 for the terminator
35 int32_t capacity = (int32_t)str_len + 1;
36
37 //no check necessary -- if NULL will fail ahead
38 UChar *utf16 = ret.getBuffer(capacity);
39 int32_t utf16_len = 0;
40 *status = U_ZERO_ERROR;
41 u_strFromUTF8WithSub(utf16, ret.getCapacity(), &utf16_len,
42 str, str_len, U_SENTINEL /* no substitution */, NULL,
43 status);
44 ret.releaseBuffer(utf16_len);
45 if (U_FAILURE(*status)) {
46 ret.setToBogus();
47 return FAILURE;
48 }
49 return SUCCESS;
50 }
51 /* }}} */
52
53 /* {{{ intl_charFromString
54 * faster than doing intl_convert_utf16_to_utf8(
55 * from.getBuffer(), from.length(), &status),
56 * but consumes more memory */
intl_charFromString(const UnicodeString & from,UErrorCode * status)57 zend_string* intl_charFromString(const UnicodeString &from, UErrorCode *status)
58 {
59 zend_string *u8res;
60
61 if (from.isBogus()) {
62 return NULL;
63 }
64
65 //the number of UTF-8 code units is not larger than that of UTF-16 code
66 //units * 3
67 int32_t capacity = from.length() * 3;
68
69 if (from.isEmpty()) {
70 return ZSTR_EMPTY_ALLOC();
71 }
72
73 u8res = zend_string_alloc(capacity, 0);
74
75 const UChar *utf16buf = from.getBuffer();
76 int32_t actual_len;
77 u_strToUTF8WithSub(ZSTR_VAL(u8res), capacity, &actual_len, utf16buf, from.length(),
78 U_SENTINEL, NULL, status);
79
80 if (U_FAILURE(*status)) {
81 zend_string_free(u8res);
82 return NULL;
83 }
84 ZSTR_VAL(u8res)[actual_len] = '\0';
85 ZSTR_LEN(u8res) = actual_len;
86
87 return u8res;
88 }
89 /* }}} */
90