~ubuntu-branches/debian/sid/postgresql-9.3/sid

« back to all changes in this revision

Viewing changes to src/port/win32setlocale.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-05-08 05:39:52 UTC
  • Revision ID: package-import@ubuntu.com-20130508053952-1j7uilp7mjtrvq8q
Tags: upstream-9.3~beta1
ImportĀ upstreamĀ versionĀ 9.3~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * win32setlocale.c
 
4
 *              Wrapper to work around bugs in Windows setlocale() implementation
 
5
 *
 
6
 * Copyright (c) 2011-2013, PostgreSQL Global Development Group
 
7
 *
 
8
 * IDENTIFICATION
 
9
 *        src/port/win32setlocale.c
 
10
 *
 
11
 *
 
12
 * Windows has a problem with locale names that have a dot in the country
 
13
 * name. For example:
 
14
 *
 
15
 * "Chinese (Traditional)_Hong Kong S.A.R..950"
 
16
 *
 
17
 * For some reason, setlocale() doesn't accept that. Fortunately, Windows'
 
18
 * setlocale() accepts various alternative names for such countries, so we
 
19
 * provide a wrapper setlocale() function that maps the troublemaking locale
 
20
 * names to accepted aliases.
 
21
 *-------------------------------------------------------------------------
 
22
 */
 
23
 
 
24
#include "c.h"
 
25
 
 
26
#undef setlocale
 
27
 
 
28
struct locale_map
 
29
{
 
30
        const char *locale_name_part;           /* string in locale name to replace */
 
31
        const char *replacement;        /* string to replace it with */
 
32
};
 
33
 
 
34
static const struct locale_map locale_map_list[] = {
 
35
        /*
 
36
         * "HKG" is listed here:
 
37
         * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
 
38
         * (Country/Region Strings).
 
39
         *
 
40
         * "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
 
41
         * above list, but seems to work anyway.
 
42
         */
 
43
        {"Hong Kong S.A.R.", "HKG"},
 
44
        {"U.A.E.", "ARE"},
 
45
 
 
46
        /*
 
47
         * The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
 
48
         * seem to recognize that. And Macau isn't listed in the table of accepted
 
49
         * abbreviations linked above. Fortunately, "ZHM" seems to be accepted as
 
50
         * an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm not sure
 
51
         * where "ZHM" comes from, must be some legacy naming scheme. But hey, it
 
52
         * works.
 
53
         *
 
54
         * Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
 
55
         * name, not just the country part.
 
56
         *
 
57
         * Some versions of Windows spell it "Macau", others "Macao".
 
58
         */
 
59
        {"Chinese (Traditional)_Macau S.A.R..950", "ZHM"},
 
60
        {"Chinese_Macau S.A.R..950", "ZHM"},
 
61
        {"Chinese (Traditional)_Macao S.A.R..950", "ZHM"},
 
62
        {"Chinese_Macao S.A.R..950", "ZHM"}
 
63
};
 
64
 
 
65
char *
 
66
pgwin32_setlocale(int category, const char *locale)
 
67
{
 
68
        char       *result;
 
69
        char       *alias;
 
70
        int                     i;
 
71
 
 
72
        if (locale == NULL)
 
73
                return setlocale(category, locale);
 
74
 
 
75
        /* Check if the locale name matches any of the problematic ones. */
 
76
        alias = NULL;
 
77
        for (i = 0; i < lengthof(locale_map_list); i++)
 
78
        {
 
79
                const char *needle = locale_map_list[i].locale_name_part;
 
80
                const char *replacement = locale_map_list[i].replacement;
 
81
                char       *match;
 
82
 
 
83
                match = strstr(locale, needle);
 
84
                if (match != NULL)
 
85
                {
 
86
                        /* Found a match. Replace the matched string. */
 
87
                        int                     matchpos = match - locale;
 
88
                        int                     replacementlen = strlen(replacement);
 
89
                        char       *rest = match + strlen(needle);
 
90
                        int                     restlen = strlen(rest);
 
91
 
 
92
                        alias = malloc(matchpos + replacementlen + restlen + 1);
 
93
                        if (!alias)
 
94
                                return NULL;
 
95
 
 
96
                        memcpy(&alias[0], &locale[0], matchpos);
 
97
                        memcpy(&alias[matchpos], replacement, replacementlen);
 
98
                        memcpy(&alias[matchpos + replacementlen], rest, restlen + 1);           /* includes null
 
99
                                                                                                                                                                 * terminator */
 
100
 
 
101
                        break;
 
102
                }
 
103
        }
 
104
 
 
105
        /* Call the real setlocale() function */
 
106
        if (alias)
 
107
        {
 
108
                result = setlocale(category, alias);
 
109
                free(alias);
 
110
        }
 
111
        else
 
112
                result = setlocale(category, locale);
 
113
 
 
114
        return result;
 
115
}