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 }