diff options
Diffstat (limited to 'Swiften/Base')
-rw-r--r-- | Swiften/Base/API.h | 4 | ||||
-rw-r--r-- | Swiften/Base/Algorithm.h | 5 | ||||
-rw-r--r-- | Swiften/Base/BoostRandomGenerator.h | 3 | ||||
-rw-r--r-- | Swiften/Base/ByteArray.cpp | 11 | ||||
-rw-r--r-- | Swiften/Base/ByteArray.h | 7 | ||||
-rw-r--r-- | Swiften/Base/DateTime.cpp | 5 | ||||
-rw-r--r-- | Swiften/Base/DateTime.h | 5 | ||||
-rw-r--r-- | Swiften/Base/Error.h | 2 | ||||
-rw-r--r-- | Swiften/Base/Listenable.h | 52 | ||||
-rw-r--r-- | Swiften/Base/Log.cpp | 34 | ||||
-rw-r--r-- | Swiften/Base/Log.h | 40 | ||||
-rw-r--r-- | Swiften/Base/Override.h | 34 | ||||
-rw-r--r-- | Swiften/Base/Path.cpp | 28 | ||||
-rw-r--r-- | Swiften/Base/Path.h | 27 | ||||
-rw-r--r-- | Swiften/Base/Paths.cpp | 9 | ||||
-rw-r--r-- | Swiften/Base/RandomGenerator.h | 4 | ||||
-rw-r--r-- | Swiften/Base/Regex.cpp | 37 | ||||
-rw-r--r-- | Swiften/Base/Regex.h | 19 | ||||
-rw-r--r-- | Swiften/Base/SConscript | 3 | ||||
-rw-r--r-- | Swiften/Base/SafeAllocator.cpp | 27 | ||||
-rw-r--r-- | Swiften/Base/SafeAllocator.h | 10 | ||||
-rw-r--r-- | Swiften/Base/SafeByteArray.h | 4 | ||||
-rw-r--r-- | Swiften/Base/String.cpp | 39 | ||||
-rw-r--r-- | Swiften/Base/String.h | 9 | ||||
-rw-r--r-- | Swiften/Base/UnitTest/PathTest.cpp | 36 | ||||
-rw-r--r-- | Swiften/Base/UnitTest/StringTest.cpp | 15 |
26 files changed, 434 insertions, 35 deletions
diff --git a/Swiften/Base/API.h b/Swiften/Base/API.h index 8f19446..388ad0a 100644 --- a/Swiften/Base/API.h +++ b/Swiften/Base/API.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Remko Tronçon + * Copyright (c) 2012-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,6 +17,8 @@ # else # define SWIFTEN_API __declspec(dllimport) # endif +# elif __GNUC__ >= 4 +# define SWIFTEN_API __attribute__((visibility("default"))) # else # define SWIFTEN_API # endif 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); |