[INTL] Implement supportedLocalesOf on Intl Constructors
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Sep 2015 17:43:27 +0000 (17:43 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Sep 2015 17:43:27 +0000 (17:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=147599

Patch by Andy VanWagoner <thetalecrafter@gmail.com> on 2015-09-15
Reviewed by Benjamin Poulain.

Source/JavaScriptCore:

Implements all of the abstract operations used by supportedLocalesOf,
except during canonicalization it does not replace redundant tags,
or subtags with their preferred values.

* icu/unicode/ucal.h: Added.
* icu/unicode/udat.h: Added.
* icu/unicode/umisc.h: Added.
* icu/unicode/unum.h: Added.
* icu/unicode/utypes.h: Clear the U_SHOW_CPLUSPLUS_API flag to prevent C++ headers from being included.
* runtime/CommonIdentifiers.h: Adde localeMatcher.
* runtime/IntlCollatorConstructor.cpp:
(JSC::IntlCollatorConstructorFuncSupportedLocalesOf): Implemented.
* runtime/IntlDateTimeFormatConstructor.cpp:
(JSC::IntlDateTimeFormatConstructorFuncSupportedLocalesOf): Implemented.
* runtime/IntlNumberFormatConstructor.cpp:
(JSC::IntlNumberFormatConstructorFuncSupportedLocalesOf): Implemented.
* runtime/IntlObject.cpp:
(JSC::canonicalizeLanguageTag):
(JSC::getCanonicalLangTag):
(JSC::getPrivateUseLangTag):
(JSC::getGrandfatheredLangTag):
(JSC::canonicalizeLocaleList):
(JSC::bestAvailableLocale):
(JSC::lookupSupportedLocales):
(JSC::bestFitSupportedLocales):
(JSC::supportedLocales):
(JSC::getIntlStringOption):
(JSC::getIntlBooleanOption):
* runtime/IntlObject.h:
* runtime/JSCJSValue.h: Added toLength.
* runtime/JSCJSValue.cpp: Added toLength.
(JSC::JSValue::toLength): Implement ToLength from ECMA 262 6.0 7.1.15
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::intlCollatorAvailableLocales): Added lazy locale list.
(JSC::JSGlobalObject::intlDateTimeFormatAvailableLocales): Added lazy locale list.
(JSC::JSGlobalObject::intlNumberFormatAvailableLocales): Added lazy locale list.
* runtime/JSGlobalObject.h:

LayoutTests:

* js/intl-collator-expected.txt: Added tests for supportedLocalesOf
* js/intl-datetimeformat-expected.txt: Added tests for supportedLocalesOf
* js/intl-numberformat-expected.txt: Added tests for supportedLocalesOf
* js/script-tests/intl-collator.js: Added tests for supportedLocalesOf
* js/script-tests/intl-datetimeformat.js: Added tests for supportedLocalesOf
* js/script-tests/intl-numberformat.js: Added tests for supportedLocalesOf

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@189811 268f45cc-cd09-0410-ab3c-d52691b4dbfc

23 files changed:
LayoutTests/ChangeLog
LayoutTests/js/intl-collator-expected.txt
LayoutTests/js/intl-datetimeformat-expected.txt
LayoutTests/js/intl-numberformat-expected.txt
LayoutTests/js/script-tests/intl-collator.js
LayoutTests/js/script-tests/intl-datetimeformat.js
LayoutTests/js/script-tests/intl-numberformat.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/icu/unicode/ucal.h [new file with mode: 0644]
Source/JavaScriptCore/icu/unicode/udat.h [new file with mode: 0644]
Source/JavaScriptCore/icu/unicode/umisc.h [new file with mode: 0644]
Source/JavaScriptCore/icu/unicode/unum.h [new file with mode: 0644]
Source/JavaScriptCore/icu/unicode/utypes.h
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/IntlCollatorConstructor.cpp
Source/JavaScriptCore/runtime/IntlDateTimeFormatConstructor.cpp
Source/JavaScriptCore/runtime/IntlNumberFormatConstructor.cpp
Source/JavaScriptCore/runtime/IntlObject.cpp
Source/JavaScriptCore/runtime/IntlObject.h
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h

index 14d55d3..e6f4b58 100644 (file)
@@ -1,3 +1,17 @@
+2015-09-15  Andy VanWagoner  <thetalecrafter@gmail.com>
+
+        [INTL] Implement supportedLocalesOf on Intl Constructors
+        https://bugs.webkit.org/show_bug.cgi?id=147599
+
+        Reviewed by Benjamin Poulain.
+
+        * js/intl-collator-expected.txt: Added tests for supportedLocalesOf
+        * js/intl-datetimeformat-expected.txt: Added tests for supportedLocalesOf
+        * js/intl-numberformat-expected.txt: Added tests for supportedLocalesOf
+        * js/script-tests/intl-collator.js: Added tests for supportedLocalesOf
+        * js/script-tests/intl-datetimeformat.js: Added tests for supportedLocalesOf
+        * js/script-tests/intl-numberformat.js: Added tests for supportedLocalesOf
+
 2015-09-15  Alex Christensen  <achristensen@webkit.org>
 
         Unreviewed gardening.
index 4d5fddf..ef3abe0 100644 (file)
@@ -18,6 +18,31 @@ PASS Object.getOwnPropertyDescriptor(Intl.Collator, 'prototype').enumerable is f
 PASS Object.getOwnPropertyDescriptor(Intl.Collator, 'prototype').configurable is false
 PASS Intl.Collator.supportedLocalesOf.length is 1
 PASS Intl.Collator.supportedLocalesOf() is an instance of Array
+PASS Intl.Collator.supportedLocalesOf.call(null, 'en') is [ 'en' ]
+PASS Intl.Collator.supportedLocalesOf.call({}, 'en') is [ 'en' ]
+PASS Intl.Collator.supportedLocalesOf.call(1, 'en') is [ 'en' ]
+PASS Intl.Collator.supportedLocalesOf(9) is []
+PASS Intl.Collator.supportedLocalesOf('en') is [ 'en' ]
+PASS Intl.Collator.supportedLocalesOf({ length: 4, 1: 'en', 0: 'es', 3: 'de' }) is [ 'es', 'en', 'de' ]
+PASS Intl.Collator.supportedLocalesOf([ 'en', 'pt', 'en', 'es' ]) is [ 'en', 'pt', 'es' ]
+PASS Intl.Collator.supportedLocalesOf('En-laTn-us-variant2-variant1-1abc-U-ko-tRue-A-aa-aaa-x-RESERVED') is [ 'en-Latn-US-variant2-variant1-1abc-a-aa-aaa-u-ko-true-x-reserved' ]
+PASS Intl.Collator.supportedLocalesOf('no-bok') is [ 'nb' ]
+PASS Intl.Collator.supportedLocalesOf('x-some-thing') is []
+PASS Intl.Collator.supportedLocalesOf(Object.create(null, { length: { get() { throw Error('a') } } })) threw exception Error: a.
+PASS Intl.Collator.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } })) threw exception Error: b.
+PASS Intl.Collator.supportedLocalesOf([ { toString() { throw Error('c') } } ]) threw exception Error: c.
+PASS Intl.Collator.supportedLocalesOf([ 5 ]) threw exception TypeError: locale value must be a string or object.
+PASS Intl.Collator.supportedLocalesOf('') threw exception RangeError: invalid language tag: .
+PASS Intl.Collator.supportedLocalesOf('a') threw exception RangeError: invalid language tag: a.
+PASS Intl.Collator.supportedLocalesOf('abcdefghij') threw exception RangeError: invalid language tag: abcdefghij.
+PASS Intl.Collator.supportedLocalesOf('#$') threw exception RangeError: invalid language tag: #$.
+PASS Intl.Collator.supportedLocalesOf('en-@-abc') threw exception RangeError: invalid language tag: en-@-abc.
+PASS Intl.Collator.supportedLocalesOf('en-u') threw exception RangeError: invalid language tag: en-u.
+PASS Intl.Collator.supportedLocalesOf('en-u-kn-true-u-ko-true') threw exception RangeError: invalid language tag: en-u-kn-true-u-ko-true.
+PASS Intl.Collator.supportedLocalesOf('en-x') threw exception RangeError: invalid language tag: en-x.
+PASS Intl.Collator.supportedLocalesOf('en-*') threw exception RangeError: invalid language tag: en-*.
+PASS Intl.Collator.supportedLocalesOf('en-') threw exception RangeError: invalid language tag: en-.
+PASS Intl.Collator.supportedLocalesOf('en--US') threw exception RangeError: invalid language tag: en--US.
 PASS Intl.Collator.prototype.constructor is Intl.Collator
 PASS Intl.Collator.prototype.compare is an instance of Function
 PASS Object.getOwnPropertyDescriptor(Intl.Collator.prototype, 'compare').get is an instance of Function
index 60173fe..d016c80 100644 (file)
@@ -18,6 +18,31 @@ PASS Object.getOwnPropertyDescriptor(Intl.DateTimeFormat, 'prototype').enumerabl
 PASS Object.getOwnPropertyDescriptor(Intl.DateTimeFormat, 'prototype').configurable is false
 PASS Intl.DateTimeFormat.supportedLocalesOf.length is 1
 PASS Intl.DateTimeFormat.supportedLocalesOf() is an instance of Array
+PASS Intl.DateTimeFormat.supportedLocalesOf.call(null, 'en') is [ 'en' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf.call({}, 'en') is [ 'en' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf.call(1, 'en') is [ 'en' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf(9) is []
+PASS Intl.DateTimeFormat.supportedLocalesOf('en') is [ 'en' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf({ length: 4, 1: 'en', 0: 'es', 3: 'de' }) is [ 'es', 'en', 'de' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf([ 'en', 'pt', 'en', 'es' ]) is [ 'en', 'pt', 'es' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf('En-laTn-us-variant2-variant1-1abc-U-ko-tRue-A-aa-aaa-x-RESERVED') is [ 'en-Latn-US-variant2-variant1-1abc-a-aa-aaa-u-ko-true-x-reserved' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf('no-bok') is [ 'nb' ]
+PASS Intl.DateTimeFormat.supportedLocalesOf('x-some-thing') is []
+PASS Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw Error('a') } } })) threw exception Error: a.
+PASS Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } })) threw exception Error: b.
+PASS Intl.DateTimeFormat.supportedLocalesOf([ { toString() { throw Error('c') } } ]) threw exception Error: c.
+PASS Intl.DateTimeFormat.supportedLocalesOf([ 5 ]) threw exception TypeError: locale value must be a string or object.
+PASS Intl.DateTimeFormat.supportedLocalesOf('') threw exception RangeError: invalid language tag: .
+PASS Intl.DateTimeFormat.supportedLocalesOf('a') threw exception RangeError: invalid language tag: a.
+PASS Intl.DateTimeFormat.supportedLocalesOf('abcdefghij') threw exception RangeError: invalid language tag: abcdefghij.
+PASS Intl.DateTimeFormat.supportedLocalesOf('#$') threw exception RangeError: invalid language tag: #$.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en-@-abc') threw exception RangeError: invalid language tag: en-@-abc.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en-u') threw exception RangeError: invalid language tag: en-u.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en-u-kn-true-u-ko-true') threw exception RangeError: invalid language tag: en-u-kn-true-u-ko-true.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en-x') threw exception RangeError: invalid language tag: en-x.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en-*') threw exception RangeError: invalid language tag: en-*.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en-') threw exception RangeError: invalid language tag: en-.
+PASS Intl.DateTimeFormat.supportedLocalesOf('en--US') threw exception RangeError: invalid language tag: en--US.
 PASS Intl.DateTimeFormat.prototype.constructor is Intl.DateTimeFormat
 PASS Intl.DateTimeFormat.prototype.format is an instance of Function
 PASS Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, 'format').get is an instance of Function
index 521851e..bfc3e77 100644 (file)
@@ -18,6 +18,31 @@ PASS Object.getOwnPropertyDescriptor(Intl.NumberFormat, 'prototype').enumerable
 PASS Object.getOwnPropertyDescriptor(Intl.NumberFormat, 'prototype').configurable is false
 PASS Intl.NumberFormat.supportedLocalesOf.length is 1
 PASS Intl.NumberFormat.supportedLocalesOf() is an instance of Array
+PASS Intl.NumberFormat.supportedLocalesOf.call(null, 'en') is [ 'en' ]
+PASS Intl.NumberFormat.supportedLocalesOf.call({}, 'en') is [ 'en' ]
+PASS Intl.NumberFormat.supportedLocalesOf.call(1, 'en') is [ 'en' ]
+PASS Intl.NumberFormat.supportedLocalesOf(9) is []
+PASS Intl.NumberFormat.supportedLocalesOf('en') is [ 'en' ]
+PASS Intl.NumberFormat.supportedLocalesOf({ length: 4, 1: 'en', 0: 'es', 3: 'de' }) is [ 'es', 'en', 'de' ]
+PASS Intl.NumberFormat.supportedLocalesOf([ 'en', 'pt', 'en', 'es' ]) is [ 'en', 'pt', 'es' ]
+PASS Intl.NumberFormat.supportedLocalesOf('En-laTn-us-variant2-variant1-1abc-U-ko-tRue-A-aa-aaa-x-RESERVED') is [ 'en-Latn-US-variant2-variant1-1abc-a-aa-aaa-u-ko-true-x-reserved' ]
+PASS Intl.NumberFormat.supportedLocalesOf('no-bok') is [ 'nb' ]
+PASS Intl.NumberFormat.supportedLocalesOf('x-some-thing') is []
+PASS Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw Error('a') } } })) threw exception Error: a.
+PASS Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } })) threw exception Error: b.
+PASS Intl.NumberFormat.supportedLocalesOf([ { toString() { throw Error('c') } } ]) threw exception Error: c.
+PASS Intl.NumberFormat.supportedLocalesOf([ 5 ]) threw exception TypeError: locale value must be a string or object.
+PASS Intl.NumberFormat.supportedLocalesOf('') threw exception RangeError: invalid language tag: .
+PASS Intl.NumberFormat.supportedLocalesOf('a') threw exception RangeError: invalid language tag: a.
+PASS Intl.NumberFormat.supportedLocalesOf('abcdefghij') threw exception RangeError: invalid language tag: abcdefghij.
+PASS Intl.NumberFormat.supportedLocalesOf('#$') threw exception RangeError: invalid language tag: #$.
+PASS Intl.NumberFormat.supportedLocalesOf('en-@-abc') threw exception RangeError: invalid language tag: en-@-abc.
+PASS Intl.NumberFormat.supportedLocalesOf('en-u') threw exception RangeError: invalid language tag: en-u.
+PASS Intl.NumberFormat.supportedLocalesOf('en-u-kn-true-u-ko-true') threw exception RangeError: invalid language tag: en-u-kn-true-u-ko-true.
+PASS Intl.NumberFormat.supportedLocalesOf('en-x') threw exception RangeError: invalid language tag: en-x.
+PASS Intl.NumberFormat.supportedLocalesOf('en-*') threw exception RangeError: invalid language tag: en-*.
+PASS Intl.NumberFormat.supportedLocalesOf('en-') threw exception RangeError: invalid language tag: en-.
+PASS Intl.NumberFormat.supportedLocalesOf('en--US') threw exception RangeError: invalid language tag: en--US.
 PASS Intl.NumberFormat.prototype.constructor is Intl.NumberFormat
 PASS Intl.NumberFormat.prototype.format is an instance of Function
 PASS Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, 'format').get is an instance of Function
index 5de190e..4ff9203 100644 (file)
@@ -35,8 +35,43 @@ shouldBeFalse("Object.getOwnPropertyDescriptor(Intl.Collator, 'prototype').confi
 // The value of the length property of the supportedLocalesOf method is 1.
 shouldBe("Intl.Collator.supportedLocalesOf.length", "1");
 
-// Returns SupportedLocales
+// Returns SupportedLocales.
 shouldBeType("Intl.Collator.supportedLocalesOf()", "Array");
+// Doesn't care about `this`.
+shouldBe("Intl.Collator.supportedLocalesOf.call(null, 'en')", "[ 'en' ]");
+shouldBe("Intl.Collator.supportedLocalesOf.call({}, 'en')", "[ 'en' ]");
+shouldBe("Intl.Collator.supportedLocalesOf.call(1, 'en')", "[ 'en' ]");
+// Ignores non-object, non-string list.
+shouldBe("Intl.Collator.supportedLocalesOf(9)", "[]");
+// Makes an array of tags.
+shouldBe("Intl.Collator.supportedLocalesOf('en')", "[ 'en' ]");
+// Handles array-like objects with holes.
+shouldBe("Intl.Collator.supportedLocalesOf({ length: 4, 1: 'en', 0: 'es', 3: 'de' })", "[ 'es', 'en', 'de' ]");
+// Deduplicates tags.
+shouldBe("Intl.Collator.supportedLocalesOf([ 'en', 'pt', 'en', 'es' ])", "[ 'en', 'pt', 'es' ]");
+// Canonicalizes tags.
+shouldBe("Intl.Collator.supportedLocalesOf('En-laTn-us-variant2-variant1-1abc-U-ko-tRue-A-aa-aaa-x-RESERVED')", "[ 'en-Latn-US-variant2-variant1-1abc-a-aa-aaa-u-ko-true-x-reserved' ]");
+// Replaces outdated tags.
+shouldBe("Intl.Collator.supportedLocalesOf('no-bok')", "[ 'nb' ]");
+// Doesn't throw, but ignores private tags.
+shouldBe("Intl.Collator.supportedLocalesOf('x-some-thing')", "[]");
+// Throws on problems with length, get, or toString.
+shouldThrow("Intl.Collator.supportedLocalesOf(Object.create(null, { length: { get() { throw Error('a') } } }))", "'Error: a'");
+shouldThrow("Intl.Collator.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } }))", "'Error: b'");
+shouldThrow("Intl.Collator.supportedLocalesOf([ { toString() { throw Error('c') } } ])", "'Error: c'");
+// Throws on bad tags.
+shouldThrow("Intl.Collator.supportedLocalesOf([ 5 ])", "'TypeError: locale value must be a string or object'");
+shouldThrow("Intl.Collator.supportedLocalesOf('')", "'RangeError: invalid language tag: '");
+shouldThrow("Intl.Collator.supportedLocalesOf('a')", "'RangeError: invalid language tag: a'");
+shouldThrow("Intl.Collator.supportedLocalesOf('abcdefghij')", "'RangeError: invalid language tag: abcdefghij'");
+shouldThrow("Intl.Collator.supportedLocalesOf('#$')", "'RangeError: invalid language tag: #$'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en-@-abc')", "'RangeError: invalid language tag: en-@-abc'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en-u')", "'RangeError: invalid language tag: en-u'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en-u-kn-true-u-ko-true')", "'RangeError: invalid language tag: en-u-kn-true-u-ko-true'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en-x')", "'RangeError: invalid language tag: en-x'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en-*')", "'RangeError: invalid language tag: en-*'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en-')", "'RangeError: invalid language tag: en-'");
+shouldThrow("Intl.Collator.supportedLocalesOf('en--US')", "'RangeError: invalid language tag: en--US'");
 
 // 10.3 Properties of the Intl.Collator Prototype Object
 
index bc7c9a7..ede1b5c 100644 (file)
@@ -37,6 +37,41 @@ shouldBe("Intl.DateTimeFormat.supportedLocalesOf.length", "1");
 
 // Returns SupportedLocales
 shouldBeType("Intl.DateTimeFormat.supportedLocalesOf()", "Array");
+// Doesn't care about `this`.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf.call(null, 'en')", "[ 'en' ]");
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf.call({}, 'en')", "[ 'en' ]");
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf.call(1, 'en')", "[ 'en' ]");
+// Ignores non-object, non-string list.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf(9)", "[]");
+// Makes an array of tags.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf('en')", "[ 'en' ]");
+// Handles array-like objects with holes.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf({ length: 4, 1: 'en', 0: 'es', 3: 'de' })", "[ 'es', 'en', 'de' ]");
+// Deduplicates tags.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf([ 'en', 'pt', 'en', 'es' ])", "[ 'en', 'pt', 'es' ]");
+// Canonicalizes tags.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf('En-laTn-us-variant2-variant1-1abc-U-ko-tRue-A-aa-aaa-x-RESERVED')", "[ 'en-Latn-US-variant2-variant1-1abc-a-aa-aaa-u-ko-true-x-reserved' ]");
+// Replaces outdated tags.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf('no-bok')", "[ 'nb' ]");
+// Doesn't throw, but ignores private tags.
+shouldBe("Intl.DateTimeFormat.supportedLocalesOf('x-some-thing')", "[]");
+// Throws on problems with length, get, or toString.
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw Error('a') } } }))", "'Error: a'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } }))", "'Error: b'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf([ { toString() { throw Error('c') } } ])", "'Error: c'");
+// Throws on bad tags.
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf([ 5 ])", "'TypeError: locale value must be a string or object'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('')", "'RangeError: invalid language tag: '");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('a')", "'RangeError: invalid language tag: a'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('abcdefghij')", "'RangeError: invalid language tag: abcdefghij'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('#$')", "'RangeError: invalid language tag: #$'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en-@-abc')", "'RangeError: invalid language tag: en-@-abc'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en-u')", "'RangeError: invalid language tag: en-u'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en-u-kn-true-u-ko-true')", "'RangeError: invalid language tag: en-u-kn-true-u-ko-true'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en-x')", "'RangeError: invalid language tag: en-x'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en-*')", "'RangeError: invalid language tag: en-*'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en-')", "'RangeError: invalid language tag: en-'");
+shouldThrow("Intl.DateTimeFormat.supportedLocalesOf('en--US')", "'RangeError: invalid language tag: en--US'");
 
 // 12.3 Properties of the Intl.DateTimeFormat Prototype Object
 
index 065d921..07df8c8 100644 (file)
@@ -37,6 +37,41 @@ shouldBe("Intl.NumberFormat.supportedLocalesOf.length", "1");
 
 // Returns SupportedLocales
 shouldBeType("Intl.NumberFormat.supportedLocalesOf()", "Array");
