diff options
Diffstat (limited to 'zen/zstring.h')
-rwxr-xr-x | zen/zstring.h | 318 |
1 files changed, 159 insertions, 159 deletions
diff --git a/zen/zstring.h b/zen/zstring.h index fdb71da0..273efd2f 100755 --- a/zen/zstring.h +++ b/zen/zstring.h @@ -1,159 +1,159 @@ -// *****************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
-// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
-// *****************************************************************************
-
-#ifndef ZSTRING_H_73425873425789
-#define ZSTRING_H_73425873425789
-
-#include "string_base.h"
-
-
- using Zchar = char;
- #define Zstr(x) x
- const Zchar FILE_NAME_SEPARATOR = '/';
-
-//"The reason for all the fuss above" - Loki/SmartPtr
-//a high-performance string for interfacing with native OS APIs in multithreaded contexts
-using Zstring = zen::Zbase<Zchar>;
-
-
-//Compare filepaths: Windows/OS X does NOT distinguish between upper/lower-case, while Linux DOES
-struct CmpFilePath
-{
- int operator()(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen) const;
-};
-
-struct CmpNaturalSort
-{
- int operator()(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen) const;
-};
-
-
-struct LessFilePath
-{
- template <class S> //don't support heterogenous input! => use as container predicate only!
- bool operator()(const S& lhs, const S& rhs) const { using namespace zen; return CmpFilePath()(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) < 0; }
-};
-
-struct LessNaturalSort
-{
- template <class S> //don't support heterogenous input! => use as container predicate only!
- bool operator()(const S& lhs, const S& rhs) const { using namespace zen; return CmpNaturalSort()(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) < 0; }
-};
-
-
-template <class S>
-S makeUpperCopy(S str);
-
-
-template <class S, class T> inline
-bool equalFilePath(const S& lhs, const T& rhs) { using namespace zen; return strEqual(lhs, rhs, CmpFilePath()); }
-
-
-inline
-Zstring appendSeparator(Zstring path) //support rvalue references!
-{
- return zen::endsWith(path, FILE_NAME_SEPARATOR) ? path : (path += FILE_NAME_SEPARATOR); //returning a by-value parameter implicitly converts to r-value!
-}
-
-
-inline
-Zstring getFileExtension(const Zstring& filePath)
-{
- const Zstring shortName = afterLast(filePath, FILE_NAME_SEPARATOR, zen::IF_MISSING_RETURN_ALL);
- return afterLast(shortName, Zchar('.'), zen::IF_MISSING_RETURN_NONE);
-}
-
-
-template <class S, class T, class U>
-S ciReplaceCpy(const S& str, const T& oldTerm, const U& newTerm);
-
-
-
-
-//################################# inline implementation ########################################
-inline
-void makeUpperInPlace(wchar_t* str, size_t strLen)
-{
- std::for_each(str, str + strLen, [](wchar_t& c) { c = std::towupper(c); }); //locale-dependent!
-}
-
-
-inline
-void makeUpperInPlace(char* str, size_t strLen)
-{
- std::for_each(str, str + strLen, [](char& c) { c = std::toupper(static_cast<unsigned char>(c)); }); //locale-dependent!
- //result of toupper() is an unsigned char mapped to int range: the char representation is in the last 8 bits and we need not care about signedness!
- //this should work for UTF-8, too: all chars >= 128 are mapped upon themselves!
-}
-
-
-template <class S> inline
-S makeUpperCopy(S str)
-{
- const size_t len = str.length(); //we assert S is a string type!
- if (len > 0)
- makeUpperInPlace(&*str.begin(), len);
-
- return std::move(str); //"str" is an l-value parameter => no copy elision!
-}
-
-
-inline
-int CmpFilePath::operator()(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen) const
-{
- assert(std::find(lhs, lhs + lhsLen, 0) == lhs + lhsLen); //don't expect embedded nulls!
- assert(std::find(rhs, rhs + rhsLen, 0) == rhs + rhsLen); //
-
- const int rv = std::strncmp(lhs, rhs, std::min(lhsLen, rhsLen));
- if (rv != 0)
- return rv;
- return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
-}
-
-
-template <class S, class T, class U> inline
-S ciReplaceCpy(const S& str, const T& oldTerm, const U& newTerm)
-{
- using namespace zen;
- static_assert(IsSameType<typename GetCharType<S>::Type, typename GetCharType<T>::Type>::value, "");
- static_assert(IsSameType<typename GetCharType<T>::Type, typename GetCharType<U>::Type>::value, "");
- const size_t oldLen = strLength(oldTerm);
- if (oldLen == 0)
- return str;
-
- const S strU = makeUpperCopy(str); //S required to be a string class
- const S oldU = makeUpperCopy<S>(oldTerm); //[!] T not required to be a string class
- assert(strLength(strU) == strLength(str ));
- assert(strLength(oldU) == strLength(oldTerm));
-
- const auto* const newBegin = strBegin(newTerm);
- const auto* const newEnd = newBegin + strLength(newTerm);
-
- S output;
-
- for (size_t pos = 0;;)
- {
- const auto itFound = std::search(strU.begin() + pos, strU.end(),
- oldU.begin(), oldU.end());
- if (itFound == strU.end() && pos == 0)
- return str; //optimize "oldTerm not found": return ref-counted copy
-
- impl::stringAppend(output, str.begin() + pos, str.begin() + (itFound - strU.begin()));
- if (itFound == strU.end())
- return output;
-
- impl::stringAppend(output, newBegin, newEnd);
- pos = (itFound - strU.begin()) + oldLen;
- }
-}
-
- int cmpStringNaturalLinux(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen);
-
-//---------------------------------------------------------------------------
-//ZEN macro consistency checks:
-
-
-#endif //ZSTRING_H_73425873425789
+// ***************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * +// ***************************************************************************** + +#ifndef ZSTRING_H_73425873425789 +#define ZSTRING_H_73425873425789 + +#include "string_base.h" + + + using Zchar = char; + #define Zstr(x) x + const Zchar FILE_NAME_SEPARATOR = '/'; + +//"The reason for all the fuss above" - Loki/SmartPtr +//a high-performance string for interfacing with native OS APIs in multithreaded contexts +using Zstring = zen::Zbase<Zchar>; + + +//Compare filepaths: Windows/OS X does NOT distinguish between upper/lower-case, while Linux DOES +struct CmpFilePath +{ + int operator()(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen) const; +}; + +struct CmpNaturalSort +{ + int operator()(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen) const; +}; + + +struct LessFilePath +{ + template <class S> //don't support heterogenous input! => use as container predicate only! + bool operator()(const S& lhs, const S& rhs) const { using namespace zen; return CmpFilePath()(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) < 0; } +}; + +struct LessNaturalSort +{ + template <class S> //don't support heterogenous input! => use as container predicate only! + bool operator()(const S& lhs, const S& rhs) const { using namespace zen; return CmpNaturalSort()(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) < 0; } +}; + + +template <class S> +S makeUpperCopy(S str); + + +template <class S, class T> inline +bool equalFilePath(const S& lhs, const T& rhs) { using namespace zen; return strEqual(lhs, rhs, CmpFilePath()); } + + +inline +Zstring appendSeparator(Zstring path) //support rvalue references! +{ + return zen::endsWith(path, FILE_NAME_SEPARATOR) ? path : (path += FILE_NAME_SEPARATOR); //returning a by-value parameter implicitly converts to r-value! +} + + +inline +Zstring getFileExtension(const Zstring& filePath) +{ + const Zstring shortName = afterLast(filePath, FILE_NAME_SEPARATOR, zen::IF_MISSING_RETURN_ALL); + return afterLast(shortName, Zchar('.'), zen::IF_MISSING_RETURN_NONE); +} + + +template <class S, class T, class U> +S ciReplaceCpy(const S& str, const T& oldTerm, const U& newTerm); + + + + +//################################# inline implementation ######################################## +inline +void makeUpperInPlace(wchar_t* str, size_t strLen) +{ + std::for_each(str, str + strLen, [](wchar_t& c) { c = std::towupper(c); }); //locale-dependent! +} + + +inline +void makeUpperInPlace(char* str, size_t strLen) +{ + std::for_each(str, str + strLen, [](char& c) { c = std::toupper(static_cast<unsigned char>(c)); }); //locale-dependent! + //result of toupper() is an unsigned char mapped to int range: the char representation is in the last 8 bits and we need not care about signedness! + //this should work for UTF-8, too: all chars >= 128 are mapped upon themselves! +} + + +template <class S> inline +S makeUpperCopy(S str) +{ + const size_t len = str.length(); //we assert S is a string type! + if (len > 0) + makeUpperInPlace(&*str.begin(), len); + + return std::move(str); //"str" is an l-value parameter => no copy elision! +} + + +inline +int CmpFilePath::operator()(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen) const +{ + assert(std::find(lhs, lhs + lhsLen, 0) == lhs + lhsLen); //don't expect embedded nulls! + assert(std::find(rhs, rhs + rhsLen, 0) == rhs + rhsLen); // + + const int rv = std::strncmp(lhs, rhs, std::min(lhsLen, rhsLen)); + if (rv != 0) + return rv; + return static_cast<int>(lhsLen) - static_cast<int>(rhsLen); +} + + +template <class S, class T, class U> inline +S ciReplaceCpy(const S& str, const T& oldTerm, const U& newTerm) +{ + using namespace zen; + static_assert(IsSameType<typename GetCharType<S>::Type, typename GetCharType<T>::Type>::value, ""); + static_assert(IsSameType<typename GetCharType<T>::Type, typename GetCharType<U>::Type>::value, ""); + const size_t oldLen = strLength(oldTerm); + if (oldLen == 0) + return str; + + const S strU = makeUpperCopy(str); //S required to be a string class + const S oldU = makeUpperCopy<S>(oldTerm); //[!] T not required to be a string class + assert(strLength(strU) == strLength(str )); + assert(strLength(oldU) == strLength(oldTerm)); + + const auto* const newBegin = strBegin(newTerm); + const auto* const newEnd = newBegin + strLength(newTerm); + + S output; + + for (size_t pos = 0;;) + { + const auto itFound = std::search(strU.begin() + pos, strU.end(), + oldU.begin(), oldU.end()); + if (itFound == strU.end() && pos == 0) + return str; //optimize "oldTerm not found": return ref-counted copy + + impl::stringAppend(output, str.begin() + pos, str.begin() + (itFound - strU.begin())); + if (itFound == strU.end()) + return output; + + impl::stringAppend(output, newBegin, newEnd); + pos = (itFound - strU.begin()) + oldLen; + } +} + + int cmpStringNaturalLinux(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen); + +//--------------------------------------------------------------------------- +//ZEN macro consistency checks: + + +#endif //ZSTRING_H_73425873425789 |