summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/IDN/ICUConverter.h')
-rw-r--r--Swiften/IDN/ICUConverter.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/Swiften/IDN/ICUConverter.h b/Swiften/IDN/ICUConverter.h
new file mode 100644
index 0000000..6ed760a
--- /dev/null
+++ b/Swiften/IDN/ICUConverter.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+
+#include <unicode/ucnv.h>
+#include <cassert>
+#include <string>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Base/SafeByteArray.h>
+
+namespace Swift {
+
+ class ICUConverter {
+ public:
+ typedef std::vector<UChar, SafeAllocator<UChar> > ICUString;
+
+ ICUConverter() {
+ UErrorCode status = U_ZERO_ERROR;
+ icuConverter.reset(ucnv_open("utf-8", &status), ucnv_close);
+ assert(U_SUCCESS(status));
+ }
+
+ template<typename T>
+ ICUString convertToICUString(const T& s) {
+ ICUString result;
+ result.resize(s.size());
+ UErrorCode status = U_ZERO_ERROR;
+ int icuResultLength = ucnv_toUChars(icuConverter.get(), vecptr(result), result.size(), toConstCharArray(s), s.size(), &status);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ result.resize(icuResultLength);
+ icuResultLength = ucnv_toUChars(icuConverter.get(), vecptr(result), result.size(), toConstCharArray(s), s.size(), &status);
+ }
+ assert(U_SUCCESS(status));
+ result.resize(icuResultLength);
+ return result;
+ }
+
+ std::string convertToString(const ICUString& input) {
+ return std::string(vecptr(convertToArray(input)));
+ }
+
+ std::vector<char, SafeAllocator<char> > convertToArray(const ICUString& input) {
+ std::vector<char, SafeAllocator<char> > result;
+ result.resize(input.size());
+ UErrorCode status = U_ZERO_ERROR;
+ int inputLength = ucnv_fromUChars(icuConverter.get(), vecptr(result), result.size(), vecptr(input), input.size(), &status);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ result.resize(inputLength);
+ inputLength = ucnv_fromUChars(icuConverter.get(), vecptr(result), result.size(), vecptr(input), input.size(), &status);
+ }
+ assert(U_SUCCESS(status));
+
+ result.resize(inputLength + 1);
+ result[result.size() - 1] = '\0';
+ return result;
+ }
+
+ private:
+ static const char* toConstCharArray(const std::string& input) {
+ return input.c_str();
+ }
+
+ static const char* toConstCharArray(const std::vector<unsigned char, SafeAllocator<unsigned char> >& input) {
+ return reinterpret_cast<const char*>(vecptr(input));
+ }
+
+ private:
+ boost::shared_ptr<UConverter> icuConverter;
+ };
+
+}