+// Doesn't care about `this`.
+shouldBe("Intl.NumberFormat.supportedLocalesOf.call(null, 'en')", "[ 'en' ]");
+shouldBe("Intl.NumberFormat.supportedLocalesOf.call({}, 'en')", "[ 'en' ]");
+shouldBe("Intl.NumberFormat.supportedLocalesOf.call(1, 'en')", "[ 'en' ]");
+// Ignores non-object, non-string list.
+shouldBe("Intl.NumberFormat.supportedLocalesOf(9)", "[]");
+// Makes an array of tags.
+shouldBe("Intl.NumberFormat.supportedLocalesOf('en')", "[ 'en' ]");
+// Handles array-like objects with holes.
+shouldBe("Intl.NumberFormat.supportedLocalesOf({ length: 4, 1: 'en', 0: 'es', 3: 'de' })", "[ 'es', 'en', 'de' ]");
+// Deduplicates tags.
+shouldBe("Intl.NumberFormat.supportedLocalesOf([ 'en', 'pt', 'en', 'es' ])", "[ 'en', 'pt', 'es' ]");
+// Canonicalizes tags.
+shouldBe("Intl.NumberFormat.supportedLocalesOf('En-laTn-us-variant2-variant1-1abc-U-ko-tRue-A-aa-aaa-x-RESERVED')", "[ 'en-Latn-US-variant2-variant1-1abc-a-aa-aaa-u-ko-true-x-reserved' ]");
+// Replaces outdated tags.
+shouldBe("Intl.NumberFormat.supportedLocalesOf('no-bok')", "[ 'nb' ]");
+// Doesn't throw, but ignores private tags.
+shouldBe("Intl.NumberFormat.supportedLocalesOf('x-some-thing')", "[]");
+// Throws on problems with length, get, or toString.
+shouldThrow("Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw Error('a') } } }))", "'Error: a'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } }))", "'Error: b'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf([ { toString() { throw Error('c') } } ])", "'Error: c'");
+// Throws on bad tags.
+shouldThrow("Intl.NumberFormat.supportedLocalesOf([ 5 ])", "'TypeError: locale value must be a string or object'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('')", "'RangeError: invalid language tag: '");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('a')", "'RangeError: invalid language tag: a'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('abcdefghij')", "'RangeError: invalid language tag: abcdefghij'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('#$')", "'RangeError: invalid language tag: #$'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en-@-abc')", "'RangeError: invalid language tag: en-@-abc'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en-u')", "'RangeError: invalid language tag: en-u'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en-u-kn-true-u-ko-true')", "'RangeError: invalid language tag: en-u-kn-true-u-ko-true'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en-x')", "'RangeError: invalid language tag: en-x'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en-*')", "'RangeError: invalid language tag: en-*'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en-')", "'RangeError: invalid language tag: en-'");
+shouldThrow("Intl.NumberFormat.supportedLocalesOf('en--US')", "'RangeError: invalid language tag: en--US'");
 
 // 11.3 Properties of the Intl.NumberFormat Prototype Object
 
index 2d49a7f..ad23034 100644 (file)
@@ -1,3 +1,48 @@
+2015-09-15  Andy VanWagoner  <thetalecrafter@gmail.com>
+
+        [INTL] Implement supportedLocalesOf on Intl Constructors
+        https://bugs.webkit.org/show_bug.cgi?id=147599
+
+        Reviewed by Benjamin Poulain.
+
+        Implements all of the abstract operations used by supportedLocalesOf,
+        except during canonicalization it does not replace redundant tags,
+        or subtags with their preferred values.
+
+        * icu/unicode/ucal.h: Added.
+        * icu/unicode/udat.h: Added.
+        * icu/unicode/umisc.h: Added.
+        * icu/unicode/unum.h: Added.
+        * icu/unicode/utypes.h: Clear the U_SHOW_CPLUSPLUS_API flag to prevent C++ headers from being included.
+        * runtime/CommonIdentifiers.h: Adde localeMatcher.
+        * runtime/IntlCollatorConstructor.cpp:
+        (JSC::IntlCollatorConstructorFuncSupportedLocalesOf): Implemented.
+        * runtime/IntlDateTimeFormatConstructor.cpp:
+        (JSC::IntlDateTimeFormatConstructorFuncSupportedLocalesOf): Implemented.
+        * runtime/IntlNumberFormatConstructor.cpp:
+        (JSC::IntlNumberFormatConstructorFuncSupportedLocalesOf): Implemented.
+        * runtime/IntlObject.cpp:
+        (JSC::canonicalizeLanguageTag):
+        (JSC::getCanonicalLangTag):
+        (JSC::getPrivateUseLangTag):
+        (JSC::getGrandfatheredLangTag):
+        (JSC::canonicalizeLocaleList):
+        (JSC::bestAvailableLocale):
+        (JSC::lookupSupportedLocales):
+        (JSC::bestFitSupportedLocales):
+        (JSC::supportedLocales):
+        (JSC::getIntlStringOption):
+        (JSC::getIntlBooleanOption):
+        * runtime/IntlObject.h:
+        * runtime/JSCJSValue.h: Added toLength.
+        * runtime/JSCJSValue.cpp: Added toLength.
+        (JSC::JSValue::toLength): Implement ToLength from ECMA 262 6.0 7.1.15
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::intlCollatorAvailableLocales): Added lazy locale list.
+        (JSC::JSGlobalObject::intlDateTimeFormatAvailableLocales): Added lazy locale list.
+        (JSC::JSGlobalObject::intlNumberFormatAvailableLocales): Added lazy locale list.
+        * runtime/JSGlobalObject.h:
+
 2015-09-14  Saam barati  <sbarati@apple.com>
 
         rename callFrameForThrow to callFrameForCatch
