mirror of https://github.com/lukechilds/node.git
isaacs
13 years ago
146 changed files with 2240 additions and 3943 deletions
@ -0,0 +1,225 @@ |
|||||
|
# Copyright 2012 the V8 project authors. All rights reserved. |
||||
|
# Redistribution and use in source and binary forms, with or without |
||||
|
# modification, are permitted provided that the following conditions are |
||||
|
# met: |
||||
|
# |
||||
|
# * Redistributions of source code must retain the above copyright |
||||
|
# notice, this list of conditions and the following disclaimer. |
||||
|
# * Redistributions in binary form must reproduce the above |
||||
|
# copyright notice, this list of conditions and the following |
||||
|
# disclaimer in the documentation and/or other materials provided |
||||
|
# with the distribution. |
||||
|
# * Neither the name of Google Inc. nor the names of its |
||||
|
# contributors may be used to endorse or promote products derived |
||||
|
# from this software without specific prior written permission. |
||||
|
# |
||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
|
||||
|
# Definitions for building standalone V8 binaries to run on Android. |
||||
|
# This is mostly excerpted from: |
||||
|
# http://src.chromium.org/viewvc/chrome/trunk/src/build/common.gypi |
||||
|
|
||||
|
{ |
||||
|
'variables': { |
||||
|
# Location of Android NDK. |
||||
|
'variables': { |
||||
|
'variables': { |
||||
|
'android_ndk_root%': '<!(/bin/echo -n $ANDROID_NDK_ROOT)', |
||||
|
'android_target_arch%': 'arm', # target_arch in android terms. |
||||
|
|
||||
|
# Switch between different build types, currently only '0' is |
||||
|
# supported. |
||||
|
'android_build_type%': 0, |
||||
|
}, |
||||
|
'android_ndk_root%': '<(android_ndk_root)', |
||||
|
'android_ndk_sysroot': '<(android_ndk_root)/platforms/android-9/arch-<(android_target_arch)', |
||||
|
'android_build_type%': '<(android_build_type)', |
||||
|
}, |
||||
|
'android_ndk_root%': '<(android_ndk_root)', |
||||
|
'android_ndk_sysroot': '<(android_ndk_sysroot)', |
||||
|
'android_ndk_include': '<(android_ndk_sysroot)/usr/include', |
||||
|
'android_ndk_lib': '<(android_ndk_sysroot)/usr/lib', |
||||
|
# Enable to use the system stlport, otherwise statically |
||||
|
# link the NDK one? |
||||
|
'use_system_stlport%': '<(android_build_type)', |
||||
|
'android_stlport_library': 'stlport_static', |
||||
|
# Copy it out one scope. |
||||
|
'android_build_type%': '<(android_build_type)', |
||||
|
|
||||
|
'OS': 'android', |
||||
|
'target_arch': 'arm', |
||||
|
'v8_target_arch': 'arm', |
||||
|
'armv7': 1, |
||||
|
'arm_neon': 0, |
||||
|
'arm_fpu': 'vfpv3', |
||||
|
}, # variables |
||||
|
'target_defaults': { |
||||
|
'defines': [ |
||||
|
'ANDROID', |
||||
|
'V8_ANDROID_LOG_STDOUT', |
||||
|
], |
||||
|
'configurations': { |
||||
|
'Release': { |
||||
|
'cflags!': [ |
||||
|
'-O2', |
||||
|
'-Os', |
||||
|
], |
||||
|
'cflags': [ |
||||
|
'-fdata-sections', |
||||
|
'-ffunction-sections', |
||||
|
'-fomit-frame-pointer', |
||||
|
'-O3', |
||||
|
], |
||||
|
}, # Release |
||||
|
}, # configurations |
||||
|
'cflags': [ '-Wno-abi', '-Wall', '-W', '-Wno-unused-parameter', |
||||
|
'-Wnon-virtual-dtor', '-fno-rtti', '-fno-exceptions', ], |
||||
|
'target_conditions': [ |
||||
|
['_toolset=="target"', { |
||||
|
'cflags!': [ |
||||
|
'-pthread', # Not supported by Android toolchain. |
||||
|
], |
||||
|
'cflags': [ |
||||
|
'-U__linux__', # Don't allow toolchain to claim -D__linux__ |
||||
|
'-ffunction-sections', |
||||
|
'-funwind-tables', |
||||
|
'-fstack-protector', |
||||
|
'-fno-short-enums', |
||||
|
'-finline-limit=64', |
||||
|
'-Wa,--noexecstack', |
||||
|
'-Wno-error=non-virtual-dtor', # TODO(michaelbai): Fix warnings. |
||||
|
# Note: This include is in cflags to ensure that it comes after |
||||
|
# all of the includes. |
||||
|
'-I<(android_ndk_include)', |
||||
|
'-march=armv7-a', |
||||
|
'-mtune=cortex-a8', |
||||
|
'-mfpu=vfp3', |
||||
|
], |
||||
|
'defines': [ |
||||
|
'ANDROID', |
||||
|
#'__GNU_SOURCE=1', # Necessary for clone() |
||||
|
'USE_STLPORT=1', |
||||
|
'_STLP_USE_PTR_SPECIALIZATIONS=1', |
||||
|
'HAVE_OFF64_T', |
||||
|
'HAVE_SYS_UIO_H', |
||||
|
'ANDROID_BINSIZE_HACK', # Enable temporary hacks to reduce binsize. |
||||
|
], |
||||
|
'ldflags!': [ |
||||
|
'-pthread', # Not supported by Android toolchain. |
||||
|
], |
||||
|
'ldflags': [ |
||||
|
'-nostdlib', |
||||
|
'-Wl,--no-undefined', |
||||
|
'-Wl,--icf=safe', # Enable identical code folding to reduce size |
||||
|
# Don't export symbols from statically linked libraries. |
||||
|
'-Wl,--exclude-libs=ALL', |
||||
|
], |
||||
|
'libraries!': [ |
||||
|
'-lrt', # librt is built into Bionic. |
||||
|
# Not supported by Android toolchain. |
||||
|
# Where do these come from? Can't find references in |
||||
|
# any Chromium gyp or gypi file. Maybe they come from |
||||
|
# gyp itself? |
||||
|
'-lpthread', '-lnss3', '-lnssutil3', '-lsmime3', '-lplds4', '-lplc4', '-lnspr4', |
||||
|
], |
||||
|
'libraries': [ |
||||
|
'-l<(android_stlport_library)', |
||||
|
# Manually link the libgcc.a that the cross compiler uses. |
||||
|
'<!($CC -print-libgcc-file-name)', |
||||
|
'-lc', |
||||
|
'-ldl', |
||||
|
'-lstdc++', |
||||
|
'-lm', |
||||
|
], |
||||
|
'conditions': [ |
||||
|
['android_build_type==0', { |
||||
|
'ldflags': [ |
||||
|
'-Wl,-rpath-link=<(android_ndk_lib)', |
||||
|
'-L<(android_ndk_lib)', |
||||
|
], |
||||
|
}], |
||||
|
# NOTE: The stlport header include paths below are specified in |
||||
|
# cflags rather than include_dirs because they need to come |
||||
|
# after include_dirs. Think of them like system headers, but |
||||
|
# don't use '-isystem' because the arm-linux-androideabi-4.4.3 |
||||
|
# toolchain (circa Gingerbread) will exhibit strange errors. |
||||
|
# The include ordering here is important; change with caution. |
||||
|
['use_system_stlport==0', { |
||||
|
'cflags': [ |
||||
|
'-I<(android_ndk_root)/sources/cxx-stl/stlport/stlport', |
||||
|
], |
||||
|
'conditions': [ |
||||
|
['target_arch=="arm" and armv7==1', { |
||||
|
'ldflags': [ |
||||
|
'-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/armeabi-v7a', |
||||
|
], |
||||
|
}], |
||||
|
['target_arch=="arm" and armv7==0', { |
||||
|
'ldflags': [ |
||||
|
'-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/armeabi', |
||||
|
], |
||||
|
}], |
||||
|
['target_arch=="ia32"', { |
||||
|
'ldflags': [ |
||||
|
'-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/x86', |
||||
|
], |
||||
|
}], |
||||
|
], |
||||
|
}], |
||||
|
['target_arch=="ia32"', { |
||||
|
# The x86 toolchain currently has problems with stack-protector. |
||||
|
'cflags!': [ |
||||
|
'-fstack-protector', |
||||
|
], |
||||
|
'cflags': [ |
||||
|
'-fno-stack-protector', |
||||
|
], |
||||
|
}], |
||||
|
], |
||||
|
'target_conditions': [ |
||||
|
['_type=="executable"', { |
||||
|
'ldflags': [ |
||||
|
'-Bdynamic', |
||||
|
'-Wl,-dynamic-linker,/system/bin/linker', |
||||
|
'-Wl,--gc-sections', |
||||
|
'-Wl,-z,nocopyreloc', |
||||
|
# crtbegin_dynamic.o should be the last item in ldflags. |
||||
|
'<(android_ndk_lib)/crtbegin_dynamic.o', |
||||
|
], |
||||
|
'libraries': [ |
||||
|
# crtend_android.o needs to be the last item in libraries. |
||||
|
# Do not add any libraries after this! |
||||
|
'<(android_ndk_lib)/crtend_android.o', |
||||
|
], |
||||
|
}], |
||||
|
['_type=="shared_library"', { |
||||
|
'ldflags': [ |
||||
|
'-Wl,-shared,-Bsymbolic', |
||||
|
], |
||||
|
}], |
||||
|
], |
||||
|
}], # _toolset=="target" |
||||
|
# Settings for building host targets using the system toolchain. |
||||
|
['_toolset=="host"', { |
||||
|
'cflags': [ '-m32', '-pthread' ], |
||||
|
'ldflags': [ '-m32', '-pthread' ], |
||||
|
'ldflags!': [ |
||||
|
'-Wl,-z,noexecstack', |
||||
|
'-Wl,--gc-sections', |
||||
|
'-Wl,-O1', |
||||
|
'-Wl,--as-needed', |
||||
|
], |
||||
|
}], |
||||
|
], # target_conditions |
||||
|
}, # target_defaults |
||||
|
} |
@ -1,252 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/break-iterator.h" |
|
||||
|
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "unicode/brkiter.h" |
|
||||
#include "unicode/locid.h" |
|
||||
#include "unicode/rbbi.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
v8::Persistent<v8::FunctionTemplate> BreakIterator::break_iterator_template_; |
|
||||
|
|
||||
icu::BreakIterator* BreakIterator::UnpackBreakIterator( |
|
||||
v8::Handle<v8::Object> obj) { |
|
||||
if (break_iterator_template_->HasInstance(obj)) { |
|
||||
return static_cast<icu::BreakIterator*>( |
|
||||
obj->GetPointerFromInternalField(0)); |
|
||||
} |
|
||||
|
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
icu::UnicodeString* BreakIterator::ResetAdoptedText( |
|
||||
v8::Handle<v8::Object> obj, v8::Handle<v8::Value> value) { |
|
||||
// Get the previous value from the internal field.
|
|
||||
icu::UnicodeString* text = static_cast<icu::UnicodeString*>( |
|
||||
obj->GetPointerFromInternalField(1)); |
|
||||
delete text; |
|
||||
|
|
||||
// Assign new value to the internal pointer.
|
|
||||
v8::String::Value text_value(value); |
|
||||
text = new icu::UnicodeString( |
|
||||
reinterpret_cast<const UChar*>(*text_value), text_value.length()); |
|
||||
obj->SetPointerInInternalField(1, text); |
|
||||
|
|
||||
// Return new unicode string pointer.
|
|
||||
return text; |
|
||||
} |
|
||||
|
|
||||
void BreakIterator::DeleteBreakIterator(v8::Persistent<v8::Value> object, |
|
||||
void* param) { |
|
||||
v8::Persistent<v8::Object> persistent_object = |
|
||||
v8::Persistent<v8::Object>::Cast(object); |
|
||||
|
|
||||
// First delete the hidden C++ object.
|
|
||||
// Unpacking should never return NULL here. That would only happen if
|
|
||||
// this method is used as the weak callback for persistent handles not
|
|
||||
// pointing to a break iterator.
|
|
||||
delete UnpackBreakIterator(persistent_object); |
|
||||
|
|
||||
delete static_cast<icu::UnicodeString*>( |
|
||||
persistent_object->GetPointerFromInternalField(1)); |
|
||||
|
|
||||
// Then dispose of the persistent handle to JS object.
|
|
||||
persistent_object.Dispose(); |
|
||||
} |
|
||||
|
|
||||
// Throws a JavaScript exception.
|
|
||||
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() { |
|
||||
// Returns undefined, and schedules an exception to be thrown.
|
|
||||
return v8::ThrowException(v8::Exception::Error( |
|
||||
v8::String::New("BreakIterator method called on an object " |
|
||||
"that is not a BreakIterator."))); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> BreakIterator::BreakIteratorAdoptText( |
|
||||
const v8::Arguments& args) { |
|
||||
if (args.Length() != 1 || !args[0]->IsString()) { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Text input is required."))); |
|
||||
} |
|
||||
|
|
||||
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
|
||||
if (!break_iterator) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
break_iterator->setText(*ResetAdoptedText(args.Holder(), args[0])); |
|
||||
|
|
||||
return v8::Undefined(); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> BreakIterator::BreakIteratorFirst( |
|
||||
const v8::Arguments& args) { |
|
||||
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
|
||||
if (!break_iterator) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
return v8::Int32::New(break_iterator->first()); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> BreakIterator::BreakIteratorNext( |
|
||||
const v8::Arguments& args) { |
|
||||
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
|
||||
if (!break_iterator) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
return v8::Int32::New(break_iterator->next()); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> BreakIterator::BreakIteratorCurrent( |
|
||||
const v8::Arguments& args) { |
|
||||
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
|
||||
if (!break_iterator) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
return v8::Int32::New(break_iterator->current()); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> BreakIterator::BreakIteratorBreakType( |
|
||||
const v8::Arguments& args) { |
|
||||
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
|
||||
if (!break_iterator) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
// TODO(cira): Remove cast once ICU fixes base BreakIterator class.
|
|
||||
icu::RuleBasedBreakIterator* rule_based_iterator = |
|
||||
static_cast<icu::RuleBasedBreakIterator*>(break_iterator); |
|
||||
int32_t status = rule_based_iterator->getRuleStatus(); |
|
||||
// Keep return values in sync with JavaScript BreakType enum.
|
|
||||
if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) { |
|
||||
return v8::Int32::New(UBRK_WORD_NONE); |
|
||||
} else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) { |
|
||||
return v8::Int32::New(UBRK_WORD_NUMBER); |
|
||||
} else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) { |
|
||||
return v8::Int32::New(UBRK_WORD_LETTER); |
|
||||
} else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { |
|
||||
return v8::Int32::New(UBRK_WORD_KANA); |
|
||||
} else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) { |
|
||||
return v8::Int32::New(UBRK_WORD_IDEO); |
|
||||
} else { |
|
||||
return v8::Int32::New(-1); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> BreakIterator::JSBreakIterator( |
|
||||
const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Locale and iterator type are required."))); |
|
||||
} |
|
||||
|
|
||||
v8::String::Utf8Value locale(args[0]); |
|
||||
icu::Locale icu_locale(*locale); |
|
||||
|
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
icu::BreakIterator* break_iterator = NULL; |
|
||||
v8::String::Utf8Value type(args[1]); |
|
||||
if (!strcmp(*type, "character")) { |
|
||||
break_iterator = |
|
||||
icu::BreakIterator::createCharacterInstance(icu_locale, status); |
|
||||
} else if (!strcmp(*type, "word")) { |
|
||||
break_iterator = |
|
||||
icu::BreakIterator::createWordInstance(icu_locale, status); |
|
||||
} else if (!strcmp(*type, "sentence")) { |
|
||||
break_iterator = |
|
||||
icu::BreakIterator::createSentenceInstance(icu_locale, status); |
|
||||
} else if (!strcmp(*type, "line")) { |
|
||||
break_iterator = |
|
||||
icu::BreakIterator::createLineInstance(icu_locale, status); |
|
||||
} else { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Invalid iterator type."))); |
|
||||
} |
|
||||
|
|
||||
if (U_FAILURE(status)) { |
|
||||
delete break_iterator; |
|
||||
return v8::ThrowException(v8::Exception::Error( |
|
||||
v8::String::New("Failed to create break iterator."))); |
|
||||
} |
|
||||
|
|
||||
if (break_iterator_template_.IsEmpty()) { |
|
||||
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New()); |
|
||||
|
|
||||
raw_template->SetClassName(v8::String::New("v8Locale.v8BreakIterator")); |
|
||||
|
|
||||
// Define internal field count on instance template.
|
|
||||
v8::Local<v8::ObjectTemplate> object_template = |
|
||||
raw_template->InstanceTemplate(); |
|
||||
|
|
||||
// Set aside internal fields for icu break iterator and adopted text.
|
|
||||
object_template->SetInternalFieldCount(2); |
|
||||
|
|
||||
// Define all of the prototype methods on prototype template.
|
|
||||
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate(); |
|
||||
proto->Set(v8::String::New("adoptText"), |
|
||||
v8::FunctionTemplate::New(BreakIteratorAdoptText)); |
|
||||
proto->Set(v8::String::New("first"), |
|
||||
v8::FunctionTemplate::New(BreakIteratorFirst)); |
|
||||
proto->Set(v8::String::New("next"), |
|
||||
v8::FunctionTemplate::New(BreakIteratorNext)); |
|
||||
proto->Set(v8::String::New("current"), |
|
||||
v8::FunctionTemplate::New(BreakIteratorCurrent)); |
|
||||
proto->Set(v8::String::New("breakType"), |
|
||||
v8::FunctionTemplate::New(BreakIteratorBreakType)); |
|
||||
|
|
||||
break_iterator_template_ = |
|
||||
v8::Persistent<v8::FunctionTemplate>::New(raw_template); |
|
||||
} |
|
||||
|
|
||||
// Create an empty object wrapper.
|
|
||||
v8::Local<v8::Object> local_object = |
|
||||
break_iterator_template_->GetFunction()->NewInstance(); |
|
||||
v8::Persistent<v8::Object> wrapper = |
|
||||
v8::Persistent<v8::Object>::New(local_object); |
|
||||
|
|
||||
// Set break iterator as internal field of the resulting JS object.
|
|
||||
wrapper->SetPointerInInternalField(0, break_iterator); |
|
||||
// Make sure that the pointer to adopted text is NULL.
|
|
||||
wrapper->SetPointerInInternalField(1, NULL); |
|
||||
|
|
||||
// Make object handle weak so we can delete iterator once GC kicks in.
|
|
||||
wrapper.MakeWeak(NULL, DeleteBreakIterator); |
|
||||
|
|
||||
return wrapper; |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,89 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
#include "unicode/uversion.h" |
|
||||
|
|
||||
namespace U_ICU_NAMESPACE { |
|
||||
class BreakIterator; |
|
||||
class UnicodeString; |
|
||||
} |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
class BreakIterator { |
|
||||
public: |
|
||||
static v8::Handle<v8::Value> JSBreakIterator(const v8::Arguments& args); |
|
||||
|
|
||||
// Helper methods for various bindings.
|
|
||||
|
|
||||
// Unpacks break iterator object from corresponding JavaScript object.
|
|
||||
static icu::BreakIterator* UnpackBreakIterator(v8::Handle<v8::Object> obj); |
|
||||
|
|
||||
// Deletes the old value and sets the adopted text in
|
|
||||
// corresponding JavaScript object.
|
|
||||
static icu::UnicodeString* ResetAdoptedText(v8::Handle<v8::Object> obj, |
|
||||
v8::Handle<v8::Value> text_value); |
|
||||
|
|
||||
// Release memory we allocated for the BreakIterator once the JS object that
|
|
||||
// holds the pointer gets garbage collected.
|
|
||||
static void DeleteBreakIterator(v8::Persistent<v8::Value> object, |
|
||||
void* param); |
|
||||
|
|
||||
// Assigns new text to the iterator.
|
|
||||
static v8::Handle<v8::Value> BreakIteratorAdoptText( |
|
||||
const v8::Arguments& args); |
|
||||
|
|
||||
// Moves iterator to the beginning of the string and returns new position.
|
|
||||
static v8::Handle<v8::Value> BreakIteratorFirst(const v8::Arguments& args); |
|
||||
|
|
||||
// Moves iterator to the next position and returns it.
|
|
||||
static v8::Handle<v8::Value> BreakIteratorNext(const v8::Arguments& args); |
|
||||
|
|
||||
// Returns current iterator's current position.
|
|
||||
static v8::Handle<v8::Value> BreakIteratorCurrent( |
|
||||
const v8::Arguments& args); |
|
||||
|
|
||||
// Returns type of the item from current position.
|
|
||||
// This call is only valid for word break iterators. Others just return 0.
|
|
||||
static v8::Handle<v8::Value> BreakIteratorBreakType( |
|
||||
const v8::Arguments& args); |
|
||||
|
|
||||
private: |
|
||||
BreakIterator() {} |
|
||||
|
|
||||
static v8::Persistent<v8::FunctionTemplate> break_iterator_template_; |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
|
|
@ -1,222 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/collator.h" |
|
||||
|
|
||||
#include "unicode/coll.h" |
|
||||
#include "unicode/locid.h" |
|
||||
#include "unicode/ucol.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
v8::Persistent<v8::FunctionTemplate> Collator::collator_template_; |
|
||||
|
|
||||
icu::Collator* Collator::UnpackCollator(v8::Handle<v8::Object> obj) { |
|
||||
if (collator_template_->HasInstance(obj)) { |
|
||||
return static_cast<icu::Collator*>(obj->GetPointerFromInternalField(0)); |
|
||||
} |
|
||||
|
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
void Collator::DeleteCollator(v8::Persistent<v8::Value> object, void* param) { |
|
||||
v8::Persistent<v8::Object> persistent_object = |
|
||||
v8::Persistent<v8::Object>::Cast(object); |
|
||||
|
|
||||
// First delete the hidden C++ object.
|
|
||||
// Unpacking should never return NULL here. That would only happen if
|
|
||||
// this method is used as the weak callback for persistent handles not
|
|
||||
// pointing to a collator.
|
|
||||
delete UnpackCollator(persistent_object); |
|
||||
|
|
||||
// Then dispose of the persistent handle to JS object.
|
|
||||
persistent_object.Dispose(); |
|
||||
} |
|
||||
|
|
||||
// Throws a JavaScript exception.
|
|
||||
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() { |
|
||||
// Returns undefined, and schedules an exception to be thrown.
|
|
||||
return v8::ThrowException(v8::Exception::Error( |
|
||||
v8::String::New("Collator method called on an object " |
|
||||
"that is not a Collator."))); |
|
||||
} |
|
||||
|
|
||||
// Extract a boolean option named in |option| and set it to |result|.
|
|
||||
// Return true if it's specified. Otherwise, return false.
|
|
||||
static bool ExtractBooleanOption(const v8::Local<v8::Object>& options, |
|
||||
const char* option, |
|
||||
bool* result) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
v8::TryCatch try_catch; |
|
||||
v8::Handle<v8::Value> value = options->Get(v8::String::New(option)); |
|
||||
if (try_catch.HasCaught()) { |
|
||||
return false; |
|
||||
} |
|
||||
// No need to check if |value| is empty because it's taken care of
|
|
||||
// by TryCatch above.
|
|
||||
if (!value->IsUndefined() && !value->IsNull()) { |
|
||||
if (value->IsBoolean()) { |
|
||||
*result = value->BooleanValue(); |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// When there's an ICU error, throw a JavaScript error with |message|.
|
|
||||
static v8::Handle<v8::Value> ThrowExceptionForICUError(const char* message) { |
|
||||
return v8::ThrowException(v8::Exception::Error(v8::String::New(message))); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> Collator::CollatorCompare(const v8::Arguments& args) { |
|
||||
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Two string arguments are required."))); |
|
||||
} |
|
||||
|
|
||||
icu::Collator* collator = UnpackCollator(args.Holder()); |
|
||||
if (!collator) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
v8::String::Value string_value1(args[0]); |
|
||||
v8::String::Value string_value2(args[1]); |
|
||||
const UChar* string1 = reinterpret_cast<const UChar*>(*string_value1); |
|
||||
const UChar* string2 = reinterpret_cast<const UChar*>(*string_value2); |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
UCollationResult result = collator->compare( |
|
||||
string1, string_value1.length(), string2, string_value2.length(), status); |
|
||||
|
|
||||
if (U_FAILURE(status)) { |
|
||||
return ThrowExceptionForICUError( |
|
||||
"Unexpected failure in Collator.compare."); |
|
||||
} |
|
||||
|
|
||||
return v8::Int32::New(result); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> Collator::JSCollator(const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Locale and collation options are required."))); |
|
||||
} |
|
||||
|
|
||||
v8::String::AsciiValue locale(args[0]); |
|
||||
icu::Locale icu_locale(*locale); |
|
||||
|
|
||||
icu::Collator* collator = NULL; |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
collator = icu::Collator::createInstance(icu_locale, status); |
|
||||
|
|
||||
if (U_FAILURE(status)) { |
|
||||
delete collator; |
|
||||
return ThrowExceptionForICUError("Failed to create collator."); |
|
||||
} |
|
||||
|
|
||||
v8::Local<v8::Object> options(args[1]->ToObject()); |
|
||||
|
|
||||
// Below, we change collation options that are explicitly specified
|
|
||||
// by a caller in JavaScript. Otherwise, we don't touch because
|
|
||||
// we don't want to change the locale-dependent default value.
|
|
||||
// The three options below are very likely to have the same default
|
|
||||
// across locales, but I haven't checked them all. Others we may add
|
|
||||
// in the future have certainly locale-dependent default (e.g.
|
|
||||
// caseFirst is upperFirst for Danish while is off for most other locales).
|
|
||||
|
|
||||
bool ignore_case, ignore_accents, numeric; |
|
||||
|
|
||||
if (ExtractBooleanOption(options, "ignoreCase", &ignore_case)) { |
|
||||
// We need to explicitly set the level to secondary to get case ignored.
|
|
||||
// The default L3 ignores UCOL_CASE_LEVEL == UCOL_OFF !
|
|
||||
if (ignore_case) { |
|
||||
collator->setStrength(icu::Collator::SECONDARY); |
|
||||
} |
|
||||
collator->setAttribute(UCOL_CASE_LEVEL, ignore_case ? UCOL_OFF : UCOL_ON, |
|
||||
status); |
|
||||
if (U_FAILURE(status)) { |
|
||||
delete collator; |
|
||||
return ThrowExceptionForICUError("Failed to set ignoreCase."); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Accents are taken into account with strength secondary or higher.
|
|
||||
if (ExtractBooleanOption(options, "ignoreAccents", &ignore_accents)) { |
|
||||
if (!ignore_accents) { |
|
||||
collator->setStrength(icu::Collator::SECONDARY); |
|
||||
} else { |
|
||||
collator->setStrength(icu::Collator::PRIMARY); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (ExtractBooleanOption(options, "numeric", &numeric)) { |
|
||||
collator->setAttribute(UCOL_NUMERIC_COLLATION, |
|
||||
numeric ? UCOL_ON : UCOL_OFF, status); |
|
||||
if (U_FAILURE(status)) { |
|
||||
delete collator; |
|
||||
return ThrowExceptionForICUError("Failed to set numeric sort option."); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (collator_template_.IsEmpty()) { |
|
||||
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New()); |
|
||||
raw_template->SetClassName(v8::String::New("v8Locale.Collator")); |
|
||||
|
|
||||
// Define internal field count on instance template.
|
|
||||
v8::Local<v8::ObjectTemplate> object_template = |
|
||||
raw_template->InstanceTemplate(); |
|
||||
|
|
||||
// Set aside internal fields for icu collator.
|
|
||||
object_template->SetInternalFieldCount(1); |
|
||||
|
|
||||
// Define all of the prototype methods on prototype template.
|
|
||||
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate(); |
|
||||
proto->Set(v8::String::New("compare"), |
|
||||
v8::FunctionTemplate::New(CollatorCompare)); |
|
||||
|
|
||||
collator_template_ = |
|
||||
v8::Persistent<v8::FunctionTemplate>::New(raw_template); |
|
||||
} |
|
||||
|
|
||||
// Create an empty object wrapper.
|
|
||||
v8::Local<v8::Object> local_object = |
|
||||
collator_template_->GetFunction()->NewInstance(); |
|
||||
v8::Persistent<v8::Object> wrapper = |
|
||||
v8::Persistent<v8::Object>::New(local_object); |
|
||||
|
|
||||
// Set collator as internal field of the resulting JS object.
|
|
||||
wrapper->SetPointerInInternalField(0, collator); |
|
||||
|
|
||||
// Make object handle weak so we can delete iterator once GC kicks in.
|
|
||||
wrapper.MakeWeak(NULL, DeleteCollator); |
|
||||
|
|
||||
return wrapper; |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,68 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_COLLATOR_H |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_COLLATOR_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
#include "unicode/uversion.h" |
|
||||
|
|
||||
namespace U_ICU_NAMESPACE { |
|
||||
class Collator; |
|
||||
class UnicodeString; |
|
||||
} |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
class Collator { |
|
||||
public: |
|
||||
static v8::Handle<v8::Value> JSCollator(const v8::Arguments& args); |
|
||||
|
|
||||
// Helper methods for various bindings.
|
|
||||
|
|
||||
// Unpacks collator object from corresponding JavaScript object.
|
|
||||
static icu::Collator* UnpackCollator(v8::Handle<v8::Object> obj); |
|
||||
|
|
||||
// Release memory we allocated for the Collator once the JS object that
|
|
||||
// holds the pointer gets garbage collected.
|
|
||||
static void DeleteCollator(v8::Persistent<v8::Value> object, void* param); |
|
||||
|
|
||||
// Compare two strings and returns -1, 0 and 1 depending on
|
|
||||
// whether string1 is smaller than, equal to or larger than string2.
|
|
||||
static v8::Handle<v8::Value> CollatorCompare(const v8::Arguments& args); |
|
||||
|
|
||||
private: |
|
||||
Collator() {} |
|
||||
|
|
||||
static v8::Persistent<v8::FunctionTemplate> collator_template_; |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_COLLATOR
|
|
@ -1,384 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/datetime-format.h" |
|
||||
|
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-utils.h" |
|
||||
#include "unicode/dtfmtsym.h" |
|
||||
#include "unicode/dtptngen.h" |
|
||||
#include "unicode/locid.h" |
|
||||
#include "unicode/smpdtfmt.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
v8::Persistent<v8::FunctionTemplate> DateTimeFormat::datetime_format_template_; |
|
||||
|
|
||||
static icu::DateFormat* CreateDateTimeFormat(v8::Handle<v8::String>, |
|
||||
v8::Handle<v8::Object>); |
|
||||
static v8::Handle<v8::Value> GetSymbols( |
|
||||
const v8::Arguments&, |
|
||||
const icu::UnicodeString*, int32_t, |
|
||||
const icu::UnicodeString*, int32_t, |
|
||||
const icu::UnicodeString*, int32_t); |
|
||||
static v8::Handle<v8::Value> ThrowUnexpectedObjectError(); |
|
||||
static icu::DateFormat::EStyle GetDateTimeStyle(const icu::UnicodeString&); |
|
||||
|
|
||||
icu::SimpleDateFormat* DateTimeFormat::UnpackDateTimeFormat( |
|
||||
v8::Handle<v8::Object> obj) { |
|
||||
if (datetime_format_template_->HasInstance(obj)) { |
|
||||
return static_cast<icu::SimpleDateFormat*>( |
|
||||
obj->GetPointerFromInternalField(0)); |
|
||||
} |
|
||||
|
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
void DateTimeFormat::DeleteDateTimeFormat(v8::Persistent<v8::Value> object, |
|
||||
void* param) { |
|
||||
v8::Persistent<v8::Object> persistent_object = |
|
||||
v8::Persistent<v8::Object>::Cast(object); |
|
||||
|
|
||||
// First delete the hidden C++ object.
|
|
||||
// Unpacking should never return NULL here. That would only happen if
|
|
||||
// this method is used as the weak callback for persistent handles not
|
|
||||
// pointing to a date time formatter.
|
|
||||
delete UnpackDateTimeFormat(persistent_object); |
|
||||
|
|
||||
// Then dispose of the persistent handle to JS object.
|
|
||||
persistent_object.Dispose(); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> DateTimeFormat::Format(const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
double millis = 0.0; |
|
||||
if (args.Length() != 1 || !args[0]->IsDate()) { |
|
||||
// Create a new date.
|
|
||||
v8::TryCatch try_catch; |
|
||||
v8::Local<v8::Script> date_script = |
|
||||
v8::Script::Compile(v8::String::New("eval('new Date()')")); |
|
||||
millis = date_script->Run()->NumberValue(); |
|
||||
if (try_catch.HasCaught()) { |
|
||||
return try_catch.ReThrow(); |
|
||||
} |
|
||||
} else { |
|
||||
millis = v8::Date::Cast(*args[0])->NumberValue(); |
|
||||
} |
|
||||
|
|
||||
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder()); |
|
||||
if (!date_format) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
icu::UnicodeString result; |
|
||||
date_format->format(millis, result); |
|
||||
|
|
||||
return v8::String::New( |
|
||||
reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length()); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> DateTimeFormat::GetMonths(const v8::Arguments& args) { |
|
||||
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder()); |
|
||||
if (!date_format) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols(); |
|
||||
|
|
||||
int32_t narrow_count; |
|
||||
const icu::UnicodeString* narrow = symbols->getMonths( |
|
||||
narrow_count, |
|
||||
icu::DateFormatSymbols::STANDALONE, |
|
||||
icu::DateFormatSymbols::NARROW); |
|
||||
int32_t abbrev_count; |
|
||||
const icu::UnicodeString* abbrev = symbols->getMonths( |
|
||||
abbrev_count, |
|
||||
icu::DateFormatSymbols::STANDALONE, |
|
||||
icu::DateFormatSymbols::ABBREVIATED); |
|
||||
int32_t wide_count; |
|
||||
const icu::UnicodeString* wide = symbols->getMonths( |
|
||||
wide_count, |
|
||||
icu::DateFormatSymbols::STANDALONE, |
|
||||
icu::DateFormatSymbols::WIDE); |
|
||||
|
|
||||
return GetSymbols( |
|
||||
args, narrow, narrow_count, abbrev, abbrev_count, wide, wide_count); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> DateTimeFormat::GetWeekdays(const v8::Arguments& args) { |
|
||||
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder()); |
|
||||
if (!date_format) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols(); |
|
||||
|
|
||||
int32_t narrow_count; |
|
||||
const icu::UnicodeString* narrow = symbols->getWeekdays( |
|
||||
narrow_count, |
|
||||
icu::DateFormatSymbols::STANDALONE, |
|
||||
icu::DateFormatSymbols::NARROW); |
|
||||
int32_t abbrev_count; |
|
||||
const icu::UnicodeString* abbrev = symbols->getWeekdays( |
|
||||
abbrev_count, |
|
||||
icu::DateFormatSymbols::STANDALONE, |
|
||||
icu::DateFormatSymbols::ABBREVIATED); |
|
||||
int32_t wide_count; |
|
||||
const icu::UnicodeString* wide = symbols->getWeekdays( |
|
||||
wide_count, |
|
||||
icu::DateFormatSymbols::STANDALONE, |
|
||||
icu::DateFormatSymbols::WIDE); |
|
||||
|
|
||||
// getXXXWeekdays always returns 8 elements - ICU stable API.
|
|
||||
// We can't use ASSERT_EQ(8, narrow_count) because ASSERT is internal to v8.
|
|
||||
if (narrow_count != 8 || abbrev_count != 8 || wide_count != 8) { |
|
||||
return v8::ThrowException(v8::Exception::Error( |
|
||||
v8::String::New("Failed to get weekday information."))); |
|
||||
} |
|
||||
|
|
||||
// ICU documentation says we should ignore element 0 of the returned array.
|
|
||||
return GetSymbols(args, narrow + 1, narrow_count - 1, abbrev + 1, |
|
||||
abbrev_count -1 , wide + 1, wide_count - 1); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> DateTimeFormat::GetEras(const v8::Arguments& args) { |
|
||||
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder()); |
|
||||
if (!date_format) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols(); |
|
||||
|
|
||||
int32_t narrow_count; |
|
||||
const icu::UnicodeString* narrow = symbols->getNarrowEras(narrow_count); |
|
||||
int32_t abbrev_count; |
|
||||
const icu::UnicodeString* abbrev = symbols->getEras(abbrev_count); |
|
||||
int32_t wide_count; |
|
||||
const icu::UnicodeString* wide = symbols->getEraNames(wide_count); |
|
||||
|
|
||||
return GetSymbols( |
|
||||
args, narrow, narrow_count, abbrev, abbrev_count, wide, wide_count); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> DateTimeFormat::GetAmPm(const v8::Arguments& args) { |
|
||||
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder()); |
|
||||
if (!date_format) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols(); |
|
||||
|
|
||||
// In this case narrow == abbreviated == wide
|
|
||||
int32_t count; |
|
||||
const icu::UnicodeString* wide = symbols->getAmPmStrings(count); |
|
||||
|
|
||||
return GetSymbols(args, wide, count, wide, count, wide, count); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> DateTimeFormat::JSDateTimeFormat( |
|
||||
const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Locale and date/time options are required."))); |
|
||||
} |
|
||||
|
|
||||
icu::SimpleDateFormat* date_format = static_cast<icu::SimpleDateFormat*>( |
|
||||
CreateDateTimeFormat(args[0]->ToString(), args[1]->ToObject())); |
|
||||
|
|
||||
if (datetime_format_template_.IsEmpty()) { |
|
||||
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New()); |
|
||||
|
|
||||
raw_template->SetClassName(v8::String::New("v8Locale.DateTimeFormat")); |
|
||||
|
|
||||
// Define internal field count on instance template.
|
|
||||
v8::Local<v8::ObjectTemplate> object_template = |
|
||||
raw_template->InstanceTemplate(); |
|
||||
|
|
||||
// Set aside internal field for icu date time formatter.
|
|
||||
object_template->SetInternalFieldCount(1); |
|
||||
|
|
||||
// Define all of the prototype methods on prototype template.
|
|
||||
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate(); |
|
||||
proto->Set(v8::String::New("format"), |
|
||||
v8::FunctionTemplate::New(Format)); |
|
||||
proto->Set(v8::String::New("getMonths"), |
|
||||
v8::FunctionTemplate::New(GetMonths)); |
|
||||
proto->Set(v8::String::New("getWeekdays"), |
|
||||
v8::FunctionTemplate::New(GetWeekdays)); |
|
||||
proto->Set(v8::String::New("getEras"), |
|
||||
v8::FunctionTemplate::New(GetEras)); |
|
||||
proto->Set(v8::String::New("getAmPm"), |
|
||||
v8::FunctionTemplate::New(GetAmPm)); |
|
||||
|
|
||||
datetime_format_template_ = |
|
||||
v8::Persistent<v8::FunctionTemplate>::New(raw_template); |
|
||||
} |
|
||||
|
|
||||
// Create an empty object wrapper.
|
|
||||
v8::Local<v8::Object> local_object = |
|
||||
datetime_format_template_->GetFunction()->NewInstance(); |
|
||||
v8::Persistent<v8::Object> wrapper = |
|
||||
v8::Persistent<v8::Object>::New(local_object); |
|
||||
|
|
||||
// Set date time formatter as internal field of the resulting JS object.
|
|
||||
wrapper->SetPointerInInternalField(0, date_format); |
|
||||
|
|
||||
// Set resolved pattern in options.pattern.
|
|
||||
icu::UnicodeString pattern; |
|
||||
date_format->toPattern(pattern); |
|
||||
v8::Local<v8::Object> options = v8::Object::New(); |
|
||||
options->Set(v8::String::New("pattern"), |
|
||||
v8::String::New(reinterpret_cast<const uint16_t*>( |
|
||||
pattern.getBuffer()), pattern.length())); |
|
||||
wrapper->Set(v8::String::New("options"), options); |
|
||||
|
|
||||
// Make object handle weak so we can delete iterator once GC kicks in.
|
|
||||
wrapper.MakeWeak(NULL, DeleteDateTimeFormat); |
|
||||
|
|
||||
return wrapper; |
|
||||
} |
|
||||
|
|
||||
// Returns SimpleDateFormat.
|
|
||||
static icu::DateFormat* CreateDateTimeFormat( |
|
||||
v8::Handle<v8::String> locale, v8::Handle<v8::Object> settings) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
v8::String::AsciiValue ascii_locale(locale); |
|
||||
icu::Locale icu_locale(*ascii_locale); |
|
||||
|
|
||||
// Make formatter from skeleton.
|
|
||||
icu::SimpleDateFormat* date_format = NULL; |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
icu::UnicodeString skeleton; |
|
||||
if (I18NUtils::ExtractStringSetting(settings, "skeleton", &skeleton)) { |
|
||||
v8::Local<icu::DateTimePatternGenerator> generator( |
|
||||
icu::DateTimePatternGenerator::createInstance(icu_locale, status)); |
|
||||
icu::UnicodeString pattern = |
|
||||
generator->getBestPattern(skeleton, status); |
|
||||
|
|
||||
date_format = new icu::SimpleDateFormat(pattern, icu_locale, status); |
|
||||
if (U_SUCCESS(status)) { |
|
||||
return date_format; |
|
||||
} else { |
|
||||
delete date_format; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Extract date style and time style from settings.
|
|
||||
icu::UnicodeString date_style; |
|
||||
icu::DateFormat::EStyle icu_date_style = icu::DateFormat::kNone; |
|
||||
if (I18NUtils::ExtractStringSetting(settings, "dateStyle", &date_style)) { |
|
||||
icu_date_style = GetDateTimeStyle(date_style); |
|
||||
} |
|
||||
|
|
||||
icu::UnicodeString time_style; |
|
||||
icu::DateFormat::EStyle icu_time_style = icu::DateFormat::kNone; |
|
||||
if (I18NUtils::ExtractStringSetting(settings, "timeStyle", &time_style)) { |
|
||||
icu_time_style = GetDateTimeStyle(time_style); |
|
||||
} |
|
||||
|
|
||||
// Try all combinations of date/time styles.
|
|
||||
if (icu_date_style == icu::DateFormat::kNone && |
|
||||
icu_time_style == icu::DateFormat::kNone) { |
|
||||
// Return default short date, short
|
|
||||
return icu::DateFormat::createDateTimeInstance( |
|
||||
icu::DateFormat::kShort, icu::DateFormat::kShort, icu_locale); |
|
||||
} else if (icu_date_style != icu::DateFormat::kNone && |
|
||||
icu_time_style != icu::DateFormat::kNone) { |
|
||||
return icu::DateFormat::createDateTimeInstance( |
|
||||
icu_date_style, icu_time_style, icu_locale); |
|
||||
} else if (icu_date_style != icu::DateFormat::kNone) { |
|
||||
return icu::DateFormat::createDateInstance(icu_date_style, icu_locale); |
|
||||
} else { |
|
||||
// icu_time_style != icu::DateFormat::kNone
|
|
||||
return icu::DateFormat::createTimeInstance(icu_time_style, icu_locale); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Creates a v8::Array of narrow, abbrev or wide symbols.
|
|
||||
static v8::Handle<v8::Value> GetSymbols(const v8::Arguments& args, |
|
||||
const icu::UnicodeString* narrow, |
|
||||
int32_t narrow_count, |
|
||||
const icu::UnicodeString* abbrev, |
|
||||
int32_t abbrev_count, |
|
||||
const icu::UnicodeString* wide, |
|
||||
int32_t wide_count) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
// Make wide width default.
|
|
||||
const icu::UnicodeString* result = wide; |
|
||||
int32_t count = wide_count; |
|
||||
|
|
||||
if (args.Length() == 1 && args[0]->IsString()) { |
|
||||
v8::String::AsciiValue ascii_value(args[0]); |
|
||||
if (strcmp(*ascii_value, "abbreviated") == 0) { |
|
||||
result = abbrev; |
|
||||
count = abbrev_count; |
|
||||
} else if (strcmp(*ascii_value, "narrow") == 0) { |
|
||||
result = narrow; |
|
||||
count = narrow_count; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Array> symbols = v8::Array::New(); |
|
||||
for (int32_t i = 0; i < count; ++i) { |
|
||||
symbols->Set(i, v8::String::New( |
|
||||
reinterpret_cast<const uint16_t*>(result[i].getBuffer()), |
|
||||
result[i].length())); |
|
||||
} |
|
||||
|
|
||||
return handle_scope.Close(symbols); |
|
||||
} |
|
||||
|
|
||||
// Throws a JavaScript exception.
|
|
||||
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() { |
|
||||
// Returns undefined, and schedules an exception to be thrown.
|
|
||||
return v8::ThrowException(v8::Exception::Error( |
|
||||
v8::String::New("DateTimeFormat method called on an object " |
|
||||
"that is not a DateTimeFormat."))); |
|
||||
} |
|
||||
|
|
||||
// Returns icu date/time style.
|
|
||||
static icu::DateFormat::EStyle GetDateTimeStyle( |
|
||||
const icu::UnicodeString& type) { |
|
||||
if (type == UNICODE_STRING_SIMPLE("medium")) { |
|
||||
return icu::DateFormat::kMedium; |
|
||||
} else if (type == UNICODE_STRING_SIMPLE("long")) { |
|
||||
return icu::DateFormat::kLong; |
|
||||
} else if (type == UNICODE_STRING_SIMPLE("full")) { |
|
||||
return icu::DateFormat::kFull; |
|
||||
} |
|
||||
|
|
||||
return icu::DateFormat::kShort; |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,83 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
#include "unicode/uversion.h" |
|
||||
|
|
||||
namespace U_ICU_NAMESPACE { |
|
||||
class SimpleDateFormat; |
|
||||
} |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
class DateTimeFormat { |
|
||||
public: |
|
||||
static v8::Handle<v8::Value> JSDateTimeFormat(const v8::Arguments& args); |
|
||||
|
|
||||
// Helper methods for various bindings.
|
|
||||
|
|
||||
// Unpacks date format object from corresponding JavaScript object.
|
|
||||
static icu::SimpleDateFormat* UnpackDateTimeFormat( |
|
||||
v8::Handle<v8::Object> obj); |
|
||||
|
|
||||
// Release memory we allocated for the DateFormat once the JS object that
|
|
||||
// holds the pointer gets garbage collected.
|
|
||||
static void DeleteDateTimeFormat(v8::Persistent<v8::Value> object, |
|
||||
void* param); |
|
||||
|
|
||||
// Formats date and returns corresponding string.
|
|
||||
static v8::Handle<v8::Value> Format(const v8::Arguments& args); |
|
||||
|
|
||||
// All date time symbol methods below return stand-alone names in
|
|
||||
// either narrow, abbreviated or wide width.
|
|
||||
|
|
||||
// Get list of months.
|
|
||||
static v8::Handle<v8::Value> GetMonths(const v8::Arguments& args); |
|
||||
|
|
||||
// Get list of weekdays.
|
|
||||
static v8::Handle<v8::Value> GetWeekdays(const v8::Arguments& args); |
|
||||
|
|
||||
// Get list of eras.
|
|
||||
static v8::Handle<v8::Value> GetEras(const v8::Arguments& args); |
|
||||
|
|
||||
// Get list of day periods.
|
|
||||
static v8::Handle<v8::Value> GetAmPm(const v8::Arguments& args); |
|
||||
|
|
||||
private: |
|
||||
DateTimeFormat(); |
|
||||
|
|
||||
static v8::Persistent<v8::FunctionTemplate> datetime_format_template_; |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_
|
|
@ -1,105 +0,0 @@ |
|||||
# Copyright 2011 the V8 project authors. All rights reserved. |
|
||||
# Redistribution and use in source and binary forms, with or without |
|
||||
# modification, are permitted provided that the following conditions are |
|
||||
# met: |
|
||||
# |
|
||||
# * Redistributions of source code must retain the above copyright |
|
||||
# notice, this list of conditions and the following disclaimer. |
|
||||
# * Redistributions in binary form must reproduce the above |
|
||||
# copyright notice, this list of conditions and the following |
|
||||
# disclaimer in the documentation and/or other materials provided |
|
||||
# with the distribution. |
|
||||
# * Neither the name of Google Inc. nor the names of its |
|
||||
# contributors may be used to endorse or promote products derived |
|
||||
# from this software without specific prior written permission. |
|
||||
# |
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
|
|
||||
{ |
|
||||
'variables': { |
|
||||
# TODO(cira): Find out how to pass this value for arbitrary embedder. |
|
||||
# Chromium sets it in common.gypi and does force include of that file for |
|
||||
# all sub projects. |
|
||||
'icu_src_dir%': '../../../../third_party/icu', |
|
||||
}, |
|
||||
'targets': [ |
|
||||
{ |
|
||||
'target_name': 'i18n_api', |
|
||||
'type': 'static_library', |
|
||||
'sources': [ |
|
||||
'break-iterator.cc', |
|
||||
'break-iterator.h', |
|
||||
'collator.cc', |
|
||||
'collator.h', |
|
||||
'datetime-format.cc', |
|
||||
'datetime-format.h', |
|
||||
'i18n-extension.cc', |
|
||||
'i18n-extension.h', |
|
||||
'i18n-locale.cc', |
|
||||
'i18n-locale.h', |
|
||||
'i18n-natives.h', |
|
||||
'i18n-utils.cc', |
|
||||
'i18n-utils.h', |
|
||||
'language-matcher.cc', |
|
||||
'language-matcher.h', |
|
||||
'number-format.cc', |
|
||||
'number-format.h', |
|
||||
'<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc', |
|
||||
], |
|
||||
'include_dirs': [ |
|
||||
'<(icu_src_dir)/public/common', |
|
||||
# v8/ is root for all includes. |
|
||||
'../../..' |
|
||||
], |
|
||||
'dependencies': [ |
|
||||
'<(icu_src_dir)/icu.gyp:*', |
|
||||
'js2c_i18n#host', |
|
||||
'../../../tools/gyp/v8.gyp:v8', |
|
||||
], |
|
||||
'direct_dependent_settings': { |
|
||||
# Adds -Iv8 for embedders. |
|
||||
'include_dirs': [ |
|
||||
'../../..' |
|
||||
], |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
'target_name': 'js2c_i18n', |
|
||||
'type': 'none', |
|
||||
'toolsets': ['host'], |
|
||||
'variables': { |
|
||||
'js_files': [ |
|
||||
'i18n.js' |
|
||||
], |
|
||||
}, |
|
||||
'actions': [ |
|
||||
{ |
|
||||
'action_name': 'js2c_i18n', |
|
||||
'inputs': [ |
|
||||
'i18n-js2c.py', |
|
||||
'<@(js_files)', |
|
||||
], |
|
||||
'outputs': [ |
|
||||
'<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc', |
|
||||
], |
|
||||
'action': [ |
|
||||
'python', |
|
||||
'i18n-js2c.py', |
|
||||
'<@(_outputs)', |
|
||||
'<@(js_files)' |
|
||||
], |
|
||||
}, |
|
||||
], |
|
||||
}, |
|
||||
], # targets |
|
||||
} |
|
@ -1,74 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-extension.h" |
|
||||
|
|
||||
#include "src/extensions/experimental/break-iterator.h" |
|
||||
#include "src/extensions/experimental/collator.h" |
|
||||
#include "src/extensions/experimental/datetime-format.h" |
|
||||
#include "src/extensions/experimental/i18n-locale.h" |
|
||||
#include "src/extensions/experimental/i18n-natives.h" |
|
||||
#include "src/extensions/experimental/number-format.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
I18NExtension* I18NExtension::extension_ = NULL; |
|
||||
|
|
||||
I18NExtension::I18NExtension() |
|
||||
: v8::Extension("v8/i18n", I18Natives::GetScriptSource()) { |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::FunctionTemplate> I18NExtension::GetNativeFunction( |
|
||||
v8::Handle<v8::String> name) { |
|
||||
if (name->Equals(v8::String::New("NativeJSLocale"))) { |
|
||||
return v8::FunctionTemplate::New(I18NLocale::JSLocale); |
|
||||
} else if (name->Equals(v8::String::New("NativeJSBreakIterator"))) { |
|
||||
return v8::FunctionTemplate::New(BreakIterator::JSBreakIterator); |
|
||||
} else if (name->Equals(v8::String::New("NativeJSCollator"))) { |
|
||||
return v8::FunctionTemplate::New(Collator::JSCollator); |
|
||||
} else if (name->Equals(v8::String::New("NativeJSDateTimeFormat"))) { |
|
||||
return v8::FunctionTemplate::New(DateTimeFormat::JSDateTimeFormat); |
|
||||
} else if (name->Equals(v8::String::New("NativeJSNumberFormat"))) { |
|
||||
return v8::FunctionTemplate::New(NumberFormat::JSNumberFormat); |
|
||||
} |
|
||||
|
|
||||
return v8::Handle<v8::FunctionTemplate>(); |
|
||||
} |
|
||||
|
|
||||
I18NExtension* I18NExtension::get() { |
|
||||
if (!extension_) { |
|
||||
extension_ = new I18NExtension(); |
|
||||
} |
|
||||
return extension_; |
|
||||
} |
|
||||
|
|
||||
void I18NExtension::Register() { |
|
||||
static v8::DeclareExtension i18n_extension_declaration(I18NExtension::get()); |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,54 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
|
|
||||
class I18NExtension : public v8::Extension { |
|
||||
public: |
|
||||
I18NExtension(); |
|
||||
|
|
||||
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
|
||||
v8::Handle<v8::String> name); |
|
||||
|
|
||||
// V8 code prefers Register, while Chrome and WebKit use get kind of methods.
|
|
||||
static void Register(); |
|
||||
static I18NExtension* get(); |
|
||||
|
|
||||
private: |
|
||||
static I18NExtension* extension_; |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_
|
|
@ -1,126 +0,0 @@ |
|||||
#!/usr/bin/env python |
|
||||
# |
|
||||
# Copyright 2011 the V8 project authors. All rights reserved. |
|
||||
# Redistribution and use in source and binary forms, with or without |
|
||||
# modification, are permitted provided that the following conditions are |
|
||||
# met: |
|
||||
# |
|
||||
# * Redistributions of source code must retain the above copyright |
|
||||
# notice, this list of conditions and the following disclaimer. |
|
||||
# * Redistributions in binary form must reproduce the above |
|
||||
# copyright notice, this list of conditions and the following |
|
||||
# disclaimer in the documentation and/or other materials provided |
|
||||
# with the distribution. |
|
||||
# * Neither the name of Google Inc. nor the names of its |
|
||||
# contributors may be used to endorse or promote products derived |
|
||||
# from this software without specific prior written permission. |
|
||||
# |
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
|
|
||||
# This is a utility for converting I18N JavaScript source code into C-style |
|
||||
# char arrays. It is used for embedded JavaScript code in the V8 |
|
||||
# library. |
|
||||
# This is a pared down copy of v8/tools/js2c.py that avoids use of |
|
||||
# v8/src/natives.h and produces different cc template. |
|
||||
|
|
||||
import os, re, sys, string |
|
||||
|
|
||||
|
|
||||
def ToCArray(lines): |
|
||||
result = [] |
|
||||
for chr in lines: |
|
||||
value = ord(chr) |
|
||||
assert value < 128 |
|
||||
result.append(str(value)) |
|
||||
result.append("0") |
|
||||
return ", ".join(result) |
|
||||
|
|
||||
|
|
||||
def RemoveCommentsAndTrailingWhitespace(lines): |
|
||||
lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments |
|
||||
lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments. |
|
||||
lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace |
|
||||
return lines |
|
||||
|
|
||||
|
|
||||
def ReadFile(filename): |
|
||||
file = open(filename, "rt") |
|
||||
try: |
|
||||
lines = file.read() |
|
||||
finally: |
|
||||
file.close() |
|
||||
return lines |
|
||||
|
|
||||
|
|
||||
EVAL_PATTERN = re.compile(r'\beval\s*\('); |
|
||||
WITH_PATTERN = re.compile(r'\bwith\s*\('); |
|
||||
|
|
||||
|
|
||||
def Validate(lines, file): |
|
||||
lines = RemoveCommentsAndTrailingWhitespace(lines) |
|
||||
# Because of simplified context setup, eval and with is not |
|
||||
# allowed in the natives files. |
|
||||
eval_match = EVAL_PATTERN.search(lines) |
|
||||
if eval_match: |
|
||||
raise ("Eval disallowed in natives: %s" % file) |
|
||||
with_match = WITH_PATTERN.search(lines) |
|
||||
if with_match: |
|
||||
raise ("With statements disallowed in natives: %s" % file) |
|
||||
|
|
||||
|
|
||||
HEADER_TEMPLATE = """\ |
|
||||
// Copyright 2011 Google Inc. All Rights Reserved. |
|
||||
|
|
||||
// This file was generated from .js source files by gyp. If you |
|
||||
// want to make changes to this file you should either change the |
|
||||
// javascript source files or the i18n-js2c.py script. |
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-natives.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
// static |
|
||||
const char* I18Natives::GetScriptSource() { |
|
||||
// JavaScript source gets injected here. |
|
||||
static const char i18n_source[] = {%s}; |
|
||||
|
|
||||
return i18n_source; |
|
||||
} |
|
||||
|
|
||||
} // internal |
|
||||
} // v8 |
|
||||
""" |
|
||||
|
|
||||
|
|
||||
def JS2C(source, target): |
|
||||
filename = str(source) |
|
||||
|
|
||||
lines = ReadFile(filename) |
|
||||
Validate(lines, filename) |
|
||||
data = ToCArray(lines) |
|
||||
|
|
||||
# Emit result |
|
||||
output = open(target, "w") |
|
||||
output.write(HEADER_TEMPLATE % data) |
|
||||
output.close() |
|
||||
|
|
||||
|
|
||||
def main(): |
|
||||
target = sys.argv[1] |
|
||||
source = sys.argv[2] |
|
||||
JS2C(source, target) |
|
||||
|
|
||||
|
|
||||
if __name__ == "__main__": |
|
||||
main() |
|
@ -1,111 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-locale.h" |
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-utils.h" |
|
||||
#include "src/extensions/experimental/language-matcher.h" |
|
||||
#include "unicode/locid.h" |
|
||||
#include "unicode/uloc.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
const char* const I18NLocale::kLocaleID = "localeID"; |
|
||||
const char* const I18NLocale::kRegionID = "regionID"; |
|
||||
const char* const I18NLocale::kICULocaleID = "icuLocaleID"; |
|
||||
|
|
||||
v8::Handle<v8::Value> I18NLocale::JSLocale(const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
if (args.Length() != 1 || !args[0]->IsObject()) { |
|
||||
return v8::Undefined(); |
|
||||
} |
|
||||
|
|
||||
v8::Local<v8::Object> settings = args[0]->ToObject(); |
|
||||
|
|
||||
// Get best match for locale.
|
|
||||
v8::TryCatch try_catch; |
|
||||
v8::Handle<v8::Value> locale_id = settings->Get(v8::String::New(kLocaleID)); |
|
||||
if (try_catch.HasCaught()) { |
|
||||
return v8::Undefined(); |
|
||||
} |
|
||||
|
|
||||
LocaleIDMatch result; |
|
||||
if (locale_id->IsArray()) { |
|
||||
LanguageMatcher::GetBestMatchForPriorityList( |
|
||||
v8::Handle<v8::Array>::Cast(locale_id), &result); |
|
||||
} else if (locale_id->IsString()) { |
|
||||
LanguageMatcher::GetBestMatchForString(locale_id->ToString(), &result); |
|
||||
} else { |
|
||||
LanguageMatcher::GetBestMatchForString(v8::String::New(""), &result); |
|
||||
} |
|
||||
|
|
||||
// Get best match for region.
|
|
||||
char region_id[ULOC_COUNTRY_CAPACITY]; |
|
||||
I18NUtils::StrNCopy(region_id, ULOC_COUNTRY_CAPACITY, ""); |
|
||||
|
|
||||
v8::Handle<v8::Value> region = settings->Get(v8::String::New(kRegionID)); |
|
||||
if (try_catch.HasCaught()) { |
|
||||
return v8::Undefined(); |
|
||||
} |
|
||||
|
|
||||
if (!GetBestMatchForRegionID(result.icu_id, region, region_id)) { |
|
||||
// Set region id to empty string because region couldn't be inferred.
|
|
||||
I18NUtils::StrNCopy(region_id, ULOC_COUNTRY_CAPACITY, ""); |
|
||||
} |
|
||||
|
|
||||
// Build JavaScript object that contains bcp and icu locale ID and region ID.
|
|
||||
v8::Handle<v8::Object> locale = v8::Object::New(); |
|
||||
locale->Set(v8::String::New(kLocaleID), v8::String::New(result.bcp47_id)); |
|
||||
locale->Set(v8::String::New(kICULocaleID), v8::String::New(result.icu_id)); |
|
||||
locale->Set(v8::String::New(kRegionID), v8::String::New(region_id)); |
|
||||
|
|
||||
return handle_scope.Close(locale); |
|
||||
} |
|
||||
|
|
||||
bool I18NLocale::GetBestMatchForRegionID( |
|
||||
const char* locale_id, v8::Handle<v8::Value> region_id, char* result) { |
|
||||
if (region_id->IsString() && region_id->ToString()->Length() != 0) { |
|
||||
icu::Locale user_locale( |
|
||||
icu::Locale("und", *v8::String::Utf8Value(region_id->ToString()))); |
|
||||
I18NUtils::StrNCopy( |
|
||||
result, ULOC_COUNTRY_CAPACITY, user_locale.getCountry()); |
|
||||
return true; |
|
||||
} |
|
||||
// Maximize locale_id to infer the region (e.g. expand "de" to "de-Latn-DE"
|
|
||||
// and grab "DE" from the result).
|
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
char maximized_locale[ULOC_FULLNAME_CAPACITY]; |
|
||||
uloc_addLikelySubtags( |
|
||||
locale_id, maximized_locale, ULOC_FULLNAME_CAPACITY, &status); |
|
||||
uloc_getCountry(maximized_locale, result, ULOC_COUNTRY_CAPACITY, &status); |
|
||||
|
|
||||
return !U_FAILURE(status); |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,60 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
class I18NLocale { |
|
||||
public: |
|
||||
I18NLocale() {} |
|
||||
|
|
||||
// Implementations of window.Locale methods.
|
|
||||
static v8::Handle<v8::Value> JSLocale(const v8::Arguments& args); |
|
||||
|
|
||||
// Infers region id given the locale id, or uses user specified region id.
|
|
||||
// Result is canonicalized.
|
|
||||
// Returns status of ICU operation (maximizing locale or get region call).
|
|
||||
static bool GetBestMatchForRegionID( |
|
||||
const char* locale_id, v8::Handle<v8::Value> regions, char* result); |
|
||||
|
|
||||
private: |
|
||||
// Key name for localeID parameter.
|
|
||||
static const char* const kLocaleID; |
|
||||
// Key name for regionID parameter.
|
|
||||
static const char* const kRegionID; |
|
||||
// Key name for the icuLocaleID result.
|
|
||||
static const char* const kICULocaleID; |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_
|
|
@ -1,87 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-utils.h" |
|
||||
|
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "unicode/unistr.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
// static
|
|
||||
void I18NUtils::StrNCopy(char* dest, int length, const char* src) { |
|
||||
if (!dest || !src) return; |
|
||||
|
|
||||
strncpy(dest, src, length); |
|
||||
dest[length - 1] = '\0'; |
|
||||
} |
|
||||
|
|
||||
// static
|
|
||||
bool I18NUtils::ExtractStringSetting(const v8::Handle<v8::Object>& settings, |
|
||||
const char* setting, |
|
||||
icu::UnicodeString* result) { |
|
||||
if (!setting || !result) return false; |
|
||||
|
|
||||
v8::HandleScope handle_scope; |
|
||||
v8::TryCatch try_catch; |
|
||||
v8::Handle<v8::Value> value = settings->Get(v8::String::New(setting)); |
|
||||
if (try_catch.HasCaught()) { |
|
||||
return false; |
|
||||
} |
|
||||
// No need to check if |value| is empty because it's taken care of
|
|
||||
// by TryCatch above.
|
|
||||
if (!value->IsUndefined() && !value->IsNull() && value->IsString()) { |
|
||||
v8::String::Utf8Value utf8_value(value); |
|
||||
if (*utf8_value == NULL) return false; |
|
||||
result->setTo(icu::UnicodeString::fromUTF8(*utf8_value)); |
|
||||
return true; |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// static
|
|
||||
void I18NUtils::AsciiToUChar(const char* source, |
|
||||
int32_t source_length, |
|
||||
UChar* target, |
|
||||
int32_t target_length) { |
|
||||
int32_t length = |
|
||||
source_length < target_length ? source_length : target_length; |
|
||||
|
|
||||
if (length <= 0) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
for (int32_t i = 0; i < length - 1; ++i) { |
|
||||
target[i] = static_cast<UChar>(source[i]); |
|
||||
} |
|
||||
|
|
||||
target[length - 1] = 0x0u; |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,69 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
#include "unicode/uversion.h" |
|
||||
|
|
||||
namespace U_ICU_NAMESPACE { |
|
||||
class UnicodeString; |
|
||||
} |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
class I18NUtils { |
|
||||
public: |
|
||||
// Safe string copy. Null terminates the destination. Copies at most
|
|
||||
// (length - 1) bytes.
|
|
||||
// We can't use snprintf since it's not supported on all relevant platforms.
|
|
||||
// We can't use OS::SNPrintF, it's only for internal code.
|
|
||||
static void StrNCopy(char* dest, int length, const char* src); |
|
||||
|
|
||||
// Extract a string setting named in |settings| and set it to |result|.
|
|
||||
// Return true if it's specified. Otherwise, return false.
|
|
||||
static bool ExtractStringSetting(const v8::Handle<v8::Object>& settings, |
|
||||
const char* setting, |
|
||||
icu::UnicodeString* result); |
|
||||
|
|
||||
// Converts ASCII array into UChar array.
|
|
||||
// Target is always \0 terminated.
|
|
||||
static void AsciiToUChar(const char* source, |
|
||||
int32_t source_length, |
|
||||
UChar* target, |
|
||||
int32_t target_length); |
|
||||
|
|
||||
private: |
|
||||
I18NUtils() {} |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_
|
|
@ -1,380 +0,0 @@ |
|||||
// Copyright 2006-2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
// TODO(cira): Rename v8Locale into LocaleInfo once we have stable API.
|
|
||||
/** |
|
||||
* LocaleInfo class is an aggregate class of all i18n API calls. |
|
||||
* @param {Object} settings - localeID and regionID to create LocaleInfo from. |
|
||||
* {Array.<string>|string} settings.localeID - |
|
||||
* Unicode identifier of the locale. |
|
||||
* See http://unicode.org/reports/tr35/#BCP_47_Conformance
|
|
||||
* {string} settings.regionID - ISO3166 region ID with addition of |
|
||||
* invalid, undefined and reserved region codes. |
|
||||
* @constructor |
|
||||
*/ |
|
||||
v8Locale = function(settings) { |
|
||||
native function NativeJSLocale(); |
|
||||
|
|
||||
// Assume user wanted to do v8Locale("sr");
|
|
||||
if (typeof(settings) === "string") { |
|
||||
settings = {'localeID': settings}; |
|
||||
} |
|
||||
|
|
||||
var properties = NativeJSLocale( |
|
||||
v8Locale.__createSettingsOrDefault(settings, {'localeID': 'root'})); |
|
||||
|
|
||||
// Keep the resolved ICU locale ID around to avoid resolving localeID to
|
|
||||
// ICU locale ID every time BreakIterator, Collator and so forth are called.
|
|
||||
this.__icuLocaleID = properties.icuLocaleID; |
|
||||
this.options = {'localeID': properties.localeID, |
|
||||
'regionID': properties.regionID}; |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Clones existing locale with possible overrides for some of the options. |
|
||||
* @param {!Object} settings - overrides for current locale settings. |
|
||||
* @returns {Object} - new LocaleInfo object. |
|
||||
*/ |
|
||||
v8Locale.prototype.derive = function(settings) { |
|
||||
return new v8Locale( |
|
||||
v8Locale.__createSettingsOrDefault(settings, this.options)); |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* v8BreakIterator class implements locale aware segmenatation. |
|
||||
* It is not part of EcmaScript proposal. |
|
||||
* @param {Object} locale - locale object to pass to break |
|
||||
* iterator implementation. |
|
||||
* @param {string} type - type of segmenatation: |
|
||||
* - character |
|
||||
* - word |
|
||||
* - sentence |
|
||||
* - line |
|
||||
* @private |
|
||||
* @constructor |
|
||||
*/ |
|
||||
v8Locale.v8BreakIterator = function(locale, type) { |
|
||||
native function NativeJSBreakIterator(); |
|
||||
|
|
||||
locale = v8Locale.__createLocaleOrDefault(locale); |
|
||||
// BCP47 ID would work in this case, but we use ICU locale for consistency.
|
|
||||
var iterator = NativeJSBreakIterator(locale.__icuLocaleID, type); |
|
||||
iterator.type = type; |
|
||||
return iterator; |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Type of the break we encountered during previous iteration. |
|
||||
* @type{Enum} |
|
||||
*/ |
|
||||
v8Locale.v8BreakIterator.BreakType = { |
|
||||
'unknown': -1, |
|
||||
'none': 0, |
|
||||
'number': 100, |
|
||||
'word': 200, |
|
||||
'kana': 300, |
|
||||
'ideo': 400 |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Creates new v8BreakIterator based on current locale. |
|
||||
* @param {string} - type of segmentation. See constructor. |
|
||||
* @returns {Object} - new v8BreakIterator object. |
|
||||
*/ |
|
||||
v8Locale.prototype.v8CreateBreakIterator = function(type) { |
|
||||
return new v8Locale.v8BreakIterator(this, type); |
|
||||
}; |
|
||||
|
|
||||
// TODO(jungshik): Set |collator.options| to actually recognized / resolved
|
|
||||
// values.
|
|
||||
/** |
|
||||
* Collator class implements locale-aware sort. |
|
||||
* @param {Object} locale - locale object to pass to collator implementation. |
|
||||
* @param {Object} settings - collation flags: |
|
||||
* - ignoreCase |
|
||||
* - ignoreAccents |
|
||||
* - numeric |
|
||||
* @private |
|
||||
* @constructor |
|
||||
*/ |
|
||||
v8Locale.Collator = function(locale, settings) { |
|
||||
native function NativeJSCollator(); |
|
||||
|
|
||||
locale = v8Locale.__createLocaleOrDefault(locale); |
|
||||
var collator = NativeJSCollator( |
|
||||
locale.__icuLocaleID, v8Locale.__createSettingsOrDefault(settings, {})); |
|
||||
return collator; |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Creates new Collator based on current locale. |
|
||||
* @param {Object} - collation flags. See constructor. |
|
||||
* @returns {Object} - new Collator object. |
|
||||
*/ |
|
||||
v8Locale.prototype.createCollator = function(settings) { |
|
||||
return new v8Locale.Collator(this, settings); |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* DateTimeFormat class implements locale-aware date and time formatting. |
|
||||
* Constructor is not part of public API. |
|
||||
* @param {Object} locale - locale object to pass to formatter. |
|
||||
* @param {Object} settings - formatting flags: |
|
||||
* - skeleton |
|
||||
* - dateStyle |
|
||||
* - timeStyle |
|
||||
* @private |
|
||||
* @constructor |
|
||||
*/ |
|
||||
v8Locale.__DateTimeFormat = function(locale, settings) { |
|
||||
native function NativeJSDateTimeFormat(); |
|
||||
|
|
||||
settings = v8Locale.__createSettingsOrDefault(settings, {}); |
|
||||
|
|
||||
var cleanSettings = {}; |
|
||||
if (settings.hasOwnProperty('skeleton')) { |
|
||||
cleanSettings['skeleton'] = settings['skeleton']; |
|
||||
} else { |
|
||||
cleanSettings = {}; |
|
||||
if (settings.hasOwnProperty('dateStyle')) { |
|
||||
var ds = settings['dateStyle']; |
|
||||
if (!/^(short|medium|long|full)$/.test(ds)) ds = 'short'; |
|
||||
cleanSettings['dateStyle'] = ds; |
|
||||
} else if (settings.hasOwnProperty('dateType')) { |
|
||||
// Obsolete. New spec requires dateStyle, but we'll keep this around
|
|
||||
// for current users.
|
|
||||
// TODO(cira): Remove when all internal users switch to dateStyle.
|
|
||||
var dt = settings['dateType']; |
|
||||
if (!/^(short|medium|long|full)$/.test(dt)) dt = 'short'; |
|
||||
cleanSettings['dateStyle'] = dt; |
|
||||
} |
|
||||
|
|
||||
if (settings.hasOwnProperty('timeStyle')) { |
|
||||
var ts = settings['timeStyle']; |
|
||||
if (!/^(short|medium|long|full)$/.test(ts)) ts = 'short'; |
|
||||
cleanSettings['timeStyle'] = ts; |
|
||||
} else if (settings.hasOwnProperty('timeType')) { |
|
||||
// TODO(cira): Remove when all internal users switch to timeStyle.
|
|
||||
var tt = settings['timeType']; |
|
||||
if (!/^(short|medium|long|full)$/.test(tt)) tt = 'short'; |
|
||||
cleanSettings['timeStyle'] = tt; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Default is to show short date and time.
|
|
||||
if (!cleanSettings.hasOwnProperty('skeleton') && |
|
||||
!cleanSettings.hasOwnProperty('dateStyle') && |
|
||||
!cleanSettings.hasOwnProperty('timeStyle')) { |
|
||||
cleanSettings = {'dateStyle': 'short', |
|
||||
'timeStyle': 'short'}; |
|
||||
} |
|
||||
|
|
||||
locale = v8Locale.__createLocaleOrDefault(locale); |
|
||||
var formatter = NativeJSDateTimeFormat(locale.__icuLocaleID, cleanSettings); |
|
||||
|
|
||||
// NativeJSDateTimeFormat creates formatter.options for us, we just need
|
|
||||
// to append actual settings to it.
|
|
||||
for (key in cleanSettings) { |
|
||||
formatter.options[key] = cleanSettings[key]; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Clones existing date time format with possible overrides for some |
|
||||
* of the options. |
|
||||
* @param {!Object} overrideSettings - overrides for current format settings. |
|
||||
* @returns {Object} - new DateTimeFormat object. |
|
||||
* @public |
|
||||
*/ |
|
||||
formatter.derive = function(overrideSettings) { |
|
||||
// To remove a setting user can specify undefined as its value. We'll remove
|
|
||||
// it from the map in that case.
|
|
||||
for (var prop in overrideSettings) { |
|
||||
if (settings.hasOwnProperty(prop) && !overrideSettings[prop]) { |
|
||||
delete settings[prop]; |
|
||||
} |
|
||||
} |
|
||||
return new v8Locale.__DateTimeFormat( |
|
||||
locale, v8Locale.__createSettingsOrDefault(overrideSettings, settings)); |
|
||||
}; |
|
||||
|
|
||||
return formatter; |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Creates new DateTimeFormat based on current locale. |
|
||||
* @param {Object} - formatting flags. See constructor. |
|
||||
* @returns {Object} - new DateTimeFormat object. |
|
||||
*/ |
|
||||
v8Locale.prototype.createDateTimeFormat = function(settings) { |
|
||||
return new v8Locale.__DateTimeFormat(this, settings); |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* NumberFormat class implements locale-aware number formatting. |
|
||||
* Constructor is not part of public API. |
|
||||
* @param {Object} locale - locale object to pass to formatter. |
|
||||
* @param {Object} settings - formatting flags: |
|
||||
* - skeleton |
|
||||
* - pattern |
|
||||
* - style - decimal, currency, percent or scientific |
|
||||
* - currencyCode - ISO 4217 3-letter currency code |
|
||||
* @private |
|
||||
* @constructor |
|
||||
*/ |
|
||||
v8Locale.__NumberFormat = function(locale, settings) { |
|
||||
native function NativeJSNumberFormat(); |
|
||||
|
|
||||
settings = v8Locale.__createSettingsOrDefault(settings, {}); |
|
||||
|
|
||||
var cleanSettings = {}; |
|
||||
if (settings.hasOwnProperty('skeleton')) { |
|
||||
// Assign skeleton to cleanSettings and fix invalid currency pattern
|
|
||||
// if present - 'ooxo' becomes 'o'.
|
|
||||
cleanSettings['skeleton'] = |
|
||||
settings['skeleton'].replace(/\u00a4+[^\u00a4]+\u00a4+/g, '\u00a4'); |
|
||||
} else if (settings.hasOwnProperty('pattern')) { |
|
||||
cleanSettings['pattern'] = settings['pattern']; |
|
||||
} else if (settings.hasOwnProperty('style')) { |
|
||||
var style = settings['style']; |
|
||||
if (!/^(decimal|currency|percent|scientific)$/.test(style)) { |
|
||||
style = 'decimal'; |
|
||||
} |
|
||||
cleanSettings['style'] = style; |
|
||||
} |
|
||||
|
|
||||
// Default is to show decimal style.
|
|
||||
if (!cleanSettings.hasOwnProperty('skeleton') && |
|
||||
!cleanSettings.hasOwnProperty('pattern') && |
|
||||
!cleanSettings.hasOwnProperty('style')) { |
|
||||
cleanSettings = {'style': 'decimal'}; |
|
||||
} |
|
||||
|
|
||||
// Add currency code if available and valid (3-letter ASCII code).
|
|
||||
if (settings.hasOwnProperty('currencyCode') && |
|
||||
/^[a-zA-Z]{3}$/.test(settings['currencyCode'])) { |
|
||||
cleanSettings['currencyCode'] = settings['currencyCode'].toUpperCase(); |
|
||||
} |
|
||||
|
|
||||
locale = v8Locale.__createLocaleOrDefault(locale); |
|
||||
// Pass in region ID for proper currency detection. Use ZZ if region is empty.
|
|
||||
var region = locale.options.regionID !== '' ? locale.options.regionID : 'ZZ'; |
|
||||
var formatter = NativeJSNumberFormat( |
|
||||
locale.__icuLocaleID, 'und_' + region, cleanSettings); |
|
||||
|
|
||||
// ICU doesn't always uppercase the currency code.
|
|
||||
if (formatter.options.hasOwnProperty('currencyCode')) { |
|
||||
formatter.options['currencyCode'] = |
|
||||
formatter.options['currencyCode'].toUpperCase(); |
|
||||
} |
|
||||
|
|
||||
for (key in cleanSettings) { |
|
||||
// Don't overwrite keys that are alredy in.
|
|
||||
if (formatter.options.hasOwnProperty(key)) continue; |
|
||||
|
|
||||
formatter.options[key] = cleanSettings[key]; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Clones existing number format with possible overrides for some |
|
||||
* of the options. |
|
||||
* @param {!Object} overrideSettings - overrides for current format settings. |
|
||||
* @returns {Object} - new or cached NumberFormat object. |
|
||||
* @public |
|
||||
*/ |
|
||||
formatter.derive = function(overrideSettings) { |
|
||||
// To remove a setting user can specify undefined as its value. We'll remove
|
|
||||
// it from the map in that case.
|
|
||||
for (var prop in overrideSettings) { |
|
||||
if (settings.hasOwnProperty(prop) && !overrideSettings[prop]) { |
|
||||
delete settings[prop]; |
|
||||
} |
|
||||
} |
|
||||
return new v8Locale.__NumberFormat( |
|
||||
locale, v8Locale.__createSettingsOrDefault(overrideSettings, settings)); |
|
||||
}; |
|
||||
|
|
||||
return formatter; |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Creates new NumberFormat based on current locale. |
|
||||
* @param {Object} - formatting flags. See constructor. |
|
||||
* @returns {Object} - new or cached NumberFormat object. |
|
||||
*/ |
|
||||
v8Locale.prototype.createNumberFormat = function(settings) { |
|
||||
return new v8Locale.__NumberFormat(this, settings); |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* Merges user settings and defaults. |
|
||||
* Settings that are not of object type are rejected. |
|
||||
* Actual property values are not validated, but whitespace is trimmed if they |
|
||||
* are strings. |
|
||||
* @param {!Object} settings - user provided settings. |
|
||||
* @param {!Object} defaults - default values for this type of settings. |
|
||||
* @returns {Object} - valid settings object. |
|
||||
* @private |
|
||||
*/ |
|
||||
v8Locale.__createSettingsOrDefault = function(settings, defaults) { |
|
||||
if (!settings || typeof(settings) !== 'object' ) { |
|
||||
return defaults; |
|
||||
} |
|
||||
for (var key in defaults) { |
|
||||
if (!settings.hasOwnProperty(key)) { |
|
||||
settings[key] = defaults[key]; |
|
||||
} |
|
||||
} |
|
||||
// Clean up settings.
|
|
||||
for (var key in settings) { |
|
||||
// Trim whitespace.
|
|
||||
if (typeof(settings[key]) === "string") { |
|
||||
settings[key] = settings[key].trim(); |
|
||||
} |
|
||||
// Remove all properties that are set to undefined/null. This allows
|
|
||||
// derive method to remove a setting we don't need anymore.
|
|
||||
if (!settings[key]) { |
|
||||
delete settings[key]; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return settings; |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* If locale is valid (defined and of v8Locale type) we return it. If not |
|
||||
* we create default locale and return it. |
|
||||
* @param {!Object} locale - user provided locale. |
|
||||
* @returns {Object} - v8Locale object. |
|
||||
* @private |
|
||||
*/ |
|
||||
v8Locale.__createLocaleOrDefault = function(locale) { |
|
||||
if (!locale || !(locale instanceof v8Locale)) { |
|
||||
return new v8Locale(); |
|
||||
} else { |
|
||||
return locale; |
|
||||
} |
|
||||
}; |
|
@ -1,252 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
// TODO(cira): Remove LanguageMatcher from v8 when ICU implements
|
|
||||
// language matching API.
|
|
||||
|
|
||||
#include "src/extensions/experimental/language-matcher.h" |
|
||||
|
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-utils.h" |
|
||||
#include "unicode/datefmt.h" // For getAvailableLocales |
|
||||
#include "unicode/locid.h" |
|
||||
#include "unicode/uloc.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
const unsigned int LanguageMatcher::kLanguageWeight = 75; |
|
||||
const unsigned int LanguageMatcher::kScriptWeight = 20; |
|
||||
const unsigned int LanguageMatcher::kRegionWeight = 5; |
|
||||
const unsigned int LanguageMatcher::kThreshold = 50; |
|
||||
const unsigned int LanguageMatcher::kPositionBonus = 1; |
|
||||
const char* const LanguageMatcher::kDefaultLocale = "root"; |
|
||||
|
|
||||
static const char* GetLanguageException(const char*); |
|
||||
static bool BCP47ToICUFormat(const char*, char*); |
|
||||
static int CompareLocaleSubtags(const char*, const char*); |
|
||||
static bool BuildLocaleName(const char*, const char*, LocaleIDMatch*); |
|
||||
|
|
||||
LocaleIDMatch::LocaleIDMatch() |
|
||||
: score(-1) { |
|
||||
I18NUtils::StrNCopy( |
|
||||
bcp47_id, ULOC_FULLNAME_CAPACITY, LanguageMatcher::kDefaultLocale); |
|
||||
|
|
||||
I18NUtils::StrNCopy( |
|
||||
icu_id, ULOC_FULLNAME_CAPACITY, LanguageMatcher::kDefaultLocale); |
|
||||
} |
|
||||
|
|
||||
LocaleIDMatch& LocaleIDMatch::operator=(const LocaleIDMatch& rhs) { |
|
||||
I18NUtils::StrNCopy(this->bcp47_id, ULOC_FULLNAME_CAPACITY, rhs.bcp47_id); |
|
||||
I18NUtils::StrNCopy(this->icu_id, ULOC_FULLNAME_CAPACITY, rhs.icu_id); |
|
||||
this->score = rhs.score; |
|
||||
|
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
// static
|
|
||||
void LanguageMatcher::GetBestMatchForPriorityList( |
|
||||
v8::Handle<v8::Array> locales, LocaleIDMatch* result) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
unsigned int position_bonus = locales->Length() * kPositionBonus; |
|
||||
|
|
||||
int max_score = 0; |
|
||||
LocaleIDMatch match; |
|
||||
for (unsigned int i = 0; i < locales->Length(); ++i) { |
|
||||
position_bonus -= kPositionBonus; |
|
||||
|
|
||||
v8::TryCatch try_catch; |
|
||||
v8::Local<v8::Value> locale_id = locales->Get(v8::Integer::New(i)); |
|
||||
|
|
||||
// Return default if exception is raised when reading parameter.
|
|
||||
if (try_catch.HasCaught()) break; |
|
||||
|
|
||||
// JavaScript arrays can be heterogenous so check each item
|
|
||||
// if it's a string.
|
|
||||
if (!locale_id->IsString()) continue; |
|
||||
|
|
||||
if (!CompareToSupportedLocaleIDList(locale_id->ToString(), &match)) { |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
// Skip items under threshold.
|
|
||||
if (match.score < kThreshold) continue; |
|
||||
|
|
||||
match.score += position_bonus; |
|
||||
if (match.score > max_score) { |
|
||||
*result = match; |
|
||||
|
|
||||
max_score = match.score; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// static
|
|
||||
void LanguageMatcher::GetBestMatchForString( |
|
||||
v8::Handle<v8::String> locale, LocaleIDMatch* result) { |
|
||||
LocaleIDMatch match; |
|
||||
|
|
||||
if (CompareToSupportedLocaleIDList(locale, &match) && |
|
||||
match.score >= kThreshold) { |
|
||||
*result = match; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// static
|
|
||||
bool LanguageMatcher::CompareToSupportedLocaleIDList( |
|
||||
v8::Handle<v8::String> locale_id, LocaleIDMatch* result) { |
|
||||
static int32_t available_count = 0; |
|
||||
// Depending on how ICU data is built, locales returned by
|
|
||||
// Locale::getAvailableLocale() are not guaranteed to support DateFormat,
|
|
||||
// Collation and other services. We can call getAvailableLocale() of all the
|
|
||||
// services we want to support and take the intersection of them all, but
|
|
||||
// using DateFormat::getAvailableLocales() should suffice.
|
|
||||
// TODO(cira): Maybe make this thread-safe?
|
|
||||
static const icu::Locale* available_locales = |
|
||||
icu::DateFormat::getAvailableLocales(available_count); |
|
||||
|
|
||||
// Skip this locale_id if it's not in ASCII.
|
|
||||
static LocaleIDMatch default_match; |
|
||||
v8::String::AsciiValue ascii_value(locale_id); |
|
||||
if (*ascii_value == NULL) return false; |
|
||||
|
|
||||
char locale[ULOC_FULLNAME_CAPACITY]; |
|
||||
if (!BCP47ToICUFormat(*ascii_value, locale)) return false; |
|
||||
|
|
||||
icu::Locale input_locale(locale); |
|
||||
|
|
||||
// Position of the best match locale in list of available locales.
|
|
||||
int position = -1; |
|
||||
const char* language = GetLanguageException(input_locale.getLanguage()); |
|
||||
const char* script = input_locale.getScript(); |
|
||||
const char* region = input_locale.getCountry(); |
|
||||
for (int32_t i = 0; i < available_count; ++i) { |
|
||||
int current_score = 0; |
|
||||
int sign = |
|
||||
CompareLocaleSubtags(language, available_locales[i].getLanguage()); |
|
||||
current_score += sign * kLanguageWeight; |
|
||||
|
|
||||
sign = CompareLocaleSubtags(script, available_locales[i].getScript()); |
|
||||
current_score += sign * kScriptWeight; |
|
||||
|
|
||||
sign = CompareLocaleSubtags(region, available_locales[i].getCountry()); |
|
||||
current_score += sign * kRegionWeight; |
|
||||
|
|
||||
if (current_score >= kThreshold && current_score > result->score) { |
|
||||
result->score = current_score; |
|
||||
position = i; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Didn't find any good matches so use defaults.
|
|
||||
if (position == -1) return false; |
|
||||
|
|
||||
return BuildLocaleName(available_locales[position].getBaseName(), |
|
||||
input_locale.getName(), result); |
|
||||
} |
|
||||
|
|
||||
// For some unsupported language subtags it is better to fallback to related
|
|
||||
// language that is supported than to default.
|
|
||||
static const char* GetLanguageException(const char* language) { |
|
||||
// Serbo-croatian to Serbian.
|
|
||||
if (!strcmp(language, "sh")) return "sr"; |
|
||||
|
|
||||
// Norweigan to Norweiaan to Norwegian Bokmal.
|
|
||||
if (!strcmp(language, "no")) return "nb"; |
|
||||
|
|
||||
// Moldavian to Romanian.
|
|
||||
if (!strcmp(language, "mo")) return "ro"; |
|
||||
|
|
||||
// Tagalog to Filipino.
|
|
||||
if (!strcmp(language, "tl")) return "fil"; |
|
||||
|
|
||||
return language; |
|
||||
} |
|
||||
|
|
||||
// Converts user input from BCP47 locale id format to ICU compatible format.
|
|
||||
// Returns false if uloc_forLanguageTag call fails or if extension is too long.
|
|
||||
static bool BCP47ToICUFormat(const char* locale_id, char* result) { |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
int32_t locale_size = 0; |
|
||||
|
|
||||
char locale[ULOC_FULLNAME_CAPACITY]; |
|
||||
I18NUtils::StrNCopy(locale, ULOC_FULLNAME_CAPACITY, locale_id); |
|
||||
|
|
||||
// uloc_forLanguageTag has a bug where long extension can crash the code.
|
|
||||
// We need to check if extension part of language id conforms to the length.
|
|
||||
// ICU bug: http://bugs.icu-project.org/trac/ticket/8519
|
|
||||
const char* extension = strstr(locale_id, "-u-"); |
|
||||
if (extension != NULL && |
|
||||
strlen(extension) > ULOC_KEYWORD_AND_VALUES_CAPACITY) { |
|
||||
// Truncate to get non-crashing string, but still preserve base language.
|
|
||||
int base_length = strlen(locale_id) - strlen(extension); |
|
||||
locale[base_length] = '\0'; |
|
||||
} |
|
||||
|
|
||||
uloc_forLanguageTag(locale, result, ULOC_FULLNAME_CAPACITY, |
|
||||
&locale_size, &status); |
|
||||
return !U_FAILURE(status); |
|
||||
} |
|
||||
|
|
||||
// Compares locale id subtags.
|
|
||||
// Returns 1 for match or -1 for mismatch.
|
|
||||
static int CompareLocaleSubtags(const char* lsubtag, const char* rsubtag) { |
|
||||
return strcmp(lsubtag, rsubtag) == 0 ? 1 : -1; |
|
||||
} |
|
||||
|
|
||||
// Builds a BCP47 compliant locale id from base name of matched locale and
|
|
||||
// full user specified locale.
|
|
||||
// Returns false if uloc_toLanguageTag failed to convert locale id.
|
|
||||
// Example:
|
|
||||
// base_name of matched locale (ICU ID): de_DE
|
|
||||
// input_locale_name (ICU ID): de_AT@collation=phonebk
|
|
||||
// result (ICU ID): de_DE@collation=phonebk
|
|
||||
// result (BCP47 ID): de-DE-u-co-phonebk
|
|
||||
static bool BuildLocaleName(const char* base_name, |
|
||||
const char* input_locale_name, |
|
||||
LocaleIDMatch* result) { |
|
||||
I18NUtils::StrNCopy(result->icu_id, ULOC_LANG_CAPACITY, base_name); |
|
||||
|
|
||||
// Get extensions (if any) from the original locale.
|
|
||||
const char* extension = strchr(input_locale_name, ULOC_KEYWORD_SEPARATOR); |
|
||||
if (extension != NULL) { |
|
||||
I18NUtils::StrNCopy(result->icu_id + strlen(base_name), |
|
||||
ULOC_KEYWORD_AND_VALUES_CAPACITY, extension); |
|
||||
} else { |
|
||||
I18NUtils::StrNCopy(result->icu_id, ULOC_LANG_CAPACITY, base_name); |
|
||||
} |
|
||||
|
|
||||
// Convert ICU locale name into BCP47 format.
|
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
uloc_toLanguageTag(result->icu_id, result->bcp47_id, |
|
||||
ULOC_FULLNAME_CAPACITY, false, &status); |
|
||||
return !U_FAILURE(status); |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,95 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
#include "unicode/uloc.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
struct LocaleIDMatch { |
|
||||
LocaleIDMatch(); |
|
||||
|
|
||||
LocaleIDMatch& operator=(const LocaleIDMatch& rhs); |
|
||||
|
|
||||
// Bcp47 locale id - "de-Latn-DE-u-co-phonebk".
|
|
||||
char bcp47_id[ULOC_FULLNAME_CAPACITY]; |
|
||||
|
|
||||
// ICU locale id - "de_Latn_DE@collation=phonebk".
|
|
||||
char icu_id[ULOC_FULLNAME_CAPACITY]; |
|
||||
|
|
||||
// Score for this locale.
|
|
||||
int score; |
|
||||
}; |
|
||||
|
|
||||
class LanguageMatcher { |
|
||||
public: |
|
||||
// Default locale.
|
|
||||
static const char* const kDefaultLocale; |
|
||||
|
|
||||
// Finds best supported locale for a given a list of locale identifiers.
|
|
||||
// It preserves the extension for the locale id.
|
|
||||
static void GetBestMatchForPriorityList( |
|
||||
v8::Handle<v8::Array> locale_list, LocaleIDMatch* result); |
|
||||
|
|
||||
// Finds best supported locale for a single locale identifier.
|
|
||||
// It preserves the extension for the locale id.
|
|
||||
static void GetBestMatchForString( |
|
||||
v8::Handle<v8::String> locale_id, LocaleIDMatch* result); |
|
||||
|
|
||||
private: |
|
||||
// If langauge subtags match add this amount to the score.
|
|
||||
static const unsigned int kLanguageWeight; |
|
||||
|
|
||||
// If script subtags match add this amount to the score.
|
|
||||
static const unsigned int kScriptWeight; |
|
||||
|
|
||||
// If region subtags match add this amount to the score.
|
|
||||
static const unsigned int kRegionWeight; |
|
||||
|
|
||||
// LocaleID match score has to be over this number to accept the match.
|
|
||||
static const unsigned int kThreshold; |
|
||||
|
|
||||
// For breaking ties in priority queue.
|
|
||||
static const unsigned int kPositionBonus; |
|
||||
|
|
||||
LanguageMatcher(); |
|
||||
|
|
||||
// Compares locale_id to the supported list of locales and returns best
|
|
||||
// match.
|
|
||||
// Returns false if it fails to convert locale id from ICU to BCP47 format.
|
|
||||
static bool CompareToSupportedLocaleIDList(v8::Handle<v8::String> locale_id, |
|
||||
LocaleIDMatch* result); |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_
|
|
@ -1,374 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include "src/extensions/experimental/number-format.h" |
|
||||
|
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "src/extensions/experimental/i18n-utils.h" |
|
||||
#include "unicode/dcfmtsym.h" |
|
||||
#include "unicode/decimfmt.h" |
|
||||
#include "unicode/locid.h" |
|
||||
#include "unicode/numfmt.h" |
|
||||
#include "unicode/uchar.h" |
|
||||
#include "unicode/ucurr.h" |
|
||||
#include "unicode/unum.h" |
|
||||
#include "unicode/uversion.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
const int NumberFormat::kCurrencyCodeLength = 4; |
|
||||
|
|
||||
v8::Persistent<v8::FunctionTemplate> NumberFormat::number_format_template_; |
|
||||
|
|
||||
static icu::DecimalFormat* CreateNumberFormat(v8::Handle<v8::String>, |
|
||||
v8::Handle<v8::String>, |
|
||||
v8::Handle<v8::Object>); |
|
||||
static icu::DecimalFormat* CreateFormatterFromSkeleton( |
|
||||
const icu::Locale&, const icu::UnicodeString&, UErrorCode*); |
|
||||
static icu::DecimalFormatSymbols* GetFormatSymbols(const icu::Locale&); |
|
||||
static bool GetCurrencyCode(const icu::Locale&, |
|
||||
const char* const, |
|
||||
v8::Handle<v8::Object>, |
|
||||
UChar*); |
|
||||
static v8::Handle<v8::Value> ThrowUnexpectedObjectError(); |
|
||||
|
|
||||
icu::DecimalFormat* NumberFormat::UnpackNumberFormat( |
|
||||
v8::Handle<v8::Object> obj) { |
|
||||
if (number_format_template_->HasInstance(obj)) { |
|
||||
return static_cast<icu::DecimalFormat*>( |
|
||||
obj->GetPointerFromInternalField(0)); |
|
||||
} |
|
||||
|
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
void NumberFormat::DeleteNumberFormat(v8::Persistent<v8::Value> object, |
|
||||
void* param) { |
|
||||
v8::Persistent<v8::Object> persistent_object = |
|
||||
v8::Persistent<v8::Object>::Cast(object); |
|
||||
|
|
||||
// First delete the hidden C++ object.
|
|
||||
// Unpacking should never return NULL here. That would only happen if
|
|
||||
// this method is used as the weak callback for persistent handles not
|
|
||||
// pointing to a number formatter.
|
|
||||
delete UnpackNumberFormat(persistent_object); |
|
||||
|
|
||||
// Then dispose of the persistent handle to JS object.
|
|
||||
persistent_object.Dispose(); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> NumberFormat::Format(const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
if (args.Length() != 1 || !args[0]->IsNumber()) { |
|
||||
// Just return NaN on invalid input.
|
|
||||
return v8::String::New("NaN"); |
|
||||
} |
|
||||
|
|
||||
icu::DecimalFormat* number_format = UnpackNumberFormat(args.Holder()); |
|
||||
if (!number_format) { |
|
||||
return ThrowUnexpectedObjectError(); |
|
||||
} |
|
||||
|
|
||||
// ICU will handle actual NaN value properly and return NaN string.
|
|
||||
icu::UnicodeString result; |
|
||||
number_format->format(args[0]->NumberValue(), result); |
|
||||
|
|
||||
return v8::String::New( |
|
||||
reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length()); |
|
||||
} |
|
||||
|
|
||||
v8::Handle<v8::Value> NumberFormat::JSNumberFormat(const v8::Arguments& args) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
// Expect locale id, region id and settings.
|
|
||||
if (args.Length() != 3 || |
|
||||
!args[0]->IsString() || !args[1]->IsString() || !args[2]->IsObject()) { |
|
||||
return v8::ThrowException(v8::Exception::SyntaxError( |
|
||||
v8::String::New("Locale, region and number settings are required."))); |
|
||||
} |
|
||||
|
|
||||
icu::DecimalFormat* number_format = CreateNumberFormat( |
|
||||
args[0]->ToString(), args[1]->ToString(), args[2]->ToObject()); |
|
||||
|
|
||||
if (number_format_template_.IsEmpty()) { |
|
||||
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New()); |
|
||||
|
|
||||
raw_template->SetClassName(v8::String::New("v8Locale.NumberFormat")); |
|
||||
|
|
||||
// Define internal field count on instance template.
|
|
||||
v8::Local<v8::ObjectTemplate> object_template = |
|
||||
raw_template->InstanceTemplate(); |
|
||||
|
|
||||
// Set aside internal field for icu number formatter.
|
|
||||
object_template->SetInternalFieldCount(1); |
|
||||
|
|
||||
// Define all of the prototype methods on prototype template.
|
|
||||
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate(); |
|
||||
proto->Set(v8::String::New("format"), |
|
||||
v8::FunctionTemplate::New(Format)); |
|
||||
|
|
||||
number_format_template_ = |
|
||||
v8::Persistent<v8::FunctionTemplate>::New(raw_template); |
|
||||
} |
|
||||
|
|
||||
// Create an empty object wrapper.
|
|
||||
v8::Local<v8::Object> local_object = |
|
||||
number_format_template_->GetFunction()->NewInstance(); |
|
||||
v8::Persistent<v8::Object> wrapper = |
|
||||
v8::Persistent<v8::Object>::New(local_object); |
|
||||
|
|
||||
// Set number formatter as internal field of the resulting JS object.
|
|
||||
wrapper->SetPointerInInternalField(0, number_format); |
|
||||
|
|
||||
// Create options key.
|
|
||||
v8::Local<v8::Object> options = v8::Object::New(); |
|
||||
|
|
||||
// Show what ICU decided to use for easier problem tracking.
|
|
||||
// Keep it as v8 specific extension.
|
|
||||
icu::UnicodeString pattern; |
|
||||
number_format->toPattern(pattern); |
|
||||
options->Set(v8::String::New("v8ResolvedPattern"), |
|
||||
v8::String::New(reinterpret_cast<const uint16_t*>( |
|
||||
pattern.getBuffer()), pattern.length())); |
|
||||
|
|
||||
// Set resolved currency code in options.currency if not empty.
|
|
||||
icu::UnicodeString currency(number_format->getCurrency()); |
|
||||
if (!currency.isEmpty()) { |
|
||||
options->Set(v8::String::New("currencyCode"), |
|
||||
v8::String::New(reinterpret_cast<const uint16_t*>( |
|
||||
currency.getBuffer()), currency.length())); |
|
||||
} |
|
||||
|
|
||||
wrapper->Set(v8::String::New("options"), options); |
|
||||
|
|
||||
// Make object handle weak so we can delete iterator once GC kicks in.
|
|
||||
wrapper.MakeWeak(NULL, DeleteNumberFormat); |
|
||||
|
|
||||
return wrapper; |
|
||||
} |
|
||||
|
|
||||
// Returns DecimalFormat.
|
|
||||
static icu::DecimalFormat* CreateNumberFormat(v8::Handle<v8::String> locale, |
|
||||
v8::Handle<v8::String> region, |
|
||||
v8::Handle<v8::Object> settings) { |
|
||||
v8::HandleScope handle_scope; |
|
||||
|
|
||||
v8::String::AsciiValue ascii_locale(locale); |
|
||||
icu::Locale icu_locale(*ascii_locale); |
|
||||
|
|
||||
// Make formatter from skeleton.
|
|
||||
icu::DecimalFormat* number_format = NULL; |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
icu::UnicodeString setting; |
|
||||
|
|
||||
if (I18NUtils::ExtractStringSetting(settings, "skeleton", &setting)) { |
|
||||
// TODO(cira): Use ICU skeleton once
|
|
||||
// http://bugs.icu-project.org/trac/ticket/8610 is resolved.
|
|
||||
number_format = CreateFormatterFromSkeleton(icu_locale, setting, &status); |
|
||||
} else if (I18NUtils::ExtractStringSetting(settings, "pattern", &setting)) { |
|
||||
number_format = |
|
||||
new icu::DecimalFormat(setting, GetFormatSymbols(icu_locale), status); |
|
||||
} else if (I18NUtils::ExtractStringSetting(settings, "style", &setting)) { |
|
||||
if (setting == UNICODE_STRING_SIMPLE("currency")) { |
|
||||
number_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createCurrencyInstance(icu_locale, status)); |
|
||||
} else if (setting == UNICODE_STRING_SIMPLE("percent")) { |
|
||||
number_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createPercentInstance(icu_locale, status)); |
|
||||
} else if (setting == UNICODE_STRING_SIMPLE("scientific")) { |
|
||||
number_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createScientificInstance(icu_locale, status)); |
|
||||
} else { |
|
||||
// Make it decimal in any other case.
|
|
||||
number_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createInstance(icu_locale, status)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (U_FAILURE(status)) { |
|
||||
delete number_format; |
|
||||
status = U_ZERO_ERROR; |
|
||||
number_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createInstance(icu_locale, status)); |
|
||||
} |
|
||||
|
|
||||
// Attach appropriate currency code to the formatter.
|
|
||||
// It affects currency formatters only.
|
|
||||
// Region is full language identifier in form 'und_' + region id.
|
|
||||
v8::String::AsciiValue ascii_region(region); |
|
||||
|
|
||||
UChar currency_code[NumberFormat::kCurrencyCodeLength]; |
|
||||
if (GetCurrencyCode(icu_locale, *ascii_region, settings, currency_code)) { |
|
||||
number_format->setCurrency(currency_code, status); |
|
||||
} |
|
||||
|
|
||||
return number_format; |
|
||||
} |
|
||||
|
|
||||
// Generates ICU number format pattern from given skeleton.
|
|
||||
// TODO(cira): Remove once ICU includes equivalent method
|
|
||||
// (see http://bugs.icu-project.org/trac/ticket/8610).
|
|
||||
static icu::DecimalFormat* CreateFormatterFromSkeleton( |
|
||||
const icu::Locale& icu_locale, |
|
||||
const icu::UnicodeString& skeleton, |
|
||||
UErrorCode* status) { |
|
||||
icu::DecimalFormat skeleton_format( |
|
||||
skeleton, GetFormatSymbols(icu_locale), *status); |
|
||||
|
|
||||
// Find out if skeleton contains currency or percent symbol and create
|
|
||||
// proper instance to tweak.
|
|
||||
icu::DecimalFormat* base_format = NULL; |
|
||||
|
|
||||
// UChar representation of U+00A4 currency symbol.
|
|
||||
const UChar currency_symbol = 0xA4u; |
|
||||
|
|
||||
int32_t index = skeleton.indexOf(currency_symbol); |
|
||||
if (index != -1) { |
|
||||
// Find how many U+00A4 are there. There is at least one.
|
|
||||
// Case of non-consecutive U+00A4 is taken care of in i18n.js.
|
|
||||
int32_t end_index = skeleton.lastIndexOf(currency_symbol, index); |
|
||||
|
|
||||
#if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6) |
|
||||
icu::NumberFormat::EStyles style; |
|
||||
switch (end_index - index) { |
|
||||
case 0: |
|
||||
style = icu::NumberFormat::kCurrencyStyle; |
|
||||
break; |
|
||||
case 1: |
|
||||
style = icu::NumberFormat::kIsoCurrencyStyle; |
|
||||
break; |
|
||||
default: |
|
||||
style = icu::NumberFormat::kPluralCurrencyStyle; |
|
||||
} |
|
||||
#else // ICU version is 4.8 or above (we ignore versions below 4.0).
|
|
||||
UNumberFormatStyle style; |
|
||||
switch (end_index - index) { |
|
||||
case 0: |
|
||||
style = UNUM_CURRENCY; |
|
||||
break; |
|
||||
case 1: |
|
||||
style = UNUM_CURRENCY_ISO; |
|
||||
break; |
|
||||
default: |
|
||||
style = UNUM_CURRENCY_PLURAL; |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
base_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createInstance(icu_locale, style, *status)); |
|
||||
} else if (skeleton.indexOf('%') != -1) { |
|
||||
base_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createPercentInstance(icu_locale, *status)); |
|
||||
} else { |
|
||||
// TODO(cira): Handle scientific skeleton.
|
|
||||
base_format = static_cast<icu::DecimalFormat*>( |
|
||||
icu::NumberFormat::createInstance(icu_locale, *status)); |
|
||||
} |
|
||||
|
|
||||
if (U_FAILURE(*status)) { |
|
||||
delete base_format; |
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
// Copy important information from skeleton to the new formatter.
|
|
||||
// TODO(cira): copy rounding information from skeleton?
|
|
||||
base_format->setGroupingUsed(skeleton_format.isGroupingUsed()); |
|
||||
|
|
||||
base_format->setMinimumIntegerDigits( |
|
||||
skeleton_format.getMinimumIntegerDigits()); |
|
||||
|
|
||||
base_format->setMinimumFractionDigits( |
|
||||
skeleton_format.getMinimumFractionDigits()); |
|
||||
|
|
||||
base_format->setMaximumFractionDigits( |
|
||||
skeleton_format.getMaximumFractionDigits()); |
|
||||
|
|
||||
return base_format; |
|
||||
} |
|
||||
|
|
||||
// Gets decimal symbols for a locale.
|
|
||||
static icu::DecimalFormatSymbols* GetFormatSymbols( |
|
||||
const icu::Locale& icu_locale) { |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
icu::DecimalFormatSymbols* symbols = |
|
||||
new icu::DecimalFormatSymbols(icu_locale, status); |
|
||||
|
|
||||
if (U_FAILURE(status)) { |
|
||||
delete symbols; |
|
||||
// Use symbols from default locale.
|
|
||||
symbols = new icu::DecimalFormatSymbols(status); |
|
||||
} |
|
||||
|
|
||||
return symbols; |
|
||||
} |
|
||||
|
|
||||
// Gets currency ISO 4217 3-letter code.
|
|
||||
// Check currencyCode setting first, then @currency=code and in the end
|
|
||||
// try to infer currency code from locale in the form 'und_' + region id.
|
|
||||
// Returns false in case of error.
|
|
||||
static bool GetCurrencyCode(const icu::Locale& icu_locale, |
|
||||
const char* const und_region_locale, |
|
||||
v8::Handle<v8::Object> settings, |
|
||||
UChar* code) { |
|
||||
UErrorCode status = U_ZERO_ERROR; |
|
||||
|
|
||||
// If there is user specified currency code, use it.
|
|
||||
icu::UnicodeString currency; |
|
||||
if (I18NUtils::ExtractStringSetting(settings, "currencyCode", ¤cy)) { |
|
||||
currency.extract(code, NumberFormat::kCurrencyCodeLength, status); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// If ICU locale has -cu- currency code use it.
|
|
||||
char currency_code[NumberFormat::kCurrencyCodeLength]; |
|
||||
int32_t length = icu_locale.getKeywordValue( |
|
||||
"currency", currency_code, NumberFormat::kCurrencyCodeLength, status); |
|
||||
if (length != 0) { |
|
||||
I18NUtils::AsciiToUChar(currency_code, length + 1, |
|
||||
code, NumberFormat::kCurrencyCodeLength); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// Otherwise infer currency code from the region id.
|
|
||||
ucurr_forLocale( |
|
||||
und_region_locale, code, NumberFormat::kCurrencyCodeLength, &status); |
|
||||
|
|
||||
return !!U_SUCCESS(status); |
|
||||
} |
|
||||
|
|
||||
// Throws a JavaScript exception.
|
|
||||
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() { |
|
||||
// Returns undefined, and schedules an exception to be thrown.
|
|
||||
return v8::ThrowException(v8::Exception::Error( |
|
||||
v8::String::New("NumberFormat method called on an object " |
|
||||
"that is not a NumberFormat."))); |
|
||||
} |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
@ -1,71 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_ |
|
||||
#define V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_ |
|
||||
|
|
||||
#include "include/v8.h" |
|
||||
|
|
||||
#include "unicode/uversion.h" |
|
||||
|
|
||||
namespace U_ICU_NAMESPACE { |
|
||||
class DecimalFormat; |
|
||||
} |
|
||||
|
|
||||
namespace v8 { |
|
||||
namespace internal { |
|
||||
|
|
||||
class NumberFormat { |
|
||||
public: |
|
||||
// 3-letter ISO 4217 currency code plus \0.
|
|
||||
static const int kCurrencyCodeLength; |
|
||||
|
|
||||
static v8::Handle<v8::Value> JSNumberFormat(const v8::Arguments& args); |
|
||||
|
|
||||
// Helper methods for various bindings.
|
|
||||
|
|
||||
// Unpacks date format object from corresponding JavaScript object.
|
|
||||
static icu::DecimalFormat* UnpackNumberFormat( |
|
||||
v8::Handle<v8::Object> obj); |
|
||||
|
|
||||
// Release memory we allocated for the NumberFormat once the JS object that
|
|
||||
// holds the pointer gets garbage collected.
|
|
||||
static void DeleteNumberFormat(v8::Persistent<v8::Value> object, |
|
||||
void* param); |
|
||||
|
|
||||
// Formats number and returns corresponding string.
|
|
||||
static v8::Handle<v8::Value> Format(const v8::Arguments& args); |
|
||||
|
|
||||
private: |
|
||||
NumberFormat(); |
|
||||
|
|
||||
static v8::Persistent<v8::FunctionTemplate> number_format_template_; |
|
||||
}; |
|
||||
|
|
||||
} } // namespace v8::internal
|
|
||||
|
|
||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_
|
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue