summaryrefslogtreecommitdiff
path: root/zen/zstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'zen/zstring.h')
-rw-r--r--zen/zstring.h216
1 files changed, 216 insertions, 0 deletions
diff --git a/zen/zstring.h b/zen/zstring.h
new file mode 100644
index 00000000..0ba9f108
--- /dev/null
+++ b/zen/zstring.h
@@ -0,0 +1,216 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#ifndef ZSTRING_H_INCLUDED
+#define ZSTRING_H_INCLUDED
+
+#include "string_base.h"
+#include <cstring> //strcmp()
+
+#ifndef NDEBUG
+#include "thread.h" //includes <boost/thread.hpp>
+#include <map>
+#endif
+
+
+#ifndef NDEBUG
+class LeakChecker //small test for memory leaks
+{
+public:
+ void insert(const void* ptr, size_t size)
+ {
+ boost::lock_guard<boost::mutex> dummy(lockActStrings);
+ if (activeStrings.find(ptr) != activeStrings.end())
+ reportProblem(std::string("Fatal Error: New memory points into occupied space: ") + rawMemToString(ptr, size));
+
+ activeStrings[ptr] = size;
+ }
+
+ void remove(const void* ptr)
+ {
+ boost::lock_guard<boost::mutex> dummy(lockActStrings);
+ if (activeStrings.find(ptr) == activeStrings.end())
+ reportProblem(std::string("Fatal Error: No memory available for deallocation at this location!"));
+
+ activeStrings.erase(ptr);
+ }
+
+ static LeakChecker& instance();
+
+private:
+ LeakChecker() {}
+ LeakChecker(const LeakChecker&);
+ LeakChecker& operator=(const LeakChecker&);
+ ~LeakChecker();
+
+ static std::string rawMemToString(const void* ptr, size_t size);
+ void reportProblem(const std::string& message); //throw (std::logic_error)
+
+ boost::mutex lockActStrings;
+ typedef std::map<const void*, size_t> VoidPtrSizeMap;
+ VoidPtrSizeMap activeStrings;
+};
+#endif //NDEBUG
+
+
+class AllocatorFreeStoreChecked
+{
+public:
+ static void* allocate(size_t size) //throw (std::bad_alloc)
+ {
+#ifndef NDEBUG
+ void* newMem = ::operator new(size);
+ LeakChecker::instance().insert(newMem, size); //test Zbase for memory leaks
+ return newMem;
+#else
+ return ::operator new(size);
+#endif
+ }
+
+ static void deallocate(void* ptr)
+ {
+#ifndef NDEBUG
+ LeakChecker::instance().remove(ptr); //check for memory leaks
+#endif
+ ::operator delete(ptr);
+ }
+
+ static size_t calcCapacity(size_t length) { return std::max<size_t>(16, length + length / 2); } //exponential growth + min size
+};
+
+
+//############################## helper functions #############################################
+#if defined(FFS_WIN) || defined(FFS_LINUX)
+//Compare filenames: Windows does NOT distinguish between upper/lower-case, while Linux DOES
+template <class T, template <class, class> class SP, class AP> int cmpFileName(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs);
+
+struct LessFilename //case-insensitive on Windows, case-sensitive on Linux
+{
+ template <class T, template <class, class> class SP, class AP>
+ bool operator()(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs) const;
+};
+
+struct EqualFilename //case-insensitive on Windows, case-sensitive on Linux
+{
+ template <class T, template <class, class> class SP, class AP>
+ bool operator()(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs) const;
+};
+#endif
+
+#ifdef FFS_WIN
+template <template <class, class> class SP, class AP>
+void makeUpper(Zbase<wchar_t, SP, AP>& str);
+#endif
+
+#ifdef FFS_WIN //Windows stores filenames in wide character format
+typedef wchar_t Zchar;
+#define Zstr(x) L ## x
+const Zchar FILE_NAME_SEPARATOR = L'\\';
+
+#elif defined FFS_LINUX //Linux uses UTF-8
+typedef char Zchar;
+#define Zstr(x) x
+const Zchar FILE_NAME_SEPARATOR = '/';
+
+#else
+#error define platform you are in: FFS_WIN or FFS_LINUX
+#endif
+
+//"The reason for all the fuss above" - Loki/SmartPtr
+//a high-performant string for use as file name in multithreaded contexts
+typedef Zbase<Zchar, StorageRefCountThreadSafe, AllocatorFreeStoreChecked> Zstring;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//################################# inline implementation ########################################
+#if defined(FFS_WIN) || defined(FFS_LINUX)
+namespace z_impl
+{
+int compareFilenamesWin(const wchar_t* a, const wchar_t* b, size_t sizeA, size_t sizeB);
+void makeUpperCaseWin(wchar_t* str, size_t size);
+}
+
+
+template <class T, template <class, class> class SP, class AP>
+inline
+int cmpFileName(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs)
+{
+#ifdef FFS_WIN
+ return z_impl::compareFilenamesWin(lhs.data(), rhs.data(), lhs.length(), rhs.length());
+#elif defined FFS_LINUX
+ return ::strcmp(lhs.c_str(), rhs.c_str()); //POSIX filenames don't have embedded 0
+#endif
+}
+
+
+template <class T, template <class, class> class SP, class AP>
+inline
+bool LessFilename::operator()(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs) const
+{
+#ifdef FFS_WIN
+ return z_impl::compareFilenamesWin(lhs.data(), rhs.data(), lhs.length(), rhs.length()) < 0;
+#elif defined FFS_LINUX
+ return ::strcmp(lhs.c_str(), rhs.c_str()) < 0; //POSIX filenames don't have embedded 0
+#endif
+}
+
+
+template <class T, template <class, class> class SP, class AP>
+inline
+bool EqualFilename::operator()(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs) const
+{
+#ifdef FFS_WIN
+ return z_impl::compareFilenamesWin(lhs.data(), rhs.data(), lhs.length(), rhs.length()) == 0;
+#elif defined FFS_LINUX
+ return ::strcmp(lhs.c_str(), rhs.c_str()) == 0; //POSIX filenames don't have embedded 0
+#endif
+}
+#endif //defined(FFS_WIN) || defined(FFS_LINUX)
+
+
+#ifdef FFS_WIN
+template <template <class, class> class SP, class AP>
+inline
+void makeUpper(Zbase<wchar_t, SP, AP>& str)
+{
+ z_impl::makeUpperCaseWin(str.begin(), str.length());
+}
+#endif
+
+
+namespace std
+{
+template<> inline
+void swap(Zstring& rhs, Zstring& lhs)
+{
+ rhs.swap(lhs);
+}
+}
+
+#endif //ZSTRING_H_INCLUDED
bgstack15