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