intl/uconv/src/nsCharsetConverterManager.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     6 #include "nsCOMPtr.h"
     7 #include "nsString.h"
     8 #include "nsUnicharUtils.h"
     9 #include "nsCharsetAlias.h"
    10 #include "nsICategoryManager.h"
    11 #include "nsICharsetConverterManager.h"
    12 #include "nsEncoderDecoderUtils.h"
    13 #include "nsIStringBundle.h"
    14 #include "nsTArray.h"
    15 #include "nsStringEnumerator.h"
    16 #include "mozilla/Services.h"
    18 #include "nsComponentManagerUtils.h"
    19 #include "nsISupportsPrimitives.h"
    20 #include "nsServiceManagerUtils.h"
    22 // just for CONTRACTIDs
    23 #include "nsCharsetConverterManager.h"
    25 static nsIStringBundle * sDataBundle;
    26 static nsIStringBundle * sTitleBundle;
    28 // Class nsCharsetConverterManager [implementation]
    30 NS_IMPL_ISUPPORTS(nsCharsetConverterManager, nsICharsetConverterManager)
    32 nsCharsetConverterManager::nsCharsetConverterManager() 
    33 {
    34 }
    36 nsCharsetConverterManager::~nsCharsetConverterManager() 
    37 {
    38 }
    40 //static
    41 void nsCharsetConverterManager::Shutdown()
    42 {
    43   NS_IF_RELEASE(sDataBundle);
    44   NS_IF_RELEASE(sTitleBundle);
    45 }
    47 static
    48 nsresult LoadExtensibleBundle(const char* aCategory, 
    49                               nsIStringBundle ** aResult)
    50 {
    51   nsCOMPtr<nsIStringBundleService> sbServ =
    52     mozilla::services::GetStringBundleService();
    53   if (!sbServ)
    54     return NS_ERROR_FAILURE;
    56   return sbServ->CreateExtensibleBundle(aCategory, aResult);
    57 }
    59 static
    60 nsresult GetBundleValue(nsIStringBundle * aBundle, 
    61                         const char * aName, 
    62                         const nsAFlatString& aProp, 
    63                         char16_t ** aResult)
    64 {
    65   nsAutoString key; 
    67   key.AssignWithConversion(aName);
    68   ToLowerCase(key); // we lowercase the main comparison key
    69   key.Append(aProp);
    71   return aBundle->GetStringFromName(key.get(), aResult);
    72 }
    74 static
    75 nsresult GetBundleValue(nsIStringBundle * aBundle, 
    76                         const char * aName, 
    77                         const nsAFlatString& aProp, 
    78                         nsAString& aResult)
    79 {
    80   nsresult rv = NS_OK;
    82   nsXPIDLString value;
    83   rv = GetBundleValue(aBundle, aName, aProp, getter_Copies(value));
    84   if (NS_FAILED(rv))
    85     return rv;
    87   aResult = value;
    89   return NS_OK;
    90 }
    92 static
    93 nsresult GetCharsetDataImpl(const char * aCharset, const char16_t * aProp,
    94                             nsAString& aResult)
    95 {
    96   NS_ENSURE_ARG_POINTER(aCharset);
    97   // aProp can be nullptr
    99   if (!sDataBundle) {
   100     nsresult rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &sDataBundle);
   101     if (NS_FAILED(rv))
   102       return rv;
   103   }
   105   return GetBundleValue(sDataBundle, aCharset, nsDependentString(aProp), aResult);
   106 }
   108 //static
   109 bool nsCharsetConverterManager::IsInternal(const nsACString& aCharset)
   110 {
   111   nsAutoString str;
   112   // fully qualify to possibly avoid vtable call
   113   nsresult rv = GetCharsetDataImpl(PromiseFlatCString(aCharset).get(),
   114                                    MOZ_UTF16(".isInternal"),
   115                                    str);
   117   return NS_SUCCEEDED(rv);
   118 }
   121 //----------------------------------------------------------------------------//----------------------------------------------------------------------------
   122 // Interface nsICharsetConverterManager [implementation]
   124 NS_IMETHODIMP
   125 nsCharsetConverterManager::GetUnicodeEncoder(const char * aDest, 
   126                                              nsIUnicodeEncoder ** aResult)
   127 {
   128   // resolve the charset first
   129   nsAutoCString charset;
   131   // fully qualify to possibly avoid vtable call
   132   nsCharsetConverterManager::GetCharsetAlias(aDest, charset);
   134   return nsCharsetConverterManager::GetUnicodeEncoderRaw(charset.get(),
   135                                                          aResult);
   136 }
   139 NS_IMETHODIMP
   140 nsCharsetConverterManager::GetUnicodeEncoderRaw(const char * aDest, 
   141                                                 nsIUnicodeEncoder ** aResult)
   142 {
   143   *aResult= nullptr;
   144   nsCOMPtr<nsIUnicodeEncoder> encoder;
   146   nsresult rv = NS_OK;
   148   nsAutoCString
   149     contractid(NS_LITERAL_CSTRING(NS_UNICODEENCODER_CONTRACTID_BASE) +
   150                nsDependentCString(aDest));
   152   // Always create an instance since encoders hold state.
   153   encoder = do_CreateInstance(contractid.get(), &rv);
   155   if (NS_FAILED(rv))
   156     rv = NS_ERROR_UCONV_NOCONV;
   157   else
   158   {
   159     *aResult = encoder.get();
   160     NS_ADDREF(*aResult);
   161   }
   162   return rv;
   163 }
   165 NS_IMETHODIMP
   166 nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc, 
   167                                              nsIUnicodeDecoder ** aResult)
   168 {
   169   // resolve the charset first
   170   nsAutoCString charset;
   172   // fully qualify to possibly avoid vtable call
   173   if (NS_FAILED(nsCharsetConverterManager::GetCharsetAlias(aSrc, charset)))
   174     return NS_ERROR_UCONV_NOCONV;
   176   return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
   177                                                          aResult);
   178 }
   180 NS_IMETHODIMP
   181 nsCharsetConverterManager::GetUnicodeDecoderInternal(const char * aSrc, 
   182                                                      nsIUnicodeDecoder ** aResult)
   183 {
   184   // resolve the charset first
   185   nsAutoCString charset;
   187   nsresult rv = nsCharsetAlias::GetPreferredInternal(nsDependentCString(aSrc),
   188                                                      charset);
   189   NS_ENSURE_SUCCESS(rv, rv);
   191   return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
   192                                                          aResult);
   193 }
   195 NS_IMETHODIMP
   196 nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc, 
   197                                                 nsIUnicodeDecoder ** aResult)
   198 {
   199   *aResult= nullptr;
   200   nsCOMPtr<nsIUnicodeDecoder> decoder;
   202   nsresult rv = NS_OK;
   204   NS_NAMED_LITERAL_CSTRING(contractbase, NS_UNICODEDECODER_CONTRACTID_BASE);
   205   nsDependentCString src(aSrc);
   207   decoder = do_CreateInstance(PromiseFlatCString(contractbase + src).get(),
   208                               &rv);
   209   NS_ENSURE_SUCCESS(rv, NS_ERROR_UCONV_NOCONV);
   211   decoder.forget(aResult);
   212   return rv;
   213 }
   215 static
   216 nsresult GetList(const nsACString& aCategory,
   217                  const nsACString& aPrefix,
   218                  nsIUTF8StringEnumerator** aResult)
   219 {
   220   NS_ENSURE_ARG_POINTER(aResult);
   221   *aResult = nullptr;
   223   nsresult rv;
   225   nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
   226   if (NS_FAILED(rv))
   227     return rv;
   229   nsTArray<nsCString>* array = new nsTArray<nsCString>;
   230   if (!array)
   231     return NS_ERROR_OUT_OF_MEMORY;
   233   nsCOMPtr<nsISimpleEnumerator> enumerator;
   234   catman->EnumerateCategory(PromiseFlatCString(aCategory).get(), 
   235                             getter_AddRefs(enumerator));
   237   bool hasMore;
   238   while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
   239     nsCOMPtr<nsISupports> supports;
   240     if (NS_FAILED(enumerator->GetNext(getter_AddRefs(supports))))
   241       continue;
   243     nsCOMPtr<nsISupportsCString> supStr = do_QueryInterface(supports);
   244     if (!supStr)
   245       continue;
   247     nsAutoCString name;
   248     if (NS_FAILED(supStr->GetData(name)))
   249       continue;
   251     nsAutoCString fullName(aPrefix);
   252     fullName.Append(name);
   253     NS_ENSURE_TRUE(array->AppendElement(fullName), NS_ERROR_OUT_OF_MEMORY);
   254   }
   256   return NS_NewAdoptingUTF8StringEnumerator(aResult, array);
   257 }
   259 // we should change the interface so that we can just pass back a enumerator!
   260 NS_IMETHODIMP
   261 nsCharsetConverterManager::GetDecoderList(nsIUTF8StringEnumerator ** aResult)
   262 {
   263   return GetList(NS_LITERAL_CSTRING(NS_UNICODEDECODER_NAME),
   264                  EmptyCString(), aResult);
   265 }
   267 NS_IMETHODIMP
   268 nsCharsetConverterManager::GetEncoderList(nsIUTF8StringEnumerator ** aResult)
   269 {
   270   return GetList(NS_LITERAL_CSTRING(NS_UNICODEENCODER_NAME),
   271                  EmptyCString(), aResult);
   272 }
   274 NS_IMETHODIMP
   275 nsCharsetConverterManager::GetCharsetDetectorList(nsIUTF8StringEnumerator** aResult)
   276 {
   277   return GetList(NS_LITERAL_CSTRING("charset-detectors"),
   278                  NS_LITERAL_CSTRING("chardet."), aResult);
   279 }
   281 // XXX Improve the implementation of this method. Right now, it is build on 
   282 // top of the nsCharsetAlias service. We can make the nsCharsetAlias
   283 // better, with its own hash table (not the StringBundle anymore) and
   284 // a nicer file format.
   285 NS_IMETHODIMP
   286 nsCharsetConverterManager::GetCharsetAlias(const char * aCharset, 
   287                                            nsACString& aResult)
   288 {
   289   NS_ENSURE_ARG_POINTER(aCharset);
   291   // We try to obtain the preferred name for this charset from the charset 
   292   // aliases.
   293   nsresult rv;
   295   rv = nsCharsetAlias::GetPreferred(nsDependentCString(aCharset), aResult);
   296   NS_ENSURE_SUCCESS(rv, rv);
   298   return NS_OK;
   299 }
   302 NS_IMETHODIMP
   303 nsCharsetConverterManager::GetCharsetTitle(const char * aCharset, 
   304                                            nsAString& aResult)
   305 {
   306   NS_ENSURE_ARG_POINTER(aCharset);
   308   if (!sTitleBundle) {
   309     nsresult rv = LoadExtensibleBundle(NS_TITLE_BUNDLE_CATEGORY, &sTitleBundle);
   310     NS_ENSURE_SUCCESS(rv, rv);
   311   }
   313   return GetBundleValue(sTitleBundle, aCharset, NS_LITERAL_STRING(".title"), aResult);
   314 }
   316 NS_IMETHODIMP
   317 nsCharsetConverterManager::GetCharsetData(const char * aCharset, 
   318                                           const char16_t * aProp,
   319                                           nsAString& aResult)
   320 {
   321   return GetCharsetDataImpl(aCharset, aProp, aResult);
   322 }
   324 NS_IMETHODIMP
   325 nsCharsetConverterManager::GetCharsetLangGroup(const char * aCharset, 
   326                                                nsIAtom** aResult)
   327 {
   328   // resolve the charset first
   329   nsAutoCString charset;
   331   nsresult rv = GetCharsetAlias(aCharset, charset);
   332   NS_ENSURE_SUCCESS(rv, rv);
   334   // fully qualify to possibly avoid vtable call
   335   return nsCharsetConverterManager::GetCharsetLangGroupRaw(charset.get(),
   336                                                            aResult);
   337 }
   339 NS_IMETHODIMP
   340 nsCharsetConverterManager::GetCharsetLangGroupRaw(const char * aCharset, 
   341                                                   nsIAtom** aResult)
   342 {
   344   *aResult = nullptr;
   345   nsAutoString langGroup;
   346   // fully qualify to possibly avoid vtable call
   347   nsresult rv = nsCharsetConverterManager::GetCharsetData(
   348       aCharset, MOZ_UTF16(".LangGroup"), langGroup);
   350   if (NS_SUCCEEDED(rv)) {
   351     ToLowerCase(langGroup); // use lowercase for all language atoms
   352     *aResult = NS_NewAtom(langGroup).take();
   353   }
   355   return rv;
   356 }

mercurial