diff --git a/Source/JavaScriptCore/icu/unicode/ucal.h b/Source/JavaScriptCore/icu/unicode/ucal.h
new file mode 100644 (file)
index 0000000..997af15
--- /dev/null
@@ -0,0 +1,1285 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2010, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ *******************************************************************************
+ */
+
+#ifndef UCAL_H
+#define UCAL_H
+
+#include "unicode/utypes.h"
+#include "unicode/uenum.h"
+#include "unicode/uloc.h"
+#include "unicode/localpointer.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+/**
+ * \file
+ * \brief C API: Calendar
+ *
+ * <h2>Calendar C API</h2>
+ *
+ * UCalendar C API is used  for converting between a <code>UDate</code> object
+ * and a set of integer fields such as <code>UCAL_YEAR</code>, <code>UCAL_MONTH</code>,
+ * <code>UCAL_DAY</code>, <code>UCAL_HOUR</code>, and so on.
+ * (A <code>UDate</code> object represents a specific instant in
+ * time with millisecond precision. See UDate
+ * for information about the <code>UDate</code> .)
+ *
+ * <p>
+ * Types of <code>UCalendar</code> interpret a <code>UDate</code>
+ * according to the rules of a specific calendar system. The U_STABLE
+ * provides the enum UCalendarType with UCAL_TRADITIONAL and
+ * UCAL_GREGORIAN.
+ * <p>
+ * Like other locale-sensitive C API, calendar API  provides a
+ * function, <code>ucal_open()</code>, which returns a pointer to
+ * <code>UCalendar</code> whose time fields have been initialized
+ * with the current date and time. We need to specify the type of
+ * calendar to be opened and the  timezoneId.
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * UCalendar *caldef;
+ * UChar *tzId;
+ * UErrorCode status;
+ * tzId=(UChar*)malloc(sizeof(UChar) * (strlen("PST") +1) );
+ * u_uastrcpy(tzId, "PST");
+ * caldef=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status);
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ *
+ * <p>
+ * A <code>UCalendar</code> object can produce all the time field values
+ * needed to implement the date-time formatting for a particular language
+ * and calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
+ *
+ * <p>
+ * When computing a <code>UDate</code> from time fields, two special circumstances
+ * may arise: there may be insufficient information to compute the
+ * <code>UDate</code> (such as only year and month but no day in the month),
+ * or there may be inconsistent information (such as "Tuesday, July 15, 1996"
+ * -- July 15, 1996 is actually a Monday).
+ *
+ * <p>
+ * <strong>Insufficient information.</strong> The calendar will use default
+ * information to specify the missing fields. This may vary by calendar; for
+ * the Gregorian calendar, the default for a field is the same as that of the
+ * start of the epoch: i.e., UCAL_YEAR = 1970, UCAL_MONTH = JANUARY, UCAL_DATE = 1, etc.
+ *
+ * <p>
+ * <strong>Inconsistent information.</strong> If fields conflict, the calendar
+ * will give preference to fields set more recently. For example, when
+ * determining the day, the calendar will look for one of the following
+ * combinations of fields.  The most recent combination, as determined by the
+ * most recently set single field, will be used.
+ *
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * UCAL_MONTH + UCAL_DAY_OF_MONTH
+ * UCAL_MONTH + UCAL_WEEK_OF_MONTH + UCAL_DAY_OF_WEEK
+ * UCAL_MONTH + UCAL_DAY_OF_WEEK_IN_MONTH + UCAL_DAY_OF_WEEK
+ * UCAL_DAY_OF_YEAR
+ * UCAL_DAY_OF_WEEK + UCAL_WEEK_OF_YEAR
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ *
+ * For the time of day:
+ *
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * UCAL_HOUR_OF_DAY
+ * UCAL_AM_PM + UCAL_HOUR
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ *
+ * <p>
+ * <strong>Note:</strong> for some non-Gregorian calendars, different
+ * fields may be necessary for complete disambiguation. For example, a full
+ * specification of the historial Arabic astronomical calendar requires year,
+ * month, day-of-month <em>and</em> day-of-week in some cases.
+ *
+ * <p>
+ * <strong>Note:</strong> There are certain possible ambiguities in
+ * interpretation of certain singular times, which are resolved in the
+ * following ways:
+ * <ol>
+ *     <li> 24:00:00 "belongs" to the following day. That is,
+ *          23:59 on Dec 31, 1969 &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970
+ *
+ *     <li> Although historically not precise, midnight also belongs to "am",
+ *          and noon belongs to "pm", so on the same day,
+ *          12:00 am (midnight) &lt; 12:01 am, and 12:00 pm (noon) &lt; 12:01 pm
+ * </ol>
+ *
+ * <p>
+ * The date or time format strings are not part of the definition of a
+ * calendar, as those must be modifiable or overridable by the user at
+ * runtime. Use {@link DateFormat}
+ * to format dates.
+ *
+ * <p>
+ * <code>Calendar</code> provides an API for field "rolling", where fields
+ * can be incremented or decremented, but wrap around. For example, rolling the
+ * month up in the date <code>December 12, <b>1996</b></code> results in
+ * <code>January 12, <b>1996</b></code>.
+ *
+ * <p>
+ * <code>Calendar</code> also provides a date arithmetic function for
+ * adding the specified (signed) amount of time to a particular time field.
+ * For example, subtracting 5 days from the date <code>September 12, 1996</code>
+ * results in <code>September 7, 1996</code>.
+ *
+ * @stable ICU 2.0
+ */
+
+/** A calendar.
+ *  For usage in C programs.
+ * @stable ICU 2.0
+ */
+typedef void* UCalendar;
+
+/** Possible types of UCalendars 
+ * @stable ICU 2.0
+ */
+enum UCalendarType {
+  /**
+   * Despite the name, UCAL_TRADITIONAL designates the locale's default calendar,
+   * which may be the Gregorian calendar or some other calendar.
+   * @stable ICU 2.0
+   */
+  UCAL_TRADITIONAL,
+  /**
+   * A better name for UCAL_TRADITIONAL.
+   * @stable ICU 4.2
+   */
+  UCAL_DEFAULT = UCAL_TRADITIONAL,
+  /**
+   * Unambiguously designates the Gregorian calendar for the locale.
+   * @stable ICU 2.0
+   */
+  UCAL_GREGORIAN
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarType UCalendarType;
+
+/** Possible fields in a UCalendar 
+ * @stable ICU 2.0
+ */
+enum UCalendarDateFields {
+  /** 
+   * Field number indicating the era, e.g., AD or BC in the Gregorian (Julian) calendar. 
+   * This is a calendar-specific value.
+   * @stable ICU 2.6 
+   */
+  UCAL_ERA,
+
+  /**
+   * Field number indicating the year. This is a calendar-specific value.
+   * @stable ICU 2.6 
+   */
+  UCAL_YEAR,
+
+  /**
+   * Field number indicating the month. This is a calendar-specific value. 
+   * The first month of the year is
+   * <code>JANUARY</code>; the last depends on the number of months in a year.
+   * @see #UCAL_JANUARY
+   * @see #UCAL_FEBRUARY
+   * @see #UCAL_MARCH
+   * @see #UCAL_APRIL
+   * @see #UCAL_MAY
+   * @see #UCAL_JUNE
+   * @see #UCAL_JULY
+   * @see #UCAL_AUGUST
+   * @see #UCAL_SEPTEMBER
+   * @see #UCAL_OCTOBER
+   * @see #UCAL_NOVEMBER
+   * @see #UCAL_DECEMBER
+   * @see #UCAL_UNDECIMBER
+   * @stable ICU 2.6 
+   */
+  UCAL_MONTH,
+
+  /**
+   * Field number indicating the
+   * week number within the current year.  The first week of the year, as
+   * defined by <code>UCAL_FIRST_DAY_OF_WEEK</code> and <code>UCAL_MINIMAL_DAYS_IN_FIRST_WEEK</code>
+   * attributes, has value 1.  Subclasses define
+   * the value of <code>UCAL_WEEK_OF_YEAR</code> for days before the first week of
+   * the year.
+   * @see ucal_getAttribute
+   * @see ucal_setAttribute
+   * @stable ICU 2.6 
+   */
+  UCAL_WEEK_OF_YEAR,
+
+ /**
+   * Field number indicating the
+   * week number within the current month.  The first week of the month, as
+   * defined by <code>UCAL_FIRST_DAY_OF_WEEK</code> and <code>UCAL_MINIMAL_DAYS_IN_FIRST_WEEK</code>
+   * attributes, has value 1.  Subclasses define
+   * the value of <code>WEEK_OF_MONTH</code> for days before the first week of
+   * the month.
+   * @see ucal_getAttribute
+   * @see ucal_setAttribute
+   * @see #UCAL_FIRST_DAY_OF_WEEK
+   * @see #UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
+   * @stable ICU 2.6 
+   */
+  UCAL_WEEK_OF_MONTH,
+
+ /**
+   * Field number indicating the
+   * day of the month. This is a synonym for <code>DAY_OF_MONTH</code>.
+   * The first day of the month has value 1.
+   * @see #UCAL_DAY_OF_MONTH
+   * @stable ICU 2.6 
+   */
+  UCAL_DATE,
+
+ /**
+   * Field number indicating the day
+   * number within the current year.  The first day of the year has value 1.
+   * @stable ICU 2.6 
+   */
+  UCAL_DAY_OF_YEAR,
+
+ /**
+   * Field number indicating the day
+   * of the week.  This field takes values <code>SUNDAY</code>,
+   * <code>MONDAY</code>, <code>TUESDAY</code>, <code>WEDNESDAY</code>,
+   * <code>THURSDAY</code>, <code>FRIDAY</code>, and <code>SATURDAY</code>.
+   * @see #UCAL_SUNDAY
+   * @see #UCAL_MONDAY
+   * @see #UCAL_TUESDAY
+   * @see #UCAL_WEDNESDAY
+   * @see #UCAL_THURSDAY
+   * @see #UCAL_FRIDAY
+   * @see #UCAL_SATURDAY
+   * @stable ICU 2.6 
+   */
+  UCAL_DAY_OF_WEEK,
+
+ /**
+   * Field number indicating the
+   * ordinal number of the day of the week within the current month. Together
+   * with the <code>DAY_OF_WEEK</code> field, this uniquely specifies a day
+   * within a month.  Unlike <code>WEEK_OF_MONTH</code> and
+   * <code>WEEK_OF_YEAR</code>, this field's value does <em>not</em> depend on
+   * <code>getFirstDayOfWeek()</code> or
+   * <code>getMinimalDaysInFirstWeek()</code>.  <code>DAY_OF_MONTH 1</code>
+   * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
+   * 1</code>; <code>8</code> through <code>15</code> correspond to
+   * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
+   * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
+   * <code>DAY_OF_WEEK_IN_MONTH 1</code>.  Negative values count back from the
+   * end of the month, so the last Sunday of a month is specified as
+   * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>.  Because
+   * negative values count backward they will usually be aligned differently
+   * within the month than positive values.  For example, if a month has 31
+   * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap
+   * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
+   * @see #UCAL_DAY_OF_WEEK
+   * @see #UCAL_WEEK_OF_MONTH
+   * @stable ICU 2.6 
+   */
+  UCAL_DAY_OF_WEEK_IN_MONTH,
+
+ /**
+   * Field number indicating
+   * whether the <code>HOUR</code> is before or after noon.
+   * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
+   * @see #UCAL_AM
+   * @see #UCAL_PM
+   * @see #UCAL_HOUR
+   * @stable ICU 2.6 
+   */
+  UCAL_AM_PM,
+
+ /**
+   * Field number indicating the
+   * hour of the morning or afternoon. <code>HOUR</code> is used for the 12-hour
+   * clock.
+   * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
+   * @see #UCAL_AM_PM
+   * @see #UCAL_HOUR_OF_DAY
+   * @stable ICU 2.6 
+   */
+  UCAL_HOUR,
+
+ /**
+   * Field number indicating the
+   * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
+   * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
+   * @see #UCAL_HOUR
+   * @stable ICU 2.6 
+   */
+  UCAL_HOUR_OF_DAY,
+
+ /**
+   * Field number indicating the
+   * minute within the hour.
+   * E.g., at 10:04:15.250 PM the <code>UCAL_MINUTE</code> is 4.
+   * @stable ICU 2.6 
+   */
+  UCAL_MINUTE,
+
+ /**
+   * Field number indicating the
+   * second within the minute.
+   * E.g., at 10:04:15.250 PM the <code>UCAL_SECOND</code> is 15.
+   * @stable ICU 2.6 
+   */
+  UCAL_SECOND,
+
+ /**
+   * Field number indicating the
+   * millisecond within the second.
+   * E.g., at 10:04:15.250 PM the <code>UCAL_MILLISECOND</code> is 250.
+   * @stable ICU 2.6 
+   */
+  UCAL_MILLISECOND,
+
+ /**
+   * Field number indicating the
+   * raw offset from GMT in milliseconds.
+   * @stable ICU 2.6 
+   */
+  UCAL_ZONE_OFFSET,
+
+ /**
+   * Field number indicating the
+   * daylight savings offset in milliseconds.
+   * @stable ICU 2.6 
+   */
+  UCAL_DST_OFFSET,
+  
+ /**
+   * Field number 
+   * indicating the extended year corresponding to the
+   * <code>UCAL_WEEK_OF_YEAR</code> field.  This may be one greater or less
+   * than the value of <code>UCAL_EXTENDED_YEAR</code>.
+   * @stable ICU 2.6
+   */
+  UCAL_YEAR_WOY,
+
+ /**
+   * Field number 
+   * indicating the localized day of week.  This will be a value from 1
+   * to 7 inclusive, with 1 being the localized first day of the week.
+   * @stable ICU 2.6
+   */
+  UCAL_DOW_LOCAL,
+
+  /**
+   * Year of this calendar system, encompassing all supra-year fields. For example, 
+   * in Gregorian/Julian calendars, positive Extended Year values indicate years AD,
+   *  1 BC = 0 extended, 2 BC = -1 extended, and so on. 
+   * @stable ICU 2.8 
+   */
+  UCAL_EXTENDED_YEAR,
+
+ /**
+   * Field number 
+   * indicating the modified Julian day number.  This is different from
+   * the conventional Julian day number in two regards.  First, it
+   * demarcates days at local zone midnight, rather than noon GMT.
+   * Second, it is a local number; that is, it depends on the local time
+   * zone.  It can be thought of as a single number that encompasses all
+   * the date-related fields.
+   * @stable ICU 2.8
+   */
+  UCAL_JULIAN_DAY, 
+
+  /**
+   * Ranges from 0 to 23:59:59.999 (regardless of DST).  This field behaves <em>exactly</em> 
+   * like a composite of all time-related fields, not including the zone fields.  As such, 
+   * it also reflects discontinuities of those fields on DST transition days.  On a day
+   * of DST onset, it will jump forward.  On a day of DST cessation, it will jump 
+   * backward.  This reflects the fact that it must be combined with the DST_OFFSET field
+   * to obtain a unique local time value.
+   * @stable ICU 2.8
+   */
+  UCAL_MILLISECONDS_IN_DAY,
+
+  /**
+   * Whether or not the current month is a leap month (0 or 1). See the Chinese calendar for
+   * an example of this.
+   */
+  UCAL_IS_LEAP_MONTH,
+  
+  /**
+   * Field count
+   * @stable ICU 2.6
+   */
+  UCAL_FIELD_COUNT,
+
+ /**
+   * Field number indicating the
+   * day of the month. This is a synonym for <code>UCAL_DATE</code>.
+   * The first day of the month has value 1.
+   * @see #UCAL_DATE
+   * Synonym for UCAL_DATE
+   * @stable ICU 2.8
+   **/
+  UCAL_DAY_OF_MONTH=UCAL_DATE
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarDateFields UCalendarDateFields;
+    /**
+     * Useful constant for days of week. Note: Calendar day-of-week is 1-based. Clients
+     * who create locale resources for the field of first-day-of-week should be aware of
+     * this. For instance, in US locale, first-day-of-week is set to 1, i.e., UCAL_SUNDAY.
+     */
+/** Possible days of the week in a UCalendar 
+ * @stable ICU 2.0
+ */
+enum UCalendarDaysOfWeek {
+  /** Sunday */
+  UCAL_SUNDAY = 1,
+  /** Monday */
+  UCAL_MONDAY,
+  /** Tuesday */
+  UCAL_TUESDAY,
+  /** Wednesday */
+  UCAL_WEDNESDAY,
+  /** Thursday */
+  UCAL_THURSDAY,
+  /** Friday */
+  UCAL_FRIDAY,
+  /** Saturday */
+  UCAL_SATURDAY
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarDaysOfWeek UCalendarDaysOfWeek;
+
+/** Possible months in a UCalendar. Note: Calendar month is 0-based.
+ * @stable ICU 2.0
+ */
+enum UCalendarMonths {
+  /** January */
+  UCAL_JANUARY,
+  /** February */
+  UCAL_FEBRUARY,
+  /** March */
+  UCAL_MARCH,
+  /** April */
+  UCAL_APRIL,
+  /** May */
+  UCAL_MAY,
+  /** June */
+  UCAL_JUNE,
+  /** July */
+  UCAL_JULY,
+  /** August */
+  UCAL_AUGUST,
+  /** September */
+  UCAL_SEPTEMBER,
+  /** October */
+  UCAL_OCTOBER,
+  /** November */
+  UCAL_NOVEMBER,
+  /** December */
+  UCAL_DECEMBER,
+  /** Value of the <code>UCAL_MONTH</code> field indicating the
+    * thirteenth month of the year. Although the Gregorian calendar
+    * does not use this value, lunar calendars do.
+    */
+  UCAL_UNDECIMBER
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarMonths UCalendarMonths;
+
+/** Possible AM/PM values in a UCalendar 
+ * @stable ICU 2.0
+ */
+enum UCalendarAMPMs {
+    /** AM */
+  UCAL_AM,
+  /** PM */
+  UCAL_PM
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarAMPMs UCalendarAMPMs;
+
+/**
+ * Create an enumeration over all time zones.
+ *
+ * @param ec input/output error code
+ *
+ * @return an enumeration object that the caller must dispose of using
+ * uenum_close(), or NULL upon failure. In case of failure *ec will
+ * indicate the error.
+ *
+ * @stable ICU 2.6
+ */
+U_STABLE UEnumeration* U_EXPORT2
+ucal_openTimeZones(UErrorCode* ec);
+
+/**
+ * Create an enumeration over all time zones associated with the given
+ * country. Some zones are affiliated with no country (e.g., "UTC");
+ * these may also be retrieved, as a group.
+ *
+ * @param country the ISO 3166 two-letter country code, or NULL to
+ * retrieve zones not affiliated with any country
+ *
+ * @param ec input/output error code
+ *
+ * @return an enumeration object that the caller must dispose of using
+ * uenum_close(), or NULL upon failure. In case of failure *ec will
+ * indicate the error.
+ *
+ * @stable ICU 2.6
+ */
+U_STABLE UEnumeration* U_EXPORT2
+ucal_openCountryTimeZones(const char* country, UErrorCode* ec);
+
+/**
+ * Return the default time zone. The default is determined initially
+ * by querying the host operating system. It may be changed with
+ * ucal_setDefaultTimeZone() or with the C++ TimeZone API.
+ *
+ * @param result A buffer to receive the result, or NULL
+ *
+ * @param resultCapacity The capacity of the result buffer
+ *
+ * @param ec input/output error code
+ *
+ * @return The result string length, not including the terminating
+ * null
+ *
+ * @stable ICU 2.6
+ */
+U_STABLE int32_t U_EXPORT2
+ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec);
+
+/**
+ * Set the default time zone.
+ *
+ * @param zoneID null-terminated time zone ID
+ *
+ * @param ec input/output error code
+ *
+ * @stable ICU 2.6
+ */
+U_STABLE void U_EXPORT2
+ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec);
+
+/**
+ * Return the amount of time in milliseconds that the clock is
+ * advanced during daylight savings time for the given time zone, or
+ * zero if the time zone does not observe daylight savings time.
+ *
+ * @param zoneID null-terminated time zone ID
+ *
+ * @param ec input/output error code
+ *
+ * @return the number of milliseconds the time is advanced with
+ * respect to standard time when the daylight savings rules are in
+ * effect. This is always a non-negative number, most commonly either
+ * 3,600,000 (one hour) or zero.
+ *
+ * @stable ICU 2.6
+ */
+U_STABLE int32_t U_EXPORT2
+ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec);
+
+/**
+ * Get the current date and time.
+ * The value returned is represented as milliseconds from the epoch.
+ * @return The current date and time.
+ * @stable ICU 2.0
+ */
+U_STABLE UDate U_EXPORT2 
+ucal_getNow(void);
+
+/**
+ * Open a UCalendar.
+ * A UCalendar may be used to convert a millisecond value to a year,
+ * month, and day.
+ * <p>
+ * Note: When unknown TimeZone ID is specified, the UCalendar returned
+ * by the function is initialized with GMT ("Etc/GMT") without any
+ * errors/warnings.  If you want to check if a TimeZone ID is valid,
+ * use ucal_getCanonicalTimeZoneID prior to this function.
+ * 
+ * @param zoneID The desired TimeZone ID.  If 0, use the default time zone.
+ * @param len The length of zoneID, or -1 if null-terminated.
+ * @param locale The desired locale
+ * @param type The type of UCalendar to open. This can be UCAL_GREGORIAN to open the Gregorian
+ * calendar for the locale, or UCAL_DEFAULT to open the default calendar for the locale (the
+ * default calendar may also be Gregorian). To open a specific non-Gregorian calendar for the
+ * locale, use uloc_setKeywordValue to set the value of the calendar keyword for the locale
+ * and then pass the locale to ucal_open with UCAL_DEFAULT as the type.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return A pointer to a UCalendar, or 0 if an error occurred.
+ * @stable ICU 2.0
+ */
+U_STABLE UCalendar* U_EXPORT2 
+ucal_open(const UChar*   zoneID,
+          int32_t        len,
+          const char*    locale,
+          UCalendarType  type,
+          UErrorCode*    status);
+
+/**
+ * Close a UCalendar.
+ * Once closed, a UCalendar may no longer be used.
+ * @param cal The UCalendar to close.
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_close(UCalendar *cal);
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUCalendarPointer
+ * "Smart pointer" class, closes a UCalendar via ucal_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 4.4
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUCalendarPointer, UCalendar, ucal_close);
+
+U_NAMESPACE_END
+
+#endif
+
+/**
+ * Open a copy of a UCalendar.
+ * This function performs a deep copy.
+ * @param cal The calendar to copy
+ * @param status A pointer to an UErrorCode to receive any errors.
+ * @return A pointer to a UCalendar identical to cal.
+ * @stable ICU 4.0
+ */
+U_STABLE UCalendar* U_EXPORT2 
+ucal_clone(const UCalendar* cal,
+           UErrorCode*      status);
+
+/**
+ * Set the TimeZone used by a UCalendar.
+ * A UCalendar uses a timezone for converting from Greenwich time to local time.
+ * @param cal The UCalendar to set.
+ * @param zoneID The desired TimeZone ID.  If 0, use the default time zone.
+ * @param len The length of zoneID, or -1 if null-terminated.
+ * @param status A pointer to an UErrorCode to receive any errors.
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_setTimeZone(UCalendar*    cal,
+                 const UChar*  zoneID,
+                 int32_t       len,
+                 UErrorCode*   status);
+
+/**
+ * Possible formats for a UCalendar's display name 
+ * @stable ICU 2.0
+ */
+enum UCalendarDisplayNameType {
+  /** Standard display name */
+  UCAL_STANDARD,
+  /** Short standard display name */
+  UCAL_SHORT_STANDARD,
+  /** Daylight savings display name */
+  UCAL_DST,
+  /** Short daylight savings display name */
+  UCAL_SHORT_DST
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarDisplayNameType UCalendarDisplayNameType;
+
+/**
+ * Get the display name for a UCalendar's TimeZone.
+ * A display name is suitable for presentation to a user.
+ * @param cal          The UCalendar to query.
+ * @param type         The desired display name format; one of UCAL_STANDARD, UCAL_SHORT_STANDARD,
+ *                     UCAL_DST, UCAL_SHORT_DST
+ * @param locale       The desired locale for the display name.
+ * @param result       A pointer to a buffer to receive the formatted number.
+ * @param resultLength The maximum size of result.
+ * @param status       A pointer to an UErrorCode to receive any errors
+ * @return             The total buffer size needed; if greater than resultLength, the output was truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucal_getTimeZoneDisplayName(const UCalendar*          cal,
+                            UCalendarDisplayNameType  type,
+                            const char*               locale,
+                            UChar*                    result,
+                            int32_t                   resultLength,
+                            UErrorCode*               status);
+
+/**
+ * Determine if a UCalendar is currently in daylight savings time.
+ * Daylight savings time is not used in all parts of the world.
+ * @param cal The UCalendar to query.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return TRUE if cal is currently in daylight savings time, FALSE otherwise
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2 
+ucal_inDaylightTime(const UCalendar*  cal,
+                    UErrorCode*       status );
+
+/**
+ * Sets the GregorianCalendar change date. This is the point when the switch from
+ * Julian dates to Gregorian dates occurred. Default is 00:00:00 local time, October
+ * 15, 1582. Previous to this time and date will be Julian dates.
+ *
+ * This function works only for Gregorian calendars. If the UCalendar is not
+ * an instance of a Gregorian calendar, then a U_UNSUPPORTED_ERROR
+ * error code is set.
+ *
+ * @param cal        The calendar object.
+ * @param date       The given Gregorian cutover date.
+ * @param pErrorCode Pointer to a standard ICU error code. Its input value must
+ *                   pass the U_SUCCESS() test, or else the function returns
+ *                   immediately. Check for U_FAILURE() on output or use with
+ *                   function chaining. (See User Guide for details.)
+ *
+ * @see GregorianCalendar::setGregorianChange
+ * @see ucal_getGregorianChange
+ * @stable ICU 3.6
+ */
+U_STABLE void U_EXPORT2
+ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode);
+
+/**
+ * Gets the Gregorian Calendar change date. This is the point when the switch from
+ * Julian dates to Gregorian dates occurred. Default is 00:00:00 local time, October
+ * 15, 1582. Previous to this time and date will be Julian dates.
+ *
+ * This function works only for Gregorian calendars. If the UCalendar is not
+ * an instance of a Gregorian calendar, then a U_UNSUPPORTED_ERROR
+ * error code is set.
+ *
+ * @param cal        The calendar object.
+ * @param pErrorCode Pointer to a standard ICU error code. Its input value must
+ *                   pass the U_SUCCESS() test, or else the function returns
+ *                   immediately. Check for U_FAILURE() on output or use with
+ *                   function chaining. (See User Guide for details.)
+ * @return   The Gregorian cutover time for this calendar.
+ *
+ * @see GregorianCalendar::getGregorianChange
+ * @see ucal_setGregorianChange
+ * @stable ICU 3.6
+ */
+U_STABLE UDate U_EXPORT2
+ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode);
+
+/**
+ * Types of UCalendar attributes 
+ * @stable ICU 2.0
+ */
+enum UCalendarAttribute {
+    /** Lenient parsing */
+  UCAL_LENIENT,
+  /** First day of week */
+  UCAL_FIRST_DAY_OF_WEEK,
+  /** Minimum number of days in first week */
+  UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarAttribute UCalendarAttribute;
+
+/**
+ * Get a numeric attribute associated with a UCalendar.
+ * Numeric attributes include the first day of the week, or the minimal numbers
+ * of days in the first week of the month.
+ * @param cal The UCalendar to query.
+ * @param attr The desired attribute; one of UCAL_LENIENT, UCAL_FIRST_DAY_OF_WEEK,
+ * or UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
+ * @return The value of attr.
+ * @see ucal_setAttribute
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucal_getAttribute(const UCalendar*    cal,
+                  UCalendarAttribute  attr);
+
+/**
+ * Set a numeric attribute associated with a UCalendar.
+ * Numeric attributes include the first day of the week, or the minimal numbers
+ * of days in the first week of the month.
+ * @param cal The UCalendar to set.
+ * @param attr The desired attribute; one of UCAL_LENIENT, UCAL_FIRST_DAY_OF_WEEK,
+ * or UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
+ * @param newValue The new value of attr.
+ * @see ucal_getAttribute
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_setAttribute(UCalendar*          cal,
+                  UCalendarAttribute  attr,
+                  int32_t             newValue);
+
+/**
+ * Get a locale for which calendars are available.
+ * A UCalendar in a locale returned by this function will contain the correct
+ * day and month names for the locale.
+ * @param localeIndex The index of the desired locale.
+ * @return A locale for which calendars are available, or 0 if none.
+ * @see ucal_countAvailable
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2 
+ucal_getAvailable(int32_t localeIndex);
+
+/**
+ * Determine how many locales have calendars available.
+ * This function is most useful as determining the loop ending condition for
+ * calls to \ref ucal_getAvailable.
+ * @return The number of locales for which calendars are available.
+ * @see ucal_getAvailable
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucal_countAvailable(void);
+
+/**
+ * Get a UCalendar's current time in millis.
+ * The time is represented as milliseconds from the epoch.
+ * @param cal The UCalendar to query.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return The calendar's current time in millis.
+ * @see ucal_setMillis
+ * @see ucal_setDate
+ * @see ucal_setDateTime
+ * @stable ICU 2.0
+ */
+U_STABLE UDate U_EXPORT2 
+ucal_getMillis(const UCalendar*  cal,
+               UErrorCode*       status);
+
+/**
+ * Set a UCalendar's current time in millis.
+ * The time is represented as milliseconds from the epoch.
+ * @param cal The UCalendar to set.
+ * @param dateTime The desired date and time.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucal_getMillis
+ * @see ucal_setDate
+ * @see ucal_setDateTime
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_setMillis(UCalendar*   cal,
+               UDate        dateTime,
+               UErrorCode*  status );
+
+/**
+ * Set a UCalendar's current date.
+ * The date is represented as a series of 32-bit integers.
+ * @param cal The UCalendar to set.
+ * @param year The desired year.
+ * @param month The desired month; one of UCAL_JANUARY, UCAL_FEBRUARY, UCAL_MARCH, UCAL_APRIL, UCAL_MAY,
+ * UCAL_JUNE, UCAL_JULY, UCAL_AUGUST, UCAL_SEPTEMBER, UCAL_OCTOBER, UCAL_NOVEMBER, UCAL_DECEMBER, UCAL_UNDECIMBER
+ * @param date The desired day of the month.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucal_getMillis
+ * @see ucal_setMillis
+ * @see ucal_setDateTime
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_setDate(UCalendar*   cal,
+             int32_t      year,
+             int32_t      month,
+             int32_t      date,
+             UErrorCode*  status);
+
+/**
+ * Set a UCalendar's current date.
+ * The date is represented as a series of 32-bit integers.
+ * @param cal The UCalendar to set.
+ * @param year The desired year.
+ * @param month The desired month; one of UCAL_JANUARY, UCAL_FEBRUARY, UCAL_MARCH, UCAL_APRIL, UCAL_MAY,
+ * UCAL_JUNE, UCAL_JULY, UCAL_AUGUST, UCAL_SEPTEMBER, UCAL_OCTOBER, UCAL_NOVEMBER, UCAL_DECEMBER, UCAL_UNDECIMBER
+ * @param date The desired day of the month.
+ * @param hour The desired hour of day.
+ * @param minute The desired minute.
+ * @param second The desirec second.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucal_getMillis
+ * @see ucal_setMillis
+ * @see ucal_setDate
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_setDateTime(UCalendar*   cal,
+                 int32_t      year,
+                 int32_t      month,
+                 int32_t      date,
+                 int32_t      hour,
+                 int32_t      minute,
+                 int32_t      second,
+                 UErrorCode*  status);
+
+/**
+ * Returns TRUE if two UCalendars are equivalent.  Equivalent
+ * UCalendars will behave identically, but they may be set to
+ * different times.
+ * @param cal1 The first of the UCalendars to compare.
+ * @param cal2 The second of the UCalendars to compare.
+ * @return TRUE if cal1 and cal2 are equivalent, FALSE otherwise.
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2 
+ucal_equivalentTo(const UCalendar*  cal1,
+                  const UCalendar*  cal2);
+
+/**
+ * Add a specified signed amount to a particular field in a UCalendar.
+ * This can modify more significant fields in the calendar.
+ * @param cal The UCalendar to which to add.
+ * @param field The field to which to add the signed value; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @param amount The signed amount to add to field. If the amount causes the value
+ * to exceed to maximum or minimum values for that field, other fields are modified
+ * to preserve the magnitude of the change.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucal_roll
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_add(UCalendar*           cal,
+         UCalendarDateFields  field,
+         int32_t              amount,
+         UErrorCode*          status);
+
+/**
+ * Add a specified signed amount to a particular field in a UCalendar.
+ * This will not modify more significant fields in the calendar.
+ * @param cal The UCalendar to which to add.
+ * @param field The field to which to add the signed value; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @param amount The signed amount to add to field. If the amount causes the value
+ * to exceed to maximum or minimum values for that field, the field is pinned to a permissible
+ * value.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucal_add
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_roll(UCalendar*           cal,
+          UCalendarDateFields  field,
+          int32_t              amount,
+          UErrorCode*          status);
+
+/**
+ * Get the current value of a field from a UCalendar.
+ * All fields are represented as 32-bit integers.
+ * @param cal The UCalendar to query.
+ * @param field The desired field; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return The value of the desired field.
+ * @see ucal_set
+ * @see ucal_isSet
+ * @see ucal_clearField
+ * @see ucal_clear
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucal_get(const UCalendar*     cal,
+         UCalendarDateFields  field,
+         UErrorCode*          status );
+
+/**
+ * Set the value of a field in a UCalendar.
+ * All fields are represented as 32-bit integers.
+ * @param cal The UCalendar to set.
+ * @param field The field to set; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @param value The desired value of field.
+ * @see ucal_get
+ * @see ucal_isSet
+ * @see ucal_clearField
+ * @see ucal_clear
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_set(UCalendar*           cal,
+         UCalendarDateFields  field,
+         int32_t              value);
+
+/**
+ * Determine if a field in a UCalendar is set.
+ * All fields are represented as 32-bit integers.
+ * @param cal The UCalendar to query.
+ * @param field The desired field; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @return TRUE if field is set, FALSE otherwise.
+ * @see ucal_get
+ * @see ucal_set
+ * @see ucal_clearField
+ * @see ucal_clear
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2 
+ucal_isSet(const UCalendar*     cal,
+           UCalendarDateFields  field);
+
+/**
+ * Clear a field in a UCalendar.
+ * All fields are represented as 32-bit integers.
+ * @param cal The UCalendar containing the field to clear.
+ * @param field The field to clear; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @see ucal_get
+ * @see ucal_set
+ * @see ucal_isSet
+ * @see ucal_clear
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_clearField(UCalendar*           cal,
+                UCalendarDateFields  field);
+
+/**
+ * Clear all fields in a UCalendar.
+ * All fields are represented as 32-bit integers.
+ * @param calendar The UCalendar to clear.
+ * @see ucal_get
+ * @see ucal_set
+ * @see ucal_isSet
+ * @see ucal_clearField
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+ucal_clear(UCalendar* calendar);
+
+/**
+ * Possible limit values for a UCalendar 
+ * @stable ICU 2.0
+ */
+enum UCalendarLimitType {
+  /** Minimum value */
+  UCAL_MINIMUM,
+  /** Maximum value */
+  UCAL_MAXIMUM,
+  /** Greatest minimum value */
+  UCAL_GREATEST_MINIMUM,
+  /** Leaest maximum value */
+  UCAL_LEAST_MAXIMUM,
+  /** Actual minimum value */
+  UCAL_ACTUAL_MINIMUM,
+  /** Actual maximum value */
+  UCAL_ACTUAL_MAXIMUM
+};
+
+/** @stable ICU 2.0 */
+typedef enum UCalendarLimitType UCalendarLimitType;
+
+/**
+ * Determine a limit for a field in a UCalendar.
+ * A limit is a maximum or minimum value for a field.
+ * @param cal The UCalendar to query.
+ * @param field The desired field; one of UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
+ * UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_DATE, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK,
+ * UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND,
+ * UCAL_MILLISECOND, UCAL_ZONE_OFFSET, UCAL_DST_OFFSET.
+ * @param type The desired critical point; one of UCAL_MINIMUM, UCAL_MAXIMUM, UCAL_GREATEST_MINIMUM,
+ * UCAL_LEAST_MAXIMUM, UCAL_ACTUAL_MINIMUM, UCAL_ACTUAL_MAXIMUM
+ * @param status A pointer to an UErrorCode to receive any errors.
+ * @return The requested value.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+ucal_getLimit(const UCalendar*     cal,
+              UCalendarDateFields  field,
+              UCalendarLimitType   type,
+              UErrorCode*          status);
+
+/** Get the locale for this calendar object. You can choose between valid and actual locale.
+ *  @param cal The calendar object
+ *  @param type type of the locale we're looking for (valid or actual) 
+ *  @param status error code for the operation
+ *  @return the locale name
+ *  @stable ICU 2.8
+ */
+U_STABLE const char * U_EXPORT2
+ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status);
+
+/**
+ * Returns the timezone data version currently used by ICU.
+ * @param status error code for the operation
+ * @return the version string, such as "2007f"
+ * @stable ICU 3.8
+ */
+U_STABLE const char * U_EXPORT2
+ucal_getTZDataVersion(UErrorCode* status);
+
+/**
+ * Returns the canonical system timezone ID or the normalized
+ * custom time zone ID for the given time zone ID.
+ * @param id        The input timezone ID to be canonicalized.
+ * @param len       The length of id, or -1 if null-terminated.
+ * @param result    The buffer receives the canonical system timezone ID
+ *                  or the custom timezone ID in normalized format.
+ * @param resultCapacity    The capacity of the result buffer.
+ * @param isSystemID        Receives if the given ID is a known system
+     *                      timezone ID.
+ * @param status    Recevies the status.  When the given timezone ID
+ *                  is neither a known system time zone ID nor a
+ *                  valid custom timezone ID, U_ILLEGAL_ARGUMENT_ERROR
+ *                  is set.
+ * @return          The result string length, not including the terminating
+ *                  null.
+ * @stable ICU 4.0
+ */
+U_STABLE int32_t U_EXPORT2
+ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len,
+                            UChar* result, int32_t resultCapacity, UBool *isSystemID, UErrorCode* status);
+/**
+ * Get the resource keyword value string designating the calendar type for the UCalendar.
+ * @param cal The UCalendar to query.
+ * @param status The error code for the operation.
+ * @return The resource keyword value string.
+ * @stable ICU 4.2
+ */
+U_STABLE const char * U_EXPORT2
+ucal_getType(const UCalendar *cal, UErrorCode* status);
+
+/**
+ * Given a key and a locale, returns an array of string values in a preferred
+ * order that would make a difference. These are all and only those values where
+ * the open (creation) of the service with the locale formed from the input locale
+ * plus input keyword and that value has different behavior than creation with the
+ * input locale alone.
+ * @param key           one of the keys supported by this service.  For now, only
+ *                      "calendar" is supported.
+ * @param locale        the locale
+ * @param commonlyUsed  if set to true it will return only commonly used values
+ *                      with the given locale in preferred order.  Otherwise,
+ *                      it will return all the available values for the locale.
+ * @param status error status
+ * @return a string enumeration over keyword values for the given key and the locale.
+ * @stable ICU 4.2
+ */
+U_STABLE UEnumeration* U_EXPORT2
+ucal_getKeywordValuesForLocale(const char* key,
+                               const char* locale,
+                               UBool commonlyUsed,
+                               UErrorCode* status);
+
+
+/** Weekday types, as returned by ucal_getDayOfWeekType().
+ * @stable ICU 4.4
+ */
+enum UCalendarWeekdayType {
+  /**
+   * Designates a full weekday (no part of the day is included in the weekend).
+   * @stable ICU 4.4 
+   */
+  UCAL_WEEKDAY,
+  /**
+   * Designates a full weekend day (the entire day is included in the weekend).
+   * @stable ICU 4.4 
+   */
+  UCAL_WEEKEND,
+  /**
+   * Designates a day that starts as a weekday and transitions to the weekend.
+   * Call ucal_getWeekendTransition() to get the time of transition.
+   * @stable ICU 4.4 
+   */
+  UCAL_WEEKEND_ONSET,
+  /**
+   * Designates a day that starts as the weekend and transitions to a weekday.
+   * Call ucal_getWeekendTransition() to get the time of transition.
+   * @stable ICU 4.4 
+   */
+  UCAL_WEEKEND_CEASE
+};
+
+/** @stable ICU 4.4 */
+typedef enum UCalendarWeekdayType UCalendarWeekdayType;
+
+/**
+ * Returns whether the given day of the week is a weekday, a
+ * weekend day, or a day that transitions from one to the other,
+ * in this calendar system. If a transition occurs at midnight,
+ * then the days before and after the transition will have the
+ * type UCAL_WEEKDAY or UCAL_WEEKEND. If a transition occurs at a time
+ * other than midnight, then the day of the transition will have
+ * the type UCAL_WEEKEND_ONSET or UCAL_WEEKEND_CEASE. In this case, the
+ * method getWeekendTransition() will return the point of
+ * transition.
+ * @param cal The UCalendar to query.
+ * @param dayOfWeek The day of the week whose type is desired (UCAL_SUNDAY..UCAL_SATURDAY).
+ * @param status The error code for the operation.
+ * @return The UCalendarWeekdayType for the day of the week.
+ * @stable ICU 4.4
+ */
+U_STABLE UCalendarWeekdayType U_EXPORT2
+ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status);
+
+/**
+ * Returns the time during the day at which the weekend begins or ends in
+ * this calendar system.  If ucal_getDayOfWeekType() rerturns UCAL_WEEKEND_ONSET
+ * for the specified dayOfWeek, return the time at which the weekend begins.
+ * If ucal_getDayOfWeekType() returns UCAL_WEEKEND_CEASE for the specified dayOfWeek,
+ * return the time at which the weekend ends. If ucal_getDayOfWeekType() returns
+ * some other UCalendarWeekdayType for the specified dayOfWeek, is it an error condition
+ * (U_ILLEGAL_ARGUMENT_ERROR).
+ * @param cal The UCalendar to query.
+ * @param dayOfWeek The day of the week for which the weekend transition time is
+ * desired (UCAL_SUNDAY..UCAL_SATURDAY).
+ * @param status The error code for the operation.
+ * @return The milliseconds after midnight at which the weekend begins or ends.
+ * @stable ICU 4.4
+ */
+U_STABLE int32_t U_EXPORT2
+ucal_getWeekendTransition(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode *status);
+
+/**
+ * Returns TRUE if the given UDate is in the weekend in
+ * this calendar system.
+ * @param cal The UCalendar to query.
+ * @param date The UDate in question.
+ * @param status The error code for the operation.
+ * @return TRUE if the given UDate is in the weekend in
+ * this calendar system, FALSE otherwise.
+ * @stable ICU 4.4
+ */
+U_STABLE UBool U_EXPORT2
+ucal_isWeekend(const UCalendar *cal, UDate date, UErrorCode *status);
+
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Source/JavaScriptCore/icu/unicode/udat.h b/Source/JavaScriptCore/icu/unicode/udat.h
new file mode 100644 (file)
index 0000000..d480c7d
--- /dev/null
@@ -0,0 +1,997 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2010, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *******************************************************************************
+*/
+
+#ifndef UDAT_H
+#define UDAT_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/localpointer.h"
+#include "unicode/ucal.h"
+#include "unicode/unum.h"
+/**
+ * \file
+ * \brief C API: DateFormat
+ *
+ * <h2> Date Format C API</h2>
+ *
+ * Date Format C API  consists of functions that convert dates and
+ * times from their internal representations to textual form and back again in a
+ * language-independent manner. Converting from the internal representation (milliseconds
+ * since midnight, January 1, 1970) to text is known as "formatting," and converting
+ * from text to millis is known as "parsing."  We currently define only one concrete
+ * structure UDateFormat, which can handle pretty much all normal
+ * date formatting and parsing actions.
+ * <P>
+ * Date Format helps you to format and parse dates for any locale. Your code can
+ * be completely independent of the locale conventions for months, days of the
+ * week, or even the calendar format: lunar vs. solar.
+ * <P>
+ * To format a date for the current Locale with default time and date style,
+ * use one of the static factory methods:
+ * <pre>
+ * \code
+ *  UErrorCode status = U_ZERO_ERROR;
+ *  UChar *myString;
+ *  int32_t myStrlen = 0;
+ *  UDateFormat* dfmt = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, -1, &status);
+ *  myStrlen = udat_format(dfmt, myDate, NULL, myStrlen, NULL, &status);
+ *  if (status==U_BUFFER_OVERFLOW_ERROR){
+ *      status=U_ZERO_ERROR;
+ *      myString=(UChar*)malloc(sizeof(UChar) * (myStrlen+1) );
+ *      udat_format(dfmt, myDate, myString, myStrlen+1, NULL, &status);
+ *  }
+ * \endcode
+ * </pre>
+ * If you are formatting multiple numbers, it is more efficient to get the
+ * format and use it multiple times so that the system doesn't have to fetch the
+ * information about the local language and country conventions multiple times.
+ * <pre>
+ * \code
+ *  UErrorCode status = U_ZERO_ERROR;
+ *  int32_t i, myStrlen = 0;
+ *  UChar* myString;
+ *  char buffer[1024];
+ *  UDate myDateArr[] = { 0.0, 100000000.0, 2000000000.0 }; // test values
+ *  UDateFormat* df = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, 0, &status);
+ *  for (i = 0; i < 3; i++) {
+ *      myStrlen = udat_format(df, myDateArr[i], NULL, myStrlen, NULL, &status);
+ *      if(status == U_BUFFER_OVERFLOW_ERROR){
+ *          status = U_ZERO_ERROR;
+ *          myString = (UChar*)malloc(sizeof(UChar) * (myStrlen+1) );
+ *          udat_format(df, myDateArr[i], myString, myStrlen+1, NULL, &status);
+ *          printf("%s\n", u_austrcpy(buffer, myString) );
+ *          free(myString);
+ *      }
+ *  }
+ * \endcode
+ * </pre>
+ * To get specific fields of a date, you can use UFieldPosition to
+ * get specific fields.
+ * <pre>
+ * \code
+ *  UErrorCode status = U_ZERO_ERROR;
+ *  UFieldPosition pos;
+ *  UChar *myString;
+ *  int32_t myStrlen = 0;
+ *  char buffer[1024];
+ *
+ *  pos.field = 1;  // Same as the DateFormat::EField enum
+ *  UDateFormat* dfmt = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, -1, NULL, 0, &status);
+ *  myStrlen = udat_format(dfmt, myDate, NULL, myStrlen, &pos, &status);
+ *  if (status==U_BUFFER_OVERFLOW_ERROR){
+ *      status=U_ZERO_ERROR;
+ *      myString=(UChar*)malloc(sizeof(UChar) * (myStrlen+1) );
+ *      udat_format(dfmt, myDate, myString, myStrlen+1, &pos, &status);
+ *  }
+ *  printf("date format: %s\n", u_austrcpy(buffer, myString));
+ *  buffer[pos.endIndex] = 0;   // NULL terminate the string.
+ *  printf("UFieldPosition position equals %s\n", &buffer[pos.beginIndex]);
+ * \endcode
+ * </pre>
+ * To format a date for a different Locale, specify it in the call to
+ * udat_open()
+ * <pre>
+ * \code
+ *        UDateFormat* df = udat_open(UDAT_SHORT, UDAT_SHORT, "fr_FR", NULL, -1, NULL, 0, &status);
+ * \endcode
+ * </pre>
+ * You can use a DateFormat API udat_parse() to parse.
+ * <pre>
+ * \code
+ *  UErrorCode status = U_ZERO_ERROR;
+ *  int32_t parsepos=0;
+ *  UDate myDate = udat_parse(df, myString, u_strlen(myString), &parsepos, &status);
+ * \endcode
+ * </pre>
+ *  You can pass in different options for the arguments for date and time style
+ *  to control the length of the result; from SHORT to MEDIUM to LONG to FULL.
+ *  The exact result depends on the locale, but generally:
+ *  see UDateFormatStyle for more details
+ * <ul type=round>
+ *   <li>   UDAT_SHORT is completely numeric, such as 12/13/52 or 3:30pm
+ *   <li>   UDAT_MEDIUM is longer, such as Jan 12, 1952
+ *   <li>   UDAT_LONG is longer, such as January 12, 1952 or 3:30:32pm
+ *   <li>   UDAT_FULL is pretty completely specified, such as
+ *          Tuesday, April 12, 1952 AD or 3:30:42pm PST.
+ * </ul>
+ * You can also set the time zone on the format if you wish.
+ * <P>
+ * You can also use forms of the parse and format methods with Parse Position and
+ * UFieldPosition to allow you to
+ * <ul type=round>
+ *   <li>   Progressively parse through pieces of a string.
+ *   <li>   Align any particular field, or find out where it is for selection
+ *          on the screen.
+ * </ul>
+ */
+
+/** A date formatter.
+ *  For usage in C programs.
+ *  @stable ICU 2.6
+ */
+typedef void* UDateFormat;
+
+/** The possible date/time format styles 
+ *  @stable ICU 2.6
+ */
+typedef enum UDateFormatStyle {
+    /** Full style */
+    UDAT_FULL,
+    /** Long style */
+    UDAT_LONG,
+    /** Medium style */
+    UDAT_MEDIUM,
+    /** Short style */
+    UDAT_SHORT,
+    /** Default style */
+    UDAT_DEFAULT = UDAT_MEDIUM,
+
+    /** Bitfield for relative date */
+    UDAT_RELATIVE = (1 << 7),
+    
+    UDAT_FULL_RELATIVE = UDAT_FULL | UDAT_RELATIVE,
+        
+    UDAT_LONG_RELATIVE = UDAT_LONG | UDAT_RELATIVE,
+    
+    UDAT_MEDIUM_RELATIVE = UDAT_MEDIUM | UDAT_RELATIVE,
+    
+    UDAT_SHORT_RELATIVE = UDAT_SHORT | UDAT_RELATIVE,
+    
+    
+    /** No style */
+    UDAT_NONE = -1,
+    /** for internal API use only */
+    UDAT_IGNORE = -2
+
+} UDateFormatStyle;
+
+
+/**
+ * @{
+ * Below are a set of pre-defined skeletons.
+ *
+ * <P>
+ * A skeleton 
+ * <ol>
+ * <li>
+ *    only keeps the field pattern letter and ignores all other parts 
+ *    in a pattern, such as space, punctuations, and string literals.
+ * </li>
+ * <li>
+ *    hides the order of fields. 
+ * </li>
+ * <li>
+ *    might hide a field's pattern letter length.
+ *
+ *    For those non-digit calendar fields, the pattern letter length is 
+ *    important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 
+ *    and the field's pattern letter length is honored.
+ *    
+ *    For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy, 
+ *    the field pattern length is ignored and the best match, which is defined 
+ *    in date time patterns, will be returned without honor the field pattern
+ *    letter length in skeleton.
+ * </li>
+ * </ol>
+ *
+ * @stable ICU 4.0
+ */
+
+#define UDAT_MINUTE_SECOND              "ms"
+#define UDAT_HOUR24_MINUTE              "Hm"
+#define UDAT_HOUR24_MINUTE_SECOND       "Hms"      
+#define UDAT_HOUR_MINUTE_SECOND         "hms"
+#define UDAT_STANDALONE_MONTH           "LLLL"
+#define UDAT_ABBR_STANDALONE_MONTH      "LLL"
+#define UDAT_YEAR_QUARTER               "yQQQ"
+#define UDAT_YEAR_ABBR_QUARTER          "yQ"
+
+/** @} */
+
+/**
+ * @{
+ * Below are a set of pre-defined skeletons that 
+ * have pre-defined interval patterns in resource files.
+ * Users are encouraged to use them in date interval format factory methods.
+ * 
+ * @stable ICU 4.0
+ */
+#define UDAT_HOUR_MINUTE                "hm"
+#define UDAT_YEAR                       "y"
+#define UDAT_DAY                        "d"
+#define UDAT_NUM_MONTH_WEEKDAY_DAY      "MEd"
+#define UDAT_YEAR_NUM_MONTH             "yM"              
+#define UDAT_NUM_MONTH_DAY              "Md"
+#define UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY "yMEd"
+#define UDAT_ABBR_MONTH_WEEKDAY_DAY     "MMMEd"
+#define UDAT_YEAR_MONTH                 "yMMMM"
+#define UDAT_YEAR_ABBR_MONTH            "yMMM"
+#define UDAT_MONTH_DAY                  "MMMMd"
+#define UDAT_ABBR_MONTH_DAY             "MMMd" 
+#define UDAT_MONTH_WEEKDAY_DAY          "MMMMEEEEd"
+#define UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY "yMMMEd" 
+#define UDAT_YEAR_MONTH_WEEKDAY_DAY     "yMMMMEEEEd"
+#define UDAT_YEAR_MONTH_DAY             "yMMMMd"
+#define UDAT_YEAR_ABBR_MONTH_DAY        "yMMMd"
+#define UDAT_YEAR_NUM_MONTH_DAY         "yMd"
+#define UDAT_NUM_MONTH                  "M"
+#define UDAT_ABBR_MONTH                 "MMM"
+#define UDAT_MONTH                      "MMMM"
+#define UDAT_HOUR_MINUTE_GENERIC_TZ     "hmv"
+#define UDAT_HOUR_MINUTE_TZ             "hmz"
+#define UDAT_HOUR                       "h"
+#define UDAT_HOUR_GENERIC_TZ            "hv"
+#define UDAT_HOUR_TZ                    "hz"
+
+/** @} */
+
+
+/**
+ * FieldPosition and UFieldPosition selectors for format fields
+ * defined by DateFormat and UDateFormat.
+ * @stable ICU 3.0
+ */
+typedef enum UDateFormatField {
+    /**
+     * FieldPosition and UFieldPosition selector for 'G' field alignment,
+     * corresponding to the UCAL_ERA field.
+     * @stable ICU 3.0
+     */
+    UDAT_ERA_FIELD = 0,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'y' field alignment,
+     * corresponding to the UCAL_YEAR field.
+     * @stable ICU 3.0
+     */
+    UDAT_YEAR_FIELD = 1,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'M' field alignment,
+     * corresponding to the UCAL_MONTH field.
+     * @stable ICU 3.0
+     */
+    UDAT_MONTH_FIELD = 2,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'd' field alignment,
+     * corresponding to the UCAL_DATE field.
+     * @stable ICU 3.0
+     */
+    UDAT_DATE_FIELD = 3,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'k' field alignment,
+     * corresponding to the UCAL_HOUR_OF_DAY field.
+     * UDAT_HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
+     * For example, 23:59 + 01:00 results in 24:59.
+     * @stable ICU 3.0
+     */
+    UDAT_HOUR_OF_DAY1_FIELD = 4,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'H' field alignment,
+     * corresponding to the UCAL_HOUR_OF_DAY field.
+     * UDAT_HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
+     * For example, 23:59 + 01:00 results in 00:59.
+     * @stable ICU 3.0
+     */
+    UDAT_HOUR_OF_DAY0_FIELD = 5,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'm' field alignment,
+     * corresponding to the UCAL_MINUTE field.
+     * @stable ICU 3.0
+     */
+    UDAT_MINUTE_FIELD = 6,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 's' field alignment,
+     * corresponding to the UCAL_SECOND field.
+     * @stable ICU 3.0
+     */
+    UDAT_SECOND_FIELD = 7,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'S' field alignment,
+     * corresponding to the UCAL_MILLISECOND field.
+     * @stable ICU 3.0
+     */
+    UDAT_FRACTIONAL_SECOND_FIELD = 8,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'E' field alignment,
+     * corresponding to the UCAL_DAY_OF_WEEK field.
+     * @stable ICU 3.0
+     */
+    UDAT_DAY_OF_WEEK_FIELD = 9,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'D' field alignment,
+     * corresponding to the UCAL_DAY_OF_YEAR field.
+     * @stable ICU 3.0
+     */
+    UDAT_DAY_OF_YEAR_FIELD = 10,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'F' field alignment,
+     * corresponding to the UCAL_DAY_OF_WEEK_IN_MONTH field.
+     * @stable ICU 3.0
+     */
+    UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'w' field alignment,
+     * corresponding to the UCAL_WEEK_OF_YEAR field.
+     * @stable ICU 3.0
+     */
+    UDAT_WEEK_OF_YEAR_FIELD = 12,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'W' field alignment,
+     * corresponding to the UCAL_WEEK_OF_MONTH field.
+     * @stable ICU 3.0
+     */
+    UDAT_WEEK_OF_MONTH_FIELD = 13,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'a' field alignment,
+     * corresponding to the UCAL_AM_PM field.
+     * @stable ICU 3.0
+     */
+    UDAT_AM_PM_FIELD = 14,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'h' field alignment,
+     * corresponding to the UCAL_HOUR field.
+     * UDAT_HOUR1_FIELD is used for the one-based 12-hour clock.
+     * For example, 11:30 PM + 1 hour results in 12:30 AM.
+     * @stable ICU 3.0
+     */
+    UDAT_HOUR1_FIELD = 15,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'K' field alignment,
+     * corresponding to the UCAL_HOUR field.
+     * UDAT_HOUR0_FIELD is used for the zero-based 12-hour clock.
+     * For example, 11:30 PM + 1 hour results in 00:30 AM.
+     * @stable ICU 3.0
+     */
+    UDAT_HOUR0_FIELD = 16,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'z' field alignment,
+     * corresponding to the UCAL_ZONE_OFFSET and
+     * UCAL_DST_OFFSET fields.
+     * @stable ICU 3.0
+     */
+    UDAT_TIMEZONE_FIELD = 17,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'Y' field alignment,
+     * corresponding to the UCAL_YEAR_WOY field.
+     * @stable ICU 3.0
+     */
+    UDAT_YEAR_WOY_FIELD = 18,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'e' field alignment,
+     * corresponding to the UCAL_DOW_LOCAL field.
+     * @stable ICU 3.0
+     */
+    UDAT_DOW_LOCAL_FIELD = 19,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'u' field alignment,
+     * corresponding to the UCAL_EXTENDED_YEAR field.
+     * @stable ICU 3.0
+     */
+    UDAT_EXTENDED_YEAR_FIELD = 20,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'g' field alignment,
+     * corresponding to the UCAL_JULIAN_DAY field.
+     * @stable ICU 3.0
+     */
+    UDAT_JULIAN_DAY_FIELD = 21,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'A' field alignment,
+     * corresponding to the UCAL_MILLISECONDS_IN_DAY field.
+     * @stable ICU 3.0
+     */
+    UDAT_MILLISECONDS_IN_DAY_FIELD = 22,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'Z' field alignment,
+     * corresponding to the UCAL_ZONE_OFFSET and
+     * UCAL_DST_OFFSET fields.
+     * @stable ICU 3.0
+     */
+    UDAT_TIMEZONE_RFC_FIELD = 23,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'v' field alignment,
+     * corresponding to the UCAL_ZONE_OFFSET field.
+     * @stable ICU 3.4
+     */
+    UDAT_TIMEZONE_GENERIC_FIELD = 24,
+    /**
+     * FieldPosition selector for 'c' field alignment,
+     * corresponding to the {@link #UCAL_DOW_LOCAL} field.
+     * This displays the stand alone day name, if available.
+     * @stable ICU 3.4
+     */
+    UDAT_STANDALONE_DAY_FIELD = 25,
+
+    /**
+     * FieldPosition selector for 'L' field alignment,
+     * corresponding to the {@link #UCAL_MONTH} field.
+     * This displays the stand alone month name, if available.
+     * @stable ICU 3.4
+     */
+    UDAT_STANDALONE_MONTH_FIELD = 26,
+
+    /**
+     * FieldPosition selector for "Q" field alignment,
+     * corresponding to quarters. This is implemented
+     * using the {@link #UCAL_MONTH} field. This
+     * displays the quarter.
+     * @stable ICU 3.6
+     */
+    UDAT_QUARTER_FIELD = 27,
+
+    /**
+     * FieldPosition selector for the "q" field alignment,
+     * corresponding to stand-alone quarters. This is
+     * implemented using the {@link #UCAL_MONTH} field.
+     * This displays the stand-alone quarter.
+     * @stable ICU 3.6
+     */
+    UDAT_STANDALONE_QUARTER_FIELD = 28,
+
+    /**
+     * FieldPosition and UFieldPosition selector for 'V' field alignment,
+     * corresponding to the UCAL_ZONE_OFFSET field.
+     * @stable ICU 3.8
+     */
+    UDAT_TIMEZONE_SPECIAL_FIELD = 29,
+
+   /**
+     * Number of FieldPosition and UFieldPosition selectors for
+     * DateFormat and UDateFormat.
+     * Valid selectors range from 0 to UDAT_FIELD_COUNT-1.
+     * This value is subject to change if new fields are defined
+     * in the future.
+     * @stable ICU 3.0
+     */
+    UDAT_FIELD_COUNT = 30
+
+} UDateFormatField;
+
+
+/**
+ * Maps from a UDateFormatField to the corresponding UCalendarDateFields.
+ * Note: since the mapping is many-to-one, there is no inverse mapping.
+ * @param field the UDateFormatField.
+ * @return the UCalendarDateField.  This will be UCAL_FIELD_COUNT in case
+ * of error (e.g., the input field is UDAT_FIELD_COUNT).
+ * @stable ICU 4.4
+ */
+U_STABLE UCalendarDateFields U_EXPORT2
+udat_toCalendarDateField(UDateFormatField field);
+
+
+/**
+ * Open a new UDateFormat for formatting and parsing dates and times.
+ * A UDateFormat may be used to format dates in calls to {@link #udat_format },
+ * and to parse dates in calls to {@link #udat_parse }.
+ * @param timeStyle The style used to format times; one of UDAT_FULL, UDAT_LONG,
+ * UDAT_MEDIUM, UDAT_SHORT, UDAT_DEFAULT, or UDAT_NONE (relative time styles
+ * are not currently supported)
+ * @param dateStyle The style used to format dates; one of UDAT_FULL, UDAT_LONG,
+ * UDAT_MEDIUM, UDAT_SHORT, UDAT_DEFAULT, UDAT_FULL_RELATIVE, UDAT_LONG_RELATIVE,
+ * UDAT_MEDIUM_RELATIVE, UDAT_SHORT_RELATIVE, or UDAT_NONE
+ * @param locale The locale specifying the formatting conventions
+ * @param tzID A timezone ID specifying the timezone to use.  If 0, use
+ * the default timezone.
+ * @param tzIDLength The length of tzID, or -1 if null-terminated.
+ * @param pattern A pattern specifying the format to use.
+ * @param patternLength The number of characters in the pattern, or -1 if null-terminated.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return A pointer to a UDateFormat to use for formatting dates and times, or 0 if
+ * an error occurred.
+ * @stable ICU 2.0
+ */
+U_STABLE UDateFormat* U_EXPORT2 
+udat_open(UDateFormatStyle  timeStyle,
+          UDateFormatStyle  dateStyle,
+          const char        *locale,
+          const UChar       *tzID,
+          int32_t           tzIDLength,
+          const UChar       *pattern,
+          int32_t           patternLength,
+          UErrorCode        *status);
+
+
+/**
+* Close a UDateFormat.
+* Once closed, a UDateFormat may no longer be used.
+* @param format The formatter to close.
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_close(UDateFormat* format);
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUDateFormatPointer
+ * "Smart pointer" class, closes a UDateFormat via udat_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 4.4
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUDateFormatPointer, UDateFormat, udat_close);
+
+U_NAMESPACE_END
+
+#endif
+
+/**
+ * Open a copy of a UDateFormat.
+ * This function performs a deep copy.
+ * @param fmt The format to copy
+ * @param status A pointer to an UErrorCode to receive any errors.
+ * @return A pointer to a UDateFormat identical to fmt.
+ * @stable ICU 2.0
+ */
+U_STABLE UDateFormat* U_EXPORT2 
+udat_clone(const UDateFormat *fmt,
+       UErrorCode *status);
+
+/**
+* Format a date using an UDateFormat.
+* The date will be formatted using the conventions specified in {@link #udat_open }
+* @param format The formatter to use
+* @param dateToFormat The date to format
+* @param result A pointer to a buffer to receive the formatted number.
+* @param resultLength The maximum size of result.
+* @param position A pointer to a UFieldPosition.  On input, position->field
+* is read.  On output, position->beginIndex and position->endIndex indicate
+* the beginning and ending indices of field number position->field, if such
+* a field exists.  This parameter may be NULL, in which case no field
+* position data is returned.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see udat_parse
+* @see UFieldPosition
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+udat_format(    const    UDateFormat*    format,
+                        UDate           dateToFormat,
+                        UChar*          result,
+                        int32_t         resultLength,
+                        UFieldPosition* position,
+                        UErrorCode*     status);
+
+/**
+* Parse a string into an date/time using a UDateFormat.
+* The date will be parsed using the conventions specified in {@link #udat_open }
+* @param format The formatter to use.
+* @param text The text to parse.
+* @param textLength The length of text, or -1 if null-terminated.
+* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which
+* to begin parsing.  If not 0, on output the offset at which parsing ended.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The value of the parsed date/time
+* @see udat_format
+* @stable ICU 2.0
+*/
+U_STABLE UDate U_EXPORT2 
+udat_parse(    const    UDateFormat*    format,
+            const    UChar*          text,
+                    int32_t         textLength,
+                    int32_t         *parsePos,
+                    UErrorCode      *status);
+
+/**
+* Parse a string into an date/time using a UDateFormat.
+* The date will be parsed using the conventions specified in {@link #udat_open }
+* @param format The formatter to use.
+* @param calendar The calendar in which to store the parsed data.
+* @param text The text to parse.
+* @param textLength The length of text, or -1 if null-terminated.
+* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which
+* to begin parsing.  If not 0, on output the offset at which parsing ended.
+* @param status A pointer to an UErrorCode to receive any errors
+* @see udat_format
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_parseCalendar(const    UDateFormat*    format,
+                            UCalendar*      calendar,
+                   const    UChar*          text,
+                            int32_t         textLength,
+                            int32_t         *parsePos,
+                            UErrorCode      *status);
+
+/**
+* Determine if an UDateFormat will perform lenient parsing.
+* With lenient parsing, the parser may use heuristics to interpret inputs that do not
+* precisely match the pattern. With strict parsing, inputs must match the pattern.
+* @param fmt The formatter to query
+* @return TRUE if fmt is set to perform lenient parsing, FALSE otherwise.
+* @see udat_setLenient
+* @stable ICU 2.0
+*/
+U_STABLE UBool U_EXPORT2 
+udat_isLenient(const UDateFormat* fmt);
+
+/**
+* Specify whether an UDateFormat will perform lenient parsing.
+* With lenient parsing, the parser may use heuristics to interpret inputs that do not
+* precisely match the pattern. With strict parsing, inputs must match the pattern.
+* @param fmt The formatter to set
+* @param isLenient TRUE if fmt should perform lenient parsing, FALSE otherwise.
+* @see dat_isLenient
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_setLenient(    UDateFormat*    fmt,
+                    UBool          isLenient);
+
+/**
+* Get the UCalendar associated with an UDateFormat.
+* A UDateFormat uses a UCalendar to convert a raw value to, for example,
+* the day of the week.
+* @param fmt The formatter to query.
+* @return A pointer to the UCalendar used by fmt.
+* @see udat_setCalendar
+* @stable ICU 2.0
+*/
+U_STABLE const UCalendar* U_EXPORT2 
+udat_getCalendar(const UDateFormat* fmt);
+
+/**
+* Set the UCalendar associated with an UDateFormat.
+* A UDateFormat uses a UCalendar to convert a raw value to, for example,
+* the day of the week.
+* @param fmt The formatter to set.
+* @param calendarToSet A pointer to an UCalendar to be used by fmt.
+* @see udat_setCalendar
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_setCalendar(            UDateFormat*    fmt,
+                    const   UCalendar*      calendarToSet);
+
+/**
+* Get the UNumberFormat associated with an UDateFormat.
+* A UDateFormat uses a UNumberFormat to format numbers within a date,
+* for example the day number.
+* @param fmt The formatter to query.
+* @return A pointer to the UNumberFormat used by fmt to format numbers.
+* @see udat_setNumberFormat
+* @stable ICU 2.0
+*/
+U_STABLE const UNumberFormat* U_EXPORT2 
+udat_getNumberFormat(const UDateFormat* fmt);
+
+/**
+* Set the UNumberFormat associated with an UDateFormat.
+* A UDateFormat uses a UNumberFormat to format numbers within a date,
+* for example the day number.
+* @param fmt The formatter to set.
+* @param numberFormatToSet A pointer to the UNumberFormat to be used by fmt to format numbers.
+* @see udat_getNumberFormat
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_setNumberFormat(            UDateFormat*    fmt,
+                        const   UNumberFormat*  numberFormatToSet);
+
+/**
+* Get a locale for which date/time formatting patterns are available.
+* A UDateFormat in a locale returned by this function will perform the correct
+* formatting and parsing for the locale.
+* @param localeIndex The index of the desired locale.
+* @return A locale for which date/time formatting patterns are available, or 0 if none.
+* @see udat_countAvailable
+* @stable ICU 2.0
+*/
+U_STABLE const char* U_EXPORT2 
+udat_getAvailable(int32_t localeIndex);
+
+/**
+* Determine how many locales have date/time  formatting patterns available.
+* This function is most useful as determining the loop ending condition for
+* calls to {@link #udat_getAvailable }.
+* @return The number of locales for which date/time formatting patterns are available.
+* @see udat_getAvailable
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+udat_countAvailable(void);
+
+/**
+* Get the year relative to which all 2-digit years are interpreted.
+* For example, if the 2-digit start year is 2100, the year 99 will be
+* interpreted as 2199.
+* @param fmt The formatter to query.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The year relative to which all 2-digit years are interpreted.
+* @see udat_Set2DigitYearStart
+* @stable ICU 2.0
+*/
+U_STABLE UDate U_EXPORT2 
+udat_get2DigitYearStart(    const   UDateFormat     *fmt,
+                                    UErrorCode      *status);
+
+/**
+* Set the year relative to which all 2-digit years will be interpreted.
+* For example, if the 2-digit start year is 2100, the year 99 will be
+* interpreted as 2199.
+* @param fmt The formatter to set.
+* @param d The year relative to which all 2-digit years will be interpreted.
+* @param status A pointer to an UErrorCode to receive any errors
+* @see udat_Set2DigitYearStart
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_set2DigitYearStart(    UDateFormat     *fmt,
+                            UDate           d,
+                            UErrorCode      *status);
+
+/**
+* Extract the pattern from a UDateFormat.
+* The pattern will follow the pattern syntax rules.
+* @param fmt The formatter to query.
+* @param localized TRUE if the pattern should be localized, FALSE otherwise.
+* @param result A pointer to a buffer to receive the pattern.
+* @param resultLength The maximum size of result.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see udat_applyPattern
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+udat_toPattern(    const   UDateFormat     *fmt,
+                        UBool          localized,
+                        UChar           *result,
+                        int32_t         resultLength,
+                        UErrorCode      *status);
+
+/**
+* Set the pattern used by an UDateFormat.
+* The pattern should follow the pattern syntax rules.
+* @param format The formatter to set.
+* @param localized TRUE if the pattern is localized, FALSE otherwise.
+* @param pattern The new pattern
+* @param patternLength The length of pattern, or -1 if null-terminated.
+* @see udat_toPattern
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_applyPattern(            UDateFormat     *format,
+                            UBool          localized,
+                    const   UChar           *pattern,
+                            int32_t         patternLength);
+
+/** 
+ * The possible types of date format symbols 
+ * @stable ICU 2.6
+ */
+typedef enum UDateFormatSymbolType {
+    /** The era names, for example AD */
+    UDAT_ERAS,
+    /** The month names, for example February */
+    UDAT_MONTHS,
+    /** The short month names, for example Feb. */
+    UDAT_SHORT_MONTHS,
+    /** The weekday names, for example Monday */
+    UDAT_WEEKDAYS,
+    /** The short weekday names, for example Mon. */
+    UDAT_SHORT_WEEKDAYS,
+    /** The AM/PM names, for example AM */
+    UDAT_AM_PMS,
+    /** The localized characters */
+    UDAT_LOCALIZED_CHARS,
+    /** The long era names, for example Anno Domini */
+    UDAT_ERA_NAMES,
+    /** The narrow month names, for example F */
+    UDAT_NARROW_MONTHS,
+    /** The narrow weekday names, for example N */
+    UDAT_NARROW_WEEKDAYS,
+    /** Standalone context versions of months */
+    UDAT_STANDALONE_MONTHS,
+    UDAT_STANDALONE_SHORT_MONTHS,
+    UDAT_STANDALONE_NARROW_MONTHS,
+    /** Standalone context versions of weekdays */
+    UDAT_STANDALONE_WEEKDAYS,
+    UDAT_STANDALONE_SHORT_WEEKDAYS,
+    UDAT_STANDALONE_NARROW_WEEKDAYS,
+    /** The quarters, for example 1st Quarter */
+    UDAT_QUARTERS,
+    /** The short quarter names, for example Q1 */
+    UDAT_SHORT_QUARTERS,
+    /** Standalone context versions of quarters */
+    UDAT_STANDALONE_QUARTERS,
+    UDAT_STANDALONE_SHORT_QUARTERS
+
+} UDateFormatSymbolType;
+
+struct UDateFormatSymbols;
+/** Date format symbols.
+ *  For usage in C programs.
+ *  @stable ICU 2.6
+ */
+typedef struct UDateFormatSymbols UDateFormatSymbols;
+
+/**
+* Get the symbols associated with an UDateFormat.
+* The symbols are what a UDateFormat uses to represent locale-specific data,
+* for example month or day names.
+* @param fmt The formatter to query.
+* @param type The type of symbols to get.  One of UDAT_ERAS, UDAT_MONTHS, UDAT_SHORT_MONTHS,
+* UDAT_WEEKDAYS, UDAT_SHORT_WEEKDAYS, UDAT_AM_PMS, or UDAT_LOCALIZED_CHARS
+* @param symbolIndex The desired symbol of type type.
+* @param result A pointer to a buffer to receive the pattern.
+* @param resultLength The maximum size of result.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see udat_countSymbols
+* @see udat_setSymbols
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+udat_getSymbols(const   UDateFormat             *fmt,
+                        UDateFormatSymbolType   type,
+                        int32_t                 symbolIndex,
+                        UChar                   *result,
+                        int32_t                 resultLength,
+                        UErrorCode              *status);
+
+/**
+* Count the number of particular symbols for an UDateFormat.
+* This function is most useful as for detemining the loop termination condition
+* for calls to {@link #udat_getSymbols }.
+* @param fmt The formatter to query.
+* @param type The type of symbols to count.  One of UDAT_ERAS, UDAT_MONTHS, UDAT_SHORT_MONTHS,
+* UDAT_WEEKDAYS, UDAT_SHORT_WEEKDAYS, UDAT_AM_PMS, or UDAT_LOCALIZED_CHARS
+* @return The number of symbols of type type.
+* @see udat_getSymbols
+* @see udat_setSymbols
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+udat_countSymbols(    const    UDateFormat                *fmt,
+                            UDateFormatSymbolType    type);
+
+/**
+* Set the symbols associated with an UDateFormat.
+* The symbols are what a UDateFormat uses to represent locale-specific data,
+* for example month or day names.
+* @param format The formatter to set
+* @param type The type of symbols to set.  One of UDAT_ERAS, UDAT_MONTHS, UDAT_SHORT_MONTHS,
+* UDAT_WEEKDAYS, UDAT_SHORT_WEEKDAYS, UDAT_AM_PMS, or UDAT_LOCALIZED_CHARS
+* @param symbolIndex The index of the symbol to set of type type.
+* @param value The new value
+* @param valueLength The length of value, or -1 if null-terminated
+* @param status A pointer to an UErrorCode to receive any errors
+* @see udat_getSymbols
+* @see udat_countSymbols
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+udat_setSymbols(    UDateFormat             *format,
+                    UDateFormatSymbolType   type,
+                    int32_t                 symbolIndex,
+                    UChar                   *value,
+                    int32_t                 valueLength,
+                    UErrorCode              *status);
+
+/**
+ * Get the locale for this date format object.
+ * You can choose between valid and actual locale.
+ * @param fmt The formatter to get the locale from
+ * @param type type of the locale we're looking for (valid or actual) 
+ * @param status error code for the operation
+ * @return the locale name
+ * @stable ICU 2.8
+ */
+U_STABLE const char* U_EXPORT2
+udat_getLocaleByType(const UDateFormat *fmt,
+                     ULocDataLocaleType type,
+                     UErrorCode* status); 
+
+/**
+* Extract the date pattern from a UDateFormat set for relative date formatting.
+* The pattern will follow the pattern syntax rules.
+* @param fmt The formatter to query.
+* @param result A pointer to a buffer to receive the pattern.
+* @param resultLength The maximum size of result.
+* @param status A pointer to a UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see udat_applyPatternRelative
+* @internal ICU 4.2 technology preview
+*/
+U_INTERNAL int32_t U_EXPORT2 
+udat_toPatternRelativeDate(const UDateFormat *fmt,
+                           UChar             *result,
+                           int32_t           resultLength,
+                           UErrorCode        *status);
+
+/**
+* Extract the time pattern from a UDateFormat set for relative date formatting.
+* The pattern will follow the pattern syntax rules.
+* @param fmt The formatter to query.
+* @param result A pointer to a buffer to receive the pattern.
+* @param resultLength The maximum size of result.
+* @param status A pointer to a UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see udat_applyPatternRelative
+* @internal ICU 4.2 technology preview
+*/
+U_INTERNAL int32_t U_EXPORT2 
+udat_toPatternRelativeTime(const UDateFormat *fmt,
+                           UChar             *result,
+                           int32_t           resultLength,
+                           UErrorCode        *status);
+
+/**
+* Set the date & time patterns used by a UDateFormat set for relative date formatting.
+* The patterns should follow the pattern syntax rules.
+* @param format The formatter to set.
+* @param datePattern The new date pattern
+* @param datePatternLength The length of datePattern, or -1 if null-terminated.
+* @param timePattern The new time pattern
+* @param timePatternLength The length of timePattern, or -1 if null-terminated.
+* @param status A pointer to a UErrorCode to receive any errors
+* @see udat_toPatternRelativeDate, udat_toPatternRelativeTime
+* @internal ICU 4.2 technology preview
+*/
+U_INTERNAL void U_EXPORT2 
+udat_applyPatternRelative(UDateFormat *format,
+                          const UChar *datePattern,
+                          int32_t     datePatternLength,
+                          const UChar *timePattern,
+                          int32_t     timePatternLength,
+                          UErrorCode  *status);
+
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Source/JavaScriptCore/icu/unicode/umisc.h b/Source/JavaScriptCore/icu/unicode/umisc.h
new file mode 100644 (file)
index 0000000..d85451f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+**********************************************************************
+*   Copyright (C) 1999-2006, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+**********************************************************************
+*   file name:  umisc.h
+*   encoding:   US-ASCII
+*   tab size:   8 (not used)
+*   indentation:4
+*
+*   created on: 1999oct15
+*   created by: Markus W. Scherer
+*/
+
+#ifndef UMISC_H
+#define UMISC_H
+
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief  C API:misc definitions 
+ *
+ *  This file contains miscellaneous definitions for the C APIs. 
+ */
+
+U_CDECL_BEGIN
+
+/** A struct representing a range of text containing a specific field 
+ *  @stable ICU 2.0
+ */
+typedef struct UFieldPosition {
+  /**
+   * The field 
+   * @stable ICU 2.0
+   */
+  int32_t field;
+  /**
+   * The start of the text range containing field 
+   * @stable ICU 2.0
+   */
+  int32_t beginIndex;
+  /** 
+   * The limit of the text range containing field 
+   * @stable ICU 2.0
+   */
+  int32_t endIndex;
+} UFieldPosition;
+
+#if !UCONFIG_NO_SERVICE
+/**
+ * Opaque type returned by registerInstance, registerFactory and unregister for service registration.
+ * @stable ICU 2.6
+ */
+typedef const void* URegistryKey;
+#endif
+
+U_CDECL_END
+
+#endif
diff --git a/Source/JavaScriptCore/icu/unicode/unum.h b/Source/JavaScriptCore/icu/unicode/unum.h
new file mode 100644 (file)
index 0000000..1102bab
--- /dev/null
@@ -0,0 +1,999 @@
+/*
+*******************************************************************************
+* Copyright (C) 1997-2010, International Business Machines Corporation and others.
+* All Rights Reserved.
+* Modification History:
+*
+*   Date        Name        Description
+*   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
+*******************************************************************************
+*/
+
+#ifndef _UNUM
+#define _UNUM
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/localpointer.h"
+#include "unicode/uloc.h"
+#include "unicode/umisc.h"
+#include "unicode/parseerr.h"
+/**
+ * \file
+ * \brief C API: NumberFormat
+ *
+ * <h2> Number Format C API </h2>
+ *
+ * Number Format C API  Provides functions for
+ * formatting and parsing a number.  Also provides methods for
+ * determining which locales have number formats, and what their names
+ * are.
+ * <P>
+ * UNumberFormat helps you to format and parse numbers for any locale.
+ * Your code can be completely independent of the locale conventions
+ * for decimal points, thousands-separators, or even the particular
+ * decimal digits used, or whether the number format is even decimal.
+ * There are different number format styles like decimal, currency,
+ * percent and spellout.
+ * <P>
+ * To format a number for the current Locale, use one of the static
+ * factory methods:
+ * <pre>
+ * \code
+ *    UChar myString[20];
+ *    double myNumber = 7.0;
+ *    UErrorCode status = U_ZERO_ERROR;
+ *    UNumberFormat* nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, &status);
+ *    unum_formatDouble(nf, myNumber, myString, 20, NULL, &status);
+ *    printf(" Example 1: %s\n", austrdup(myString) ); //austrdup( a function used to convert UChar* to char*)
+ * \endcode
+ * </pre>
+ * If you are formatting multiple numbers, it is more efficient to get
+ * the format and use it multiple times so that the system doesn't
+ * have to fetch the information about the local language and country
+ * conventions multiple times.
+ * <pre>
+ * \code
+ * uint32_t i, resultlength, reslenneeded;
+ * UErrorCode status = U_ZERO_ERROR;
+ * UFieldPosition pos;
+ * uint32_t a[] = { 123, 3333, -1234567 };
+ * const uint32_t a_len = sizeof(a) / sizeof(a[0]);
+ * UNumberFormat* nf;
+ * UChar* result = NULL;
+ *
+ * nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, &status);
+ * for (i = 0; i < a_len; i++) {
+ *    resultlength=0;
+ *    reslenneeded=unum_format(nf, a[i], NULL, resultlength, &pos, &status);
+ *    result = NULL;
+ *    if(status==U_BUFFER_OVERFLOW_ERROR){
+ *       status=U_ZERO_ERROR;
+ *       resultlength=reslenneeded+1;
+ *       result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ *       unum_format(nf, a[i], result, resultlength, &pos, &status);
+ *    }
+ *    printf( " Example 2: %s\n", austrdup(result));
+ *    free(result);
+ * }
+ * \endcode
+ * </pre>
+ * To format a number for a different Locale, specify it in the
+ * call to unum_open().
+ * <pre>
+ * \code
+ *     UNumberFormat* nf = unum_open(UNUM_DEFAULT, NULL, -1, "fr_FR", NULL, &success)
+ * \endcode
+ * </pre>
+ * You can use a NumberFormat API unum_parse() to parse.
+ * <pre>
+ * \code
+ *    UErrorCode status = U_ZERO_ERROR;
+ *    int32_t pos=0;
+ *    int32_t num;
+ *    num = unum_parse(nf, str, u_strlen(str), &pos, &status);
+ * \endcode
+ * </pre>
+ * Use UNUM_DECIMAL to get the normal number format for that country.
+ * There are other static options available.  Use UNUM_CURRENCY
+ * to get the currency number format for that country.  Use UNUM_PERCENT
+ * to get a format for displaying percentages. With this format, a
+ * fraction from 0.53 is displayed as 53%.
+ * <P>
+ * Use a pattern to create either a DecimalFormat or a RuleBasedNumberFormat
+ * formatter.  The pattern must conform to the syntax defined for those
+ * formatters.
+ * <P>
+ * You can also control the display of numbers with such function as
+ * unum_getAttribues() and unum_setAtributes(), which let you set the
+ * miminum fraction digits, grouping, etc.
+ * @see UNumberFormatAttributes for more details
+ * <P>
+ * You can also use forms of the parse and format methods with
+ * ParsePosition and UFieldPosition to allow you to:
+ * <ul type=round>
+ *   <li>(a) progressively parse through pieces of a string.
+ *   <li>(b) align the decimal point and other areas.
+ * </ul>
+ * <p>
+ * It is also possible to change or set the symbols used for a particular
+ * locale like the currency symbol, the grouping seperator , monetary seperator
+ * etc by making use of functions unum_setSymbols() and unum_getSymbols().
+ */
+
+/** A number formatter.
+ *  For usage in C programs.
+ *  @stable ICU 2.0
+ */
+typedef void* UNumberFormat;
+
+/** The possible number format styles. 
+ *  @stable ICU 2.0
+ */
+typedef enum UNumberFormatStyle {
+    /**
+     * Decimal format defined by pattern 
+     * @stable ICU 3.0
+     */
+    UNUM_PATTERN_DECIMAL=0,
+    /** Decimal format */
+    UNUM_DECIMAL=1,
+    /** Currency format */
+    UNUM_CURRENCY,
+    /** Percent format */
+    UNUM_PERCENT,
+    /** Scientific format */
+    UNUM_SCIENTIFIC,
+    /** Spellout rule-based format */
+    UNUM_SPELLOUT,
+    /** 
+     * Ordinal rule-based format 
+     * @stable ICU 3.0
+     */
+    UNUM_ORDINAL,
+    /** 
+     * Duration rule-based format 
+     * @stable ICU 3.0
+     */
+    UNUM_DURATION,
+    /** 
+     * Numbering system rule-based format 
+     * @stable ICU 4.2
+     */
+    UNUM_NUMBERING_SYSTEM,
+    /** 
+     * Rule-based format defined by pattern 
+     * @stable ICU 3.0
+     */
+    UNUM_PATTERN_RULEBASED,
+    /** Default format */
+    UNUM_DEFAULT = UNUM_DECIMAL,
+    /** (Alias for UNUM_PATTERN_DECIMAL) */
+    UNUM_IGNORE = UNUM_PATTERN_DECIMAL
+} UNumberFormatStyle;
+
+/** The possible number format rounding modes. 
+ *  @stable ICU 2.0
+ */
+typedef enum UNumberFormatRoundingMode {
+    UNUM_ROUND_CEILING,
+    UNUM_ROUND_FLOOR,
+    UNUM_ROUND_DOWN,
+    UNUM_ROUND_UP,
+    /**
+     * Half-even rounding, misspelled name
+     * @deprecated, ICU 3.8
+     */
+    UNUM_FOUND_HALFEVEN,
+    UNUM_ROUND_HALFDOWN,
+    UNUM_ROUND_HALFUP,
+    /**
+     * Half-even rounding
+     * @stable, ICU 3.8
+     */
+    UNUM_ROUND_HALFEVEN = UNUM_FOUND_HALFEVEN
+} UNumberFormatRoundingMode;
+
+/** The possible number format pad positions. 
+ *  @stable ICU 2.0
+ */
+typedef enum UNumberFormatPadPosition {
+    UNUM_PAD_BEFORE_PREFIX,
+    UNUM_PAD_AFTER_PREFIX,
+    UNUM_PAD_BEFORE_SUFFIX,
+    UNUM_PAD_AFTER_SUFFIX
+} UNumberFormatPadPosition;
+
+/**
+ * Create and return a new UNumberFormat for formatting and parsing
+ * numbers.  A UNumberFormat may be used to format numbers by calling
+ * {@link #unum_format }, and to parse numbers by calling {@link #unum_parse }.
+ * The caller must call {@link #unum_close } when done to release resources
+ * used by this object.
+ * @param style The type of number format to open: one of
+ * UNUM_DECIMAL, UNUM_CURRENCY, UNUM_PERCENT, UNUM_SCIENTIFIC, UNUM_SPELLOUT,
+ * UNUM_PATTERN_DECIMAL, UNUM_PATTERN_RULEBASED, or UNUM_DEFAULT.
+ * If UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED is passed then the
+ * number format is opened using the given pattern, which must conform
+ * to the syntax described in DecimalFormat or RuleBasedNumberFormat,
+ * respectively.
+ * @param pattern A pattern specifying the format to use. 
+ * This parameter is ignored unless the style is
+ * UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED.
+ * @param patternLength The number of characters in the pattern, or -1
+ * if null-terminated. This parameter is ignored unless the style is
+ * UNUM_PATTERN.
+ * @param locale A locale identifier to use to determine formatting
+ * and parsing conventions, or NULL to use the default locale.
+ * @param parseErr A pointer to a UParseError struct to receive the
+ * details of any parsing errors, or NULL if no parsing error details
+ * are desired.
+ * @param status A pointer to an input-output UErrorCode.
+ * @return A pointer to a newly created UNumberFormat, or NULL if an
+ * error occurred.
+ * @see unum_close
+ * @see DecimalFormat
+ * @stable ICU 2.0
+ */
+U_STABLE UNumberFormat* U_EXPORT2 
+unum_open(  UNumberFormatStyle    style,
+            const    UChar*    pattern,
+            int32_t            patternLength,
+            const    char*     locale,
+            UParseError*       parseErr,
+            UErrorCode*        status);
+
+
+/**
+* Close a UNumberFormat.
+* Once closed, a UNumberFormat may no longer be used.
+* @param fmt The formatter to close.
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+unum_close(UNumberFormat* fmt);
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUNumberFormatPointer
+ * "Smart pointer" class, closes a UNumberFormat via unum_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 4.4
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberFormatPointer, UNumberFormat, unum_close);
+
+U_NAMESPACE_END
+
+#endif
+
+/**
+ * Open a copy of a UNumberFormat.
+ * This function performs a deep copy.
+ * @param fmt The format to copy
+ * @param status A pointer to an UErrorCode to receive any errors.
+ * @return A pointer to a UNumberFormat identical to fmt.
+ * @stable ICU 2.0
+ */
+U_STABLE UNumberFormat* U_EXPORT2 
+unum_clone(const UNumberFormat *fmt,
+       UErrorCode *status);
+
+/**
+* Format an integer using a UNumberFormat.
+* The integer will be formatted according to the UNumberFormat's locale.
+* @param fmt The formatter to use.
+* @param number The number to format.
+* @param result A pointer to a buffer to receive the formatted number.
+* @param resultLength The maximum size of result.
+* @param pos    A pointer to a UFieldPosition.  On input, position->field
+* is read.  On output, position->beginIndex and position->endIndex indicate
+* the beginning and ending indices of field number position->field, if such
+* a field exists.  This parameter may be NULL, in which case no field
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see unum_formatInt64
+* @see unum_formatDouble
+* @see unum_parse
+* @see unum_parseInt64
+* @see unum_parseDouble
+* @see UFieldPosition
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_format(    const    UNumberFormat*    fmt,
+        int32_t            number,
+        UChar*            result,
+        int32_t            resultLength,
+        UFieldPosition    *pos,
+        UErrorCode*        status);
+
+/**
+* Format an int64 using a UNumberFormat.
+* The int64 will be formatted according to the UNumberFormat's locale.
+* @param fmt The formatter to use.
+* @param number The number to format.
+* @param result A pointer to a buffer to receive the formatted number.
+* @param resultLength The maximum size of result.
+* @param pos    A pointer to a UFieldPosition.  On input, position->field
+* is read.  On output, position->beginIndex and position->endIndex indicate
+* the beginning and ending indices of field number position->field, if such
+* a field exists.  This parameter may be NULL, in which case no field
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see unum_format
+* @see unum_formatDouble
+* @see unum_parse
+* @see unum_parseInt64
+* @see unum_parseDouble
+* @see UFieldPosition
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_formatInt64(const UNumberFormat *fmt,
+        int64_t         number,
+        UChar*          result,
+        int32_t         resultLength,
+        UFieldPosition *pos,
+        UErrorCode*     status);
+
+/**
+* Format a double using a UNumberFormat.
+* The double will be formatted according to the UNumberFormat's locale.
+* @param fmt The formatter to use.
+* @param number The number to format.
+* @param result A pointer to a buffer to receive the formatted number.
+* @param resultLength The maximum size of result.
+* @param pos    A pointer to a UFieldPosition.  On input, position->field
+* is read.  On output, position->beginIndex and position->endIndex indicate
+* the beginning and ending indices of field number position->field, if such
+* a field exists.  This parameter may be NULL, in which case no field
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see unum_format
+* @see unum_formatInt64
+* @see unum_parse
+* @see unum_parseInt64
+* @see unum_parseDouble
+* @see UFieldPosition
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_formatDouble(    const    UNumberFormat*  fmt,
+            double          number,
+            UChar*          result,
+            int32_t         resultLength,
+            UFieldPosition  *pos, /* 0 if ignore */
+            UErrorCode*     status);
+
+/**
+* Format a decimal number using a UNumberFormat.
+* The number will be formatted according to the UNumberFormat's locale.
+* The syntax of the input number is a "numeric string"
+* as defined in the Decimal Arithmetic Specification, available at
+* http://speleotrove.com/decimal
+* @param fmt The formatter to use.
+* @param number The number to format.
+* @param length The length of the input number, or -1 if the input is nul-terminated.
+* @param result A pointer to a buffer to receive the formatted number.
+* @param resultLength The maximum size of result.
+* @param pos    A pointer to a UFieldPosition.  On input, position->field
+*               is read.  On output, position->beginIndex and position->endIndex indicate
+*               the beginning and ending indices of field number position->field, if such
+*               a field exists.  This parameter may be NULL, in which case it is ignored.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see unum_format
+* @see unum_formatInt64
+* @see unum_parse
+* @see unum_parseInt64
+* @see unum_parseDouble
+* @see UFieldPosition
+* @stable ICU 4.4 
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_formatDecimal(    const    UNumberFormat*  fmt,
+            const char *    number,
+            int32_t         length,
+            UChar*          result,
+            int32_t         resultLength,
+            UFieldPosition  *pos, /* 0 if ignore */
+            UErrorCode*     status);
+
+/**
+ * Format a double currency amount using a UNumberFormat.
+ * The double will be formatted according to the UNumberFormat's locale.
+ * @param fmt the formatter to use
+ * @param number the number to format
+ * @param currency the 3-letter null-terminated ISO 4217 currency code
+ * @param result a pointer to the buffer to receive the formatted number
+ * @param resultLength the maximum number of UChars to write to result
+ * @param pos a pointer to a UFieldPosition.  On input,
+ * position->field is read.  On output, position->beginIndex and
+ * position->endIndex indicate the beginning and ending indices of
+ * field number position->field, if such a field exists.  This
+ * parameter may be NULL, in which case it is ignored.
+ * @param status a pointer to an input-output UErrorCode
+ * @return the total buffer size needed; if greater than resultLength,
+ * the output was truncated.
+ * @see unum_formatDouble
+ * @see unum_parseDoubleCurrency
+ * @see UFieldPosition
+ * @stable ICU 3.0
+ */
+U_STABLE int32_t U_EXPORT2 
+unum_formatDoubleCurrency(const UNumberFormat* fmt,
+                          double number,
+                          UChar* currency,
+                          UChar* result,
+                          int32_t resultLength,
+                          UFieldPosition* pos, /* ignored if 0 */
+                          UErrorCode* status);
+
+/**
+* Parse a string into an integer using a UNumberFormat.
+* The string will be parsed according to the UNumberFormat's locale.
+* @param fmt The formatter to use.
+* @param text The text to parse.
+* @param textLength The length of text, or -1 if null-terminated.
+* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which
+* to begin parsing.  If not 0, on output the offset at which parsing ended.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The value of the parsed integer
+* @see unum_parseInt64
+* @see unum_parseDouble
+* @see unum_format
+* @see unum_formatInt64
+* @see unum_formatDouble
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_parse(    const   UNumberFormat*  fmt,
+        const   UChar*          text,
+        int32_t         textLength,
+        int32_t         *parsePos /* 0 = start */,
+        UErrorCode      *status);
+
+/**
+* Parse a string into an int64 using a UNumberFormat.
+* The string will be parsed according to the UNumberFormat's locale.
+* @param fmt The formatter to use.
+* @param text The text to parse.
+* @param textLength The length of text, or -1 if null-terminated.
+* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which
+* to begin parsing.  If not 0, on output the offset at which parsing ended.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The value of the parsed integer
+* @see unum_parse
+* @see unum_parseDouble
+* @see unum_format
+* @see unum_formatInt64
+* @see unum_formatDouble
+* @stable ICU 2.8
+*/
+U_STABLE int64_t U_EXPORT2 
+unum_parseInt64(const UNumberFormat*  fmt,
+        const UChar*  text,
+        int32_t       textLength,
+        int32_t       *parsePos /* 0 = start */,
+        UErrorCode    *status);
+
+/**
+* Parse a string into a double using a UNumberFormat.
+* The string will be parsed according to the UNumberFormat's locale.
+* @param fmt The formatter to use.
+* @param text The text to parse.
+* @param textLength The length of text, or -1 if null-terminated.
+* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which
+* to begin parsing.  If not 0, on output the offset at which parsing ended.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The value of the parsed double
+* @see unum_parse
+* @see unum_parseInt64
+* @see unum_format
+* @see unum_formatInt64
+* @see unum_formatDouble
+* @stable ICU 2.0
+*/
+U_STABLE double U_EXPORT2 
+unum_parseDouble(    const   UNumberFormat*  fmt,
+            const   UChar*          text,
+            int32_t         textLength,
+            int32_t         *parsePos /* 0 = start */,
+            UErrorCode      *status);
+
+
+/**
+* Parse a number from a string into an unformatted numeric string using a UNumberFormat.
+* The input string will be parsed according to the UNumberFormat's locale.
+* The syntax of the output is a "numeric string"
+* as defined in the Decimal Arithmetic Specification, available at
+* http://speleotrove.com/decimal
+* @param fmt The formatter to use.
+* @param text The text to parse.
+* @param textLength The length of text, or -1 if null-terminated.
+* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which
+*                 to begin parsing.  If not 0, on output the offset at which parsing ended.
+* @param outBuf A (char *) buffer to receive the parsed number as a string.  The output string
+*               will be nul-terminated if there is sufficient space.
+* @param outBufLength The size of the output buffer.  May be zero, in which case
+*               the outBuf pointer may be NULL, and the function will return the
+*               size of the output string.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return the length of the output string, not including any terminating nul.
+* @see unum_parse
+* @see unum_parseInt64
+* @see unum_format
+* @see unum_formatInt64
+* @see unum_formatDouble
+* @stable ICU 4.4
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_parseDecimal(const   UNumberFormat*  fmt,
+                 const   UChar*          text,
+                         int32_t         textLength,
+                         int32_t         *parsePos /* 0 = start */,
+                         char            *outBuf,
+                         int32_t         outBufLength,
+                         UErrorCode      *status);
+
+/**
+ * Parse a string into a double and a currency using a UNumberFormat.
+ * The string will be parsed according to the UNumberFormat's locale.
+ * @param fmt the formatter to use
+ * @param text the text to parse
+ * @param textLength the length of text, or -1 if null-terminated
+ * @param parsePos a pointer to an offset index into text at which to
+ * begin parsing. On output, *parsePos will point after the last
+ * parsed character.  This parameter may be 0, in which case parsing
+ * begins at offset 0.
+ * @param currency a pointer to the buffer to receive the parsed null-
+ * terminated currency.  This buffer must have a capacity of at least
+ * 4 UChars.
+ * @param status a pointer to an input-output UErrorCode
+ * @return the parsed double
+ * @see unum_parseDouble
+ * @see unum_formatDoubleCurrency
+ * @stable ICU 3.0
+ */
+U_STABLE double U_EXPORT2
+unum_parseDoubleCurrency(const UNumberFormat* fmt,
+                         const UChar* text,
+                         int32_t textLength,
+                         int32_t* parsePos, /* 0 = start */
+                         UChar* currency,
+                         UErrorCode* status);
+
+/**
+ * Set the pattern used by a UNumberFormat.  This can only be used
+ * on a DecimalFormat, other formats return U_ILLEGAL_ARGUMENT_ERROR
+ * in the status.
+ * @param format The formatter to set.
+ * @param localized TRUE if the pattern is localized, FALSE otherwise.
+ * @param pattern The new pattern
+ * @param patternLength The length of pattern, or -1 if null-terminated.
+ * @param parseError A pointer to UParseError to recieve information
+ * about errors occurred during parsing, or NULL if no parse error
+ * information is desired.
+ * @param status A pointer to an input-output UErrorCode.
+ * @see unum_toPattern
+ * @see DecimalFormat
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2 
+unum_applyPattern(          UNumberFormat  *format,
+                            UBool          localized,
+                    const   UChar          *pattern,
+                            int32_t         patternLength,
+                            UParseError    *parseError,
+                            UErrorCode     *status
+                                    );
+
+/**
+* Get a locale for which decimal formatting patterns are available.
+* A UNumberFormat in a locale returned by this function will perform the correct
+* formatting and parsing for the locale.  The results of this call are not
+* valid for rule-based number formats.
+* @param localeIndex The index of the desired locale.
+* @return A locale for which number formatting patterns are available, or 0 if none.
+* @see unum_countAvailable
+* @stable ICU 2.0
+*/
+U_STABLE const char* U_EXPORT2 
+unum_getAvailable(int32_t localeIndex);
+
+/**
+* Determine how many locales have decimal formatting patterns available.  The
+* results of this call are not valid for rule-based number formats.
+* This function is useful for determining the loop ending condition for
+* calls to {@link #unum_getAvailable }.
+* @return The number of locales for which decimal formatting patterns are available.
+* @see unum_getAvailable
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_countAvailable(void);
+
+/** The possible UNumberFormat numeric attributes @stable ICU 2.0 */
+typedef enum UNumberFormatAttribute {
+  /** Parse integers only */
+  UNUM_PARSE_INT_ONLY,
+  /** Use grouping separator */
+  UNUM_GROUPING_USED,
+  /** Always show decimal point */
+  UNUM_DECIMAL_ALWAYS_SHOWN,
+  /** Maximum integer digits */
+  UNUM_MAX_INTEGER_DIGITS,
+  /** Minimum integer digits */
+  UNUM_MIN_INTEGER_DIGITS,
+  /** Integer digits */
+  UNUM_INTEGER_DIGITS,
+  /** Maximum fraction digits */
+  UNUM_MAX_FRACTION_DIGITS,
+  /** Minimum fraction digits */
+  UNUM_MIN_FRACTION_DIGITS,
+  /** Fraction digits */
+  UNUM_FRACTION_DIGITS,
+  /** Multiplier */
+  UNUM_MULTIPLIER,
+  /** Grouping size */
+  UNUM_GROUPING_SIZE,
+  /** Rounding Mode */
+  UNUM_ROUNDING_MODE,
+  /** Rounding increment */
+  UNUM_ROUNDING_INCREMENT,
+  /** The width to which the output of <code>format()</code> is padded. */
+  UNUM_FORMAT_WIDTH,
+  /** The position at which padding will take place. */
+  UNUM_PADDING_POSITION,
+  /** Secondary grouping size */
+  UNUM_SECONDARY_GROUPING_SIZE,
+  /** Use significant digits
+   * @stable ICU 3.0 */
+  UNUM_SIGNIFICANT_DIGITS_USED,
+  /** Minimum significant digits
+   * @stable ICU 3.0 */
+  UNUM_MIN_SIGNIFICANT_DIGITS,
+  /** Maximum significant digits
+   * @stable ICU 3.0 */
+  UNUM_MAX_SIGNIFICANT_DIGITS,
+  /** Lenient parse mode used by rule-based formats.
+   * @stable ICU 3.0
+   */
+  UNUM_LENIENT_PARSE
+} UNumberFormatAttribute;
+
+/**
+* Get a numeric attribute associated with a UNumberFormat.
+* An example of a numeric attribute is the number of integer digits a formatter will produce.
+* @param fmt The formatter to query.
+* @param attr The attribute to query; one of UNUM_PARSE_INT_ONLY, UNUM_GROUPING_USED,
+* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS,
+* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER,
+* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE.
+* @return The value of attr.
+* @see unum_setAttribute
+* @see unum_getDoubleAttribute
+* @see unum_setDoubleAttribute
+* @see unum_getTextAttribute
+* @see unum_setTextAttribute
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_getAttribute(const UNumberFormat*          fmt,
+          UNumberFormatAttribute  attr);
+
+/**
+* Set a numeric attribute associated with a UNumberFormat.
+* An example of a numeric attribute is the number of integer digits a formatter will produce.  If the
+* formatter does not understand the attribute, the call is ignored.  Rule-based formatters only understand
+* the lenient-parse attribute.
+* @param fmt The formatter to set.
+* @param attr The attribute to set; one of UNUM_PARSE_INT_ONLY, UNUM_GROUPING_USED,
+* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS,
+* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER,
+* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE,
+* or UNUM_LENIENT_PARSE.
+* @param newValue The new value of attr.
+* @see unum_getAttribute
+* @see unum_getDoubleAttribute
+* @see unum_setDoubleAttribute
+* @see unum_getTextAttribute
+* @see unum_setTextAttribute
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+unum_setAttribute(    UNumberFormat*          fmt,
+            UNumberFormatAttribute  attr,
+            int32_t                 newValue);
+
+
+/**
+* Get a numeric attribute associated with a UNumberFormat.
+* An example of a numeric attribute is the number of integer digits a formatter will produce.
+* If the formatter does not understand the attribute, -1 is returned.
+* @param fmt The formatter to query.
+* @param attr The attribute to query; e.g. UNUM_ROUNDING_INCREMENT.
+* @return The value of attr.
+* @see unum_getAttribute
+* @see unum_setAttribute
+* @see unum_setDoubleAttribute
+* @see unum_getTextAttribute
+* @see unum_setTextAttribute
+* @stable ICU 2.0
+*/
+U_STABLE double U_EXPORT2 
+unum_getDoubleAttribute(const UNumberFormat*          fmt,
+          UNumberFormatAttribute  attr);
+
+/**
+* Set a numeric attribute associated with a UNumberFormat.
+* An example of a numeric attribute is the number of integer digits a formatter will produce.
+* If the formatter does not understand the attribute, this call is ignored.
+* @param fmt The formatter to set.
+* @param attr The attribute to set; e.g. UNUM_ROUNDING_INCREMENT.
+* @param newValue The new value of attr.
+* @see unum_getAttribute
+* @see unum_setAttribute
+* @see unum_getDoubleAttribute
+* @see unum_getTextAttribute
+* @see unum_setTextAttribute
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+unum_setDoubleAttribute(    UNumberFormat*          fmt,
+            UNumberFormatAttribute  attr,
+            double                 newValue);
+
+/** The possible UNumberFormat text attributes @stable ICU 2.0*/
+typedef enum UNumberFormatTextAttribute {
+  /** Positive prefix */
+  UNUM_POSITIVE_PREFIX,
+  /** Positive suffix */
+  UNUM_POSITIVE_SUFFIX,
+  /** Negative prefix */
+  UNUM_NEGATIVE_PREFIX,
+  /** Negative suffix */
+  UNUM_NEGATIVE_SUFFIX,
+  /** The character used to pad to the format width. */
+  UNUM_PADDING_CHARACTER,
+  /** The ISO currency code */
+  UNUM_CURRENCY_CODE,
+  /**
+   * The default rule set.  This is only available with rule-based formatters.
+   * @stable ICU 3.0
+   */
+  UNUM_DEFAULT_RULESET,
+  /**
+   * The public rule sets.  This is only available with rule-based formatters.
+   * This is a read-only attribute.  The public rulesets are returned as a
+   * single string, with each ruleset name delimited by ';' (semicolon).
+   * @stable ICU 3.0
+   */
+  UNUM_PUBLIC_RULESETS
+} UNumberFormatTextAttribute;
+
+/**
+* Get a text attribute associated with a UNumberFormat.
+* An example of a text attribute is the suffix for positive numbers.  If the formatter
+* does not understand the attributre, U_UNSUPPORTED_ERROR is returned as the status.
+* Rule-based formatters only understand UNUM_DEFAULT_RULESET and UNUM_PUBLIC_RULESETS.
+* @param fmt The formatter to query.
+* @param tag The attribute to query; one of UNUM_POSITIVE_PREFIX, UNUM_POSITIVE_SUFFIX,
+* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX, UNUM_PADDING_CHARACTER, UNUM_CURRENCY_CODE,
+* UNUM_DEFAULT_RULESET, or UNUM_PUBLIC_RULESETS.
+* @param result A pointer to a buffer to receive the attribute.
+* @param resultLength The maximum size of result.
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The total buffer size needed; if greater than resultLength, the output was truncated.
+* @see unum_setTextAttribute
+* @see unum_getAttribute
+* @see unum_setAttribute
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2 
+unum_getTextAttribute(    const    UNumberFormat*                    fmt,
+            UNumberFormatTextAttribute      tag,
+            UChar*                            result,
+            int32_t                            resultLength,
+            UErrorCode*                        status);
+
+/**
+* Set a text attribute associated with a UNumberFormat.
+* An example of a text attribute is the suffix for positive numbers.  Rule-based formatters
+* only understand UNUM_DEFAULT_RULESET.
+* @param fmt The formatter to set.
+* @param tag The attribute to set; one of UNUM_POSITIVE_PREFIX, UNUM_POSITIVE_SUFFIX,
+* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX, UNUM_PADDING_CHARACTER, UNUM_CURRENCY_CODE,
+* or UNUM_DEFAULT_RULESET.
+* @param newValue The new value of attr.
+* @param newValueLength The length of newValue, or -1 if null-terminated.
+* @param status A pointer to an UErrorCode to receive any errors
+* @see unum_getTextAttribute
+* @see unum_getAttribute
+* @see unum_setAttribute
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2 
+unum_setTextAttribute(    UNumberFormat*                    fmt,
+            UNumberFormatTextAttribute      tag,
+            const    UChar*                            newValue,
+            int32_t                            newValueLength,
+            UErrorCode                        *status);
+
+/**
+ * Extract the pattern from a UNumberFormat.  The pattern will follow
+ * the DecimalFormat pattern syntax.
+ * @param fmt The formatter to query.
+ * @param isPatternLocalized TRUE if the pattern should be localized,
+ * FALSE otherwise.  This is ignored if the formatter is a rule-based
+ * formatter.
+ * @param result A pointer to a buffer to receive the pattern.
+ * @param resultLength The maximum size of result.
+ * @param status A pointer to an input-output UErrorCode.
+ * @return The total buffer size needed; if greater than resultLength,
+ * the output was truncated.
+ * @see unum_applyPattern
+ * @see DecimalFormat
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 
+unum_toPattern(    const    UNumberFormat*          fmt,
+        UBool                  isPatternLocalized,
+        UChar*                  result,
+        int32_t                 resultLength,
+        UErrorCode*             status);
+
+
+/**
+ * Constants for specifying a number format symbol.
+ * @stable ICU 2.0
+ */
+typedef enum UNumberFormatSymbol {
+  /** The decimal separator */
+  UNUM_DECIMAL_SEPARATOR_SYMBOL = 0,
+  /** The grouping separator */
+  UNUM_GROUPING_SEPARATOR_SYMBOL = 1,
+  /** The pattern separator */
+  UNUM_PATTERN_SEPARATOR_SYMBOL = 2,
+  /** The percent sign */
+  UNUM_PERCENT_SYMBOL = 3,
+  /** Zero*/
+  UNUM_ZERO_DIGIT_SYMBOL = 4,
+  /** Character representing a digit in the pattern */
+  UNUM_DIGIT_SYMBOL = 5,
+  /** The minus sign */
+  UNUM_MINUS_SIGN_SYMBOL = 6,
+  /** The plus sign */
+  UNUM_PLUS_SIGN_SYMBOL = 7,
+  /** The currency symbol */
+  UNUM_CURRENCY_SYMBOL = 8,
+  /** The international currency symbol */
+  UNUM_INTL_CURRENCY_SYMBOL = 9,
+  /** The monetary separator */
+  UNUM_MONETARY_SEPARATOR_SYMBOL = 10,
+  /** The exponential symbol */
+  UNUM_EXPONENTIAL_SYMBOL = 11,
+  /** Per mill symbol */
+  UNUM_PERMILL_SYMBOL = 12,
+  /** Escape padding character */
+  UNUM_PAD_ESCAPE_SYMBOL = 13,
+  /** Infinity symbol */
+  UNUM_INFINITY_SYMBOL = 14,
+  /** Nan symbol */
+  UNUM_NAN_SYMBOL = 15,
+  /** Significant digit symbol
+   * @stable ICU 3.0 */
+  UNUM_SIGNIFICANT_DIGIT_SYMBOL = 16,
+  /** The monetary grouping separator 
+   * @stable ICU 3.6
+   */
+  UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL = 17,  
+  /** One
+   * @draft ICU 4.6
+   */
+  UNUM_ONE_DIGIT_SYMBOL = 18,
+  /** Two
+   * @draft ICU 4.6
+   */
+  UNUM_TWO_DIGIT_SYMBOL = 19,
+  /** Three
+   * @draft ICU 4.6
+   */
+  UNUM_THREE_DIGIT_SYMBOL = 20,
+  /** Four
+   * @draft ICU 4.6
+   */
+  UNUM_FOUR_DIGIT_SYMBOL = 21,
+  /** Five
+   * @draft ICU 4.6
+   */
+  UNUM_FIVE_DIGIT_SYMBOL = 22,
+  /** Six
+   * @draft ICU 4.6
+   */
+  UNUM_SIX_DIGIT_SYMBOL = 23,
+  /** Seven
+    * @draft ICU 4.6
+   */
+  UNUM_SEVEN_DIGIT_SYMBOL = 24,
+  /** Eight
+   * @draft ICU 4.6
+   */
+  UNUM_EIGHT_DIGIT_SYMBOL = 25,
+  /** Nine
+   * @draft ICU 4.6
+   */
+  UNUM_NINE_DIGIT_SYMBOL = 26,
+  /** count symbol constants */
+  UNUM_FORMAT_SYMBOL_COUNT = 27
+} UNumberFormatSymbol;
+
+/**
+* Get a symbol associated with a UNumberFormat.
+* A UNumberFormat uses symbols to represent the special locale-dependent
+* characters in a number, for example the percent sign. This API is not
+* supported for rule-based formatters.
+* @param fmt The formatter to query.
+* @param symbol The UNumberFormatSymbol constant for the symbol to get
+* @param buffer The string buffer that will receive the symbol string;
+*               if it is NULL, then only the length of the symbol is returned
+* @param size The size of the string buffer
+* @param status A pointer to an UErrorCode to receive any errors
+* @return The length of the symbol; the buffer is not modified if
+*         <code>length&gt;=size</code>
+* @see unum_setSymbol
+* @stable ICU 2.0
+*/
+U_STABLE int32_t U_EXPORT2
+unum_getSymbol(const UNumberFormat *fmt,
+               UNumberFormatSymbol symbol,
+               UChar *buffer,
+               int32_t size,
+               UErrorCode *status);
+
+/**
+* Set a symbol associated with a UNumberFormat.
+* A UNumberFormat uses symbols to represent the special locale-dependent
+* characters in a number, for example the percent sign.  This API is not
+* supported for rule-based formatters.
+* @param fmt The formatter to set.
+* @param symbol The UNumberFormatSymbol constant for the symbol to set
+* @param value The string to set the symbol to
+* @param length The length of the string, or -1 for a zero-terminated string
+* @param status A pointer to an UErrorCode to receive any errors.
+* @see unum_getSymbol
+* @stable ICU 2.0
+*/
+U_STABLE void U_EXPORT2
+unum_setSymbol(UNumberFormat *fmt,
+               UNumberFormatSymbol symbol,
+               const UChar *value,
+               int32_t length,
+               UErrorCode *status);
+
+
+/**
+ * Get the locale for this number format object.
+ * You can choose between valid and actual locale.
+ * @param fmt The formatter to get the locale from
+ * @param type type of the locale we're looking for (valid or actual) 
+ * @param status error code for the operation
+ * @return the locale name
+ * @stable ICU 2.8
+ */
+U_STABLE const char* U_EXPORT2
+unum_getLocaleByType(const UNumberFormat *fmt,
+                     ULocDataLocaleType type,
+                     UErrorCode* status); 
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
index 00bf14c..1bcf7f5 100644 (file)
@@ -55,7 +55,7 @@
  */
 #ifdef XP_CPLUSPLUS
 #   ifndef U_SHOW_CPLUSPLUS_API
