diff --git a/CMakeLists.txt b/CMakeLists.txt index 42f81b28..04764845 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,10 @@ if (POLICY CMP0177) cmake_policy(SET CMP0177 OLD) endif() project(PIP) -set(PIP_MAJOR 4) -set(PIP_MINOR 8) +set(PIP_MAJOR 5) +set(PIP_MINOR 0) set(PIP_REVISION 0) -set(PIP_SUFFIX ) +set(PIP_SUFFIX _beta) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) @@ -371,6 +371,9 @@ set(PCRE2_BUILD_PCRE2_32 OFF) set(PCRE2_BUILD_PCRE2GREP OFF) set(PCRE2_BUILD_TESTS OFF) set(PCRE2_SHOW_REPORT OFF) +if (WIN32) + set (ZLIB_ROOT "${MINGW_INCLUDE}") +endif() add_subdirectory("3rd/pcre2" EXCLUDE_FROM_ALL) list(APPEND LIBS_MAIN pcre2-16-static) diff --git a/libs/main/io_devices/pidir.cpp b/libs/main/io_devices/pidir.cpp index 341b2446..bb0607b4 100644 --- a/libs/main/io_devices/pidir.cpp +++ b/libs/main/io_devices/pidir.cpp @@ -298,9 +298,9 @@ bool sort_compare(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) { //! также "." и "..". Возвращаются абсолютные пути. //! \attention Этот метод не читает содержимое директорий //! рекурсивно! -PIVector PIDir::entries() { - PIVector l; - if (!isExists()) return l; +PIVector PIDir::entries(const PIRegularExpression & regexp) { + if (!isExists()) return {}; + PIVector ret; PIString dp = absolutePath(); PIString p(dp); if (dp == ".") @@ -309,9 +309,9 @@ PIVector PIDir::entries() { dp += separator; // piCout << "start entries from" << p; #ifdef WINDOWS + PIFile::FileInfo fi; if (dp == separator) { char letters[1024]; - PIFile::FileInfo fi; DWORD ll = GetLogicalDriveStringsA(1023, letters); PIString clet; for (DWORD i = 0; i < ll; ++i) { @@ -319,7 +319,12 @@ PIVector PIDir::entries() { clet.resize(2); fi.path = clet; fi.flags = PIFile::FileInfo::Dir; - l << fi; + if (regexp.isValid()) { + if (regexp.match(fi.name())) { + ret << fi; + } + } else + ret << fi; clet.clear(); } else clet += PIChar(letters[i]); @@ -329,21 +334,27 @@ PIVector PIDir::entries() { piZeroMemory(fd); p += "\\*"; void * hf = FindFirstFileA((LPCSTR)(p.data()), &fd); - if (!hf) return l; + if (!hf) return ret; bool hdd = false; do { PIString fn(fd.cFileName); if (fn == "..") hdd = true; - l << PIFile::fileInfo(dp + fn); + fi = PIFile::fileInfo(dp + fn); + if (regexp.isValid()) { + if (regexp.match(fi.name())) { + ret << fi; + } + } else + ret << fi; piZeroMemory(fd); } while (FindNextFileA(hf, &fd) != 0); FindClose(hf); - l.sort(sort_compare); + ret.sort(sort_compare); if (!hdd) { PIFile::FileInfo fi; fi.path = ".."; fi.flags = PIFile::FileInfo::Dir | PIFile::FileInfo::DotDot; - l.push_front(fi); + ret.push_front(fi); } } @@ -356,7 +367,7 @@ PIVector PIDir::entries() { for (;;) { de = readdir(dir); if (!de) break; - l << PIFile::fileInfo(dp + PIString(de->d_name)); + ret << PIFile::fileInfo(dp + PIString(de->d_name)); } closedir(dir); } @@ -371,14 +382,14 @@ PIVector PIDir::entries() { versionsort); # endif for (int i = 0; i < cnt; ++i) { - l << PIFile::fileInfo(dp + PIString(list[i]->d_name)); + ret << PIFile::fileInfo(dp + PIString(list[i]->d_name)); free(list[i]); } free(list); # endif #endif // piCout << "end entries from" << p; - return l; + return ret; } @@ -394,7 +405,7 @@ PIVector PIDir::entries() { //! одним списком, сортированным по алфавиту. Список не содержит //! "." и "..". Возвращаются абсолютные пути, причём файлы //! располагаются после директорий. -PIVector PIDir::allEntries() { +PIVector PIDir::allEntries(const PIRegularExpression & regexp) { PIVector ret; PIVector dirs; PIStringList cdirs, ndirs; @@ -409,8 +420,14 @@ PIVector PIDir::allEntries() { if (de.isDir()) { dirs << de; ndirs << de.path; - } else + } else { + if (regexp.isValid()) { + if (!regexp.match(de.name())) { + continue; + } + } ret << de; + } } } cdirs = ndirs; @@ -516,8 +533,8 @@ PIDir PIDir::temporary() { } -PIVector PIDir::allEntries(const PIString & path) { - return PIDir(path).allEntries(); +PIVector PIDir::allEntries(const PIString & path, const PIRegularExpression & regexp) { + return PIDir(path).allEntries(regexp); } diff --git a/libs/main/io_devices/pidir.h b/libs/main/io_devices/pidir.h index 5d31e330..f97efdf8 100644 --- a/libs/main/io_devices/pidir.h +++ b/libs/main/io_devices/pidir.h @@ -27,6 +27,7 @@ #define PIDIR_H #include "pifile.h" +#include "piregularexpression.h" //! \ingroup IO @@ -104,11 +105,11 @@ public: //! \~english Returns this directory content //! \~russian Возвращает содержимое этой директории - PIVector entries(); + PIVector entries(const PIRegularExpression & regexp = {}); //! \~english Returns this directory content recursively //! \~russian Возвращает содержимое этой директории рекурсивно - PIVector allEntries(); + PIVector allEntries(const PIRegularExpression & regexp = {}); //! \~english Make this directory, recursively if "withParents" //! \~russian Создаёт эту директорию, рекурсивно если "withParents" @@ -155,7 +156,7 @@ public: //! \~english Returns directory "path" content recursively //! \~russian Возвращает содержимое директории "path" рекурсивно - static PIVector allEntries(const PIString & path); + static PIVector allEntries(const PIString & path, const PIRegularExpression & regexp = {}); //! \~english Returns if directory "path" exists //! \~russian Возвращает существует ли эта директория diff --git a/libs/main/literals/piliterals.h b/libs/main/literals/piliterals.h index 845d4ab6..88b58d59 100644 --- a/libs/main/literals/piliterals.h +++ b/libs/main/literals/piliterals.h @@ -12,7 +12,7 @@ */ /* PIP - Platform Independent Primitives - C++11 literals + C++11 literals Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify @@ -34,6 +34,7 @@ #include "piliterals_bytearray.h" #include "piliterals_bytes.h" +#include "piliterals_regularexpression.h" #include "piliterals_string.h" #include "piliterals_time.h" diff --git a/libs/main/literals/piliterals_regularexpression.h b/libs/main/literals/piliterals_regularexpression.h new file mode 100644 index 00000000..9e47b8f7 --- /dev/null +++ b/libs/main/literals/piliterals_regularexpression.h @@ -0,0 +1,46 @@ +/*! \file piliterals_regularexpression.h + * \ingroup Core + * \~\brief + * \~english PIRegularExpression C++11 literals + * \~russian C++11 суффиксы PIString + */ +/* + PIP - Platform Independent Primitives + PIRegularExpression C++11 literals + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PILITERALS_REGULAREXPRESSION_H +#define PILITERALS_REGULAREXPRESSION_H + +#include "piregularexpression.h" + +//! \~\brief +//! \~english PIRegularExpression from string pattern in PCRE2 format +//! \~russian PIRegularExpression из строки в формате PCRE2 +inline PIRegularExpression operator""_regex(const char * v, size_t sz) { + return PIRegularExpression(PIString::fromUTF8(v, sz)); +} + +//! \~\brief +//! \~english PIRegularExpression from string pattern in Glob format +//! \~russian PIRegularExpression из строки в формате Glob +inline PIRegularExpression operator""_glob(const char * v, size_t sz) { + return PIRegularExpression::fromGlob(PIString::fromUTF8(v, sz)); +} + + +#endif diff --git a/libs/main/text/piregularexpression.cpp b/libs/main/text/piregularexpression.cpp index 04bc4b74..cb0470c3 100644 --- a/libs/main/text/piregularexpression.cpp +++ b/libs/main/text/piregularexpression.cpp @@ -192,25 +192,8 @@ int PIRegularExpression::captureGroupIndex(const PIString & gname) const { } -PIRegularExpression::Matcher PIRegularExpression::matchIterator(PIString & subject, size_t offset) { - PIRegularExpression::Matcher ret(this); - ret.start_offset = offset; - ret.subject = &subject; - return ret; -} - - -PIRegularExpression::Matcher PIRegularExpression::matchIterator(PIString && subject, size_t offset) { - PIRegularExpression::Matcher ret(this); - ret.start_offset = offset; - ret.subject_own = std::move(subject); - ret.subject = &ret.subject_own; - return ret; -} - - -PIRegularExpression::Matcher PIRegularExpression::matchIterator(const PIString & subject, size_t offset) { - PIRegularExpression::Matcher ret(this); +PIRegularExpression::Matcher PIRegularExpression::matchIterator(const PIString & subject, size_t offset) const { + PIRegularExpression::Matcher ret(const_cast(this)); ret.start_offset = offset; ret.subject_own = subject; ret.subject = &ret.subject_own; @@ -218,27 +201,44 @@ PIRegularExpression::Matcher PIRegularExpression::matchIterator(const PIString & } -PIRegularExpression::Matcher PIRegularExpression::match(PIString & subject, size_t offset) { +PIRegularExpression::Matcher PIRegularExpression::matchIterator(PIString & subject, size_t offset) const { + PIRegularExpression::Matcher ret(const_cast(this)); + ret.start_offset = offset; + ret.subject = &subject; + return ret; +} + + +PIRegularExpression::Matcher PIRegularExpression::matchIterator(PIString && subject, size_t offset) const { + PIRegularExpression::Matcher ret(const_cast(this)); + ret.start_offset = offset; + ret.subject_own = std::move(subject); + ret.subject = &ret.subject_own; + return ret; +} + + +PIRegularExpression::Matcher PIRegularExpression::match(const PIString & subject, size_t offset) const { PIRegularExpression::Matcher ret = matchIterator(subject, offset); PRIVATE->match(ret); return ret; } -PIRegularExpression::Matcher PIRegularExpression::match(PIString && subject, size_t offset) { +PIRegularExpression::Matcher PIRegularExpression::match(PIString & subject, size_t offset) const { + PIRegularExpression::Matcher ret = matchIterator(subject, offset); + PRIVATE->match(ret); + return ret; +} + + +PIRegularExpression::Matcher PIRegularExpression::match(PIString && subject, size_t offset) const { PIRegularExpression::Matcher ret = matchIterator(std::move(subject), offset); PRIVATE->match(ret); return ret; } -PIRegularExpression::Matcher PIRegularExpression::match(const PIString & subject, size_t offset) { - PIRegularExpression::Matcher ret = matchIterator(subject, offset); - PRIVATE->match(ret); - return ret; -} - - PIRegularExpression::Matcher::Matcher(PIRegularExpression * p): parent(p) {} diff --git a/libs/main/text/piregularexpression.h b/libs/main/text/piregularexpression.h index bff92c71..e7bce887 100644 --- a/libs/main/text/piregularexpression.h +++ b/libs/main/text/piregularexpression.h @@ -103,13 +103,13 @@ public: PIString captureGroupName(int index) const; int captureGroupIndex(const PIString & gname) const; - Matcher match(const PIString & subject, size_t offset = 0); - Matcher match(PIString & subject, size_t offset = 0); - Matcher match(PIString && subject, size_t offset = 0); + Matcher match(const PIString & subject, size_t offset = 0) const; + Matcher match(PIString & subject, size_t offset = 0) const; + Matcher match(PIString && subject, size_t offset = 0) const; - Matcher matchIterator(const PIString & subject, size_t offset = 0); - Matcher matchIterator(PIString & subject, size_t offset = 0); - Matcher matchIterator(PIString && subject, size_t offset = 0); + Matcher matchIterator(const PIString & subject, size_t offset = 0) const; + Matcher matchIterator(PIString & subject, size_t offset = 0) const; + Matcher matchIterator(PIString && subject, size_t offset = 0) const; static PIRegularExpression fromGlob(const PIString & pattern, Options opt = None); static PIRegularExpression fromPOSIX(const PIString & pattern, Options opt = None); diff --git a/libs/main/text/pistring.cpp b/libs/main/text/pistring.cpp index e9b37fad..ec09bf65 100644 --- a/libs/main/text/pistring.cpp +++ b/libs/main/text/pistring.cpp @@ -998,6 +998,11 @@ PIStringList PIString::split(const PIString & delim) const { } +bool PIString::contains(const PIRegularExpression & regexp) const { + return regexp.match(const_cast(*this)).hasMatch(); +} + + //! \~\details //! \~\code //! PIString s("012345012345"); @@ -1033,6 +1038,11 @@ int PIString::find(const PIString & str, const int start) const { } +int PIString::find(const PIRegularExpression & regexp, const int start) const { + return regexp.match(const_cast(*this), start).matchedStart(); +} + + //! \~\details //! \~\code //! piCout << PIString("1.str").findAny(".,:"); // 1 @@ -1090,6 +1100,16 @@ int PIString::findLast(const PIString & str, const int start) const { } +int PIString::findLast(const PIRegularExpression & regexp, const int start) const { + auto m = regexp.match(const_cast(*this), start); + int ret = m.matchedStart(); + while (m.next()) { + ret = m.matchedStart(); + } + return ret; +} + + //! \~\details //! \~\code //! piCout << PIString(".str.0").findAnyLast(".,:"); // 4 diff --git a/libs/main/text/pistring.h b/libs/main/text/pistring.h index ffc17c84..014928c3 100644 --- a/libs/main/text/pistring.h +++ b/libs/main/text/pistring.h @@ -33,6 +33,7 @@ class PIStringList; +class PIRegularExpression; //! \ingroup Text //! \~\brief @@ -1174,6 +1175,10 @@ public: //! \~russian Возвращает содержит ли строка подстроку "str". bool contains(const PIString & str) const { return find(str) >= 0; } + //! \~english Returns if string match "regexp". + //! \~russian Возвращает совпадает ли строка "regexp". + bool contains(const PIRegularExpression & regexp) const; + //! \~english Search character "c" from character at index "start" and return first occur position. //! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение. @@ -1200,6 +1205,10 @@ public: //! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange() int find(const char * str, const int start = 0) const { return find(PIString(str), start); } + //! \~english Search match of "regexp" from character at index "start" and return first occur position. + //! \~russian Ищет совпадение с "regexp" от символа "start" и возвращает первое вхождение. + int find(const PIRegularExpression & regexp, const int start = 0) const; + //! \~english Search any character of "str" from character at index "start" and return first occur position. //! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение. int findAny(const PIString & str, const int start = 0) const; @@ -1240,6 +1249,10 @@ public: //! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange() int findLast(const char * str, const int start = 0) const { return findLast(PIString(str), start); } + //! \~english Search match of "regexp" from character at index "start" and return last occur position. + //! \~russian Ищет совпадение с "regexp" от символа "start" и возвращает последнее вхождение. + int findLast(const PIRegularExpression & regexp, const int start = 0) const; + //! \~english Search any character of "str" from character at index "start" and return last occur position. //! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение. int findAnyLast(const PIString & str, const int start = 0) const;