summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Base')
-rw-r--r--Swiften/Base/Algorithm.h5
-rw-r--r--Swiften/Base/BoostRandomGenerator.h3
-rw-r--r--Swiften/Base/ByteArray.cpp11
-rw-r--r--Swiften/Base/ByteArray.h7
-rw-r--r--Swiften/Base/DateTime.cpp5
-rw-r--r--Swiften/Base/DateTime.h5
-rw-r--r--Swiften/Base/Error.h2
-rw-r--r--Swiften/Base/Listenable.h52
-rw-r--r--Swiften/Base/Log.cpp34
-rw-r--r--Swiften/Base/Log.h40
-rw-r--r--Swiften/Base/Override.h34
-rw-r--r--Swiften/Base/Path.cpp28
-rw-r--r--Swiften/Base/Path.h27
-rw-r--r--Swiften/Base/Paths.cpp9
-rw-r--r--Swiften/Base/RandomGenerator.h4
-rw-r--r--Swiften/Base/Regex.cpp37
-rw-r--r--Swiften/Base/Regex.h19
-rw-r--r--Swiften/Base/SConscript3
-rw-r--r--Swiften/Base/SafeAllocator.cpp27
-rw-r--r--Swiften/Base/SafeAllocator.h10
-rw-r--r--Swiften/Base/SafeByteArray.h4
-rw-r--r--Swiften/Base/String.cpp39
-rw-r--r--Swiften/Base/String.h9
-rw-r--r--Swiften/Base/UnitTest/PathTest.cpp36
-rw-r--r--Swiften/Base/UnitTest/StringTest.cpp15
25 files changed, 431 insertions, 34 deletions
diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h
index 4e68e70..d5edab1 100644
--- a/Swiften/Base/Algorithm.h
+++ b/Swiften/Base/Algorithm.h
@@ -99,6 +99,11 @@ namespace Swift {
target.insert(target.end(), source.begin(), source.end());
}
+ template<typename Source, typename Target>
+ void assign(Target& target, const Source& source) {
+ target.assign(source.begin(), source.end());
+ }
+
template<typename A, typename B, typename C, typename D>
B get(const std::map<A, B, C, D>& map, const A& key, const B& defaultValue) {
typename std::map<A, B, C, D>::const_iterator i = map.find(key);
diff --git a/Swiften/Base/BoostRandomGenerator.h b/Swiften/Base/BoostRandomGenerator.h
index b5a6cac..6065ff3 100644
--- a/Swiften/Base/BoostRandomGenerator.h
+++ b/Swiften/Base/BoostRandomGenerator.h
@@ -7,6 +7,7 @@
#pragma once
#include <Swiften/Base/RandomGenerator.h>
+#include <Swiften/Base/Override.h>
#include <boost/random/mersenne_twister.hpp>
@@ -15,7 +16,7 @@ namespace Swift {
public:
BoostRandomGenerator();
- int generateRandomInteger(int max);
+ int generateRandomInteger(int max) SWIFTEN_OVERRIDE;
private:
boost::mt19937 generator;
diff --git a/Swiften/Base/ByteArray.cpp b/Swiften/Base/ByteArray.cpp
index 6be96aa..466db5f 100644
--- a/Swiften/Base/ByteArray.cpp
+++ b/Swiften/Base/ByteArray.cpp
@@ -1,24 +1,25 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Base/ByteArray.h>
-#include <fstream>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/filesystem/fstream.hpp>
namespace Swift {
static const int BUFFER_SIZE = 4096;
-void readByteArrayFromFile(ByteArray& data, const std::string& file) {
- std::ifstream input(file.c_str(), std::ios_base::in|std::ios_base::binary);
+void readByteArrayFromFile(ByteArray& data, const boost::filesystem::path& file) {
+ boost::filesystem::ifstream input(file, std::ios_base::in|std::ios_base::binary);
while (input.good()) {
size_t oldSize = data.size();
data.resize(oldSize + BUFFER_SIZE);
input.read(reinterpret_cast<char*>(&data[oldSize]), BUFFER_SIZE);
- data.resize(oldSize + input.gcount());
+ data.resize(oldSize + boost::numeric_cast<size_t>(input.gcount()));
}
input.close();
}
diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h
index 34b89d3..133b75f 100644
--- a/Swiften/Base/ByteArray.h
+++ b/Swiften/Base/ByteArray.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -10,6 +10,7 @@
#include <string>
#include <Swiften/Base/API.h>
+#include <boost/filesystem/path.hpp>
namespace Swift {
typedef std::vector<unsigned char> ByteArray;
@@ -26,7 +27,7 @@ namespace Swift {
}
inline ByteArray createByteArray(char c) {
- return std::vector<unsigned char>(1, c);
+ return std::vector<unsigned char>(1, static_cast<unsigned char>(c));
}
template<typename T, typename A>
@@ -41,6 +42,6 @@ namespace Swift {
SWIFTEN_API std::string byteArrayToString(const ByteArray& b);
- SWIFTEN_API void readByteArrayFromFile(ByteArray&, const std::string& file);
+ SWIFTEN_API void readByteArrayFromFile(ByteArray&, const boost::filesystem::path& file);
}
diff --git a/Swiften/Base/DateTime.cpp b/Swiften/Base/DateTime.cpp
index fae26d4..5d192c4 100644
--- a/Swiften/Base/DateTime.cpp
+++ b/Swiften/Base/DateTime.cpp
@@ -10,6 +10,7 @@
#include <boost/date_time/time_facet.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/c_local_time_adjustor.hpp>
#include <Swiften/Base/String.h>
@@ -31,4 +32,8 @@ std::string dateTimeToString(const boost::posix_time::ptime& time) {
return stampString;
}
+std::string dateTimeToLocalString(const boost::posix_time::ptime& time) {
+ return boost::posix_time::to_simple_string(boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(time));
+}
+
}
diff --git a/Swiften/Base/DateTime.h b/Swiften/Base/DateTime.h
index bc9eecb..891b170 100644
--- a/Swiften/Base/DateTime.h
+++ b/Swiften/Base/DateTime.h
@@ -20,4 +20,9 @@ namespace Swift {
* Converts a UTC ptime object to a XEP-0082 formatted string.
*/
SWIFTEN_API std::string dateTimeToString(const boost::posix_time::ptime& time);
+
+ /**
+ * Converts a UTC ptime object to a localized human readable string.
+ */
+ SWIFTEN_API std::string dateTimeToLocalString(const boost::posix_time::ptime& time);
}
diff --git a/Swiften/Base/Error.h b/Swiften/Base/Error.h
index 906c1d9..d9f3b91 100644
--- a/Swiften/Base/Error.h
+++ b/Swiften/Base/Error.h
@@ -13,4 +13,4 @@ namespace Swift {
public:
virtual ~Error();
};
-};
+}
diff --git a/Swiften/Base/Listenable.h b/Swiften/Base/Listenable.h
new file mode 100644
index 0000000..445dfd7
--- /dev/null
+++ b/Swiften/Base/Listenable.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <boost/bind.hpp>
+#include <algorithm>
+
+namespace Swift {
+ template<typename T>
+ class SWIFTEN_API Listenable {
+ public:
+ void addListener(T* listener) {
+ listeners.push_back(listener);
+ }
+
+ void removeListener(T* listener) {
+ listeners.erase(std::remove(listeners.begin(), listeners.end(), listener), listeners.end());
+ }
+
+ protected:
+ template<typename F>
+ void notifyListeners(F event) {
+ for (typename std::vector<T*>::iterator i = listeners.begin(); i != listeners.end(); ++i) {
+ event(*i);
+ }
+ }
+
+ template<typename F, typename A1>
+ void notifyListeners(F f, const A1& a1) {
+ notifyListeners(boost::bind(f, _1, a1));
+ }
+
+ template<typename F, typename A1, typename A2>
+ void notifyListeners(F f, const A1& a1, const A2& a2) {
+ notifyListeners(boost::bind(f, _1, a1, a2));
+ }
+
+ template<typename F, typename A1, typename A2, typename A3>
+ void notifyListeners(F f, const A1& a1, const A2& a2, const A3& a3) {
+ notifyListeners(boost::bind(f, _1, a1, a2, a3));
+ }
+
+ private:
+ std::vector<T*> listeners;
+ };
+}
+
diff --git a/Swiften/Base/Log.cpp b/Swiften/Base/Log.cpp
index 4132353..317798c 100644
--- a/Swiften/Base/Log.cpp
+++ b/Swiften/Base/Log.cpp
@@ -1,13 +1,43 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Base/Log.h>
+#include <cstdio>
+
+
namespace Swift {
-bool logging = false;
+static Log::Severity logLevel = Log::warning;
+
+Log::Log() {
+}
+
+Log::~Log() {
+ // Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic)
+ fprintf(stderr, "%s", stream.str().c_str());
+ fflush(stderr);
+}
+
+std::ostringstream& Log::getStream(
+ Severity /*severity*/,
+ const std::string& severityString,
+ const std::string& file,
+ int line,
+ const std::string& function) {
+ stream << "[" << severityString << "] " << file << ":" << line << " " << function << ": ";
+ return stream;
+}
+
+Log::Severity Log::getLogLevel() {
+ return logLevel;
+}
+
+void Log::setLogLevel(Severity level) {
+ logLevel = level;
+}
}
diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h
index 6d76dc6..a46860f 100644
--- a/Swiften/Base/Log.h
+++ b/Swiften/Base/Log.h
@@ -1,26 +1,44 @@
/*
- * Copyright (c) 2010-2012 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
-#include <iostream>
+#include <sstream>
#include <Swiften/Base/API.h>
namespace Swift {
- extern SWIFTEN_API bool logging;
- namespace LogDetail {
- // Only here to be able to statically check the correctness of the severity levers
- namespace Severity {
- enum {
- debug, info, warning, error
+ class SWIFTEN_API Log {
+ public:
+ enum Severity {
+ error, warning, info, debug
};
- }
- }
+
+ Log();
+ ~Log();
+
+ std::ostringstream& getStream(
+ Severity severity,
+ const std::string& severityString,
+ const std::string& file,
+ int line,
+ const std::string& function);
+
+ static Severity getLogLevel();
+ static void setLogLevel(Severity level);
+
+ private:
+ std::ostringstream stream;
+ };
}
#define SWIFT_LOG(severity) \
- if (!Swift::logging) {} else (void) LogDetail::Severity::severity, std::cerr << "[" << #severity << "] " << __FILE__ << ":" << __LINE__ << " " << __FUNCTION__ << ": "
+ if (Log::severity > Log::getLogLevel()) ; \
+ else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__)
+
+#define SWIFT_LOG_ASSERT(test, severity) \
+ if (Log::severity > Log::getLogLevel() || (test)) ; \
+ else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) << "Assertion failed: " << #test << ". "
diff --git a/Swiften/Base/Override.h b/Swiften/Base/Override.h
new file mode 100644
index 0000000..6d9baaa
--- /dev/null
+++ b/Swiften/Base/Override.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#if defined(__clang__)
+# if __has_feature(cxx_override_control) || __has_extension(cxx_override_control)
+# define SWIFTEN_OVERRIDE override
+# else
+# define SWIFTEN_OVERRIDE
+# endif
+
+#elif defined(__GNUC__)
+# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) && defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define SWIFTEN_OVERRIDE override
+# else
+# define SWIFTEN_OVERRIDE
+# endif
+
+#elif defined(_MSC_VER)
+// Actually, 1700 is the first version that supports the C++11 override, but
+// older versions apparently support a similar keyword.
+# if _MSC_VER >= 1400
+# define SWIFTEN_OVERRIDE override
+# else
+# define SWIFTEN_OVERRIDE
+# endif
+
+#else
+# define SWIFTEN_OVERRIDE
+#endif
diff --git a/Swiften/Base/Path.cpp b/Swiften/Base/Path.cpp
new file mode 100644
index 0000000..2a49676
--- /dev/null
+++ b/Swiften/Base/Path.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Base/Path.h>
+
+#include <Swiften/Base/Platform.h>
+#include <Swiften/Base/String.h>
+
+using namespace Swift;
+
+boost::filesystem::path Swift::stringToPath(const std::string& path) {
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ return boost::filesystem::path(convertStringToWString(path));
+#else
+ return boost::filesystem::path(path);
+#endif
+}
+
+std::string Swift::pathToString(const boost::filesystem::path& path) {
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ return convertWStringToString(path.native());
+#else
+ return path.native();
+#endif
+}
diff --git a/Swiften/Base/Path.h b/Swiften/Base/Path.h
new file mode 100644
index 0000000..ea99be9
--- /dev/null
+++ b/Swiften/Base/Path.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <boost/filesystem/path.hpp>
+#include <string>
+
+namespace Swift {
+ /**
+ * Creates a path for the given UTF-8 encoded string.
+ * This works independently of global locale settings.
+ */
+ SWIFTEN_API boost::filesystem::path stringToPath(const std::string&);
+
+ /**
+ * Returns the UTF-8 representation of the given path
+ * This works independently of global locale settings.
+ */
+ SWIFTEN_API std::string pathToString(const boost::filesystem::path&);
+}
+
+
diff --git a/Swiften/Base/Paths.cpp b/Swiften/Base/Paths.cpp
index edebc30..8ad1159 100644
--- a/Swiften/Base/Paths.cpp
+++ b/Swiften/Base/Paths.cpp
@@ -30,16 +30,17 @@ boost::filesystem::path Paths::getExecutablePath() {
#elif defined(SWIFTEN_PLATFORM_LINUX)
ByteArray path;
path.resize(4096);
- ssize_t size = readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size());
+ size_t size = static_cast<size_t>(readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size()));
if (size > 0) {
path.resize(size);
return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path();
}
#elif defined(SWIFTEN_PLATFORM_WINDOWS)
- ByteArray data;
+ std::vector<wchar_t> data;
data.resize(2048);
- GetModuleFileName(NULL, reinterpret_cast<char*>(vecptr(data)), data.size());
- return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(data)), data.size()).c_str()).parent_path();
+ GetModuleFileNameW(NULL, vecptr(data), data.size());
+ return boost::filesystem::path(
+ std::wstring(vecptr(data), data.size())).parent_path();
#endif
return boost::filesystem::path();
}
diff --git a/Swiften/Base/RandomGenerator.h b/Swiften/Base/RandomGenerator.h
index 8f33020..eb5b84d 100644
--- a/Swiften/Base/RandomGenerator.h
+++ b/Swiften/Base/RandomGenerator.h
@@ -14,6 +14,10 @@ namespace Swift {
public:
virtual ~RandomGenerator();
+ /**
+ * Generates a random integer between 0 and 'max',
+ * 'max' inclusive.
+ */
virtual int generateRandomInteger(int max) = 0;
};
}
diff --git a/Swiften/Base/Regex.cpp b/Swiften/Base/Regex.cpp
new file mode 100644
index 0000000..5e3d89a
--- /dev/null
+++ b/Swiften/Base/Regex.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+/*
+ * Copyright (c) 2012 Maciej Niedzielski
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Base/Regex.h>
+
+#include <string>
+
+#include <boost/regex.hpp>
+
+namespace Swift {
+
+ namespace Regex {
+ std::string escape(const std::string& source) {
+ // escape regex special characters: ^.$| etc
+ // these need to be escaped: [\^\$\|.........]
+ // and then C++ requires '\' to be escaped, too....
+ static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])");
+ // matched character should be prepended with '\'
+ // replace matched special character with \\\1
+ // and escape once more for C++ rules...
+ static const std::string rep("\\\\\\1");
+ return boost::regex_replace(source, esc, rep);
+ }
+
+ }
+
+}
+
diff --git a/Swiften/Base/Regex.h b/Swiften/Base/Regex.h
new file mode 100644
index 0000000..6d12a60
--- /dev/null
+++ b/Swiften/Base/Regex.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <Swiften/Base/API.h>
+
+namespace Swift {
+
+ namespace Regex {
+ SWIFTEN_API std::string escape(const std::string& source);
+ }
+
+}
diff --git a/Swiften/Base/SConscript b/Swiften/Base/SConscript
index 754164b..094059a 100644
--- a/Swiften/Base/SConscript
+++ b/Swiften/Base/SConscript
@@ -4,8 +4,10 @@ objects = swiften_env.SwiftenObject([
"ByteArray.cpp",
"DateTime.cpp",
"SafeByteArray.cpp",
+ "SafeAllocator.cpp",
"Error.cpp",
"Log.cpp",
+ "Path.cpp",
"Paths.cpp",
"String.cpp",
"IDGenerator.cpp",
@@ -14,5 +16,6 @@ objects = swiften_env.SwiftenObject([
"BoostRandomGenerator.cpp",
"sleep.cpp",
"URL.cpp",
+ "Regex.cpp"
])
swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Base/SafeAllocator.cpp b/Swiften/Base/SafeAllocator.cpp
new file mode 100644
index 0000000..d61d8b9
--- /dev/null
+++ b/Swiften/Base/SafeAllocator.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Base/SafeByteArray.h>
+
+#include <Swiften/Base/Platform.h>
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+#include <windows.h>
+#endif
+
+namespace Swift {
+
+void secureZeroMemory(char* memory, size_t numberOfBytes) {
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ SecureZeroMemory(memory, numberOfBytes);
+#else
+ volatile char* p = memory;
+ for (size_t i = 0; i < numberOfBytes; ++i) {
+ *(p++) = 0;
+ }
+#endif
+}
+
+}
diff --git a/Swiften/Base/SafeAllocator.h b/Swiften/Base/SafeAllocator.h
index 9f9dd42..b01d77d 100644
--- a/Swiften/Base/SafeAllocator.h
+++ b/Swiften/Base/SafeAllocator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -10,6 +10,8 @@
#include <algorithm>
namespace Swift {
+ void secureZeroMemory(char* memory, size_t numberOfBytes);
+
template<typename T>
class SafeAllocator : public std::allocator<T> {
public:
@@ -23,8 +25,10 @@ namespace Swift {
~SafeAllocator() throw() {}
void deallocate (T* p, size_t num) {
- std::fill(reinterpret_cast<char*>(p), reinterpret_cast<char*>(p + num), 0);
+ secureZeroMemory(reinterpret_cast<char*>(p), num);
std::allocator<T>::deallocate(p, num);
}
+
+ private:
};
-};
+}
diff --git a/Swiften/Base/SafeByteArray.h b/Swiften/Base/SafeByteArray.h
index dda51fe..b85373c 100644
--- a/Swiften/Base/SafeByteArray.h
+++ b/Swiften/Base/SafeByteArray.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -31,7 +31,7 @@ namespace Swift {
}
inline SafeByteArray createSafeByteArray(char c) {
- return SafeByteArray(1, c);
+ return SafeByteArray(1, static_cast<unsigned char>(c));
}
inline SafeByteArray createSafeByteArray(const char* c, size_t n) {
diff --git a/Swiften/Base/String.cpp b/Swiften/Base/String.cpp
index 242b8e5..40ea2e1 100644
--- a/Swiften/Base/String.cpp
+++ b/Swiften/Base/String.cpp
@@ -1,15 +1,21 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
+#include <Swiften/Base/Platform.h>
+
#include <cassert>
#include <algorithm>
#include <sstream>
#include <iomanip>
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+#include <windows.h>
+#endif
#include <Swiften/Base/String.h>
+#include <Swiften/Base/ByteArray.h>
namespace Swift {
@@ -113,4 +119,35 @@ int String::convertHexStringToInt(const std::string& s) {
return h;
}
+
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+std::string convertWStringToString(const std::wstring& s) {
+ int utf8Size = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL);
+ if (utf8Size < 0) {
+ throw std::runtime_error("Conversion error");
+ }
+ std::vector<char> utf8Data(utf8Size);
+ int result = WideCharToMultiByte(
+ CP_UTF8, 0, s.c_str(), -1, vecptr(utf8Data), utf8Data.size(), NULL, NULL);
+ if (result < 0) {
+ throw std::runtime_error("Conversion error");
+ }
+ return std::string(vecptr(utf8Data), utf8Size-1 /* trailing 0 character */);
+}
+
+std::wstring convertStringToWString(const std::string& s) {
+ int utf16Size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0);
+ if (utf16Size < 0) {
+ throw std::runtime_error("Conversion error");
+ }
+ std::vector<wchar_t> utf16Data(utf16Size);
+ int result = MultiByteToWideChar(
+ CP_UTF8, 0, s.c_str(), -1, vecptr(utf16Data), utf16Data.size());
+ if (result < 0) {
+ throw std::runtime_error("Conversion error");
+ }
+ return std::wstring(vecptr(utf16Data), utf16Size-1 /* trailing 0 character */);
+}
+#endif
+
}
diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h
index de181a1..5a5642e 100644
--- a/Swiften/Base/String.h
+++ b/Swiften/Base/String.h
@@ -11,6 +11,7 @@
#include <sstream>
#include <Swiften/Base/API.h>
+#include <Swiften/Base/Platform.h>
#define SWIFTEN_STRING_TO_CFSTRING(a) \
CFStringCreateWithBytes(NULL, reinterpret_cast<const UInt8*>(a.c_str()), a.size(), kCFStringEncodingUTF8, false)
@@ -32,7 +33,13 @@ namespace Swift {
std::string convertIntToHexString(int h);
int convertHexStringToInt(const std::string& s);
- };
+
+ }
+
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ SWIFTEN_API std::string convertWStringToString(const std::wstring& s);
+ SWIFTEN_API std::wstring convertStringToWString(const std::string& s);
+#endif
class SWIFTEN_API makeString {
public:
diff --git a/Swiften/Base/UnitTest/PathTest.cpp b/Swiften/Base/UnitTest/PathTest.cpp
new file mode 100644
index 0000000..f5f99e7
--- /dev/null
+++ b/Swiften/Base/UnitTest/PathTest.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swiften/Base/Path.h>
+#include <Swiften/Base/Platform.h>
+
+using namespace Swift;
+
+class PathTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(PathTest);
+ CPPUNIT_TEST(testStringToPath);
+ CPPUNIT_TEST(testPathToString);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testStringToPath() {
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == stringToPath("tron\xc3\xa7on").native());
+#else
+ CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), stringToPath("tron\xc3\xa7on").native());
+#endif
+ }
+
+ void testPathToString() {
+ CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), pathToString(stringToPath("tron\xc3\xa7on")));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PathTest);
+
diff --git a/Swiften/Base/UnitTest/StringTest.cpp b/Swiften/Base/UnitTest/StringTest.cpp
index b29f331..ffca98a 100644
--- a/Swiften/Base/UnitTest/StringTest.cpp
+++ b/Swiften/Base/UnitTest/StringTest.cpp
@@ -9,6 +9,7 @@
#include <string>
#include <Swiften/Base/String.h>
+#include <Swiften/Base/Platform.h>
using namespace Swift;
@@ -24,6 +25,10 @@ class StringTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testReplaceAll_ConsecutiveChars);
CPPUNIT_TEST(testReplaceAll_MatchingReplace);
CPPUNIT_TEST(testSplit);
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ CPPUNIT_TEST(testConvertWStringToString);
+ CPPUNIT_TEST(testConvertStringToWString);
+#endif
CPPUNIT_TEST_SUITE_END();
public:
@@ -109,6 +114,16 @@ class StringTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("def"), result[1]);
CPPUNIT_ASSERT_EQUAL(std::string("ghi"), result[2]);
}
+
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ void testConvertWStringToString() {
+ CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), convertWStringToString(std::wstring(L"tron\xe7on")));
+ }
+
+ void testConvertStringToWString() {
+ CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == convertStringToWString(std::string("tron\xc3\xa7on")));
+ }
+#endif
};
CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);