-#       define U_SHOW_CPLUSPLUS_API 1
+#       define U_SHOW_CPLUSPLUS_API 0
 #   endif
 #else
 #   undef U_SHOW_CPLUSPLUS_API
index 163b116..c51b46d 100644 (file)
     macro(lastIndex) \
     macro(length) \
     macro(line) \
+    macro(localeMatcher) \
     macro(message) \
     macro(multiline) \
     macro(name) \
index d41dd17..3107b3f 100644 (file)
@@ -150,25 +150,17 @@ EncodedJSValue JSC_HOST_CALL IntlCollatorConstructorFuncSupportedLocalesOf(ExecS
     // 10.2.2 Intl.Collator.supportedLocalesOf(locales [, options]) (ECMA-402 2.0)
 
     // 1. Let requestedLocales be CanonicalizeLocaleList(locales).
-    // FIXME: requested = CanonicalizeLocaleList(locales);
+    JSArray* requestedLocales = canonicalizeLocaleList(exec, exec->argument(0));
 
     // 2. ReturnIfAbrupt(requestedLocales).
-    // if (exec->hadException())
-    //     return JSValue::encode(jsUndefined());
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
     // 3. Return SupportedLocales(%Collator%.[[availableLocales]], requestedLocales, options).
-    // FIXME: return JSValue::encode(SupportedLocales(available, requested, options));
-
-    // Return empty array until properly implemented.
-    VM& vm = exec->vm();
     JSGlobalObject* globalObject = exec->callee()->globalObject();
-    JSArray* supportedLocales = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
-    if (!supportedLocales)
-        return JSValue::encode(throwOutOfMemoryError(exec));
-
-    return JSValue::encode(supportedLocales);
+    return JSValue::encode(supportedLocales(exec, globalObject->intlCollatorAvailableLocales(), requestedLocales, exec->argument(1)));
 }
