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 #include "fuzzy/fuzzyimpl.h"
00029 #include "base/memory.hpp"
00030 #include "base/list.hpp"
00031 #include "base/common.hpp"
00032 #include "base/map.hpp"
00033 #include "base/vector.hpp"
00034 #include "base/stack.hpp"
00035 #include "base/string.hpp"
00036 #include "base/date.h"
00037 #include "base/keymaker.hpp"
00038 #include "smart/byterep.hpp"
00039
00040 #include "fuzzyphonetic.hpp"
00041
00042 BEGIN_TERIMBER_NAMESPACE
00043 #pragma pack(4)
00044
00045 class fuzzy_wrapper_impl : public fuzzy_wrapper
00046 {
00047 public:
00048 fuzzy_wrapper_impl(size_t memory_usage);
00049 ~fuzzy_wrapper_impl();
00050
00051 virtual bool add(const char* phrase);
00052
00053
00054
00055 virtual bool remove(const char* phrase);
00056
00057
00058 virtual bool match( ngram_quality nq,
00059 phonetic_quality fq,
00060 const char* phrase,
00061 linked_result& suggestions) const;
00062 private:
00063 keylocker _key;
00064 mutex _mtx;
00065 mutable list< byte_allocator* > _all_container;
00066 fuzzy_matcher_impl _matcher;
00067 };
00068
00069 #pragma pack()
00070 END_TERIMBER_NAMESPACE
00071
00072
00073 fuzzy_wrapper*
00074 fuzzy_wrapper_factory::get_fuzzy_wrapper(size_t memory_usage)
00075 {
00076 return new TERIMBER::fuzzy_wrapper_impl(memory_usage);
00077 }
00078
00079 BEGIN_TERIMBER_NAMESPACE
00080 #pragma pack(4)
00081
00082 const size_t all_default_size = 1024*64;
00083
00084 fuzzy_wrapper_impl::fuzzy_wrapper_impl(size_t memory_usage) : _matcher(memory_usage)
00085 {
00086 }
00087
00088 fuzzy_wrapper_impl::~fuzzy_wrapper_impl()
00089 {
00090 while (!_all_container.empty())
00091 {
00092 delete _all_container.front();
00093 _all_container.pop_front();
00094 }
00095 }
00096
00097
00098 bool
00099 fuzzy_wrapper_impl::add(const char* phrase)
00100 {
00101 keylocker_server locker(_key);
00102 byte_allocator* tmp = 0;
00103
00104 mutex_keeper keeper(_mtx);
00105 if (_all_container.empty())
00106 tmp = new byte_allocator(all_default_size);
00107 else
00108 {
00109 tmp = _all_container.front();
00110 _all_container.pop_front();
00111 }
00112
00113 if (!tmp)
00114 return false;
00115
00116 keeper.unlock();
00117
00118 size_t ident = _matcher.add(phrase, *tmp);
00119
00120 keeper.lock();
00121 _all_container.push_front(tmp);
00122
00123 return ident != 0;
00124 }
00125
00126
00127
00128
00129 bool
00130 fuzzy_wrapper_impl::remove(const char* phrase)
00131 {
00132 keylocker_server locker(_key);
00133 byte_allocator* tmp = 0;
00134
00135 mutex_keeper keeper(_mtx);
00136 if (_all_container.empty())
00137 tmp = new byte_allocator(all_default_size);
00138 else
00139 {
00140 tmp = _all_container.front();
00141 _all_container.pop_front();
00142 }
00143
00144 if (!tmp)
00145 return false;
00146
00147 keeper.unlock();
00148
00149 bool res = _matcher.remove(phrase, *tmp);
00150
00151 keeper.lock();
00152 _all_container.push_front(tmp);
00153
00154 return res;
00155
00156 }
00157
00158
00159
00160 bool
00161 fuzzy_wrapper_impl::match( ngram_quality nq,
00162 phonetic_quality pq,
00163 const char* phrase,
00164 linked_result& suggestions) const
00165 {
00166 keylocker_client locker(_key);
00167
00168 byte_allocator* tmp = 0;
00169 byte_allocator* all = 0;
00170
00171 mutex_keeper keeper(_mtx);
00172 if (_all_container.empty())
00173 tmp = new byte_allocator(all_default_size);
00174 else
00175 {
00176 tmp = _all_container.front();
00177 _all_container.pop_front();
00178 }
00179
00180 if (_all_container.empty())
00181 all = new byte_allocator(all_default_size);
00182 else
00183 {
00184 all = _all_container.front();
00185 _all_container.pop_front();
00186 }
00187
00188 if (!tmp || !all)
00189 return false;
00190
00191 keeper.unlock();
00192
00193 _list< const char* > candidates;
00194 bool res = _matcher.match(nq, pq, phrase, *all, *tmp, candidates);
00195
00196 linked_result* curr = 0;
00197
00198 if (res)
00199 {
00200 for (_list< const char* >::const_iterator it = candidates.begin(); it != candidates.end(); ++it)
00201 {
00202 if (!curr)
00203 {
00204 curr = &suggestions;
00205 }
00206 else
00207 {
00208 linked_result* next = new linked_result();
00209 if (!next)
00210 break;
00211
00212 curr->_next = next;
00213 curr = next;
00214 }
00215
00216 size_t len = (*it) ? strlen(*it) : 0;
00217 if (len)
00218 {
00219
00220 char* str = new char[len + 1];
00221 if (!str)
00222 break;
00223
00224 memcpy(str, *it, len + 1);
00225 curr->_str = str;
00226 }
00227 }
00228 }
00229
00230 keeper.lock();
00231
00232 _all_container.push_front(tmp);
00233 _all_container.push_front(all);
00234
00235
00236 return res;
00237 }
00238
00239 #pragma pack()
00240 END_TERIMBER_NAMESPACE