~ubuntu-branches/ubuntu/precise/hime/precise

« back to all changes in this revision

Viewing changes to src/hime-tsa2d32.c

  • Committer: Package Import Robot
  • Author(s): Yao Wei (魏銘廷)
  • Date: 2012-01-14 00:24:08 UTC
  • Revision ID: package-import@ubuntu.com-20120114002408-e79gagbeg1rt8npv
Tags: upstream-0.9.9
Import upstream version 0.9.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1995-2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan
 
2
 *
 
3
 * This library is free software; you can redistribute it and/or
 
4
 * modify it under the terms of the GNU Lesser General Public
 
5
 * License as published by the Free Software Foundation; either
 
6
 * version 2.1 of the License, or (at your option) any later version.
 
7
 *
 
8
 * This library is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
 * Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public
 
14
 * License along with this library; if not, write to the Free Software
 
15
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
16
 */
 
17
 
 
18
#include <stdio.h>
 
19
#include <sys/types.h>
 
20
#include <string.h>
 
21
#include "hime.h"
 
22
#include "pho.h"
 
23
#include "tsin.h"
 
24
#include "gtab.h"
 
25
#include "gst.h"
 
26
 
 
27
void load_pin_juyin();
 
28
phokey_t pinyin2phokey(char *s);
 
29
 
 
30
static char *bf;
 
31
//static int bfN_a = 0;
 
32
static gboolean b_pinyin;
 
33
 
 
34
int *phidx, *sidx, phcount;
 
35
int bfsize, phidxsize;
 
36
u_char *sf;
 
37
gboolean is_gtab, gtabkey64;
 
38
int phsz, hash_shift;
 
39
int (*key_cmp)(char *a, char *b, char len);
 
40
 
 
41
int key_cmp16(char *a, char *b, char len)
 
42
{
 
43
  u_char i;
 
44
  for(i=0; i < len; i++) {
 
45
    phokey_t ka,kb;
 
46
    memcpy(&ka, a, 2);
 
47
    memcpy(&kb, b, 2);
 
48
    if (ka > kb) return 1;
 
49
    if (kb > ka) return -1;
 
50
    a+=2;
 
51
    b+=2;
 
52
  }
 
53
 
 
54
  return 0;
 
55
}
 
56
 
 
57
int key_cmp32(char *a, char *b, char len)
 
58
{
 
59
  u_char i;
 
60
  for(i=0; i < len; i++) {
 
61
    u_int ka,kb;
 
62
    memcpy(&ka, a, 4);
 
63
    memcpy(&kb, b, 4);
 
64
    if (ka > kb) return 1;
 
65
    if (kb > ka) return -1;
 
66
    a+=4;
 
67
    b+=4;
 
68
  }
 
69
  return 0;
 
70
}
 
71
 
 
72
int key_cmp64(char *a, char *b, char len)
 
73
{
 
74
  u_char i;
 
75
  for(i=0; i < len; i++) {
 
76
    u_int64_t ka,kb;
 
77
    memcpy(&ka, a, 8);
 
78
    memcpy(&kb, b, 8);
 
79
    if (ka > kb) return 1;
 
80
    if (kb > ka) return -1;
 
81
    a+=8;
 
82
    b+=8;
 
83
  }
 
84
  return 0;
 
85
}
 
86
 
 
87
static int qcmp(const void *a, const void *b)
 
88
{
 
89
  int idxa=*((int *)a);  char *pa = (char *)&bf[idxa];
 
90
  int idxb=*((int *)b);  char *pb = (char *)&bf[idxb];
 
91
  u_char lena,lenb, len;
 
92
  usecount_t usecounta, usecountb;
 
93
 
 
94
  lena=*(pa++); memcpy(&usecounta, pa, sizeof(usecount_t)); pa+= sizeof(usecount_t);
 
95
  char *ka = pa;
 
96
  pa += lena * phsz;
 
97
  lenb=*(pb++); memcpy(&usecountb, pb, sizeof(usecount_t)); pb+= sizeof(usecount_t);
 
98
  char *kb = pb;
 
99
  pb += lenb * phsz;
 
100
  len=Min(lena,lenb);
 
101
 
 
102
  int d = (*key_cmp)(ka, kb, len);
 
103
  if (d)
 
104
    return d;
 
105
 
 
106
  if (lena > lenb)
 
107
    return 1;
 
108
  if (lena < lenb)
 
109
    return -1;
 
110
 
 
111
  int tlena = utf8_tlen(pa, lena);
 
112
  int tlenb = utf8_tlen(pb, lenb);
 
113
 
 
114
  if (tlena > tlenb)
 
115
    return 1;
 
116
  if (tlena < tlenb)
 
117
    return -1;
 
118
 
 
119
  if ((d=memcmp(pa, pb, tlena)))
 
120
    return d;
 
121
 
 
122
  // large first, so large one will be kept after delete
 
123
  return usecountb - usecounta;
 
124
}
 
