summaryrefslogtreecommitdiff
path: root/zen/zstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'zen/zstring.h')
-rw-r--r--zen/zstring.h118
1 files changed, 87 insertions, 31 deletions
diff --git a/zen/zstring.h b/zen/zstring.h
index 462ea39c..3a431ea7 100644
--- a/zen/zstring.h
+++ b/zen/zstring.h
@@ -4,15 +4,11 @@
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
-#ifndef ZSTRING_H_INCLUDED_73425873425789
-#define ZSTRING_H_INCLUDED_73425873425789
+#ifndef ZSTRING_H_73425873425789
+#define ZSTRING_H_73425873425789
#include "string_base.h"
-#ifdef ZEN_LINUX
- #include <cstring> //strncmp
-#endif
-
#ifdef ZEN_WIN //Windows encodes Unicode as UTF-16 wchar_t
typedef wchar_t Zchar;
@@ -30,33 +26,33 @@
typedef zen::Zbase<Zchar, zen::StorageRefCountThreadSafe, zen::AllocatorOptimalSpeed> Zstring;
+int cmpStringNoCase(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rhsLen);
+#if defined ZEN_LINUX || defined ZEN_MAC
+ int cmpStringNoCase(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen);
+#endif
+
+template <class S, class T> inline
+bool equalNoCase(const S& lhs, const T& rhs) { using namespace zen; return cmpStringNoCase(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) == 0; }
+
+template <class S>
+S makeUpperCopy(S str);
-//Compare filepaths: Windows does NOT distinguish between upper/lower-case, while Linux DOES
-int cmpFilePath(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rhsLen);
+//Compare filepaths: Windows/OS X does NOT distinguish between upper/lower-case, while Linux DOES
+int cmpFilePath(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rhsLen);
#if defined ZEN_LINUX || defined ZEN_MAC
int cmpFilePath(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen);
#endif
+template <class S, class T> inline
+bool equalFilePath(const S& lhs, const T& rhs) { using namespace zen; return cmpFilePath(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) == 0; }
-
-
-struct LessFilePath //case-insensitive on Windows, case-sensitive on Linux
+struct LessFilePath
{
template <class S, class T>
bool operator()(const S& lhs, const T& rhs) const { using namespace zen; return cmpFilePath(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) < 0; }
};
-struct EqualFilePath //case-insensitive on Windows, case-sensitive on Linux
-{
- template <class S, class T>
- bool operator()(const S& lhs, const T& rhs) const { using namespace zen; return cmpFilePath(strBegin(lhs), strLength(lhs), strBegin(rhs), strLength(rhs)) == 0; }
-};
-
-
-#if defined ZEN_WIN || defined ZEN_MAC
- Zstring makeUpperCopy(const Zstring& str);
-#endif
inline
@@ -103,38 +99,98 @@ bool pathEndsWith(const S& str, const T& postfix)
//################################# inline implementation ########################################
+#ifdef ZEN_WIN
+void makeUpperInPlace(wchar_t* str, size_t strLen);
-#if defined ZEN_LINUX || defined ZEN_MAC
+#elif defined ZEN_LINUX || defined ZEN_MAC
inline
-int cmpFilePath(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen)
+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, so 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!
+}
+
+
+inline
+int cmpStringNoCase(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rhsLen)
+{
+ 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 = ::wcsncasecmp(lhs, rhs, std::min(lhsLen, rhsLen)); //locale-dependent!
+ if (rv != 0)
+ return rv;
+ return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
+}
+
+
+inline
+int cmpStringNoCase(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen)
{
assert(std::find(lhs, lhs + lhsLen, 0) == lhs + lhsLen); //don't expect embedded nulls!
assert(std::find(rhs, rhs + rhsLen, 0) == rhs + rhsLen); //
-#if defined ZEN_LINUX
- const int rv = std::strncmp(lhs, rhs, std::min(lhsLen, rhsLen));
-#elif defined ZEN_MAC
const int rv = ::strncasecmp(lhs, rhs, std::min(lhsLen, rhsLen)); //locale-dependent!
-#endif
if (rv != 0)
return rv;
return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
}
+#endif
+
+
+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(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rhsLen)
{
+#if defined ZEN_WIN || defined ZEN_MAC
+ return cmpStringNoCase(lhs, lhsLen, rhs, rhsLen);
+
+#elif defined ZEN_LINUX
assert(std::find(lhs, lhs + lhsLen, 0) == lhs + lhsLen); //don't expect embedded nulls!
assert(std::find(rhs, rhs + rhsLen, 0) == rhs + rhsLen); //
-#if defined ZEN_LINUX
const int rv = std::wcsncmp(lhs, rhs, std::min(lhsLen, rhsLen));
-#elif defined ZEN_MAC
- const int rv = ::wcsncasecmp(lhs, rhs, std::min(lhsLen, rhsLen)); //locale-dependent!
+ if (rv != 0)
+ return rv;
+ return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
#endif
+}
+
+
+#if defined ZEN_LINUX || defined ZEN_MAC
+inline
+int cmpFilePath(const char* lhs, size_t lhsLen, const char* rhs, size_t rhsLen)
+{
+#if defined ZEN_MAC
+ return cmpStringNoCase(lhs, lhsLen, rhs, rhsLen);
+
+#elif defined ZEN_LINUX
+ 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);
+#endif
}
#endif
@@ -172,4 +228,4 @@ int cmpFilePath(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rh
#error no target platform defined
#endif
-#endif //ZSTRING_H_INCLUDED_73425873425789
+#endif //ZSTRING_H_73425873425789
bgstack15