-    
+
 void IntlCollatorConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     IntlCollatorConstructor* thisObject = jsCast<IntlCollatorConstructor*>(cell);
index 0b8d460..98d3bbe 100644 (file)
@@ -150,22 +150,16 @@ EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatConstructorFuncSupportedLocalesOf
     // 12.2.2 Intl.DateTimeFormat.supportedLocalesOf(locales [, options]) (ECMA-402 2.0)
 
     // 1. Let availableLocales be %DateTimeFormat%.[[availableLocales]].
-    // FIXME: available = IntlDateTimeFormatConstructor::getAvailableLocales()
+    JSGlobalObject* globalObject = exec->callee()->globalObject();
+    const HashSet<String> availableLocales = globalObject->intlDateTimeFormatAvailableLocales();
 
     // 2. Let requestedLocales be CanonicalizeLocaleList(locales).
-    // FIXME: requested = CanonicalizeLocaleList(locales)
+    JSArray* requestedLocales = canonicalizeLocaleList(exec, exec->argument(0));
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
     // 3. Return SupportedLocales(availableLocales, requestedLocales, options).
-    // FIXME: return JSValue::encode(SupportedLocales(available, requested, options));
-
-    // Return empty array until properly implemented.
-    VM& vm = exec->vm();
-    JSGlobalObject* globalObject = exec->callee()->globalObject();
-    JSArray* supportedLocales = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
-    if (!supportedLocales)
-        return JSValue::encode(throwOutOfMemoryError(exec));
-
-    return JSValue::encode(supportedLocales);
+    return JSValue::encode(supportedLocales(exec, availableLocales, requestedLocales, exec->argument(1)));
 }
     
 void IntlDateTimeFormatConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
