forked from zhujian198/unispim
-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathwordlib.c
2574 lines (2108 loc) · 116 KB
/
wordlib.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* 词库处理函数组。
* 系统中的词库可能有多个,因此需要统一管理。
* 函数列表:
* LoadWordLib 装载词库文件到共享区
* SaveWordLib 保存词库文件
* CloseWordLib 关闭词库文件
* BackupWordLib 备份词库
* MergeWordLib 合并词库
* AddWord 增加一条词汇
* DelWord 删除一条词汇
* SetFuzzyMode 设定模糊模式
* GetWordCANDIDATE 获得词的候选
* GetAllItems 获得词库中的全部词条
* GetSystemItems 获得全部系统词汇条目
* GetUserItems 获得全部用户自定义条目
*/
/* 词库结构说明
* 采用页表方式进行内存的申请,每次扩展词库都以一个页为单位。
* 页:1024字节。
*
* 词库结构:
* 1、词库信息
* 2、词库索引表
* 3、词库页内容
*/
#include <tchar.h>
#include <assert.h>
#include <io.h>
#include <fcntl.h>
#include <wordlib.h>
#include <utility.h>
#include <ci.h>
#include <zi.h>
#include <config.h>
#include <win32/pim_ime.h>
#include <share_segment.h>
//词库指针数组,等于0的时候,为该ID没有被分配。
static WORDLIB *wordlib_buffer[MAX_WORDLIBS * 2] = { 0, };
//词库文件是否可写
static int wordlib_can_write[MAX_WORDLIBS + MAX_WORDLIBS] = { 0 };
//上面的变量应该为每一个进程分配一个,不能够使用全局的,否则会出毛病(在IE7)中。
//#pragma data_seg(HYPIM_SHARED_SEGMENT)
//
////用户词库标识
//int user_wordlib_id = -1;
//int user_wl_modified = 0; //是否改变
//
////是否可以保存用户词库(向用户词库Import词汇可能被覆盖)
//int can_save_user_wordlib = 1;
//
////词库的名称
//static TCHAR wordlib_name[MAX_WORDLIBS * 2][WORDLIB_FILE_NAME_LENGTH] = { 0 };
//
////词库长度数组
//static int wordlib_length[MAX_WORDLIBS * 2] = { -1 };
//
////词库是否已经被删除
//static int wordlib_deleted[MAX_WORDLIBS * 2] = { 0 };
//
////共享内存的标识
//static TCHAR wordlib_shared_name[MAX_WORDLIBS * 2][0x20] =
//{
// TEXT("HYPIM_WORDLIB_SHARED_NAME0"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME1"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME2"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME3"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME4"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME5"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME6"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME7"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME8"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME9"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME10"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME11"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME12"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME13"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME14"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME15"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME16"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME17"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME18"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME19"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME20"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME21"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME22"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME23"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME24"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME25"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME26"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME27"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME28"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME29"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME30"),
// TEXT("HYPIM_WORDLIB_SHARED_NAME31"),
//};
//
//#pragma data_seg()
typedef void (_stdcall *progress_indicator) (int total_number, int current_number);
/* 获得用户词库的标识。
* 参数:无
* 返回:
* 用户词库标识,没有装载则返回-1。
*/
int GetUserWordLibId()
{
extern int resource_thread_finished;
while (!resource_thread_finished)
Sleep(0); //此处引发了死机问题
return share_segment->user_wordlib_id;
}
/* 获得词库的内存大小(用于保存词库数据)
* 参数:
* wordlib 词库指针
* 返回:
* 词库的大小(头加上页长度)
*/
int GetWordLibSize(WORDLIB *wordlib)
{
assert(wordlib);
return sizeof(wordlib->header_data) + wordlib->header.page_count * WORDLIB_PAGE_SIZE;
}
/** 获得词库信息
* 当参数为0的时候,不对参数进行赋值
* 参数:
* name 词库文件
* version 词库版本号
* wl_name 词库文件名称
* author_name 词库作者名称
* can_be_edit 是否可以被编辑
* items 词库中的词条数目
* 返回:
* 成功:1
* 失败:0(词库可能不存在)
*/
int GetWordLibInformation(const TCHAR *name, int *version, TCHAR *wl_name, TCHAR *author_name, int *can_be_edit, int *items)
{
WORDLIBHEADER header;
extern int IsV3WordLibBK(const TCHAR*);
if (LoadFromFile(name, (char*)&header, sizeof(header)) < sizeof(header))
return 0;
if (version)
{
switch (header.signature)
{
case HYPIM_WORDLIB_V66_SIGNATURE:
*version = WORDLIB_V66;
break;
case HYPIM_WORDLIB_V6_SIGNATURE:
*version = WORDLIB_V6;
break;
case HYPIM_WORDLIB_V6B1_SIGNATURE:
*version = WORDLIB_V6B1;
break;
case HYPIM_WORDLIB_V6B2_SIGNATURE:
*version = WORDLIB_V6B2;
break;
case HYPIM_WORDLIB_V5_SIGNATURE:
*version = WORDLIB_V5;
return 1;
default:
//需要判断是否为V3/V5的备份词库文件
*version = IsV3WordLibBK(name) ? WORDLIB_V5_BKUP : WORDLIB_WRONG;
return 1;
}
}
if (wl_name)
_tcscpy_s(wl_name, WORDLIB_NAME_LENGTH, header.name);
if (author_name)
_tcscpy_s(author_name, WORDLIB_AUTHOR_LENGTH, header.author_name);
if (can_be_edit)
*can_be_edit = header.can_be_edit;
if (items)
*items = header.word_count;
return 1;
}
/** 快速获得词库信息(不检查V3V5的备份文件)
* 当参数为0的时候,不对参数进行赋值
* 参数:
* name 词库文件
* version 词库版本号
* wl_name 词库文件名称
* author_name 词库作者名称
* can_be_edit 是否可以被编辑
* items 词库中的词条数目
* 返回:
* 成功:1
* 失败:0(词库可能不存在)
*/
int GetWordLibInformationFast(const TCHAR *name, int *version, TCHAR *wl_name, TCHAR *author_name, int *can_be_edit, int *items)
{
WORDLIBHEADER header;
if (LoadFromFile(name, (char*)&header, sizeof(header)) < sizeof(header))
return 0;
if (version)
{
switch (header.signature)
{
case HYPIM_WORDLIB_V66_SIGNATURE:
*version = WORDLIB_V66;
break;
case HYPIM_WORDLIB_V6_SIGNATURE:
*version = WORDLIB_V6;
break;
case HYPIM_WORDLIB_V6B1_SIGNATURE:
*version = WORDLIB_V6B1;
break;
case HYPIM_WORDLIB_V6B2_SIGNATURE:
*version = WORDLIB_V6B2;
break;
case HYPIM_WORDLIB_V5_SIGNATURE:
*version = WORDLIB_V5;
return 1;
default:
*version = WORDLIB_WRONG;
return 1;
}
}
if (wl_name)
_tcscpy_s(wl_name, WORDLIB_NAME_LENGTH, header.name);
if (author_name)
_tcscpy_s(author_name, WORDLIB_AUTHOR_LENGTH, header.author_name);
if (can_be_edit)
*can_be_edit = header.can_be_edit;
if (items)
*items = header.word_count;
return 1;
}
/* 依据词库标识,获得内存中词库的指针。
* 参数:
* wordlib_id 词库标识
* 返回:
* 找到:词库指针
* 未找到:0
*/
WORDLIB *GetWordLibrary(int wordlib_id)
{
if (wordlib_id < 0) //非法标识
return 0;
if (wordlib_buffer[wordlib_id] == 0) //没有这个词库的指针(可能被释放掉了)
{
Log(LOG_ID, L"获取词库指针出错。id=%d", wordlib_id);
return 0;
}
return wordlib_buffer[wordlib_id];
}
/* 保存词库文件。
* 参数:
* wordlib_id 词库标识
* 返回:
* 成功:1
* 失败:0
*/
int SaveWordLibrary(int wordlib_id)
{
WORDLIB *wordlib;
int length; //词库长度
if (wordlib_id == share_segment->user_wordlib_id &&
(!share_segment->can_save_user_wordlib || !share_segment->user_wl_modified))
{
Log(LOG_ID, L"用户词库没有改变或禁止改变,不保存词库");
return 0;
}
//词库指针获取
wordlib = GetWordLibrary(wordlib_id);
if (!wordlib)
{
Log(LOG_ID, L"未找到词库,id=%d", wordlib_id);
return 0;
}
//用户词库,需要做一下备份
if (GetUserWordLibId() == wordlib_id)
{
TCHAR bak_wordlib_name[MAX_PATH];
_tcscpy_s(bak_wordlib_name, _SizeOf(bak_wordlib_name), share_segment->wordlib_name[wordlib_id]);
_tcscat_s(bak_wordlib_name, _SizeOf(bak_wordlib_name), TEXT(".bak"));
if (FileExists(bak_wordlib_name))
{
SetFileAttributes(bak_wordlib_name, FILE_ATTRIBUTE_NORMAL);
DeleteFile(bak_wordlib_name);
}
//备份用户文件
CopyFile(share_segment->wordlib_name[wordlib_id], bak_wordlib_name, FALSE);
}
length = GetWordLibSize(wordlib);
if (!SaveToFile(share_segment->wordlib_name[wordlib_id], wordlib, length))
{
Log(LOG_ID, L"保存词库失败,id = %d, lib_ptr = %p, length = %d", wordlib_id, wordlib, length);
return 0;
}
if (wordlib_id == share_segment->user_wordlib_id)
share_segment->user_wl_modified = 0;
return 1;
}
/** 获得内存中已经装载的词库文件
*/
int GetWordLibraryLoaded(const TCHAR *lib_name)
{
int i;
//遍历内存中的词库
for (i = 0; i < MAX_WORDLIBS; i++)
if (!share_segment->wordlib_deleted[i] && !_tcscmp(share_segment->wordlib_name[i], lib_name))
break;
if (i != MAX_WORDLIBS) //本词库已经在内存中
return i;
return -1;
}
/* 装载词库文件。模块内部使用。
* 词库文件将装载到内存的共享区。对于同一个用户,所有的应用程序共享相同的
* 词库(包括多个词库)。
* 参数:
* lib_name 词库的完整文件名字(包含路径)
* extra_length 词库所需要的扩展数据长度
* check_exist 检查是否已经存在(用于词库的更新)
* 返回值:
* 成功:词库序号 >= 0
* 失败:-1
*/
int LoadWordLibraryWithExtraLength(const TCHAR *lib_name, int extra_length, int check_exist)
{
int length,length1; //词库长度
char *buffer; //词库的指针
int i, error; //是否出错
int empty_id; //未使用的ID
WORDLIB *wl; //词库指针
error = 1; //默认出错
Log(LOG_ID, L"装载词库<%s>文件,需要额外数据:%d", lib_name, extra_length);
//需要加锁
Lock();
do
{
//首先检查内存中是否已经存入了词库的数据
empty_id = -1;
if (!check_exist) //不检查已有词库,则从剩余的共享中寻找
{
for (i = MAX_WORDLIBS; i < 2 * MAX_WORDLIBS; i++)
if (wordlib_buffer[i] == 0) //可以使用的ID
{
empty_id = i;
break;
}
}
else
{ //检查内存中存在的词库
for (i = 0; i < MAX_WORDLIBS; i++)
{
if (check_exist && !share_segment->wordlib_deleted[i] &&
!_tcscmp(share_segment->wordlib_name[i], lib_name))
break;
if (empty_id == -1 && wordlib_buffer[i] == 0) //可以使用的ID
empty_id = i;
}
if (i != MAX_WORDLIBS) //本词库已经在内存中
{
buffer = GetSharedMemory(share_segment->wordlib_shared_name[i]);
if (!buffer) //没有找到,系统错误!
{
//可能由于IE7的优先级问题造成只能读取这个词库,所以要获得ReadOnly内存映射
buffer = GetReadOnlySharedMemory(share_segment->wordlib_shared_name[i]);
if (buffer)
{
wordlib_can_write[i] = 0;
wordlib_buffer[i] = (WORDLIB*)buffer;
return i;
}
//Sandboxie等程序会造成无法获取共享内存(共享内存的名字被修改了)
//因此重新加载共享内存
else
empty_id = i;
}
else
{
wordlib_can_write[i] = 1;
wordlib_buffer[i] = (WORDLIB*)buffer; //设定本地址空间内的词库指针
}
if (buffer)
{
Unlock();
return i; //返回已经找到的词库标识
}
}
}
if (empty_id == -1) //无法再装载新的词库,已满
break;
//判断是否为V6当前词库,如果不是能够升级进行升级,否则返回
if (!CheckAndUpdateWordLibraryFast(lib_name))
{
error = 1;
break;
}
//内存中没有词库数据,需要进行装载
length = GetFileLength(lib_name); //获得词库的长度
if (length <= 0) //文件不存在?
break;
//临时解决系统词库清零问题,固定系统词库内存为2M+1M,不足2M的直接申请2M,外挂1M作为扩展(不断的增加单词)
//大概能保存20W左右的数据
if(!_tcscmp(lib_name + _tcslen(lib_name) - 8,TEXT("user.uwl")) && length < 0x200000)
length1 = 0x200000;
else
length1 = length;
//分配共享内存
buffer = AllocateSharedMemory(share_segment->wordlib_shared_name[empty_id], length1 + extra_length);
if (!buffer) //分配失败
break;
//判断词库内容为何被加载了其他的内容
if (empty_id == 1) //系统词库
{
int len = (int)_tcslen(lib_name);
if (_tcscmp(lib_name + len - 7, TEXT("sys.uwl")))
Log(LOG_ID, L"!!!!!!!!!!系统词库正在被覆盖,程序:%s, 覆盖文件:%s", GetProgramName(), lib_name);
}
if (!LoadFromFile(lib_name, buffer, length))
{ //装载失败
FreeSharedMemory(share_segment->wordlib_shared_name[empty_id], buffer);
break;
}
wl = (WORDLIB*)buffer;
if (wl->header.signature != HYPIM_WORDLIB_V66_SIGNATURE)
{
error = 1;
FreeSharedMemory(share_segment->wordlib_shared_name[empty_id], buffer);
break;
}
//对词库相关数据进行记录
_tcsncpy(share_segment->wordlib_name[empty_id], lib_name, _SizeOf(share_segment->wordlib_name[0]));
share_segment->wordlib_length[empty_id] = length1 + extra_length;
wordlib_buffer[empty_id] = (WORDLIB*)buffer;
wordlib_can_write[empty_id] = 1;
error = 0;
}while(0);
//需要解锁
Unlock();
if (error)
{
Log(LOG_ID, L"加载失败");
return -1;
}
return empty_id;
}
/* 装载词库文件。
* 词库文件将装载到内存的共享区。对于同一个用户,所有的应用程序共享相同的
* 词库(包括多个词库)。
* 参数:
* wordlib_name 词库的完整文件名字(包含路径)
* 返回值:
* 成功:词库序号 >= 0
* 失败:-1
*/
int LoadWordLibrary(const TCHAR *wordlib_name)
{
return LoadWordLibraryWithExtraLength(wordlib_name, WORDLIB_NORMAL_EXTRA_LENGTH, 1);
}
/* 装载用户词库文件。
* 词库文件将装载到内存的共享区。对于同一个用户,所有的应用程序共享相同的
* 词库(包括多个词库)。
* 由于用户词库将存储自行制造的词汇,因此需要加入扩展的数据长度。
* 参数:
* wordlib_name 词库的完整文件名字(包含路径)
* 返回值:
* 如果成功,返回词库标识;失败返回-1。
*/
int LoadUserWordLibrary(const TCHAR *wordlib_name)
{
TCHAR new_wordlib_name[MAX_PATH];
TCHAR bak_wordlib_name[MAX_PATH];
Log(LOG_ID, L"0");
Log(LOG_ID, L"加载用户词库<%s>", wordlib_name);
if (GetFileLength(wordlib_name) <= 0) //没有词库文件,创建一份
if (!CreateEmptyWordLibFile(wordlib_name, DEFAULT_USER_WORDLIB_NAME, DEFAULT_USER_WORDLIB_AUTHOR, 1))
return -1; //彻底失败
Log(LOG_ID, L"1");
//用户词库需要扩充内存
share_segment->user_wordlib_id = LoadWordLibraryWithExtraLength(wordlib_name, WORDLIB_EXTRA_LENGTH, 1);
//无法加载,可能是词库文件出错了,备份之前的文件,然后重新创建用户词库
if (-1 == share_segment->user_wordlib_id)
{
_tcscpy_s(new_wordlib_name, _SizeOf(new_wordlib_name), wordlib_name);
_tcscat_s(new_wordlib_name, _SizeOf(new_wordlib_name), TEXT(".bad"));
_tcscpy_s(bak_wordlib_name, _SizeOf(bak_wordlib_name), wordlib_name);
_tcscat_s(bak_wordlib_name, _SizeOf(bak_wordlib_name), TEXT(".bak"));
if (FileExists(new_wordlib_name))
{
SetFileAttributes(new_wordlib_name, FILE_ATTRIBUTE_NORMAL);
DeleteFile(new_wordlib_name);
}
//备份错误的文件
MoveFile(wordlib_name, new_wordlib_name);
//恢复备份文件
if (FileExists(bak_wordlib_name))
CopyFile(bak_wordlib_name, wordlib_name, FALSE);
//装载备份文件
if (FileExists(wordlib_name))
share_segment->user_wordlib_id = LoadWordLibraryWithExtraLength(wordlib_name, WORDLIB_EXTRA_LENGTH, 1);
//备份文件也不对,创建一个新的用户词库文件
if (-1 == share_segment->user_wordlib_id)
{
CreateEmptyWordLibFile(wordlib_name, DEFAULT_USER_WORDLIB_NAME, DEFAULT_USER_WORDLIB_AUTHOR, 1);
share_segment->user_wordlib_id = LoadWordLibraryWithExtraLength(wordlib_name, WORDLIB_EXTRA_LENGTH, 1);
}
}
return share_segment->user_wordlib_id;
}
/* 释放词库数据。
* 参数:无
* 返回:无
*/
void CloseWordLibrary(int wordlib_id)
{
if (wordlib_id < 0 || wordlib_id >= MAX_WORDLIBS * 2)
return;
//加锁
Lock();
FreeSharedMemory(share_segment->wordlib_shared_name[wordlib_id], wordlib_buffer[wordlib_id]);
wordlib_buffer[wordlib_id] = 0; //指针清零
share_segment->wordlib_length[wordlib_id] = 0; //长度清零
share_segment->wordlib_name[wordlib_id][0] = 0; //文件名字清零
wordlib_can_write[wordlib_id] = 0; //禁止写入
share_segment->wordlib_deleted[wordlib_id] = 0; //被删除标志
//解锁
Unlock();
}
/** 释放所有的词库数据。
* 参数:无
* 返回:无
*/
void CloseAllWordLibrary()
{
int i;
for (i = 0; i < MAX_WORDLIBS; i++)
CloseWordLibrary(i);
}
/** 在词库中建新页。
* 参数:
* wordlib_id 词库句柄
* 返回:
* 成功创建:页号
* 失败:-1
*/
static int NewWordLibPage(int wordlib_id)
{
WORDLIB *wordlib = GetWordLibrary(wordlib_id); //词库指针
int length = share_segment->wordlib_length[wordlib_id]; //词库的总长度
int new_length, new_page_no; //新的词库长度、新页号
if (!wordlib) //没有这个词库
return -1;
//计算当前词库的Size是否已经到达词库的边界
new_length = sizeof(wordlib->header_data) + //词库头
wordlib->header.page_count * WORDLIB_PAGE_SIZE + //页数据长度
WORDLIB_PAGE_SIZE; //新页数据长度
if (new_length > length) //超出内存边界,无法分配
return -1;
//对页初始化
new_page_no = wordlib->header.page_count;
wordlib->pages[new_page_no].data_length = 0;
wordlib->pages[new_page_no].next_page_no = PAGE_END;
wordlib->pages[new_page_no].page_no = new_page_no;
wordlib->pages[new_page_no].length_flag = 0;
wordlib->header.page_count++;
return new_page_no;
}
/* 判断词是否已经在词库中
* 参数:
* 返回:
* 在词库中:指向词条的指针
* 不在:0
*/
WORDLIBITEM *GetCiInWordLibrary(int wordlib_id, HZ *hz, int hz_length, SYLLABLE *syllable, int syllable_length)
{
int count, i;
//CANDIDATE candidates[MAX_CANDIDATES];
CANDIDATE *candidates;
WORDLIBITEM *item = 0;
candidates = malloc(sizeof(CANDIDATE) * MAX_CANDIDATES);
count = GetCiCandidates(wordlib_id, syllable, syllable_length, candidates, MAX_CANDIDATES, FUZZY_CI_SYLLABLE_LENGTH);
for (i = 0; i < count; i++)
if (candidates[i].word.item->ci_length == hz_length && !memcmp(candidates[i].word.hz, hz, hz_length * sizeof(HZ)))
{
item = candidates[i].word.item; //找到
break;
}
free(candidates);
return item;
}
/* 在词库中删除词汇。
* 参数:
* wordlib_id 词库标识
* syllable 音节数组
* hz 汉字数组
* length 长度
* 返回:
* 1 删除成功
* 0 未找到
* -1 失败
*/
int DeleteCiFromWordLib(int wordlib_id, HZ *hz, int hz_length, SYLLABLE *syllable, int syllable_length, int clear_syllable)
{
WORDLIBITEM *item;
WORDLIB *wordlib;
wordlib = GetWordLibrary(wordlib_id);
if (!wordlib) //没有这个词库
return -1;
//在词库中查找词
item = GetCiInWordLibrary(wordlib_id, hz, hz_length, syllable, syllable_length);
if (!item) //没有找到
return 0;
if (item->effective)
wordlib->header.word_count--;
item->effective = 0;
if (clear_syllable)
{
item->syllable[0].con = CON_NULL;
item->syllable[0].vow = VOW_NULL;
}
if (wordlib_id == share_segment->user_wordlib_id)
share_segment->user_wl_modified = 1;
return 1;
}
/* 向词库中增加词汇(用户自造词)。
* 要求:词的音节必须与字一一对应,不能出现“分隔符”以及“通配符”。
* 参数:
* wordlib_id 词库标识
* hz 词
* length 词长度
* freq 词频
* 返回:
* 成功加入:1
* 失败:0
*/
int AddCiToWordLibrary(int wordlib_id, HZ *hz, int hz_length, SYLLABLE *syllable, int syllable_length, int freq)
{
WORDLIBITEM *item; //词项指针
WORDLIB *wordlib; //词库指针
PAGE *page; //页指针
int page_no, new_page_no; //页号
int item_length; //词项长度
int i;
//检查词频,避免越界
if (freq > WORDLIB_MAX_FREQ)
freq = WORDLIB_MAX_FREQ;
if (wordlib_id < 0 || wordlib_id >= MAX_WORDLIBS * 2)
return 0;
//不能进行写的词库文件
if (!wordlib_can_write[wordlib_id])
return 0;
if (syllable_length < 2 || syllable_length > MAX_WORD_LENGTH || hz_length < 2 || hz_length > MAX_WORD_LENGTH)
{
Log(LOG_ID, L"增加词汇长度错误。syllable_length = %d, ci_length = %d", syllable_length, hz_length);
return 0; //音节过少或者过大
}
//判断是否都是汉字
if (!IsAllCanInLibrary(hz, hz_length))
return 0;
//进行插入
wordlib = GetWordLibrary(wordlib_id);
if (!wordlib) //没有这个词库
return 0;
//判断该词是否在词库中存在,如果存在不做插入,但将有效置为1,并且增加一次词频
if ((item = GetCiInWordLibrary(wordlib_id, hz, hz_length, syllable, syllable_length)) != 0)
{
if (!item->effective)
{
item->effective = 1;
wordlib->header.word_count++;
}
if (wordlib_id == GetUserWordLibId())
{
if (freq > (int)item->freq)
item->freq = (unsigned int)freq;
else
item->freq++;
share_segment->user_wl_modified = 1;
return 1;
}
if (freq > (int)item->freq)
item->freq = (unsigned int)freq;
return 1;
}
item_length = GetItemLength(hz_length, syllable_length);
//找出音节序列的词库页索引
page_no = wordlib->header.index[syllable[0].con][syllable[1].con];
if (page_no == PAGE_END) //索引没有指向页
{
new_page_no = NewWordLibPage(wordlib_id); //分配新页
if (new_page_no == -1) //未能分配成功,只好返回
return 0;
wordlib->header.index[syllable[0].con][syllable[1].con] = new_page_no; //索引联接
page_no = new_page_no;
}
//遍历页表找出最后一页。
//不进行已删除词汇空洞的填补工作,省力(好编)并且省心(程序健壮)。
while(wordlib->pages[page_no].next_page_no != PAGE_END)
page_no = wordlib->pages[page_no].next_page_no;
//获得页
page = &wordlib->pages[page_no];
//如果本页的数据不能满足加入要求
if (page->data_length + item_length > WORDLIB_PAGE_DATA_LENGTH)
{//需要分配新页
new_page_no = NewWordLibPage(wordlib_id);
if (new_page_no == -1) //未能分配成功,只好返回
return 0;
//分配成功,维护页链表
page->next_page_no = new_page_no;
page_no = new_page_no;
page = &wordlib->pages[page_no];
}
assert(page->data_length + item_length <= WORDLIB_PAGE_DATA_LENGTH);
//词汇长度
page->length_flag |= (1 << syllable_length);
//在本页中插入输入
item = (WORDLIBITEM*)&page->data[page->data_length];
item->effective = 1; //有效
item->ci_length = hz_length; //词长度
item->syllable_length = syllable_length; //音节长度
item->freq = freq; //词频
for (i = 0; i < syllable_length; i++)
item->syllable[i] = syllable[i]; //音节
for (i = 0; i < hz_length; i++)
GetItemHZPtr(item)[i] = hz[i]; //汉字
//增加页的数据长度
page->data_length += item_length;
//增加了一条记录
wordlib->header.word_count++;
if (wordlib_id == share_segment->user_wordlib_id)
share_segment->user_wl_modified = 1;
//成功插入
return 1;
}
/* 创建新的空的词库文件。
* 参数:
* wordlib_file_name 词库文件名字(全路径)
* name 词库名字(放在词库内部)
* author 作者
* can_be_edit 是否允许编辑
* 返回:
* 成功创建:1
* 失败:0
*/
int CreateEmptyWordLibFile(const TCHAR *wordlib_file_name, const TCHAR *name, const TCHAR *author, int can_be_edit)
{
WORDLIB wordlib;
int i, j;
Log(LOG_ID, L"创建新词库<%s>, name:%s, author:%s, can_be_edit:%d",
wordlib_file_name, name, author, can_be_edit);
//清零
memset(&wordlib, 0, sizeof(wordlib));
//作者名字
_tcsncpy(wordlib.header.author_name, author, _SizeOf(wordlib.header.author_name));
//词库名字
_tcsncpy(wordlib.header.name, name, _SizeOf(wordlib.header.name));
wordlib.header.can_be_edit = can_be_edit;
//将Index置为没有页
for (i = CON_NULL; i < CON_END; i++)
for (j = CON_NULL; j < CON_END; j++)
wordlib.header.index[i][j] = PAGE_END;
//没有已分配的页
wordlib.header.page_count = 0;
wordlib.header.pim_version = HYPIM_VERSION;
wordlib.header.signature = HYPIM_WORDLIB_V66_SIGNATURE;
wordlib.header.word_count = 0;
if (!SaveToFile(wordlib_file_name, &wordlib, sizeof(wordlib)))
return 0;
return 1;
}
/** 检查是否词库的指针都已经是正确的。
*/
void MaintainWordLibPointer()
{
int i;
for (i = 0; i < MAX_WORDLIBS; i++)
{
//词库不在内存中 || 是被删除的词库 || 指针已经被设置
if (!share_segment->wordlib_name[i][0] || share_segment->wordlib_deleted[i] || wordlib_buffer[i])
continue;
//获取词库的指针
wordlib_buffer[i] = GetSharedMemory(share_segment->wordlib_shared_name[i]);
}
}
/** 获得下一个词库标识,用于词库的遍历。
* 参数:
* cur_id 当前的ID(第一次的时候输入-1)
* 返回:
* 下一个词库标识:>0
* 没有下一个词库的标识:-1
*/
int GetNextWordLibId(int cur_id)
{
int i;
if (cur_id < 0)
cur_id = -1;
for (i = cur_id + 1; i < MAX_WORDLIBS; i++)
if (!share_segment->wordlib_deleted[i] && wordlib_buffer[i])
return i;
return -1;
}
/** 获得词库中被删除的词条
* 参数:
* wordlib_id 词库标识
* item_array 词项指针数组
* length 数组长度
* 返回:
* 被删除词条数目
*/
int GetDeleteItems(int wordlib_id, WORDLIBITEM **item_array, int length)
{
extern WORDLIBITEM *NextCiItem(WORDLIBITEM *item);
WORDLIBITEM *item;
WORDLIB *wl;
PAGE *page;
int i;
int count = 0;
if (!item_array)
return 0;
wl = GetWordLibrary(wordlib_id);
if (!wl)
return 0;
for (i = 0; i < wl->header.page_count; i++)
{ //遍历页表
for (page = &wl->pages[i], item = (WORDLIBITEM*) page->data;
count < length && (char*)item < (char*) &page->data + page->data_length;
item = GetNextCiItem(item))
{
if (item->effective) //有效的词跳过
continue;
item_array[count++] = item;
}
}
return count;
}
//词库维护外部接口