aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/Foundation/include/Poco/String.h
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/poco/Foundation/include/Poco/String.h
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
downloadydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/poco/Foundation/include/Poco/String.h')
-rw-r--r--contrib/libs/poco/Foundation/include/Poco/String.h1412
1 files changed, 706 insertions, 706 deletions
diff --git a/contrib/libs/poco/Foundation/include/Poco/String.h b/contrib/libs/poco/Foundation/include/Poco/String.h
index fcf10d6de5..cdeffa7e3e 100644
--- a/contrib/libs/poco/Foundation/include/Poco/String.h
+++ b/contrib/libs/poco/Foundation/include/Poco/String.h
@@ -1,706 +1,706 @@
-//
-// String.h
-//
-// Library: Foundation
-// Package: Core
-// Module: String
-//
-// String utility functions.
-//
-// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
-// and Contributors.
-//
-// SPDX-License-Identifier: BSL-1.0
-//
-
-
-#ifndef Foundation_String_INCLUDED
-#define Foundation_String_INCLUDED
-
-
-#include "Poco/Foundation.h"
-#include "Poco/Ascii.h"
-#include <cstring>
-#include <algorithm>
-
-
-namespace Poco {
-
-
-template <class S>
-S trimLeft(const S& str)
- /// Returns a copy of str with all leading
- /// whitespace removed.
-{
- typename S::const_iterator it = str.begin();
- typename S::const_iterator end = str.end();
-
- while (it != end && Ascii::isSpace(*it)) ++it;
- return S(it, end);
-}
-
-
-template <class S>
-S& trimLeftInPlace(S& str)
- /// Removes all leading whitespace in str.
-{
- typename S::iterator it = str.begin();
- typename S::iterator end = str.end();
-
- while (it != end && Ascii::isSpace(*it)) ++it;
- str.erase(str.begin(), it);
- return str;
-}
-
-
-template <class S>
-S trimRight(const S& str)
- /// Returns a copy of str with all trailing
- /// whitespace removed.
-{
- int pos = int(str.size()) - 1;
-
- while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
- return S(str, 0, pos + 1);
-}
-
-
-template <class S>
-S& trimRightInPlace(S& str)
- /// Removes all trailing whitespace in str.
-{
- int pos = int(str.size()) - 1;
-
- while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
- str.resize(pos + 1);
-
- return str;
-}
-
-
-template <class S>
-S trim(const S& str)
- /// Returns a copy of str with all leading and
- /// trailing whitespace removed.
-{
- int first = 0;
- int last = int(str.size()) - 1;
-
- while (first <= last && Ascii::isSpace(str[first])) ++first;
- while (last >= first && Ascii::isSpace(str[last])) --last;
-
- return S(str, first, last - first + 1);
-}
-
-
-template <class S>
-S& trimInPlace(S& str)
- /// Removes all leading and trailing whitespace in str.
-{
- int first = 0;
- int last = int(str.size()) - 1;
-
- while (first <= last && Ascii::isSpace(str[first])) ++first;
- while (last >= first && Ascii::isSpace(str[last])) --last;
-
- str.resize(last + 1);
- str.erase(0, first);
-
- return str;
-}
-
-
-template <class S>
-S toUpper(const S& str)
- /// Returns a copy of str containing all upper-case characters.
-{
- typename S::const_iterator it = str.begin();
- typename S::const_iterator end = str.end();
-
- S result;
- result.reserve(str.size());
- while (it != end) result += static_cast<typename S::value_type>(Ascii::toUpper(*it++));
- return result;
-}
-
-
-template <class S>
-S& toUpperInPlace(S& str)
- /// Replaces all characters in str with their upper-case counterparts.
-{
- typename S::iterator it = str.begin();
- typename S::iterator end = str.end();
-
- while (it != end) { *it = static_cast<typename S::value_type>(Ascii::toUpper(*it)); ++it; }
- return str;
-}
-
-
-template <class S>
-S toLower(const S& str)
- /// Returns a copy of str containing all lower-case characters.
-{
- typename S::const_iterator it = str.begin();
- typename S::const_iterator end = str.end();
-
- S result;
- result.reserve(str.size());
- while (it != end) result += static_cast<typename S::value_type>(Ascii::toLower(*it++));
- return result;
-}
-
-
-template <class S>
-S& toLowerInPlace(S& str)
- /// Replaces all characters in str with their lower-case counterparts.
-{
- typename S::iterator it = str.begin();
- typename S::iterator end = str.end();
-
- while (it != end) { *it = static_cast<typename S::value_type>(Ascii::toLower(*it)); ++it; }
- return str;
-}
-
-
-#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
-
-
-template <class S, class It>
-int icompare(
- const S& str,
- typename S::size_type pos,
- typename S::size_type n,
- It it2,
- It end2)
- /// Case-insensitive string comparison
-{
- typename S::size_type sz = str.size();
- if (pos > sz) pos = sz;
- if (pos + n > sz) n = sz - pos;
- It it1 = str.begin() + pos;
- It end1 = str.begin() + pos + n;
- while (it1 != end1 && it2 != end2)
- {
- typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it1)));
- typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*it2)));
- if (c1 < c2)
- return -1;
- else if (c1 > c2)
- return 1;
- ++it1; ++it2;
- }
-
- if (it1 == end1)
- return it2 == end2 ? 0 : -1;
- else
- return 1;
-}
-
-
-template <class S>
-int icompare(const S& str1, const S& str2)
- // A special optimization for an often used case.
-{
- typename S::const_iterator it1(str1.begin());
- typename S::const_iterator end1(str1.end());
- typename S::const_iterator it2(str2.begin());
- typename S::const_iterator end2(str2.end());
- while (it1 != end1 && it2 != end2)
- {
- typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it1)));
- typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*it2)));
- if (c1 < c2)
- return -1;
- else if (c1 > c2)
- return 1;
- ++it1; ++it2;
- }
-
- if (it1 == end1)
- return it2 == end2 ? 0 : -1;
- else
- return 1;
-}
-
-
-template <class S>
-int icompare(const S& str1, typename S::size_type n1, const S& str2, typename S::size_type n2)
-{
- if (n2 > str2.size()) n2 = str2.size();
- return icompare(str1, 0, n1, str2.begin(), str2.begin() + n2);
-}
-
-
-template <class S>
-int icompare(const S& str1, typename S::size_type n, const S& str2)
-{
- if (n > str2.size()) n = str2.size();
- return icompare(str1, 0, n, str2.begin(), str2.begin() + n);
-}
-
-
-template <class S>
-int icompare(const S& str1, typename S::size_type pos, typename S::size_type n, const S& str2)
-{
- return icompare(str1, pos, n, str2.begin(), str2.end());
-}
-
-
-template <class S>
-int icompare(
- const S& str1,
- typename S::size_type pos1,
- typename S::size_type n1,
- const S& str2,
- typename S::size_type pos2,
- typename S::size_type n2)
-{
- typename S::size_type sz2 = str2.size();
- if (pos2 > sz2) pos2 = sz2;
- if (pos2 + n2 > sz2) n2 = sz2 - pos2;
- return icompare(str1, pos1, n1, str2.begin() + pos2, str2.begin() + pos2 + n2);
-}
-
-
-template <class S>
-int icompare(
- const S& str1,
- typename S::size_type pos1,
- typename S::size_type n,
- const S& str2,
- typename S::size_type pos2)
-{
- typename S::size_type sz2 = str2.size();
- if (pos2 > sz2) pos2 = sz2;
- if (pos2 + n > sz2) n = sz2 - pos2;
- return icompare(str1, pos1, n, str2.begin() + pos2, str2.begin() + pos2 + n);
-}
-
-
-template <class S>
-int icompare(
- const S& str,
- typename S::size_type pos,
- typename S::size_type n,
- const typename S::value_type* ptr)
-{
- poco_check_ptr (ptr);
- typename S::size_type sz = str.size();
- if (pos > sz) pos = sz;
- if (pos + n > sz) n = sz - pos;
- typename S::const_iterator it = str.begin() + pos;
- typename S::const_iterator end = str.begin() + pos + n;
- while (it != end && *ptr)
- {
- typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it)));
- typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*ptr)));
- if (c1 < c2)
- return -1;
- else if (c1 > c2)
- return 1;
- ++it; ++ptr;
- }
-
- if (it == end)
- return *ptr == 0 ? 0 : -1;
- else
- return 1;
-}
-
-
-template <class S>
-int icompare(
- const S& str,
- typename S::size_type pos,
- const typename S::value_type* ptr)
-{
- return icompare(str, pos, str.size() - pos, ptr);
-}
-
-
-template <class S>
-int icompare(
- const S& str,
- const typename S::value_type* ptr)
-{
- return icompare(str, 0, str.size(), ptr);
-}
-
-
-#else
-
-
-int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2);
-int Foundation_API icompare(const std::string& str1, const std::string& str2);
-int Foundation_API icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2);
-int Foundation_API icompare(const std::string& str1, std::string::size_type n, const std::string& str2);
-int Foundation_API icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2);
-int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n1, const std::string& str2, std::string::size_type pos2, std::string::size_type n2);
-int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n, const std::string& str2, std::string::size_type pos2);
-int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr);
-int Foundation_API icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr);
-int Foundation_API icompare(const std::string& str, const std::string::value_type* ptr);
-
-
-#endif
-
-
-template <class S>
-S translate(const S& str, const S& from, const S& to)
- /// Returns a copy of str with all characters in
- /// from replaced by the corresponding (by position)
- /// characters in to. If there is no corresponding
- /// character in to, the character is removed from
- /// the copy.
-{
- S result;
- result.reserve(str.size());
- typename S::const_iterator it = str.begin();
- typename S::const_iterator end = str.end();
- typename S::size_type toSize = to.size();
- while (it != end)
- {
- typename S::size_type pos = from.find(*it);
- if (pos == S::npos)
- {
- result += *it;
- }
- else
- {
- if (pos < toSize) result += to[pos];
- }
- ++it;
- }
- return result;
-}
-
-
-template <class S>
-S translate(const S& str, const typename S::value_type* from, const typename S::value_type* to)
-{
- poco_check_ptr (from);
- poco_check_ptr (to);
- return translate(str, S(from), S(to));
-}
-
-
-template <class S>
-S& translateInPlace(S& str, const S& from, const S& to)
- /// Replaces in str all occurrences of characters in from
- /// with the corresponding (by position) characters in to.
- /// If there is no corresponding character, the character
- /// is removed.
-{
- str = translate(str, from, to);
- return str;
-}
-
-
-template <class S>
-S translateInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to)
-{
- poco_check_ptr (from);
- poco_check_ptr (to);
- str = translate(str, S(from), S(to));
-#if defined(__SUNPRO_CC)
-// Fix around the RVO bug in SunStudio 12.4
- S ret(str);
- return ret;
-#else
- return str;
-#endif
-}
-
-
-#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
-
-
-template <class S>
-S& replaceInPlace(S& str, const S& from, const S& to, typename S::size_type start = 0)
-{
- poco_assert (from.size() > 0);
-
- S result;
- typename S::size_type pos = 0;
- result.append(str, 0, start);
- do
- {
- pos = str.find(from, start);
- if (pos != S::npos)
- {
- result.append(str, start, pos - start);
- result.append(to);
- start = pos + from.length();
- }
- else result.append(str, start, str.size() - start);
- }
- while (pos != S::npos);
- str.swap(result);
- return str;
-}
-
-
-template <class S>
-S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
-{
- poco_assert (*from);
-
- S result;
- typename S::size_type pos = 0;
- typename S::size_type fromLen = std::strlen(from);
- result.append(str, 0, start);
- do
- {
- pos = str.find(from, start);
- if (pos != S::npos)
- {
- result.append(str, start, pos - start);
- result.append(to);
- start = pos + fromLen;
- }
- else result.append(str, start, str.size() - start);
- }
- while (pos != S::npos);
- str.swap(result);
- return str;
-}
-
-
-template <class S>
-S& replaceInPlace(S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
-{
- if (from == to) return str;
-
- typename S::size_type pos = 0;
- do
- {
- pos = str.find(from, start);
- if (pos != S::npos)
- {
- if (to) str[pos] = to;
- else str.erase(pos, 1);
- }
- } while (pos != S::npos);
-
- return str;
-}
-
-
-template <class S>
-S& removeInPlace(S& str, const typename S::value_type ch, typename S::size_type start = 0)
-{
- return replaceInPlace(str, ch, 0, start);
-}
-
-
-template <class S>
-S replace(const S& str, const S& from, const S& to, typename S::size_type start = 0)
- /// Replace all occurrences of from (which must not be the empty string)
- /// in str with to, starting at position start.
-{
- S result(str);
- replaceInPlace(result, from, to, start);
- return result;
-}
-
-
-template <class S>
-S replace(const S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
-{
- S result(str);
- replaceInPlace(result, from, to, start);
- return result;
-}
-
-
-template <class S>
-S replace(const S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
-{
- S result(str);
- replaceInPlace(result, from, to, start);
- return result;
-}
-
-
-template <class S>
-S remove(const S& str, const typename S::value_type ch, typename S::size_type start = 0)
-{
- S result(str);
- replaceInPlace(result, ch, 0, start);
- return result;
-}
-
-
-#else
-
-
-Foundation_API std::string replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
-Foundation_API std::string replace(const std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
-Foundation_API std::string replace(const std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
-Foundation_API std::string remove(const std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
-Foundation_API std::string& replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
-Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
-Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
-Foundation_API std::string& removeInPlace(std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
-
-
-#endif
-
-
-template <class S>
-S cat(const S& s1, const S& s2)
- /// Concatenates two strings.
-{
- S result = s1;
- result.reserve(s1.size() + s2.size());
- result.append(s2);
- return result;
-}
-
-
-template <class S>
-S cat(const S& s1, const S& s2, const S& s3)
- /// Concatenates three strings.
-{
- S result = s1;
- result.reserve(s1.size() + s2.size() + s3.size());
- result.append(s2);
- result.append(s3);
- return result;
-}
-
-
-template <class S>
-S cat(const S& s1, const S& s2, const S& s3, const S& s4)
- /// Concatenates four strings.
-{
- S result = s1;
- result.reserve(s1.size() + s2.size() + s3.size() + s4.size());
- result.append(s2);
- result.append(s3);
- result.append(s4);
- return result;
-}
-
-
-template <class S>
-S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5)
- /// Concatenates five strings.
-{
- S result = s1;
- result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size());
- result.append(s2);
- result.append(s3);
- result.append(s4);
- result.append(s5);
- return result;
-}
-
-
-template <class S>
-S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5, const S& s6)
- /// Concatenates six strings.
-{
- S result = s1;
- result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size());
- result.append(s2);
- result.append(s3);
- result.append(s4);
- result.append(s5);
- result.append(s6);
- return result;
-}
-
-
-template <class S, class It>
-S cat(const S& delim, const It& begin, const It& end)
- /// Concatenates a sequence of strings, delimited
- /// by the string given in delim.
-{
- S result;
- for (It it = begin; it != end; ++it)
- {
- if (!result.empty()) result.append(delim);
- result += *it;
- }
- return result;
-}
-
-
-//
-// case-insensitive string equality
-//
-
-
-template <typename charT>
-struct i_char_traits : public std::char_traits<charT>
-{
- inline static bool eq(charT c1, charT c2)
- {
- return Ascii::toLower(c1) == Ascii::toLower(c2);
- }
-
- inline static bool ne(charT c1, charT c2)
- {
- return !eq(c1, c2);
- }
-
- inline static bool lt(charT c1, charT c2)
- {
- return Ascii::toLower(c1) < Ascii::toLower(c2);
- }
-
- static int compare(const charT* s1, const charT* s2, std::size_t n)
- {
- for (int i = 0; i < n && s1 && s2; ++i, ++s1, ++s2)
- {
- if (Ascii::toLower(*s1) == Ascii::toLower(*s2)) continue;
- else if (Ascii::toLower(*s1) < Ascii::toLower(*s2)) return -1;
- else return 1;
- }
-
- return 0;
- }
-
- static const charT* find(const charT* s, int n, charT a)
- {
- while(n-- > 0 && Ascii::toLower(*s) != Ascii::toLower(a)) { ++s; }
- return s;
- }
-};
-
-
-typedef std::basic_string<char, i_char_traits<char> > istring;
- /// Case-insensitive std::string counterpart.
-
-
-template<typename T>
-std::size_t isubstr(const T& str, const T& sought)
- /// Case-insensitive substring; searches for a substring
- /// without regards to case.
-{
- typename T::const_iterator it = std::search(str.begin(), str.end(),
- sought.begin(), sought.end(),
- i_char_traits<typename T::value_type>::eq);
-
- if (it != str.end()) return it - str.begin();
- else return static_cast<std::size_t>(T::npos);
-}
-
-
-struct CILess
- /// Case-insensitive less-than functor; useful for standard maps
- /// and sets with std::strings keys and case-insensitive ordering
- /// requirement.
-{
- inline bool operator() (const std::string& s1, const std::string& s2) const
- {
- return icompare(s1, s2) < 0;
- }
-};
-
-
-} // namespace Poco
-
-
-#endif // Foundation_String_INCLUDED
+//
+// String.h
+//
+// Library: Foundation
+// Package: Core
+// Module: String
+//
+// String utility functions.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Foundation_String_INCLUDED
+#define Foundation_String_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Ascii.h"
+#include <cstring>
+#include <algorithm>
+
+
+namespace Poco {
+
+
+template <class S>
+S trimLeft(const S& str)
+ /// Returns a copy of str with all leading
+ /// whitespace removed.
+{
+ typename S::const_iterator it = str.begin();
+ typename S::const_iterator end = str.end();
+
+ while (it != end && Ascii::isSpace(*it)) ++it;
+ return S(it, end);
+}
+
+
+template <class S>
+S& trimLeftInPlace(S& str)
+ /// Removes all leading whitespace in str.
+{
+ typename S::iterator it = str.begin();
+ typename S::iterator end = str.end();
+
+ while (it != end && Ascii::isSpace(*it)) ++it;
+ str.erase(str.begin(), it);
+ return str;
+}
+
+
+template <class S>
+S trimRight(const S& str)
+ /// Returns a copy of str with all trailing
+ /// whitespace removed.
+{
+ int pos = int(str.size()) - 1;
+
+ while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
+ return S(str, 0, pos + 1);
+}
+
+
+template <class S>
+S& trimRightInPlace(S& str)
+ /// Removes all trailing whitespace in str.
+{
+ int pos = int(str.size()) - 1;
+
+ while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
+ str.resize(pos + 1);
+
+ return str;
+}
+
+
+template <class S>
+S trim(const S& str)
+ /// Returns a copy of str with all leading and
+ /// trailing whitespace removed.
+{
+ int first = 0;
+ int last = int(str.size()) - 1;
+
+ while (first <= last && Ascii::isSpace(str[first])) ++first;
+ while (last >= first && Ascii::isSpace(str[last])) --last;
+
+ return S(str, first, last - first + 1);
+}
+
+
+template <class S>
+S& trimInPlace(S& str)
+ /// Removes all leading and trailing whitespace in str.
+{
+ int first = 0;
+ int last = int(str.size()) - 1;
+
+ while (first <= last && Ascii::isSpace(str[first])) ++first;
+ while (last >= first && Ascii::isSpace(str[last])) --last;
+
+ str.resize(last + 1);
+ str.erase(0, first);
+
+ return str;
+}
+
+
+template <class S>
+S toUpper(const S& str)
+ /// Returns a copy of str containing all upper-case characters.
+{
+ typename S::const_iterator it = str.begin();
+ typename S::const_iterator end = str.end();
+
+ S result;
+ result.reserve(str.size());
+ while (it != end) result += static_cast<typename S::value_type>(Ascii::toUpper(*it++));
+ return result;
+}
+
+
+template <class S>
+S& toUpperInPlace(S& str)
+ /// Replaces all characters in str with their upper-case counterparts.
+{
+ typename S::iterator it = str.begin();
+ typename S::iterator end = str.end();
+
+ while (it != end) { *it = static_cast<typename S::value_type>(Ascii::toUpper(*it)); ++it; }
+ return str;
+}
+
+
+template <class S>
+S toLower(const S& str)
+ /// Returns a copy of str containing all lower-case characters.
+{
+ typename S::const_iterator it = str.begin();
+ typename S::const_iterator end = str.end();
+
+ S result;
+ result.reserve(str.size());
+ while (it != end) result += static_cast<typename S::value_type>(Ascii::toLower(*it++));
+ return result;
+}
+
+
+template <class S>
+S& toLowerInPlace(S& str)
+ /// Replaces all characters in str with their lower-case counterparts.
+{
+ typename S::iterator it = str.begin();
+ typename S::iterator end = str.end();
+
+ while (it != end) { *it = static_cast<typename S::value_type>(Ascii::toLower(*it)); ++it; }
+ return str;
+}
+
+
+#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
+
+
+template <class S, class It>
+int icompare(
+ const S& str,
+ typename S::size_type pos,
+ typename S::size_type n,
+ It it2,
+ It end2)
+ /// Case-insensitive string comparison
+{
+ typename S::size_type sz = str.size();
+ if (pos > sz) pos = sz;
+ if (pos + n > sz) n = sz - pos;
+ It it1 = str.begin() + pos;
+ It end1 = str.begin() + pos + n;
+ while (it1 != end1 && it2 != end2)
+ {
+ typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it1)));
+ typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*it2)));
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+ ++it1; ++it2;
+ }
+
+ if (it1 == end1)
+ return it2 == end2 ? 0 : -1;
+ else
+ return 1;
+}
+
+
+template <class S>
+int icompare(const S& str1, const S& str2)
+ // A special optimization for an often used case.
+{
+ typename S::const_iterator it1(str1.begin());
+ typename S::const_iterator end1(str1.end());
+ typename S::const_iterator it2(str2.begin());
+ typename S::const_iterator end2(str2.end());
+ while (it1 != end1 && it2 != end2)
+ {
+ typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it1)));
+ typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*it2)));
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+ ++it1; ++it2;
+ }
+
+ if (it1 == end1)
+ return it2 == end2 ? 0 : -1;
+ else
+ return 1;
+}
+
+
+template <class S>
+int icompare(const S& str1, typename S::size_type n1, const S& str2, typename S::size_type n2)
+{
+ if (n2 > str2.size()) n2 = str2.size();
+ return icompare(str1, 0, n1, str2.begin(), str2.begin() + n2);
+}
+
+
+template <class S>
+int icompare(const S& str1, typename S::size_type n, const S& str2)
+{
+ if (n > str2.size()) n = str2.size();
+ return icompare(str1, 0, n, str2.begin(), str2.begin() + n);
+}
+
+
+template <class S>
+int icompare(const S& str1, typename S::size_type pos, typename S::size_type n, const S& str2)
+{
+ return icompare(str1, pos, n, str2.begin(), str2.end());
+}
+
+
+template <class S>
+int icompare(
+ const S& str1,
+ typename S::size_type pos1,
+ typename S::size_type n1,
+ const S& str2,
+ typename S::size_type pos2,
+ typename S::size_type n2)
+{
+ typename S::size_type sz2 = str2.size();
+ if (pos2 > sz2) pos2 = sz2;
+ if (pos2 + n2 > sz2) n2 = sz2 - pos2;
+ return icompare(str1, pos1, n1, str2.begin() + pos2, str2.begin() + pos2 + n2);
+}
+
+
+template <class S>
+int icompare(
+ const S& str1,
+ typename S::size_type pos1,
+ typename S::size_type n,
+ const S& str2,
+ typename S::size_type pos2)
+{
+ typename S::size_type sz2 = str2.size();
+ if (pos2 > sz2) pos2 = sz2;
+ if (pos2 + n > sz2) n = sz2 - pos2;
+ return icompare(str1, pos1, n, str2.begin() + pos2, str2.begin() + pos2 + n);
+}
+
+
+template <class S>
+int icompare(
+ const S& str,
+ typename S::size_type pos,
+ typename S::size_type n,
+ const typename S::value_type* ptr)
+{
+ poco_check_ptr (ptr);
+ typename S::size_type sz = str.size();
+ if (pos > sz) pos = sz;
+ if (pos + n > sz) n = sz - pos;
+ typename S::const_iterator it = str.begin() + pos;
+ typename S::const_iterator end = str.begin() + pos + n;
+ while (it != end && *ptr)
+ {
+ typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it)));
+ typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*ptr)));
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+ ++it; ++ptr;
+ }
+
+ if (it == end)
+ return *ptr == 0 ? 0 : -1;
+ else
+ return 1;
+}
+
+
+template <class S>
+int icompare(
+ const S& str,
+ typename S::size_type pos,
+ const typename S::value_type* ptr)
+{
+ return icompare(str, pos, str.size() - pos, ptr);
+}
+
+
+template <class S>
+int icompare(
+ const S& str,
+ const typename S::value_type* ptr)
+{
+ return icompare(str, 0, str.size(), ptr);
+}
+
+
+#else
+
+
+int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2);
+int Foundation_API icompare(const std::string& str1, const std::string& str2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type n, const std::string& str2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n1, const std::string& str2, std::string::size_type pos2, std::string::size_type n2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n, const std::string& str2, std::string::size_type pos2);
+int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr);
+int Foundation_API icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr);
+int Foundation_API icompare(const std::string& str, const std::string::value_type* ptr);
+
+
+#endif
+
+
+template <class S>
+S translate(const S& str, const S& from, const S& to)
+ /// Returns a copy of str with all characters in
+ /// from replaced by the corresponding (by position)
+ /// characters in to. If there is no corresponding
+ /// character in to, the character is removed from
+ /// the copy.
+{
+ S result;
+ result.reserve(str.size());
+ typename S::const_iterator it = str.begin();
+ typename S::const_iterator end = str.end();
+ typename S::size_type toSize = to.size();
+ while (it != end)
+ {
+ typename S::size_type pos = from.find(*it);
+ if (pos == S::npos)
+ {
+ result += *it;
+ }
+ else
+ {
+ if (pos < toSize) result += to[pos];
+ }
+ ++it;
+ }
+ return result;
+}
+
+
+template <class S>
+S translate(const S& str, const typename S::value_type* from, const typename S::value_type* to)
+{
+ poco_check_ptr (from);
+ poco_check_ptr (to);
+ return translate(str, S(from), S(to));
+}
+
+
+template <class S>
+S& translateInPlace(S& str, const S& from, const S& to)
+ /// Replaces in str all occurrences of characters in from
+ /// with the corresponding (by position) characters in to.
+ /// If there is no corresponding character, the character
+ /// is removed.
+{
+ str = translate(str, from, to);
+ return str;
+}
+
+
+template <class S>
+S translateInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to)
+{
+ poco_check_ptr (from);
+ poco_check_ptr (to);
+ str = translate(str, S(from), S(to));
+#if defined(__SUNPRO_CC)
+// Fix around the RVO bug in SunStudio 12.4
+ S ret(str);
+ return ret;
+#else
+ return str;
+#endif
+}
+
+
+#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
+
+
+template <class S>
+S& replaceInPlace(S& str, const S& from, const S& to, typename S::size_type start = 0)
+{
+ poco_assert (from.size() > 0);
+
+ S result;
+ typename S::size_type pos = 0;
+ result.append(str, 0, start);
+ do
+ {
+ pos = str.find(from, start);
+ if (pos != S::npos)
+ {
+ result.append(str, start, pos - start);
+ result.append(to);
+ start = pos + from.length();
+ }
+ else result.append(str, start, str.size() - start);
+ }
+ while (pos != S::npos);
+ str.swap(result);
+ return str;
+}
+
+
+template <class S>
+S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
+{
+ poco_assert (*from);
+
+ S result;
+ typename S::size_type pos = 0;
+ typename S::size_type fromLen = std::strlen(from);
+ result.append(str, 0, start);
+ do
+ {
+ pos = str.find(from, start);
+ if (pos != S::npos)
+ {
+ result.append(str, start, pos - start);
+ result.append(to);
+ start = pos + fromLen;
+ }
+ else result.append(str, start, str.size() - start);
+ }
+ while (pos != S::npos);
+ str.swap(result);
+ return str;
+}
+
+
+template <class S>
+S& replaceInPlace(S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
+{
+ if (from == to) return str;
+
+ typename S::size_type pos = 0;
+ do
+ {
+ pos = str.find(from, start);
+ if (pos != S::npos)
+ {
+ if (to) str[pos] = to;
+ else str.erase(pos, 1);
+ }
+ } while (pos != S::npos);
+
+ return str;
+}
+
+
+template <class S>
+S& removeInPlace(S& str, const typename S::value_type ch, typename S::size_type start = 0)
+{
+ return replaceInPlace(str, ch, 0, start);
+}
+
+
+template <class S>
+S replace(const S& str, const S& from, const S& to, typename S::size_type start = 0)
+ /// Replace all occurrences of from (which must not be the empty string)
+ /// in str with to, starting at position start.
+{
+ S result(str);
+ replaceInPlace(result, from, to, start);
+ return result;
+}
+
+
+template <class S>
+S replace(const S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
+{
+ S result(str);
+ replaceInPlace(result, from, to, start);
+ return result;
+}
+
+
+template <class S>
+S replace(const S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
+{
+ S result(str);
+ replaceInPlace(result, from, to, start);
+ return result;
+}
+
+
+template <class S>
+S remove(const S& str, const typename S::value_type ch, typename S::size_type start = 0)
+{
+ S result(str);
+ replaceInPlace(result, ch, 0, start);
+ return result;
+}
+
+
+#else
+
+
+Foundation_API std::string replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
+Foundation_API std::string replace(const std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
+Foundation_API std::string replace(const std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
+Foundation_API std::string remove(const std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
+Foundation_API std::string& replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
+Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
+Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
+Foundation_API std::string& removeInPlace(std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
+
+
+#endif
+
+
+template <class S>
+S cat(const S& s1, const S& s2)
+ /// Concatenates two strings.
+{
+ S result = s1;
+ result.reserve(s1.size() + s2.size());
+ result.append(s2);
+ return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3)
+ /// Concatenates three strings.
+{
+ S result = s1;
+ result.reserve(s1.size() + s2.size() + s3.size());
+ result.append(s2);
+ result.append(s3);
+ return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3, const S& s4)
+ /// Concatenates four strings.
+{
+ S result = s1;
+ result.reserve(s1.size() + s2.size() + s3.size() + s4.size());
+ result.append(s2);
+ result.append(s3);
+ result.append(s4);
+ return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5)
+ /// Concatenates five strings.
+{
+ S result = s1;
+ result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size());
+ result.append(s2);
+ result.append(s3);
+ result.append(s4);
+ result.append(s5);
+ return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5, const S& s6)
+ /// Concatenates six strings.
+{
+ S result = s1;
+ result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size());
+ result.append(s2);
+ result.append(s3);
+ result.append(s4);
+ result.append(s5);
+ result.append(s6);
+ return result;
+}
+
+
+template <class S, class It>
+S cat(const S& delim, const It& begin, const It& end)
+ /// Concatenates a sequence of strings, delimited
+ /// by the string given in delim.
+{
+ S result;
+ for (It it = begin; it != end; ++it)
+ {
+ if (!result.empty()) result.append(delim);
+ result += *it;
+ }
+ return result;
+}
+
+
+//
+// case-insensitive string equality
+//
+
+
+template <typename charT>
+struct i_char_traits : public std::char_traits<charT>
+{
+ inline static bool eq(charT c1, charT c2)
+ {
+ return Ascii::toLower(c1) == Ascii::toLower(c2);
+ }
+
+ inline static bool ne(charT c1, charT c2)
+ {
+ return !eq(c1, c2);
+ }
+
+ inline static bool lt(charT c1, charT c2)
+ {
+ return Ascii::toLower(c1) < Ascii::toLower(c2);
+ }
+
+ static int compare(const charT* s1, const charT* s2, std::size_t n)
+ {
+ for (int i = 0; i < n && s1 && s2; ++i, ++s1, ++s2)
+ {
+ if (Ascii::toLower(*s1) == Ascii::toLower(*s2)) continue;
+ else if (Ascii::toLower(*s1) < Ascii::toLower(*s2)) return -1;
+ else return 1;
+ }
+
+ return 0;
+ }
+
+ static const charT* find(const charT* s, int n, charT a)
+ {
+ while(n-- > 0 && Ascii::toLower(*s) != Ascii::toLower(a)) { ++s; }
+ return s;
+ }
+};
+
+
+typedef std::basic_string<char, i_char_traits<char> > istring;
+ /// Case-insensitive std::string counterpart.
+
+
+template<typename T>
+std::size_t isubstr(const T& str, const T& sought)
+ /// Case-insensitive substring; searches for a substring
+ /// without regards to case.
+{
+ typename T::const_iterator it = std::search(str.begin(), str.end(),
+ sought.begin(), sought.end(),
+ i_char_traits<typename T::value_type>::eq);
+
+ if (it != str.end()) return it - str.begin();
+ else return static_cast<std::size_t>(T::npos);
+}
+
+
+struct CILess
+ /// Case-insensitive less-than functor; useful for standard maps
+ /// and sets with std::strings keys and case-insensitive ordering
+ /// requirement.
+{
+ inline bool operator() (const std::string& s1, const std::string& s2) const
+ {
+ return icompare(s1, s2) < 0;
+ }
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_String_INCLUDED