Removing experimental i18n code from v8 repository. Internationalization support is hosted under code.google.com/p/v8-i18n for couple months now.
TEST=Chromium/WebKit builds should pass. Review URL: https://chromiumcodereview.appspot.com/9016034 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10471 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8c776261c2
commit
bc091f31c8
@ -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,43 +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_NATIVES_H_
|
|
||||||
#define V8_EXTENSIONS_EXPERIMENTAL_I18N_NATIVES_H_
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
class I18Natives {
|
|
||||||
public:
|
|
||||||
// Gets script source from generated file.
|
|
||||||
// Source is statically allocated string.
|
|
||||||
static const char* GetScriptSource();
|
|
||||||
};
|
|
||||||
|
|
||||||
} } // namespace v8::internal
|
|
||||||
|
|
||||||
#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_NATIVES_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_
|
|
Loading…
Reference in New Issue
Block a user