index b8639d6..d066ee8 100644 (file)
@@ -150,22 +150,16 @@ EncodedJSValue JSC_HOST_CALL IntlNumberFormatConstructorFuncSupportedLocalesOf(E
     // 11.2.2 Intl.NumberFormat.supportedLocalesOf(locales [, options]) (ECMA-402 2.0)
 
     // 1. Let availableLocales be %NumberFormat%.[[availableLocales]].
-    // FIXME: available = IntlNumberFormatConstructor::getAvailableLocales()
+    JSGlobalObject* globalObject = exec->callee()->globalObject();
+    const HashSet<String> availableLocales = globalObject->intlNumberFormatAvailableLocales();
 
     // 2. Let requestedLocales be CanonicalizeLocaleList(locales).
-    // FIXME: requested = CanonicalizeLocaleList(locales)
+    JSArray* requestedLocales = canonicalizeLocaleList(exec, exec->argument(0));
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
     // 3. Return SupportedLocales(availableLocales, requestedLocales, options).
-    // FIXME: return JSValue::encode(SupportedLocales(available, requested, options));
-
-    // Return empty array until properly implemented.
-    VM& vm = exec->vm();
-    JSGlobalObject* globalObject = exec->callee()->globalObject();
-    JSArray* supportedLocales = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
-    if (!supportedLocales)
-        return JSValue::encode(throwOutOfMemoryError(exec));
-
-    return JSValue::encode(supportedLocales);
+    return JSValue::encode(supportedLocales(exec, availableLocales, requestedLocales, exec->argument(1)));
 }
 
 void IntlNumberFormatConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