125
 
 
126
static int qcmp_eq(const void *a, const void *b)
 
127
{
 
128
  int idxa=*((int *)a);  char *pa = (char *)&bf[idxa];
 
129
  int idxb=*((int *)b);  char *pb = (char *)&bf[idxb];
 
130
  u_char lena,lenb, len;
 
131
 
 
132
  lena=*(pa++);  pa+= sizeof(usecount_t);
 
133
  char *ka = pa;
 
134
  pa += lena * phsz;
 
135
  lenb=*(pb++);  pb+= sizeof(usecount_t);
 
136
  char *kb = pb;
 
137
  pb += lenb * phsz;
 
138
  len=Min(lena,lenb);
 
139
 
 
140
  int d = (*key_cmp)(ka, kb, len);
 
141
  if (d)
 
142
    return d;
 
143
 
 
144
  if (lena > lenb)
 
145
    return 1;
 
146
  if (lena < lenb)
 
147
    return -1;
 
148
 
 
149
  int tlena = utf8_tlen(pa, lena);
 
150
  int tlenb = utf8_tlen(pb, lenb);
 
151
 
 
152
  if (tlena > tlenb)
 
153
    return 1;
 
154
  if (tlena < tlenb)
 
155
    return -1;
 
156
 
 
157
  return memcmp(pa, pb, tlena);
 
158
}
 
159
 
 
160
static int qcmp_usecount(const void *a, const void *b)
 
161
{
 
162
  int idxa=*((int *)a);  char *pa = (char *)&sf[idxa];
 
163
  int idxb=*((int *)b);  char *pb = (char *)&sf[idxb];
 
164
  u_char lena,lenb, len;
 
165
  usecount_t usecounta, usecountb;
 
166
 
 
167
  lena=*(pa++); memcpy(&usecounta, pa, sizeof(usecount_t)); pa+= sizeof(usecount_t);
 
168
  lenb=*(pb++); memcpy(&usecountb, pb, sizeof(usecount_t)); pb+= sizeof(usecount_t);
 
169
  len=Min(lena,lenb);
 
170
 
 
171
  int d = (*key_cmp)(pa, pb, len);
 
172
  if (d)
 
173
    return d;
 
174
  pa += len*phsz;
 
175
  pb += len*phsz;
 
176
 
 
177
  if (lena > lenb)
 
178
    return 1;
 
179
  if (lena < lenb)
 
180
    return -1;
 
181
 
 
182
  // now lena == lenb
 
183
  int tlena = utf8_tlen(pa, lena);
 
184
  int tlenb = utf8_tlen(pb, lenb);
 
185
 
 
186
  if (tlena > tlenb)
 
187
    return 1;
 
188
  if (tlena < tlenb)
 
189
    return -1;
 
190
 
 
191
  return usecountb - usecounta;
 
192
}
 
193
 
 
194
void send_hime_message(Display *dpy, char *s);
 
195
 
 
196
void init_TableDir();
 
197
 
 
198
int main(int argc, char **argv)
 
