|
31 | 31 | #include "util-inl.h"
|
32 | 32 | #include "v8.h"
|
33 | 33 |
|
| 34 | +#include <unicode/utypes.h> |
34 | 35 | #include <unicode/putil.h>
|
35 | 36 | #include <unicode/uchar.h>
|
36 | 37 | #include <unicode/udata.h>
|
37 | 38 | #include <unicode/uidna.h>
|
38 |
| -#include <unicode/utypes.h> |
39 | 39 | #include <unicode/ucnv.h>
|
40 | 40 | #include <unicode/utf8.h>
|
41 | 41 | #include <unicode/utf16.h>
|
| 42 | +#include <unicode/timezone.h> |
| 43 | +#include <unicode/ulocdata.h> |
| 44 | +#include <unicode/uvernum.h> |
| 45 | +#include <unicode/uversion.h> |
42 | 46 |
|
43 | 47 | #ifdef NODE_HAVE_SMALL_ICU
|
44 | 48 | /* if this is defined, we have a 'secondary' entry point.
|
@@ -339,6 +343,67 @@ static void ICUErrorName(const FunctionCallbackInfo<Value>& args) {
|
339 | 343 | v8::NewStringType::kNormal).ToLocalChecked());
|
340 | 344 | }
|
341 | 345 |
|
| 346 | +#define TYPE_ICU "icu" |
| 347 | +#define TYPE_UNICODE "unicode" |
| 348 | +#define TYPE_CLDR "cldr" |
| 349 | +#define TYPE_TZ "tz" |
| 350 | + |
| 351 | +/** |
| 352 | + * This is the workhorse function that deals with the actual version info. |
| 353 | + * Get an ICU version. |
| 354 | + * @param type the type of version to get. One of VERSION_TYPES |
| 355 | + * @param buf optional buffer for result |
| 356 | + * @param status ICU error status. If failure, assume result is undefined. |
| 357 | + * @return version number, or NULL. May or may not be buf. |
| 358 | + */ |
| 359 | +static const char* GetVersion(const char* type, |
| 360 | + char buf[U_MAX_VERSION_STRING_LENGTH], |
| 361 | + UErrorCode* status) { |
| 362 | + if (!strcmp(type, TYPE_ICU)) { |
| 363 | + return U_ICU_VERSION; |
| 364 | + } else if (!strcmp(type, TYPE_UNICODE)) { |
| 365 | + return U_UNICODE_VERSION; |
| 366 | + } else if (!strcmp(type, TYPE_TZ)) { |
| 367 | + return TimeZone::getTZDataVersion(*status); |
| 368 | + } else if (!strcmp(type, TYPE_CLDR)) { |
| 369 | + UVersionInfo versionArray; |
| 370 | + ulocdata_getCLDRVersion(versionArray, status); |
| 371 | + if (U_SUCCESS(*status)) { |
| 372 | + u_versionToString(versionArray, buf); |
| 373 | + return buf; |
| 374 | + } |
| 375 | + } |
| 376 | + // Fall through - unknown type or error case |
| 377 | + return nullptr; |
| 378 | +} |
| 379 | + |
| 380 | +static void GetVersion(const FunctionCallbackInfo<Value>& args) { |
| 381 | + Environment* env = Environment::GetCurrent(args); |
| 382 | + if ( args.Length() == 0 ) { |
| 383 | + // With no args - return a comma-separated list of allowed values |
| 384 | + args.GetReturnValue().Set( |
| 385 | + String::NewFromUtf8(env->isolate(), |
| 386 | + TYPE_ICU "," |
| 387 | + TYPE_UNICODE "," |
| 388 | + TYPE_CLDR "," |
| 389 | + TYPE_TZ)); |
| 390 | + } else { |
| 391 | + CHECK_GE(args.Length(), 1); |
| 392 | + CHECK(args[0]->IsString()); |
| 393 | + Utf8Value val(env->isolate(), args[0]); |
| 394 | + UErrorCode status = U_ZERO_ERROR; |
| 395 | + char buf[U_MAX_VERSION_STRING_LENGTH] = ""; // Possible output buffer. |
| 396 | + const char* versionString = GetVersion(*val, buf, &status); |
| 397 | + |
| 398 | + if (U_SUCCESS(status) && versionString) { |
| 399 | + // Success. |
| 400 | + args.GetReturnValue().Set( |
| 401 | + String::NewFromUtf8(env->isolate(), |
| 402 | + versionString)); |
| 403 | + } |
| 404 | + } |
| 405 | +} |
| 406 | + |
342 | 407 | bool InitializeICUDirectory(const char* icu_data_path) {
|
343 | 408 | if (icu_data_path != nullptr) {
|
344 | 409 | flag_icu_data_dir = true;
|
@@ -558,6 +623,7 @@ void Init(Local<Object> target,
|
558 | 623 | env->SetMethod(target, "toUnicode", ToUnicode);
|
559 | 624 | env->SetMethod(target, "toASCII", ToASCII);
|
560 | 625 | env->SetMethod(target, "getStringWidth", GetStringWidth);
|
| 626 | + env->SetMethod(target, "getVersion", GetVersion); |
561 | 627 |
|
562 | 628 | // One-shot converters
|
563 | 629 | env->SetMethod(target, "icuErrName", ICUErrorName);
|
|
0 commit comments