10596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert*   Copyright (C) 1997-2016, International Business Machines
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  FILE NAME : putil.c (previously putil.cpp and ptypes.cpp)
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/14/97    aliu        Creation.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/24/97    aliu        Added getDefaultDataDirectory() and
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            getDefaultLocaleID().
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/28/97    aliu        Rewritten to assume Unix and apply general methods
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            for assumed case.  Non-UNIX platforms must be
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            special-cased.  Rewrote numeric methods dealing
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            with NaN and Infinity to be platform independent
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                             over all IEEE 754 platforms.
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/13/97    aliu        Restored sign of timezone
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            (semantics are hours West of GMT)
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/16/98    erm         Added IEEE_754 stuff, cleaned up isInfinite, isNan,
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                             nextDouble..
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/22/98    stephen     Added remainder, max, min, trunc
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   08/13/98    stephen     Added isNegativeInfinity, isPositiveInfinity
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   08/24/98    stephen     Added longBitsFromDouble
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   09/08/98    stephen     Minor changes for Mac Port
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   03/02/99    stephen     Removed openFile().  Added AS400 support.
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            Fixed EBCDIC tables
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/15/99    stephen     Converted to C.
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/28/99    stephen     Removed mutex locking in u_isBigEndian().
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   08/04/99    jeffrey R.  Added OS/2 changes
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   11/15/99    helena      Integrated S/390 IEEE support.
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/26/01    Barry N.    OS/400 support for uprv_getDefaultLocaleID
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   08/15/01    Steven H.   OS/400 support for uprv_getDefaultCodepage
3885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho*   01/03/08    Steven L.   Fake Time Support
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
42103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Defines _XOPEN_SOURCE for access to POSIX functions.
43103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Must be before any other #includes.
44103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uposixdefs.h"
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
460596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// First, the platform type. Need this for U_PLATFORM.
470596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include "unicode/platform.h"
480596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
490596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM == U_PF_MINGW && defined __STRICT_ANSI__
500596faeddefbf198de137d5e893708495ab1584cFredrik Roubert/* tzset isn't defined in strict ANSI on MinGW. */
510596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#undef __STRICT_ANSI__
520596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
530596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
540596faeddefbf198de137d5e893708495ab1584cFredrik Roubert/*
550596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * Cygwin with GCC requires inclusion of time.h after the above disabling strict asci mode statement.
560596faeddefbf198de137d5e893708495ab1584cFredrik Roubert */
570596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include <time.h>
580596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
590596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if !U_PLATFORM_USES_ONLY_WIN32_API
600596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include <sys/time.h>
610596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
620596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
630596faeddefbf198de137d5e893708495ab1584cFredrik Roubert/* include the rest of the ICU headers */
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "putilimp.h"
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "locmap.h"
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_cmn.h"
73f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "charstr.h"
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Include standard headers. */
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdlib.h>
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <string.h>
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <math.h>
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <locale.h>
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <float.h>
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
83103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifndef U_COMMON_IMPLEMENTATION
84103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#error U_COMMON_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu
85103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
86103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
87103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* include system headers */
89103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
90103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    /*
91103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius     * TODO: U_PLATFORM_USES_ONLY_WIN32_API includes MinGW.
92103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius     * Should Cygwin be included as well (U_PLATFORM_HAS_WIN32_API)
93103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius     * to use native APIs as much as possible?
94103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius     */
950596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#ifndef WIN32_LEAN_AND_MEAN
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define WIN32_LEAN_AND_MEAN
970596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define VC_EXTRALEAN
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define NOUSER
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define NOSERVICE
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define NOIME
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define NOMCX
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include <windows.h>
104ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#   include "unicode/uloc.h"
1050596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WINUWP_API == 0
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include "wintz.h"
1070596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#else // U_PLATFORM_HAS_WINUWP_API
1080596faeddefbf198de137d5e893708495ab1584cFredrik Rouberttypedef PVOID LPMSG; // TODO: figure out how to get rid of this typedef
1090596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include <Windows.Globalization.h>
1100596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include <windows.system.userprofile.h>
111ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include <wrl/wrappers/corewrappers.h>
112ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include <wrl/client.h>
1130596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
1140596faeddefbf198de137d5e893708495ab1584cFredrik Roubertusing namespace ABI::Windows::Foundation;
1150596faeddefbf198de137d5e893708495ab1584cFredrik Roubertusing namespace Microsoft::WRL;
1160596faeddefbf198de137d5e893708495ab1584cFredrik Roubertusing namespace Microsoft::WRL::Wrappers;
1170596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
118103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS400
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include <float.h>
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include <qusec.h>       /* error code structure */
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include <qusrjobi.h>
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include <qliept.h>      /* EPT_CALL macro  - this include must be after all other "QSYSINCs" */
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   include <mih/testptr.h> /* For uprv_maximumPtr */
124103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS390
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#   include "unicode/ucnv.h"   /* Needed for UCNV_SWAP_LFNL_OPTION_STRING */
1268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#elif U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#   include <limits.h>
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#   include <unistd.h>
1298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#   if U_PLATFORM == U_PF_SOLARIS
1308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#       ifndef _XPG4_2
1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#           define _XPG4_2
1328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#       endif
1338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#   endif
134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_QNX
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#   include <sys/neutrino.h>
13650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
13750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Only include langinfo.h if we have a way to get the codeset. If we later
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * depend on more feature, we can test on U_HAVE_NL_LANGINFO.
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_HAVE_NL_LANGINFO_CODESET
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <langinfo.h>
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
14950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Simple things (presence of functions, etc) should just go in configure.in and be added to
15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * icucfg.h via autoheader.
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
152103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_IMPLEMENTS_POSIX
153103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   if U_PLATFORM == U_PF_OS400
154103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#    define HAVE_DLFCN_H 0
155103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#    define HAVE_DLOPEN 0
156103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   else
157103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   ifndef HAVE_DLFCN_H
158103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#    define HAVE_DLFCN_H 1
159103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   endif
160103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   ifndef HAVE_DLOPEN
161103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#    define HAVE_DLOPEN 1
162103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   endif
163103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   endif
164103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   ifndef HAVE_GETTIMEOFDAY
165103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#    define HAVE_GETTIMEOFDAY 1
166103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   endif
167103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#else
168103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   define HAVE_DLFCN_H 0
169103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   define HAVE_DLOPEN 0
170103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   define HAVE_GETTIMEOFDAY 0
17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
173f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_NAMESPACE_USE
174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Define the extension for data files, again... */
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define DATA_TYPE "dat"
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Leave this copyright notice here! */
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char copyright[] = U_COPYRIGHT_STRING;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* floating point implementations ------------------------------------------- */
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* We return QNAN rather than SNAN*/
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define SIGN 0x80000000U
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Make it easy to define certain types of constants */
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef union {
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int64_t i64; /* This must be defined first in order to allow the initialization to work. This is a C89 feature. */
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double d64;
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} BitPatternConversion;
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const BitPatternConversion gNan = { (int64_t) INT64_C(0x7FF8000000000000) };
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const BitPatternConversion gInf = { (int64_t) INT64_C(0x7FF0000000000000) };
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*---------------------------------------------------------------------------
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Platform utilities
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Our general strategy is to assume we're on a POSIX platform.  Platforms which
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  are non-POSIX must declare themselves so.  The default POSIX implementation
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  will sometimes work for non-POSIX platforms as well (e.g., the NaN-related
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  functions).
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ---------------------------------------------------------------------------*/
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
202f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#if U_PLATFORM_USES_ONLY_WIN32_API || U_PLATFORM == U_PF_OS400
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   undef U_POSIX_LOCALE
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   define U_POSIX_LOCALE    1
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    WARNING! u_topNBytesOfDouble and u_bottomNBytesOfDouble
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    can't be properly optimized by the gcc compiler sometimes (i.e. gcc 3.2).
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !IEEE_754
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char*
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_topNBytesOfDouble(double* d, int n)
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_IS_BIG_ENDIAN
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (char*)d;
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (char*)(d + 1) - n;
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char*
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_bottomNBytesOfDouble(double* d, int n)
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_IS_BIG_ENDIAN
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (char*)(d + 1) - n;
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (char*)d;
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
23227f654740f2a26ad62a5c155af9199af9e69b889claireho#endif   /* !IEEE_754 */
23327f654740f2a26ad62a5c155af9199af9e69b889claireho
23427f654740f2a26ad62a5c155af9199af9e69b889claireho#if IEEE_754
23527f654740f2a26ad62a5c155af9199af9e69b889clairehostatic UBool
23627f654740f2a26ad62a5c155af9199af9e69b889clairehou_signBit(double d) {
23727f654740f2a26ad62a5c155af9199af9e69b889claireho    uint8_t hiByte;
23827f654740f2a26ad62a5c155af9199af9e69b889claireho#if U_IS_BIG_ENDIAN
23927f654740f2a26ad62a5c155af9199af9e69b889claireho    hiByte = *(uint8_t *)&d;
24027f654740f2a26ad62a5c155af9199af9e69b889claireho#else
24127f654740f2a26ad62a5c155af9199af9e69b889claireho    hiByte = *(((uint8_t *)&d) + sizeof(double) - 1);
24227f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
24327f654740f2a26ad62a5c155af9199af9e69b889claireho    return (hiByte & 0x80) != 0;
24427f654740f2a26ad62a5c155af9199af9e69b889claireho}
24527f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
24627f654740f2a26ad62a5c155af9199af9e69b889claireho
24727f654740f2a26ad62a5c155af9199af9e69b889claireho
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if defined (U_DEBUG_FAKETIME)
25085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* Override the clock to test things without having to move the system clock.
25185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Assumes POSIX gettimeofday() will function
25285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
25385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUDate fakeClock_t0 = 0; /** Time to start the clock from **/
25485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUDate fakeClock_dt = 0; /** Offset (fake time - real time) **/
25585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool fakeClock_set = FALSE; /** True if fake clock has spun up **/
25654dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex fakeClockMutex = U_MUTEX_INTIALIZER;
25785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
25885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic UDate getUTCtime_real() {
25985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    struct timeval posixTime;
26085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    gettimeofday(&posixTime, NULL);
26185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return (UDate)(((int64_t)posixTime.tv_sec * U_MILLIS_PER_SECOND) + (posixTime.tv_usec/1000));
26285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
26385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
26485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic UDate getUTCtime_fake() {
26585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    umtx_lock(&fakeClockMutex);
26685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(!fakeClock_set) {
26785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UDate real = getUTCtime_real();
26885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        const char *fake_start = getenv("U_FAKETIME_START");
26927f654740f2a26ad62a5c155af9199af9e69b889claireho        if((fake_start!=NULL) && (fake_start[0]!=0)) {
27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            sscanf(fake_start,"%lf",&fakeClock_t0);
27127f654740f2a26ad62a5c155af9199af9e69b889claireho            fakeClock_dt = fakeClock_t0 - real;
27227f654740f2a26ad62a5c155af9199af9e69b889claireho            fprintf(stderr,"U_DEBUG_FAKETIME was set at compile time, so the ICU clock will start at a preset value\n"
27327f654740f2a26ad62a5c155af9199af9e69b889claireho                    "env variable U_FAKETIME_START=%.0f (%s) for an offset of %.0f ms from the current time %.0f\n",
27427f654740f2a26ad62a5c155af9199af9e69b889claireho                    fakeClock_t0, fake_start, fakeClock_dt, real);
27527f654740f2a26ad62a5c155af9199af9e69b889claireho        } else {
27627f654740f2a26ad62a5c155af9199af9e69b889claireho          fakeClock_dt = 0;
27727f654740f2a26ad62a5c155af9199af9e69b889claireho            fprintf(stderr,"U_DEBUG_FAKETIME was set at compile time, but U_FAKETIME_START was not set.\n"
27827f654740f2a26ad62a5c155af9199af9e69b889claireho                    "Set U_FAKETIME_START to the number of milliseconds since 1/1/1970 to set the ICU clock.\n");
27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
28085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fakeClock_set = TRUE;
28185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
28285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    umtx_unlock(&fakeClockMutex);
28385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return getUTCtime_real() + fakeClock_dt;
28585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
28685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
28785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
288103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef union {
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int64_t int64;
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FILETIME fileTime;
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} FileTimeConversion;   /* This is like a ULARGE_INTEGER */
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Number of 100 nanoseconds from 1/1/1601 to 1/1/1970 */
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define EPOCH_BIAS  INT64_C(116444736000000000)
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define HECTONANOSECOND_PER_MILLISECOND   10000
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*---------------------------------------------------------------------------
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Universal Implementations
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  These are designed to work on all platforms.  Try these, and if they
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  don't work on your platform, then special case your platform with new
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  implementations.
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru---------------------------------------------------------------------------*/
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UDate U_EXPORT2
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getUTCtime()
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
31085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if defined(U_DEBUG_FAKETIME)
31185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return getUTCtime_fake(); /* Hook for overriding the clock */
31227f654740f2a26ad62a5c155af9199af9e69b889claireho#else
31327f654740f2a26ad62a5c155af9199af9e69b889claireho    return uprv_getRawUTCtime();
31427f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
31527f654740f2a26ad62a5c155af9199af9e69b889claireho}
31627f654740f2a26ad62a5c155af9199af9e69b889claireho
31727f654740f2a26ad62a5c155af9199af9e69b889claireho/* Return UTC (GMT) time measured in milliseconds since 0:00 on 1/1/70.*/
31827f654740f2a26ad62a5c155af9199af9e69b889clairehoU_CAPI UDate U_EXPORT2
31927f654740f2a26ad62a5c155af9199af9e69b889clairehouprv_getRawUTCtime()
32027f654740f2a26ad62a5c155af9199af9e69b889claireho{
321f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#if U_PLATFORM_USES_ONLY_WIN32_API
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FileTimeConversion winTime;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    GetSystemTimeAsFileTime(&winTime.fileTime);
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UDate)((winTime.int64 - EPOCH_BIAS) / HECTONANOSECOND_PER_MILLISECOND);
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
328103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if HAVE_GETTIMEOFDAY
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct timeval posixTime;
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gettimeofday(&posixTime, NULL);
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UDate)(((int64_t)posixTime.tv_sec * U_MILLIS_PER_SECOND) + (posixTime.tv_usec/1000));
33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    time_t epochtime;
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    time(&epochtime);
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UDate)epochtime * U_MILLIS_PER_SECOND;
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*-----------------------------------------------------------------------------
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  IEEE 754
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  These methods detect and return NaN and infinity values for doubles
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  conforming to IEEE 754.  Platforms which support this standard include X86,
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Mac 680x0, Mac PowerPC, AIX RS/6000, and most others.
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  If this doesn't work on your platform, you have non-IEEE floating-point, and
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  will need to code your own versions.  A naive implementation is to return 0.0
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for getNaN and getInfinity, and false for isNaN and isInfinite.
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ---------------------------------------------------------------------------*/
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_isNaN(double number)
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if IEEE_754
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    BitPatternConversion convertedNumber;
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    convertedNumber.d64 = number;
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Infinity is 0x7FF0000000000000U. Anything greater than that is a NaN */
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)((convertedNumber.i64 & U_INT64_MAX) > gInf.i64);
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
360103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS390
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number,
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sizeof(uint32_t));
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t lowBits  = *(uint32_t*)u_bottomNBytesOfDouble(&number,
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sizeof(uint32_t));
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ((highBits & 0x7F080000L) == 0x7F080000L) &&
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (lowBits == 0x00000000L);
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If your platform doesn't support IEEE 754 but *does* have an NaN value,*/
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* you'll need to replace this default implementation with what's correct*/
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* for your platform.*/
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return number != number;
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_isInfinite(double number)
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if IEEE_754
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    BitPatternConversion convertedNumber;
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    convertedNumber.d64 = number;
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Infinity is exactly 0x7FF0000000000000U. */
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)((convertedNumber.i64 & U_INT64_MAX) == gInf.i64);
385103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS390
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number,
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sizeof(uint32_t));
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t lowBits  = *(uint32_t*)u_bottomNBytesOfDouble(&number,
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sizeof(uint32_t));
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ((highBits  & ~SIGN) == 0x70FF0000L) && (lowBits == 0x00000000L);
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If your platform doesn't support IEEE 754 but *does* have an infinity*/
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* value, you'll need to replace this default implementation with what's*/
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* correct for your platform.*/
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return number == (2.0 * number);
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_isPositiveInfinity(double number)
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
404103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if IEEE_754 || U_PLATFORM == U_PF_OS390
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(number > 0 && uprv_isInfinite(number));
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return uprv_isInfinite(number);
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_isNegativeInfinity(double number)
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
414103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if IEEE_754 || U_PLATFORM == U_PF_OS390
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(number < 0 && uprv_isInfinite(number));
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number,
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sizeof(uint32_t));
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return((highBits & SIGN) && uprv_isInfinite(number));
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getNaN()
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
428103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if IEEE_754 || U_PLATFORM == U_PF_OS390
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return gNan.d64;
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If your platform doesn't support IEEE 754 but *does* have an NaN value,*/
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* you'll need to replace this default implementation with what's correct*/
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* for your platform.*/
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0.0;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getInfinity()
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
441103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if IEEE_754 || U_PLATFORM == U_PF_OS390
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return gInf.d64;
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If your platform doesn't support IEEE 754 but *does* have an infinity*/
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* value, you'll need to replace this default implementation with what's*/
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* correct for your platform.*/
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0.0;
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_floor(double x)
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return floor(x);
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_ceil(double x)
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ceil(x);
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_round(double x)
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return uprv_floor(x + 0.5);
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_fabs(double x)
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fabs(x);
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_modf(double x, double* y)
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return modf(x, y);
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_fmod(double x, double y)
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fmod(x, y);
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_pow(double x, double y)
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* This is declared as "double pow(double x, double y)" */
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return pow(x, y);
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_pow10(int32_t x)
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return pow(10.0, (double)x);
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_fmax(double x, double y)
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if IEEE_754
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* first handle NaN*/
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(uprv_isNaN(x) || uprv_isNaN(y))
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return uprv_getNaN();
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check for -0 and 0*/
50927f654740f2a26ad62a5c155af9199af9e69b889claireho    if(x == 0.0 && y == 0.0 && u_signBit(x))
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return y;
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
51427f654740f2a26ad62a5c155af9199af9e69b889claireho    /* this should work for all flt point w/o NaN and Inf special cases */
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (x > y ? x : y);
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_fmin(double x, double y)
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if IEEE_754
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* first handle NaN*/
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(uprv_isNaN(x) || uprv_isNaN(y))
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return uprv_getNaN();
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check for -0 and 0*/
52727f654740f2a26ad62a5c155af9199af9e69b889claireho    if(x == 0.0 && y == 0.0 && u_signBit(y))
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return y;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* this should work for all flt point w/o NaN and Inf special cases */
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (x > y ? y : x);
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Truncates the given double.
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * trunc(3.3) = 3.0, trunc (-3.3) = -3.0
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is different than calling floor() or ceil():
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * floor(3.3) = 3, floor(-3.3) = -4
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * ceil(3.3) = 4, ceil(-3.3) = -3
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_trunc(double d)
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if IEEE_754
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* handle error cases*/
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(uprv_isNaN(d))
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return uprv_getNaN();
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(uprv_isInfinite(d))
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return uprv_getInfinity();
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55327f654740f2a26ad62a5c155af9199af9e69b889claireho    if(u_signBit(d))    /* Signbit() picks up -0.0;  d<0 does not. */
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return ceil(d);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return floor(d);
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return d >= 0 ? floor(d) : ceil(d);
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Return the largest positive number that can be represented by an integer
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * type of arbitrary bit length.
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_maxMantissa(void)
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return pow(2.0, DBL_MANT_DIG + 1.0) - 1.0;
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_log(double d)
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return log(d);
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void * U_EXPORT2
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_maximumPtr(void * base)
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
583103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM == U_PF_OS400
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
58585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * With the provided function we should never be out of range of a given segment
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * (a traditional/typical segment that is).  Our segments have 5 bytes for the
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * id and 3 bytes for the offset.  The key is that the casting takes care of
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * only retrieving the offset portion minus x1000.  Hence, the smallest offset
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * seen in a program is x001000 and when casted to an int would be 0.
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * That's why we can only add 0xffefff.  Otherwise, we would exceed the segment.
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
59285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * Currently, 16MB is the current addressing limitation on i5/OS if the activation is
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * non-TERASPACE.  If it is TERASPACE it is 2GB - 4k(header information).
59485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * This function determines the activation based on the pointer that is passed in and
59585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * calculates the appropriate maximum available size for
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * each pointer type (TERASPACE and non-TERASPACE)
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Unlike other operating systems, the pointer model isn't determined at
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * compile time on i5/OS.
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((base != NULL) && (_TESTPTR(base, _C_TERASPACE_CHECK))) {
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* if it is a TERASPACE pointer the max is 2GB - 4k */
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return ((void *)(((char *)base)-((uint32_t)(base))+((uint32_t)0x7fffefff)));
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* otherwise 16MB since NULL ptr is not checkable or the ptr is not TERASPACE */
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ((void *)(((char *)base)-((uint32_t)(base))+((uint32_t)0xffefff)));
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
60985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return U_MAX_PTR(base);
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*---------------------------------------------------------------------------
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Platform-specific Implementations
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Try these, and if they don't work on your platform, then special case your
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  platform with new implementations.
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ---------------------------------------------------------------------------*/
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Generic time zone layer -------------------------------------------------- */
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Time zone utilities */
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_tzset()
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if defined(U_TZSET)
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_TZSET();
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* no initialization*/
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_timezone()
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_TIMEZONE
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return U_TIMEZONE;
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    time_t t, t1, t2;
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct tm tmrec;
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t tdiff = 0;
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    time(&t);
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memcpy( &tmrec, localtime(&t), sizeof(tmrec) );
64459d709d503bab6e2b61931737e662dd293b40578ccornelius#if U_PLATFORM != U_PF_IPHONE
64559d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool dst_checked = (tmrec.tm_isdst != 0); /* daylight savings time is checked*/
64659d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    t1 = mktime(&tmrec);                 /* local time in seconds*/
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memcpy( &tmrec, gmtime(&t), sizeof(tmrec) );
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    t2 = mktime(&tmrec);                 /* GMT (or UTC) in seconds*/
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    tdiff = t2 - t1;
65159d709d503bab6e2b61931737e662dd293b40578ccornelius
65259d709d503bab6e2b61931737e662dd293b40578ccornelius#if U_PLATFORM != U_PF_IPHONE
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* imitate NT behaviour, which returns same timezone offset to GMT for
65454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius       winter and summer.
65554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius       This does not work on all platforms. For instance, on glibc on Linux
65654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius       and on Mac OS 10.5, tdiff calculated above remains the same
65759d709d503bab6e2b61931737e662dd293b40578ccornelius       regardless of whether DST is in effect or not. iOS is another
65859d709d503bab6e2b61931737e662dd293b40578ccornelius       platform where this does not work. Linux + glibc and Mac OS 10.5
65959d709d503bab6e2b61931737e662dd293b40578ccornelius       have U_TIMEZONE defined so that this code is not reached.
66059d709d503bab6e2b61931737e662dd293b40578ccornelius    */
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dst_checked)
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tdiff += 3600;
66359d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return tdiff;
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Note that U_TZNAME does *not* have to be tzname, but if it is,
66985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho   some platforms need to have it declared here. */
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
6710596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if defined(U_TZNAME) && (U_PLATFORM == U_PF_IRIX || U_PLATFORM_IS_DARWIN_BASED)
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* RS6000 and others reject char **tzname.  */
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruextern U_IMPORT char *U_TZNAME[];
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
67659d709d503bab6e2b61931737e662dd293b40578ccornelius#if !UCONFIG_NO_FILE_IO && ((U_PLATFORM_IS_DARWIN_BASED && (U_PLATFORM != U_PF_IPHONE || defined(U_TIMEZONE))) || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS)
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* These platforms are likely to use Olson timezone IDs. */
678ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert/* common targets of the symbolic link at TZDEFAULT are:
679ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * "/usr/share/zoneinfo/<olsonID>" default, older Linux distros, macOS to 10.12
680ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * "../usr/share/zoneinfo/<olsonID>" newer Linux distros: Red Hat Enterprise Linux 7, Ubuntu 16, SuSe Linux 12
681ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * "/usr/share/lib/zoneinfo/<olsonID>" Solaris
682ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * "../usr/share/lib/zoneinfo/<olsonID>" Solaris
683ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * "/var/db/timezone/zoneinfo/<olsonID>" macOS 10.13
684ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * To avoid checking lots of paths, just check that the target path
685ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * before the <olsonID> ends with "/zoneinfo/", and the <olsonID> is valid.
686ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert */
687ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CHECK_LOCALTIME_LINK 1
689103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_IS_DARWIN_BASED
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <tzfile.h>
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define TZZONEINFO      (TZDIR "/")
6928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#elif U_PLATFORM == U_PF_SOLARIS
6938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#define TZDEFAULT       "/etc/localtime"
6948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#define TZZONEINFO      "/usr/share/lib/zoneinfo/"
6958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#define TZ_ENV_CHECK    "localtime"
69685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#else
69785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define TZDEFAULT       "/etc/localtime"
69885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define TZZONEINFO      "/usr/share/zoneinfo/"
69985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
700ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#define TZZONEINFOTAIL  "/zoneinfo/"
70185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if U_HAVE_DIRENT_H
70250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define TZFILE_SKIP     "posixrules" /* tz file to skip when searching. */
70327f654740f2a26ad62a5c155af9199af9e69b889claireho/* Some Linux distributions have 'localtime' in /usr/share/zoneinfo
70427f654740f2a26ad62a5c155af9199af9e69b889claireho   symlinked to /etc/localtime, which makes searchForTZFile return
70527f654740f2a26ad62a5c155af9199af9e69b889claireho   'localtime' when it's the first match. */
70627f654740f2a26ad62a5c155af9199af9e69b889claireho#define TZFILE_SKIP2    "localtime"
70785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define SEARCH_TZFILE
70885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include <dirent.h>  /* Needed to search through system timezone files */
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char gTimeZoneBuffer[PATH_MAX];
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char *gTimeZoneBufferPtr = NULL;
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
714103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if !U_PLATFORM_USES_ONLY_WIN32_API
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define isNonDigit(ch) (ch < '0' || '9' < ch)
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool isValidOlsonID(const char *id) {
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t idx = 0;
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Determine if this is something like Iceland (Olson ID)
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    or AST4ADT (non-Olson ID) */
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (id[idx] && isNonDigit(id[idx]) && id[idx] != ',') {
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idx++;
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If we went through the whole string, then it might be okay.
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    The timezone is sometimes set to "CST-7CDT", "CST6CDT5,J129,J131/19:30",
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GRNLNDST3GRNLNDDT" or similar, so we cannot use it.
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    The rest of the time it could be an Olson ID. George */
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(id[idx] == 0
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || uprv_strcmp(id, "PST8PDT") == 0
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || uprv_strcmp(id, "MST7MDT") == 0
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || uprv_strcmp(id, "CST6CDT") == 0
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || uprv_strcmp(id, "EST5EDT") == 0);
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
73527f654740f2a26ad62a5c155af9199af9e69b889claireho
73627f654740f2a26ad62a5c155af9199af9e69b889claireho/* On some Unix-like OS, 'posix' subdirectory in
73727f654740f2a26ad62a5c155af9199af9e69b889claireho   /usr/share/zoneinfo replicates the top-level contents. 'right'
73827f654740f2a26ad62a5c155af9199af9e69b889claireho   subdirectory has the same set of files, but individual files
73927f654740f2a26ad62a5c155af9199af9e69b889claireho   are different from those in the top-level directory or 'posix'
74027f654740f2a26ad62a5c155af9199af9e69b889claireho   because 'right' has files for TAI (Int'l Atomic Time) while 'posix'
74127f654740f2a26ad62a5c155af9199af9e69b889claireho   has files for UTC.
74227f654740f2a26ad62a5c155af9199af9e69b889claireho   When the first match for /etc/localtime is in either of them
74327f654740f2a26ad62a5c155af9199af9e69b889claireho   (usually in posix because 'right' has different file contents),
74427f654740f2a26ad62a5c155af9199af9e69b889claireho   or TZ environment variable points to one of them, createTimeZone
74527f654740f2a26ad62a5c155af9199af9e69b889claireho   fails because, say, 'posix/America/New_York' is not an Olson
74627f654740f2a26ad62a5c155af9199af9e69b889claireho   timezone id ('America/New_York' is). So, we have to skip
74727f654740f2a26ad62a5c155af9199af9e69b889claireho   'posix/' and 'right/' at the beginning. */
74827f654740f2a26ad62a5c155af9199af9e69b889clairehostatic void skipZoneIDPrefix(const char** id) {
74927f654740f2a26ad62a5c155af9199af9e69b889claireho    if (uprv_strncmp(*id, "posix/", 6) == 0
75027f654740f2a26ad62a5c155af9199af9e69b889claireho        || uprv_strncmp(*id, "right/", 6) == 0)
75127f654740f2a26ad62a5c155af9199af9e69b889claireho    {
75227f654740f2a26ad62a5c155af9199af9e69b889claireho        *id += 6;
75327f654740f2a26ad62a5c155af9199af9e69b889claireho    }
75427f654740f2a26ad62a5c155af9199af9e69b889claireho}
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(U_TZNAME) && !U_PLATFORM_USES_ONLY_WIN32_API
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CONVERT_HOURS_TO_SECONDS(offset) (int32_t)(offset*3600)
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct OffsetZoneMapping {
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetSeconds;
762103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t daylightType; /* 0=U_DAYLIGHT_NONE, 1=daylight in June-U_DAYLIGHT_JUNE, 2=daylight in December=U_DAYLIGHT_DECEMBER*/
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *stdID;
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *dstID;
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *olsonID;
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} OffsetZoneMapping;
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
768103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusenum { U_DAYLIGHT_NONE=0,U_DAYLIGHT_JUNE=1,U_DAYLIGHT_DECEMBER=2 };
769103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis list tries to disambiguate a set of abbreviated timezone IDs and offsets
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruand maps it to an Olson ID.
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBefore adding anything to this list, take a look at
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruicu/source/tools/tzcode/tz.alias
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSometimes no daylight savings (0) is important to define due to aliases.
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis list can be tested with icu/source/test/compat/tzone.pl
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMore values could be added to daylightType to increase precision.
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const struct OffsetZoneMapping OFFSET_ZONE_MAPPINGS[] = {
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-45900, 2, "CHAST", "CHADT", "Pacific/Chatham"},
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-43200, 1, "PETT", "PETST", "Asia/Kamchatka"},
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-43200, 2, "NZST", "NZDT", "Pacific/Auckland"},
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-43200, 1, "ANAT", "ANAST", "Asia/Anadyr"},
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-39600, 1, "MAGT", "MAGST", "Asia/Magadan"},
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-37800, 2, "LHST", "LHST", "Australia/Lord_Howe"},
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-36000, 2, "EST", "EST", "Australia/Sydney"},
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-36000, 1, "SAKT", "SAKST", "Asia/Sakhalin"},
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-36000, 1, "VLAT", "VLAST", "Asia/Vladivostok"},
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-34200, 2, "CST", "CST", "Australia/South"},
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-32400, 1, "YAKT", "YAKST", "Asia/Yakutsk"},
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-32400, 1, "CHOT", "CHOST", "Asia/Choibalsan"},
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-31500, 2, "CWST", "CWST", "Australia/Eucla"},
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-28800, 1, "IRKT", "IRKST", "Asia/Irkutsk"},
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-28800, 1, "ULAT", "ULAST", "Asia/Ulaanbaatar"},
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-28800, 2, "WST", "WST", "Australia/West"},
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-25200, 1, "HOVT", "HOVST", "Asia/Hovd"},
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-25200, 1, "KRAT", "KRAST", "Asia/Krasnoyarsk"},
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-21600, 1, "NOVT", "NOVST", "Asia/Novosibirsk"},
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-21600, 1, "OMST", "OMSST", "Asia/Omsk"},
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-18000, 1, "YEKT", "YEKST", "Asia/Yekaterinburg"},
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-14400, 1, "SAMT", "SAMST", "Europe/Samara"},
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-14400, 1, "AMT", "AMST", "Asia/Yerevan"},
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-14400, 1, "AZT", "AZST", "Asia/Baku"},
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-10800, 1, "AST", "ADT", "Asia/Baghdad"},
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-10800, 1, "MSK", "MSD", "Europe/Moscow"},
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-10800, 1, "VOLT", "VOLST", "Europe/Volgograd"},
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-7200, 0, "EET", "CEST", "Africa/Tripoli"},
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-7200, 1, "EET", "EEST", "Europe/Athens"}, /* Conflicts with Africa/Cairo */
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-7200, 1, "IST", "IDT", "Asia/Jerusalem"},
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-3600, 0, "CET", "WEST", "Africa/Algiers"},
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {-3600, 2, "WAT", "WAST", "Africa/Windhoek"},
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {0, 1, "GMT", "IST", "Europe/Dublin"},
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {0, 1, "GMT", "BST", "Europe/London"},
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {0, 0, "WET", "WEST", "Africa/Casablanca"},
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {0, 0, "WET", "WET", "Africa/El_Aaiun"},
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {3600, 1, "AZOT", "AZOST", "Atlantic/Azores"},
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {3600, 1, "EGT", "EGST", "America/Scoresbysund"},
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {10800, 1, "PMST", "PMDT", "America/Miquelon"},
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {10800, 2, "UYT", "UYST", "America/Montevideo"},
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {10800, 1, "WGT", "WGST", "America/Godthab"},
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {10800, 2, "BRT", "BRST", "Brazil/East"},
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {12600, 1, "NST", "NDT", "America/St_Johns"},
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {14400, 1, "AST", "ADT", "Canada/Atlantic"},
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {14400, 2, "AMT", "AMST", "America/Cuiaba"},
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {14400, 2, "CLT", "CLST", "Chile/Continental"},
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {14400, 2, "FKT", "FKST", "Atlantic/Stanley"},
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {14400, 2, "PYT", "PYST", "America/Asuncion"},
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {18000, 1, "CST", "CDT", "America/Havana"},
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {18000, 1, "EST", "EDT", "US/Eastern"}, /* Conflicts with America/Grand_Turk */
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {21600, 2, "EAST", "EASST", "Chile/EasterIsland"},
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {21600, 0, "CST", "MDT", "Canada/Saskatchewan"},
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {21600, 0, "CST", "CDT", "America/Guatemala"},
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {21600, 1, "CST", "CDT", "US/Central"}, /* Conflicts with Mexico/General */
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {25200, 1, "MST", "MDT", "US/Mountain"}, /* Conflicts with Mexico/BajaSur */
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {28800, 0, "PST", "PST", "Pacific/Pitcairn"},
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {28800, 1, "PST", "PDT", "US/Pacific"}, /* Conflicts with Mexico/BajaNorte */
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {32400, 1, "AKST", "AKDT", "US/Alaska"},
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {36000, 1, "HAST", "HADT", "US/Aleutian"}
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*#define DEBUG_TZNAME*/
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* remapShortTimeZone(const char *stdID, const char *dstID, int32_t daylightType, int32_t offset)
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t idx;
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef DEBUG_TZNAME
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fprintf(stderr, "TZ=%s std=%s dst=%s daylight=%d offset=%d\n", getenv("TZ"), stdID, dstID, daylightType, offset);
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
849f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    for (idx = 0; idx < UPRV_LENGTHOF(OFFSET_ZONE_MAPPINGS); idx++)
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (offset == OFFSET_ZONE_MAPPINGS[idx].offsetSeconds
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            && daylightType == OFFSET_ZONE_MAPPINGS[idx].daylightType
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            && strcmp(OFFSET_ZONE_MAPPINGS[idx].stdID, stdID) == 0
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            && strcmp(OFFSET_ZONE_MAPPINGS[idx].dstID, dstID) == 0)
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return OFFSET_ZONE_MAPPINGS[idx].olsonID;
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
86385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#ifdef SEARCH_TZFILE
86485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define MAX_READ_SIZE 512
86585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hotypedef struct DefaultTZInfo {
86785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char* defaultTZBuffer;
86885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int64_t defaultTZFileSize;
86985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    FILE* defaultTZFilePtr;
87085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool defaultTZstatus;
87185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t defaultTZPosition;
87285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} DefaultTZInfo;
87385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
87485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/*
87585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * This method compares the two files given to see if they are a match.
87685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * It is currently use to compare two TZ files.
87785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
87885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic UBool compareBinaryFiles(const char* defaultTZFileName, const char* TZFileName, DefaultTZInfo* tzInfo) {
87985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    FILE* file;
88085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int64_t sizeFile;
88185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int64_t sizeFileLeft;
88285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t sizeFileRead;
88385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t sizeFileToRead;
88485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char bufferFile[MAX_READ_SIZE];
88585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool result = TRUE;
88685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
88785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (tzInfo->defaultTZFilePtr == NULL) {
88885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        tzInfo->defaultTZFilePtr = fopen(defaultTZFileName, "r");
88985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
89085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    file = fopen(TZFileName, "r");
89185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
89285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    tzInfo->defaultTZPosition = 0; /* reset position to begin search */
89385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
89485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (file != NULL && tzInfo->defaultTZFilePtr != NULL) {
89585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* First check that the file size are equal. */
89685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (tzInfo->defaultTZFileSize == 0) {
89785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fseek(tzInfo->defaultTZFilePtr, 0, SEEK_END);
89885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            tzInfo->defaultTZFileSize = ftell(tzInfo->defaultTZFilePtr);
89985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
90085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fseek(file, 0, SEEK_END);
90185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        sizeFile = ftell(file);
90285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        sizeFileLeft = sizeFile;
90385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
90485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (sizeFile != tzInfo->defaultTZFileSize) {
90585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            result = FALSE;
90685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
90785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* Store the data from the files in seperate buffers and
90885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             * compare each byte to determine equality.
90985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             */
91085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (tzInfo->defaultTZBuffer == NULL) {
91185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                rewind(tzInfo->defaultTZFilePtr);
91285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZBuffer = (char*)uprv_malloc(sizeof(char) * tzInfo->defaultTZFileSize);
9131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                sizeFileRead = fread(tzInfo->defaultTZBuffer, 1, tzInfo->defaultTZFileSize, tzInfo->defaultTZFilePtr);
91485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
91585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            rewind(file);
91685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            while(sizeFileLeft > 0) {
91785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                uprv_memset(bufferFile, 0, MAX_READ_SIZE);
91885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sizeFileToRead = sizeFileLeft < MAX_READ_SIZE ? sizeFileLeft : MAX_READ_SIZE;
91985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
92085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sizeFileRead = fread(bufferFile, 1, sizeFileToRead, file);
92185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (memcmp(tzInfo->defaultTZBuffer + tzInfo->defaultTZPosition, bufferFile, sizeFileRead) != 0) {
92285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    result = FALSE;
92385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
92485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
92585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sizeFileLeft -= sizeFileRead;
92685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZPosition += sizeFileRead;
92785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
92885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
92985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
93085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        result = FALSE;
93185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
93285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
93385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (file != NULL) {
93485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fclose(file);
93585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
93685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
93785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return result;
93885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
93964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
94064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
94185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* dirent also lists two entries: "." and ".." that we can safely ignore. */
94285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define SKIP1 "."
94385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define SKIP2 ".."
94464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic UBool U_CALLCONV putil_cleanup(void);
94564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic CharString *gSearchTZFileResult = NULL;
94664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
94764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert/*
94864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * This method recursively traverses the directory given for a matching TZ file and returns the first match.
94964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * This function is not thread safe - it uses a global, gSearchTZFileResult, to hold its results.
95064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert */
95185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) {
952ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    DIR* dirp = NULL;
95385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    struct dirent* dirEntry = NULL;
95485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char* result = NULL;
955ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    UErrorCode status = U_ZERO_ERROR;
956ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
957ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /* Save the current path */
958ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    CharString curpath(path, -1, status);
959ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    if (U_FAILURE(status)) {
960ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        goto cleanupAndReturn;
961ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
962ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
963ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    dirp = opendir(path);
96450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (dirp == NULL) {
965ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        goto cleanupAndReturn;
96650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
96785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
96864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (gSearchTZFileResult == NULL) {
96964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        gSearchTZFileResult = new CharString;
97064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (gSearchTZFileResult == NULL) {
971ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            goto cleanupAndReturn;
97264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        }
97364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
97464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
97564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
97685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* Check each entry in the directory. */
97785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while((dirEntry = readdir(dirp)) != NULL) {
97827f654740f2a26ad62a5c155af9199af9e69b889claireho        const char* dirName = dirEntry->d_name;
97927f654740f2a26ad62a5c155af9199af9e69b889claireho        if (uprv_strcmp(dirName, SKIP1) != 0 && uprv_strcmp(dirName, SKIP2) != 0) {
98085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* Create a newpath with the new entry to test each entry in the directory. */
98164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            CharString newpath(curpath, status);
98264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            newpath.append(dirName, -1, status);
98364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (U_FAILURE(status)) {
984ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                break;
98564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            }
98685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
987ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            DIR* subDirp = NULL;
98864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if ((subDirp = opendir(newpath.data())) != NULL) {
98985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                /* If this new path is a directory, make a recursive call with the newpath. */
99085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                closedir(subDirp);
99164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                newpath.append('/', status);
99264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                if (U_FAILURE(status)) {
993ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                    break;
99464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                }
99564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                result = searchForTZFile(newpath.data(), tzInfo);
99627f654740f2a26ad62a5c155af9199af9e69b889claireho                /*
99727f654740f2a26ad62a5c155af9199af9e69b889claireho                 Have to get out here. Otherwise, we'd keep looking
99827f654740f2a26ad62a5c155af9199af9e69b889claireho                 and return the first match in the top-level directory
99927f654740f2a26ad62a5c155af9199af9e69b889claireho                 if there's a match in the top-level. If not, this function
100027f654740f2a26ad62a5c155af9199af9e69b889claireho                 would return NULL and set gTimeZoneBufferPtr to NULL in initDefault().
100127f654740f2a26ad62a5c155af9199af9e69b889claireho                 It worked without this in most cases because we have a fallback of calling
100227f654740f2a26ad62a5c155af9199af9e69b889claireho                 localtime_r to figure out the default timezone.
100327f654740f2a26ad62a5c155af9199af9e69b889claireho                */
100427f654740f2a26ad62a5c155af9199af9e69b889claireho                if (result != NULL)
100527f654740f2a26ad62a5c155af9199af9e69b889claireho                    break;
100627f654740f2a26ad62a5c155af9199af9e69b889claireho            } else if (uprv_strcmp(TZFILE_SKIP, dirName) != 0 && uprv_strcmp(TZFILE_SKIP2, dirName) != 0) {
100764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                if(compareBinaryFiles(TZDEFAULT, newpath.data(), tzInfo)) {
100864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    int32_t amountToSkip = sizeof(TZZONEINFO) - 1;
100964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    if (amountToSkip > newpath.length()) {
101064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        amountToSkip = newpath.length();
101164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    }
101264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    const char* zoneid = newpath.data() + amountToSkip;
101327f654740f2a26ad62a5c155af9199af9e69b889claireho                    skipZoneIDPrefix(&zoneid);
101464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    gSearchTZFileResult->clear();
101564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    gSearchTZFileResult->append(zoneid, -1, status);
101664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    if (U_FAILURE(status)) {
1017ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                        break;
101864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    }
101964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    result = gSearchTZFileResult->data();
102085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* Get out after the first one found. */
102185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
102285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
102385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
102485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
102585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1026ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
1027ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  cleanupAndReturn:
1028ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    if (dirp) {
1029ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        closedir(dirp);
1030ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
103185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return result;
103285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
103385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
103464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
103564339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertU_CAPI void U_EXPORT2
103664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertuprv_tzname_clear_cache()
103764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert{
103864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if defined(CHECK_LOCALTIME_LINK) && !defined(DEBUG_SKIP_LOCALTIME_LINK)
103964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    gTimeZoneBufferPtr = NULL;
104064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif
104164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
104264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
10430596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// With the Universal Windows Platform we can just ask Windows for the name
10440596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WINUWP_API
10450596faeddefbf198de137d5e893708495ab1584cFredrik RoubertU_CAPI const char* U_EXPORT2
10460596faeddefbf198de137d5e893708495ab1584cFredrik Roubertuprv_getWindowsTimeZone()
10470596faeddefbf198de137d5e893708495ab1584cFredrik Roubert{
10480596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Get default Windows timezone.
10490596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    ComPtr<IInspectable> calendar;
10500596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    HRESULT hr = RoActivateInstance(
10510596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        HStringReference(RuntimeClass_Windows_Globalization_Calendar).Get(),
10520596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        &calendar);
10530596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (SUCCEEDED(hr))
10540596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
10550596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        ComPtr<ABI::Windows::Globalization::ITimeZoneOnCalendar> timezone;
10560596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        hr = calendar.As(&timezone);
10570596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (SUCCEEDED(hr))
10580596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
10590596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            HString timezoneString;
10600596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            hr = timezone->GetTimeZone(timezoneString.GetAddressOf());
10610596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            if (SUCCEEDED(hr))
10620596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            {
1063ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                int32_t length = static_cast<int32_t>(wcslen(timezoneString.GetRawBuffer(NULL)));
10640596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                char* asciiId = (char*)uprv_calloc(length + 1, sizeof(char));
10650596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                if (asciiId != nullptr)
10660596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                {
10670596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                    u_UCharsToChars((UChar*)timezoneString.GetRawBuffer(NULL), asciiId, length);
10680596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                    return asciiId;
10690596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                }
10700596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            }
10710596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
10720596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
10730596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
10740596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Failed
10750596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return nullptr;
10760596faeddefbf198de137d5e893708495ab1584cFredrik Roubert}
10770596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
10780596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char* U_EXPORT2
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_tzname(int n)
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1082ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    (void)n; // Avoid unreferenced parameter warning.
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *tzid = NULL;
1084103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
10850596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WINUWP_API > 0
10860596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    tzid = uprv_getWindowsTimeZone();
10870596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#else
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    tzid = uprv_detectWindowsTimeZone();
10890596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tzid != NULL) {
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return tzid;
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
10940596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
10950596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#ifndef U_TZNAME
10960596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // The return value is free'd in timezone.cpp on Windows because
10970596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // the other code path returns a pointer to a heap location.
10980596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // If we don't have a name already, then tzname wouldn't be any
10990596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // better, so just fall back.
11000596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return uprv_strdup("Etc/UTC");
11010596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif // !U_TZNAME
11020596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1105103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/*#if U_PLATFORM_IS_DARWIN_BASED
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int ret;
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    tzid = getenv("TZFILE");
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tzid != NULL) {
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return tzid;
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif*/
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* This code can be temporarily disabled to test tzname resolution later on. */
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef DEBUG_TZNAME
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    tzid = getenv("TZ");
11178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (tzid != NULL && isValidOlsonID(tzid)
11188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#if U_PLATFORM == U_PF_SOLARIS
11198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    /* When TZ equals localtime on Solaris, check the /etc/localtime file. */
11208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        && uprv_strcmp(tzid, TZ_ENV_CHECK) != 0
11218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#endif
11228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ) {
11238de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        /* The colon forces tzset() to treat the remainder as zoneinfo path */
11248de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (tzid[0] == ':') {
11258de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            tzid++;
11268de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        }
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* This might be a good Olson ID. */
112827f654740f2a26ad62a5c155af9199af9e69b889claireho        skipZoneIDPrefix(&tzid);
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return tzid;
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* else U_TZNAME will give a better result. */
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(CHECK_LOCALTIME_LINK) && !defined(DEBUG_SKIP_LOCALTIME_LINK)
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Caller must handle threading issues */
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (gTimeZoneBufferPtr == NULL) {
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        This is a trick to look at the name of the link to get the Olson ID
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        because the tzfile contents is underspecified.
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        This isn't guaranteed to work because it may not be a symlink.
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
114264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        int32_t ret = (int32_t)readlink(TZDEFAULT, gTimeZoneBuffer, sizeof(gTimeZoneBuffer)-1);
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (0 < ret) {
1144ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            int32_t tzZoneInfoTailLen = uprv_strlen(TZZONEINFOTAIL);
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            gTimeZoneBuffer[ret] = 0;
1146ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            char *  tzZoneInfoTailPtr = uprv_strstr(gTimeZoneBuffer, TZZONEINFOTAIL);
1147ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
1148ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            if (tzZoneInfoTailPtr != NULL
1149ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                && isValidOlsonID(tzZoneInfoTailPtr + tzZoneInfoTailLen))
115059d709d503bab6e2b61931737e662dd293b40578ccornelius            {
1151ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                return (gTimeZoneBufferPtr = tzZoneInfoTailPtr + tzZoneInfoTailLen);
115259d709d503bab6e2b61931737e662dd293b40578ccornelius            }
115385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
115485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if defined(SEARCH_TZFILE)
115585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            DefaultTZInfo* tzInfo = (DefaultTZInfo*)uprv_malloc(sizeof(DefaultTZInfo));
115685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (tzInfo != NULL) {
115785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZBuffer = NULL;
115885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZFileSize = 0;
115985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZFilePtr = NULL;
116085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZstatus = FALSE;
116185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                tzInfo->defaultTZPosition = 0;
116285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
116385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                gTimeZoneBufferPtr = searchForTZFile(TZZONEINFO, tzInfo);
116485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
116585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                /* Free previously allocated memory */
116685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (tzInfo->defaultTZBuffer != NULL) {
116785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    uprv_free(tzInfo->defaultTZBuffer);
116885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
116985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (tzInfo->defaultTZFilePtr != NULL) {
117085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    fclose(tzInfo->defaultTZFilePtr);
117185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
117285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                uprv_free(tzInfo);
117385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
117485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
117585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (gTimeZoneBufferPtr != NULL && isValidOlsonID(gTimeZoneBufferPtr)) {
117685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return gTimeZoneBufferPtr;
117785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
117885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return gTimeZoneBufferPtr;
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_TZNAME
1188103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
118950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* The return value is free'd in timezone.cpp on Windows because
119050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * the other code path returns a pointer to a heap location. */
119150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return uprv_strdup(U_TZNAME[n]);
119250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_TZNAME is usually a non-unique abbreviation, which isn't normally usable.
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    So we remap the abbreviation to an olson ID.
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Since Windows exposes a little more timezone information,
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    we normally don't use this code on Windows because
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_detectWindowsTimeZone should have already given the correct answer.
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        struct tm juneSol, decemberSol;
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int daylightType;
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        static const time_t juneSolstice=1182478260; /*2007-06-21 18:11 UT*/
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        static const time_t decemberSolstice=1198332540; /*2007-12-22 06:09 UT*/
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* This probing will tell us when daylight savings occurs.  */
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localtime_r(&juneSolstice, &juneSol);
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localtime_r(&decemberSolstice, &decemberSol);
1210103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if(decemberSol.tm_isdst > 0) {
1211103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius          daylightType = U_DAYLIGHT_DECEMBER;
1212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else if(juneSol.tm_isdst > 0) {
1213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius          daylightType = U_DAYLIGHT_JUNE;
1214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else {
1215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius          daylightType = U_DAYLIGHT_NONE;
1216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tzid = remapShortTimeZone(U_TZNAME[0], U_TZNAME[1], daylightType, uprv_timezone());
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (tzid != NULL) {
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return tzid;
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return U_TZNAME[n];
122350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return "";
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Get and set the ICU data directory --------------------------------------- */
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1231f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic icu::UInitOnce gDataDirInitOnce = U_INITONCE_INITIALIZER;
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char *gDataDirectory = NULL;
1233f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1234f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUInitOnce gTimeZoneFilesInitOnce = U_INITONCE_INITIALIZER;
1235f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic CharString *gTimeZoneFilesDirectory = NULL;
1236f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
123759d709d503bab6e2b61931737e662dd293b40578ccornelius#if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API
1238ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert static const char *gCorrectedPOSIXLocale = NULL; /* Sometimes heap allocated */
12390596faeddefbf198de137d5e893708495ab1584cFredrik Roubert static bool gCorrectedPOSIXLocaleHeapAllocated = false;
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV putil_cleanup(void)
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (gDataDirectory && *gDataDirectory) {
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(gDataDirectory);
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gDataDirectory = NULL;
1248f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gDataDirInitOnce.reset();
1249f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1250f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    delete gTimeZoneFilesDirectory;
1251f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTimeZoneFilesDirectory = NULL;
1252f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTimeZoneFilesInitOnce.reset();
1253f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
125464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#ifdef SEARCH_TZFILE
125564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    delete gSearchTZFileResult;
125664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    gSearchTZFileResult = NULL;
125764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif
125864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
125959d709d503bab6e2b61931737e662dd293b40578ccornelius#if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API
12600596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (gCorrectedPOSIXLocale && gCorrectedPOSIXLocaleHeapAllocated) {
1261ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        uprv_free(const_cast<char *>(gCorrectedPOSIXLocale));
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        gCorrectedPOSIXLocale = NULL;
12630596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        gCorrectedPOSIXLocaleHeapAllocated = false;
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Set the data directory.
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *    Make a copy of the passed string, and set the global data dir to point to it.
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_setDataDirectory(const char *directory) {
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *newDataDir;
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length;
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(directory==NULL || *directory==0) {
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* A small optimization to prevent the malloc and copy when the
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        shared library is used, and this is a way to make sure that NULL
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        is never returned.
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        newDataDir = (char *)"";
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length=(int32_t)uprv_strlen(directory);
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        newDataDir = (char *)uprv_malloc(length + 2);
128885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Exit out if newDataDir could not be created. */
128985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (newDataDir == NULL) {
129085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
129185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcpy(newDataDir, directory);
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char *p;
1297ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            while((p = uprv_strchr(newDataDir, U_FILE_ALT_SEP_CHAR)) != NULL) {
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *p = U_FILE_SEP_CHAR;
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (gDataDirectory && *gDataDirectory) {
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(gDataDirectory);
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gDataDirectory = newDataDir;
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
131285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houprv_pathIsAbsolute(const char *path)
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
131485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho  if(!path || !*path) {
131585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return FALSE;
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(*path == U_FILE_SEP_CHAR) {
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(*path == U_FILE_ALT_SEP_CHAR) {
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1328103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if( (((path[0] >= 'A') && (path[0] <= 'Z')) ||
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       ((path[0] >= 'a') && (path[0] <= 'z'))) &&
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      path[1] == ':' ) {
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return FALSE;
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
133927f654740f2a26ad62a5c155af9199af9e69b889claireho/* Temporary backup setting of ICU_DATA_DIR_PREFIX_ENV_VAR
134027f654740f2a26ad62a5c155af9199af9e69b889claireho   until some client wrapper makefiles are updated */
1341103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_IS_DARWIN_BASED && TARGET_IPHONE_SIMULATOR
134227f654740f2a26ad62a5c155af9199af9e69b889claireho# if !defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
134327f654740f2a26ad62a5c155af9199af9e69b889claireho#  define ICU_DATA_DIR_PREFIX_ENV_VAR "IPHONE_SIMULATOR_ROOT"
134427f654740f2a26ad62a5c155af9199af9e69b889claireho# endif
134527f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
134627f654740f2a26ad62a5c155af9199af9e69b889claireho
1347f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV dataDirectoryInitFn() {
1348f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* If we already have the directory, then return immediately. Will happen if user called
1349f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius     * u_setDataDirectory().
1350f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius     */
1351f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gDataDirectory) {
1352f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1353f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1354f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *path = NULL;
135602fdd983fede27bf25bddfbe3b5deb20813df5efElliott Hughes#if defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
135750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    char datadir_path_buffer[PATH_MAX];
135850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    When ICU_NO_USER_DATA_OVERRIDE is defined, users aren't allowed to
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    override ICU's data with the ICU_DATA environment variable. This prevents
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    problems where multiple custom copies of ICU's specific version of data
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    are installed on a system. Either the application must define the data
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    directory with u_setDataDirectory, define ICU_DATA_DIR when compiling
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ICU, set the data with udata_setCommonData or trust that all of the
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    required data is contained in ICU's data library that contains
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    the entry point defined by U_ICUDATA_ENTRY_POINT.
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    There may also be some platforms where environment variables
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    are not allowed.
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   if !defined(ICU_NO_USER_DATA_OVERRIDE) && !UCONFIG_NO_FILE_IO
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* First try to get the environment variable */
13750596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#       if U_PLATFORM_HAS_WINUWP_API == 0  // Windows UWP does not support getenv
13760596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        path=getenv("ICU_DATA");
13770596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#       endif
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   endif
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
138027f654740f2a26ad62a5c155af9199af9e69b889claireho    /* ICU_DATA_DIR may be set as a compile option.
138127f654740f2a26ad62a5c155af9199af9e69b889claireho     * U_ICU_DATA_DEFAULT_DIR is provided and is set by ICU at compile time
138227f654740f2a26ad62a5c155af9199af9e69b889claireho     * and is used only when data is built in archive mode eliminating the need
138327f654740f2a26ad62a5c155af9199af9e69b889claireho     * for ICU_DATA_DIR to be set. U_ICU_DATA_DEFAULT_DIR is set to the installation
138427f654740f2a26ad62a5c155af9199af9e69b889claireho     * directory of the data dat file. Users should use ICU_DATA_DIR if they want to
138527f654740f2a26ad62a5c155af9199af9e69b889claireho     * set their own path.
138627f654740f2a26ad62a5c155af9199af9e69b889claireho     */
138727f654740f2a26ad62a5c155af9199af9e69b889claireho#if defined(ICU_DATA_DIR) || defined(U_ICU_DATA_DEFAULT_DIR)
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(path==NULL || *path==0) {
138927f654740f2a26ad62a5c155af9199af9e69b889claireho# if defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
139002fdd983fede27bf25bddfbe3b5deb20813df5efElliott Hughes        const char *prefix = getenv(ICU_DATA_DIR_PREFIX_ENV_VAR);
139127f654740f2a26ad62a5c155af9199af9e69b889claireho# endif
139227f654740f2a26ad62a5c155af9199af9e69b889claireho# ifdef ICU_DATA_DIR
139327f654740f2a26ad62a5c155af9199af9e69b889claireho        path=ICU_DATA_DIR;
139427f654740f2a26ad62a5c155af9199af9e69b889claireho# else
139527f654740f2a26ad62a5c155af9199af9e69b889claireho        path=U_ICU_DATA_DEFAULT_DIR;
139627f654740f2a26ad62a5c155af9199af9e69b889claireho# endif
139727f654740f2a26ad62a5c155af9199af9e69b889claireho# if defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
139802fdd983fede27bf25bddfbe3b5deb20813df5efElliott Hughes        if (prefix != NULL) {
139927f654740f2a26ad62a5c155af9199af9e69b889claireho            snprintf(datadir_path_buffer, PATH_MAX, "%s%s", prefix, path);
140050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            path=datadir_path_buffer;
140150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
140227f654740f2a26ad62a5c155af9199af9e69b889claireho# endif
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
140427f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
14060596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if defined(ICU_DATA_DIR_WINDOWS) && U_PLATFORM_HAS_WINUWP_API != 0
14070596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Use data from the %windir%\globalization\icu directory
14080596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // This is only available if ICU is built as a system component
14090596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    char datadir_path_buffer[MAX_PATH];
14100596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    UINT length = GetWindowsDirectoryA(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer));
14110596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (length > 0 && length < (UPRV_LENGTHOF(datadir_path_buffer) - sizeof(ICU_DATA_DIR_WINDOWS) - 1))
14120596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
14130596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (datadir_path_buffer[length - 1] != '\\')
14140596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
14150596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            datadir_path_buffer[length++] = '\\';
14160596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            datadir_path_buffer[length] = '\0';
14170596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
14180596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
14190596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if ((length + 1 + sizeof(ICU_DATA_DIR_WINDOWS)) < UPRV_LENGTHOF(datadir_path_buffer))
14200596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
14210596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            uprv_strcat(datadir_path_buffer, ICU_DATA_DIR_WINDOWS);
14220596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            path = datadir_path_buffer;
14230596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
14240596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
14250596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
14260596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(path==NULL) {
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* It looks really bad, set it to something. */
14290596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WIN32_API
14300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        // Windows UWP will require icudtl.dat file in same directory as icuuc.dll
14310596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        path = ".\\";
14320596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#else
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        path = "";
14340596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_setDataDirectory(path);
1438f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return;
1439f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1440f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1441f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI const char * U_EXPORT2
1442f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_getDataDirectory(void) {
1443f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_initOnce(gDataDirInitOnce, &dataDirectoryInitFn);
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return gDataDirectory;
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1447f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void setTimeZoneFilesDir(const char *path, UErrorCode &status) {
1448f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1449f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1450f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1451f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTimeZoneFilesDirectory->clear();
1452f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTimeZoneFilesDirectory->append(path, status);
1453f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
1454f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    char *p = gTimeZoneFilesDirectory->data();
1455ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    while ((p = uprv_strchr(p, U_FILE_ALT_SEP_CHAR)) != NULL) {
1456f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        *p = U_FILE_SEP_CHAR;
1457f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1458f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#endif
1459f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1461f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#define TO_STRING(x) TO_STRING_2(x)
1462f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#define TO_STRING_2(x) #x
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1464f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) {
1465f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    U_ASSERT(gTimeZoneFilesDirectory == NULL);
1466f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1467f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTimeZoneFilesDirectory = new CharString();
1468f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gTimeZoneFilesDirectory == NULL) {
1469f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        status = U_MEMORY_ALLOCATION_ERROR;
1470f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1471f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
14720596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WINUWP_API == 0
1473f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const char *dir = getenv("ICU_TIMEZONE_FILES_DIR");
14740596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#else
14750596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // TODO: UWP does not support alternate timezone data directories at this time
14760596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    const char *dir = "";
14770596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif // U_PLATFORM_HAS_WINUWP_API
1478f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#if defined(U_TIMEZONE_FILES_DIR)
1479f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (dir == NULL) {
1480f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        dir = TO_STRING(U_TIMEZONE_FILES_DIR);
1481f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1482f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#endif
1483f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (dir == NULL) {
1484f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        dir = "";
1485f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1486f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    setTimeZoneFilesDir(dir, status);
1487f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1490f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI const char * U_EXPORT2
1491f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_getTimeZoneFilesDirectory(UErrorCode *status) {
1492f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_initOnce(gTimeZoneFilesInitOnce, &TimeZoneDataDirInitFn, *status);
1493f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return U_SUCCESS(*status) ? gTimeZoneFilesDirectory->data() : "";
1494f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1495f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1496f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2
1497f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_setTimeZoneFilesDirectory(const char *path, UErrorCode *status) {
1498f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_initOnce(gTimeZoneFilesInitOnce, &TimeZoneDataDirInitFn, *status);
1499f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    setTimeZoneFilesDir(path, *status);
1500f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1501f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Note: this function does some extra churn, first setting based on the
1502f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    //       environment, then immediately replacing with the value passed in.
1503f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    //       The logic is simpler that way, and performance shouldn't be an issue.
1504f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_POSIX_LOCALE
150827f654740f2a26ad62a5c155af9199af9e69b889claireho/* A helper function used by uprv_getPOSIXIDForDefaultLocale and
150927f654740f2a26ad62a5c155af9199af9e69b889claireho * uprv_getPOSIXIDForDefaultCodepage. Returns the posix locale id for
151027f654740f2a26ad62a5c155af9199af9e69b889claireho * LC_CTYPE and LC_MESSAGES. It doesn't support other locale categories.
151127f654740f2a26ad62a5c155af9199af9e69b889claireho */
151227f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char *uprv_getPOSIXIDForCategory(int category)
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
151427f654740f2a26ad62a5c155af9199af9e69b889claireho    const char* posixID = NULL;
151527f654740f2a26ad62a5c155af9199af9e69b889claireho    if (category == LC_MESSAGES || category == LC_CTYPE) {
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
151785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        * On Solaris two different calls to setlocale can result in
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * different values. Only get this value once.
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * We must check this first because an application can set this.
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * LC_ALL can't be used because it's platform dependent. The LANG
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * environment variable seems to affect LC_CTYPE variable by default.
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * Here is what setlocale(LC_ALL, NULL) can return.
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * HPUX can return 'C C C C C C C'
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * Solaris can return /en_US/C/C/C/C/C on the second try.
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * Linux can return LC_CTYPE=C;LC_NUMERIC=C;...
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * The default codepage detection also needs to use LC_CTYPE.
153085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        *
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * Do not call setlocale(LC_*, "")! Using an empty string instead
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * of NULL, will modify the libc behavior.
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
153427f654740f2a26ad62a5c155af9199af9e69b889claireho        posixID = setlocale(category, NULL);
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((posixID == 0)
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            || (uprv_strcmp("C", posixID) == 0)
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            || (uprv_strcmp("POSIX", posixID) == 0))
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Maybe we got some garbage.  Try something more reasonable */
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            posixID = getenv("LC_ALL");
15418de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            /* Solaris speaks POSIX -  See IEEE Std 1003.1-2008
15428de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert             * This is needed to properly handle empty env. variables
15438de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert             */
15448de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#if U_PLATFORM == U_PF_SOLARIS
15458de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if ((posixID == 0) || (posixID[0] == '\0')) {
15468de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
15478de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if ((posixID == 0) || (posixID[0] == '\0')) {
15488de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#else
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (posixID == 0) {
155027f654740f2a26ad62a5c155af9199af9e69b889claireho                posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (posixID == 0) {
15528de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#endif
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    posixID = getenv("LANG");
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
155727f654740f2a26ad62a5c155af9199af9e69b889claireho    }
155827f654740f2a26ad62a5c155af9199af9e69b889claireho    if ((posixID==0)
155927f654740f2a26ad62a5c155af9199af9e69b889claireho        || (uprv_strcmp("C", posixID) == 0)
156027f654740f2a26ad62a5c155af9199af9e69b889claireho        || (uprv_strcmp("POSIX", posixID) == 0))
156127f654740f2a26ad62a5c155af9199af9e69b889claireho    {
156227f654740f2a26ad62a5c155af9199af9e69b889claireho        /* Nothing worked.  Give it a nice POSIX default value. */
156327f654740f2a26ad62a5c155af9199af9e69b889claireho        posixID = "en_US_POSIX";
156427f654740f2a26ad62a5c155af9199af9e69b889claireho    }
156527f654740f2a26ad62a5c155af9199af9e69b889claireho    return posixID;
156627f654740f2a26ad62a5c155af9199af9e69b889claireho}
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
156827f654740f2a26ad62a5c155af9199af9e69b889claireho/* Return just the POSIX id for the default locale, whatever happens to be in
156927f654740f2a26ad62a5c155af9199af9e69b889claireho * it. It gets the value from LC_MESSAGES and indirectly from LC_ALL and LANG.
157027f654740f2a26ad62a5c155af9199af9e69b889claireho */
157127f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char *uprv_getPOSIXIDForDefaultLocale(void)
157227f654740f2a26ad62a5c155af9199af9e69b889claireho{
157327f654740f2a26ad62a5c155af9199af9e69b889claireho    static const char* posixID = NULL;
157427f654740f2a26ad62a5c155af9199af9e69b889claireho    if (posixID == 0) {
157527f654740f2a26ad62a5c155af9199af9e69b889claireho        posixID = uprv_getPOSIXIDForCategory(LC_MESSAGES);
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
157727f654740f2a26ad62a5c155af9199af9e69b889claireho    return posixID;
157827f654740f2a26ad62a5c155af9199af9e69b889claireho}
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
158054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if !U_CHARSET_IS_UTF8
158127f654740f2a26ad62a5c155af9199af9e69b889claireho/* Return just the POSIX id for the default codepage, whatever happens to be in
158227f654740f2a26ad62a5c155af9199af9e69b889claireho * it. It gets the value from LC_CTYPE and indirectly from LC_ALL and LANG.
158327f654740f2a26ad62a5c155af9199af9e69b889claireho */
158427f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char *uprv_getPOSIXIDForDefaultCodepage(void)
158527f654740f2a26ad62a5c155af9199af9e69b889claireho{
158627f654740f2a26ad62a5c155af9199af9e69b889claireho    static const char* posixID = NULL;
158727f654740f2a26ad62a5c155af9199af9e69b889claireho    if (posixID == 0) {
158827f654740f2a26ad62a5c155af9199af9e69b889claireho        posixID = uprv_getPOSIXIDForCategory(LC_CTYPE);
158927f654740f2a26ad62a5c155af9199af9e69b889claireho    }
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return posixID;
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
159354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#endif
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* NOTE: The caller should handle thread safety */
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char* U_EXPORT2
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getDefaultLocaleID()
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_POSIX_LOCALE
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Note that:  (a '!' means the ID is improper somehow)
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     LC_ALL  ---->     default_loc          codepage
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru--------------------------------------------------------
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     ab.CD             ab                   CD
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     ab@CD             ab__CD               -
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     ab@CD.EF          ab__CD               EF
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     ab_CD.EF@GH       ab_CD_GH             EF
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSome 'improper' ways to do the same as above:
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  !  ab_CD@GH.EF       ab_CD_GH             EF
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  !  ab_CD.EF@GH.IJ    ab_CD_GH             EF
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  !  ab_CD@ZZ.EF@GH.IJ ab_CD_GH             EF
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     _CD@GH            _CD_GH               -
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     _CD.EF@GH         _CD_GH               EF
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe variant cannot have dots in it.
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe 'rightmost' variant (@xxx) wins.
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe leftmost codepage (.xxx) wins.
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *correctedPOSIXLocale = 0;
162327f654740f2a26ad62a5c155af9199af9e69b889claireho    const char* posixID = uprv_getPOSIXIDForDefaultLocale();
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *p;
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *q;
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Format: (no spaces)
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ll [ _CC ] [ . MM ] [ @ VV]
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      l = lang, C = ctry, M = charmap, V = variant
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (gCorrectedPOSIXLocale != NULL) {
163585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return gCorrectedPOSIXLocale;
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((p = uprv_strchr(posixID, '.')) != NULL) {
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* assume new locale can't be larger than old one? */
164054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        correctedPOSIXLocale = static_cast<char *>(uprv_malloc(uprv_strlen(posixID)+1));
164185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Exit on memory allocation error. */
164285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (correctedPOSIXLocale == NULL) {
164385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return NULL;
164485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strncpy(correctedPOSIXLocale, posixID, p-posixID);
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        correctedPOSIXLocale[p-posixID] = 0;
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* do not copy after the @ */
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((p = uprv_strchr(correctedPOSIXLocale, '@')) != NULL) {
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correctedPOSIXLocale[p-correctedPOSIXLocale] = 0;
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Note that we scan the *uncorrected* ID. */
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((p = uprv_strrchr(posixID, '@')) != NULL) {
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (correctedPOSIXLocale == NULL) {
165754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            correctedPOSIXLocale = static_cast<char *>(uprv_malloc(uprv_strlen(posixID)+1));
165885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* Exit on memory allocation error. */
165985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (correctedPOSIXLocale == NULL) {
166085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return NULL;
166185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strncpy(correctedPOSIXLocale, posixID, p-posixID);
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correctedPOSIXLocale[p-posixID] = 0;
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        p++;
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Take care of any special cases here.. */
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (!uprv_strcmp(p, "nynorsk")) {
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            p = "NY";
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Don't worry about no__NY. In practice, it won't appear. */
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strchr(correctedPOSIXLocale,'_') == NULL) {
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(correctedPOSIXLocale, "__"); /* aa@b -> aa__b */
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(correctedPOSIXLocale, "_"); /* aa_CC@b -> aa_CC_b */
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((q = uprv_strchr(p, '.')) != NULL) {
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* How big will the resulting string be? */
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len = (int32_t)(uprv_strlen(correctedPOSIXLocale) + (q-p));
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strncat(correctedPOSIXLocale, p, q-p);
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correctedPOSIXLocale[len] = 0;
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Anything following the @ sign */
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(correctedPOSIXLocale, p);
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Should there be a map from 'no@nynorsk' -> no_NO_NY here?
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * How about 'russian' -> 'ru'?
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Many of the other locales using ISO codes will be handled by the
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * canonicalization functions in uloc_getDefault.
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Was a correction made? */
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (correctedPOSIXLocale != NULL) {
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        posixID = correctedPOSIXLocale;
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy it, just in case the original pointer goes away.  See j2395 */
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        correctedPOSIXLocale = (char *)uprv_malloc(uprv_strlen(posixID) + 1);
170585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Exit on memory allocation error. */
170685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (correctedPOSIXLocale == NULL) {
170785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return NULL;
170885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        posixID = uprv_strcpy(correctedPOSIXLocale, posixID);
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (gCorrectedPOSIXLocale == NULL) {
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        gCorrectedPOSIXLocale = correctedPOSIXLocale;
17140596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        gCorrectedPOSIXLocaleHeapAllocated = true;
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        correctedPOSIXLocale = NULL;
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (correctedPOSIXLocale != NULL) {  /* Was already set - clean up. */
172085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(correctedPOSIXLocale);
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return posixID;
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1725103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM_USES_ONLY_WIN32_API
172659d709d503bab6e2b61931737e662dd293b40578ccornelius#define POSIX_LOCALE_CAPACITY 64
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
172859d709d503bab6e2b61931737e662dd293b40578ccornelius    char *correctedPOSIXLocale = 0;
172959d709d503bab6e2b61931737e662dd293b40578ccornelius
17300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // If we have already figured this out just use the cached value
173159d709d503bab6e2b61931737e662dd293b40578ccornelius    if (gCorrectedPOSIXLocale != NULL) {
173259d709d503bab6e2b61931737e662dd293b40578ccornelius        return gCorrectedPOSIXLocale;
173359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
173459d709d503bab6e2b61931737e662dd293b40578ccornelius
17350596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // No cached value, need to determine the current value
17360596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    static WCHAR windowsLocale[LOCALE_NAME_MAX_LENGTH];
17370596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WINUWP_API == 0
17380596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // If not a Universal Windows App, we'll need user default language.
17390596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Vista and above should use Locale Names instead of LCIDs
17400596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    int length = GetUserDefaultLocaleName(windowsLocale, UPRV_LENGTHOF(windowsLocale));
17410596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#else
17420596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // In a UWP app, we want the top language that the application and user agreed upon
17430596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING>> languageList;
17440596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17450596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    ComPtr<ABI::Windows::Globalization::IApplicationLanguagesStatics> applicationLanguagesStatics;
17460596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    HRESULT hr = GetActivationFactory(
17470596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        HStringReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(),
17480596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        &applicationLanguagesStatics);
17490596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (SUCCEEDED(hr))
17500596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
17510596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        hr = applicationLanguagesStatics->get_Languages(&languageList);
17520596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
17530596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17540596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (FAILED(hr))
17550596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
17560596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        // If there is no application context, then use the top language from the user language profile
17570596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        ComPtr<ABI::Windows::System::UserProfile::IGlobalizationPreferencesStatics> globalizationPreferencesStatics;
17580596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        hr = GetActivationFactory(
17590596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            HStringReference(RuntimeClass_Windows_System_UserProfile_GlobalizationPreferences).Get(),
17600596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            &globalizationPreferencesStatics);
17610596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (SUCCEEDED(hr))
17620596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
17630596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            hr = globalizationPreferencesStatics->get_Languages(&languageList);
17640596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
17650596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
17660596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17670596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // We have a list of languages, ICU knows one, so use the top one for our locale
17680596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    HString topLanguage;
17690596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (SUCCEEDED(hr))
17700596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
17710596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        hr = languageList->GetAt(0, topLanguage.GetAddressOf());
17720596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
17730596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17740596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (FAILED(hr))
17750596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
17760596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        // Unexpected, use en-US by default
17770596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (gCorrectedPOSIXLocale == NULL) {
17780596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            gCorrectedPOSIXLocale = "en_US";
17790596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
17800596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17810596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        return gCorrectedPOSIXLocale;
17820596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
17830596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17840596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // ResolveLocaleName will get a likely subtags form consistent with Windows behavior.
17850596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    int length = ResolveLocaleName(topLanguage.GetRawBuffer(NULL), windowsLocale, UPRV_LENGTHOF(windowsLocale));
17860596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
17870596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Now we should have a Windows locale name that needs converted to the POSIX style,
17880596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (length > 0)
17890596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
17900596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        // First we need to go from UTF-16 to char (and also convert from _ to - while we're at it.)
17910596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        char modifiedWindowsLocale[LOCALE_NAME_MAX_LENGTH];
17920596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
17930596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        int32_t i;
17940596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        for (i = 0; i < UPRV_LENGTHOF(modifiedWindowsLocale); i++)
17950596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
17960596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            if (windowsLocale[i] == '_')
17970596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            {
17980596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                modifiedWindowsLocale[i] = '-';
17990596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            }
18000596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            else
18010596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            {
18020596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                modifiedWindowsLocale[i] = static_cast<char>(windowsLocale[i]);
18030596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            }
18040596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
18050596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            if (modifiedWindowsLocale[i] == '\0')
18060596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            {
18070596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                break;
18080596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            }
18090596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
18100596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
18110596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (i >= UPRV_LENGTHOF(modifiedWindowsLocale))
18120596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
18130596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // Ran out of room, can't really happen, maybe we'll be lucky about a matching
18140596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // locale when tags are dropped
18150596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            modifiedWindowsLocale[UPRV_LENGTHOF(modifiedWindowsLocale) - 1] = '\0';
18160596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
18170596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
18180596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        // Now normalize the resulting name
1819ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        correctedPOSIXLocale = static_cast<char *>(uprv_malloc(POSIX_LOCALE_CAPACITY + 1));
1820ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        /* TODO: Should we just exit on memory allocation failure? */
18210596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (correctedPOSIXLocale)
18220596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        {
18230596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            int32_t posixLen = uloc_canonicalize(modifiedWindowsLocale, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status);
18240596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            if (U_SUCCESS(status))
18250596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            {
18260596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                *(correctedPOSIXLocale + posixLen) = 0;
18270596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                gCorrectedPOSIXLocale = correctedPOSIXLocale;
18280596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                gCorrectedPOSIXLocaleHeapAllocated = true;
18290596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
18300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            }
18310596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            else
18320596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            {
18330596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                uprv_free(correctedPOSIXLocale);
18340596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            }
183559d709d503bab6e2b61931737e662dd293b40578ccornelius        }
183659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
18380596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // If unable to find a locale we can agree upon, use en-US by default
183959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (gCorrectedPOSIXLocale == NULL) {
18400596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        gCorrectedPOSIXLocale = "en_US";
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
184259d709d503bab6e2b61931737e662dd293b40578ccornelius    return gCorrectedPOSIXLocale;
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS400
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* locales are process scoped and are by definition thread safe */
1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static char correctedLocale[64];
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const  char *localeID = getenv("LC_ALL");
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           char *p;
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeID == NULL)
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID = getenv("LANG");
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeID == NULL)
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID = setlocale(LC_ALL, NULL);
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Make sure we have something... */
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeID == NULL)
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return "en_US_POSIX";
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Extract the locale name from the path. */
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((p = uprv_strrchr(localeID, '/')) != NULL)
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Increment p to start of locale name. */
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        p++;
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID = p;
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Copy to work location. */
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcpy(correctedLocale, localeID);
1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Strip off the '.locale' extension. */
1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((p = uprv_strchr(correctedLocale, '.')) != NULL) {
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *p = 0;
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Upper case the locale name. */
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_CString_toUpperCase(correctedLocale);
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* See if we are using the POSIX locale.  Any of the
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * following are equivalent and use the same QLGPGCMA
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * (POSIX) locale.
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * QLGPGCMA2 means UCS2
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * QLGPGCMA_4 means UTF-32
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * QLGPGCMA_8 means UTF-8
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((uprv_strcmp("C", correctedLocale) == 0) ||
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (uprv_strcmp("POSIX", correctedLocale) == 0) ||
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (uprv_strncmp("QLGPGCMA", correctedLocale, 8) == 0))
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcpy(correctedLocale, "en_US_POSIX");
1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int16_t LocaleLen;
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Lower case the lang portion. */
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(p = correctedLocale; *p != 0 && *p != '_'; p++)
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *p = uprv_tolower(*p);
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Adjust for Euro.  After '_E' add 'URO'. */
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LocaleLen = uprv_strlen(correctedLocale);
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (correctedLocale[LocaleLen - 2] == '_' &&
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correctedLocale[LocaleLen - 1] == 'E')
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(correctedLocale, "URO");
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* If using Lotus-based locale then convert to
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * equivalent non Lotus.
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (correctedLocale[LocaleLen - 2] == '_' &&
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correctedLocale[LocaleLen - 1] == 'L')
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correctedLocale[LocaleLen - 2] = 0;
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* There are separate simplified and traditional
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * locales called zh_HK_S and zh_HK_T.
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (uprv_strncmp(correctedLocale, "zh_HK", 5) == 0)
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcpy(correctedLocale, "zh_HK");
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* A special zh_CN_GBK locale...
1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (uprv_strcmp(correctedLocale, "zh_CN_GBK") == 0)
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcpy(correctedLocale, "zh_CN");
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return correctedLocale;
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
193985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_POSIX_LOCALE
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDue to various platform differences, one platform may specify a charset,
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwhen they really mean a different charset. Remap the names so that they are
1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querucompatible with ICU. Only conflicting/ambiguous aliases should be resolved
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruhere. Before adding anything to this function, please consider adding unique
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunames to the ICU alias table in the data directory.
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char*
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruremapPlatformDependentCodepage(const char *locale, const char *name) {
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (locale != NULL && *locale == 0) {
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Make sure that an empty locale is handled the same way. */
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        locale = NULL;
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (name == NULL) {
1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1957103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM == U_PF_AIX
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (uprv_strcmp(name, "IBM-943") == 0) {
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Use the ASCII compatible ibm-943 */
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "Shift-JIS";
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (uprv_strcmp(name, "IBM-1252") == 0) {
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Use the windows-1252 that contains the Euro */
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "IBM-5348";
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1966103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_SOLARIS
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (locale != NULL && uprv_strcmp(name, "EUC") == 0) {
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Solaris underspecifies the "EUC" name. */
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strcmp(locale, "zh_CN") == 0) {
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            name = "EUC-CN";
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (uprv_strcmp(locale, "zh_TW") == 0) {
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            name = "EUC-TW";
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (uprv_strcmp(locale, "ko_KR") == 0) {
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            name = "EUC-KR";
1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (uprv_strcmp(name, "eucJP") == 0) {
1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-954 is the best match.
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-33722 is the default for eucJP (similar to Windows).
1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "eucjis";
1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
198685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if (uprv_strcmp(name, "646") == 0) {
198785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /*
198885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         * The default codepage given by Solaris is 646 but the C library routines treat it as if it was
198985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         * ISO-8859-1 instead of US-ASCII(646).
199085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         */
199185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        name = "ISO-8859-1";
199285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1993103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM_IS_DARWIN_BASED
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (locale == NULL && *name == 0) {
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        No locale was specified, and an empty name was passed in.
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        This usually indicates that nl_langinfo didn't return valid information.
1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Mac OS X uses UTF-8 by default (especially the locale data and console).
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "UTF-8";
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
200285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if (uprv_strcmp(name, "CP949") == 0) {
200385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Remap CP949 to a similar codepage to avoid issues with backslash and won symbol. */
200485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        name = "EUC-KR";
200585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
200650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    else if (locale != NULL && uprv_strcmp(locale, "en_US_POSIX") != 0 && uprv_strcmp(name, "US-ASCII") == 0) {
200750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /*
200850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * For non C/POSIX locale, default the code page to UTF-8 instead of US-ASCII.
200950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         */
201050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        name = "UTF-8";
201150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
2012103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_BSD
201385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (uprv_strcmp(name, "CP949") == 0) {
201485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Remap CP949 to a similar codepage to avoid issues with backslash and won symbol. */
201585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        name = "EUC-KR";
201685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
2017103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_HPUX
201885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (locale != NULL && uprv_strcmp(locale, "zh_HK") == 0 && uprv_strcmp(name, "big5") == 0) {
201985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* HP decided to extend big5 as hkbig5 even though it's not compatible :-( */
202085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* zh_TW.big5 is not the same charset as zh_HK.big5! */
202185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        name = "hkbig5";
202285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
202385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if (uprv_strcmp(name, "eucJP") == 0) {
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-1350 is the best match, but unavailable.
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-954 is mostly a superset of ibm-1350.
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-33722 is the default for eucJP (similar to Windows).
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "eucjis";
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2031103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_LINUX
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (locale != NULL && uprv_strcmp(name, "euc") == 0) {
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Linux underspecifies the "EUC" name. */
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strcmp(locale, "korean") == 0) {
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            name = "EUC-KR";
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (uprv_strcmp(locale, "japanese") == 0) {
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* See comment below about eucJP */
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            name = "eucjis";
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (uprv_strcmp(name, "eucjp") == 0) {
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-1350 is the best match, but unavailable.
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-954 is mostly a superset of ibm-1350.
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ibm-33722 is the default for eucJP (similar to Windows).
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "eucjis";
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
205050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    else if (locale != NULL && uprv_strcmp(locale, "en_US_POSIX") != 0 &&
205150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            (uprv_strcmp(name, "ANSI_X3.4-1968") == 0 || uprv_strcmp(name, "US-ASCII") == 0)) {
205250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /*
205350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * For non C/POSIX locale, default the code page to UTF-8 instead of US-ASCII.
205450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         */
205550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        name = "UTF-8";
205650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
205727f654740f2a26ad62a5c155af9199af9e69b889claireho    /*
205827f654740f2a26ad62a5c155af9199af9e69b889claireho     * Linux returns ANSI_X3.4-1968 for C/POSIX, but the call site takes care of
205927f654740f2a26ad62a5c155af9199af9e69b889claireho     * it by falling back to 'US-ASCII' when NULL is returned from this
206027f654740f2a26ad62a5c155af9199af9e69b889claireho     * function. So, we don't have to worry about it here.
206127f654740f2a26ad62a5c155af9199af9e69b889claireho     */
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* return NULL when "" is passed in */
2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (*name == 0) {
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = NULL;
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return name;
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const char*
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetCodepageFromPOSIXID(const char *localeName, char * buffer, int32_t buffCapacity)
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char localeBuf[100];
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *name = NULL;
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *variant = NULL;
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeName != NULL && (name = (uprv_strchr(localeName, '.'))) != NULL) {
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        size_t localeCapacity = uprv_min(sizeof(localeBuf), (name-localeName)+1);
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strncpy(localeBuf, localeName, localeCapacity);
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeBuf[localeCapacity-1] = 0; /* ensure NULL termination */
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = uprv_strncpy(buffer, name+1, buffCapacity);
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        buffer[buffCapacity-1] = 0; /* ensure NULL termination */
2083103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if ((variant = const_cast<char *>(uprv_strchr(name, '@'))) != NULL) {
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *variant = 0;
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = remapPlatformDependentCodepage(localeBuf, name);
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return name;
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
209285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const char*
2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint_getDefaultCodepage()
2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2095103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM == U_PF_OS400
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t ccsid = 37; /* Default to ibm-37 */
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static char codepage[64];
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Qwc_JOBI0400_t jobinfo;
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Qus_EC_t error = { sizeof(Qus_EC_t) }; /* SPI error code */
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    EPT_CALL(QUSRJOBI)(&jobinfo, sizeof(jobinfo), "JOBI0400",
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        "*                         ", "                ", &error);
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (error.Bytes_Available == 0) {
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (jobinfo.Coded_Char_Set_ID != 0xFFFF) {
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ccsid = (uint32_t)jobinfo.Coded_Char_Set_ID;
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (jobinfo.Default_Coded_Char_Set_Id != 0xFFFF) {
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ccsid = (uint32_t)jobinfo.Default_Coded_Char_Set_Id;
2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* else use the default */
2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    sprintf(codepage,"ibm-%d", ccsid);
2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return codepage;
2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2116103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS390
2117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static char codepage[64];
211885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
211985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    strncpy(codepage, nl_langinfo(CODESET),63-strlen(UCNV_SWAP_LFNL_OPTION_STRING));
212085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    strcat(codepage,UCNV_SWAP_LFNL_OPTION_STRING);
2121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    codepage[63] = 0; /* NULL terminate */
212285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return codepage;
2124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2125103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM_USES_ONLY_WIN32_API
2126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static char codepage[64];
21270596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    DWORD codepageNumber = 0;
21280596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
21290596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#if U_PLATFORM_HAS_WINUWP_API > 0
21300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // UWP doesn't have a direct API to get the default ACP as Microsoft would rather
21310596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // have folks use Unicode than a "system" code page, however this is the same
21320596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // codepage as the system default locale codepage.  (FWIW, the system locale is
21330596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // ONLY used for codepage, it should never be used for anything else)
21340596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
21350596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        (LPWSTR)&codepageNumber, sizeof(codepageNumber) / sizeof(WCHAR));
21360596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#else
21370596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Win32 apps can call GetACP
21380596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    codepageNumber = GetACP();
21390596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#endif
21400596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Special case for UTF-8
21410596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (codepageNumber == 65001)
21420596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
21430596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        return "UTF-8";
21440596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
21450596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Windows codepages can look like windows-1252, so format the found number
21460596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // the numbers are eclectic, however all valid system code pages, besides UTF-8
21470596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // are between 3 and 19999
21480596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (codepageNumber > 0 && codepageNumber < 20000)
21490596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    {
21500596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        sprintf(codepage, "windows-%ld", codepageNumber);
21510596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        return codepage;
21520596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
21530596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // If the codepage number call failed then return UTF-8
21540596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return "UTF-8";
2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#elif U_POSIX_LOCALE
2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static char codesetName[100];
2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *localeName = NULL;
2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *name = NULL;
2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
216127f654740f2a26ad62a5c155af9199af9e69b889claireho    localeName = uprv_getPOSIXIDForDefaultCodepage();
2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(codesetName, 0, sizeof(codesetName));
21638de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    /* On Solaris nl_langinfo returns C locale values unless setlocale
21648de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert     * was called earlier.
21658de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert     */
21668de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#if (U_HAVE_NL_LANGINFO_CODESET && U_PLATFORM != U_PF_SOLARIS)
216727f654740f2a26ad62a5c155af9199af9e69b889claireho    /* When available, check nl_langinfo first because it usually gives more
216827f654740f2a26ad62a5c155af9199af9e69b889claireho       useful names. It depends on LC_CTYPE.
2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       nl_langinfo may use the same buffer as setlocale. */
2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *codeset = nl_langinfo(U_NL_LANGINFO_CODESET);
2172103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED
217350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /*
217450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * On Linux and MacOSX, ensure that default codepage for non C/POSIX locale is UTF-8
217550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * instead of ASCII.
217650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         */
217750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (uprv_strcmp(localeName, "en_US_POSIX") != 0) {
217850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            codeset = remapPlatformDependentCodepage(localeName, codeset);
217950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else
218050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
218150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {
218250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            codeset = remapPlatformDependentCodepage(NULL, codeset);
218350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
218450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (codeset != NULL) {
2186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strncpy(codesetName, codeset, sizeof(codesetName));
2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            codesetName[sizeof(codesetName)-1] = 0;
2188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return codesetName;
2189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219327f654740f2a26ad62a5c155af9199af9e69b889claireho    /* Use setlocale in a nice way, and then check some environment variables.
219427f654740f2a26ad62a5c155af9199af9e69b889claireho       Maybe the application used setlocale already.
219527f654740f2a26ad62a5c155af9199af9e69b889claireho    */
219627f654740f2a26ad62a5c155af9199af9e69b889claireho    uprv_memset(codesetName, 0, sizeof(codesetName));
219727f654740f2a26ad62a5c155af9199af9e69b889claireho    name = getCodepageFromPOSIXID(localeName, codesetName, sizeof(codesetName));
219827f654740f2a26ad62a5c155af9199af9e69b889claireho    if (name) {
219927f654740f2a26ad62a5c155af9199af9e69b889claireho        /* if we can find the codeset name from setlocale, return that. */
220027f654740f2a26ad62a5c155af9199af9e69b889claireho        return name;
220127f654740f2a26ad62a5c155af9199af9e69b889claireho    }
220227f654740f2a26ad62a5c155af9199af9e69b889claireho
2203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (*codesetName == 0)
2204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Everything failed. Return US ASCII (ISO 646). */
2206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (void)uprv_strcpy(codesetName, "US-ASCII");
2207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return codesetName;
2209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
2210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return "US-ASCII";
2211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char*  U_EXPORT2
2216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getDefaultCodepage()
2217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static char const  *name = NULL;
2219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(NULL);
2220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (name == NULL) {
2221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = int_getDefaultCodepage();
2222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(NULL);
2224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return name;
2225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
222685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif  /* !U_CHARSET_IS_UTF8 */
2227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* end of platform-specific implementation -------------- */
2230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* version handling --------------------------------------------------------- */
2232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
2234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_versionFromString(UVersionInfo versionArray, const char *versionString) {
2235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *end;
2236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t part=0;
2237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(versionArray==NULL) {
2239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
2240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(versionString!=NULL) {
2243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
2244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            versionArray[part]=(uint8_t)uprv_strtoul(versionString, &end, 10);
2245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(end==versionString || ++part==U_MAX_VERSION_LENGTH || *end!=U_VERSION_DELIMITER) {
2246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
2247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            versionString=end+1;
2249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(part<U_MAX_VERSION_LENGTH) {
2253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        versionArray[part++]=0;
2254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
225885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hou_versionFromUString(UVersionInfo versionArray, const UChar *versionString) {
225985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(versionArray!=NULL && versionString!=NULL) {
226085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        char versionChars[U_MAX_VERSION_STRING_LENGTH+1];
226185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t len = u_strlen(versionString);
226285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(len>U_MAX_VERSION_STRING_LENGTH) {
226385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            len = U_MAX_VERSION_STRING_LENGTH;
226485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
226585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        u_UCharsToChars(versionString, versionChars, len);
226650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        versionChars[len]=0;
226785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        u_versionFromString(versionArray, versionChars);
226885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
226985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
227085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
227185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CAPI void U_EXPORT2
2272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusu_versionToString(const UVersionInfo versionArray, char *versionString) {
2273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t count, part;
2274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t field;
2275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(versionString==NULL) {
2277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
2278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(versionArray==NULL) {
2281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        versionString[0]=0;
2282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
2283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* count how many fields need to be written */
2286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(count=4; count>0 && versionArray[count-1]==0; --count) {
2287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(count <= 1) {
2290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count = 2;
2291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write the first part */
2294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write the decimal field value */
2295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    field=versionArray[0];
2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(field>=100) {
2297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *versionString++=(char)('0'+field/100);
2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        field%=100;
2299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(field>=10) {
2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *versionString++=(char)('0'+field/10);
2302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        field%=10;
2303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *versionString++=(char)('0'+field);
2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write the following parts */
2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(part=1; part<count; ++part) {
2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* write a dot first */
2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *versionString++=U_VERSION_DELIMITER;
2310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* write the decimal field value */
2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        field=versionArray[part];
2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(field>=100) {
2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *versionString++=(char)('0'+field/100);
2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            field%=100;
2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(field>=10) {
2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *versionString++=(char)('0'+field/10);
2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            field%=10;
2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *versionString++=(char)('0'+field);
2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* NUL-terminate */
2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *versionString=0;
2326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_getVersion(UVersionInfo versionArray) {
2330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    (void)copyright;   // Suppress unused variable warning from clang.
2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_versionFromString(versionArray, U_ICU_VERSION);
2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
233450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
233550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * icucfg.h dependent code
233650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
233750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2338ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#if U_ENABLE_DYLOAD && HAVE_DLOPEN && !U_PLATFORM_USES_ONLY_WIN32_API
233950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2340103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if HAVE_DLFCN_H
234150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#ifdef __MVS__
234250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#ifndef __SUSV3
234350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define __SUSV3 1
234450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
234550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
234650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <dlfcn.h>
2347ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#endif /* HAVE_DLFCN_H */
234850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
234950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_INTERNAL void * U_EXPORT2
235050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouprv_dl_open(const char *libName, UErrorCode *status) {
235127f654740f2a26ad62a5c155af9199af9e69b889claireho  void *ret = NULL;
235227f654740f2a26ad62a5c155af9199af9e69b889claireho  if(U_FAILURE(*status)) return ret;
235327f654740f2a26ad62a5c155af9199af9e69b889claireho  ret =  dlopen(libName, RTLD_NOW|RTLD_GLOBAL);
235427f654740f2a26ad62a5c155af9199af9e69b889claireho  if(ret==NULL) {
2355103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifdef U_TRACE_DYLOAD
2356103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    printf("dlerror on dlopen(%s): %s\n", libName, dlerror());
235727f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
235827f654740f2a26ad62a5c155af9199af9e69b889claireho    *status = U_MISSING_RESOURCE_ERROR;
235927f654740f2a26ad62a5c155af9199af9e69b889claireho  }
236027f654740f2a26ad62a5c155af9199af9e69b889claireho  return ret;
236150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
236250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
236350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_INTERNAL void U_EXPORT2
236450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouprv_dl_close(void *lib, UErrorCode *status) {
236527f654740f2a26ad62a5c155af9199af9e69b889claireho  if(U_FAILURE(*status)) return;
236627f654740f2a26ad62a5c155af9199af9e69b889claireho  dlclose(lib);
236750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
236850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_INTERNAL UVoidFunction* U_EXPORT2
2370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehouprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
2371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  union {
2372103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      UVoidFunction *fp;
2373103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      void *vp;
2374103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } uret;
2375103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uret.fp = NULL;
2376103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if(U_FAILURE(*status)) return uret.fp;
2377103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  uret.vp = dlsym(lib, sym);
2378103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if(uret.vp == NULL) {
2379103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifdef U_TRACE_DYLOAD
2380103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    printf("dlerror on dlsym(%p,%s): %s\n", lib,sym, dlerror());
2381103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
238227f654740f2a26ad62a5c155af9199af9e69b889claireho    *status = U_MISSING_RESOURCE_ERROR;
238327f654740f2a26ad62a5c155af9199af9e69b889claireho  }
2384103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return uret.fp;
238550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
238650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2387ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#elif U_ENABLE_DYLOAD && U_PLATFORM_USES_ONLY_WIN32_API && !U_PLATFORM_HAS_WINUWP_API
238850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2389ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert/* Windows API implementation. */
2390ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// Note: UWP does not expose/allow these APIs, so the UWP version gets the null implementation. */
239150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
239250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_INTERNAL void * U_EXPORT2
239350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouprv_dl_open(const char *libName, UErrorCode *status) {
239427f654740f2a26ad62a5c155af9199af9e69b889claireho  HMODULE lib = NULL;
239527f654740f2a26ad62a5c155af9199af9e69b889claireho
239627f654740f2a26ad62a5c155af9199af9e69b889claireho  if(U_FAILURE(*status)) return NULL;
239727f654740f2a26ad62a5c155af9199af9e69b889claireho
2398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  lib = LoadLibraryA(libName);
239927f654740f2a26ad62a5c155af9199af9e69b889claireho
240027f654740f2a26ad62a5c155af9199af9e69b889claireho  if(lib==NULL) {
240127f654740f2a26ad62a5c155af9199af9e69b889claireho    *status = U_MISSING_RESOURCE_ERROR;
240227f654740f2a26ad62a5c155af9199af9e69b889claireho  }
240327f654740f2a26ad62a5c155af9199af9e69b889claireho
240427f654740f2a26ad62a5c155af9199af9e69b889claireho  return (void*)lib;
240550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
240650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
240750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_INTERNAL void U_EXPORT2
240850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouprv_dl_close(void *lib, UErrorCode *status) {
240927f654740f2a26ad62a5c155af9199af9e69b889claireho  HMODULE handle = (HMODULE)lib;
241027f654740f2a26ad62a5c155af9199af9e69b889claireho  if(U_FAILURE(*status)) return;
241127f654740f2a26ad62a5c155af9199af9e69b889claireho
241227f654740f2a26ad62a5c155af9199af9e69b889claireho  FreeLibrary(handle);
241327f654740f2a26ad62a5c155af9199af9e69b889claireho
241427f654740f2a26ad62a5c155af9199af9e69b889claireho  return;
241550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
241650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_INTERNAL UVoidFunction* U_EXPORT2
2418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehouprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
241927f654740f2a26ad62a5c155af9199af9e69b889claireho  HMODULE handle = (HMODULE)lib;
2420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UVoidFunction* addr = NULL;
242127f654740f2a26ad62a5c155af9199af9e69b889claireho
242227f654740f2a26ad62a5c155af9199af9e69b889claireho  if(U_FAILURE(*status) || lib==NULL) return NULL;
242327f654740f2a26ad62a5c155af9199af9e69b889claireho
2424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  addr = (UVoidFunction*)GetProcAddress(handle, sym);
242527f654740f2a26ad62a5c155af9199af9e69b889claireho
242627f654740f2a26ad62a5c155af9199af9e69b889claireho  if(addr==NULL) {
242727f654740f2a26ad62a5c155af9199af9e69b889claireho    DWORD lastError = GetLastError();
242827f654740f2a26ad62a5c155af9199af9e69b889claireho    if(lastError == ERROR_PROC_NOT_FOUND) {
242927f654740f2a26ad62a5c155af9199af9e69b889claireho      *status = U_MISSING_RESOURCE_ERROR;
243027f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
243127f654740f2a26ad62a5c155af9199af9e69b889claireho      *status = U_UNSUPPORTED_ERROR; /* other unknown error. */
243227f654740f2a26ad62a5c155af9199af9e69b889claireho    }
243327f654740f2a26ad62a5c155af9199af9e69b889claireho  }
243427f654740f2a26ad62a5c155af9199af9e69b889claireho
243527f654740f2a26ad62a5c155af9199af9e69b889claireho  return addr;
243650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
243750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
243850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
243950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2440ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert/* No dynamic loading, null (nonexistent) implementation. */
244150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
244250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_INTERNAL void * U_EXPORT2
244350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouprv_dl_open(const char *libName, UErrorCode *status) {
24448de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    (void)libName;
244550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(U_FAILURE(*status)) return NULL;
244650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    *status = U_UNSUPPORTED_ERROR;
244750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return NULL;
244850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
244950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
245050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_INTERNAL void U_EXPORT2
245150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouprv_dl_close(void *lib, UErrorCode *status) {
24528de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    (void)lib;
245350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(U_FAILURE(*status)) return;
245450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    *status = U_UNSUPPORTED_ERROR;
245550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return;
245650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
245750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_INTERNAL UVoidFunction* U_EXPORT2
2459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehouprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
24608de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert  (void)lib;
24618de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert  (void)sym;
2462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(U_SUCCESS(*status)) {
246350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    *status = U_UNSUPPORTED_ERROR;
2464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
2465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return (UVoidFunction*)NULL;
246650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
246750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2468ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#endif
246950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Hey, Emacs, please set the following:
2472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
2473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Local Variables:
2474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * indent-tabs-mode: nil
2475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * End:
2476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
2477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
2478