1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "Quotes.h"
7 #include "MozLocale.h"
8 #include "mozilla/ClearOnShutdown.h"
9 #include "mozilla/StaticPtr.h"
10 #include "nsTHashMap.h"
11 #include "nsPrintfCString.h"
12
13 using namespace mozilla;
14 using namespace mozilla::intl;
15
16 namespace {
17 struct LangQuotesRec {
18 const char* mLangs;
19 Quotes mQuotes;
20 };
21
22 #include "cldr-quotes.inc"
23
24 static StaticAutoPtr<nsTHashMap<nsCStringHashKey, Quotes>> sQuotesForLang;
25 } // anonymous namespace
26
27 namespace mozilla {
28 namespace intl {
29
QuotesForLang(const nsAtom * aLang)30 const Quotes* QuotesForLang(const nsAtom* aLang) {
31 MOZ_ASSERT(NS_IsMainThread());
32
33 // On first use, initialize the hashtable from our CLDR-derived data array.
34 if (!sQuotesForLang) {
35 sQuotesForLang = new nsTHashMap<nsCStringHashKey, Quotes>(32);
36 ClearOnShutdown(&sQuotesForLang);
37 for (const auto& i : sLangQuotes) {
38 const char* s = i.mLangs;
39 size_t len;
40 while ((len = strlen(s))) {
41 sQuotesForLang->InsertOrUpdate(nsDependentCString(s, len), i.mQuotes);
42 s += len + 1;
43 }
44 }
45 }
46
47 nsAtomCString langStr(aLang);
48 const Quotes* entry = sQuotesForLang->Lookup(langStr).DataPtrOrNull();
49 if (entry) {
50 // Found an exact match for the requested lang.
51 return entry;
52 }
53
54 // Try parsing lang as a Locale (which will also canonicalize case of the
55 // subtags), then see if we can match it with region or script subtags,
56 // if present, or just the primary language tag.
57 Locale loc(langStr);
58 if (!loc.IsWellFormed()) {
59 return nullptr;
60 }
61 if (!loc.GetRegion().IsEmpty()) {
62 nsAutoCString langAndRegion;
63 langAndRegion.Append(loc.GetLanguage());
64 langAndRegion.Append('-');
65 langAndRegion.Append(loc.GetRegion());
66 if ((entry = sQuotesForLang->Lookup(langAndRegion).DataPtrOrNull())) {
67 return entry;
68 }
69 }
70 if (!loc.GetScript().IsEmpty()) {
71 nsAutoCString langAndScript;
72 langAndScript.Append(loc.GetLanguage());
73 langAndScript.Append('-');
74 langAndScript.Append(loc.GetScript());
75 if ((entry = sQuotesForLang->Lookup(langAndScript).DataPtrOrNull())) {
76 return entry;
77 }
78 }
79 if ((entry = sQuotesForLang->Lookup(loc.GetLanguage()).DataPtrOrNull())) {
80 return entry;
81 }
82
83 return nullptr;
84 }
85
86 } // namespace intl
87 } // namespace mozilla
88