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 loaded_l10nfile
00096 {
00097 const char *filename;
00098 int decided;
00099
00100 const void *data;
00101
00102 loaded_l10nfile() : filename(0), decided(0), data(0) {}
00103 };
00104
00105 void k_nl_load_domain(struct 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 loaded_l10nfile *domain_file,
00159 const char *msgid);
00160
00161 char *
00162 k_nl_find_msg (struct 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 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 kdelibs Version 3.1.0.