23
23
24
24
#if defined(NODE_HAVE_I18N_SUPPORT)
25
25
26
+ #include " node.h"
27
+ #include " env.h"
28
+ #include " env-inl.h"
29
+ #include " util.h"
30
+ #include " util-inl.h"
31
+ #include " v8.h"
32
+
26
33
#include < unicode/putil.h>
27
34
#include < unicode/udata.h>
35
+ #include < unicode/uidna.h>
28
36
29
37
#ifdef NODE_HAVE_SMALL_ICU
30
38
/* if this is defined, we have a 'secondary' entry point.
@@ -43,6 +51,13 @@ extern "C" const char U_DATA_API SMALL_ICUDATA_ENTRY_POINT[];
43
51
44
52
namespace node {
45
53
54
+ using v8::Context;
55
+ using v8::FunctionCallbackInfo;
56
+ using v8::Local;
57
+ using v8::Object;
58
+ using v8::String;
59
+ using v8::Value;
60
+
46
61
bool flag_icu_data_dir = false ;
47
62
48
63
namespace i18n {
@@ -64,7 +79,124 @@ bool InitializeICUDirectory(const char* icu_data_path) {
64
79
}
65
80
}
66
81
82
+ static int32_t ToUnicode (MaybeStackBuffer<char >* buf,
83
+ const char * input,
84
+ size_t length) {
85
+ UErrorCode status = U_ZERO_ERROR;
86
+ uint32_t options = UIDNA_DEFAULT;
87
+ options |= UIDNA_NONTRANSITIONAL_TO_UNICODE;
88
+ UIDNA* uidna = uidna_openUTS46 (options, &status);
89
+ if (U_FAILURE (status))
90
+ return -1 ;
91
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
92
+
93
+ int32_t len = uidna_nameToUnicodeUTF8 (uidna,
94
+ input, length,
95
+ **buf, buf->length (),
96
+ &info,
97
+ &status);
98
+
99
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
100
+ status = U_ZERO_ERROR;
101
+ buf->AllocateSufficientStorage (len);
102
+ len = uidna_nameToUnicodeUTF8 (uidna,
103
+ input, length,
104
+ **buf, buf->length (),
105
+ &info,
106
+ &status);
107
+ }
108
+
109
+ if (U_FAILURE (status))
110
+ len = -1 ;
111
+
112
+ uidna_close (uidna);
113
+ return len;
114
+ }
115
+
116
+ static int32_t ToASCII (MaybeStackBuffer<char >* buf,
117
+ const char * input,
118
+ size_t length) {
119
+ UErrorCode status = U_ZERO_ERROR;
120
+ uint32_t options = UIDNA_DEFAULT;
121
+ options |= UIDNA_NONTRANSITIONAL_TO_ASCII;
122
+ UIDNA* uidna = uidna_openUTS46 (options, &status);
123
+ if (U_FAILURE (status))
124
+ return -1 ;
125
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
126
+
127
+ int32_t len = uidna_nameToASCII_UTF8 (uidna,
128
+ input, length,
129
+ **buf, buf->length (),
130
+ &info,
131
+ &status);
132
+
133
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
134
+ status = U_ZERO_ERROR;
135
+ buf->AllocateSufficientStorage (len);
136
+ len = uidna_nameToASCII_UTF8 (uidna,
137
+ input, length,
138
+ **buf, buf->length (),
139
+ &info,
140
+ &status);
141
+ }
142
+
143
+ if (U_FAILURE (status))
144
+ len = -1 ;
145
+
146
+ uidna_close (uidna);
147
+ return len;
148
+ }
149
+
150
+ static void ToUnicode (const FunctionCallbackInfo<Value>& args) {
151
+ Environment* env = Environment::GetCurrent (args);
152
+ CHECK_GE (args.Length (), 1 );
153
+ CHECK (args[0 ]->IsString ());
154
+ Utf8Value val (env->isolate (), args[0 ]);
155
+ MaybeStackBuffer<char > buf;
156
+ int32_t len = ToUnicode (&buf, *val, val.length ());
157
+
158
+ if (len < 0 ) {
159
+ return env->ThrowError (" Cannot convert name to Unicode" );
160
+ }
161
+
162
+ args.GetReturnValue ().Set (
163
+ String::NewFromUtf8 (env->isolate (),
164
+ *buf,
165
+ v8::NewStringType::kNormal ,
166
+ len).ToLocalChecked ());
167
+ }
168
+
169
+ static void ToASCII (const FunctionCallbackInfo<Value>& args) {
170
+ Environment* env = Environment::GetCurrent (args);
171
+ CHECK_GE (args.Length (), 1 );
172
+ CHECK (args[0 ]->IsString ());
173
+ Utf8Value val (env->isolate (), args[0 ]);
174
+ MaybeStackBuffer<char > buf;
175
+ int32_t len = ToASCII (&buf, *val, val.length ());
176
+
177
+ if (len < 0 ) {
178
+ return env->ThrowError (" Cannot convert name to ASCII" );
179
+ }
180
+
181
+ args.GetReturnValue ().Set (
182
+ String::NewFromUtf8 (env->isolate (),
183
+ *buf,
184
+ v8::NewStringType::kNormal ,
185
+ len).ToLocalChecked ());
186
+ }
187
+
188
+ void Init (Local<Object> target,
189
+ Local<Value> unused,
190
+ Local<Context> context,
191
+ void * priv) {
192
+ Environment* env = Environment::GetCurrent (context);
193
+ env->SetMethod (target, " toUnicode" , ToUnicode);
194
+ env->SetMethod (target, " toASCII" , ToASCII);
195
+ }
196
+
67
197
} // namespace i18n
68
198
} // namespace node
69
199
200
+ NODE_MODULE_CONTEXT_AWARE_BUILTIN (icu, node::i18n::Init)
201
+
70
202
#endif // NODE_HAVE_I18N_SUPPORT
0 commit comments