199
{
 
200
  FILE *fp,*fw;
 
201
  char s[1024];
 
202
  u_char chbuf[MAX_PHRASE_LEN * CH_SZ];
 
203
  u_short phbuf[80];
 
204
  u_int phbuf32[80];
 
205
  u_int64_t phbuf64[80];
 
206
  int i,j,idx,len, ofs;
 
207
  u_short kk;
 
208
  u_int64_t kk64;
 
209
  int hashidx[TSIN_HASH_N];
 
210
  u_char clen;
 
211
  int lineCnt=0;
 
212
  gboolean reload = getenv("HIME_NO_RELOAD")==NULL;
 
213
 
 
214
  if (reload) {
 
215
    dbg("need reload\n");
 
216
  } else {
 
217
    dbg("NO_GTK_INIT\n");
 
218
  }
 
219
 
 
220
  if (getenv("NO_GTK_INIT")==NULL)
 
221
    gtk_init(&argc, &argv);
 
222
 
 
223
  dbg("enter %s\n", argv[0]);
 
224
 
 
225
  if (argc < 2)
 
226
    p_err("must specify input file");
 
227
 
 
228
 
 
229
  init_TableDir();
 
230
 
 
231
  if ((fp=fopen(argv[1], "rb"))==NULL) {
 
232
     printf("Cannot open %s\n", argv[1]);
 
233
     exit(-1);
 
234
  }
 
235
 
 
236
  skip_utf8_sigature(fp);
 
237
  char *outfile;
 
238
  int fofs = ftell(fp);
 
239
  myfgets(s, sizeof(s), fp);
 
240
  if (strstr(s, "!!pinyin")) {
 
241
    b_pinyin = TRUE;
 
242
    printf("is pinyin\n");
 
243
    load_pin_juyin();
 
244
  } else
 
245
    fseek(fp, fofs, SEEK_SET);
 
246
 
 
247
  fofs = ftell(fp);
 
248
  int keybits=0, maxkey=0;
 
249
  char keymap[128];
 
250
  char kno[128];
 
251
  bzero(kno, sizeof(kno));
 
252
  myfgets(s, sizeof(s), fp);
 
253
  puts(s);
 
254
  if (strstr(s, TSIN_GTAB_KEY)) {
 
255
    is_gtab = TRUE;
 
256
    lineCnt++;
 
257
 
 
258
    if (argc < 3)
 
259
      p_err("useage %s input_file output_file", argv[0]);
 
260
 
 
261
    outfile = argv[2];
 
262
 
 
263
    len=strlen((char *)s);
 
264
    if (s[len-1]=='\n')
 
265
      s[--len]=0;
 
266
    char aa[128];
 
267
    keymap[0]=' ';
 
268
    sscanf(s, "%s %d %d %s", aa, &keybits, &maxkey, keymap+1);
 
269
    for(i=0; keymap[i]; i++)
 
270
      kno[keymap[i]]=i;
 
271
 
 
272
    if (maxkey * keybits > 32)
 
273
      gtabkey64 = TRUE;
 
274
  } else {
 
275
    if (argc==3)
 
276
      outfile = argv[2];
 
277
    else
 
278
      outfile = "tsin32";
 
279
 
 
280
    fseek(fp, fofs, SEEK_SET);
 
281
  }
 
282
 
 
283
 
 
284
 
 
285
  INMD inmd, *cur_inmd = &inmd;
 
286
 
 
287
  char *cphbuf;
 
288
  if (is_gtab) {
 
289
    cur_inmd->keybits = keybits;
 
290
    if (gtabkey64) {
 
291
      cphbuf = (char *)phbuf64;
 
292
      phsz = 8;
 
293
      key_cmp = key_cmp64;
 
294
      hash_shift = TSIN_HASH_SHIFT_64;
 
295
      cur_inmd->key64 = TRUE;
 
296
    } else {
 
297
      cphbuf = (char *)phbuf32;
 
298
      phsz = 4;
 
299
      hash_shift = TSIN_HASH_SHIFT_32;
 
300
      key_cmp = key_cmp32;
 
301
      cur_inmd->key64 = FALSE;
 
302
    }
 
303
    cur_inmd->last_k_bitn = (((cur_inmd->key64 ? 64:32) / cur_inmd->keybits) - 1) * cur_inmd->keybits;
 
304
    dbg("cur_inmd->last_k_bitn %d\n", cur_inmd->last_k_bitn);
 
305
  } else {
 
306
      cphbuf = (char *)phbuf;
 
307
      phsz = 2;
 
308
      key_cmp = key_cmp16;
 
309
      hash_shift = TSIN_HASH_SHIFT;
 
310
  }
 
311
 
 
312
  dbg("phsz: %d\n", phsz);
 
313
 
 
314
  phcount=ofs=0;
 
315
  while (!feof(fp)) {
 
316
    usecount_t usecount=0;
 
317
 
 
318
    lineCnt++;
 
319
 
 
320
    myfgets((char *)s,sizeof(s),fp);
 
321
    len=strlen((char *)s);
 
322
    if (s[0]=='#')
 
323
      continue;
 
324
 
 
325
    if (strstr(s, TSIN_GTAB_KEY))
 
326
      continue;
 
327
 
 
328
    if (s[len-1]=='\n')
 
329
      s[--len]=0;
 
330
 
 
331
    if (len==0)
 
332
      continue;
 
333
 
 
334
    i=0;
 
335
    int chbufN=0;
 
336
    int charN = 0;
 
337
    while (s[i]!=' ' && i<len) {
 
338
      int len = utf8_sz((char *)&s[i]);
 
339
 
 
340
      memcpy(&chbuf[chbufN], &s[i], len);
 
341
 
 
342
      i+=len;
 
343
      chbufN+=len;
 
344
      charN++;
 
345
    }
 
346
 
 
347
    while ((i < len && s[i]==' ') || s[i]=='\t')
 
348
      i++;
 
349
 
 
350
    int phbufN=0;
 
351
    while (i<len && phbufN < charN && s[i]!=' ') {
 
352
      if (is_gtab) {
 
353
        kk64=0;
 
354
        int idx=0;
 
355
        while (s[i]!=' ' && i<len) {
 
356
          int k = kno[s[i]];
 
357
          kk64|=(u_int64_t)k << ( LAST_K_bitN - idx*keybits);
 
358
          i++;
 
359
          idx++;
 
360
        }
 
361
 
 
362
        if (phsz==8)
 
363
          phbuf64[phbufN++]=kk64;
 
364
        else
 
365
          phbuf32[phbufN++]=(u_int)kk64;
 
366
      } else {
 
367
        kk=0;
 
368
        if (b_pinyin) {
 
369
          kk = pinyin2phokey(s+i);
 
370
          while (s[i]!=' ' && i<len)
 
371
            i++;
 
372
        } else {
 
373
          while (s[i]!=' ' && i<len) {
 
374
            if (kk==(BACK_QUOTE_NO << 9))
 
375
              kk|=s[i];
 
376
            else
 
377
              kk |= lookup((u_char *)&s[i]);
 
378
 
 
379
            i+=utf8_sz((char *)&s[i]);
 
380
          }
 
381
        }
 
382
 
 
383
        phbuf[phbufN++]=kk;
 
384
      }
 
385
 
 
386
      i++;
 
387
    }
 
388
 
 
389
    if (phbufN!=charN) {
 
390
      p_err("%s   Line %d problem in phbufN!=chbufN %d != %d\n", s, lineCnt, phbufN, chbufN);
 
391
    }
 
392
 
 
393
    clen=phbufN;
 
394
 
 
395
    while (i<len && s[i]==' ')
 
396
      i++;
 
397
 
 
398
    if (i==len)
 
399
      usecount = 0;
 
400
    else
 
401
      usecount = atoi((char *)&s[i]);
 
402
 
 
403
    /*      printf("len:%d\n", clen); */
 
404
 
 
405
    if (phcount >= phidxsize) {
 
406
      phidxsize+=1024;
 
407
      if (!(phidx=(int *)realloc(phidx,phidxsize*4))) {
 
408
        puts("realloc err");
 
409
        exit(1);
 
410
      }
 
411
    }
 
412
 
 
413
    phidx[phcount++]=ofs;
 
414
 
 
415
    int new_bfN = ofs + 1 + sizeof(usecount_t)+ phsz * clen + chbufN;
 
416
 
 
417
    if (bfsize < new_bfN) {
 
418
      bfsize = new_bfN + 1024*1024;
 
419
      bf = (char *)realloc(bf, bfsize);
 
420
    }
 
421
 
 
422
    memcpy(&bf[ofs++],&clen,1);
 
423
    memcpy(&bf[ofs],&usecount, sizeof(usecount_t)); ofs+=sizeof(usecount_t);
 
424
 
 
425
    memcpy(&bf[ofs], cphbuf, clen * phsz);
 
426
    ofs+=clen * phsz;
 
427
 
 
428
    memcpy(&bf[ofs], chbuf, chbufN);
 
429
    ofs+=chbufN;
 
430
  }
 
431
  fclose(fp);
 
432
 
 
433
  /* dumpbf(bf,phidx); */
 
434
 
 
435
  puts("Sorting ....");
 
436
 
 
437
  qsort(phidx,phcount, sizeof(phidx[0]),qcmp);
 
438
 
 
439
  if (!(sf=(u_char *)malloc(bfsize))) {
 
440
    puts("malloc err");
 
441
    exit(1);
 
442
  }
 
443
 
 
444
  if (!(sidx=(int *)malloc(phidxsize*sizeof(int)))) {
 
445
    puts("malloc err");
 
446
    exit(1);
 
447
  }
 
448
 
 
449
 
 
450
  // delete duplicate
 
451
  ofs=0;
 
452
  j=0;
 
453
  for(i=0;i<phcount;i++) {
 
454
    idx = phidx[i];
 
455
    sidx[j]=ofs;
 
456
    len=bf[idx];
 
457
    int tlen = utf8_tlen(&bf[idx + 1 + sizeof(usecount_t) + phsz*len], len);
 
458
    clen= phsz*len + tlen + 1 + sizeof(usecount_t);
 
459
 
 
460
    if (i && !qcmp_eq(&phidx[i-1], &phidx[i]))
 
461
      continue;
 
462
 
 
463
    memcpy(&sf[ofs], &bf[idx], clen);
 
464
    j++;
 
465
    ofs+=clen;
 
466
  }
 
467
 
 
468
  phcount=j;
 
469
#if 1
 
470
  puts("Sorting by usecount ....");
 
471
  qsort(sidx, phcount, 4, qcmp_usecount);
 
472
#endif
 
473
 
 
474
  for(i=0;i<256;i++)
 
475
    hashidx[i]=-1;
 
476
 
 
477
  for(i=0;i<phcount;i++) {
 
478
    idx=sidx[i];
 
479
    idx+= 1 + sizeof(usecount_t);
 
480
    int v;
 
481
 
 
482
    if (phsz==2) {
 
483
      phokey_t kk;
 
484
      memcpy(&kk, &sf[idx], phsz);
 
485
      v = kk >> TSIN_HASH_SHIFT;
 
486
    } else if (phsz==4) {
 
487
      u_int kk32;
 
488
      memcpy(&kk32, &sf[idx], phsz);
 
489
      v = kk32 >> TSIN_HASH_SHIFT_32;
 
490
    }
 
491
    else if (phsz==8) {
 
492
      u_int64_t kk64;
 
493
      memcpy(&kk64, &sf[idx], phsz);
 
494
      v = kk64 >> TSIN_HASH_SHIFT_64;
 
495
    }
 
496
 
 
497
    if (v >= TSIN_HASH_N)
 
498
      p_err("error found %d", v);
 
499
 
 
500
    if (hashidx[v] < 0) {
 
501
      hashidx[v]=i;
 
502
    }
 
503
  }
 
504
 
 
505
  if (hashidx[0]==-1)
 
506
    hashidx[0]=0;
 
507
 
 
508
  hashidx[TSIN_HASH_N-1]=phcount;
 
509
  for(i=TSIN_HASH_N-2;i>=0;i--) {
 
510
    if (hashidx[i]==-1)
 
511
      hashidx[i]=hashidx[i+1];
 
512
  }
 
513
 
 
514
  for(i=1; i< TSIN_HASH_N; i++) {
 
515
    if (hashidx[i]==-1)
 
516
      hashidx[i]=hashidx[i-1];
 
517
  }
 
518
 
 
519
  printf("Writing data %s %d\n", outfile, ofs);
 
520
  if ((fw=fopen(outfile,"wb"))==NULL) {
 
521
    p_err("create err %s", outfile);
 
522
  }
 
523
 
 
524
  if (is_gtab) {
 
525
    TSIN_GTAB_HEAD head;
 
526
    bzero(&head, sizeof(head));
 
527
    strcpy(head.signature, TSIN_GTAB_KEY);
 
528
    head.keybits = keybits;
 
529
    head.maxkey = maxkey;
 
530
    strcpy(head.keymap, keymap);
 
531
    fwrite(&head, sizeof(head), 1, fw);
 
532
  }
 
533
 
 
534
  fwrite(sf,1,ofs,fw);
 
535
  fclose(fw);
 
536
 
 
537
  char outfileidx[512];
 
538
  strcat(strcpy(outfileidx, outfile), ".idx");
 
539
 
 
540
  dbg("Writing data %s\n", outfileidx);
 
541
  if ((fw=fopen(outfileidx,"wb"))==NULL) {
 
542
    p_err("cannot create %s", outfileidx);
 
543
  }
 
544
 
 
545
  fwrite(&phcount,4,1,fw);
 
546
  fwrite(hashidx,1,sizeof(hashidx),fw);
 
547
  fwrite(sidx,4,phcount,fw);
 
548
  printf("%d phrases\n",phcount);
 
549
 
 
550
  fclose(fw);
 
551
  free(sf);
 
552
  free(bf);
 
553
 
 
554
 
 
555
  if (reload) {
 
556
    printf("reload....\n");
 
557
    send_hime_message(GDK_DISPLAY(), RELOAD_TSIN_DB);
 
558
  }
 
559
 
 
560
  exit(0);
 
561
}