From a30e675f56ca6803b2940281ec79cccb97fcd9a8 Mon Sep 17 00:00:00 2001 From: Lucas Trzesniewski Date: Sun, 6 Oct 2024 16:26:44 +0200 Subject: [PATCH] Reduce number of calls to pcre2_substitute --- src/PCRE.NET.Native/pcrenet_substitute.c | 9 +++++++-- src/PCRE.NET.Tests/PcreNet/SubstituteTests.cs | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/PCRE.NET.Native/pcrenet_substitute.c b/src/PCRE.NET.Native/pcrenet_substitute.c index 49f1095..c2b0823 100644 --- a/src/PCRE.NET.Native/pcrenet_substitute.c +++ b/src/PCRE.NET.Native/pcrenet_substitute.c @@ -41,6 +41,11 @@ typedef struct replay_queue callout_queue; } substitute_callout_data; +static size_t max_size(const size_t a, const size_t b) +{ + return a > b ? a : b; +} + static void replay_queue_init(replay_queue* queue) { queue->buffer = NULL; @@ -83,7 +88,7 @@ static void replay_queue_try_enqueue(replay_queue* queue, uint8_t result) if (queue->count == queue->buffer_size) { - const size_t new_size = max(64, 2 * queue->buffer_size); + const size_t new_size = max_size(64, 2 * queue->buffer_size); uint8_t* new_buf = realloc(queue->buffer, new_size * sizeof(uint8_t)); if (!new_buf) return; @@ -279,7 +284,7 @@ static void substitute_with_callout(const pcrenet_substitute_input* input, // Output buffer is too small if (result->result_code == PCRE2_ERROR_NOMEMORY) { - buffer_length *= 2; + buffer_length = max_size(2 * buffer_length, 2 * (size_t)input->subject_length); if (!result->output_on_heap) { diff --git a/src/PCRE.NET.Tests/PcreNet/SubstituteTests.cs b/src/PCRE.NET.Tests/PcreNet/SubstituteTests.cs index 3fd0dd0..72b1078 100644 --- a/src/PCRE.NET.Tests/PcreNet/SubstituteTests.cs +++ b/src/PCRE.NET.Tests/PcreNet/SubstituteTests.cs @@ -265,7 +265,7 @@ public void should_execute_each_callout_once() var execCount = 0; - var result = re.InternalRegex.Substitute(str.AsSpan(), null, "#".AsSpan(), PcreMatchSettings.Default, 0, (uint)PcreSubstituteOptions.SubstituteGlobal, data => + var result = re.InternalRegex.Substitute(str.AsSpan(), null, "#:#:#:#".AsSpan(), PcreMatchSettings.Default, 0, (uint)PcreSubstituteOptions.SubstituteGlobal, data => { ++execCount; Assert.That(data.SubstitutionCount, Is.EqualTo(execCount)); @@ -274,8 +274,8 @@ public void should_execute_each_callout_once() }, out var substituteCallCount); Assert.That(execCount, Is.EqualTo(str.Length)); - Assert.That(result, Is.EqualTo(str.Replace("aaa", "aa#"))); - Assert.That(substituteCallCount, Is.EqualTo(6)); + Assert.That(result, Is.EqualTo(str.Replace("aaa", "aa#:#:#:#"))); + Assert.That(substituteCallCount, Is.EqualTo(3)); } [Test]