sbStringBundle.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4 //
5 // BEGIN SONGBIRD GPL
6 //
7 // This file is part of the Songbird web player.
8 //
9 // Copyright(c) 2005-2009 POTI, Inc.
10 // http://songbirdnest.com
11 //
12 // This file may be licensed under the terms of of the
13 // GNU General Public License Version 2 (the "GPL").
14 //
15 // Software distributed under the License is distributed
16 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
17 // express or implied. See the GPL for the specific language
18 // governing rights and limitations.
19 //
20 // You should have received a copy of the GPL along with this
21 // program. If not, go to http://www.gnu.org/licenses/gpl.html
22 // or write to the Free Software Foundation, Inc.,
23 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 //
25 // END SONGBIRD GPL
26 //
27 */
28 
29 //------------------------------------------------------------------------------
30 //------------------------------------------------------------------------------
31 //
32 // Songbird string bundle services.
33 //
34 //------------------------------------------------------------------------------
35 //------------------------------------------------------------------------------
36 
43 //------------------------------------------------------------------------------
44 //
45 // Songbird string bundle imported services.
46 //
47 //------------------------------------------------------------------------------
48 
49 // Self imports.
50 #include "sbStringBundle.h"
51 
52 // Songbird imports.
53 #include <sbIStringBundleService.h>
54 
55 // Mozilla imports.
56 #include <nsIStringBundle.h>
57 #include <nsServiceManagerUtils.h>
58 #include <prlog.h>
59 
66 #ifdef PR_LOGGING
67 static PRLogModuleInfo* gStringBundleLog = nsnull;
68 #define TRACE(args) PR_LOG(gStringBundleLog, PR_LOG_DEBUG, args)
69 #define LOG(args) PR_LOG(gStringBundleLog, PR_LOG_WARN, args)
70 #ifdef __GNUC__
71 #define __FUNCTION__ __PRETTY_FUNCTION__
72 #endif /* __GNUC__ */
73 #else
74 #define TRACE(args) /* nothing */
75 #define LOG(args) /* nothing */
76 #endif /* PR_LOGGING */
77 
78 
79 //------------------------------------------------------------------------------
80 //
81 // Songbird string bundle constructors/destructors.
82 //
83 //------------------------------------------------------------------------------
84 
93 sbStringBundle::sbStringBundle(const char* aURI)
94 {
95  nsresult rv;
96 
97 #ifdef PR_LOGGING
98  if (!gStringBundleLog) {
99  gStringBundleLog = PR_NewLogModule("sbStringBundle");
100  }
101 #endif
102 
103  TRACE(("%s[%8.x] - %s", __FUNCTION__, this, aURI));
104 
105  // Get the Songbird string bundle service.
106  mStringBundleService = do_GetService(SB_STRINGBUNDLESERVICE_CONTRACTID, &rv);
107  NS_ENSURE_SUCCESS(rv, /* void */);
108 
109  // Load the string bundle. If no string bundle is specified, load the default
110  // one.
111  if (aURI) {
112  rv = LoadBundle(aURI);
113  NS_ENSURE_SUCCESS(rv, /* void */);
114  } else {
115  nsCOMPtr<nsIStringBundle> defaultBundle;
116  rv = mStringBundleService->GetBundle(getter_AddRefs(defaultBundle));
117  NS_ENSURE_SUCCESS(rv, /* void */);
118  rv = LoadBundle(defaultBundle);
119  NS_ENSURE_SUCCESS(rv, /* void */);
120  }
121 }
122 
123 
132 sbStringBundle::sbStringBundle(nsIStringBundle* aBundle)
133 {
134  nsresult rv;
135 
136 #ifdef PR_LOGGING
137  if (!gStringBundleLog) {
138  gStringBundleLog = PR_NewLogModule("sbStringBundle");
139  }
140 #endif
141 
142  TRACE(("%s[%8.x] - (existing bundle %.08x)", __FUNCTION__, this, aBundle));
143 
144  // Get the Songbird string bundle service.
145  mStringBundleService = do_GetService(SB_STRINGBUNDLESERVICE_CONTRACTID, &rv);
146  NS_ENSURE_SUCCESS(rv, /* void */);
147 
148  // Load the string bundle.
149  rv = LoadBundle(aBundle);
150  NS_ENSURE_SUCCESS(rv, /* void */);
151 }
152 
153 
154 //------------------------------------------------------------------------------
155 //
156 // Public Songbird string bundle services.
157 //
158 //------------------------------------------------------------------------------
159 
171 nsString
172 sbStringBundle::Get(const nsAString& aKey,
173  const nsAString& aDefault)
174 {
175  nsString stringValue;
176  nsresult rv;
177 
178  TRACE(("%s[%8.x] - %s (default %s)",
179  __FUNCTION__,
180  this,
181  NS_ConvertUTF16toUTF8(aKey).get(),
182  NS_ConvertUTF16toUTF8(aDefault).get()));
183 
184  // Get the default string value.
185  if (!aDefault.IsVoid())
186  stringValue = aDefault;
187  else
188  stringValue = aKey;
189 
190  // Get the string from the bundle list.
191  nsString bundleString;
192  PRInt32 bundleCount = mBundleList.Count();
193  for (PRInt32 i = 0; i < bundleCount; i++) {
194  rv = mBundleList[i]->GetStringFromName(aKey.BeginReading(),
195  getter_Copies(bundleString));
196  if (NS_SUCCEEDED(rv)) {
197  stringValue = bundleString;
198  break;
199  }
200  }
201 
202  // Apply string substitutions.
203  ApplySubstitutions(stringValue);
204 
205  return stringValue;
206 }
207 
208 nsString
209 sbStringBundle::Get(const char* aKey,
210  const char* aDefault)
211 {
212  TRACE(("%s[%8.x] - %s (default %s)", __FUNCTION__, this, aKey, aDefault));
213 
214  // Convert the key.
215  nsAutoString key;
216  if (aKey)
217  key = NS_ConvertUTF8toUTF16(aKey);
218  else
219  key = SBVoidString();
220 
221  // Convert the default string.
222  nsAutoString defaultString;
223  if (aDefault)
224  defaultString = NS_ConvertUTF8toUTF16(aDefault);
225  else
226  defaultString = SBVoidString();
227 
228  return Get(key, defaultString);
229 }
230 
231 
245 nsString
246 sbStringBundle::Format(const nsAString& aKey,
247  nsTArray<nsString>& aParams,
248  const nsAString& aDefault)
249 {
250  nsString stringValue;
251  nsresult rv;
252 
253  TRACE(("%s[%8.x] - %s (has params) (default %s)",
254  __FUNCTION__,
255  this,
256  NS_ConvertUTF16toUTF8(aKey).get(),
257  NS_ConvertUTF16toUTF8(aDefault).get()));
258 
259  // Get the default string value.
260  if (!aDefault.IsVoid())
261  stringValue = aDefault;
262  else
263  stringValue = aKey;
264 
265  // Convert format parameters.
266  nsTArray<const PRUnichar*> params;
267  PRUint32 paramCount = aParams.Length();
268  for (PRUint32 i = 0; i < paramCount; i++) {
269  params.AppendElement(aParams[i].get());
270  }
271 
272  // Get the string from the bundle list.
273  nsString bundleString;
274  PRInt32 bundleCount = mBundleList.Count();
275  for (PRInt32 i = 0; i < bundleCount; i++) {
276  rv = mBundleList[i]->FormatStringFromName(aKey.BeginReading(),
277  params.Elements(),
278  paramCount,
279  getter_Copies(bundleString));
280  if (NS_SUCCEEDED(rv)) {
281  stringValue = bundleString;
282  break;
283  }
284  }
285 
286  // Apply string substitutions.
287  ApplySubstitutions(stringValue);
288 
289  return stringValue;
290 }
291 
292 nsString
293 sbStringBundle::Format(const char* aKey,
294  nsTArray<nsString>& aParams,
295  const char* aDefault)
296 {
297  TRACE(("%s[%8.x] - %s (has params) (default %s)",
298  __FUNCTION__,
299  this,
300  aKey,
301  aDefault));
302 
303  // Convert the key.
304  nsAutoString key;
305  if (aKey)
306  key = NS_ConvertUTF8toUTF16(aKey);
307  else
308  key = SBVoidString();
309 
310  // Convert the default string.
311  nsAutoString defaultString;
312  if (aDefault)
313  defaultString = NS_ConvertUTF8toUTF16(aDefault);
314  else
315  defaultString = SBVoidString();
316 
317  return Format(key, aParams, defaultString);
318 }
319 
320 nsString
321 sbStringBundle::Format(const nsAString& aKey,
322  const nsAString& aParam,
323  const nsAString& aDefault)
324 {
325  TRACE(("%s[%8.x] - %s (param %s) (default %s)",
326  __FUNCTION__,
327  this,
328  NS_ConvertUTF16toUTF8(aKey).get(),
329  NS_ConvertUTF16toUTF8(aParam).get(),
330  NS_ConvertUTF16toUTF8(aDefault).get()));
331 
332  nsTArray<nsString> params(1);
333  params.AppendElement(aParam);
334  return Format(aKey, params, aDefault);
335 }
336 
337 nsString
338 sbStringBundle::Format(const char* aKey,
339  const nsAString& aParam,
340  const char* aDefault)
341 {
342  TRACE(("%s[%8.x] - %s (param %s) (default %s)",
343  __FUNCTION__,
344  this,
345  aKey,
346  NS_ConvertUTF16toUTF8(aParam).BeginReading(),
347  aDefault));
348 
349  nsTArray<nsString> params(1);
350  params.AppendElement(aParam);
351  return Format(aKey, params, aDefault);
352 }
353 
354 //------------------------------------------------------------------------------
355 //
356 // Internal Songbird string bundle services.
357 //
358 //------------------------------------------------------------------------------
359 
367 nsresult
368 sbStringBundle::LoadBundle(const char* aURI)
369 {
370  nsresult rv;
371 
372  TRACE(("%s[%8.x] - loading bundle %s", __FUNCTION__, this, aURI));
373 
374  // Create the string bundle.
375  nsCOMPtr<nsIStringBundle> bundle;
376  nsCOMPtr<nsIStringBundleService>
377  stringBundleService = do_QueryInterface(mStringBundleService, &rv);
378  NS_ENSURE_SUCCESS(rv, rv);
379  rv = stringBundleService->CreateBundle(aURI, getter_AddRefs(bundle));
380  NS_ENSURE_SUCCESS(rv, rv);
381 
382  // Load the string bundle.
383  rv = LoadBundle(bundle);
384  NS_ENSURE_SUCCESS(rv, rv);
385 
386  return NS_OK;
387 }
388 
389 
397 nsresult
398 sbStringBundle::LoadBundle(nsIStringBundle* aBundle)
399 {
400  nsresult rv;
401 
402  TRACE(("%s[%8.x] - existing bundle [%8.x]", __FUNCTION__, this, aBundle));
403 
404  // Add the string bundle to the list of string bundles.
405  mBundleList.AppendObject(aBundle);
406 
407  // Get the list of included string bundles.
408  nsString includeBundleListString;
409  rv = aBundle->GetStringFromName
410  (NS_LITERAL_STRING("include_bundle_list").get(),
411  getter_Copies(includeBundleListString));
412  if (NS_FAILED(rv))
413  return NS_OK;
414 
415  // Load each of the included string bundles.
416  nsTArray<nsString> includeBundleList;
417  nsString_Split(includeBundleListString,
418  NS_LITERAL_STRING(","),
419  includeBundleList);
420  PRUint32 includeBundleCount = includeBundleList.Length();
421  for (PRUint32 i = 0; i < includeBundleCount; i++) {
422  rv = LoadBundle(NS_ConvertUTF16toUTF8(includeBundleList[i]).get());
423  NS_ENSURE_SUCCESS(rv, rv);
424  }
425 
426  return NS_OK;
427 }
428 
429 
430 /*
431  * Apply and string bundle substitutions to the string specified by aString.
432  *
433  * \param aString String to which to apply substitutions.
434  */
435 
436 nsresult
437 sbStringBundle::ApplySubstitutions(nsAString& aString)
438 {
439  TRACE(("%s[%8.x] - applying %s",
440  __FUNCTION__,
441  this,
442  NS_ConvertUTF16toUTF8(aString).get()));
443  // Apply all string substitutions.
444  PRInt32 currentOffset = 0;
445  do {
446  // Get the starting and ending index of the next string substitution.
447  PRInt32 subStartIndex = aString.Find(NS_LITERAL_STRING("&"), currentOffset);
448  if (subStartIndex < 0)
449  break;
450  PRInt32 subEndIndex = aString.Find(NS_LITERAL_STRING(";"),
451  subStartIndex + 1);
452  if (subEndIndex < 0)
453  break;
454 
455  // Get the substitution string key.
456  PRInt32 subKeyStartIndex = subStartIndex + 1;
457  PRInt32 subKeyLength = subEndIndex - subKeyStartIndex;
458  nsAutoString subKey;
459  subKey.Assign(nsDependentSubstring(aString,
460  subKeyStartIndex,
461  subKeyLength));
462 
463  // Get the substitution string, special-casing "&amp;".
464  nsAutoString subString;
465  if (subKey.EqualsLiteral("amp")) {
466  subString = NS_LITERAL_STRING("&");
467  } else {
468  subString = Get(subKey, NS_LITERAL_STRING(""));
469  }
470 
471  // Apply the substitution.
472  PRInt32 subLength = subEndIndex - subStartIndex + 1;
473  aString.Replace(subStartIndex, subLength, subString);
474 
475  // Advance past the substitution.
476  currentOffset = subStartIndex + subString.Length();
477  } while (1);
478 
479  return NS_OK;
480 }
481 
return NS_OK
#define TRACE(args)
#define SB_STRINGBUNDLESERVICE_CONTRACTID
nsString Get(const nsAString &aKey, const nsAString &aDefault=SBVoidString())
nsString Format(const nsAString &aKey, nsTArray< nsString > &aParams, const nsAString &aDefault=SBVoidString())
var bundle
void nsString_Split(const nsAString &aString, const nsAString &aDelimiter, nsTArray< nsString > &aSubStringArray)
Songbird String Bundle Definitions.
_getSelectedPageStyle s i