(file) Return to intlstr.c CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 /*
  2              **==============================================================================
  3              **
  4              ** Open Management Infrastructure (OMI)
  5              **
  6              ** Copyright (c) Microsoft Corporation
  7              **
  8 krisbash 1.2 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
  9              ** use this file except in compliance with the License. You may obtain a copy
 10              ** of the License at
 11              **
 12              **     http://www.apache.org/licenses/LICENSE-2.0
 13 krisbash 1.1 **
 14              ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15 krisbash 1.2 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
 16              ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
 17              ** MERCHANTABLITY OR NON-INFRINGEMENT.
 18 krisbash 1.1 **
 19 krisbash 1.2 ** See the Apache 2 License for the specific language governing permissions
 20 krisbash 1.1 ** and limitations under the License.
 21              **
 22              **==============================================================================
 23              */
 24              
 25              #include "intlstr.h"
 26              
 27              #include <assert.h>
 28 krisbash 1.2 #include <pal/intsafe.h>
 29 krisbash 1.1 
 30              #if defined(_MSC_VER)
 31              
 32                  #include <windows.h>
 33              
 34                  _Use_decl_annotations_
 35                  const PAL_Char* _Intlstr_GetString_LoadString(HINSTANCE hInstance, UINT uID)
 36                  {
 37                      int err;
 38                      LPTSTR lpBuffer;
 39              
 40                      err = LoadString(hInstance, uID, (LPTSTR)&lpBuffer, 0);
 41                      if (err == 0)
 42                      {
 43                          /* TODO/FIXME - OI diagnostics */
 44                          return NULL;
 45                      }
 46              
 47                      return lpBuffer;
 48                  }
 49              
 50 krisbash 1.1     _Use_decl_annotations_
 51                  PAL_Char* _Intlstr_FormatString_FormatMessage(HINSTANCE hInstance, UINT uID, ...)
 52                  {
 53                      DWORD result;
 54                      int err;
 55                      LPTSTR lpTemplate;
 56                      LPTSTR lpFormattedString;
 57 krisbash 1.2         va_list ap;
 58 krisbash 1.1 
 59                      err = LoadString(hInstance, uID, (LPTSTR)&lpTemplate, 0);
 60                      if (err == 0)
 61                      {
 62                          /* TODO/FIXME - OI diagnostics */
 63                          return NULL;
 64                      }
 65              
 66 krisbash 1.2         va_start(ap, uID);
 67 krisbash 1.1         result = FormatMessage(
 68                          /* TODO/FIXME - FORMAT_MESSAGE_FROM_HMODULE can in theory help avoid the LoadString above, but I couldn't get it to work... */
 69 krisbash 1.2             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
 70                          lpTemplate,
 71 krisbash 1.1             0, /* dwMessageId;  ignored when FORMAT_MESSAGE_FROM_STRING is used */
 72                          0, /* dwLanguageId; ignored when FORMAT_MESSAGE_FROM_STRING is used */
 73                          (LPTSTR)&lpFormattedString,
 74                          0, /* nSize - maximum size of buffer to allocate;  0 means no limit */
 75                          &ap);
 76 krisbash 1.2         va_end(ap);
 77 krisbash 1.1         if (result == 0)
 78                      {
 79                          /* TODO/FIXME - OI diagnostics */
 80                          return NULL;
 81                      }
 82              
 83                      return lpFormattedString;
 84                  }
 85              
 86              #else /* !defined(_MSC_VER) */
 87              
 88                  #include <pal/format.h>
 89                  #include <pal/strings.h>
 90              
 91                  #if defined(CONFIG_ENABLE_GETTEXT)
 92              
 93                  #include <libintl.h>
 94                  #include <stdarg.h>
 95                  #include <pal/hashmap.h>
 96                  #include <pal/once.h>
 97                  #include <pal/lock.h>
 98 krisbash 1.1 
 99                      #if defined(CONFIG_ENABLE_WCHAR)
