From effd22637d8ee3d67c2ad86c64ac942f24fef362 Mon Sep 17 00:00:00 2001 From: Peter Breitenlohner Date: Fri, 26 Oct 2012 09:04:38 +0000 Subject: icu 50.1 (50_rc): Add the missing new files git-svn-id: svn://tug.org/texlive/trunk@28088 c570f23f-e606-0410-a88d-b1316a301751 --- .../libs/icu/icu-50.1/common/dictionarydata.cpp | 228 ++++++++++ .../libs/icu/icu-50.1/common/dictionarydata.h | 165 +++++++ .../libs/icu/icu-50.1/common/listformatter.cpp | 325 ++++++++++++++ Build/source/libs/icu/icu-50.1/common/umutex.cpp | 483 +++++++++++++++++++++ .../icu/icu-50.1/common/unicode/listformatter.h | 134 ++++++ Build/source/libs/icu/icu-50.1/common/utypeinfo.h | 27 ++ 6 files changed, 1362 insertions(+) create mode 100644 Build/source/libs/icu/icu-50.1/common/dictionarydata.cpp create mode 100644 Build/source/libs/icu/icu-50.1/common/dictionarydata.h create mode 100644 Build/source/libs/icu/icu-50.1/common/listformatter.cpp create mode 100644 Build/source/libs/icu/icu-50.1/common/umutex.cpp create mode 100644 Build/source/libs/icu/icu-50.1/common/unicode/listformatter.h create mode 100644 Build/source/libs/icu/icu-50.1/common/utypeinfo.h (limited to 'Build/source/libs/icu/icu-50.1/common') diff --git a/Build/source/libs/icu/icu-50.1/common/dictionarydata.cpp b/Build/source/libs/icu/icu-50.1/common/dictionarydata.cpp new file mode 100644 index 00000000000..cc845425c33 --- /dev/null +++ b/Build/source/libs/icu/icu-50.1/common/dictionarydata.cpp @@ -0,0 +1,228 @@ +/* +******************************************************************************* +* Copyright (C) 2012, International Business Machines +* Corporation and others. All Rights Reserved. +******************************************************************************* +* dictionarydata.h +* +* created on: 2012may31 +* created by: Markus W. Scherer & Maxime Serrano +*/ + +#include "dictionarydata.h" +#include "unicode/ucharstrie.h" +#include "unicode/bytestrie.h" +#include "unicode/udata.h" +#include "cmemory.h" + +#if !UCONFIG_NO_BREAK_ITERATION + +U_NAMESPACE_BEGIN + +#ifndef CYGWINMSVC /* On Cygwin/MSVC, the error redefinition of symbols occurs.*/ +const int32_t DictionaryData::TRIE_TYPE_BYTES; +const int32_t DictionaryData::TRIE_TYPE_UCHARS; +#endif + +DictionaryMatcher::~DictionaryMatcher() { +} + +UCharsDictionaryMatcher::~UCharsDictionaryMatcher() { + udata_close(file); +} + +int32_t UCharsDictionaryMatcher::getType() const { + return DictionaryData::TRIE_TYPE_UCHARS; +} + +int32_t UCharsDictionaryMatcher::matches(UText *text, int32_t maxLength, int *lengths, int &count, int limit, int32_t *values) const { + UCharsTrie uct(characters); + UChar32 c = utext_next32(text); + if (c < 0) { + return 0; + } + UStringTrieResult result = uct.first(c); + int32_t numChars = 1; + count = 0; + for (;;) { + if (USTRINGTRIE_HAS_VALUE(result)) { + if (count < limit) { + if (values != NULL) { + values[count] = uct.getValue(); + } + lengths[count++] = numChars; + } + if (result == USTRINGTRIE_FINAL_VALUE) { + break; + } + } + else if (result == USTRINGTRIE_NO_MATCH) { + break; + } + + // TODO: why do we have a text limit if the UText knows its length? + if (numChars >= maxLength) { + break; + } + + c = utext_next32(text); + if (c < 0) { + break; + } + ++numChars; + result = uct.next(c); + } + return numChars; +} + +BytesDictionaryMatcher::~BytesDictionaryMatcher() { + udata_close(file); +} + +UChar32 BytesDictionaryMatcher::transform(UChar32 c) const { + if ((transformConstant & DictionaryData::TRANSFORM_TYPE_MASK) == DictionaryData::TRANSFORM_TYPE_OFFSET) { + if (c == 0x200D) { + return 0xFF; + } else if (c == 0x200C) { + return 0xFE; + } + int32_t delta = c - (transformConstant & DictionaryData::TRANSFORM_OFFSET_MASK); + if (delta < 0 || 0xFD < delta) { + return U_SENTINEL; + } + return (UChar32)delta; + } + return c; +} + +int32_t BytesDictionaryMatcher::getType() const { + return DictionaryData::TRIE_TYPE_BYTES; +} + +int32_t BytesDictionaryMatcher::matches(UText *text, int32_t maxLength, int *lengths, int &count, int limit, int32_t *values) const { + BytesTrie bt(characters); + UChar32 c = utext_next32(text); + if (c < 0) { + return 0; + } + UStringTrieResult result = bt.first(transform(c)); + int32_t numChars = 1; + count = 0; + for (;;) { + if (USTRINGTRIE_HAS_VALUE(result)) { + if (count < limit) { + if (values != NULL) { + values[count] = bt.getValue(); + } + lengths[count++] = numChars; + } + if (result == USTRINGTRIE_FINAL_VALUE) { + break; + } + } + else if (result == USTRINGTRIE_NO_MATCH) { + break; + } + + // TODO: why do we have a text limit if the UText knows its length? + if (numChars >= maxLength) { + break; + } + + c = utext_next32(text); + if (c < 0) { + break; + } + ++numChars; + result = bt.next(transform(c)); + } + return numChars; +} + + +U_NAMESPACE_END + +U_NAMESPACE_USE + +U_CAPI int32_t U_EXPORT2 +udict_swap(const UDataSwapper *ds, const void *inData, int32_t length, + void *outData, UErrorCode *pErrorCode) { + const UDataInfo *pInfo; + int32_t headerSize; + const uint8_t *inBytes; + uint8_t *outBytes; + const int32_t *inIndexes; + int32_t indexes[DictionaryData::IX_COUNT]; + int32_t i, offset, size; + + headerSize = udata_swapDataHeader(ds, inData, length, outData, pErrorCode); + if (pErrorCode == NULL || U_FAILURE(*pErrorCode)) return 0; + pInfo = (const UDataInfo *)((const char *)inData + 4); + if (!(pInfo->dataFormat[0] == 0x44 && + pInfo->dataFormat[1] == 0x69 && + pInfo->dataFormat[2] == 0x63 && + pInfo->dataFormat[3] == 0x74 && + pInfo->formatVersion[0] == 1)) { + udata_printError(ds, "udict_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as dictionary data\n", + pInfo->dataFormat[0], pInfo->dataFormat[1], pInfo->dataFormat[2], pInfo->dataFormat[3], pInfo->formatVersion[0]); + *pErrorCode = U_UNSUPPORTED_ERROR; + return 0; + } + + inBytes = (const uint8_t *)inData + headerSize; + outBytes = (uint8_t *)outData + headerSize; + + inIndexes = (const int32_t *)inBytes; + if (length >= 0) { + length -= headerSize; + if (length < (int32_t)(sizeof(indexes))) { + udata_printError(ds, "udict_swap(): too few bytes (%d after header) for dictionary data\n", length); + *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + } + + for (i = 0; i < DictionaryData::IX_COUNT; i++) { + indexes[i] = udata_readInt32(ds, inIndexes[i]); + } + + size = indexes[DictionaryData::IX_TOTAL_SIZE]; + + if (length >= 0) { + if (length < size) { + udata_printError(ds, "udict_swap(): too few bytes (%d after header) for all of dictionary data\n", length); + *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + if (inBytes != outBytes) { + uprv_memcpy(outBytes, inBytes, size); + } + + offset = 0; + ds->swapArray32(ds, inBytes, sizeof(indexes), outBytes, pErrorCode); + offset = (int32_t)sizeof(indexes); + int32_t trieType = indexes[DictionaryData::IX_TRIE_TYPE] & DictionaryData::TRIE_TYPE_MASK; + int32_t nextOffset = indexes[DictionaryData::IX_RESERVED1_OFFSET]; + + if (trieType == DictionaryData::TRIE_TYPE_UCHARS) { + ds->swapArray16(ds, inBytes + offset, nextOffset - offset, outBytes + offset, pErrorCode); + } else if (trieType == DictionaryData::TRIE_TYPE_BYTES) { + // nothing to do + } else { + udata_printError(ds, "udict_swap(): unknown trie type!\n"); + *pErrorCode = U_UNSUPPORTED_ERROR; + return 0; + } + + // these next two sections are empty in the current format, + // but may be used later. + offset = nextOffset; + nextOffset = indexes[DictionaryData::IX_RESERVED2_OFFSET]; + offset = nextOffset; + nextOffset = indexes[DictionaryData::IX_TOTAL_SIZE]; + offset = nextOffset; + } + return headerSize + size; +} +#endif diff --git a/Build/source/libs/icu/icu-50.1/common/dictionarydata.h b/Build/source/libs/icu/icu-50.1/common/dictionarydata.h new file mode 100644 index 00000000000..eedc926fa09 --- /dev/null +++ b/Build/source/libs/icu/icu-50.1/common/dictionarydata.h @@ -0,0 +1,165 @@ +/* +******************************************************************************* +* Copyright (C) 2012, International Business Machines +* Corporation and others. All Rights Reserved. +******************************************************************************* +* dictionarydata.h +* +* created on: 2012may31 +* created by: Markus W. Scherer & Maxime Serrano +*/ + +#ifndef __DICTIONARYDATA_H__ +#define __DICTIONARYDATA_H__ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_BREAK_ITERATION + +#include "unicode/utext.h" +#include "unicode/udata.h" +#include "udataswp.h" +#include "unicode/uobject.h" +#include "unicode/ustringtrie.h" + +U_NAMESPACE_BEGIN + +class UCharsTrie; +class BytesTrie; + +class U_COMMON_API DictionaryData : public UMemory { +public: + static const int32_t TRIE_TYPE_BYTES = 0; + static const int32_t TRIE_TYPE_UCHARS = 1; + static const int32_t TRIE_TYPE_MASK = 7; + static const int32_t TRIE_HAS_VALUES = 8; + + static const int32_t TRANSFORM_NONE = 0; + static const int32_t TRANSFORM_TYPE_OFFSET = 0x1000000; + static const int32_t TRANSFORM_TYPE_MASK = 0x7f000000; + static const int32_t TRANSFORM_OFFSET_MASK = 0x1fffff; + + enum { + // Byte offsets from the start of the data, after the generic header. + IX_STRING_TRIE_OFFSET, + IX_RESERVED1_OFFSET, + IX_RESERVED2_OFFSET, + IX_TOTAL_SIZE, + + // Trie type: TRIE_HAS_VALUES | TRIE_TYPE_BYTES etc. + IX_TRIE_TYPE, + // Transform specification: TRANSFORM_TYPE_OFFSET | 0xe00 etc. + IX_TRANSFORM, + + IX_RESERVED6, + IX_RESERVED7, + IX_COUNT + }; +}; + +/** + * Wrapper class around generic dictionaries, implementing matches(). + * getType() should return a TRIE_TYPE_??? constant from DictionaryData. + * + * All implementations of this interface must be thread-safe if they are to be used inside of the + * dictionary-based break iteration code. + */ +class U_COMMON_API DictionaryMatcher : public UMemory { +public: + virtual ~DictionaryMatcher(); + // this should emulate CompactTrieDictionary::matches() + virtual int32_t matches(UText *text, int32_t maxLength, int32_t *lengths, int &count, + int limit, int32_t *values = NULL) const = 0; + /** @return DictionaryData::TRIE_TYPE_XYZ */ + virtual int32_t getType() const = 0; +}; + +// Implementation of the DictionaryMatcher interface for a UCharsTrie dictionary +class U_COMMON_API UCharsDictionaryMatcher : public DictionaryMatcher { +public: + // constructs a new UCharsDictionaryMatcher. + // The UDataMemory * will be closed on this object's destruction. + UCharsDictionaryMatcher(const UChar *c, UDataMemory *f) : characters(c), file(f) { } + virtual ~UCharsDictionaryMatcher(); + virtual int32_t matches(UText *text, int32_t maxLength, int32_t *lengths, int &count, + int limit, int32_t *values = NULL) const; + virtual int32_t getType() const; +private: + const UChar *characters; + UDataMemory *file; +}; + +// Implementation of the DictionaryMatcher interface for a BytesTrie dictionary +class U_COMMON_API BytesDictionaryMatcher : public DictionaryMatcher { +public: + // constructs a new BytesTrieDictionaryMatcher + // the transform constant should be the constant read from the file, not a masked version! + // the UDataMemory * fed in here will be closed on this object's destruction + BytesDictionaryMatcher(const char *c, int32_t t, UDataMemory *f) + : characters(c), transformConstant(t), file(f) { } + virtual ~BytesDictionaryMatcher(); + virtual int32_t matches(UText *text, int32_t maxLength, int32_t *lengths, int &count, + int limit, int32_t *values = NULL) const; + virtual int32_t getType() const; +private: + UChar32 transform(UChar32 c) const; + + const char *characters; + int32_t transformConstant; + UDataMemory *file; +}; + +U_NAMESPACE_END + +U_CAPI int32_t U_EXPORT2 +udict_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData, UErrorCode *pErrorCode); + +/** + * Format of dictionary .dict data files. + * Format version 1.0. + * + * A dictionary .dict data file contains a byte-serialized BytesTrie or + * a UChars-serialized UCharsTrie. + * Such files are used in dictionary-based break iteration (DBBI). + * + * For a BytesTrie, a transformation type is specified for + * transforming Unicode strings into byte sequences. + * + * A .dict file begins with a standard ICU data file header + * (DataHeader, see ucmndata.h and unicode/udata.h). + * The UDataInfo.dataVersion field is currently unused (set to 0.0.0.0). + * + * After the header, the file contains the following parts. + * Constants are defined in the DictionaryData class. + * + * For the data structure of BytesTrie & UCharsTrie see + * http://site.icu-project.org/design/struct/tries + * and the bytestrie.h and ucharstrie.h header files. + * + * int32_t indexes[indexesLength]; -- indexesLength=indexes[IX_STRING_TRIE_OFFSET]/4; + * + * The first four indexes are byte offsets in ascending order. + * Each byte offset marks the start of the next part in the data file, + * and the end of the previous one. + * When two consecutive byte offsets are the same, then the corresponding part is empty. + * Byte offsets are offsets from after the header, + * that is, from the beginning of the indexes[]. + * Each part starts at an offset with proper alignment for its data. + * If necessary, the previous part may include padding bytes to achieve this alignment. + * + * trieType=indexes[IX_TRIE_TYPE] defines the trie type. + * transform=indexes[IX_TRANSFORM] defines the Unicode-to-bytes transformation. + * If the transformation type is TRANSFORM_TYPE_OFFSET, + * then the lower 21 bits contain the offset code point. + * Each code point c is mapped to byte b = (c - offset). + * Code points outside the range offset..(offset+0xff) cannot be mapped + * and do not occur in the dictionary. + * + * stringTrie; -- a serialized BytesTrie or UCharsTrie + * + * The dictionary maps strings to specific values (TRIE_HAS_VALUES bit set in trieType), + * or it maps all strings to 0 (TRIE_HAS_VALUES bit not set). + */ + +#endif /* !UCONFIG_NO_BREAK_ITERATION */ +#endif /* __DICTIONARYDATA_H__ */ diff --git a/Build/source/libs/icu/icu-50.1/common/listformatter.cpp b/Build/source/libs/icu/icu-50.1/common/listformatter.cpp new file mode 100644 index 00000000000..6a6e986377d --- /dev/null +++ b/Build/source/libs/icu/icu-50.1/common/listformatter.cpp @@ -0,0 +1,325 @@ +/* +******************************************************************************* +* +* Copyright (C) 2012, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: listformatter.cpp +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2012aug27 +* created by: Umesh P. Nair +*/ + +#include "unicode/listformatter.h" +#include "mutex.h" +#include "hash.h" +#include "cstring.h" +#include "ulocimp.h" +#include "charstr.h" +#include "ucln_cmn.h" + +U_NAMESPACE_BEGIN + +static Hashtable* listPatternHash = NULL; +static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; +static UChar FIRST_PARAMETER[] = { 0x7b, 0x30, 0x7d }; // "{0}" +static UChar SECOND_PARAMETER[] = { 0x7b, 0x31, 0x7d }; // "{0}" + +U_CDECL_BEGIN +static UBool U_CALLCONV uprv_listformatter_cleanup() { + delete listPatternHash; + listPatternHash = NULL; + return TRUE; +} + +static void U_CALLCONV +uprv_deleteListFormatData(void *obj) { + delete static_cast(obj); +} + +U_CDECL_END + +void ListFormatter::initializeHash(UErrorCode& errorCode) { + if (U_FAILURE(errorCode)) { + return; + } + + listPatternHash = new Hashtable(); + if (listPatternHash == NULL) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + + listPatternHash->setValueDeleter(uprv_deleteListFormatData); + ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_cleanup); + + addDataToHash("af", "{0} en {1}", "{0}, {1}", "{0}, {1}", "{0} en {1}", errorCode); + addDataToHash("am", "{0} \\u12a5\\u1293 {1}", "{0}, {1}", "{0}, {1}", "{0}, \\u12a5\\u1293 {1}", errorCode); + addDataToHash("ar", "{0} \\u0648 {1}", "{0}\\u060c {1}", "{0}\\u060c {1}", "{0}\\u060c \\u0648 {1}", errorCode); + addDataToHash("bg", "{0} \\u0438 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0438 {1}", errorCode); + addDataToHash("bn", "{0} \\u098f\\u09ac\\u0982 {1}", "{0}, {1}", "{0}, {1}", "{0}, \\u098f\\u09ac\\u0982 {1}", errorCode); + addDataToHash("bs", "{0} i {1}", "{0}, {1}", "{0}, {1}", "{0} i {1}", errorCode); + addDataToHash("ca", "{0} i {1}", "{0}, {1}", "{0}, {1}", "{0} i {1}", errorCode); + addDataToHash("cs", "{0} a {1}", "{0}, {1}", "{0}, {1}", "{0} a {1}", errorCode); + addDataToHash("da", "{0} og {1}", "{0}, {1}", "{0}, {1}", "{0} og {1}", errorCode); + addDataToHash("de", "{0} und {1}", "{0}, {1}", "{0}, {1}", "{0} und {1}", errorCode); + addDataToHash("ee", "{0} kple {1}", "{0}, {1}", "{0}, {1}", "{0}, kple {1}", errorCode); + addDataToHash("el", "{0} \\u03ba\\u03b1\\u03b9 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u03ba\\u03b1\\u03b9 {1}", errorCode); + addDataToHash("en", "{0} and {1}", "{0}, {1}", "{0}, {1}", "{0}, and {1}", errorCode); + addDataToHash("es", "{0} y {1}", "{0}, {1}", "{0}, {1}", "{0} y {1}", errorCode); + addDataToHash("et", "{0} ja {1}", "{0}, {1}", "{0}, {1}", "{0} ja {1}", errorCode); + addDataToHash("eu", "{0} eta {1}", "{0}, {1}", "{0}, {1}", "{0} eta {1}", errorCode); + addDataToHash("fa", "{0} \\u0648 {1}", "{0}\\u060c\\u200f {1}", "{0}\\u060c\\u200f {1}", "{0}\\u060c \\u0648 {1}", errorCode); + addDataToHash("fi", "{0} ja {1}", "{0}, {1}", "{0}, {1}", "{0} ja {1}", errorCode); + addDataToHash("fil", "{0} at {1}", "{0}, {1}", "{0}, {1}", "{0} at {1}", errorCode); + addDataToHash("fo", "{0} og {1}", "{0}, {1}", "{0}, {1}", "{0} og {1}", errorCode); + addDataToHash("fr", "{0} et {1}", "{0}, {1}", "{0}, {1}", "{0} et {1}", errorCode); + addDataToHash("fur", "{0} e {1}", "{0}, {1}", "{0}, {1}", "{0} e {1}", errorCode); + addDataToHash("gd", "{0} agus {1}", "{0}, {1}", "{0}, {1}", "{0}, agus {1}", errorCode); + addDataToHash("gl", "{0} e {1}", "{0}, {1}", "{0}, {1}", "{0} e {1}", errorCode); + addDataToHash("gsw", "{0} und {1}", "{0}, {1}", "{0}, {1}", "{0} und {1}", errorCode); + addDataToHash("gu", "{0} \\u0a85\\u0aa8\\u0ac7 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0a85\\u0aa8\\u0ac7 {1}", errorCode); + addDataToHash("he", "{0} \\u05d5-{1}", "{0}, {1}", "{0}, {1}", "{0} \\u05d5-{1}", errorCode); + addDataToHash("hi", "{0} \\u0914\\u0930 {1}", "{0}, {1}", "{0}, {1}", "{0}, \\u0914\\u0930 {1}", errorCode); + addDataToHash("hr", "{0} i {1}", "{0}, {1}", "{0}, {1}", "{0} i {1}", errorCode); + addDataToHash("hu", "{0} \\u00e9s {1}", "{0}, {1}", "{0}, {1}", "{0} \\u00e9s {1}", errorCode); + addDataToHash("id", "{0} dan {1}", "{0}, {1}", "{0}, {1}", "{0}, dan {1}", errorCode); + addDataToHash("is", "{0} og {1}", "{0}, {1}", "{0}, {1}", "{0} og {1}", errorCode); + addDataToHash("it", "{0} e {1}", "{0}, {1}", "{0}, {1}", "{0}, e {1}", errorCode); + addDataToHash("ja", "{0}\\u3001{1}", "{0}\\u3001{1}", "{0}\\u3001{1}", "{0}\\u3001{1}", errorCode); + addDataToHash("ka", "{0} \\u10d3\\u10d0 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u10d3\\u10d0 {1}", errorCode); + addDataToHash("kea", "{0} y {1}", "{0}, {1}", "{0}, {1}", "{0} y {1}", errorCode); + addDataToHash("kl", "{0} aamma {1}", "{0} aamma {1}", "{0}, {1}", "{0}, {1}", errorCode); + addDataToHash("kn", "{0} \\u0cae\\u0ca4\\u0ccd\\u0ca4\\u0cc1 {1}", "{0}, {1}", "{0}, {1}", + "{0}, \\u0cae\\u0ca4\\u0ccd\\u0ca4\\u0cc1 {1}", errorCode); + addDataToHash("ko", "{0} \\ubc0f {1}", "{0}, {1}", "{0}, {1}", "{0} \\ubc0f {1}", errorCode); + addDataToHash("ksh", "{0} un {1}", "{0}, {1}", "{0}, {1}", "{0} un {1}", errorCode); + addDataToHash("lt", "{0} ir {1}", "{0}, {1}", "{0}, {1}", "{0} ir {1}", errorCode); + addDataToHash("lv", "{0} un {1}", "{0}, {1}", "{0}, {1}", "{0} un {1}", errorCode); + addDataToHash("ml", "{0} \\u0d15\\u0d42\\u0d1f\\u0d3e\\u0d24\\u0d46 {1}", "{0}, {1}", "{0}, {1}", + "{0}, {1} \\u0d0e\\u0d28\\u0d4d\\u0d28\\u0d3f\\u0d35", errorCode); + addDataToHash("mr", "{0} \\u0906\\u0923\\u093f {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0906\\u0923\\u093f {1}", errorCode); + addDataToHash("ms", "{0} dan {1}", "{0}, {1}", "{0}, {1}", "{0}, dan {1}", errorCode); + addDataToHash("nb", "{0} og {1}", "{0}, {1}", "{0}, {1}", "{0} og {1}", errorCode); + addDataToHash("nl", "{0} en {1}", "{0}, {1}", "{0}, {1}", "{0} en {1}", errorCode); + addDataToHash("nn", "{0} og {1}", "{0}, {1}", "{0}, {1}", "{0} og {1}", errorCode); + addDataToHash("pl", "{0} i {1}", "{0}; {1}", "{0}; {1}", "{0} i {1}", errorCode); + addDataToHash("pt", "{0} e {1}", "{0}, {1}", "{0}, {1}", "{0} e {1}", errorCode); + addDataToHash("ro", "{0} \\u015fi {1}", "{0}, {1}", "{0}, {1}", "{0} \\u015fi {1}", errorCode); + addDataToHash("", "{0}, {1}", "{0}, {1}", "{0}, {1}", "{0}, {1}", errorCode); // root + addDataToHash("ru", "{0} \\u0438 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0438 {1}", errorCode); + addDataToHash("se", "{0} ja {1}", "{0}, {1}", "{0}, {1}", "{0} ja {1}", errorCode); + addDataToHash("sk", "{0} a {1}", "{0}, {1}", "{0}, {1}", "{0} a {1}", errorCode); + addDataToHash("sl", "{0} in {1}", "{0}, {1}", "{0}, {1}", "{0} in {1}", errorCode); + addDataToHash("sr", "{0} \\u0438 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0438 {1}", errorCode); + addDataToHash("sr_Cyrl", "{0} \\u0438 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0438 {1}", errorCode); + addDataToHash("sr_Latn", "{0} i {1}", "{0}, {1}", "{0}, {1}", "{0} i {1}", errorCode); + addDataToHash("sv", "{0} och {1}", "{0}, {1}", "{0}, {1}", "{0} och {1}", errorCode); + addDataToHash("sw", "{0} na {1}", "{0}, {1}", "{0}, {1}", "{0}, na {1}", errorCode); + addDataToHash("ta", "{0} \\u0bae\\u0bb1\\u0bcd\\u0bb1\\u0bc1\\u0bae\\u0bcd {1}", "{0}, {1}", "{0}, {1}", + "{0} \\u0bae\\u0bb1\\u0bcd\\u0bb1\\u0bc1\\u0bae\\u0bcd {1}", errorCode); + addDataToHash("te", "{0} \\u0c2e\\u0c30\\u0c3f\\u0c2f\\u0c41 {1}", "{0}, {1}", "{0}, {1}", + "{0} \\u0c2e\\u0c30\\u0c3f\\u0c2f\\u0c41 {1}", errorCode); + addDataToHash("th", "{0}\\u0e41\\u0e25\\u0e30{1}", "{0} {1}", "{0} {1}", "{0} \\u0e41\\u0e25\\u0e30{1}", errorCode); + addDataToHash("tr", "{0} ve {1}", "{0}, {1}", "{0}, {1}", "{0} ve {1}", errorCode); + addDataToHash("uk", "{0} \\u0442\\u0430 {1}", "{0}, {1}", "{0}, {1}", "{0} \\u0442\\u0430 {1}", errorCode); + addDataToHash("ur", "{0} \\u0627\\u0648\\u0631 {1}", "{0}\\u060c {1}", "{0}\\u060c {1}", + "{0}\\u060c \\u0627\\u0648\\u0631 {1}", errorCode); + addDataToHash("vi", "{0} v\\u00e0 {1}", "{0}, {1}", "{0}, {1}", "{0} v\\u00e0 {1}", errorCode); + addDataToHash("wae", "{0} und {1}", "{0}, {1}", "{0}, {1}", "{0} und {1}", errorCode); + addDataToHash("zh", "{0}\\u548c{1}", "{0}\\u3001{1}", "{0}\\u3001{1}", "{0}\\u548c{1}", errorCode); + addDataToHash("zu", "I-{0} ne-{1}", "{0}, {1}", "{0}, {1}", "{0}, no-{1}", errorCode); +} + +void ListFormatter::addDataToHash( + const char* locale, + const char* two, + const char* start, + const char* middle, + const char* end, + UErrorCode& errorCode) { + if (U_FAILURE(errorCode)) { + return; + } + UnicodeString key(locale, -1, US_INV); + ListFormatData* value = new ListFormatData( + UnicodeString(two, -1, US_INV).unescape(), + UnicodeString(start, -1, US_INV).unescape(), + UnicodeString(middle, -1, US_INV).unescape(), + UnicodeString(end, -1, US_INV).unescape()); + + if (value == NULL) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + listPatternHash->put(key, value, errorCode); +} + +const ListFormatData* ListFormatter::getListFormatData( + const Locale& locale, UErrorCode& errorCode) { + if (U_FAILURE(errorCode)) { + return NULL; + } + { + Mutex m(&listFormatterMutex); + if (listPatternHash == NULL) { + initializeHash(errorCode); + if (U_FAILURE(errorCode)) { + return NULL; + } + } + } + + UnicodeString key(locale.getName(), -1, US_INV); + return static_cast(listPatternHash->get(key)); +} + +ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) { + Locale locale; // The default locale. + return createInstance(locale, errorCode); +} + +ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& errorCode) { + Locale tempLocale = locale; + for (;;) { + const ListFormatData* listFormatData = getListFormatData(tempLocale, errorCode); + if (U_FAILURE(errorCode)) { + return NULL; + } + if (listFormatData != NULL) { + ListFormatter* p = new ListFormatter(*listFormatData); + if (p == NULL) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + return p; + } + errorCode = U_ZERO_ERROR; + Locale correctLocale; + getFallbackLocale(tempLocale, correctLocale, errorCode); + if (U_FAILURE(errorCode)) { + return NULL; + } + if (correctLocale.isBogus()) { + return createInstance(Locale::getRoot(), errorCode); + } + tempLocale = correctLocale; + } +} + +ListFormatter::ListFormatter(const ListFormatData& listFormatterData) : data(listFormatterData) { +} + +ListFormatter::~ListFormatter() {} + +void ListFormatter::getFallbackLocale(const Locale& in, Locale& out, UErrorCode& errorCode) { + if (uprv_strcmp(in.getName(), "zh_TW") == 0) { + out = Locale::getTraditionalChinese(); + } else { + const char* localeString = in.getName(); + const char* extStart = locale_getKeywordsStart(localeString); + if (extStart == NULL) { + extStart = uprv_strchr(localeString, 0); + } + const char* last = extStart; + + // TODO: Check whether uloc_getParent() will work here. + while (last > localeString && *(last - 1) != '_') { + --last; + } + + // Truncate empty segment. + while (last > localeString) { + if (*(last-1) != '_') { + break; + } + --last; + } + + size_t localePortionLen = last - localeString; + CharString fullLocale; + fullLocale.append(localeString, localePortionLen, errorCode).append(extStart, errorCode); + + if (U_FAILURE(errorCode)) { + return; + } + out = Locale(fullLocale.data()); + } +} + +UnicodeString& ListFormatter::format(const UnicodeString items[], int32_t nItems, + UnicodeString& appendTo, UErrorCode& errorCode) const { + if (U_FAILURE(errorCode)) { + return appendTo; + } + + if (nItems > 0) { + UnicodeString newString = items[0]; + if (nItems == 2) { + addNewString(data.twoPattern, newString, items[1], errorCode); + } else if (nItems > 2) { + addNewString(data.startPattern, newString, items[1], errorCode); + int i; + for (i = 2; i < nItems - 1; ++i) { + addNewString(data.middlePattern, newString, items[i], errorCode); + } + addNewString(data.endPattern, newString, items[nItems - 1], errorCode); + } + if (U_SUCCESS(errorCode)) { + appendTo += newString; + } + } + return appendTo; +} + +/** + * Joins originalString and nextString using the pattern pat and puts the result in + * originalString. + */ +void ListFormatter::addNewString(const UnicodeString& pat, UnicodeString& originalString, + const UnicodeString& nextString, UErrorCode& errorCode) const { + if (U_FAILURE(errorCode)) { + return; + } + + int32_t p0Offset = pat.indexOf(FIRST_PARAMETER, 3, 0); + if (p0Offset < 0) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + int32_t p1Offset = pat.indexOf(SECOND_PARAMETER, 3, 0); + if (p1Offset < 0) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + int32_t i, j; + + const UnicodeString* firstString; + const UnicodeString* secondString; + if (p0Offset < p1Offset) { + i = p0Offset; + j = p1Offset; + firstString = &originalString; + secondString = &nextString; + } else { + i = p1Offset; + j = p0Offset; + firstString = &nextString; + secondString = &originalString; + } + + UnicodeString result = UnicodeString(pat, 0, i) + *firstString; + result += UnicodeString(pat, i+3, j-i-3); + result += *secondString; + result += UnicodeString(pat, j+3); + originalString = result; +} + +UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(ListFormatter) + +U_NAMESPACE_END diff --git a/Build/source/libs/icu/icu-50.1/common/umutex.cpp b/Build/source/libs/icu/icu-50.1/common/umutex.cpp new file mode 100644 index 00000000000..a7299a5cfd1 --- /dev/null +++ b/Build/source/libs/icu/icu-50.1/common/umutex.cpp @@ -0,0 +1,483 @@ +/* +****************************************************************************** +* +* Copyright (C) 1997-2012, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +* +* File umutex.cpp +* +* Modification History: +* +* Date Name Description +* 04/02/97 aliu Creation. +* 04/07/99 srl updated +* 05/13/99 stephen Changed to umutex (from cmutex). +* 11/22/99 aliu Make non-global mutex autoinitialize [j151] +****************************************************************************** +*/ + +#include "unicode/utypes.h" +#include "uassert.h" +#include "ucln_cmn.h" + +/* + * ICU Mutex wrappers. Wrap operating system mutexes, giving the rest of ICU a + * platform independent set of mutex operations. For internal ICU use only. + */ + +#if U_PLATFORM_HAS_WIN32_API + /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */ +# undef POSIX +#elif U_PLATFORM_IMPLEMENTS_POSIX +# define POSIX +#else +# undef POSIX +#endif + +#if defined(POSIX) +# include /* must be first, so that we get the multithread versions of things. */ +#endif /* POSIX */ + +#if U_PLATFORM_HAS_WIN32_API +# define WIN32_LEAN_AND_MEAN +# define VC_EXTRALEAN +# define NOUSER +# define NOSERVICE +# define NOIME +# define NOMCX +# include +#endif + +#include "umutex.h" +#include "cmemory.h" + +#if U_PLATFORM_HAS_WIN32_API +#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \ + InterlockedCompareExchangePointer(dest, newval, oldval) + +#elif defined(POSIX) +#if (U_HAVE_GCC_ATOMICS == 1) +#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \ + __sync_val_compare_and_swap(dest, oldval, newval) +#else +#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \ + mutexed_compare_and_swap(dest, newval, oldval) +#endif + +#else +// Unknown platform. Note that user can still set mutex functions at run time. +#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \ + mutexed_compare_and_swap(dest, newval, oldval) +#endif + +static void *mutexed_compare_and_swap(void **dest, void *newval, void *oldval); + +// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. +static UMutex globalMutex = U_MUTEX_INITIALIZER; + +// Implementation mutex. Used for compare & swap when no intrinsic is available, and +// for safe initialization of user defined mutexes. +static UMutex implMutex = U_MUTEX_INITIALIZER; + +// List of all user mutexes that have been initialized. +// Used to allow us to destroy them when cleaning up ICU. +// Normal platform mutexes are not kept track of in this way - they survive until the process is shut down. +// Normal platfrom mutexes don't allocate storage, so not cleaning them up won't trigger memory leak complaints. +// +// Note: putting this list in allocated memory would be awkward to arrange, because memory allocations +// are used as a flag to indicate that ICU has been initialized, and setting other ICU +// override functions will no longer work. +// +static const int MUTEX_LIST_LIMIT = 100; +static UMutex *gMutexList[MUTEX_LIST_LIMIT]; +static int gMutexListSize = 0; + + +/* + * User mutex implementation functions. If non-null, call back to these rather than + * directly using the system (Posix or Windows) APIs. See u_setMutexFunctions(). + * (declarations are in uclean.h) + */ +static UMtxInitFn *pMutexInitFn = NULL; +static UMtxFn *pMutexDestroyFn = NULL; +static UMtxFn *pMutexLockFn = NULL; +static UMtxFn *pMutexUnlockFn = NULL; +static const void *gMutexContext = NULL; + + +// Clean up (undo) the effects of u_setMutexFunctions(). +// +static void usrMutexCleanup() { + if (pMutexDestroyFn != NULL) { + for (int i = 0; i < gMutexListSize; i++) { + UMutex *m = gMutexList[i]; + U_ASSERT(m->fInitialized); + (*pMutexDestroyFn)(gMutexContext, &m->fUserMutex); + m->fInitialized = FALSE; + } + (*pMutexDestroyFn)(gMutexContext, &globalMutex.fUserMutex); + (*pMutexDestroyFn)(gMutexContext, &implMutex.fUserMutex); + } + gMutexListSize = 0; + pMutexInitFn = NULL; + pMutexDestroyFn = NULL; + pMutexLockFn = NULL; + pMutexUnlockFn = NULL; + gMutexContext = NULL; +} + + +/* + * User mutex lock. + * + * User mutexes need to be initialized before they can be used. We use the impl mutex + * to synchronize the initialization check. This could be sped up on platforms that + * support alternate ways to safely check the initialization flag. + * + */ +static void usrMutexLock(UMutex *mutex) { + UErrorCode status = U_ZERO_ERROR; + if (!(mutex == &implMutex || mutex == &globalMutex)) { + umtx_lock(&implMutex); + if (!mutex->fInitialized) { + (*pMutexInitFn)(gMutexContext, &mutex->fUserMutex, &status); + U_ASSERT(U_SUCCESS(status)); + mutex->fInitialized = TRUE; + U_ASSERT(gMutexListSize < MUTEX_LIST_LIMIT); + if (gMutexListSize < MUTEX_LIST_LIMIT) { + gMutexList[gMutexListSize] = mutex; + ++gMutexListSize; + } + } + umtx_unlock(&implMutex); + } + (*pMutexLockFn)(gMutexContext, &mutex->fUserMutex); +} + + + +#if defined(POSIX) + +// +// POSIX implementation of UMutex. +// +// Each UMutex has a corresponding pthread_mutex_t. +// All are statically initialized and ready for use. +// There is no runtime mutex initialization code needed. + +U_CAPI void U_EXPORT2 +umtx_lock(UMutex *mutex) { + if (mutex == NULL) { + mutex = &globalMutex; + } + if (pMutexLockFn) { + usrMutexLock(mutex); + } else { + #if U_DEBUG + // #if to avoid unused variable warnings in non-debug builds. + int sysErr = pthread_mutex_lock(&mutex->fMutex); + U_ASSERT(sysErr == 0); + #else + pthread_mutex_lock(&mutex->fMutex); + #endif + } +} + + +U_CAPI void U_EXPORT2 +umtx_unlock(UMutex* mutex) +{ + if (mutex == NULL) { + mutex = &globalMutex; + } + if (pMutexUnlockFn) { + (*pMutexUnlockFn)(gMutexContext, &mutex->fUserMutex); + } else { + #if U_DEBUG + // #if to avoid unused variable warnings in non-debug builds. + int sysErr = pthread_mutex_unlock(&mutex->fMutex); + U_ASSERT(sysErr == 0); + #else + pthread_mutex_unlock(&mutex->fMutex); + #endif + } +} + +#elif U_PLATFORM_HAS_WIN32_API +// +// Windows implementation of UMutex. +// +// Each UMutex has a corresponding Windows CRITICAL_SECTION. +// CRITICAL_SECTIONS must be initialized before use. This is done +// with a InitOnceExcuteOnce operation. +// +// InitOnceExecuteOnce was introduced with Windows Vista. For now ICU +// must support Windows XP, so we roll our own. ICU will switch to the +// native Windows InitOnceExecuteOnce when possible. + +typedef UBool (*U_PINIT_ONCE_FN) ( + U_INIT_ONCE *initOnce, + void *parameter, + void **context +); + +UBool u_InitOnceExecuteOnce( + U_INIT_ONCE *initOnce, + U_PINIT_ONCE_FN initFn, + void *parameter, + void **context) { + for (;;) { + long previousState = InterlockedCompareExchange( + &initOnce->fState, // Destination, + 1, // Exchange Value + 0); // Compare value + if (previousState == 2) { + // Initialization was already completed. + if (context != NULL) { + *context = initOnce->fContext; + } + return TRUE; + } + if (previousState == 1) { + // Initialization is in progress in some other thread. + // Loop until it completes. + Sleep(1); + continue; + } + + // Initialization needed. Execute the callback function to do it. + U_ASSERT(previousState == 0); + U_ASSERT(initOnce->fState == 1); + UBool success = (*initFn)(initOnce, parameter, &initOnce->fContext); + U_ASSERT(success); // ICU is not supporting the failure case. + + // Assign the state indicating that initialization has completed. + // Using InterlockedCompareExchange to do it ensures that all + // threads will have a consistent view of memory. + previousState = InterlockedCompareExchange(&initOnce->fState, 2, 1); + U_ASSERT(previousState == 1); + // Next loop iteration will see the initialization and return. + } +}; + +static UBool winMutexInit(U_INIT_ONCE *initOnce, void *param, void **context) { + UMutex *mutex = static_cast(param); + U_ASSERT(sizeof(CRITICAL_SECTION) <= sizeof(mutex->fCS)); + InitializeCriticalSection((CRITICAL_SECTION *)mutex->fCS); + return TRUE; +} + +/* + * umtx_lock + */ +U_CAPI void U_EXPORT2 +umtx_lock(UMutex *mutex) { + if (mutex == NULL) { + mutex = &globalMutex; + } + if (pMutexLockFn) { + usrMutexLock(mutex); + } else { + u_InitOnceExecuteOnce(&mutex->fInitOnce, winMutexInit, mutex, NULL); + EnterCriticalSection((CRITICAL_SECTION *)mutex->fCS); + } +} + +U_CAPI void U_EXPORT2 +umtx_unlock(UMutex* mutex) +{ + if (mutex == NULL) { + mutex = &globalMutex; + } + if (pMutexUnlockFn) { + (*pMutexUnlockFn)(gMutexContext, &mutex->fUserMutex); + } else { + LeaveCriticalSection((CRITICAL_SECTION *)mutex->fCS); + } +} + +#endif // Windows Implementation + + +U_CAPI void U_EXPORT2 +u_setMutexFunctions(const void *context, UMtxInitFn *i, UMtxFn *d, UMtxFn *l, UMtxFn *u, + UErrorCode *status) { + if (U_FAILURE(*status)) { + return; + } + + /* Can not set a mutex function to a NULL value */ + if (i==NULL || d==NULL || l==NULL || u==NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + /* If ICU is not in an initial state, disallow this operation. */ + if (cmemory_inUse()) { + *status = U_INVALID_STATE_ERROR; + return; + } + + // Clean up any previously set user mutex functions. + // It's possible to call u_setMutexFunctions() more than once without without explicitly cleaning up, + // and the last call should take. Kind of a corner case, but it worked once, there is a test for + // it, so we keep it working. The global and impl mutexes will have been created by the + // previous u_setMutexFunctions(), and now need to be destroyed. + + usrMutexCleanup(); + + /* Swap in the mutex function pointers. */ + pMutexInitFn = i; + pMutexDestroyFn = d; + pMutexLockFn = l; + pMutexUnlockFn = u; + gMutexContext = context; + gMutexListSize = 0; + + /* Initialize the global and impl mutexes. Safe to do at this point because + * u_setMutexFunctions must be done in a single-threaded envioronment. Not thread safe. + */ + (*pMutexInitFn)(gMutexContext, &globalMutex.fUserMutex, status); + globalMutex.fInitialized = TRUE; + (*pMutexInitFn)(gMutexContext, &implMutex.fUserMutex, status); + implMutex.fInitialized = TRUE; +} + + + +/* synchronized compare and swap function, for use when OS or compiler built-in + * equivalents aren't available. + */ +static void *mutexed_compare_and_swap(void **dest, void *newval, void *oldval) { + umtx_lock(&implMutex); + void *temp = *dest; + if (temp == oldval) { + *dest = newval; + } + umtx_unlock(&implMutex); + + return temp; +} + + + +/*----------------------------------------------------------------- + * + * Atomic Increment and Decrement + * umtx_atomic_inc + * umtx_atomic_dec + * + *----------------------------------------------------------------*/ + +/* Pointers to user-supplied inc/dec functions. Null if no funcs have been set. */ +static UMtxAtomicFn *pIncFn = NULL; +static UMtxAtomicFn *pDecFn = NULL; +static const void *gIncDecContext = NULL; + +#if defined (POSIX) && (U_HAVE_GCC_ATOMICS == 0) +static UMutex gIncDecMutex = U_MUTEX_INITIALIZER; +#endif + +U_CAPI int32_t U_EXPORT2 +umtx_atomic_inc(int32_t *p) { + int32_t retVal; + if (pIncFn) { + retVal = (*pIncFn)(gIncDecContext, p); + } else { + #if U_PLATFORM_HAS_WIN32_API + retVal = InterlockedIncrement((LONG*)p); + #elif defined(USE_MAC_OS_ATOMIC_INCREMENT) + retVal = OSAtomicIncrement32Barrier(p); + #elif (U_HAVE_GCC_ATOMICS == 1) + retVal = __sync_add_and_fetch(p, 1); + #elif defined (POSIX) + umtx_lock(&gIncDecMutex); + retVal = ++(*p); + umtx_unlock(&gIncDecMutex); + #else + /* Unknown Platform. */ + retVal = ++(*p); + #endif + } + return retVal; +} + +U_CAPI int32_t U_EXPORT2 +umtx_atomic_dec(int32_t *p) { + int32_t retVal; + if (pDecFn) { + retVal = (*pDecFn)(gIncDecContext, p); + } else { + #if U_PLATFORM_HAS_WIN32_API + retVal = InterlockedDecrement((LONG*)p); + #elif defined(USE_MAC_OS_ATOMIC_INCREMENT) + retVal = OSAtomicDecrement32Barrier(p); + #elif (U_HAVE_GCC_ATOMICS == 1) + retVal = __sync_sub_and_fetch(p, 1); + #elif defined (POSIX) + umtx_lock(&gIncDecMutex); + retVal = --(*p); + umtx_unlock(&gIncDecMutex); + #else + /* Unknown Platform. */ + retVal = --(*p); + #endif + } + return retVal; +} + + + +U_CAPI void U_EXPORT2 +u_setAtomicIncDecFunctions(const void *context, UMtxAtomicFn *ip, UMtxAtomicFn *dp, + UErrorCode *status) { + if (U_FAILURE(*status)) { + return; + } + /* Can not set a mutex function to a NULL value */ + if (ip==NULL || dp==NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + /* If ICU is not in an initial state, disallow this operation. */ + if (cmemory_inUse()) { + *status = U_INVALID_STATE_ERROR; + return; + } + + pIncFn = ip; + pDecFn = dp; + gIncDecContext = context; + +#if U_DEBUG + { + int32_t testInt = 0; + U_ASSERT(umtx_atomic_inc(&testInt) == 1); /* Sanity Check. Do the functions work at all? */ + U_ASSERT(testInt == 1); + U_ASSERT(umtx_atomic_dec(&testInt) == 0); + U_ASSERT(testInt == 0); + } +#endif +} + + +/* + * Mutex Cleanup Function + * Reset the mutex function callback pointers. + * Called from the global ICU u_cleanup() function. + */ +U_CFUNC UBool umtx_cleanup(void) { + /* Extra, do-nothing function call to suppress compiler warnings on platforms where + * mutexed_compare_and_swap is not otherwise used. */ + void *pv = &globalMutex; + mutexed_compare_and_swap(&pv, NULL, NULL); + usrMutexCleanup(); + + pIncFn = NULL; + pDecFn = NULL; + gIncDecContext = NULL; + + return TRUE; +} diff --git a/Build/source/libs/icu/icu-50.1/common/unicode/listformatter.h b/Build/source/libs/icu/icu-50.1/common/unicode/listformatter.h new file mode 100644 index 00000000000..37042379db6 --- /dev/null +++ b/Build/source/libs/icu/icu-50.1/common/unicode/listformatter.h @@ -0,0 +1,134 @@ +/* +******************************************************************************* +* +* Copyright (C) 2012, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: listformatter.h +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 20120426 +* created by: Umesh P. Nair +*/ + +#ifndef __LISTFORMATTER_H__ +#define __LISTFORMATTER_H__ + +#include "unicode/unistr.h" +#include "unicode/locid.h" + + +U_NAMESPACE_BEGIN + +/** @internal */ +class Hashtable; + +/** @internal */ +struct ListFormatData : public UMemory { + UnicodeString twoPattern; + UnicodeString startPattern; + UnicodeString middlePattern; + UnicodeString endPattern; + + ListFormatData(const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end) : + twoPattern(two), startPattern(start), middlePattern(middle), endPattern(end) {} +}; + + +/** + * \file + * \brief C++ API: API for formatting a list. + */ + + +/** + * An immutable class for formatting a list, using data from CLDR (or supplied + * separately). + * + * Example: Input data ["Alice", "Bob", "Charlie", "Delta"] will be formatted + * as "Alice, Bob, Charlie and Delta" in English. + * + * The ListFormatter class is not intended for public subclassing. + */ +class U_COMMON_API ListFormatter : public UObject{ + + public: + /** + * Creates a ListFormatter appropriate for the default locale. + * + * @param errorCode ICU error code, set if no data available for default locale. + * @return Pointer to a ListFormatter object for the default locale, + * created from internal data derived from CLDR data. + * @draft ICU 50 + */ + static ListFormatter* createInstance(UErrorCode& errorCode); + + /** + * Creates a ListFormatter appropriate for a locale. + * + * @param locale The locale. + * @param errorCode ICU error code, set if no data available for the given locale. + * @return A ListFormatter object created from internal data derived from + * CLDR data. + * @draft ICU 50 + */ + static ListFormatter* createInstance(const Locale& locale, UErrorCode& errorCode); + + + /** + * Destructor. + * + * @draft ICU 50 + */ + virtual ~ListFormatter(); + + + /** + * Formats a list of strings. + * + * @param items An array of strings to be combined and formatted. + * @param n_items Length of the array items. + * @param appendTo The string to which the result should be appended to. + * @param errorCode ICU error code, set if there is an error. + * @return Formatted string combining the elements of items, appended to appendTo. + * @draft ICU 50 + */ + UnicodeString& format(const UnicodeString items[], int32_t n_items, + UnicodeString& appendTo, UErrorCode& errorCode) const; + + /** + * Gets the fallback locale for a given locale. + * TODO: Consider moving this to the Locale class. + * @param in The input locale. + * @param out The output locale after fallback. + * @internal For testing. + */ + static void getFallbackLocale(const Locale& in, Locale& out, UErrorCode& errorCode); + + /** + * @internal constructor made public for testing. + */ + ListFormatter(const ListFormatData& listFormatterData); + + private: + static void initializeHash(UErrorCode& errorCode); + static void addDataToHash(const char* locale, const char* two, const char* start, const char* middle, const char* end, UErrorCode& errorCode); + static const ListFormatData* getListFormatData(const Locale& locale, UErrorCode& errorCode); + + ListFormatter(); + ListFormatter(const ListFormatter&); + + ListFormatter& operator = (const ListFormatter&); + void addNewString(const UnicodeString& pattern, UnicodeString& originalString, + const UnicodeString& newString, UErrorCode& errorCode) const; + virtual UClassID getDynamicClassID() const; + + const ListFormatData& data; +}; + +U_NAMESPACE_END + +#endif diff --git a/Build/source/libs/icu/icu-50.1/common/utypeinfo.h b/Build/source/libs/icu/icu-50.1/common/utypeinfo.h new file mode 100644 index 00000000000..4de16d6d790 --- /dev/null +++ b/Build/source/libs/icu/icu-50.1/common/utypeinfo.h @@ -0,0 +1,27 @@ +/* +****************************************************************************** +* +* Copyright (C) 2012, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +*/ + +#ifndef __UTYPEINFO_H__ +#define __UTYPEINFO_H__ + +// Windows header does not define 'exception' in 'std' namespace. +// Therefore, a project using ICU cannot be compiled with _HAS_EXCEPTION +// set to 0 on Windows with Visual Studio. To work around that, we have to +// include explicilty and add using statement below. +// Whenever 'typeid' is used, this header has to be included +// instead of . +// Visual Stuido 10 emits warning 4275 with this change. If you compile +// with exception disabled, you have to suppress warning 4275. +#if defined(_MSC_VER) && _HAS_EXCEPTIONS == 0 +#include +using std::exception; +#endif +#include // for 'typeid' to work + +#endif -- cgit v1.2.3