From 06ecef76d3689f74b8ce325c9649094aa46eb357 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 27 Jan 2010 09:50:10 -0500 Subject: [PATCH] Enhancement - caseless find - Added support for a starting offset. --- src/tests/text.t.cpp | 5 ++++- src/text.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++ src/text.h | 1 + 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/tests/text.t.cpp b/src/tests/text.t.cpp index a8a96e20f..d320fadf0 100644 --- a/src/tests/text.t.cpp +++ b/src/tests/text.t.cpp @@ -34,7 +34,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest t (176); + UnitTest t (178); // void wrapText (std::vector & lines, const std::string& text, const int width) std::string text = "This is a test of the line wrapping code."; @@ -356,6 +356,9 @@ int main (int argc, char** argv) t.is ((int) find ("FOO", "fo", false), 0, "FOO contains fo (caseless)"); t.is ((int) find ("FOO", "FO", false), 0, "FOO contains FO (caseless)"); + // Test start offset. + t.is ((int) find ("one two three", "e", 3, true), (int) 11, "offset obeyed"); + t.is ((int) find ("one two three", "e", 11, true), (int) 11, "offset obeyed"); return 0; } diff --git a/src/text.cpp b/src/text.cpp index 395fb78f8..7a3c21b81 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -519,3 +519,50 @@ std::string::size_type find ( } //////////////////////////////////////////////////////////////////////////////// +std::string::size_type find ( + const std::string& text, + const std::string& pattern, + std::string::size_type begin, + bool sensitive /*= true*/) +{ + // Implement a sensitive find, which is really just a loop withing a loop, + // comparing lower-case versions of each character in turn. + if (!sensitive) + { + // Handle empty pattern. + const char* p = pattern.c_str (); + size_t len = pattern.length (); + if (len == 0) + return 0; + + // Handle bad begin. + if (begin >= len) + return std::string::npos; + + // Evaluate these once, for performance reasons. + const char* t = text.c_str (); + const char* start = t + begin; + const char* end = start + text.size (); + + for (; t < end - len; ++t) + { + int diff; + for (size_t i = 0; i < len; ++i) + if ((diff = tolower (t[i]) - tolower (p[i]))) + break; + + // diff == 0 means there was no break from the loop, which only occurs + // when a difference is detected. Therefore, the loop terminated, and + // diff is zero. + if (diff == 0) + return t - start; + } + + return std::string::npos; + } + + // Otherwise, just use std::string::find. + return text.find (pattern, begin); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h index 33571da00..4b488cda9 100644 --- a/src/text.h +++ b/src/text.h @@ -56,6 +56,7 @@ bool isWordStart (const std::string&, std::string::size_type); bool isWordEnd (const std::string&, std::string::size_type); bool compare (const std::string&, const std::string&, bool sensitive = true); std::string::size_type find (const std::string&, const std::string&, bool sensitive = true); +std::string::size_type find (const std::string&, const std::string&, std::string::size_type, bool sensitive = true); #endif ////////////////////////////////////////////////////////////////////////////////