libintl.cpp
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 #include <config.h>
00051 
00052 #include <qglobal.h>
00053 
00054 #include <stdlib.h>
00055 
00056 #if defined HAVE_STRING_H
00057 # include <string.h>
00058 #else
00059 # include <strings.h>
00060 #endif
00061 
00062 #include <sys/types.h>
00063 #include <fcntl.h>
00064 #include <sys/stat.h>
00065 
00066 #if defined HAVE_UNISTD_H
00067 # include <unistd.h>
00068 #endif
00069 
00070 #if (defined HAVE_MMAP && defined HAVE_MUNMAP)
00071 # include <sys/mman.h>
00072 #endif
00073 
00074 #ifndef W
00075 # define W(flag, data) ((flag) ? SWAP (data) : (data))
00076 #endif
00077 
00078 typedef Q_UINT32 nls_uint32;
00079 
00080 struct loaded_domain
00081 {
00082   const char *data;
00083 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00084   int use_mmap;
00085   size_t mmap_size;
00086 #endif
00087   int must_swap;
00088   nls_uint32 nstrings;
00089   struct string_desc *orig_tab;
00090   struct string_desc *trans_tab;
00091   nls_uint32 hash_size;
00092   nls_uint32 *hash_tab;
00093 };
00094 
00095 struct kde_loaded_l10nfile
00096 {
00097   const char *filename;
00098   int decided;
00099 
00100   const void *data;
00101 
00102   kde_loaded_l10nfile() : filename(0), decided(0), data(0) {}
00103 };
00104 
00105 void k_nl_load_domain(struct kde_loaded_l10nfile *__domain);
00106 
00107 static inline nls_uint32
00108 SWAP (nls_uint32  i)
00109 {
00110   return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
00111 }
00112 
00113 
00114 
00115 
00116 #define _MAGIC 0x950412de
00117 #define _MAGIC_SWAPPED 0xde120495
00118 
00119 
00120 #define MO_REVISION_NUMBER 0
00121 
00122 
00123 
00124 
00125 
00126 static inline unsigned long hash_string  (const char *__str_param);
00127 
00128 
00129 
00130 
00131 struct mo_file_header
00132 {
00133   
00134   nls_uint32 magic;
00135   
00136   nls_uint32 revision;
00137   
00138   nls_uint32 nstrings;
00139   
00140   nls_uint32 orig_tab_offset;
00141   
00142   nls_uint32 trans_tab_offset;
00143   
00144   nls_uint32 hash_tab_size;
00145   
00146   nls_uint32 hash_tab_offset;
00147 };
00148 
00149 struct string_desc
00150 {
00151   
00152   nls_uint32 length;
00153   
00154   nls_uint32 offset;
00155 };
00156 
00157 
00158 char *k_nl_find_msg  (struct kde_loaded_l10nfile *domain_file,
00159             const char *msgid);
00160 
00161 char *
00162 k_nl_find_msg (struct kde_loaded_l10nfile *domain_file, const char *msgid)
00163 {
00164   size_t top, act, bottom;
00165   struct loaded_domain *domain;
00166 
00167   if (domain_file->decided == 0)
00168     k_nl_load_domain (domain_file);
00169 
00170   if (domain_file->data == NULL)
00171     return NULL;
00172 
00173   domain = (struct loaded_domain *) domain_file->data;
00174 
00175   
00176   if (domain->hash_size > 2 && domain->hash_tab != NULL)
00177     {
00178       
00179       nls_uint32 len = strlen (msgid);
00180       nls_uint32 hash_val = hash_string (msgid);
00181       nls_uint32 idx = hash_val % domain->hash_size;
00182       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
00183       nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
00184 
00185       if (nstr == 0)
00186     
00187     return NULL;
00188 
00189       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
00190       && strcmp (msgid,
00191              domain->data + W (domain->must_swap,
00192                        domain->orig_tab[nstr - 1].offset)) == 0)
00193     return (char *) domain->data + W (domain->must_swap,
00194                       domain->trans_tab[nstr - 1].offset);
00195 
00196       while (1)
00197     {
00198       if (idx >= domain->hash_size - incr)
00199         idx -= domain->hash_size - incr;
00200       else
00201         idx += incr;
00202 
00203       nstr = W (domain->must_swap, domain->hash_tab[idx]);
00204       if (nstr == 0)
00205         
00206         return NULL;
00207 
00208       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
00209           && strcmp (msgid,
00210              domain->data + W (domain->must_swap,
00211                        domain->orig_tab[nstr - 1].offset))
00212              == 0)
00213         return (char *) domain->data
00214           + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
00215     }
00216       
00217     }
00218 
00219   
00220 
00221   bottom = 0;
00222   top = domain->nstrings;
00223   act = top;
00224   while (bottom < top)
00225     {
00226       int cmp_val;
00227 
00228       act = (bottom + top) / 2;
00229       cmp_val = strcmp (msgid, domain->data
00230                    + W (domain->must_swap,
00231                     domain->orig_tab[act].offset));
00232       if (cmp_val < 0)
00233     top = act;
00234       else if (cmp_val > 0)
00235     bottom = act + 1;
00236       else
00237     break;
00238     }
00239 
00240   
00241   return bottom >= top ? NULL : (char *) domain->data
00242                                 + W (domain->must_swap,
00243                      domain->trans_tab[act].offset);
00244 }
00245 
00246 
00247 
00248 #define HASHWORDBITS 32
00249 
00250 static inline unsigned long
00251 hash_string (const char *str_param)
00252 {
00253   unsigned long int hval, g;
00254   const char *str = str_param;
00255 
00256   
00257   hval = 0;
00258   while (*str != '\0')
00259     {
00260       hval <<= 4;
00261       hval += (unsigned long) *str++;
00262       g = hval & ((unsigned long) 0xf << (HASHWORDBITS - 4));
00263       if (g != 0)
00264     {
00265       hval ^= g >> (HASHWORDBITS - 8);
00266       hval ^= g;
00267     }
00268     }
00269   return hval;
00270 }
00271 
00272 
00273 
00274 void
00275 k_nl_load_domain (struct kde_loaded_l10nfile *domain_file)
00276 {
00277   int fd;
00278   struct stat st;
00279   struct mo_file_header *data = (struct mo_file_header *) -1;
00280 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00281   int use_mmap = 0;
00282 #endif
00283   struct loaded_domain *domain;
00284 
00285   domain_file->decided = 1;
00286   domain_file->data = NULL;
00287 
00288   
00289 
00290 
00291 
00292   if (domain_file->filename == NULL)
00293     return;
00294 
00295   
00296   fd = open (domain_file->filename, O_RDONLY);
00297   if (fd == -1)
00298     return;
00299 
00300   
00301   if (fstat (fd, &st) != 0
00302       || st.st_size < (off_t) sizeof (struct mo_file_header))
00303     {
00304       
00305       close (fd);
00306       return;
00307     }
00308 
00309 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00310   
00311 
00312   data = (struct mo_file_header *) mmap (NULL, st.st_size, PROT_READ,
00313                      MAP_PRIVATE, fd, 0);
00314 
00315   if (data != (struct mo_file_header *) -1)
00316     {
00317       
00318       close (fd);
00319       use_mmap = 1;
00320     }
00321 #endif
00322 
00323   
00324 
00325   if (data == (struct mo_file_header *) -1)
00326     {
00327       off_t to_read;
00328       char *read_ptr;
00329 
00330       data = (struct mo_file_header *) malloc (st.st_size);
00331       if (data == NULL)
00332     return;
00333 
00334       to_read = st.st_size;
00335       read_ptr = (char *) data;
00336       do
00337     {
00338       long int nb = (long int) read (fd, read_ptr, to_read);
00339       if (nb == -1)
00340         {
00341           close (fd);
00342           return;
00343         }
00344 
00345       read_ptr += nb;
00346       to_read -= nb;
00347     }
00348       while (to_read > 0);
00349 
00350       close (fd);
00351     }
00352 
00353   
00354 
00355   if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
00356     {
00357       
00358 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00359       if (use_mmap)
00360     munmap ((char *) data, st.st_size);
00361       else
00362 #endif
00363     free (data);
00364       return;
00365     }
00366 
00367   domain_file->data
00368     = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
00369   if (domain_file->data == NULL)
00370     return;
00371 
00372   domain = (struct loaded_domain *) domain_file->data;
00373   domain->data = (char *) data;
00374 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00375   domain->use_mmap = use_mmap;
00376   domain->mmap_size = st.st_size;
00377 #endif
00378   domain->must_swap = data->magic != _MAGIC;
00379 
00380   
00381   switch (W (domain->must_swap, data->revision))
00382     {
00383     case 0:
00384       domain->nstrings = W (domain->must_swap, data->nstrings);
00385       domain->orig_tab = (struct string_desc *)
00386     ((char *) data + W (domain->must_swap, data->orig_tab_offset));
00387       domain->trans_tab = (struct string_desc *)
00388     ((char *) data + W (domain->must_swap, data->trans_tab_offset));
00389       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
00390       domain->hash_tab = (nls_uint32 *)
00391     ((char *) data + W (domain->must_swap, data->hash_tab_offset));
00392       break;
00393     default:
00394       
00395 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00396       if (use_mmap)
00397     munmap ((char *) data, st.st_size);
00398       else
00399 #endif
00400     free (data);
00401       free (domain);
00402       domain_file->data = NULL;
00403       return;
00404     }
00405 }
00406 
00407 void
00408 k_nl_unload_domain (struct loaded_domain *domain)
00409 {
00410 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
00411   if (domain->use_mmap)
00412     munmap ((caddr_t) domain->data, domain->mmap_size);
00413   else
00414 # endif
00415     free ((void *) domain->data);
00416 
00417   free (domain);
00418 }
 
This file is part of the documentation for kdecore Library Version 3.2.0.