diff --git a/lib/libZRCola/build/libZRCola.vcxproj b/lib/libZRCola/build/libZRCola.vcxproj index d83ae03..db326dd 100644 --- a/lib/libZRCola/build/libZRCola.vcxproj +++ b/lib/libZRCola/build/libZRCola.vcxproj @@ -30,6 +30,7 @@ Create Create + diff --git a/lib/libZRCola/build/libZRCola.vcxproj.filters b/lib/libZRCola/build/libZRCola.vcxproj.filters index 6a611b4..6075625 100644 --- a/lib/libZRCola/build/libZRCola.vcxproj.filters +++ b/lib/libZRCola/build/libZRCola.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + diff --git a/lib/libZRCola/include/zrcola/tag.h b/lib/libZRCola/include/zrcola/tag.h index c7b8220..ef46de4 100644 --- a/lib/libZRCola/include/zrcola/tag.h +++ b/lib/libZRCola/include/zrcola/tag.h @@ -291,6 +291,17 @@ namespace ZRCola { /// Constructs the database /// inline tagname_db() : idxName(data) {} + + /// + /// Search for tags by names + /// + /// \param[in ] str Search string + /// \param[in ] locale Locale to search tags in + /// \param[inout] hits (tag, count) map to append hits to + /// \param[in ] fn_abort Pointer to function to periodically test for search cancellation + /// \param[in ] cookie Cookie for \p fn_abort call + /// + bool Search(_In_z_ const wchar_t *str, _In_ LCID locale, _Inout_ std::map &hits, _In_opt_ bool (__cdecl *fn_abort)(void *cookie) = NULL, _In_opt_ void *cookie = NULL) const; }; diff --git a/lib/libZRCola/src/tag.cpp b/lib/libZRCola/src/tag.cpp new file mode 100644 index 0000000..4ff965b --- /dev/null +++ b/lib/libZRCola/src/tag.cpp @@ -0,0 +1,90 @@ +/* + Copyright 2015-2016 Amebis + + This file is part of ZRCola. + + ZRCola is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ZRCola is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ZRCola. If not, see . +*/ + +#include "stdafx.h" + + +bool ZRCola::tagname_db::Search(_In_z_ const wchar_t *str, _In_ LCID locale, _Inout_ std::map &hits, _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 true; + else if (!iswspace(*str)) + break; + else + str++; + } + + // Get name. + std::wstring name; + if (*str == L'"') { + const wchar_t *str_end = ++str; + for (;;) { + if (*str_end == 0) { + name.assign(str, str_end); + break; + } else if (*str_end == L'"') { + name.assign(str, str_end); + str_end++; + break; + } else + str_end++; + } + str = str_end; + } else { + const wchar_t *str_end = str + 1; + for (; *str_end && !iswspace(*str_end); str_end++); + name.assign(str, str_end); + str = str_end; + } + + if (!name.empty()) { + if (fn_abort && fn_abort(cookie)) return false; + + // Find the name. + std::unique_ptr tn(reinterpret_cast(new char[sizeof(tagname) + name.length()])); + tn->locale = locale; + wmemcpy(tn->name, name.data(), tn->name_len = (unsigned __int16)name.length()); + size_t start, end; + if (idxName.find(*tn, start, end)) { + // The name was found. + for (size_t i = start; i < end; i++) { + const tagname &name = idxName[i]; + if (fn_abort && fn_abort(cookie)) return false; + auto idx = hits.find(name.tag); + if (idx == hits.end()) { + // New tag. + hits.insert(std::make_pair(name.tag, 1)); + } else { + // Increase count for existing tag. + idx->second++; + } + } + } + } + } + + return true; +}