index ba457e7..6799b88 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(INTL)
 
+#include "Error.h"
 #include "FunctionPrototype.h"
 #include "IntlCollator.h"
 #include "IntlCollatorConstructor.h"
 #include "IntlNumberFormatConstructor.h"
 #include "IntlNumberFormatPrototype.h"
 #include "JSCInlines.h"
+#include "JSCJSValueInlines.h"
 #include "Lookup.h"
 #include "ObjectPrototype.h"
+#include <unicode/uloc.h>
 #include <wtf/Assertions.h>
 
 namespace JSC {
@@ -102,6 +105,596 @@ Structure* IntlObject::createStructure(VM& vm, JSGlobalObject* globalObject, JSV
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
+static String getIntlStringOption(ExecState* exec, JSValue options, PropertyName property, const HashSet<String>& values, const char* notFound, String fallback)
+{
+    // 9.2.9 GetOption (options, property, type, values, fallback)
+    // For type="string".
+
+    // 1. Let opts be ToObject(options).
+    JSObject* opts = options.toObject(exec);
+
+    // 2. ReturnIfAbrupt(opts).
+    if (exec->hadException())
+        return String();
+
+    // 3. Let value be Get(opts, property).
+    JSValue value = opts->get(exec, property);
+
+    // 4. ReturnIfAbrupt(value).
+    if (exec->hadException())
+        return String();
+
+    // 5. If value is not undefined, then
+    if (!value.isUndefined()) {
+        // a. Assert: type is "boolean" or "string".
+        // Function dedicated to "string".
+
+        // c. If type is "string", then
+        // i. Let value be ToString(value).
+        JSString* stringValue = value.toString(exec);
+
+        // ii. ReturnIfAbrupt(value).
+        if (exec->hadException())
+            return String();
+
+        // d. If values is not undefined, then
+        // i. If values does not contain an element equal to value, throw a RangeError exception.
+        if (!values.isEmpty() && !values.contains(stringValue->value(exec))) {
+            exec->vm().throwException(exec, createRangeError(exec, String(notFound)));
+            return String();
+        }
+
+        // e. Return value.
+        return stringValue->value(exec);
+    }
+
+    // 6. Else return fallback.
+    return fallback;
+}
+
+static String getPrivateUseLangTag(const Vector<String>& parts, size_t startIndex)
+{
+    size_t numParts = parts.size();
+    size_t currentIndex = startIndex;
+
+    // Check for privateuse.
+    // privateuse = "x" 1*("-" (2*8alphanum))
+    StringBuilder privateuse;
+    while (currentIndex < numParts) {
+        const String& singleton = parts[currentIndex];
+        unsigned singletonLength = singleton.length();
+        bool isValid = (singletonLength == 1 && (singleton == "x" || singleton == "X"));
+        if (!isValid)
+            break;
+
+        if (currentIndex != startIndex)
+            privateuse.append('-');
+
+        ++currentIndex;
+        unsigned numExtParts = 0;
+        privateuse.append('x');
+        while (currentIndex < numParts) {
+            const String& extPart = parts[currentIndex];
+            unsigned extPartLength = extPart.length();
+
+            bool isValid = (extPartLength >= 2 && extPartLength <= 8 && extPart.isAllSpecialCharacters<isASCIIAlphanumeric>());
+            if (!isValid)
+                break;
+
+            ++currentIndex;
+            ++numExtParts;
+            privateuse.append('-');
+            privateuse.append(extPart.convertToASCIILowercase());
+        }
+
+        // Requires at least one production.
+        if (!numExtParts)
+            return String();
+    }
+
+    // Leftovers makes it invalid.
+    if (currentIndex < numParts)
+        return String();
+
+    return privateuse.toString();
+}
+
+static String getCanonicalLangTag(const Vector<String>& parts)
+{
+    ASSERT(!parts.isEmpty());
+
+    // Follows the grammar at https://www.rfc-editor.org/rfc/bcp/bcp47.txt
+    // langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse]
+
+    size_t numParts = parts.size();
+    // Check for language.
+    // language = 2*3ALPHA ["-" extlang] / 4ALPHA / 5*8ALPHA
+    size_t currentIndex = 0;
+    const String& language = parts[currentIndex];
+    unsigned languageLength = language.length();
+    bool canHaveExtlang = languageLength >= 2 && languageLength <= 3;
+    bool isValidLanguage = languageLength >= 2 && languageLength <= 8 && language.isAllSpecialCharacters<isASCIIAlpha>();
+    if (!isValidLanguage)
+        return String();
+
+    ++currentIndex;
+    StringBuilder canonical;
+    canonical.append(language.convertToASCIILowercase());
+
+    // Check for extlang.
+    // extlang = 3ALPHA *2("-" 3ALPHA)
+    if (canHaveExtlang) {
+        for (unsigned times = 0; times < 3 && currentIndex < numParts; ++times) {
+            const String& extlang = parts[currentIndex];
+            unsigned extlangLength = extlang.length();
+            if (extlangLength == 3 && extlang.isAllSpecialCharacters<isASCIIAlpha>()) {
+                ++currentIndex;
+                canonical.append('-');
+                canonical.append(extlang.convertToASCIILowercase());
+            } else
+                break;
+        }
+    }
+
+    // Check for script.
+    // script = 4ALPHA
+    if (currentIndex < numParts) {
+        const String& script = parts[currentIndex];
+        unsigned scriptLength = script.length();
+        if (scriptLength == 4 && script.isAllSpecialCharacters<isASCIIAlpha>()) {
+            ++currentIndex;
+            canonical.append('-');
+            canonical.append(toASCIIUpper(script[0]));
+            canonical.append(script.substring(1, 3).convertToASCIILowercase());
+        }
+    }
+
+    // Check for region.
+    // region = 2ALPHA / 3DIGIT
+    if (currentIndex < numParts) {
+        const String& region = parts[currentIndex];
+        unsigned regionLength = region.length();
+        bool isValidRegion = (
+            (regionLength == 2 && region.isAllSpecialCharacters<isASCIIAlpha>())
+            || (regionLength == 3 && region.isAllSpecialCharacters<isASCIIDigit>())
+        );
+        if (isValidRegion) {
+            ++currentIndex;
+            canonical.append('-');
+            canonical.append(region.upper());
+        }
+    }
+
+    // Check for variant.
+    // variant = 5*8alphanum / (DIGIT 3alphanum)
+    HashSet<String> subtags;
+    while (currentIndex < numParts) {
+        const String& variant = parts[currentIndex];
+        unsigned variantLength = variant.length();
+        bool isValidVariant = (
+            (variantLength >= 5 && variantLength <= 8 && variant.isAllSpecialCharacters<isASCIIAlphanumeric>())
+            || (variantLength == 4 && isASCIIDigit(variant[0]) && variant.substring(1, 3).isAllSpecialCharacters<isASCIIAlphanumeric>())
+        );
+        if (!isValidVariant)
+            break;
+
+        // Cannot include duplicate subtags (case insensitive).
+        String lowerVariant = variant.convertToASCIILowercase();
+        if (!subtags.add(lowerVariant).isNewEntry)
+            return String();
+
+        ++currentIndex;
+
+        // Reordering variant subtags is not required in the spec.
+        canonical.append('-');
+        canonical.append(lowerVariant);
+    }
+
+    // Check for extension.
+    // extension = singleton 1*("-" (2*8alphanum))
+    // singleton = alphanum except x or X
+    subtags.clear();
+    Vector<String> extensions;
+    while (currentIndex < numParts) {
+        const String& possibleSingleton = parts[currentIndex];
+        unsigned singletonLength = possibleSingleton.length();
+        bool isValidSingleton = (singletonLength == 1 && possibleSingleton != "x" && possibleSingleton != "X" && isASCIIAlphanumeric(possibleSingleton[0]));
+        if (!isValidSingleton)
+            break;
+
+        // Cannot include duplicate singleton (case insensitive).
+        String singleton = possibleSingleton.convertToASCIILowercase();
+        if (!subtags.add(singleton).isNewEntry)
+            return String();
+
+        ++currentIndex;
+        int numExtParts = 0;
+        StringBuilder extension;
+        extension.append(singleton);
+        while (currentIndex < numParts) {
+            const String& extPart = parts[currentIndex];
+            unsigned extPartLength = extPart.length();
+
+            bool isValid = (extPartLength >= 2 && extPartLength <= 8 && extPart.isAllSpecialCharacters<isASCIIAlphanumeric>());
+            if (!isValid)
+                break;
+
+            ++currentIndex;
+            ++numExtParts;
+            extension.append('-');
+            extension.append(extPart.convertToASCIILowercase());
+        }
+
+        // Requires at least one production.
+        if (!numExtParts)
+            return String();
+
+        extensions.append(extension.toString());
+    }
+
+    // Add extensions to canonical sorted by singleton.
+    std::sort(
+        extensions.begin(),
+        extensions.end(),
+        [] (const String& a, const String& b) -> bool {
+            return a[0] < b[0];
+        }
+    );
+    size_t numExtenstions = extensions.size();
+    for (size_t i = 0; i < numExtenstions; ++i) {
+        canonical.append('-');
+        canonical.append(extensions[i]);
+    }
+
+    // Check for privateuse.
+    if (currentIndex < numParts) {
+        String privateuse = getPrivateUseLangTag(parts, currentIndex);
+        if (privateuse.isNull())
+            return String();
+        canonical.append('-');
+        canonical.append(privateuse);
+    }
+
+    // FIXME: Replace subtags with their preferred values.
+
+    return canonical.toString();
+}
+
+static String getGrandfatheredLangTag(const String& locale)
+{
+    // grandfathered = irregular / regular
+    // FIXME: convert to a compile time hash table if this is causing performance issues.
+    HashMap<String, String> tagMap = {
+        // Irregular.
+        { ASCIILiteral("en-gb-oed"), ASCIILiteral("en-GB-oed") },
+        { ASCIILiteral("i-ami"), ASCIILiteral("ami") },
+        { ASCIILiteral("i-bnn"), ASCIILiteral("bnn") },
+        { ASCIILiteral("i-default"), ASCIILiteral("i-default") },
+        { ASCIILiteral("i-enochian"), ASCIILiteral("i-enochian") },
+        { ASCIILiteral("i-hak"), ASCIILiteral("hak") },
+        { ASCIILiteral("i-klingon"), ASCIILiteral("tlh") },
+        { ASCIILiteral("i-lux"), ASCIILiteral("lb") },
+        { ASCIILiteral("i-mingo"), ASCIILiteral("i-mingo") },
+        { ASCIILiteral("i-navajo"), ASCIILiteral("nv") },
+        { ASCIILiteral("i-pwn"), ASCIILiteral("pwn") },
+        { ASCIILiteral("i-tao"), ASCIILiteral("tao") },
+        { ASCIILiteral("i-tay"), ASCIILiteral("tay") },
+        { ASCIILiteral("i-tsu"), ASCIILiteral("tsu") },
+        { ASCIILiteral("sgn-be-fr"), ASCIILiteral("sfb") },
+        { ASCIILiteral("sgn-be-nl"), ASCIILiteral("vgt") },
+        { ASCIILiteral("sgn-ch-de"), ASCIILiteral("sgg") },
+        // Regular.
+        { ASCIILiteral("art-lojban"), ASCIILiteral("jbo") },
+        { ASCIILiteral("cel-gaulish"), ASCIILiteral("cel-gaulish") },
+        { ASCIILiteral("no-bok"), ASCIILiteral("nb") },
+        { ASCIILiteral("no-nyn"), ASCIILiteral("nn") },
+        { ASCIILiteral("zh-guoyu"), ASCIILiteral("cmn") },
+        { ASCIILiteral("zh-hakka"), ASCIILiteral("hak") },
+        { ASCIILiteral("zh-min"), ASCIILiteral("zh-min") },
+        { ASCIILiteral("zh-min-nan"), ASCIILiteral("nan") },
+        { ASCIILiteral("zh-xiang"), ASCIILiteral("hsn") }
+    };
+
+    return tagMap.get(locale.convertToASCIILowercase());
+}
+
+static String canonicalizeLanguageTag(const String& locale)
+{
+    // 6.2.2 IsStructurallyValidLanguageTag (locale)
+    // 6.2.3 CanonicalizeLanguageTag (locale)
+    // These are done one after another in CanonicalizeLocaleList, so they are combined here to reduce duplication.
+    // https://www.rfc-editor.org/rfc/bcp/bcp47.txt
+
+    // Language-Tag = langtag / privateuse / grandfathered
+    String grandfather = getGrandfatheredLangTag(locale);
+    if (!grandfather.isNull())
+        return grandfather;
+
+    // FIXME: Replace redundant tags [RFC4647].
+
+    Vector<String> parts;
+    locale.split('-', true, parts);
+    if (!parts.isEmpty()) {
+        String langtag = getCanonicalLangTag(parts);
+        if (!langtag.isNull())
+            return langtag;
+
+        String privateuse = getPrivateUseLangTag(parts, 0);
+        if (!privateuse.isNull())
+            return privateuse;
+    }
+
+    return String();
+}
+
+JSArray* canonicalizeLocaleList(ExecState* exec, JSValue locales)
+{
+    // 9.2.1 CanonicalizeLocaleList (locales)
+    VM& vm = exec->vm();
+    JSGlobalObject* globalObject = exec->callee()->globalObject();
+    JSArray* seen = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0);
+    if (!seen) {
+        throwOutOfMemoryError(exec);
+        return nullptr;
+    }
+
+    // 1. If locales is undefined, then a. Return a new empty List.
+    if (locales.isUndefined())
+        return seen;
+
+    // 2. Let seen be an empty List.
+    // Done before to also return in step 1, if needed.
+
+    // 3. If Type(locales) is String, then
+    JSObject* localesObject;
+    if (locales.isString()) {
+        //  a. Let aLocales be CreateArrayFromList(«locales»).
+        JSArray* localesArray = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 1);
+        localesArray->initializeIndex(vm, 0, locales);
+        // 4. Let O be ToObject(aLocales).
+        localesObject = localesArray;
+    } else {
+        // 4. Let O be ToObject(aLocales).
+        localesObject = locales.toObject(exec);
+    }
+
+    // 5. ReturnIfAbrupt(O).
+    if (exec->hadException())
+        return nullptr;
+
+    // 6. Let len be ToLength(Get(O, "length")).
+    JSValue lengthProperty = localesObject->get(exec, vm.propertyNames->length);
+    if (exec->hadException())
+        return nullptr;
+
+    double length = lengthProperty.toLength(exec);
+    if (exec->hadException())
+        return nullptr;
+
+    // Keep track of locales that have been added to the list.
+    HashSet<String> seenSet;
+
+    // 7. Let k be 0.
+    // 8. Repeat, while k < len
+    for (double k = 0; k < length; ++k) {
+        // a. Let Pk be ToString(k).
+        // Not needed because hasProperty and get take an int for numeric key.
+
+        // b. Let kPresent be HasProperty(O, Pk).
+        bool kPresent = localesObject->hasProperty(exec, k);
+
+        // c. ReturnIfAbrupt(kPresent).
+        if (exec->hadException())
+            return nullptr;
+
+        // d. If kPresent is true, then
+        if (kPresent) {
+            // i. Let kValue be Get(O, Pk).
+            JSValue kValue = localesObject->get(exec, k);
+
+            // ii. ReturnIfAbrupt(kValue).
+            if (exec->hadException())
+                return nullptr;
+
+            // iii. If Type(kValue) is not String or Object, throw a TypeError exception.
+            if (!kValue.isString() && !kValue.isObject()) {
+                throwTypeError(exec, ASCIILiteral("locale value must be a string or object"));
+                return nullptr;
+            }
+
+            // iv. Let tag be ToString(kValue).
+            JSString* tag = kValue.toString(exec);
+
+            // v. ReturnIfAbrupt(tag).
+            if (exec->hadException())
+                return nullptr;
+
+            // vi. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
+            // vii. Let canonicalizedTag be CanonicalizeLanguageTag(tag).
+            String canonicalizedTag = canonicalizeLanguageTag(tag->value(exec));
+            if (canonicalizedTag.isNull()) {
+                exec->vm().throwException(exec, createRangeError(exec, String::format("invalid language tag: %s", tag->value(exec).utf8().data())));
+                return nullptr;
+            }
+
+            // viii. If canonicalizedTag is not an element of seen, append canonicalizedTag as the last element of seen.
+            if (seenSet.add(canonicalizedTag).isNewEntry)
+                seen->push(exec, jsString(exec, canonicalizedTag));
+        }
+        // e. Increase k by 1.
+    }
+
+    return seen;
+}
+
+static String bestAvailableLocale(const HashSet<String>& availableLocales, const String& locale)
+{
+    // 9.2.2 BestAvailableLocale (availableLocales, locale)
+    // 1. Let candidate be locale.
+    String candidate = locale;
+
+    // 2. Repeat
+    while (!candidate.isEmpty()) {
+        // a. If availableLocales contains an element equal to candidate, then return candidate.
+        if (availableLocales.contains(candidate))
+            return candidate;
+
+        // b. Let pos be the character index of the last occurrence of "-" (U+002D) within candidate. If that character does not occur, return undefined.
+        size_t pos = candidate.reverseFind('-');
+        if (pos == notFound)
+            return String();
+
+        // c. If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, then decrease pos by 2.
+        if (pos >= 2 && candidate[pos - 2] == '-')
+            pos -= 2;
+
+        // d. Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive.
+        candidate = candidate.substring(0, pos);
+    }
+
+    return String();
+}
+
+static JSArray* lookupSupportedLocales(ExecState* exec, const HashSet<String>& availableLocales, JSArray* requestedLocales)
+{
+    // 9.2.6 LookupSupportedLocales (availableLocales, requestedLocales)
+
+    // 1. Let rLocales be CreateArrayFromList(requestedLocales).
+    // Already an array.
+
+    // 2. Let len be ToLength(Get(rLocales, "length")).
+    unsigned len = requestedLocales->length();
+
+    // 3. Let subset be an empty List.
+    VM& vm = exec->vm();
+    JSGlobalObject* globalObject = exec->callee()->globalObject();
+    JSArray* subset = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
+    if (!subset) {
+        throwOutOfMemoryError(exec);
+        return nullptr;
+    }
+
+    // 4. Let k be 0.
+    // 5. Repeat while k < len
+    for (unsigned k = 0; k < len; ++k) {
+        // a. Let Pk be ToString(k).
+        // b. Let locale be Get(rLocales, Pk).
+        JSValue locale = requestedLocales->get(exec, k);
+
+        // c. ReturnIfAbrupt(locale).
+        if (exec->hadException())
+            return nullptr;
+
+        // d. Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed.
+        JSString* jsLocale = locale.toString(exec);
+        if (exec->hadException())
+            return nullptr;
+
+        String sLocale = jsLocale->value(exec);
+        Vector<String> parts;
+        sLocale.split('-', parts);
+        StringBuilder builder;
+        size_t partsSize = parts.size();
+        if (partsSize > 0)
+            builder.append(parts[0]);
+        for (size_t p = 1; p < partsSize; ++p) {
+            if (parts[p] == "u") {
+                // Skip the u- and anything that follows until another singleton.
+                // While the next part is part of the unicode extension, skip it.
+                while (p + 1 < partsSize && parts[p + 1].length() > 1)
+                    ++p;
+            } else {
+                builder.append('-');
+                builder.append(parts[p]);
+            }
+        }
+        String noExtensionsLocale = builder.toString();
+
+        // e. Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale).
+        String availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale);
+
+        // f. If availableLocale is not undefined, then append locale to the end of subset.
+        if (!availableLocale.isNull())
+            subset->push(exec, locale);
+
+        // g. Increment k by 1.
+    }
+
+    // 6. Return subset.
+    return subset;
+}
+
+static JSArray* bestFitSupportedLocales(ExecState* exec, const HashSet<String>& availableLocales, JSArray* requestedLocales)
+{
+    // 9.2.7 BestFitSupportedLocales (availableLocales, requestedLocales)
+    // FIXME: Implement something better than lookup.
+    return lookupSupportedLocales(exec, availableLocales, requestedLocales);
+}
+
+JSValue supportedLocales(ExecState* exec, const HashSet<String>& availableLocales, JSArray* requestedLocales, JSValue options)
+{
+    // 9.2.8 SupportedLocales (availableLocales, requestedLocales, options)
+    VM& vm = exec->vm();
+    String matcher;
+
+    // 1. If options is not undefined, then
+    if (!options.isUndefined()) {
+        // a. Let matcher be GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
+        const HashSet<String> matchers({ ASCIILiteral("lookup"), ASCIILiteral("best fit") });
+        matcher = getIntlStringOption(exec, options, vm.propertyNames->localeMatcher, matchers, "localeMatcher must be either \"lookup\" or \"best fit\"", ASCIILiteral("best fit"));
+        // b. ReturnIfAbrupt(matcher).
+        if (exec->hadException())
+            return jsUndefined();
+    } else {
+        // 2. Else, let matcher be "best fit".
+        matcher = ASCIILiteral("best fit");
+    }
+
+    JSArray* supportedLocales;
+    // 3. If matcher is "best fit",
+    if (matcher == "best fit") {
+        // a. Let MatcherOperation be the abstract operation BestFitSupportedLocales.
+        // 5. Let supportedLocales be MatcherOperation(availableLocales, requestedLocales).
+        supportedLocales = bestFitSupportedLocales(exec, availableLocales, requestedLocales);
+    } else {
+        // 4. Else
+        // a. Let MatcherOperation be the abstract operation LookupSupportedLocales.
+        // 5. Let supportedLocales be MatcherOperation(availableLocales, requestedLocales).
+        supportedLocales = lookupSupportedLocales(exec, availableLocales, requestedLocales);
+    }
+
+    if (exec->hadException())
+        return jsUndefined();
+
+    // 6. Let subset be CreateArrayFromList(supportedLocales).
+    // Already an array.
+
+    // 7. Let keys be subset.[[OwnPropertyKeys]]().
+    PropertyNameArray keys(exec, PropertyNameMode::Strings);
+    supportedLocales->getOwnPropertyNames(supportedLocales, exec, keys, EnumerationMode());
+
+    PropertyDescriptor desc;
+    desc.setConfigurable(false);
+    desc.setWritable(false);
+
+    // 8. Repeat for each element P of keys in List order,
+    size_t len = keys.size();
+    for (size_t i = 0; i < len; ++i) {
+        // a. Let desc be PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }.
+        // Created above for reuse.
+
+        // b. Let status be DefinePropertyOrThrow(subset, P, desc).
+        supportedLocales->defineOwnProperty(supportedLocales, exec, keys[i], desc, true);
+
+        // c. Assert: status is not abrupt completion.
+        if (exec->hadException())
+            return jsUndefined();
+    }
+
+    // 9. Return subset.
+    return supportedLocales;
+}
+
 } // namespace JSC
 
 #endif // ENABLE(INTL)
