Hello community, here is the log from the commit of package nuspell for openSUSE:Factory checked in at 2020-07-15 15:03:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nuspell (Old) and /work/SRC/openSUSE:Factory/.nuspell.new.3060 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nuspell" Wed Jul 15 15:03:56 2020 rev:2 rq:820818 version:3.1.2 Changes: -------- --- /work/SRC/openSUSE:Factory/nuspell/nuspell.changes 2020-07-03 00:05:35.806712572 +0200 +++ /work/SRC/openSUSE:Factory/.nuspell.new.3060/nuspell.changes 2020-07-15 15:04:18.111368015 +0200 @@ -1,0 +2,17 @@ +Sat Jul 11 17:52:37 UTC 2020 - andy great <andythe_gr...@pm.me> + +- Update to version 3.1.2. + * Fixed: Internal refactorings that reduce function templates in + utils and finder. + * Changed: File utils.hxx is not installed any more. It is a + private header. + * Deprecated: Some functions for searching dictionaries in class + Finder are deprecated as they were searching in directories that + no longer contain dictionaries. + +------------------------------------------------------------------- +Sat Jul 11 17:49:40 UTC 2020 - andy great <andythe_gr...@pm.me> + +- Fix build for leap by enabling cmake rpath flag. + +------------------------------------------------------------------- Old: ---- nuspell-3.1.1.tar.gz New: ---- nuspell-3.1.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nuspell.spec ++++++ --- /var/tmp/diff_new_pack.8IIyJ6/_old 2020-07-15 15:04:19.331369204 +0200 +++ /var/tmp/diff_new_pack.8IIyJ6/_new 2020-07-15 15:04:19.335369209 +0200 @@ -19,8 +19,8 @@ %define sonum 3 %define libname libnuspell Name: nuspell -Version: 3.1.1 -Release: 1 +Version: 3.1.2 +Release: 0 Summary: A spell checker library and command-line tool License: LGPL-3.0-or-later Group: Productivity/Office/Other @@ -83,6 +83,7 @@ %build %cmake -DBUILD_SHARED_LIBS:BOOL=ON \ -DBUILD_TESTING:BOOL=ON \ + -DCMAKE_SKIP_RPATH:BOOL=OFF \ .. %cmake_build @@ -107,7 +108,7 @@ %files -n %{libname}%{sonum} %doc README.md CHANGELOG.md AUTHORS %license COPYING.LESSER COPYING -%{_libdir}/%{libname}.so.%{sonum}.1.0 +%{_libdir}/%{libname}.so.%{sonum}.1.2 %exclude %{_datadir}/doc/nuspell/README.md %files devel ++++++ nuspell-3.1.1.tar.gz -> nuspell-3.1.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/CHANGELOG.md new/nuspell-3.1.2/CHANGELOG.md --- old/nuspell-3.1.1/CHANGELOG.md 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/CHANGELOG.md 2020-07-01 13:34:17.000000000 +0200 @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.1.2] - 2020-07-01 +### Fixed +- Internal refactorings that reduce function templates in `utils` and `finder`. + +### Changed +- File `utils.hxx` is not installed any more. It is a private header. + +### Deprecated +- Some functions for searching dictionaries in class `Finder` are deprecated as + they were searching in directories that no longer contain dictionaries. + ## [3.1.1] - 2020-05-04 ### Changed - Updated description in README. Packagers are encouraged to update it in their @@ -112,7 +123,8 @@ - Spelling error detection (checking) is closely matching Hunspell - Support for spelling error correction (suggestions) -[Unreleased]: https://github.com/nuspell/nuspell/compare/v3.1.1...HEAD +[Unreleased]: https://github.com/nuspell/nuspell/compare/v3.1.2...HEAD +[3.1.2]: https://github.com/nuspell/nuspell/compare/v3.1.1...v3.1.2 [3.1.1]: https://github.com/nuspell/nuspell/compare/v3.1.0...v3.1.1 [3.1.0]: https://github.com/nuspell/nuspell/compare/v3.0.0...v3.1.0 [3.0.0]: https://github.com/nuspell/nuspell/compare/v2.3.0...v3.0.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/CMakeLists.txt new/nuspell-3.1.2/CMakeLists.txt --- old/nuspell-3.1.1/CMakeLists.txt 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/CMakeLists.txt 2020-07-01 13:34:17.000000000 +0200 @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.8) -project(nuspell VERSION 3.1.0) +project(nuspell VERSION 3.1.2) set(PROJECT_HOMEPAGE_URL "https://nuspell.github.io/") include(GNUInstallDirs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/CMakeLists.txt new/nuspell-3.1.2/src/nuspell/CMakeLists.txt --- old/nuspell-3.1.1/src/nuspell/CMakeLists.txt 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/CMakeLists.txt 2020-07-01 13:34:17.000000000 +0200 @@ -7,8 +7,7 @@ add_library(Nuspell::nuspell ALIAS nuspell) -get_target_property(nuspell_headers nuspell SOURCES) -list(FILTER nuspell_headers INCLUDE REGEX [=[.*\.hxx$]=]) +set(nuspell_headers aff_data.hxx dictionary.hxx finder.hxx structures.hxx) set_target_properties(nuspell PROPERTIES PUBLIC_HEADER "${nuspell_headers}" VERSION ${PROJECT_VERSION} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/aff_data.hxx new/nuspell-3.1.2/src/nuspell/aff_data.hxx --- old/nuspell-3.1.1/src/nuspell/aff_data.hxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/aff_data.hxx 2020-07-01 13:34:17.000000000 +0200 @@ -41,9 +41,9 @@ enum Enc_Type { SINGLEBYTE = false, UTF8 = true }; Encoding() = default; - Encoding(const std::string& e) : name(e) { normalize_name(); } - Encoding(std::string&& e) : name(move(e)) { normalize_name(); } - Encoding(const char* e) : name(e) { normalize_name(); } + explicit Encoding(const std::string& e) : name(e) { normalize_name(); } + explicit Encoding(std::string&& e) : name(move(e)) { normalize_name(); } + explicit Encoding(const char* e) : name(e) { normalize_name(); } auto& operator=(const std::string& e) { name = e; @@ -63,7 +63,6 @@ return *this; } auto empty() const { return name.empty(); } - operator const std::string&() const { return name; } auto& value() const { return name; } auto is_utf8() const { return name == "UTF-8"; } auto value_or_default() const -> std::string diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/dictionary.cxx new/nuspell-3.1.2/src/nuspell/dictionary.cxx --- old/nuspell-3.1.1/src/nuspell/dictionary.cxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/dictionary.cxx 2020-07-01 13:34:17.000000000 +0200 @@ -27,14 +27,6 @@ namespace nuspell { -#ifdef __GNUC__ -#define likely(expr) __builtin_expect(!!(expr), 1) -#define unlikely(expr) __builtin_expect(!!(expr), 0) -#else -#define likely(expr) (expr) -#define unlikely(expr) (expr) -#endif - using namespace std; using boost::make_iterator_range; @@ -2066,7 +2058,7 @@ auto static insert_sug_first(const wstring& word, List_WStrings& out) { - out.insert(begin(out), word); + out.insert(begin(out), word); } auto& operator|=(Dict_Base::High_Quality_Sugs& lhs, @@ -2953,7 +2945,7 @@ if (score < -100 && (old_num_sugs != out.size() || only_max_diff)) break; - if (any_of(begin(out), end(out), [& g = guess_word](auto& sug) { + if (any_of(begin(out), end(out), [&g = guess_word](auto& sug) { return g.find(sug) != g.npos; })) { if (score < -100) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/dictionary.hxx new/nuspell-3.1.2/src/nuspell/dictionary.hxx --- old/nuspell-3.1.1/src/nuspell/dictionary.hxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/dictionary.hxx 2020-07-01 13:34:17.000000000 +0200 @@ -43,7 +43,7 @@ operator Word_List::const_pointer() const { return root_word; } auto& operator*() const { return *root_word; } - auto operator-> () const { return root_word; } + auto operator->() const { return root_word; } }; template <class T1 = void, class T2 = void> @@ -83,7 +83,7 @@ bool affixed_and_modified = {}; /**< non-zero affix */ operator Word_List::const_pointer() const { return word_entry; } auto& operator*() const { return *word_entry; } - auto operator-> () const { return word_entry; } + auto operator->() const { return word_entry; } }; struct Dict_Base : public Aff_Data { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/finder.cxx new/nuspell-3.1.2/src/nuspell/finder.cxx --- old/nuspell-3.1.1/src/nuspell/finder.cxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/finder.cxx 2020-07-01 13:34:17.000000000 +0200 @@ -66,51 +66,38 @@ #endif /** - * @brief Gets the default search paths. - * - * @param out Output iterator, begin of the output range. - * @return End of the output range. + * @brief Adds the default directory paths to the list of search directories. */ -template <class OutIt> -auto get_default_search_paths(OutIt out) -> OutIt +auto Finder::add_default_dir_paths() -> void { - *out++ = "."; + paths.push_back("."); auto dicpath = getenv("DICPATH"); if (dicpath) { - out = split(string(dicpath), PATHSEP, out); + split(string(dicpath), PATHSEP, paths); } #ifdef _POSIX_VERSION auto home = getenv("HOME"); if (home) { - *out++ = home + string("/.local/share/hunspell"); + paths.push_back(home + string("/.local/share/hunspell")); } - *out++ = "/usr/local/share/hunspell"; - *out++ = "/usr/share/hunspell"; + paths.push_back("/usr/local/share/hunspell"); + paths.push_back("/usr/share/hunspell"); #if defined(__APPLE__) && defined(__MACH__) auto osx = string("/Library/Spelling"); if (home) { - *out++ = home + osx; + paths.push_back(home + osx); } - *out++ = osx; + paths.push_back(osx); #endif #endif #ifdef _WIN32 auto winpaths = {getenv("LOCALAPPDATA"), getenv("PROGRAMDATA")}; for (auto& p : winpaths) { if (p) { - *out++ = string(p) + "\\hunspell"; + paths.push_back(string(p) + "\\hunspell"); } } #endif - return out; -} - -/** - * @brief Adds the default directory paths which may containt dictionaries. - */ -auto Finder::add_default_dir_paths() -> void -{ - get_default_search_paths(back_inserter(paths)); } #ifdef _WIN32 @@ -252,13 +239,10 @@ } auto begin() -> const char* const* { return g.gl_pathv; } auto end() -> const char* const* { return begin() + g.gl_pathc; } - template <class OutIt> - auto copy_glob_paths(OutIt out) -> OutIt + auto append_glob_paths_to(vector<string>& out) -> void { - if (ret == 0) { - out = copy(begin(), end(), out); - } - return out; + if (ret == 0) + out.insert(out.end(), begin(), end()); } ~Globber() { globfree(&g); } }; @@ -285,7 +269,7 @@ auto q2 = q1; auto v = q1; - split_on_any_of(pattern, "\\/", back_inserter(v)); + split_on_any_of(pattern, "\\/", v); auto i = v.begin(); if (i == v.end()) return false; @@ -329,11 +313,9 @@ } auto begin() -> vector<string>::iterator { return data.begin(); } auto end() -> vector<string>::iterator { return data.end(); } - template <class OutIt> - auto copy_glob_paths(OutIt out) -> OutIt + auto append_glob_paths_to(vector<string>& out) -> void { - out = copy(begin(), end(), out); - return out; + out.insert(out.end(), begin(), end()); } }; #else @@ -345,99 +327,21 @@ auto glob(const string& pattern) -> bool { return false; } auto begin() -> char** { return nullptr; } auto end() -> char** { return nullptr; } - template <class OutIt> - auto copy_glob_paths(OutIt out) -> OutIt - { - return out; - } + auto append_glob_paths_to(vector<string>& out) -> void {} }; #endif /** - * @brief Gets the Mozilla search paths. - * - * @param out Output iterator, begin of the output range. - * @return End of the output range. - */ -template <class OutIt> -auto get_mozilla_paths(OutIt out) -> OutIt -{ -#ifdef _POSIX_VERSION - // add Mozilla Linux global path - auto dirs = {"/usr/local/lib/firefox/dictionaries", - "/usr/lib/firefox/dictionaries", - "/usr/local/lib/thunderbird/dictionaries", - "/usr/lib/thunderbird/dictionaries"}; - struct stat dir_stat; - for (auto& dir : dirs) { - if (lstat(dir, &dir_stat) == 0) { - if (S_ISDIR(dir_stat.st_mode)) { - *out++ = dir; - } - // if SYMLINK do not add - } - } - - // add Mozilla Linux user path - auto home = getenv("HOME"); - if (home == nullptr) { - return out; - } - auto moz = string(home); - moz += "/.mozilla/firefox/*/extensions/*/dictionaries"; - Globber g(moz); - out = g.copy_glob_paths(out); - - moz = home; - moz += "/.thunderbird/*/extensions/*/dictionaries"; - g.glob(moz); - out = g.copy_glob_paths(out); - -#elif defined(_WIN32) - // add Mozilla Windows global path - auto winpaths = {getenv("PROGRAMFILES"), getenv("PROGRAMFILES(x86)")}; - for (auto& p : winpaths) { - if (p) { - *out++ = string(p) + "\\Mozilla Firefox\\dictionaries"; - *out++ = - string(p) + "\\Mozilla Thunderbird\\dictionaries"; - } - } - // add Mozilla Windows local path - char* home = getenv("APPDATA"); - if (home == nullptr) { - return out; - } - string moz = home; - moz += "\\Mozilla\\Firefox\\Profiles\\*\\extensions\\*\\dictionaries"; - Globber g(moz); - out = g.copy_glob_paths(out); - - moz = home; - moz += - "\\Mozilla\\Thunderbird\\Profiles\\*\\extensions\\*\\dictionaries"; - g.glob(moz); - out = g.copy_glob_paths(out); -#endif - return out; -} - -/** - * Adds the Mozilla directory paths which may containt dictionaries. + * @brief Adds the Mozilla directory paths to the list of search directories. + * @deprecated Don't use this, Firefox does not offer unpacked dictionaries any + * more. They are all inside archive, either in omni.ja or in extension in .xpi. */ -auto Finder::add_mozilla_dir_paths() -> void -{ - get_mozilla_paths(back_inserter(paths)); -} +auto Finder::add_mozilla_dir_paths() -> void {} /** - * @brief Gets the LibreOffice search paths. - * - * @param out Output iterator, begin of the output range. - * @return End of the output range. + * @brief Adds the LibreOffice directory paths which may containt dictionaries. */ -template <class OutIt> -auto get_libreoffice_paths(OutIt out) -> OutIt +auto Finder::add_libreoffice_dir_paths() -> void { auto lo_user_glob = string(); #ifdef _POSIX_VERSION @@ -446,15 +350,14 @@ "/opt/libreoffice*"}; for (auto& prefix : prefixes) { Globber g(string(prefix) + "/share/extensions/dict-*"); - out = g.copy_glob_paths(out); + g.append_glob_paths_to(paths); } // add LibreOffice Linux local auto home = getenv("HOME"); - if (home == nullptr) { - return out; - } + if (home == nullptr) + return; lo_user_glob = home; lo_user_glob += "/.config/libreoffice/?/user/uno_packages/cache" "/uno_packages/*/*.oxt/"; @@ -462,157 +365,69 @@ // add Libreoffice Windows global paths auto prefixes = {getenv("PROGRAMFILES"), getenv("PROGRAMFILES(x86)")}; for (auto& prefix : prefixes) { - if (prefix == nullptr) { + if (prefix == nullptr) continue; - } Globber g(string(prefix) + "\\LibreOffice ?\\share\\extensions\\dict-*"); - out = g.copy_glob_paths(out); + g.append_glob_paths_to(paths); } auto home = getenv("APPDATA"); - if (home == nullptr) { - return out; - } + if (home == nullptr) + return; lo_user_glob = home; lo_user_glob += "\\libreoffice\\?\\user\\uno_packages\\cache" "\\uno_packages\\*\\*.oxt\\"; #else - return out; + return; #endif // finish adding LibreOffice user path dicts (Linux and Windows) Globber g(lo_user_glob + "dict*"); - out = g.copy_glob_paths(out); + g.append_glob_paths_to(paths); g.glob(lo_user_glob + "*.aff"); auto path_str = string(); for (auto& path : g) { path_str = path; path_str.erase(path_str.rfind(DIRSEP)); - *out = path_str; - ++out; + paths.push_back(path_str); } - return out; } /** - * @brief Adds the LibreOffice directory paths which may containt dictionaries. + * @brief Adds the OpenOffice directory paths to the list of search directories. + * @deprecated Does nothing now, please switch to Libreoffice. */ -auto Finder::add_libreoffice_dir_paths() -> void -{ - get_libreoffice_paths(back_inserter(paths)); -} - -/** - * @brief Gets the Apache OpenOffice search paths. - * - * @param out Output iterator, begin of the output range. - * @return End of the output range. - */ -template <class OutIt> -auto get_openoffice_paths(OutIt out) -> OutIt -{ - // Note that Apache OpenOffice is no longer available on Debian and - // Ubuntu. For legacy reasons, all paths are still supported. - auto aoo_user_glob = string(); -#ifdef _POSIX_VERSION - // add Apache OpenOffice Linux global paths - auto prefixes = {"/usr/local/lib/openoffice", "/usr/lib/openoffice", - "/opt/openoffice*"}; - for (auto& prefix : prefixes) { - Globber g(string(prefix) + "/share/extensions/dict-*"); - out = g.copy_glob_paths(out); - } - - // add Apache OpenOffice Linux local - - auto home = getenv("HOME"); - if (home == nullptr) { - return out; - } - aoo_user_glob = home; - aoo_user_glob += "/.config/openoffice/?/user/uno_packages/cache" - "/uno_packages/*/*.oxt/"; -#elif defined(_WIN32) - // add Apache OpenOffice Windows global paths - auto prefixes = {getenv("PROGRAMFILES"), getenv("PROGRAMFILES(x86)")}; - for (auto& prefix : prefixes) { - if (prefix == nullptr) { - continue; - } - Globber g(string(prefix) + - "\\OpenOffice ?\\share\\extensions\\dict-*"); - out = g.copy_glob_paths(out); - } - - auto home = getenv("APPDATA"); - if (home == nullptr) { - return out; - } - aoo_user_glob = home; - aoo_user_glob += "\\openoffice\\?\\user\\uno_packages\\cache" - "\\uno_packages\\*\\*.oxt\\"; -#else - return out; -#endif - // finish adding Apache OpenOffice user path dicts (Linux and Windows) - Globber g(aoo_user_glob + "dict*"); - out = g.copy_glob_paths(out); - - g.glob(aoo_user_glob + "*.aff"); - string path_str; - for (auto& path : g) { - path_str = path; - path_str.erase(path_str.rfind(DIRSEP)); - *out = path_str; - ++out; - } - return out; -} - -/** - * @brief Adds the OpenOffice directory paths which may containt dictionaries. - */ -auto Finder::add_openoffice_dir_paths() -> void -{ - get_openoffice_paths(back_inserter(paths)); -} +auto Finder::add_openoffice_dir_paths() -> void {} /** * @brief Searches directory for dictionaries. * * @param dir directory path. - * @param out output iter where to append the found dictionary names. - * @return end of the output range + * @param out vector where to append the found dictionary names. */ -template <class OutIt> -auto search_path_for_dicts(const string& dir, OutIt out) -> OutIt +auto static search_path_for_dicts(const string& dir, + vector<pair<string, string>>& out) -> void { Directory d; - if (d.open(dir) == false) { - return out; - } + if (d.open(dir) == false) + return; + unordered_set<string> dics; string file_name; - while (d.next()) { // Ideally process file names in alphabetical - // order, output is now: - // nl_BE /usr/share/hunspell/nl_BE - // en_US /usr/share/hunspell/en_US - // nl_NL /usr/share/hunspell/nl_NL - // en_GB /usr/share/hunspell/en_GB + while (d.next()) { file_name = d.entry_name(); auto sz = file_name.size(); - if (sz < 4) { + if (sz < 4) continue; - } + if (file_name.compare(sz - 4, 4, ".dic") == 0) { dics.insert(file_name); file_name.replace(sz - 4, 4, ".aff"); if (dics.count(file_name)) { file_name.erase(sz - 4); auto full_path = dir + DIRSEP + file_name; - *out = make_pair(file_name, full_path); - out++; + out.emplace_back(file_name, full_path); } } else if (file_name.compare(sz - 4, 4, ".aff") == 0) { @@ -621,12 +436,10 @@ if (dics.count(file_name)) { file_name.erase(sz - 4); auto full_path = dir + DIRSEP + file_name; - *out = make_pair(file_name, full_path); - out++; + out.emplace_back(file_name, full_path); } } } - return out; } /** @@ -636,7 +449,7 @@ { dictionaries.clear(); for (auto& path : paths) { - search_path_for_dicts(path, back_inserter(dictionaries)); + search_path_for_dicts(path, dictionaries); } stable_sort(dictionaries.begin(), dictionaries.end(), [](auto& a, auto& b) { return a.first < b.first; }); @@ -650,9 +463,7 @@ { auto ret = Finder(); ret.add_default_dir_paths(); - ret.add_mozilla_dir_paths(); ret.add_libreoffice_dir_paths(); - ret.add_openoffice_dir_paths(); ret.search_for_dictionaries(); return ret; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/finder.hxx new/nuspell-3.1.2/src/nuspell/finder.hxx --- old/nuspell-3.1.1/src/nuspell/finder.hxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/finder.hxx 2020-07-01 13:34:17.000000000 +0200 @@ -39,9 +39,9 @@ using const_iterator = Dict_List::const_iterator; auto add_default_dir_paths() -> void; - auto add_mozilla_dir_paths() -> void; + [[deprecated]] auto add_mozilla_dir_paths() -> void; auto add_libreoffice_dir_paths() -> void; - auto add_openoffice_dir_paths() -> void; + [[deprecated]] auto add_openoffice_dir_paths() -> void; auto search_for_dictionaries() -> void; auto static search_all_dirs_for_dicts() -> Finder; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/structures.hxx new/nuspell-3.1.2/src/nuspell/structures.hxx --- old/nuspell-3.1.1/src/nuspell/structures.hxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/structures.hxx 2020-07-01 13:34:17.000000000 +0200 @@ -100,9 +100,9 @@ using const_reverse_iterator = typename Str::const_reverse_iterator; String_Set() = default; - String_Set(const Str& s) : d(s) { sort_uniq(); } - String_Set(Str&& s) : d(move(s)) { sort_uniq(); } - String_Set(const CharT* s) : d(s) { sort_uniq(); } + explicit String_Set(const Str& s) : d(s) { sort_uniq(); } + explicit String_Set(Str&& s) : d(move(s)) { sort_uniq(); } + explicit String_Set(const CharT* s) : d(s) { sort_uniq(); } template <class InputIterator> String_Set(InputIterator first, InputIterator last) : d(first, last) { @@ -319,8 +319,14 @@ public: Substr_Replacer() = default; - Substr_Replacer(const Table_Pairs& v) : table(v) { sort_uniq(); } - Substr_Replacer(Table_Pairs&& v) : table(move(v)) { sort_uniq(); } + explicit Substr_Replacer(const Table_Pairs& v) : table(v) + { + sort_uniq(); + } + explicit Substr_Replacer(Table_Pairs&& v) : table(move(v)) + { + sort_uniq(); + } auto& operator=(const Table_Pairs& v) { @@ -443,8 +449,11 @@ public: Break_Table() = default; - Break_Table(const Table_Str& v) : table(v) { order_entries(); } - Break_Table(Table_Str&& v) : table(move(v)) { order_entries(); } + explicit Break_Table(const Table_Str& v) : table(v) { order_entries(); } + explicit Break_Table(Table_Str&& v) : table(move(v)) + { + order_entries(); + } auto& operator=(const Table_Str& v) { @@ -683,9 +692,18 @@ public: Condition() = default; - Condition(const Str& condition) : cond(condition) { construct(); } - Condition(Str&& condition) : cond(move(condition)) { construct(); } - Condition(const CharT* condition) : cond(condition) { construct(); } + explicit Condition(const Str& condition) : cond(condition) + { + construct(); + } + explicit Condition(Str&& condition) : cond(move(condition)) + { + construct(); + } + explicit Condition(const CharT* condition) : cond(condition) + { + construct(); + } auto& operator=(const Str& condition) { cond = condition; @@ -827,8 +845,7 @@ } template <class CharT> -class Prefix { - public: +struct Prefix { using Str = std::basic_string<CharT>; using Cond = Condition<CharT>; using value_type = CharT; @@ -867,8 +884,7 @@ }; template <class CharT> -class Suffix { - public: +struct Suffix { using Str = std::basic_string<CharT>; using Cond = Condition<CharT>; using value_type = CharT; @@ -986,18 +1002,18 @@ public: Prefix_Multiset() = default; - Prefix_Multiset(Key_Extr ke, Key_Transform kt = {}) + explicit Prefix_Multiset(Key_Extr ke, Key_Transform kt = {}) : ebo{{ke}, {kt}, {}} { } - Prefix_Multiset(const Vector_Type& v, Key_Extr ke = {}, - Key_Transform kt = {}) + explicit Prefix_Multiset(const Vector_Type& v, Key_Extr ke = {}, + Key_Transform kt = {}) : ebo{{ke}, {kt}, v} { sort(); } - Prefix_Multiset(Vector_Type&& v, Key_Extr ke = {}, - Key_Transform kt = {}) + explicit Prefix_Multiset(Vector_Type&& v, Key_Extr ke = {}, + Key_Transform kt = {}) : ebo{{ke}, {kt}, std::move(v)} { sort(); @@ -1082,7 +1098,7 @@ return old; } auto& operator*() const { return *it; } - auto operator-> () const { return &*it; } + auto operator->() const { return &*it; } auto operator==(const Iter_Prefixes_Of& other) const { return valid == other.valid; @@ -1223,7 +1239,10 @@ public: Reversed_String_View() = default; - Reversed_String_View(const Str& s) : first(s.rbegin()), sz(s.size()) {} + explicit Reversed_String_View(const Str& s) + : first(s.rbegin()), sz(s.size()) + { + } Reversed_String_View(Str&& s) = delete; auto& operator[](size_type i) const { return first[i]; } auto size() const { return sz; } @@ -1277,8 +1296,11 @@ public: Prefix_Table() = default; - Prefix_Table(const Vector_Type& t) : table(t) { populate(); } - Prefix_Table(Vector_Type&& t) : table(std::move(t)) { populate(); } + explicit Prefix_Table(const Vector_Type& t) : table(t) { populate(); } + explicit Prefix_Table(Vector_Type&& t) : table(std::move(t)) + { + populate(); + } auto& operator=(const Vector_Type& t) { table = t; @@ -1326,8 +1348,11 @@ public: Suffix_Table() = default; - Suffix_Table(const Vector_Type& t) : table(t) { populate(); } - Suffix_Table(Vector_Type&& t) : table(std::move(t)) { populate(); } + explicit Suffix_Table(const Vector_Type& t) : table(t) { populate(); } + explicit Suffix_Table(Vector_Type&& t) : table(std::move(t)) + { + populate(); + } auto& operator=(const Vector_Type& t) { table = t; @@ -1427,11 +1452,12 @@ public: Compound_Rule_Table() = default; - Compound_Rule_Table(const std::vector<std::u16string>& tbl) : rules(tbl) + explicit Compound_Rule_Table(const std::vector<std::u16string>& tbl) + : rules(tbl) { fill_all_flags(); } - Compound_Rule_Table(std::vector<std::u16string>&& tbl) + explicit Compound_Rule_Table(std::vector<std::u16string>&& tbl) : rules(move(tbl)) { fill_all_flags(); @@ -2014,8 +2040,14 @@ public: Replacement_Table() = default; - Replacement_Table(const Table_Str& v) : table(v) { order_entries(); } - Replacement_Table(Table_Str&& v) : table(move(v)) { order_entries(); } + explicit Replacement_Table(const Table_Str& v) : table(v) + { + order_entries(); + } + explicit Replacement_Table(Table_Str&& v) : table(move(v)) + { + order_entries(); + } auto& operator=(const Table_Str& v) { @@ -2094,7 +2126,7 @@ auto parse(const Str& s) -> void; Similarity_Group() = default; - Similarity_Group(const Str& s) { parse(s); } + explicit Similarity_Group(const Str& s) { parse(s); } auto& operator=(const Str& s) { parse(s); @@ -2144,8 +2176,14 @@ public: Phonetic_Table() = default; - Phonetic_Table(const std::vector<Pair_Str>& v) : table(v) { order(); } - Phonetic_Table(std::vector<Pair_Str>&& v) : table(move(v)) { order(); } + explicit Phonetic_Table(const std::vector<Pair_Str>& v) : table(v) + { + order(); + } + explicit Phonetic_Table(std::vector<Pair_Str>&& v) : table(move(v)) + { + order(); + } auto& operator=(const std::vector<Pair_Str>& v) { table = v; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/utils.cxx new/nuspell-3.1.2/src/nuspell/utils.cxx --- old/nuspell-3.1.1/src/nuspell/utils.cxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/utils.cxx 2020-07-01 13:34:17.000000000 +0200 @@ -18,6 +18,7 @@ #include "utils.hxx" +#include <algorithm> #include <limits> #include <boost/locale/utf8_codecvt.hpp> @@ -37,18 +38,60 @@ namespace nuspell { using namespace std; -#ifdef __GNUC__ -#define likely(expr) __builtin_expect(!!(expr), 1) -#define unlikely(expr) __builtin_expect(!!(expr), 0) -#else -#define likely(expr) (expr) -#define unlikely(expr) (expr) -#endif +template <class SepT> +static auto& split_on_any_of_low(const std::string& s, const SepT& sep, + std::vector<std::string>& out) +{ + size_t i1 = 0; + size_t i2; + do { + i2 = s.find_first_of(sep, i1); + out.push_back(s.substr(i1, i2 - i1)); + i1 = i2 + 1; // we can only add +1 if sep is single char. + + // i2 gets s.npos after the last separator. + // Length of i2-i1 will always go past the end. That is defined. + } while (i2 != s.npos); + return out; +} + +/** + * @brief Splits string on single char seperator. + * + * Consecutive separators are treated as separate and will emit empty strings. + * + * @param s string to split. + * @param sep char that acts as separator to split on. + * @param out vector where separated strings are appended. + * @return @p out. + */ +auto split(const std::string& s, char sep, std::vector<std::string>& out) + -> std::vector<std::string>& +{ + return split_on_any_of_low(s, sep, out); +} + +/** + * @brief Splits string on set of single char seperators. + * + * Consecutive separators are treated as separate and will emit empty strings. + * + * @param s string to split. + * @param sep seperator(s) to split on. + * @param out vector where separated strings are appended. + * @return @p out. + */ +auto split_on_any_of(const std::string& s, const char* sep, + std::vector<std::string>& out) -> std::vector<std::string>& +{ + return split_on_any_of_low(s, sep, out); +} enum class Utf_Error_Handling { ALWAYS_VALID, REPLACE, SKIP }; template <Utf_Error_Handling eh, class InChar, class OutContainer> -auto utf_to_utf(const std::basic_string<InChar>& in, OutContainer& out) -> bool +auto static utf_to_utf(const std::basic_string<InChar>& in, OutContainer& out) + -> bool { using OutChar = typename OutContainer::value_type; using namespace boost::locale::utf; @@ -99,15 +142,15 @@ } template <class InChar, class OutContainer> -auto valid_utf_to_utf(const std::basic_string<InChar>& in, OutContainer& out) - -> void +auto static valid_utf_to_utf(const std::basic_string<InChar>& in, + OutContainer& out) -> void { utf_to_utf<Utf_Error_Handling::ALWAYS_VALID>(in, out); } template <class InChar, class OutContainer> -auto utf_to_utf_my(const std::basic_string<InChar>& in, OutContainer& out) - -> bool +auto static utf_to_utf_my(const std::basic_string<InChar>& in, + OutContainer& out) -> bool { return utf_to_utf<Utf_Error_Handling::REPLACE>(in, out); } @@ -157,15 +200,17 @@ return utf_to_utf_my(in, out); } -auto is_ascii(char c) -> bool { return static_cast<unsigned char>(c) <= 127; } +auto static is_ascii(char c) -> bool +{ + return static_cast<unsigned char>(c) <= 127; +} auto is_all_ascii(const std::string& s) -> bool { return all_of(begin(s), end(s), is_ascii); } -template <class CharT> -auto widen_latin1(char c) -> CharT +auto static widen_latin1(char c) -> char16_t { return static_cast<unsigned char>(c); } @@ -179,10 +224,10 @@ auto latin1_to_ucs2(const std::string& s, std::u16string& out) -> void { out.resize(s.size()); - transform(begin(s), end(s), begin(out), widen_latin1<char16_t>); + transform(begin(s), end(s), begin(out), widen_latin1); } -auto is_surrogate_pair(char16_t c) -> bool +auto static is_surrogate_pair(char16_t c) -> bool { return 0xD800 <= c && c <= 0xDFFF; } @@ -518,8 +563,58 @@ return out; } -auto count_appereances_of(const wstring& haystack, const wstring& needles) - -> size_t +auto replace_char(wstring& s, wchar_t from, wchar_t to) -> void +{ + for (auto i = s.find(from); i != s.npos; i = s.find(from, i + 1)) { + s[i] = to; + } +} + +auto erase_chars(wstring& s, wstring_view erase_chars) -> void +{ + if (erase_chars.empty()) + return; + auto is_erasable = [&](auto c) { + return erase_chars.find(c) != erase_chars.npos; + }; + auto it = remove_if(begin(s), end(s), is_erasable); + s.erase(it, end(s)); + return; +} + +/** + * @brief Tests if word is a number. + * + * Allow numbers with dots ".", dashes "-" and commas ",", but forbids double + * separators such as "..", "--" and ".,". This implementation increases + * performance over the regex implementation in the standard library. + */ +auto is_number(wstring_view s) -> bool +{ + if (s.empty()) + return false; + + auto it = begin(s); + if (s[0] == '-') + ++it; + while (it != end(s)) { + auto next = std::find_if( + it, end(s), [](auto c) { return c < '0' || c > '9'; }); + if (next == it) + return false; + if (next == end(s)) + return true; + it = next; + auto c = *it; + if (c == '.' || c == ',' || c == '-') + ++it; + else + return false; + } + return false; +} + +auto count_appereances_of(wstring_view haystack, wstring_view needles) -> size_t { return std::count_if(begin(haystack), end(haystack), [&](auto c) { return needles.find(c) != needles.npos; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/src/nuspell/utils.hxx new/nuspell-3.1.2/src/nuspell/utils.hxx --- old/nuspell-3.1.1/src/nuspell/utils.hxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/src/nuspell/utils.hxx 2020-07-01 13:34:17.000000000 +0200 @@ -24,10 +24,11 @@ #ifndef NUSPELL_UTILS_HXX #define NUSPELL_UTILS_HXX -#include "structures.hxx" - -#include <locale> #include <clocale> +#include <locale> +#include <string> +#include <string_view> +#include <vector> #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || \ (defined(__APPLE__) && defined(__MACH__))) @@ -36,10 +37,24 @@ #include <unicode/locid.h> +#ifdef __GNUC__ +#define likely(expr) __builtin_expect(!!(expr), 1) +#define unlikely(expr) __builtin_expect(!!(expr), 0) +#else +#define likely(expr) (expr) +#define unlikely(expr) (expr) +#endif + struct UConverter; // unicode/ucnv.h namespace nuspell { +auto split(const std::string& s, char sep, std::vector<std::string>& out) + -> std::vector<std::string>&; +auto split_on_any_of(const std::string& s, const char* sep, + std::vector<std::string>& out) + -> std::vector<std::string>&; + auto wide_to_utf8(const std::wstring& in, std::string& out) -> void; auto wide_to_utf8(const std::wstring& in) -> std::string; @@ -49,7 +64,6 @@ auto utf8_to_16(const std::string& in) -> std::u16string; auto utf8_to_16(const std::string& in, std::u16string& out) -> bool; -auto is_ascii(char c) -> bool; auto is_all_ascii(const std::string& s) -> bool; auto latin1_to_ucs2(const std::string& s) -> std::u16string; @@ -181,110 +195,11 @@ }; #endif -/** - * @brief Splits string on set of single char seperators. - * - * Consecutive separators are treated as separate and will emit empty strings. - * - * @param s string to split. - * @param sep seperator(s) to split on. - * @param out start of the output range where separated strings are - * appended. - * @return The end of the output range where separated strings are appended. - */ -template <class CharT, class SepT, class OutIt> -auto split_on_any_of(const std::basic_string<CharT>& s, const SepT& sep, - OutIt out) -{ - using size_type = typename std::basic_string<CharT>::size_type; - size_type i1 = 0; - size_type i2; - do { - i2 = s.find_first_of(sep, i1); - *out++ = s.substr(i1, i2 - i1); - i1 = i2 + 1; // we can only add +1 if sep is single char. - - // i2 gets s.npos after the last separator. - // Length of i2-i1 will always go past the end. That is defined. - } while (i2 != s.npos); - return out; -} - -/** - * @brief Splits string on single char seperator. - * - * Consecutive separators are treated as separate and will emit empty strings. - * - * @param s string to split. - * @param sep char that acts as separator to split on. - * @param out start of the output range where separated strings are - * appended. - * @return The iterator that indicates the end of the output range. - */ -template <class CharT, class OutIt> -auto split(const std::basic_string<CharT>& s, CharT sep, OutIt out) -{ - return split_on_any_of(s, sep, out); -} - -template <class CharT> -auto& erase_chars(std::basic_string<CharT>& s, - const std::basic_string<CharT>& erase_chars) -{ - if (erase_chars.empty()) - return s; - auto is_erasable = [&](CharT c) { - return erase_chars.find(c) != erase_chars.npos; - }; - auto it = remove_if(begin(s), end(s), is_erasable); - s.erase(it, end(s)); - return s; -} - -template <class CharT> -auto& replace_char(std::basic_string<CharT>& s, CharT from, CharT to) -{ - for (auto i = s.find(from); i != s.npos; i = s.find(from, i + 1)) { - s[i] = to; - } - return s; -} - -/** - * @brief Tests if word is a number. - * - * Allow numbers with dots ".", dashes "-" and commas ",", but forbids double - * separators such as "..", "--" and ".,". This implementation increases - * performance over the regex implementation in the standard library. - */ -template <class CharT> -auto is_number(const std::basic_string<CharT>& s) -> bool -{ - if (s.empty()) - return false; - - auto it = begin(s); - if (s[0] == '-') - ++it; - while (it != end(s)) { - auto next = find_if(it, end(s), - [](auto c) { return c < '0' || c > '9'; }); - if (next == it) - return false; - if (next == end(s)) - return true; - it = next; - auto c = *it; - if (c == '.' || c == ',' || c == '-') - ++it; - else - return false; - } - return false; -} - -auto count_appereances_of(const std::wstring& haystack, - const std::wstring& needles) -> size_t; +auto replace_char(std::wstring& s, wchar_t from, wchar_t to) -> void; +auto erase_chars(std::wstring& s, std::wstring_view erase_chars) -> void; +auto is_number(std::wstring_view s) -> bool; +auto count_appereances_of(std::wstring_view haystack, std::wstring_view needles) + -> size_t; auto inline begins_with(std::wstring_view haystack, std::wstring_view needle) -> bool @@ -309,6 +224,5 @@ { return x.data() + x.size(); } - } // namespace nuspell #endif // NUSPELL_UTILS_HXX diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/tests/dictionary_test.cxx new/nuspell-3.1.2/tests/dictionary_test.cxx --- old/nuspell-3.1.1/tests/dictionary_test.cxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/tests/dictionary_test.cxx 2020-07-01 13:34:17.000000000 +0200 @@ -60,7 +60,8 @@ d.words.emplace(L"May", u"T"); d.words.emplace(L"vary", u""); - d.suffixes = {{u'T', true, L"y", L"ies", Flag_Set(), L".[^aeiou]y"}}; + d.suffixes = {{u'T', true, L"y", L"ies", Flag_Set(), + Condition<wchar_t>(L".[^aeiou]y")}}; auto good = {L"berry", L"Berry", L"berries", L"BERRIES", L"May", L"MAY", L"vary"}; @@ -77,8 +78,10 @@ auto d = Dict_Test(); d.words.emplace(L"drink", u"X"); - d.suffixes = {{u'Y', true, L"", L"s", Flag_Set(), L"."}, - {u'X', true, L"", L"able", Flag_Set(u"Y"), L"."}}; + d.suffixes = { + {u'Y', true, L"", L"s", Flag_Set(), Condition<wchar_t>(L".")}, + {u'X', true, L"", L"able", Flag_Set(u"Y"), + Condition<wchar_t>(L".")}}; auto good = {L"drink", L"drinkable", L"drinkables"}; for (auto& g : good) @@ -98,12 +101,14 @@ d.words.emplace(L"aa", u"ABC"); d.words.emplace(L"bb", u"XYZ"); - d.prefixes = {{u'A', true, L"", L"W", Flag_Set(u"B"), L"aa"}, - {u'B', true, L"", L"Q", Flag_Set(u"C"), L"Wa"}, - {u'X', true, L"b", L"1", Flag_Set(u"Y"), L"b"}, - {u'Z', true, L"", L"3", Flag_Set(), L"1"}}; - d.suffixes = {{u'C', true, L"", L"E", Flag_Set(), L"a"}, - {u'Y', true, L"", L"2", Flag_Set(u"Z"), L"b"}}; + d.prefixes = { + {u'A', true, L"", L"W", Flag_Set(u"B"), Condition<wchar_t>(L"aa")}, + {u'B', true, L"", L"Q", Flag_Set(u"C"), Condition<wchar_t>(L"Wa")}, + {u'X', true, L"b", L"1", Flag_Set(u"Y"), Condition<wchar_t>(L"b")}, + {u'Z', true, L"", L"3", Flag_Set(), Condition<wchar_t>(L"1")}}; + d.suffixes = { + {u'C', true, L"", L"E", Flag_Set(), Condition<wchar_t>(L"a")}, + {u'Y', true, L"", L"2", Flag_Set(u"Z"), Condition<wchar_t>(L"b")}}; // complex strip suffix prefix prefix CHECK(d.spell_priv(L"QWaaE") == true); // complex strip prefix suffix prefix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/tests/structures_test.cxx new/nuspell-3.1.2/tests/structures_test.cxx --- old/nuspell-3.1.1/tests/structures_test.cxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/tests/structures_test.cxx 2020-07-01 13:34:17.000000000 +0200 @@ -61,10 +61,11 @@ TEST_CASE("String_Set::begin end", "[structures]") { - auto ss1 = String_Set<char16_t>(); + using U16Str_Set = String_Set<char16_t>; + auto ss1 = U16Str_Set(); ss1.insert(u"aa"); ss1.insert(u"bb"); - CHECK(ss1 == u"ab"); + CHECK(ss1 == U16Str_Set(u"ab")); auto b = ss1.begin(); auto e = ss1.end(); @@ -422,7 +423,8 @@ TEST_CASE("Prefix", "[structures]") { - auto pfx_tests = Prefix<char>{u'U', true, "", "un", {}, "wr."}; + auto pfx_tests = + Prefix<char>{u'U', true, "", "un", {}, Condition<char>("wr.")}; auto word = string("unwry"); CHECK("wry" == pfx_tests.to_root(word)); CHECK("wry" == word); @@ -445,7 +447,8 @@ TEST_CASE("Suffix", "[structures]") { - auto sfx_tests = Suffix<char>{u'T', true, "y", "ies", {}, ".[^aeiou]y"}; + auto sfx_tests = Suffix<char>{ + u'T', true, "y", "ies", {}, Condition<char>(".[^aeiou]y")}; auto word = string("wries"); CHECK("wry" == sfx_tests.to_root(word)); CHECK("wry" == word); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nuspell-3.1.1/tests/utils_test.cxx new/nuspell-3.1.2/tests/utils_test.cxx --- old/nuspell-3.1.1/tests/utils_test.cxx 2020-05-04 22:26:13.000000000 +0200 +++ new/nuspell-3.1.2/tests/utils_test.cxx 2020-07-01 13:34:17.000000000 +0200 @@ -24,13 +24,6 @@ using namespace std; using namespace nuspell; -TEST_CASE("is_ascii", "[locale_utils]") -{ - CHECK(is_ascii('a')); - CHECK(is_ascii('\t')); - CHECK_FALSE(is_ascii('\x80')); -} - TEST_CASE("is_all_ascii", "[locale_utils]") { CHECK(is_all_ascii("")); @@ -341,69 +334,69 @@ auto in = string("^abc;.qwe/zxc/"); auto exp = vector<string>{"", "abc", "", "qwe", "zxc", ""}; auto out = vector<string>(); - split_on_any_of(in, ".;^/", back_inserter(out)); + split_on_any_of(in, ".;^/", out); CHECK(exp == out); } TEST_CASE("is_number", "[string_utils]") { - CHECK_FALSE(is_number(""s)); - CHECK_FALSE(is_number("a"s)); - CHECK_FALSE(is_number("1a"s)); - CHECK_FALSE(is_number("a1"s)); - CHECK_FALSE(is_number(".a"s)); - CHECK_FALSE(is_number("a."s)); - CHECK_FALSE(is_number(",a"s)); - CHECK_FALSE(is_number("a,"s)); - CHECK_FALSE(is_number("-a"s)); - CHECK_FALSE(is_number("a-"s)); - - CHECK_FALSE(is_number("1..1"s)); - CHECK_FALSE(is_number("1.,1"s)); - CHECK_FALSE(is_number("1.-1"s)); - CHECK_FALSE(is_number("1,.1"s)); - CHECK_FALSE(is_number("1,,1"s)); - CHECK_FALSE(is_number("1,-1"s)); - CHECK_FALSE(is_number("1-.1"s)); - CHECK_FALSE(is_number("1-,1"s)); - CHECK_FALSE(is_number("1--1"s)); - - CHECK(is_number("1,1111"s)); - CHECK(is_number("-1,1111"s)); - CHECK(is_number("1,1111.00"s)); - CHECK(is_number("-1,1111.00"s)); - CHECK(is_number("1.1111"s)); - CHECK(is_number("-1.1111"s)); - CHECK(is_number("1.1111,00"s)); - CHECK(is_number("-1.1111,00"s)); + CHECK_FALSE(is_number(L"")); + CHECK_FALSE(is_number(L"a")); + CHECK_FALSE(is_number(L"1a")); + CHECK_FALSE(is_number(L"a1")); + CHECK_FALSE(is_number(L".a")); + CHECK_FALSE(is_number(L"a.")); + CHECK_FALSE(is_number(L",a")); + CHECK_FALSE(is_number(L"a,")); + CHECK_FALSE(is_number(L"-a")); + CHECK_FALSE(is_number(L"a-")); + + CHECK_FALSE(is_number(L"1..1")); + CHECK_FALSE(is_number(L"1.,1")); + CHECK_FALSE(is_number(L"1.-1")); + CHECK_FALSE(is_number(L"1,.1")); + CHECK_FALSE(is_number(L"1,,1")); + CHECK_FALSE(is_number(L"1,-1")); + CHECK_FALSE(is_number(L"1-.1")); + CHECK_FALSE(is_number(L"1-,1")); + CHECK_FALSE(is_number(L"1--1")); + + CHECK(is_number(L"1,1111")); + CHECK(is_number(L"-1,1111")); + CHECK(is_number(L"1,1111.00")); + CHECK(is_number(L"-1,1111.00")); + CHECK(is_number(L"1.1111")); + CHECK(is_number(L"-1.1111")); + CHECK(is_number(L"1.1111,00")); + CHECK(is_number(L"-1.1111,00")); // below needs extra review - CHECK(is_number("1"s)); - CHECK(is_number("-1"s)); - CHECK_FALSE(is_number("1-"s)); - - CHECK_FALSE(is_number("1."s)); - CHECK_FALSE(is_number("-1."s)); - CHECK_FALSE(is_number("1.-"s)); - - CHECK_FALSE(is_number("1,"s)); - CHECK_FALSE(is_number("-1,"s)); - CHECK_FALSE(is_number("1,-"s)); - - CHECK(is_number("1.1"s)); - CHECK(is_number("-1.1"s)); - CHECK_FALSE(is_number("1.1-"s)); - - CHECK(is_number("1,1"s)); - CHECK(is_number("-1,1"s)); - CHECK_FALSE(is_number("1,1-"s)); - - CHECK_FALSE(is_number(".1"s)); - CHECK_FALSE(is_number("-.1"s)); - CHECK_FALSE(is_number(".1-"s)); - - CHECK_FALSE(is_number(",1"s)); - CHECK_FALSE(is_number("-,1"s)); - CHECK_FALSE(is_number(",1-"s)); + CHECK(is_number(L"1")); + CHECK(is_number(L"-1")); + CHECK_FALSE(is_number(L"1-")); + + CHECK_FALSE(is_number(L"1.")); + CHECK_FALSE(is_number(L"-1.")); + CHECK_FALSE(is_number(L"1.-")); + + CHECK_FALSE(is_number(L"1,")); + CHECK_FALSE(is_number(L"-1,")); + CHECK_FALSE(is_number(L"1,-")); + + CHECK(is_number(L"1.1")); + CHECK(is_number(L"-1.1")); + CHECK_FALSE(is_number(L"1.1-")); + + CHECK(is_number(L"1,1")); + CHECK(is_number(L"-1,1")); + CHECK_FALSE(is_number(L"1,1-")); + + CHECK_FALSE(is_number(L".1")); + CHECK_FALSE(is_number(L"-.1")); + CHECK_FALSE(is_number(L".1-")); + + CHECK_FALSE(is_number(L",1")); + CHECK_FALSE(is_number(L"-,1")); + CHECK_FALSE(is_number(L",1-")); }