package/kodi: switch to pcre2

Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
Signed-off-by: Julien Olivain <ju.o@free.fr>
This commit is contained in:
Bernd Kuhls
2026-04-09 10:43:00 +02:00
committed by Julien Olivain
parent 66b520817f
commit f99d5f46e2
5 changed files with 807 additions and 3 deletions

View File

@@ -0,0 +1,127 @@
From 4dd017b2eae39356cda0d96a2f5743dbb8ccf299 Mon Sep 17 00:00:00 2001
From: fuzzard <fuzzard@kodi.tv>
Date: Sun, 2 Jun 2024 12:13:01 +1000
Subject: [PATCH] RegExp remove unused methods
Upstream: https://github.com/xbmc/xbmc/commit/5df2e57368cf5867f588d00a503eb624e5121460
Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
---
xbmc/utils/RegExp.cpp | 30 ------------------------------
xbmc/utils/RegExp.h | 5 -----
xbmc/utils/test/TestRegExp.cpp | 17 -----------------
3 files changed, 52 deletions(-)
diff --git a/xbmc/utils/RegExp.cpp b/xbmc/utils/RegExp.cpp
index 9667b646a9..40263a28eb 100644
--- a/xbmc/utils/RegExp.cpp
+++ b/xbmc/utils/RegExp.cpp
@@ -485,11 +485,6 @@ int CRegExp::GetSubStart(int iSub) const
return m_iOvector[iSub*2] + m_offset;
}
-int CRegExp::GetSubStart(const std::string& subName) const
-{
- return GetSubStart(GetNamedSubPatternNumber(subName.c_str()));
-}
-
int CRegExp::GetSubLength(int iSub) const
{
if (!IsValidSubNumber(iSub))
@@ -498,11 +493,6 @@ int CRegExp::GetSubLength(int iSub) const
return m_iOvector[(iSub*2)+1] - m_iOvector[(iSub*2)];
}
-int CRegExp::GetSubLength(const std::string& subName) const
-{
- return GetSubLength(GetNamedSubPatternNumber(subName.c_str()));
-}
-
std::string CRegExp::GetMatch(int iSub /* = 0 */) const
{
if (!IsValidSubNumber(iSub))
@@ -516,26 +506,6 @@ std::string CRegExp::GetMatch(int iSub /* = 0 */) const
return m_subject.substr(pos, len);
}
-std::string CRegExp::GetMatch(const std::string& subName) const
-{
- return GetMatch(GetNamedSubPatternNumber(subName.c_str()));
-}
-
-bool CRegExp::GetNamedSubPattern(const char* strName, std::string& strMatch) const
-{
- strMatch.clear();
- int iSub = pcre_get_stringnumber(m_re, strName);
- if (!IsValidSubNumber(iSub))
- return false;
- strMatch = GetMatch(iSub);
- return true;
-}
-
-int CRegExp::GetNamedSubPatternNumber(const char* strName) const
-{
- return pcre_get_stringnumber(m_re, strName);
-}
-
void CRegExp::DumpOvector(int iLog /* = LOGDEBUG */)
{
if (iLog < LOGDEBUG || iLog > LOGNONE)
diff --git a/xbmc/utils/RegExp.h b/xbmc/utils/RegExp.h
index 53f6019a8f..feea89cd0d 100644
--- a/xbmc/utils/RegExp.h
+++ b/xbmc/utils/RegExp.h
@@ -111,15 +111,10 @@ public:
};
int GetSubCount() const { return m_iMatchCount - 1; } // PCRE returns the number of sub-patterns + 1
int GetSubStart(int iSub) const;
- int GetSubStart(const std::string& subName) const;
int GetSubLength(int iSub) const;
- int GetSubLength(const std::string& subName) const;
int GetCaptureTotal() const;
std::string GetMatch(int iSub = 0) const;
- std::string GetMatch(const std::string& subName) const;
const std::string& GetPattern() const { return m_pattern; }
- bool GetNamedSubPattern(const char* strName, std::string& strMatch) const;
- int GetNamedSubPatternNumber(const char* strName) const;
void DumpOvector(int iLog);
/**
* Check is RegExp object is ready for matching
diff --git a/xbmc/utils/test/TestRegExp.cpp b/xbmc/utils/test/TestRegExp.cpp
index d757127417..9435a46aa4 100644
--- a/xbmc/utils/test/TestRegExp.cpp
+++ b/xbmc/utils/test/TestRegExp.cpp
@@ -96,19 +96,6 @@ TEST(TestRegExp, GetPattern)
EXPECT_STREQ("^(Test)\\s*(.*)\\.", regex.GetPattern().c_str());
}
-TEST(TestRegExp, GetNamedSubPattern)
-{
- CRegExp regex;
- std::string match;
-
- EXPECT_TRUE(regex.RegComp("^(?<first>Test)\\s*(?<second>.*)\\."));
- EXPECT_EQ(0, regex.RegFind("Test string."));
- EXPECT_TRUE(regex.GetNamedSubPattern("first", match));
- EXPECT_STREQ("Test", match.c_str());
- EXPECT_TRUE(regex.GetNamedSubPattern("second", match));
- EXPECT_STREQ("string", match.c_str());
-}
-
TEST(TestRegExp, operatorEqual)
{
CRegExp regex, regexcopy;
@@ -117,10 +104,6 @@ TEST(TestRegExp, operatorEqual)
EXPECT_TRUE(regex.RegComp("^(?<first>Test)\\s*(?<second>.*)\\."));
regexcopy = regex;
EXPECT_EQ(0, regexcopy.RegFind("Test string."));
- EXPECT_TRUE(regexcopy.GetNamedSubPattern("first", match));
- EXPECT_STREQ("Test", match.c_str());
- EXPECT_TRUE(regexcopy.GetNamedSubPattern("second", match));
- EXPECT_STREQ("string", match.c_str());
}
class TestRegExpLog : public testing::Test
--
2.47.3

View File

@@ -0,0 +1,192 @@
From 4a4642b1d7562b553f80da279255a9755a9e20f7 Mon Sep 17 00:00:00 2001
From: fuzzard <fuzzard@kodi.tv>
Date: Sun, 2 Jun 2024 13:24:57 +1000
Subject: [PATCH] Introduce PCRE2 dependency
create PCRE2 in tools/depends/target
Create Find module for PCRE2
Upstream: https://github.com/xbmc/xbmc/commit/5c24bf262e5cd75b413fcb4c2c5c144d6971d7cc
[Bernd: backported relevant parts to 21.3-Omega]
Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
---
cmake/modules/FindPCRE2.cmake | 151 +++++++++++++++++++++++
tools/depends/target/pcre2/PCRE2-VERSION | 7 ++
2 files changed, 158 insertions(+)
create mode 100644 cmake/modules/FindPCRE2.cmake
create mode 100644 tools/depends/target/pcre2/PCRE2-VERSION
diff --git a/cmake/modules/FindPCRE2.cmake b/cmake/modules/FindPCRE2.cmake
new file mode 100644
index 0000000000..7e50d5f2c1
--- /dev/null
+++ b/cmake/modules/FindPCRE2.cmake
@@ -0,0 +1,151 @@
+#.rst:
+# FindPCRE2
+# --------
+# Finds the PCRE2 library
+#
+# This will define the following imported target::
+#
+# ${APP_NAME_LC}::PCRE2 - The PCRE2 library
+
+if(NOT TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME})
+
+ macro(buildPCRE2)
+ set(PCRE2_VERSION ${${MODULE}_VER})
+ if(WIN32)
+ set(PCRE_DEBUG_POSTFIX d)
+ endif()
+
+ set(patches "${CORE_SOURCE_DIR}/tools/depends/target/${MODULE_LC}/001-all-enable_docs_pc.patch"
+ "${CORE_SOURCE_DIR}/tools/depends/target/${MODULE_LC}/002-all-cmake-config-installdir.patch")
+
+ generate_patchcommand("${patches}")
+
+ set(CMAKE_ARGS -DBUILD_STATIC_LIBS=ON
+ -DPCRE2_BUILD_PCRE2_8=ON
+ -DPCRE2_BUILD_PCRE2_16=OFF
+ -DPCRE2_BUILD_PCRE2_32=OFF
+ -DPCRE2_SUPPORT_JIT=ON
+ -DPCRE2_SUPPORT_UNICODE=ON
+ -DPCRE2_BUILD_PCRE2GREP=OFF
+ -DPCRE2_BUILD_TESTS=OFF
+ -DENABLE_DOCS=OFF)
+
+ if(CORE_SYSTEM_NAME STREQUAL darwin_embedded)
+ list(APPEND CMAKE_ARGS -DPCRE2_SUPPORT_JIT=OFF)
+ endif()
+
+ set(${CMAKE_FIND_PACKAGE_NAME}_COMPILEDEFINITIONS PCRE2_STATIC)
+
+ BUILD_DEP_TARGET()
+ endmacro()
+
+ include(cmake/scripts/common/ModuleHelpers.cmake)
+
+ set(MODULE_LC pcre2)
+
+ SETUP_BUILD_VARS()
+
+ if(KODI_DEPENDSBUILD OR (WIN32 OR WINDOWS_STORE))
+ set(PCRE2_USE_STATIC_LIBS ON)
+ endif()
+
+ # Check for existing PCRE2. If version >= PCRE2-VERSION file version, dont build
+ find_package(PCRE2 CONFIG COMPONENTS 8BIT QUIET)
+
+ if((PCRE2_VERSION VERSION_LESS ${${MODULE}_VER} AND ENABLE_INTERNAL_PCRE2) OR
+ ((CORE_SYSTEM_NAME STREQUAL linux OR CORE_SYSTEM_NAME STREQUAL freebsd) AND ENABLE_INTERNAL_PCRE2))
+ buildPCRE2()
+ else()
+ # if PCRE2::8BIT target exists, it meets version requirements
+ # we only do a pkgconfig search when a suitable cmake config returns nothing
+ if(TARGET PCRE2::8BIT)
+ get_target_property(_PCRE2_CONFIGURATIONS PCRE2::8BIT IMPORTED_CONFIGURATIONS)
+ if(_PCRE2_CONFIGURATIONS)
+ foreach(_pcre2_config IN LISTS _PCRE2_CONFIGURATIONS)
+ # Just set to RELEASE var so select_library_configurations can continue to work its magic
+ string(TOUPPER ${_pcre2_config} _pcre2_config_UPPER)
+ if((NOT ${_pcre2_config_UPPER} STREQUAL "RELEASE") AND
+ (NOT ${_pcre2_config_UPPER} STREQUAL "DEBUG"))
+ get_target_property(PCRE2_LIBRARY_RELEASE PCRE2::8BIT IMPORTED_LOCATION_${_pcre2_config_UPPER})
+ else()
+ get_target_property(PCRE2_LIBRARY_${_pcre2_config_UPPER} PCRE2::8BIT IMPORTED_LOCATION_${_pcre2_config_UPPER})
+ endif()
+ endforeach()
+ else()
+ get_target_property(PCRE2_LIBRARY_RELEASE PCRE2::8BIT IMPORTED_LOCATION)
+ endif()
+ get_target_property(PCRE2_INCLUDE_DIR PCRE2::8BIT INTERFACE_INCLUDE_DIRECTORIES)
+ else()
+ # ToDo: use pkgconfig data imported and drop manual find_path/find_library
+ find_package(PkgConfig)
+ if(PKG_CONFIG_FOUND)
+ pkg_check_modules(PC_PCRE2 libpcre2-8 QUIET)
+ endif()
+
+ find_path(PCRE2_INCLUDE_DIR pcre2.h
+ HINTS ${PC_PCRE2_INCLUDEDIR})
+ find_library(PCRE2_LIBRARY_RELEASE NAMES pcre2-8
+ HINTS ${PC_PCRE2_LIBDIR})
+ set(PCRE2_VERSION ${PC_PCRE2_VERSION})
+ endif()
+ endif()
+
+ include(SelectLibraryConfigurations)
+ select_library_configurations(PCRE2)
+
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(PCRE2
+ REQUIRED_VARS PCRE2_LIBRARY PCRE2_INCLUDE_DIR
+ VERSION_VAR PCRE2_VERSION)
+
+ if(PCRE2_FOUND)
+ if(TARGET PCRE2::8BIT AND NOT TARGET pcre2)
+ add_library(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} ALIAS PCRE2::8BIT)
+ else()
+ add_library(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} UNKNOWN IMPORTED)
+ if(PCRE2_LIBRARY_RELEASE)
+ set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
+ IMPORTED_CONFIGURATIONS RELEASE
+ IMPORTED_LOCATION_RELEASE "${PCRE2_LIBRARY_RELEASE}")
+ endif()
+ if(PCRE2_LIBRARY_DEBUG)
+ set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
+ IMPORTED_LOCATION_DEBUG "${PCRE2_LIBRARY_DEBUG}")
+ set_property(TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS DEBUG)
+ endif()
+ set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${PCRE2_INCLUDE_DIR}")
+
+ # Add interface compile definitions. This will usually come from an INTERNAL build being required.
+ if(${CMAKE_FIND_PACKAGE_NAME}_COMPILEDEFINITIONS)
+ set_property(TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} APPEND PROPERTY
+ INTERFACE_COMPILE_DEFINITIONS ${${CMAKE_FIND_PACKAGE_NAME}_COMPILEDEFINITIONS})
+ endif()
+ endif()
+ if(TARGET pcre2)
+ add_dependencies(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} pcre2)
+ endif()
+
+ # Add internal build target when a Multi Config Generator is used
+ # We cant add a dependency based off a generator expression for targeted build types,
+ # https://gitlab.kitware.com/cmake/cmake/-/issues/19467
+ # therefore if the find heuristics only find the library, we add the internal build
+ # target to the project to allow user to manually trigger for any build type they need
+ # in case only a specific build type is actually available (eg Release found, Debug Required)
+ # This is mainly targeted for windows who required different runtime libs for different
+ # types, and they arent compatible
+ if(_multiconfig_generator)
+ if(NOT TARGET pcre2)
+ buildPCRE2()
+ set_target_properties(pcre2 PROPERTIES EXCLUDE_FROM_ALL TRUE)
+ endif()
+ add_dependencies(build_internal_depends pcre2)
+ endif()
+
+ else()
+ if(PCRE2_FIND_REQUIRED)
+ message(FATAL_ERROR "PCRE2 not found. Possibly use -DENABLE_INTERNAL_PCRE2=ON to build PCRE2")
+ endif()
+ endif()
+endif()
diff --git a/tools/depends/target/pcre2/PCRE2-VERSION b/tools/depends/target/pcre2/PCRE2-VERSION
new file mode 100644
index 0000000000..800eebf0b9
--- /dev/null
+++ b/tools/depends/target/pcre2/PCRE2-VERSION
@@ -0,0 +1,7 @@
+LIBNAME=pcre2
+VERSION=10.42
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2
+SHA512=72fbde87fecec3aa4b47225dd919ea1d55e97f2cbcf02aba26e5a0d3b1ffb58c25a80a9ef069eb99f9cf4e41ba9604ad06a7ec159870e1e875d86820e12256d3
+BYPRODUCT=libpcre2-8.a
+BYPRODUCT_WIN=pcre2-8-static.lib
+
--
2.47.3

View File

@@ -0,0 +1,486 @@
From 250d14b8e3f614147c9465ca6c1b86a3b5a5f7a2 Mon Sep 17 00:00:00 2001
From: fuzzard <fuzzard@kodi.tv>
Date: Sun, 2 Jun 2024 13:56:07 +1000
Subject: [PATCH] Migrate PCRE to PCRE2 and remove PCRE
Upstream: https://github.com/xbmc/xbmc/commit/8e0c4fd22a0b1f9c54b0536960752263f0d5a04f
[Bernd: backported to 21.3-Omega]
Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
---
CMakeLists.txt | 4 +-
xbmc/utils/RegExp.cpp | 202 ++++++++++++++++++-------------------
xbmc/utils/RegExp.h | 22 ++--
xbmc/utils/StringUtils.cpp | 6 +-
4 files changed, 111 insertions(+), 123 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb648e9a27..319b95044f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -92,7 +92,7 @@ dependent_option(ENABLE_INTERNAL_CEC "Enable internal libcec?")
dependent_option(ENABLE_INTERNAL_FLATBUFFERS "Enable internal flatbuffers?")
dependent_option(ENABLE_INTERNAL_FMT "Enable internal fmt?")
dependent_option(ENABLE_INTERNAL_NFS "Enable internal libnfs?")
-dependent_option(ENABLE_INTERNAL_PCRE "Enable internal pcre?")
+dependent_option(ENABLE_INTERNAL_PCRE2 "Enable internal pcre2?")
dependent_option(ENABLE_INTERNAL_RapidJSON "Enable internal rapidjson?")
# If ENABLE_INTERNAL_FMT is ON, we force ENABLE_INTERNAL_SPDLOG ON as it has a hard
@@ -215,7 +215,7 @@ set(required_deps ASS>=0.15.0
LibDvd
Lzo2
OpenSSL>=1.1.0
- PCRE
+ PCRE2
RapidJSON>=1.0.2
Spdlog
Sqlite3
diff --git a/xbmc/utils/RegExp.cpp b/xbmc/utils/RegExp.cpp
index 40263a28eb..cb620208dc 100644
--- a/xbmc/utils/RegExp.cpp
+++ b/xbmc/utils/RegExp.cpp
@@ -16,27 +16,6 @@
#include <stdlib.h>
#include <string.h>
-using namespace PCRE;
-
-#ifndef PCRE_UCP
-#define PCRE_UCP 0
-#endif // PCRE_UCP
-
-#ifdef PCRE_CONFIG_JIT
-#define PCRE_HAS_JIT_CODE 1
-#endif
-
-#ifndef PCRE_STUDY_JIT_COMPILE
-#define PCRE_STUDY_JIT_COMPILE 0
-#endif
-#ifndef PCRE_INFO_JIT
-// some unused number
-#define PCRE_INFO_JIT 2048
-#endif
-#ifndef PCRE_HAS_JIT_CODE
-#define pcre_free_study(x) pcre_free((x))
-#endif
-
int CRegExp::m_Utf8Supported = -1;
int CRegExp::m_UcpSupported = -1;
int CRegExp::m_JitSupported = -1;
@@ -51,25 +30,24 @@ void CRegExp::InitValues(bool caseless /*= false*/, CRegExp::utf8Mode utf8 /*= a
{
m_utf8Mode = utf8;
m_re = NULL;
- m_sd = NULL;
- m_iOptions = PCRE_DOTALL | PCRE_NEWLINE_ANY;
+ m_ctxt = nullptr;
+ m_iOptions = PCRE2_DOTALL;
if(caseless)
- m_iOptions |= PCRE_CASELESS;
+ m_iOptions |= PCRE2_CASELESS;
if (m_utf8Mode == forceUtf8)
{
if (IsUtf8Supported())
- m_iOptions |= PCRE_UTF8;
+ m_iOptions |= PCRE2_UTF;
if (AreUnicodePropertiesSupported())
- m_iOptions |= PCRE_UCP;
+ m_iOptions |= PCRE2_UCP;
}
m_offset = 0;
m_jitCompiled = false;
m_bMatched = false;
m_iMatchCount = 0;
- m_jitStack = NULL;
-
- memset(m_iOvector, 0, sizeof(m_iOvector));
+ m_iOvector = nullptr;
+ m_jitStack = NULL;
}
CRegExp::CRegExp(bool caseless, CRegExp::utf8Mode utf8, const char *re, studyMode study /*= NoStudy*/)
@@ -225,7 +203,8 @@ bool CRegExp::isCharClassWithUnicode(const std::string& regexp, size_t& pos)
CRegExp::CRegExp(const CRegExp& re)
{
m_re = NULL;
- m_sd = NULL;
+ m_ctxt = nullptr;
+ m_iOvector = nullptr;
m_jitStack = NULL;
m_utf8Mode = re.m_utf8Mode;
m_iOptions = re.m_iOptions;
@@ -240,12 +219,13 @@ CRegExp& CRegExp::operator=(const CRegExp& re)
m_pattern = re.m_pattern;
if (re.m_re)
{
- if (pcre_fullinfo(re.m_re, NULL, PCRE_INFO_SIZE, &size) >= 0)
+ if (pcre2_pattern_info(re.m_re, PCRE2_INFO_SIZE, &size) >= 0)
{
- if ((m_re = (pcre*)malloc(size)))
+ if ((m_re = pcre2_code_copy(re.m_re)))
{
- memcpy(m_re, re.m_re, size);
- memcpy(m_iOvector, re.m_iOvector, OVECCOUNT*sizeof(int));
+ if (re.m_ctxt)
+ m_ctxt = pcre2_match_context_copy(re.m_ctxt);
+ m_iOvector = re.m_iOvector;
m_offset = re.m_offset;
m_iMatchCount = re.m_iMatchCount;
m_bMatched = re.m_bMatched;
@@ -273,18 +253,27 @@ bool CRegExp::RegComp(const char *re, studyMode study /*= NoStudy*/)
m_jitCompiled = false;
m_bMatched = false;
m_iMatchCount = 0;
- const char *errMsg = NULL;
- int errOffset = 0;
- int options = m_iOptions;
+ pcre2_compile_context* ctxt;
+ int errCode;
+ char errMsg[120];
+ PCRE2_SIZE errOffset;
+ uint32_t options = m_iOptions;
if (m_utf8Mode == autoUtf8 && requireUtf8(re))
- options |= (IsUtf8Supported() ? PCRE_UTF8 : 0) | (AreUnicodePropertiesSupported() ? PCRE_UCP : 0);
+ options |=
+ (IsUtf8Supported() ? PCRE2_UTF : 0) | (AreUnicodePropertiesSupported() ? PCRE2_UCP : 0);
Cleanup();
- m_re = pcre_compile(re, options, &errMsg, &errOffset, NULL);
+ ctxt = pcre2_compile_context_create(NULL);
+ pcre2_set_newline(ctxt, PCRE2_NEWLINE_ANY);
+ m_re = pcre2_compile(reinterpret_cast<PCRE2_SPTR>(re), PCRE2_ZERO_TERMINATED, options, &errCode,
+ &errOffset, ctxt);
+ pcre2_compile_context_free(ctxt);
+
if (!m_re)
{
m_pattern.clear();
+ pcre2_get_error_message(errCode, reinterpret_cast<PCRE2_UCHAR*>(errMsg), sizeof(errMsg));
CLog::Log(LOGERROR, "PCRE: {}. Compilation failed at offset {} in expression '{}'", errMsg,
errOffset, re);
return false;
@@ -295,23 +284,12 @@ bool CRegExp::RegComp(const char *re, studyMode study /*= NoStudy*/)
if (study)
{
const bool jitCompile = (study == StudyWithJitComp) && IsJitSupported();
- const int studyOptions = jitCompile ? PCRE_STUDY_JIT_COMPILE : 0;
-
- m_sd = pcre_study(m_re, studyOptions, &errMsg);
- if (errMsg != NULL)
- {
- CLog::Log(LOGWARNING, "{}: PCRE error \"{}\" while studying expression", __FUNCTION__,
- errMsg);
- if (m_sd != NULL)
- {
- pcre_free_study(m_sd);
- m_sd = NULL;
- }
- }
- else if (jitCompile)
+ if (jitCompile)
{
- int jitPresent = 0;
- m_jitCompiled = (pcre_fullinfo(m_re, m_sd, PCRE_INFO_JIT, &jitPresent) == 0 && jitPresent == 1);
+ pcre2_jit_compile(m_re, PCRE2_JIT_COMPLETE);
+ size_t jitPresent = 0;
+ m_jitCompiled =
+ (pcre2_pattern_info(m_re, PCRE2_INFO_JITSIZE, &jitPresent) == 0 && jitPresent > 0);
}
}
@@ -325,6 +303,9 @@ int CRegExp::RegFind(const char *str, unsigned int startoffset /*= 0*/, int maxN
int CRegExp::PrivateRegFind(size_t bufferLen, const char *str, unsigned int startoffset /* = 0*/, int maxNumberOfCharsToTest /*= -1*/)
{
+ pcre2_match_data* md;
+ PCRE2_SIZE offset;
+
m_offset = 0;
m_bMatched = false;
m_iMatchCount = 0;
@@ -347,37 +328,46 @@ int CRegExp::PrivateRegFind(size_t bufferLen, const char *str, unsigned int star
return -1;
}
-#ifdef PCRE_HAS_JIT_CODE
+ if (!m_ctxt)
+ m_ctxt = pcre2_match_context_create(NULL);
+
if (m_jitCompiled && !m_jitStack)
{
- m_jitStack = pcre_jit_stack_alloc(32*1024, 512*1024);
+ m_jitStack = pcre2_jit_stack_create(32 * 1024, 512 * 1024, NULL);
if (m_jitStack == NULL)
CLog::Log(LOGWARNING, "{}: can't allocate address space for JIT stack", __FUNCTION__);
- pcre_assign_jit_stack(m_sd, NULL, m_jitStack);
+ pcre2_jit_stack_assign(m_ctxt, NULL, m_jitStack);
}
-#endif
if (maxNumberOfCharsToTest >= 0)
bufferLen = std::min<size_t>(bufferLen, startoffset + maxNumberOfCharsToTest);
m_subject.assign(str + startoffset, bufferLen - startoffset);
- int rc = pcre_exec(m_re, NULL, m_subject.c_str(), m_subject.length(), 0, 0, m_iOvector, OVECCOUNT);
+ md = pcre2_match_data_create(OVECCOUNT, nullptr);
+ int rc = pcre2_match(m_re, reinterpret_cast<PCRE2_SPTR>(m_subject.c_str()), m_subject.length(), 0,
+ 0, md, m_ctxt);
+ m_iOvector = pcre2_get_ovector_pointer(md);
+ offset = pcre2_get_startchar(md);
+ pcre2_match_data_free(md);
if (rc<1)
{
static const int fragmentLen = 80; // length of excerpt before erroneous char for log
switch(rc)
{
- case PCRE_ERROR_NOMATCH:
- return -1;
+ case PCRE2_ERROR_NOMATCH:
+ return -1;
- case PCRE_ERROR_MATCHLIMIT:
- CLog::Log(LOGERROR, "PCRE: Match limit reached");
- return -1;
+ case PCRE2_ERROR_MATCHLIMIT:
+ CLog::Log(LOGERROR, "PCRE: Match limit reached");
+ return -1;
-#ifdef PCRE_ERROR_SHORTUTF8
- case PCRE_ERROR_SHORTUTF8:
+ case PCRE2_ERROR_UTF8_ERR1:
+ case PCRE2_ERROR_UTF8_ERR2:
+ case PCRE2_ERROR_UTF8_ERR3:
+ case PCRE2_ERROR_UTF8_ERR4:
+ case PCRE2_ERROR_UTF8_ERR5:
{
const size_t startPos = (m_subject.length() > fragmentLen) ? CUtf8Utils::RFindValidUtf8Char(m_subject, m_subject.length() - fragmentLen) : 0;
if (startPos != std::string::npos)
@@ -389,28 +379,44 @@ int CRegExp::PrivateRegFind(size_t bufferLen, const char *str, unsigned int star
CLog::Log(LOGERROR, "PCRE: Bad UTF-8 character at the end of string");
return -1;
}
-#endif
- case PCRE_ERROR_BADUTF8:
+ case PCRE2_ERROR_UTF8_ERR6:
+ case PCRE2_ERROR_UTF8_ERR7:
+ case PCRE2_ERROR_UTF8_ERR8:
+ case PCRE2_ERROR_UTF8_ERR9:
+ case PCRE2_ERROR_UTF8_ERR10:
+ case PCRE2_ERROR_UTF8_ERR11:
+ case PCRE2_ERROR_UTF8_ERR12:
+ case PCRE2_ERROR_UTF8_ERR13:
+ case PCRE2_ERROR_UTF8_ERR14:
+ case PCRE2_ERROR_UTF8_ERR15:
+ case PCRE2_ERROR_UTF8_ERR16:
+ case PCRE2_ERROR_UTF8_ERR17:
+ case PCRE2_ERROR_UTF8_ERR18:
+ case PCRE2_ERROR_UTF8_ERR19:
+ case PCRE2_ERROR_UTF8_ERR20:
+ case PCRE2_ERROR_UTF8_ERR21:
{
+ char errbuf[120];
+
+ pcre2_get_error_message(rc, reinterpret_cast<PCRE2_UCHAR*>(errbuf), sizeof(errbuf));
const size_t startPos = (m_iOvector[0] > fragmentLen) ? CUtf8Utils::RFindValidUtf8Char(m_subject, m_iOvector[0] - fragmentLen) : 0;
- if (m_iOvector[0] >= 0 && startPos != std::string::npos)
+ if ((int)m_iOvector[0] >= 0 && startPos != std::string::npos)
CLog::Log(LOGERROR,
"PCRE: Bad UTF-8 character, error code: {}, position: {}. Text before bad "
"char: \"{}\"",
- m_iOvector[1], m_iOvector[0],
- m_subject.substr(startPos, m_iOvector[0] - startPos + 1));
+ errbuf, offset, m_subject.substr(startPos, m_iOvector[0] - startPos + 1));
else
- CLog::Log(LOGERROR, "PCRE: Bad UTF-8 character, error code: {}, position: {}",
- m_iOvector[1], m_iOvector[0]);
+ CLog::Log(LOGERROR, "PCRE: Bad UTF-8 character, error code: {}, position: {}", errbuf,
+ offset);
return -1;
}
- case PCRE_ERROR_BADUTF8_OFFSET:
- CLog::Log(LOGERROR, "PCRE: Offset is pointing to the middle of UTF-8 character");
- return -1;
+ case PCRE2_ERROR_BADUTFOFFSET:
+ CLog::Log(LOGERROR, "PCRE: Offset is pointing to the middle of UTF-8 character");
+ return -1;
- default:
- CLog::Log(LOGERROR, "PCRE: Unknown error: {}", rc);
- return -1;
+ default:
+ CLog::Log(LOGERROR, "PCRE: Unknown error: {}", rc);
+ return -1;
}
}
m_offset = startoffset;
@@ -423,7 +429,7 @@ int CRegExp::GetCaptureTotal() const
{
int c = -1;
if (m_re)
- pcre_fullinfo(m_re, NULL, PCRE_INFO_CAPTURECOUNT, &c);
+ pcre2_pattern_info(m_re, PCRE2_INFO_CAPTURECOUNT, &c);
return c;
}
@@ -528,23 +534,21 @@ void CRegExp::Cleanup()
{
if (m_re)
{
- pcre_free(m_re);
- m_re = NULL;
+ pcre2_code_free(m_re);
+ m_re = nullptr;
}
- if (m_sd)
+ if (m_ctxt)
{
- pcre_free_study(m_sd);
- m_sd = NULL;
+ pcre2_match_context_free(m_ctxt);
+ m_ctxt = nullptr;
}
-#ifdef PCRE_HAS_JIT_CODE
if (m_jitStack)
{
- pcre_jit_stack_free(m_jitStack);
+ pcre2_jit_stack_free(m_jitStack);
m_jitStack = NULL;
}
-#endif
}
inline bool CRegExp::IsValidSubNumber(int iSub) const
@@ -557,7 +561,7 @@ bool CRegExp::IsUtf8Supported(void)
{
if (m_Utf8Supported == -1)
{
- if (pcre_config(PCRE_CONFIG_UTF8, &m_Utf8Supported) != 0)
+ if (pcre2_config(PCRE2_CONFIG_UNICODE, &m_Utf8Supported) < 0)
m_Utf8Supported = 0;
}
@@ -566,13 +570,11 @@ bool CRegExp::IsUtf8Supported(void)
bool CRegExp::AreUnicodePropertiesSupported(void)
{
-#if defined(PCRE_CONFIG_UNICODE_PROPERTIES) && PCRE_UCP != 0
if (m_UcpSupported == -1)
{
- if (pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &m_UcpSupported) != 0)
+ if (pcre2_config(PCRE2_CONFIG_UNICODE, &m_UcpSupported) < 0)
m_UcpSupported = 0;
}
-#endif
return m_UcpSupported == 1;
}
@@ -595,13 +597,13 @@ bool CRegExp::LogCheckUtf8Support(void)
if (!utf8FullSupport)
{
+ char ver[24];
+
+ pcre2_config(PCRE2_CONFIG_VERSION, ver);
CLog::Log(LOGINFO,
- "Consider installing PCRE lib version 8.10 or later with enabled Unicode properties "
+ "Consider installing PCRE lib version 10.10 or later with enabled Unicode properties "
"and UTF-8 support. Your PCRE lib version: {}",
- PCRE::pcre_version());
-#if PCRE_UCP == 0
- CLog::Log(LOGINFO, "You will need to rebuild XBMC after PCRE lib update.");
-#endif
+ ver);
}
return utf8FullSupport;
@@ -611,9 +613,7 @@ bool CRegExp::IsJitSupported(void)
{
if (m_JitSupported == -1)
{
-#ifdef PCRE_HAS_JIT_CODE
- if (pcre_config(PCRE_CONFIG_JIT, &m_JitSupported) != 0)
-#endif
+ if (pcre2_config(PCRE2_CONFIG_JIT, &m_JitSupported) < 0)
m_JitSupported = 0;
}
diff --git a/xbmc/utils/RegExp.h b/xbmc/utils/RegExp.h
index feea89cd0d..90d3db541e 100644
--- a/xbmc/utils/RegExp.h
+++ b/xbmc/utils/RegExp.h
@@ -13,16 +13,8 @@
#include <string>
#include <vector>
-/* make sure stdlib.h is included before including pcre.h inside the
- namespace; this works around stdlib.h definitions also living in
- the PCRE namespace */
-#include <stdlib.h>
-
-namespace PCRE {
-struct real_pcre_jit_stack; // forward declaration for PCRE without JIT
-typedef struct real_pcre_jit_stack pcre_jit_stack;
-#include <pcre.h>
-}
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
class CRegExp
{
@@ -138,17 +130,17 @@ private:
void Cleanup();
inline bool IsValidSubNumber(int iSub) const;
- PCRE::pcre* m_re;
- PCRE::pcre_extra* m_sd;
+ pcre2_code* m_re;
+ pcre2_match_context* m_ctxt;
static const int OVECCOUNT=(m_MaxNumOfBackrefrences + 1) * 3;
unsigned int m_offset;
- int m_iOvector[OVECCOUNT];
+ PCRE2_SIZE* m_iOvector;
utf8Mode m_utf8Mode;
int m_iMatchCount;
- int m_iOptions;
+ uint32_t m_iOptions;
bool m_jitCompiled;
bool m_bMatched;
- PCRE::pcre_jit_stack* m_jitStack;
+ pcre2_jit_stack* m_jitStack;
std::string m_subject;
std::string m_pattern;
static int m_Utf8Supported;
diff --git a/xbmc/utils/StringUtils.cpp b/xbmc/utils/StringUtils.cpp
index 2c77e58ebd..d390113dd7 100644
--- a/xbmc/utils/StringUtils.cpp
+++ b/xbmc/utils/StringUtils.cpp
@@ -30,6 +30,7 @@
#include "LangInfo.h"
#include "StringUtils.h"
#include "XBDateTime.h"
+#include "utils/RegExp.h"
#include <algorithm>
#include <array>
@@ -46,11 +47,6 @@
#include <fstrcmp.h>
#include <memory.h>
-// don't move or std functions end up in PCRE namespace
-// clang-format off
-#include "utils/RegExp.h"
-// clang-format on
-
#define FORMAT_BLOCK_SIZE 512 // # of bytes for initial allocation for printf
namespace
--
2.47.3

View File

@@ -91,8 +91,7 @@ menuconfig BR2_PACKAGE_KODI
select BR2_PACKAGE_LIBPNG
select BR2_PACKAGE_LZO
select BR2_PACKAGE_OPENSSL
select BR2_PACKAGE_PCRE
select BR2_PACKAGE_PCRE_UCP
select BR2_PACKAGE_PCRE2
select BR2_PACKAGE_PYTHON3_2TO3
select BR2_PACKAGE_PYTHON3_PYEXPAT
select BR2_PACKAGE_PYTHON3_SQLITE

View File

@@ -47,7 +47,7 @@ KODI_DEPENDENCIES = \
libpng \
lzo \
openssl \
pcre \
pcre2 \
python3 \
rapidjson \
spdlog \