version 5.0.0_beta

integrate PIRegularExpression into PIString and PIDir
add piliterals_regularexpression.h for ""_regex and ""_glob literals
This commit is contained in:
2025-08-13 18:48:01 +03:00
parent 7a6936ccd9
commit b6c5d65a8d
9 changed files with 158 additions and 57 deletions

View File

@@ -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)

View File

@@ -298,9 +298,9 @@ bool sort_compare(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
//! также "." и "..". Возвращаются абсолютные пути.
//! \attention Этот метод не читает содержимое директорий
//! рекурсивно!
PIVector<PIFile::FileInfo> PIDir::entries() {
PIVector<PIFile::FileInfo> l;
if (!isExists()) return l;
PIVector<PIFile::FileInfo> PIDir::entries(const PIRegularExpression & regexp) {
if (!isExists()) return {};
PIVector<PIFile::FileInfo> ret;
PIString dp = absolutePath();
PIString p(dp);
if (dp == ".")
@@ -309,9 +309,9 @@ PIVector<PIFile::FileInfo> 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<PIFile::FileInfo> 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<PIFile::FileInfo> 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<PIFile::FileInfo> 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<PIFile::FileInfo> 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<PIFile::FileInfo> PIDir::entries() {
//! одним списком, сортированным по алфавиту. Список не содержит
//! "." и "..". Возвращаются абсолютные пути, причём файлы
//! располагаются после директорий.
PIVector<PIFile::FileInfo> PIDir::allEntries() {
PIVector<PIFile::FileInfo> PIDir::allEntries(const PIRegularExpression & regexp) {
PIVector<PIFile::FileInfo> ret;
PIVector<PIFile::FileInfo> dirs;
PIStringList cdirs, ndirs;
@@ -409,10 +420,16 @@ PIVector<PIFile::FileInfo> 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;
ndirs.clear();
}
@@ -516,8 +533,8 @@ PIDir PIDir::temporary() {
}
PIVector<PIFile::FileInfo> PIDir::allEntries(const PIString & path) {
return PIDir(path).allEntries();
PIVector<PIFile::FileInfo> PIDir::allEntries(const PIString & path, const PIRegularExpression & regexp) {
return PIDir(path).allEntries(regexp);
}

View File

@@ -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<PIFile::FileInfo> entries();
PIVector<PIFile::FileInfo> entries(const PIRegularExpression & regexp = {});
//! \~english Returns this directory content recursively
//! \~russian Возвращает содержимое этой директории рекурсивно
PIVector<PIFile::FileInfo> allEntries();
PIVector<PIFile::FileInfo> 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<PIFile::FileInfo> allEntries(const PIString & path);
static PIVector<PIFile::FileInfo> allEntries(const PIString & path, const PIRegularExpression & regexp = {});
//! \~english Returns if directory "path" exists
//! \~russian Возвращает существует ли эта директория

View File

@@ -34,6 +34,7 @@
#include "piliterals_bytearray.h"
#include "piliterals_bytes.h"
#include "piliterals_regularexpression.h"
#include "piliterals_string.h"
#include "piliterals_time.h"

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@@ -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<PIRegularExpression *>(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<PIRegularExpression *>(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<PIRegularExpression *>(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) {}

View File

@@ -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);

View File

@@ -998,6 +998,11 @@ PIStringList PIString::split(const PIString & delim) const {
}
bool PIString::contains(const PIRegularExpression & regexp) const {
return regexp.match(const_cast<PIString &>(*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<PIString &>(*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<PIString &>(*this), start);
int ret = m.matchedStart();
while (m.next()) {
ret = m.matchedStart();
}
return ret;
}
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").findAnyLast(".,:"); // 4

View File

@@ -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;