100              
101                          typedef struct _IntlstrBucket {
102                              HashBucket      bucket;
103                              int id;
104                              const char* domain_name;
105                              PAL_Char text[1];
106                          } IntlstrBucket;
107              
108                          static size_t Intlstr_HashMapHashProc(const HashBucket* untypedBucket)
109                          {
110                              IntlstrBucket* bucket = (IntlstrBucket*)untypedBucket;
111                              return (size_t)bucket->id ^ HashMap_HashProc_AnsiString(bucket->domain_name);
112                          }
113              
114                          static int Intlstr_HashMapEqualProc(_In_ const HashBucket* untypedBucket1, _In_ const HashBucket* untypedBucket2)
115                          {
116                              IntlstrBucket* bucket1 = (IntlstrBucket*)untypedBucket1;
117                              IntlstrBucket* bucket2 = (IntlstrBucket*)untypedBucket2;
118                              return (bucket1->id == bucket2->id) &&
119 krisbash 1.1                     (0 == strcmp(bucket1->domain_name, bucket2->domain_name));
120                          }
121              
122                          static void Intlstr_HashMapReleaseProc(_In_ HashBucket* untypedBucket)
123                          {
124                              PAL_UNUSED(untypedBucket);
125                          }
126              
127                          static Once g_intlStr_once = ONCE_INITIALIZER;
128                          static HashMap g_intlStr_hashmap;
129                          static ReadWriteLock g_intlStr_lock;
130              
131                          static void ATEXIT_API _Intlstr_OnceCleanup(void)
132                          {
133                              HashMap_Destroy(&g_intlStr_hashmap);
134                          }
135              
136                          _Success_(return == 0) int _Intlstr_OnceInit(void* data, _Outptr_result_maybenull_ void** value)
137                          {
138                              int result = 0;
139              
140 krisbash 1.1                 *value = NULL;
141              
142                              ReadWriteLock_Init(&g_intlStr_lock);
143              
144                              result = HashMap_Init(
145 krisbash 1.2                     &g_intlStr_hashmap,
146 krisbash 1.1                     32, /* initial number of buckets */
147                                  Intlstr_HashMapHashProc,
148                                  Intlstr_HashMapEqualProc,
149                                  Intlstr_HashMapReleaseProc);
150              
151                              if (result == 0)
152                              {
153                                  result = PAL_Atexit(_Intlstr_OnceCleanup);
154                              }
155              
156                              return result;
157                          }
158              
159                      #endif /* ?defined(CONFIG_ENABLE_WCHAR) */
160              
161                      _Use_decl_annotations_
162                      const PAL_Char* _Intlstr_GetString_GetText(const char* domain_name, int id, const char* msgid)
163                      {
164                      #if defined(CONFIG_ENABLE_WCHAR)
165                          IntlstrBucket* bucket;
166              
167 krisbash 1.1             if (0 != Once_Invoke(&g_intlStr_once, _Intlstr_OnceInit, NULL))
168                          {
169                              /* TODO/FIXME - OI diagnostics */
170                              return NULL;
171                          }
172              
173                          {
174                              IntlstrBucket referenceBucket;
175                              referenceBucket.id = id;
176                              referenceBucket.domain_name = domain_name;
177                              ReadWriteLock_AcquireRead(&g_intlStr_lock);
178                              bucket = (IntlstrBucket*) HashMap_Find(&g_intlStr_hashmap, (HashBucket*) &referenceBucket);
179                              ReadWriteLock_ReleaseRead(&g_intlStr_lock);
180                          }
181              
182                          if (bucket == NULL)
183                          {
184                              size_t wcharCount;
185                              size_t copiedCount;
186                              int insertResult;
187              
188 krisbash 1.1                 char* localizedString = dgettext(domain_name, msgid);
189                              if (localizedString == NULL)
190                              {
191                                  /* TODO/FIXME - OI diagnostics */
192                                  return NULL;
193                              }
194              
195                              wcharCount = mbstowcs(NULL, localizedString, 0);
196                              if (wcharCount == ((size_t)-1))
197                              {
198                                  /* TODO/FIXME - OI diagnostics */
199                                  return NULL;
200                              }
201                              if ((((size_t)(-1)) - sizeof(IntlstrBucket) / 2) < wcharCount)
202                              {
203                                  /* TODO/FIXME - OI diagnostics */
204                                  return NULL;
205                              }
206              
207 krisbash 1.2                 size_t allocSize = 0;
208                              if (SizeTMult(sizeof(wchar_t), wcharCount, &allocSize) != S_OK ||
209                                  SizeTAdd(allocSize, sizeof(IntlstrBucket), &allocSize != S_OK))
210                              {
211                                  return NULL;
212                              }
213              
214                              bucket = (IntlstrBucket*) PAL_Malloc(allocSize);
215 krisbash 1.1                 if (!bucket)
216                              {
217                                  /* TODO/FIXME - OI diagnostics */
218                                  return NULL;
219                              }
220                              bucket->id = id;
221                              bucket->domain_name = domain_name;
222              
223                              copiedCount = mbstowcs(bucket->text, localizedString, wcharCount + 1);
224                              assert(copiedCount == wcharCount);
225              
226                              ReadWriteLock_AcquireWrite(&g_intlStr_lock);
227                              insertResult = HashMap_Insert(&g_intlStr_hashmap, (HashBucket*) bucket);
228                              if (insertResult == 1) /* already exists? => use the old one / discard the new one */
229                              {
230                                  IntlstrBucket* oldBucket = (IntlstrBucket*) HashMap_Find(&g_intlStr_hashmap, (HashBucket*) bucket);
231                                  assert(oldBucket != NULL);
232                                  PAL_Free(bucket);
233                                  bucket = oldBucket;
234                              }
235                              ReadWriteLock_ReleaseWrite(&g_intlStr_lock);
236 krisbash 1.1             }
237              
238                          return bucket->text;
239                      #else /* !defined(CONFIG_ENABLE_WCHAR) */
240                          char* localizedString;
241 krisbash 1.2 
242 krisbash 1.1             PAL_UNUSED(id);
243              
244                          localizedString = dgettext(domain_name, msgid);
245                          if (localizedString == NULL)
246                          {
247                              /* TODO/FIXME - OI diagnostics */
248                              return NULL;
249                          }
250              
251                          return localizedString;
252                      #endif /* ?defined(CONFIG_ENABLE_WCHAR) */
253                      }
254              
255                      PAL_Char* _Intlstr_FormatString_gettext_and_snprintf(const char* domain_name, int id, const char* msgid, ...)
256                      {
257                          PAL_Char* templateString = NULL;
258                          PAL_Char* resultString = NULL;
259 krisbash 1.2             va_list ap;
260 krisbash 1.1 
261 krisbash 1.2             va_start(ap, msgid);
262 krisbash 1.1 
263                          templateString = _Intlstr_GetString_GetText(domain_name, id, msgid);
264                          if (!templateString)
265                          {
266                              /* TODO/FIXME - OI diagnostics */
267                              goto CleanUp;
268                          }
269              
270                          resultString = Vstprintf_StrDup(templateString, ap);
271                          if (!resultString)
272                          {
273                              /* TODO/FIXME - OI diagnostics */
274                              goto CleanUp;
275                          }
276              
277                      CleanUp:
278 krisbash 1.2             va_end(ap);
279 krisbash 1.1             return resultString;
280                      }
281              
282                  #endif /* ?defined(CONFIG_ENABLE_GETTEXT) */
283              
284              #endif /* ?defined(_MSC_VER) */

ViewCVS 0.9.2