Character search moved to separate thread for smoother experience
This commit is contained in:
parent
710937f8df
commit
155fb03c5a
@ -2432,7 +2432,7 @@
|
||||
<property name="search_button">1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxTE_PROCESS_ENTER</property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
@ -2469,7 +2469,7 @@
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnText">OnSearchText</event>
|
||||
<event name="OnTextEnter">OnSearchEnter</event>
|
||||
<event name="OnTextEnter"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
@ -3506,15 +3506,6 @@
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="wxTimer" expanded="0">
|
||||
<property name="enabled">0</property>
|
||||
<property name="id">wxID_TIMER_SEARCH</property>
|
||||
<property name="name">m_timerSearch</property>
|
||||
<property name="oneshot">1</property>
|
||||
<property name="period">1000</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnTimer">OnSearchTimer</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
||||
|
@ -20,32 +20,22 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
static int __cdecl compare_hits(const void *a, const void *b)
|
||||
{
|
||||
const std::pair<unsigned long, wchar_t> *_a = (const std::pair<unsigned long, wchar_t>*)a;
|
||||
const std::pair<unsigned long, wchar_t> *_b = (const std::pair<unsigned long, wchar_t>*)b;
|
||||
|
||||
if (_a->first > _b->first) return -1;
|
||||
else if (_a->first < _b->first) return 1;
|
||||
|
||||
if (_a->second < _b->second) return -1;
|
||||
else if (_a->second > _b->second) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// wxZRColaCharSelect
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxDEFINE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent);
|
||||
|
||||
|
||||
wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
|
||||
m_searchChanged(false),
|
||||
m_unicodeChanged(false),
|
||||
m_char(0),
|
||||
m_searchThread(NULL),
|
||||
wxZRColaCharSelectBase(parent)
|
||||
{
|
||||
Connect(wxID_ANY, wxEVT_SEARCH_COMPLETE, wxThreadEventHandler(wxZRColaCharSelect::OnSearchComplete), NULL, this);
|
||||
|
||||
m_unicode->SetValidator(wxHexValidator<wchar_t>(&m_char));
|
||||
|
||||
// Fill categories.
|
||||
@ -61,6 +51,15 @@ wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
|
||||
}
|
||||
|
||||
|
||||
wxZRColaCharSelect::~wxZRColaCharSelect()
|
||||
{
|
||||
if (m_searchThread)
|
||||
m_searchThread->Delete();
|
||||
|
||||
Disconnect(wxID_ANY, wxEVT_SEARCH_COMPLETE, wxThreadEventHandler(wxZRColaCharSelect::OnSearchComplete), NULL, this);
|
||||
}
|
||||
|
||||
|
||||
void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
@ -90,7 +89,31 @@ void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
|
||||
|
||||
m_unicodeChanged = false;
|
||||
} else if (m_searchChanged) {
|
||||
m_timerSearch.Start(1000, true);
|
||||
if (m_searchThread)
|
||||
m_searchThread->Delete();
|
||||
|
||||
wxString val(m_search->GetValue());
|
||||
if (!val.IsEmpty()) {
|
||||
ZRColaApp *app = (ZRColaApp*)wxTheApp;
|
||||
|
||||
m_searchThread = new SearchThread(this);
|
||||
|
||||
m_searchThread->m_search.assign(val.c_str(), val.Length());
|
||||
|
||||
// Select categories.
|
||||
for (size_t i = 0, n = app->m_cc_db.idxRnk.size(); i < n; i++) {
|
||||
const ZRCola::chrcat_db::chrcat &cc = app->m_cc_db.idxRnk[i];
|
||||
if (m_categories->IsChecked(i))
|
||||
m_searchThread->m_cats.insert(cc.id);
|
||||
}
|
||||
|
||||
if (m_searchThread->Run() != wxTHREAD_NO_ERROR) {
|
||||
wxFAIL_MSG("Can't create the thread!");
|
||||
delete m_searchThread;
|
||||
m_searchThread = NULL;
|
||||
}
|
||||
} else
|
||||
ResetResults();
|
||||
|
||||
m_searchChanged = false;
|
||||
}
|
||||
@ -101,75 +124,35 @@ void wxZRColaCharSelect::OnSearchText(wxCommandEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
m_timerSearch.Stop();
|
||||
m_searchChanged = true;
|
||||
}
|
||||
|
||||
|
||||
void wxZRColaCharSelect::OnSearchEnter(wxCommandEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
m_timerSearch.Stop();
|
||||
wxTimerEvent e(m_timerSearch);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
|
||||
m_searchChanged = false;
|
||||
}
|
||||
|
||||
|
||||
void wxZRColaCharSelect::OnSearchTimer(wxTimerEvent& event)
|
||||
{
|
||||
wxString val(m_search->GetValue());
|
||||
if (!val.IsEmpty()) {
|
||||
ZRColaApp *app = (ZRColaApp*)wxTheApp;
|
||||
std::map<wchar_t, unsigned long> hits;
|
||||
std::set<ZRCola::chrcatid_t> cats;
|
||||
|
||||
// Select categories.
|
||||
for (size_t i = 0, n = app->m_cc_db.idxRnk.size(); i < n; i++) {
|
||||
const ZRCola::chrcat_db::chrcat &cc = app->m_cc_db.idxRnk[i];
|
||||
if (m_categories->IsChecked(i))
|
||||
cats.insert(cc.id);
|
||||
}
|
||||
|
||||
{
|
||||
// Search by indexes and merge results.
|
||||
std::map<wchar_t, unsigned long> hits_sub;
|
||||
app->m_chr_db.Search(val.c_str(), cats, hits, hits_sub);
|
||||
for (std::map<wchar_t, unsigned long>::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) {
|
||||
std::map<wchar_t, unsigned long>::iterator idx = hits.find(i->first);
|
||||
if (idx == hits.end())
|
||||
hits.insert(std::make_pair(i->first, i->second / 4));
|
||||
else
|
||||
idx->second += i->second / 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Now sort the characters by rank.
|
||||
std::vector< std::pair<unsigned long, wchar_t> > hits2;
|
||||
hits2.reserve(hits.size());
|
||||
for (std::map<wchar_t, unsigned long>::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i)
|
||||
hits2.push_back(std::make_pair(i->second, i->first));
|
||||
std::qsort(hits2.data(), hits2.size(), sizeof(std::pair<unsigned long, wchar_t>), compare_hits);
|
||||
|
||||
// Display results.
|
||||
wxString chars;
|
||||
chars.reserve(hits2.size());
|
||||
for (std::vector< std::pair<unsigned long, wchar_t> >::const_iterator i = hits2.cbegin(), i_end = hits2.cend(); i != i_end; ++i)
|
||||
chars += i->second;
|
||||
m_gridResults->SetCharacters(chars);
|
||||
} else
|
||||
ResetResults();
|
||||
|
||||
m_gridResults->Scroll(0, 0);
|
||||
}
|
||||
|
||||
|
||||
void wxZRColaCharSelect::OnCategoriesToggle(wxCommandEvent& event)
|
||||
{
|
||||
m_timerSearch.Stop();
|
||||
m_timerSearch.Start(500, true);
|
||||
event.Skip();
|
||||
|
||||
m_searchChanged = true;
|
||||
}
|
||||
|
||||
|
||||
void wxZRColaCharSelect::OnSearchComplete(wxThreadEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
if (m_searchThread) {
|
||||
// Display results.
|
||||
wxString chars;
|
||||
chars.reserve(m_searchThread->m_hits.size());
|
||||
for (std::vector< std::pair<unsigned long, wchar_t> >::const_iterator i = m_searchThread->m_hits.cbegin(), i_end = m_searchThread->m_hits.cend(); i != i_end; ++i)
|
||||
chars += i->second;
|
||||
m_gridResults->SetCharacters(chars);
|
||||
|
||||
m_searchThread->Delete();
|
||||
m_searchThread = NULL;
|
||||
|
||||
m_gridResults->Scroll(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -305,6 +288,74 @@ void wxZRColaCharSelect::ResetResults()
|
||||
}
|
||||
|
||||
|
||||
wxZRColaCharSelect::SearchThread::SearchThread(wxZRColaCharSelect *parent) :
|
||||
m_parent(parent),
|
||||
wxThread(wxTHREAD_JOINABLE)
|
||||
{
|
||||
//// This is a worker thread. Set priority between minimal and normal.
|
||||
//SetPriority((wxPRIORITY_MIN + wxPRIORITY_DEFAULT) / 2);
|
||||
}
|
||||
|
||||
|
||||
wxThread::ExitCode wxZRColaCharSelect::SearchThread::Entry()
|
||||
{
|
||||
ZRColaApp *app = (ZRColaApp*)wxTheApp;
|
||||
std::map<wchar_t, unsigned long> hits;
|
||||
|
||||
if (TestDestroy()) return (wxThread::ExitCode)1;
|
||||
|
||||
{
|
||||
// Search by indexes and merge results.
|
||||
std::map<wchar_t, unsigned long> hits_sub;
|
||||
if (!app->m_chr_db.Search(m_search.c_str(), m_cats, hits, hits_sub, TestDestroyS, this)) return (wxThread::ExitCode)1;
|
||||
for (std::map<wchar_t, unsigned long>::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) {
|
||||
if (TestDestroy()) return (wxThread::ExitCode)1;
|
||||
std::map<wchar_t, unsigned long>::iterator idx = hits.find(i->first);
|
||||
if (idx == hits.end())
|
||||
hits.insert(std::make_pair(i->first, i->second / 4));
|
||||
else
|
||||
idx->second += i->second / 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Now sort the characters by rank.
|
||||
m_hits.reserve(hits.size());
|
||||
for (std::map<wchar_t, unsigned long>::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i) {
|
||||
if (TestDestroy()) return (wxThread::ExitCode)1;
|
||||
m_hits.push_back(std::make_pair(i->second, i->first));
|
||||
}
|
||||
std::qsort(m_hits.data(), m_hits.size(), sizeof(std::pair<unsigned long, wchar_t>), CompareHits);
|
||||
|
||||
// Signal the event handler that this thread is going to be destroyed.
|
||||
// NOTE: here we assume that using the m_parent pointer is safe,
|
||||
// (in this case this is assured by the wxZRColaCharSelect destructor)
|
||||
wxQueueEvent(m_parent, new wxThreadEvent(wxEVT_SEARCH_COMPLETE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int __cdecl wxZRColaCharSelect::SearchThread::CompareHits(const void *a, const void *b)
|
||||
{
|
||||
const std::pair<unsigned long, wchar_t> *_a = (const std::pair<unsigned long, wchar_t>*)a;
|
||||
const std::pair<unsigned long, wchar_t> *_b = (const std::pair<unsigned long, wchar_t>*)b;
|
||||
|
||||
if (_a->first > _b->first) return -1;
|
||||
else if (_a->first < _b->first) return 1;
|
||||
|
||||
if (_a->second < _b->second) return -1;
|
||||
else if (_a->second > _b->second) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool __cdecl wxZRColaCharSelect::SearchThread::TestDestroyS(void *cookie)
|
||||
{
|
||||
return static_cast<wxZRColaCharSelect::SearchThread*>(cookie)->TestDestroy();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// wxPersistentZRColaCharSelect
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -30,9 +30,14 @@ class wxZRColaCharSelect;
|
||||
#include <zrcola/character.h>
|
||||
#include <wxex/valhex.h>
|
||||
#include <wxex/persist/dialog.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/thread.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
wxDECLARE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent);
|
||||
|
||||
|
||||
///
|
||||
/// ZRCola character select dialog
|
||||
///
|
||||
@ -40,15 +45,16 @@ class wxZRColaCharSelect : public wxZRColaCharSelectBase
|
||||
{
|
||||
public:
|
||||
wxZRColaCharSelect(wxWindow* parent);
|
||||
virtual ~wxZRColaCharSelect();
|
||||
|
||||
friend class wxPersistentZRColaCharSelect; // Allow saving/restoring window state.
|
||||
friend class SearchThread; // For search thread back-notifications
|
||||
|
||||
protected:
|
||||
virtual void OnIdle(wxIdleEvent& event);
|
||||
virtual void OnSearchText(wxCommandEvent& event);
|
||||
virtual void OnSearchEnter(wxCommandEvent& event);
|
||||
virtual void OnSearchTimer(wxTimerEvent& event);
|
||||
virtual void OnCategoriesToggle(wxCommandEvent& event);
|
||||
void OnSearchComplete(wxThreadEvent& event);
|
||||
virtual void OnResultSelectCell(wxGridEvent& event);
|
||||
virtual void OnResultCellDClick(wxGridEvent& event);
|
||||
virtual void OnResultsKeyDown(wxKeyEvent& event);
|
||||
@ -65,12 +71,36 @@ public:
|
||||
wchar_t m_char; ///< Currently selected character (0 when none)
|
||||
|
||||
protected:
|
||||
bool m_searchChanged; ///< Did Search field change?
|
||||
bool m_searchChanged; ///< Did Search field or category selection change?
|
||||
std::map<ZRCola::chrcatid_t, int> m_ccOrder; ///< Character category order
|
||||
bool m_unicodeChanged; ///< Did Unicode field change?
|
||||
|
||||
|
||||
///
|
||||
/// Search worker thread
|
||||
///
|
||||
class SearchThread : public wxThread
|
||||
{
|
||||
public:
|
||||
SearchThread(wxZRColaCharSelect *parent);
|
||||
|
||||
protected:
|
||||
virtual ExitCode Entry();
|
||||
static int __cdecl CompareHits(const void *a, const void *b);
|
||||
static bool __cdecl TestDestroyS(void *cookie);
|
||||
|
||||
public:
|
||||
std::wstring m_search; ///< Search phrase
|
||||
std::set<ZRCola::chrcatid_t> m_cats; ///< Search categories
|
||||
std::vector< std::pair<unsigned long, wchar_t> > m_hits; ///< Search results
|
||||
|
||||
protected:
|
||||
wxZRColaCharSelect *m_parent; ///< Thread owner
|
||||
} *m_searchThread; ///< Search thread
|
||||
};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Supports saving/restoring wxZRColaCharSelect state
|
||||
///
|
||||
|
@ -416,7 +416,7 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
|
||||
wxStaticBoxSizer* sbSizerBrowse;
|
||||
sbSizerBrowse = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("&Browse") ), wxVERTICAL );
|
||||
|
||||
m_search = new wxSearchCtrl( sbSizerBrowse->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||
m_search = new wxSearchCtrl( sbSizerBrowse->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifndef __WXMAC__
|
||||
m_search->ShowSearchButton( true );
|
||||
#endif
|
||||
@ -610,12 +610,10 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
|
||||
this->SetSizer( bSizerContent );
|
||||
this->Layout();
|
||||
bSizerContent->Fit( this );
|
||||
m_timerSearch.SetOwner( this, wxID_TIMER_SEARCH );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
|
||||
m_search->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
|
||||
m_search->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchEnter ), NULL, this );
|
||||
m_categories->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
|
||||
m_gridResults->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
|
||||
m_gridResults->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
|
||||
@ -626,7 +624,6 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
|
||||
m_unicode->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
|
||||
m_gridRelated->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
|
||||
m_sdbSizerButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
|
||||
this->Connect( wxID_TIMER_SEARCH, wxEVT_TIMER, wxTimerEventHandler( wxZRColaCharSelectBase::OnSearchTimer ) );
|
||||
}
|
||||
|
||||
wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
||||
@ -634,7 +631,6 @@ wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
|
||||
m_search->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
|
||||
m_search->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchEnter ), NULL, this );
|
||||
m_categories->Disconnect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
|
||||
m_gridResults->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
|
||||
m_gridResults->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
|
||||
@ -645,6 +641,5 @@ wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
||||
m_unicode->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
|
||||
m_gridRelated->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
|
||||
m_sdbSizerButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
|
||||
this->Disconnect( wxID_TIMER_SEARCH, wxEVT_TIMER, wxTimerEventHandler( wxZRColaCharSelectBase::OnSearchTimer ) );
|
||||
|
||||
}
|
||||
|
@ -186,11 +186,6 @@ class wxZRColaCharSelectBase : public wxDialog
|
||||
private:
|
||||
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
wxID_TIMER_SEARCH = 1000
|
||||
};
|
||||
|
||||
wxSearchCtrl* m_search;
|
||||
wxCheckListBox* m_categories;
|
||||
wxZRColaCharGrid* m_gridResults;
|
||||
@ -203,12 +198,10 @@ class wxZRColaCharSelectBase : public wxDialog
|
||||
wxStdDialogButtonSizer* m_sdbSizerButtons;
|
||||
wxButton* m_sdbSizerButtonsOK;
|
||||
wxButton* m_sdbSizerButtonsCancel;
|
||||
wxTimer m_timerSearch;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
|
||||
virtual void OnSearchText( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSearchEnter( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCategoriesToggle( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnResultCellDClick( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnResultSelectCell( wxGridEvent& event ) { event.Skip(); }
|
||||
@ -219,7 +212,6 @@ class wxZRColaCharSelectBase : public wxDialog
|
||||
virtual void OnUnicodeText( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRelatedSelectCell( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSearchTimer( wxTimerEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
@ -234,8 +234,10 @@ namespace ZRCola {
|
||||
/// \param[in ] cats Set of categories, character must be a part of
|
||||
/// \param[inout] hits (character, count) map to append full-word hits to
|
||||
/// \param[inout] hits_sub (character, count) map to append partial-word hits to
|
||||
/// \param[in] fn_abort Pointer to function to periodically test for search cancellation
|
||||
/// \param[in] cookie Cookie for \p fn_abort call
|
||||
///
|
||||
void Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub) const;
|
||||
bool Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie) = NULL, _In_opt_ void *cookie = NULL) const;
|
||||
|
||||
///
|
||||
/// Get character category
|
||||
|
@ -20,15 +20,17 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub) const
|
||||
bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie), _In_opt_ void *cookie) const
|
||||
{
|
||||
assert(str);
|
||||
|
||||
while (*str) {
|
||||
if (fn_abort && fn_abort(cookie)) return false;
|
||||
|
||||
// Skip white space.
|
||||
for (;;) {
|
||||
if (*str == 0)
|
||||
return;
|
||||
return true;
|
||||
else if (!iswspace(*str))
|
||||
break;
|
||||
else
|
||||
@ -59,15 +61,20 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
|
||||
}
|
||||
|
||||
if (!term.empty()) {
|
||||
if (fn_abort && fn_abort(cookie)) return false;
|
||||
|
||||
// Find the term.
|
||||
std::transform(term.begin(), term.end(), term.begin(), std::towlower);
|
||||
|
||||
if (fn_abort && fn_abort(cookie)) return false;
|
||||
|
||||
const wchar_t *data;
|
||||
size_t len;
|
||||
|
||||
if (idxDsc.find(term.c_str(), term.size(), &data, &len)) {
|
||||
// The term was found.
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (fn_abort && fn_abort(cookie)) return false;
|
||||
wchar_t c = data[i];
|
||||
if (cats.find(GetCharCat(c)) != cats.end()) {
|
||||
std::map<wchar_t, unsigned long>::iterator idx = hits.find(c);
|
||||
@ -85,6 +92,7 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
|
||||
if (idxDscSub.find(term.c_str(), term.size(), &data, &len)) {
|
||||
// The term was found in the sub-term index.
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (fn_abort && fn_abort(cookie)) return false;
|
||||
wchar_t c = data[i];
|
||||
if (cats.find(GetCharCat(c)) != cats.end()) {
|
||||
std::map<wchar_t, unsigned long>::iterator idx = hits_sub.find(c);
|
||||
@ -100,4 +108,6 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user