Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: base/localization.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/localization.h ('k') | base/localization_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2004-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15 //
16 // localization.cpp
17 //
18 // Localization functions for date-time, strings, locales, and numbers
19
20 #include "omaha/base/localization.h"
21
22 #include <windows.h> // SetThreadLocale
23 #include <mlang.h>
24 #include "omaha/base/debug.h"
25 #include "omaha/base/logging.h"
26 #include "omaha/base/string.h"
27 #include "omaha/base/time.h"
28 #include "omaha/base/utils.h"
29
30 namespace omaha {
31
32 // The maximum length for a date
33 #define kDateLengthMax 200
34
35 // The maximum length for chracter seperators
36 #define kDecimalSeparatorMaxLen 5
37
38 // Allow the unittest to override.
39 static LCID lcid_override = MAKELCID(-1, -1);
40
41 void SetLcidOverride(const LCID & lcid_new) {
42 lcid_override = lcid_new;
43 }
44
45 // We should call this, it allows for our override
46 LCID GetLiveLcid() {
47 if (lcid_override != MAKELCID(-1, -1))
48 return lcid_override;
49
50 return GetUserDefaultLCID();
51 }
52
53
54 CString ShowDateInternal(const time64 & t, const LCID & lcid,
55 // Either type needs to be 0 or format needs to be
56 // NULL; both cannot be set simultaneously:
57 const DWORD type, const TCHAR * format ) {
58 SYSTEMTIME time = Time64ToLocalTime(t);
59 TCHAR buf[kDateLengthMax] = {_T('\0')};
60 int num = ::GetDateFormat(lcid, type, &time, format, buf, kDateLengthMax);
61 ASSERT(num > 0, (_T("[localization::ShowDateInternal] - GetDateFormat ")
62 _T("failed")));
63
64 return CString(buf);
65 }
66
67 CString ShowDateForLocale(const time64 & t, const LCID & lcid) {
68 return ShowDateInternal(t, lcid, DATE_SHORTDATE, NULL);
69 }
70
71 CString ShowFormattedDateForLocale(const time64 & t, const LCID & lcid,
72 const TCHAR * format) {
73 return ShowDateInternal(t, lcid, 0, format);
74 }
75
76
77 CString ShowTimeInternal(const time64 & t, const LCID & lcid,
78 // Either type needs to be 0 or format needs to be
79 // NULL; both cannot be set simultaneously:
80 const DWORD type, const TCHAR * format) {
81 ASSERT(IsValidTime(t), (_T("[localization::ShowTimeInternal - Invalid ")
82 _T("time %llu"), t));
83
84 SYSTEMTIME time = Time64ToLocalTime(t);
85 TCHAR buf[kDateLengthMax] = {_T('\0')};
86 int num = ::GetTimeFormat(lcid, type, &time, format, buf, kDateLengthMax);
87 ASSERT(num > 0, (_T("[localization::ShowTimeInternal - GetTimeFormat ")
88 _T("failed")));
89
90 return CString(buf);
91 }
92
93 CString ShowTimeForLocale(const time64 & t, const LCID & lcid) {
94 return ShowTimeInternal(t, lcid, TIME_NOSECONDS, NULL);
95 }
96
97 CString ShowFormattedTimeForLocale(const time64 & t, const LCID & lcid,
98 const TCHAR * format) {
99 return ShowTimeInternal(t, lcid, 0, format);
100 }
101
102 // Show the long date and time [ie - Tuesday, March 20, 2004 5:15pm]
103 CString ShowDateTimeForLocale(const time64 & t, const LCID & lcid) {
104 return ShowDateForLocale(t, lcid) + _T(" ") + ShowTimeForLocale(t, lcid);
105 }
106
107 // Get the long data and time in a (US English) format for logging
108 CString ShowDateTimeForLogging(const time64 & t) {
109 if (t == 0) {
110 return CString();
111 }
112 const LCID lcid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
113 return ShowDateTimeForLocale(t, lcid);
114 }
115
116 // Convert a number in string format to formatted string
117 static CString Show(const CString & in, const int decimal_places) {
118 NUMBERFMT nf = {0};
119 TCHAR decimal_seperator[8] = {_T('\0')};
120 TCHAR thousands_seperator[8] = {_T('\0')};
121 GetNumberFormatForLCID(GetLiveLcid(), &nf,
122 decimal_seperator, arraysize(decimal_seperator),
123 thousands_seperator, arraysize(thousands_seperator));
124 nf.NumDigits = decimal_places;
125
126 TCHAR buf[kDateLengthMax] = {_T('\0')};
127 int num = GetNumberFormat(GetLiveLcid(), // locale (current user locale)
128 0, // options
129 in, // input string (see MSDN for chars)
130 &nf, // formatting information
131 buf, // formatted string buffer
132 kDateLengthMax); // size of buffer
133
134 ASSERT(num > 0, (_T("GetNumberFormat failed: %s?"), in.GetString()));
135
136 return CString(buf);
137 }
138
139 // If we have a formatted number containing a decimal, and we want it to be
140 // an int
141 CString TrimDecimal(const CString & in) {
142 // Get the decimal seperator -- cache it as this is very slow
143 static LCID last_user_default_lcid = MAKELCID(-1, -1);
144 static TCHAR buf[kDecimalSeparatorMaxLen] = {_T('\0')};
145
146 LCID current_lcid = GetLiveLcid();
147 if (last_user_default_lcid != current_lcid) {
148 int num = GetLocaleInfo(GetLiveLcid(),
149 LOCALE_SDECIMAL,
150 buf,
151 kDecimalSeparatorMaxLen);
152 ASSERT(num > 0, (L"GetLocaleInfo(.., LOCALE_SDECIMAL, ..) failed?"));
153 last_user_default_lcid = current_lcid;
154 }
155
156 CString sep(buf);
157
158 // Trim it if necessary
159 int pos = String_FindString(in, sep);
160 if (pos != -1)
161 return in.Left(pos);
162
163 return in;
164 }
165
166 // Number Functions
167 // Changes the number into a user viewable format for the current locale
168
169 // TODO(omaha): Rename these functions into ShowNumberForLocale.
170 CString Show(const int i) {
171 return TrimDecimal(Show(itostr(i), 0));
172 }
173
174 CString Show(const uint32 u) {
175 return TrimDecimal(Show(itostr(u), 0));
176 }
177
178 CString Show(const double & d, const int decimal_places) {
179 return Show(String_DoubleToString(d, decimal_places), decimal_places);
180 }
181
182 HRESULT SetLocaleToRfc1766(const TCHAR * rfc1766_locale) {
183 ASSERT1(rfc1766_locale != NULL);
184
185 // Convert the RFC 1766 locale (eg, "fr-CA" for Canadian French to a
186 // Windows LCID (eg, 0x0c0c for Canadian French)
187 CComPtr<IMultiLanguage2> pIM;
188 RET_IF_FAILED(pIM.CoCreateInstance(__uuidof(CMultiLanguage)));
189
190 LCID lcid = 0;
191 CComBSTR rfc1766_locale_bstr(rfc1766_locale);
192 RET_IF_FAILED(pIM->GetLcidFromRfc1766(&lcid, (BSTR)rfc1766_locale_bstr));
193
194 return SetLocaleToLCID(lcid);
195 }
196
197 HRESULT SetLocaleToLCID(const LCID & lcid) {
198 // Initialize the locales
199 // (in an attempt to cut down on our memory footprint, don't call
200 // the libc version of setlocale)
201 if (!::SetThreadLocale(lcid)) {
202 UTIL_LOG(LEVEL_ERROR, (_T("Unable to SetThreadLocale to lcid 0x%x"),
203 lcid));
204 return E_FAIL;
205 }
206
207 return S_OK;
208 }
209
210 HRESULT GetLocaleAsLCID(LCID * lcid) {
211 ASSERT1(lcid != NULL);
212
213 *lcid = GetThreadLocale();
214 return S_OK;
215 }
216
217 HRESULT GetLocaleAsRfc1766(CString * rfc1766_locale) {
218 ASSERT1(rfc1766_locale != NULL);
219
220 LCID lcid = 0;
221 HRESULT hr = GetLocaleAsLCID(&lcid);
222 if (FAILED(hr)) {
223 return hr;
224 }
225
226 CComPtr<IMultiLanguage2> pIM;
227 RET_IF_FAILED(pIM.CoCreateInstance(__uuidof(CMultiLanguage)));
228
229 CComBSTR bstr;
230 RET_IF_FAILED(pIM->GetRfc1766FromLcid(lcid, &bstr));
231
232 *rfc1766_locale = bstr;
233 return hr;
234 }
235
236 HRESULT GetNumberFormatForLCID(const LCID & lcid, NUMBERFMT * fmt,
237 TCHAR * fmt_decimal_buf,
238 size_t decimal_buf_len, // including null char
239 TCHAR * fmt_thousand_buf,
240 size_t thousand_buf_len) { // including null
241 ASSERT1(fmt);
242
243 TCHAR buf[64] = {_T('\0')};
244 size_t buf_len = arraysize(buf);
245
246 HRESULT hr = S_OK;
247 int retval = GetLocaleInfo(lcid, LOCALE_IDIGITS, buf, buf_len);
248
249 if (!retval) {
250 CORE_LOG(LEVEL_WARNING, (_T("[localization::GetNumberFormatForLCID - ")
251 _T("Failed to load LOCALE_IDIGITS]")));
252 hr = E_FAIL;
253 } else {
254 fmt->NumDigits = String_StringToInt(buf);
255 }
256
257 retval = GetLocaleInfo(lcid, LOCALE_ILZERO, buf, buf_len);
258 if (!retval) {
259 CORE_LOG(LEVEL_WARNING, (_T("[App::Impl::InitializeLocaleSettings - ")
260 _T("Failed to load LOCALE_ILZERO]")));
261 hr = E_FAIL;
262 } else {
263 fmt->LeadingZero = String_StringToInt(buf);
264 }
265
266 retval = GetLocaleInfo(lcid, LOCALE_INEGNUMBER, buf, buf_len);
267 if (!retval) {
268 CORE_LOG(LEVEL_WARNING, (_T("[App::Impl::InitializeLocaleSettings - ")
269 _T("Failed to load LOCALE_INEGNUMBER]")));
270 hr = E_FAIL;
271 } else {
272 fmt->NegativeOrder = String_StringToInt(buf);
273 }
274
275 retval = GetLocaleInfo(lcid, LOCALE_SGROUPING, buf, buf_len);
276 if (!retval) {
277 CORE_LOG(LEVEL_WARNING, (_T("[App::Impl::InitializeLocaleSettings - ")
278 _T("Failed to load LOCALE_SGROUPING]")));
279 hr = E_FAIL;
280 } else {
281 // A string terminated in ';0' is equivalent to the substring without
282 // the ';0', so just truncate the ';0' from the string
283 int semicolon_idx = String_ReverseFindChar(buf, _T(';'));
284 if (retval > semicolon_idx && buf[semicolon_idx + 1] == _T('0')) {
285 buf[semicolon_idx] = _T('\0');
286 }
287
288 if (String_FindChar(buf, _T(';')) != -1) {
289 // NUMBERFMT only allows values 0-9 or 32 for number grouping. If
290 // this locale has variable-length grouping rules (as indicated by
291 // the presence of ';[1-9]'), pass in the only variable-length
292 // grouping rule NUMBERFMT understands: 32. Note that '3;0' is
293 // considered a fixed-length grouping rule and handled above.
294 // This is a HACK.
295 fmt->Grouping = 32;
296 } else {
297 fmt->Grouping = String_StringToInt(buf);
298 }
299 }
300
301 // GetLocaleInfo doesn't write more than 4 chars for this field (per MSDN)
302 retval = GetLocaleInfo(lcid, LOCALE_SDECIMAL, fmt_decimal_buf,
303 decimal_buf_len);
304 if (!retval) {
305 CORE_LOG(LEVEL_WARNING, (_T("[App::Impl::InitializeLocaleSettings - ")
306 _T("Failed to load LOCALE_SDECIMAL]")));
307 hr = E_FAIL;
308 } else {
309 fmt->lpDecimalSep = fmt_decimal_buf;
310 }
311
312 // GetLocaleInfo doesn't write more than 4 chars for this field (per MSDN)
313 retval = GetLocaleInfo(lcid, LOCALE_STHOUSAND, fmt_thousand_buf,
314 thousand_buf_len);
315 if (!retval) {
316 CORE_LOG(LEVEL_WARNING, (_T("[App::Impl::InitializeLocaleSettings - ")
317 _T("Failed to load LOCALE_STHOUSAND]")));
318 hr = E_FAIL;
319 } else {
320 fmt->lpThousandSep = fmt_thousand_buf;
321 }
322
323 retval = GetLocaleInfo(lcid, LOCALE_INEGNUMBER, buf, buf_len);
324 if (!retval) {
325 CORE_LOG(LEVEL_WARNING, (_T("[App::Impl::InitializeLocaleSettings - ")
326 _T("Failed to load LOCALE_INEGNUMBER]")));
327 hr = E_FAIL;
328 } else {
329 fmt->NegativeOrder = String_StringToInt(buf);
330 }
331
332 return hr;
333 }
334
335 } // namespace omaha
336
OLDNEW
« no previous file with comments | « base/localization.h ('k') | base/localization_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698