From 296b679d6e3217cc112b7ed19b363b82356615ef Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 6 Aug 2017 08:42:01 -0400 Subject: Implement findFirst and findLast in InputSource Preparing to refactor some pattern searching code to use these instead of their own memchr loops. This should simplify the code that replaces PCRE. --- libtests/build.mk | 1 + libtests/input_source.cc | 108 +++++++++++++++++++++++++++ libtests/libtests.testcov | 8 ++ libtests/qtest/input_source.test | 26 +++++++ libtests/qtest/input_source/input_source.out | 14 ++++ 5 files changed, 157 insertions(+) create mode 100644 libtests/input_source.cc create mode 100644 libtests/qtest/input_source.test create mode 100644 libtests/qtest/input_source/input_source.out (limited to 'libtests') diff --git a/libtests/build.mk b/libtests/build.mk index 22d9299e..2a272799 100644 --- a/libtests/build.mk +++ b/libtests/build.mk @@ -6,6 +6,7 @@ BINS_libtests = \ concatenate \ flate \ hex \ + input_source \ lzw \ md5 \ pcre \ diff --git a/libtests/input_source.cc b/libtests/input_source.cc new file mode 100644 index 00000000..091a1ea1 --- /dev/null +++ b/libtests/input_source.cc @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include + +static PointerHolder +get_buffer() +{ + size_t size = 3172; + PointerHolder b(new Buffer(size)); + unsigned char* p = b->getBuffer(); + for (size_t i = 0; i < size; ++i) + { + p[i] = static_cast(i & 0xff); + } + return b; +} + +class Finder: public InputSource::Finder +{ + public: + Finder(PointerHolder is, std::string const& after) : + is(is), + after(after) + { + } + virtual ~Finder() + { + } + virtual bool check(); + + private: + PointerHolder is; + std::string after; +}; + +bool +Finder::check() +{ + QPDFTokenizer tokenizer; + QPDFTokenizer::Token t = tokenizer.readToken(is, "finder", true); + if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "potato")) + { + t = tokenizer.readToken(is, "finder", true); + return (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, after)); + } + return false; +} + +void check(char const* description, bool expected, bool actual) +{ + std::cout << description << ": " + << ((actual == expected) ? "PASS" : "FAIL") + << std::endl; +} + +int main() +{ + PointerHolder b1 = get_buffer(); + unsigned char* b = b1->getBuffer(); + // Straddle block boundaries + memcpy(b + 1022, "potato", 6); + // Overlap so that the first check() would advance past the start + // of the next match + memcpy(b + 2037, "potato potato salad ", 20); + PointerHolder is = + new BufferInputSource("test buffer input source", b1.getPointer()); + Finder f1(is, "salad"); + check("find potato salad", true, + is->findFirst("potato", 0, 0, f1)); + check("barely find potato salad", true, + is->findFirst("potato", 1100, 945, f1)); + check("barely find potato salad", true, + is->findFirst("potato", 2000, 45, f1)); + check("potato salad is too late", false, + is->findFirst("potato", 1100, 944, f1)); + check("potato salad is too late", false, + is->findFirst("potato", 2000, 44, f1)); + check("potato salad not found", false, + is->findFirst("potato", 2045, 0, f1)); + check("potato salad not found", false, + is->findFirst("potato", 0, 1, f1)); + + // Put one more right at EOF + memcpy(b + b1->getSize() - 12, "potato salad", 12); + check("potato salad at EOF", true, + is->findFirst("potato", 3000, 0, f1)); + + is->findFirst("potato", 0, 0, f1); + check("findFirst found first", true, + is->tell() == 2056); + check("findLast found potato salad", true, + is->findLast("potato", 0, 0, f1)); + check("findLast found at EOF", true, + is->tell() == 3172); + + // Make check() bump into EOF + memcpy(b + b1->getSize() - 6, "potato", 6); + check("potato but not salad salad at EOF", false, + is->findFirst("potato", 3000, 0, f1)); + check("findLast found potato salad", true, + is->findLast("potato", 0, 0, f1)); + check("findLast found first one", true, + is->tell() == 2056); + + return 0; +} diff --git a/libtests/libtests.testcov b/libtests/libtests.testcov index ddbccd24..a5fe625f 100644 --- a/libtests/libtests.testcov +++ b/libtests/libtests.testcov @@ -16,3 +16,11 @@ bits write zero bits 0 Pl_ASCIIHexDecoder ignore space 0 Pl_ASCIIHexDecoder no-op flush 0 Pl_ASCIIHexDecoder partial flush 1 +InputSource read next block 1 +InputSource find EOF 1 +InputSource out of range 0 +InputSource first char matched but not string 0 +InputSource start_chars matched but not check 0 +InputSource not enough bytes 0 +InputSource findLast found more than one 0 +InputSource found match at buf[0] 0 diff --git a/libtests/qtest/input_source.test b/libtests/qtest/input_source.test new file mode 100644 index 00000000..89a1c21a --- /dev/null +++ b/libtests/qtest/input_source.test @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +require 5.008; +use warnings; +use strict; + +chdir("input_source") or die "chdir testdir failed: $!\n"; + +require TestDriver; + +my $td = new TestDriver('InputSource'); + +cleanup(); + +$td->runtest("input source tests", + {$td->COMMAND => "input_source"}, + {$td->FILE => "input_source.out", + $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + +cleanup(); + +$td->report(1); + +sub cleanup +{ +} diff --git a/libtests/qtest/input_source/input_source.out b/libtests/qtest/input_source/input_source.out new file mode 100644 index 00000000..6af379c6 --- /dev/null +++ b/libtests/qtest/input_source/input_source.out @@ -0,0 +1,14 @@ +find potato salad: PASS +barely find potato salad: PASS +barely find potato salad: PASS +potato salad is too late: PASS +potato salad is too late: PASS +potato salad not found: PASS +potato salad not found: PASS +potato salad at EOF: PASS +findFirst found first: PASS +findLast found potato salad: PASS +findLast found at EOF: PASS +potato but not salad salad at EOF: PASS +findLast found potato salad: PASS +findLast found first one: PASS -- cgit v1.2.3-70-g09d2