index 8342854..fde62b5 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(INTL)
 
+#include "JSCJSValueInlines.h"
 #include "JSObject.h"
 
 namespace JSC {
@@ -56,6 +57,9 @@ private:
     IntlObject(VM&, Structure*);
 };
 
+JSArray* canonicalizeLocaleList(ExecState*, JSValue locales);
+JSValue supportedLocales(ExecState*, const HashSet<String>& availableLocales, JSArray* requestedLocales, JSValue options);
+
 } // namespace JSC
 
 #endif // ENABLE(INTL)
index 9e0aab1..a0cf777 100644 (file)
@@ -56,6 +56,18 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const
     return trunc(toNumber(exec));
 }
 
+double JSValue::toLength(ExecState* exec) const
+{
+    // ECMA 7.1.15
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-tolength
+    double d = toInteger(exec);
+    if (d <= 0)
+        return 0.0;
+    if (std::isinf(d))
+        return 9007199254740991.0; // 2 ** 53 - 1
+    return std::min(d, 9007199254740991.0);
+}
+
 double JSValue::toNumberSlowCase(ExecState* exec) const
 {
     ASSERT(!isInt32() && !isDouble());
index b7eaad2..c803b64 100644 (file)
@@ -262,6 +262,7 @@ public:
     JS_EXPORT_PRIVATE double toIntegerPreserveNaN(ExecState*) const;
     int32_t toInt32(ExecState*) const;
     uint32_t toUInt32(ExecState*) const;
+    double toLength(ExecState*) const;
 
     // Floating point conversions (this is a convenience function for WebCore;
     // single precision float is not a representation used in JS or JSC).
index 2991064..545a134 100644 (file)
 
 #if ENABLE(INTL)
 #include "IntlObject.h"
+#include <unicode/ucol.h>
+#include <unicode/udat.h>
+#include <unicode/unum.h>
 #endif // ENABLE(INTL)
 
 #if ENABLE(REMOTE_INSPECTOR)
@@ -1007,6 +1010,50 @@ void JSGlobalObject::setName(const String& name)
 #endif
 }
 
+# if ENABLE(INTL)
+const HashSet<String>& JSGlobalObject::intlCollatorAvailableLocales()
+{
+    if (m_intlCollatorAvailableLocales.isEmpty()) {
+        int32_t count = ucol_countAvailable();
+        for (int32_t i = 0; i < count; ++i) {
+            String locale(ucol_getAvailable(i));
+            // Change from ICU format to BCP47.
+            locale.replace('_', '-');
+            m_intlCollatorAvailableLocales.add(locale);
+        }
+    }
+    return m_intlCollatorAvailableLocales;
+}
+
+const HashSet<String>& JSGlobalObject::intlDateTimeFormatAvailableLocales()
+{
+    if (m_intlDateTimeFormatAvailableLocales.isEmpty()) {
+        int32_t count = udat_countAvailable();
+        for (int32_t i = 0; i < count; ++i) {
+            String locale(udat_getAvailable(i));
+            // Change from ICU format to BCP47.
+            locale.replace('_', '-');
+            m_intlDateTimeFormatAvailableLocales.add(locale);
+        }
+    }
+    return m_intlDateTimeFormatAvailableLocales;
+}
+
+const HashSet<String>& JSGlobalObject::intlNumberFormatAvailableLocales()
+{
+    if (m_intlNumberFormatAvailableLocales.isEmpty()) {
+        int32_t count = unum_countAvailable();
+        for (int32_t i = 0; i < count; ++i) {
+            String locale(unum_getAvailable(i));
+            // Change from ICU format to BCP47.
+            locale.replace('_', '-');
+            m_intlNumberFormatAvailableLocales.add(locale);
+        }
+    }
+    return m_intlNumberFormatAvailableLocales;
+}
+#endif // ENABLE(INTL)
+
 void JSGlobalObject::queueMicrotask(PassRefPtr<Microtask> task)
 {
     if (globalObjectMethodTable()->queueTaskToEventLoop) {
index dcb3a08..1df6da2 100644 (file)
@@ -307,6 +307,12 @@ protected:
     std::unique_ptr<JSGlobalObjectDebuggable> m_inspectorDebuggable;
 #endif
 
+#if ENABLE(INTL)
+    HashSet<String> m_intlCollatorAvailableLocales;
+    HashSet<String> m_intlDateTimeFormatAvailableLocales;
+    HashSet<String> m_intlNumberFormatAvailableLocales;
+#endif // ENABLE(INTL)
+
     RefPtr<WatchpointSet> m_masqueradesAsUndefinedWatchpoint;
     RefPtr<WatchpointSet> m_havingABadTimeWatchpoint;
     RefPtr<WatchpointSet> m_varInjectionWatchpoint;
@@ -525,6 +531,12 @@ public:
     JSGlobalObjectDebuggable& inspectorDebuggable() { return *m_inspectorDebuggable.get(); }
 #endif
 
+#if ENABLE(INTL)
+    const HashSet<String>& intlCollatorAvailableLocales();
+    const HashSet<String>& intlDateTimeFormatAvailableLocales();
+    const HashSet<String>& intlNumberFormatAvailableLocales();
+#endif // ENABLE(INTL)
+
     void setConsoleClient(ConsoleClient* consoleClient) { m_consoleClient = consoleClient; }
     ConsoleClient* consoleClient() const { return m_consoleClient; }