1 |
/* |
2 |
|
3 |
MacOS X implementation of the SKK input method. |
4 |
|
5 |
Copyright (C) 2008 Tomotaka SUWA <t.suwa@mac.com> |
6 |
|
7 |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
10 |
any later version. |
11 |
|
12 |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
16 |
|
17 |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
|
21 |
*/ |
22 |
|
23 |
#include "SKKDictionaryKeeper.h" |
24 |
#include "jconv.h" |
25 |
|
26 |
class CompareFunctor { |
27 |
int length_; |
28 |
|
29 |
bool compare(const std::string& lhs, const std::string& rhs) const { |
30 |
return 0 < rhs.compare(0, length_, lhs, 0, length_); |
31 |
} |
32 |
|
33 |
public: |
34 |
CompareFunctor(int length) : length_(length) {} |
35 |
|
36 |
bool operator()(const SKKDictionaryEntry& lhs, const SKKDictionaryEntry& rhs) const { |
37 |
return compare(lhs.first, rhs.first); |
38 |
} |
39 |
|
40 |
bool operator()(const SKKDictionaryEntry& lhs, const std::string& rhs) const { |
41 |
return compare(lhs.first, rhs); |
42 |
} |
43 |
|
44 |
bool operator()(const std::string& lhs, const SKKDictionaryEntry& rhs) const { |
45 |
return compare(lhs, rhs.first); |
46 |
} |
47 |
}; |
48 |
|
49 |
SKKDictionaryKeeper::SKKDictionaryKeeper() : loaded_(false), timer_(0) {} |
50 |
|
51 |
void SKKDictionaryKeeper::Initialize(SKKDictionaryLoader* loader, int interval, int timeout) { |
52 |
if(timer_.get()) return; |
53 |
|
54 |
timeout_ = timeout; |
55 |
|
56 |
loader->Connect(this); |
57 |
|
58 |
timer_ = std::auto_ptr<pthread::timer>(new pthread::timer(loader, interval)); |
59 |
} |
60 |
|
61 |
std::string SKKDictionaryKeeper::FindOkuriAri(const std::string& query) { |
62 |
return fetch(query, file_.OkuriAri()); |
63 |
} |
64 |
|
65 |
std::string SKKDictionaryKeeper::FindOkuriNasi(const std::string& query) { |
66 |
return fetch(query, file_.OkuriNasi()); |
67 |
} |
68 |
|
69 |
bool SKKDictionaryKeeper::FindCompletions(const std::string& entry, std::vector<std::string>& result) { |
70 |
pthread::lock scope(condition_); |
71 |
|
72 |
if(!ready()) return false; |
73 |
|
74 |
SKKDictionaryEntryContainer& container = file_.OkuriNasi(); |
75 |
|
76 |
typedef std::pair<SKKDictionaryEntryIterator, SKKDictionaryEntryIterator> EntryRange; |
77 |
|
78 |
std::string index; |
79 |
jconv::convert_utf8_to_eucj(entry, index); |
80 |
|
81 |
EntryRange range = std::equal_range(container.begin(), container.end(), index, CompareFunctor(index.size())); |
82 |
|
83 |
for(SKKDictionaryEntryIterator iter = range.first; iter != range.second; ++ iter) { |
84 |
std::string tmp; |
85 |
jconv::convert_eucj_to_utf8(iter->first, tmp); |
86 |
result.push_back(tmp); |
87 |
} |
88 |
|
89 |
return range.first != range.second; |
90 |
} |
91 |
|
92 |
void SKKDictionaryKeeper::SKKDictionaryLoaderUpdate(const SKKDictionaryFile& file) { |
93 |
pthread::lock scope(condition_); |
94 |
|
95 |
file_ = file; |
96 |
|
97 |
loaded_ = true; |
98 |
|
99 |
condition_.signal(); |
100 |
} |
101 |
|
102 |
std::string SKKDictionaryKeeper::fetch(const std::string& query, SKKDictionaryEntryContainer& container) { |
103 |
pthread::lock scope(condition_); |
104 |
|
105 |
if(!ready()) return ""; |
106 |
|
107 |
std::string index; |
108 |
std::string result; |
109 |
|
110 |
jconv::convert_utf8_to_eucj(query, index); |
111 |
|
112 |
if(!std::binary_search(container.begin(), container.end(), index, SKKDictionaryEntryCompare())) { |
113 |
return result; |
114 |
} |
115 |
|
116 |
SKKDictionaryEntryIterator iter = std::lower_bound(container.begin(), container.end(), |
117 |
index, SKKDictionaryEntryCompare()); |
118 |
|
119 |
jconv::convert_eucj_to_utf8(iter->second, result); |
120 |
|
121 |
return result; |
122 |
} |
123 |
|
124 |
bool SKKDictionaryKeeper::ready() { |
125 |
// ��������������������������������������������� |
126 |
if(!loaded_) { |
127 |
if(!condition_.wait(timeout_)) return false; |
128 |
} |
129 |
|
130 |
return true; |
131 |
} |