aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS2
-rw-r--r--CMakeLists.txt75
-rw-r--r--SConstruct15
-rw-r--r--cmake/FindICU.cmake314
-rw-r--r--cmake/config.hpp.cmake4
-rw-r--r--src/charsetConverter.cpp3
-rw-r--r--src/charsetConverter_iconv.cpp18
-rwxr-xr-xsrc/charsetConverter_icu.cpp202
-rw-r--r--tests/parser/charsetFilteredOutputStreamTest.cpp10
-rw-r--r--tests/parser/charsetTest.cpp3
-rw-r--r--vmime/charsetConverter.hpp6
-rw-r--r--vmime/charsetConverter_iconv.hpp8
-rwxr-xr-xvmime/charsetConverter_icu.hpp84
13 files changed, 727 insertions, 17 deletions
diff --git a/AUTHORS b/AUTHORS
index 98406a08..42b43b4b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -28,7 +28,7 @@ AUTHORS file.
- Zarafa <http://developer.zarafa.com/VmimePatches>
- Bartek Szurgot <[email protected], http://baszerr.org>
- Achim Brandt <http://sourceforge.net/users/a-brandt/>
- - Mehmet Bozkurt <[email protected]> (OpenSSL support)
+ - Mehmet Bozkurt <[email protected]> (OpenSSL support, ICU support)
Please apologize if I have forgotten someone here. ;) Send me an email
to <[email protected]> if you want your name to be listed.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f246d74..6809e7c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,7 +12,7 @@
# http://www.cmake.org
#
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3 FATAL_ERROR)
INCLUDE(cmake/Utils.cmake)
@@ -623,25 +623,74 @@ ENDIF(VMIME_HAVE_TLS_SUPPORT)
##############################################################################
-# iconv
+# Charset conversion library
INCLUDE(cmake/FindIconv.cmake)
+INCLUDE(cmake/FindICU.cmake)
-INCLUDE_DIRECTORIES(
- ${INCLUDE_DIRECTORIES}
- ${ICONV_INCLUDE_DIR}
+FIND_PACKAGE(ICU QUIET)
+
+IF(ICONV_FOUND)
+ SET(VMIME_CHARSETCONV_LIB_IS_ICONV_DEFAULT "ON")
+ SET(VMIME_CHARSETCONV_LIB_IS_ICU_DEFAULT "OFF")
+ELSEIF(ICU_LIBRARIES)
+ SET(VMIME_CHARSETCONV_LIB_IS_ICONV_DEFAULT "OFF")
+ SET(VMIME_CHARSETCONV_LIB_IS_ICU_DEFAULT "ON")
+ENDIF()
+
+OPTION(
+ VMIME_CHARSETCONV_LIB_IS_ICONV
+ "Use iconv library for charset conversion"
+ ${VMIME_CHARSETCONV_LIB_IS_ICONV_DEFAULT}
)
-IF(VMIME_BUILD_SHARED_LIBRARY)
- TARGET_LINK_LIBRARIES(
- ${VMIME_LIBRARY_NAME}
- ${TARGET_LINK_LIBRARIES}
- ${ICONV_LIBRARIES}
+OPTION(
+ VMIME_CHARSETCONV_LIB_IS_ICU
+ "Use ICU library for charset conversion"
+ ${VMIME_CHARSETCONV_LIB_IS_ICU_DEFAULT}
+)
+
+IF(VMIME_CHARSETCONV_LIB_IS_ICONV)
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${ICONV_INCLUDE_DIR}
)
-ENDIF()
-SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} ${ICONV_LIBRARIES}")
-SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} -I${ICONV_INCLUDE_DIR}")
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${ICONV_LIBRARIES}
+ )
+ ENDIF()
+
+ SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} ${ICONV_LIBRARIES}")
+ SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} -I${ICONV_INCLUDE_DIR}")
+
+ELSEIF(VMIME_CHARSETCONV_LIB_IS_ICU)
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${ICU_INCLUDE_DIRS}
+ )
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${ICU_LIBRARIES}
+ )
+ ENDIF()
+
+ SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} ${ICU_LIBRARIES}")
+ SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} -I${ICU_INCLUDE_DIRS}")
+
+ELSE()
+
+ MESSAGE(FATAL_ERROR "No charset conversion library was selected/found")
+
+ENDIF()
##############################################################################
diff --git a/SConstruct b/SConstruct
index 60ee5159..eed044f7 100644
--- a/SConstruct
+++ b/SConstruct
@@ -57,6 +57,7 @@ libvmime_sources = [
'charset.cpp', 'charset.hpp',
'charsetConverter.cpp', 'charsetConverter.hpp',
'charsetConverter_iconv.cpp', 'charsetConverter_iconv.hpp',
+ 'charsetConverter_icu.cpp', 'charsetConverter_icu.hpp',
'charsetConverter_idna.cpp', 'charsetConverter_idna.hpp',
'charsetConverterOptions.cpp', 'charsetConverterOptions.hpp',
'component.cpp', 'component.hpp',
@@ -673,6 +674,15 @@ if env['with_tls'] == 'yes':
env.Append(CXXFLAGS = ['-pthread'])
+# Charset conversion library
+
+# -- iconv
+if sys.platform == "mac" or sys.platform == "darwin":
+ env.Append(LIBS = ['iconv', 'gcrypt'])
+
+# -- ICU
+env.Append(LIBS = ['icuuc', 'icudata', 'icui18n'])
+
# Generate help text for command line options
Help(opts.GenerateHelpText(env))
@@ -836,6 +846,11 @@ config_hpp.write('\n')
config_hpp.write('#define VMIME_HAVE_SIZE_T 1\n')
config_hpp.write('\n')
+config_hpp.write('// Charset conversion support\n')
+config_hpp.write('#define VMIME_CHARSETCONV_LIB_IS_ICONV 1\n')
+config_hpp.write('#define VMIME_CHARSETCONV_LIB_IS_ICU 0\n')
+config_hpp.write('\n')
+
config_hpp.write('// Options\n')
config_hpp.write('// -- File-system support\n')
diff --git a/cmake/FindICU.cmake b/cmake/FindICU.cmake
new file mode 100644
index 00000000..786f157c
--- /dev/null
+++ b/cmake/FindICU.cmake
@@ -0,0 +1,314 @@
+# This module can find the International Components for Unicode (ICU) Library
+#
+# Requirements:
+# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args)
+#
+# The following variables will be defined for your use:
+# - ICU_FOUND : were all of your specified components found (include dependencies)?
+# - ICU_INCLUDE_DIRS : ICU include directory
+# - ICU_LIBRARIES : ICU libraries
+# - ICU_VERSION : complete version of ICU (x.y.z)
+# - ICU_MAJOR_VERSION : major version of ICU
+# - ICU_MINOR_VERSION : minor version of ICU
+# - ICU_PATCH_VERSION : patch version of ICU
+# - ICU_<COMPONENT>_FOUND : were <COMPONENT> found? (FALSE for non specified component if it is not a dependency)
+#
+# For windows or non standard installation, define ICU_ROOT variable to point to the root installation of ICU. Two ways:
+# - run cmake with -DICU_ROOT=<PATH>
+# - define an environment variable with the same name before running cmake
+# With cmake-gui, before pressing "Configure":
+# 1) Press "Add Entry" button
+# 2) Add a new entry defined as:
+# - Name: ICU_ROOT
+# - Type: choose PATH in the selection list
+# - Press "..." button and select the root installation of ICU
+#
+# Example Usage:
+#
+# 1. Copy this file in the root of your project source directory
+# 2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt:
+# set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
+# 3. Finally call find_package() once, here are some examples to pick from
+#
+# Require ICU 4.4 or later
+# find_package(ICU 4.4 REQUIRED)
+#
+# if(ICU_FOUND)
+# include_directories(${ICU_INCLUDE_DIRS})
+# add_executable(myapp myapp.c)
+# target_link_libraries(myapp ${ICU_LIBRARIES})
+# endif(ICU_FOUND)
+
+#=============================================================================
+# Copyright (c) 2011-2012, julp
+# https://github.com/julp/FindICU.cmake
+#
+# Distributed under the OSI-approved BSD License
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#=============================================================================
+
+find_package(PkgConfig QUIET)
+
+########## Private ##########
+set(ICU_PUBLIC_VAR_NS "ICU") # Prefix for all ICU relative public variables
+set(ICU_PRIVATE_VAR_NS "_${ICU_PUBLIC_VAR_NS}") # Prefix for all ICU relative internal variables
+set(PC_ICU_PRIVATE_VAR_NS "_PC${ICU_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables
+
+function(icudebug _VARNAME)
+ if(${ICU_PUBLIC_VAR_NS}_DEBUG)
+ if(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = ${${ICU_PUBLIC_VAR_NS}_${_VARNAME}}")
+ else(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = <UNDEFINED>")
+ endif(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ endif(${ICU_PUBLIC_VAR_NS}_DEBUG)
+endfunction(icudebug)
+
+set(${ICU_PRIVATE_VAR_NS}_ROOT "")
+if(DEFINED ENV{ICU_ROOT})
+ set(${ICU_PRIVATE_VAR_NS}_ROOT "$ENV{ICU_ROOT}")
+endif(DEFINED ENV{ICU_ROOT})
+if (DEFINED ICU_ROOT)
+ set(${ICU_PRIVATE_VAR_NS}_ROOT "${ICU_ROOT}")
+endif(DEFINED ICU_ROOT)
+
+set(${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES )
+set(${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES )
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin64")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib64")
+endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin")
+list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib")
+
+set(${ICU_PRIVATE_VAR_NS}_COMPONENTS )
+# <icu component name> <library name 1> ... <library name N>
+macro(icu_declare_component _NAME)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_COMPONENTS ${_NAME})
+ set("${ICU_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN})
+endmacro(icu_declare_component)
+
+icu_declare_component(data icudata)
+icu_declare_component(uc icuuc) # Common and Data libraries
+icu_declare_component(i18n icui18n icuin) # Internationalization library
+icu_declare_component(io icuio ustdio) # Stream and I/O Library
+icu_declare_component(le icule) # Layout library
+icu_declare_component(lx iculx) # Paragraph Layout library
+
+########## Public ##########
+set(${ICU_PUBLIC_VAR_NS}_FOUND TRUE)
+set(${ICU_PUBLIC_VAR_NS}_LIBRARIES )
+set(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS )
+set(${ICU_PUBLIC_VAR_NS}_C_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS "")
+foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS})
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the icu_declare_component macro
+endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+# Check components
+if(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS) # uc required at least
+ set(${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+else(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+ list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ if(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ message(FATAL_ERROR "Unknown ICU component: ${${ICU_PRIVATE_VAR_NS}_COMPONENT}")
+ endif(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+endif(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+
+# Includes
+find_path(
+ ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+ NAMES unicode/utypes.h utypes.h
+ HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+ PATH_SUFFIXES "include"
+ DOC "Include directories for ICU"
+)
+
+if(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+ ########## <part to keep synced with tests/version/CMakeLists.txt> ##########
+ if(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h") # ICU >= 4
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h") # ICU [2;4[
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h") # ICU [1.4;2[
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h") # ICU 1.3
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ else()
+ message(FATAL_ERROR "ICU version header not found")
+ endif()
+
+ if(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *ICU_VERSION *\"([0-9]+)\".*") # ICU 1.3
+ # [1.3;1.4[ as #define ICU_VERSION "3" (no patch version, ie all 1.3.X versions will be detected as 1.3.0)
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "1")
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+ elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION_MAJOR_NUM *([0-9]+).*")
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+ #
+ # Since version 4.9.1, ICU release version numbering was totaly changed, see:
+ # - http://site.icu-project.org/download/49
+ # - http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
+ #
+ if(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION LESS 49)
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_PATCHLEVEL_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ else(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION LESS 49)
+ string(REGEX MATCH [0-9]$ ${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}")
+ string(REGEX REPLACE [0-9]$ "" ${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}")
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ endif(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION LESS 49)
+ elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION *\"(([0-9]+)(\\.[0-9]+)*)\".*") # ICU [1.4;1.8[
+ # [1.4;1.8[ as #define U_ICU_VERSION "1.4.1.2" but it seems that some 1.4.1(?:\.\d)? have releasing error and appears as 1.4.0
+ set(${ICU_PRIVATE_VAR_NS}_FULL_VERSION "${CMAKE_MATCH_1}") # copy CMAKE_MATCH_1, no longer valid on the following if
+ if(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)$")
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+ elseif(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)")
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${CMAKE_MATCH_3}")
+ endif()
+ else()
+ message(FATAL_ERROR "failed to detect ICU version")
+ endif()
+ set(${ICU_PUBLIC_VAR_NS}_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_MINOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_PATCH_VERSION}")
+ ########## </part to keep synced with tests/version/CMakeLists.txt> ##########
+
+ # Check dependencies (implies pkg-config)
+ if(PKG_CONFIG_FOUND)
+ set(${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP})
+ pkg_check_modules(PC_ICU_PRIVATE_VAR_NS "icu-${${ICU_PRIVATE_VAR_NS}_COMPONENT}" QUIET)
+
+ if(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+ foreach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY ${PC_ICU_LIBRARIES})
+ string(REGEX REPLACE "^icu" "" ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY ${${PC_ICU_PRIVATE_VAR_NS}_LIBRARY})
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY})
+ endforeach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY)
+ endif(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+ list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ endif(PKG_CONFIG_FOUND)
+
+ # Check libraries
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES )
+ set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES )
+ foreach(${ICU_PRIVATE_VAR_NS}_BASE_NAME ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}d")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}d")
+ endforeach(${ICU_PRIVATE_VAR_NS}_BASE_NAME)
+
+ find_library(
+ ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+ NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES}
+ HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+ PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+ DOC "Release libraries for ICU"
+ )
+ find_library(
+ ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+ NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES}
+ HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+ PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+ DOC "Debug libraries for ICU"
+ )
+
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # both not found
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE)
+ set("${ICU_PUBLIC_VAR_NS}_FOUND" FALSE)
+ else(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # one or both found
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE)
+ if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # release not found => we are in debug
+ set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+ elseif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # debug not found => we are in release
+ set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+ else() # both found
+ set(
+ ${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+ optimized ${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+ debug ${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+ )
+ endif()
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+ endif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+ # Try to find out compiler flags
+ find_program(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT} icu-config)
+ if(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ endif(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+
+ # Check find_package arguments
+ include(FindPackageHandleStandardArgs)
+ if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ find_package_handle_standard_args(
+ ${ICU_PUBLIC_VAR_NS}
+ REQUIRED_VARS ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+ VERSION_VAR ${ICU_PUBLIC_VAR_NS}_VERSION
+ )
+ else(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ find_package_handle_standard_args(${ICU_PUBLIC_VAR_NS} "ICU not found" ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+ endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+else(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+ if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ message(FATAL_ERROR "Could not find ICU include directory")
+ endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+endif(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+
+mark_as_advanced(
+ ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+ ${ICU_PUBLIC_VAR_NS}_LIBRARIES
+)
+
+# IN (args)
+icudebug("FIND_COMPONENTS")
+icudebug("FIND_REQUIRED")
+icudebug("FIND_QUIETLY")
+icudebug("FIND_VERSION")
+# OUT
+# Found
+icudebug("FOUND")
+icudebug("UC_FOUND")
+icudebug("I18N_FOUND")
+icudebug("IO_FOUND")
+icudebug("LE_FOUND")
+icudebug("LX_FOUND")
+icudebug("DATA_FOUND")
+# Flags
+icudebug("C_FLAGS")
+icudebug("CPP_FLAGS")
+icudebug("CXX_FLAGS")
+icudebug("C_SHARED_FLAGS")
+icudebug("CPP_SHARED_FLAGS")
+icudebug("CXX_SHARED_FLAGS")
+# Linking
+icudebug("INCLUDE_DIRS")
+icudebug("LIBRARIES")
+# Version
+icudebug("MAJOR_VERSION")
+icudebug("MINOR_VERSION")
+icudebug("PATCH_VERSION")
+icudebug("VERSION")
diff --git a/cmake/config.hpp.cmake b/cmake/config.hpp.cmake
index 3af17eb5..71badf40 100644
--- a/cmake/config.hpp.cmake
+++ b/cmake/config.hpp.cmake
@@ -37,6 +37,10 @@ typedef unsigned @VMIME_32BIT_TYPE@ vmime_uint32;
#cmakedefine01 VMIME_HAVE_SIZE_T
+// Charset conversion support
+#cmakedefine01 VMIME_CHARSETCONV_LIB_IS_ICONV
+#cmakedefine01 VMIME_CHARSETCONV_LIB_IS_ICU
+
// Options
// -- File-system support
#cmakedefine01 VMIME_HAVE_FILESYSTEM_FEATURES
diff --git a/src/charsetConverter.cpp b/src/charsetConverter.cpp
index c2041476..5d3ab626 100644
--- a/src/charsetConverter.cpp
+++ b/src/charsetConverter.cpp
@@ -23,7 +23,6 @@
#include "vmime/charsetConverter.hpp"
-#include "vmime/charsetConverter_iconv.hpp"
#include "vmime/charsetConverter_idna.hpp"
@@ -39,7 +38,7 @@ ref <charsetConverter> charsetConverter::create
if (source == "idna" || dest == "idna")
return vmime::create <charsetConverter_idna>(source, dest, opts);
else
- return vmime::create <charsetConverter_iconv>(source, dest, opts);
+ return createGenericConverter(source, dest, opts);
}
diff --git a/src/charsetConverter_iconv.cpp b/src/charsetConverter_iconv.cpp
index c5d3557e..43556298 100644
--- a/src/charsetConverter_iconv.cpp
+++ b/src/charsetConverter_iconv.cpp
@@ -21,6 +21,12 @@
// the GNU General Public License cover the whole combination.
//
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICONV
+
+
#include "vmime/charsetConverter_iconv.hpp"
#include "vmime/exception.hpp"
@@ -82,6 +88,15 @@ namespace vmime
{
+// static
+ref <charsetConverter> charsetConverter::createGenericConverter
+ (const charset& source, const charset& dest,
+ const charsetConverterOptions& opts)
+{
+ return vmime::create <charsetConverter_iconv>(source, dest, opts);
+}
+
+
charsetConverter_iconv::charsetConverter_iconv
(const charset& source, const charset& dest, const charsetConverterOptions& opts)
: m_desc(NULL), m_source(source), m_dest(dest), m_options(opts)
@@ -433,3 +448,6 @@ void charsetFilteredOutputStream_iconv::flush()
} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_ICONV
diff --git a/src/charsetConverter_icu.cpp b/src/charsetConverter_icu.cpp
new file mode 100755
index 00000000..c5a19dc6
--- /dev/null
+++ b/src/charsetConverter_icu.cpp
@@ -0,0 +1,202 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2013 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICU
+
+
+#include "vmime/charsetConverter_icu.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+
+extern "C"
+{
+#ifndef VMIME_BUILDING_DOC
+
+ #include <unicode/ucnv.h>
+ #include <unicode/ucnv_err.h>
+
+#endif // VMIME_BUILDING_DOC
+}
+
+
+#include <unicode/unistr.h>
+
+
+namespace vmime
+{
+
+
+// static
+ref <charsetConverter> charsetConverter::createGenericConverter
+ (const charset& source, const charset& dest,
+ const charsetConverterOptions& opts)
+{
+ return vmime::create <charsetConverter_icu>(source, dest, opts);
+}
+
+
+charsetConverter_icu::charsetConverter_icu
+ (const charset& source, const charset& dest, const charsetConverterOptions& opts)
+ : m_from(NULL), m_to(NULL), m_source(source), m_dest(dest), m_options(opts)
+{
+ UErrorCode err = U_ZERO_ERROR;
+ m_from = ucnv_open(source.getName().c_str(), &err);
+
+ if (err != U_ZERO_ERROR)
+ throw exceptions::charset_conv_error("Cannot initialize ICU [from] converter.");
+
+ m_to = ucnv_open(dest.getName().c_str(), &err);
+
+ if (err != U_ZERO_ERROR)
+ throw exceptions::charset_conv_error("Cannot initialize ICU [to] converter.");
+}
+
+
+charsetConverter_icu::~charsetConverter_icu()
+{
+ ucnv_close(m_from);
+ ucnv_close(m_to);
+}
+
+
+void charsetConverter_icu::convert(utility::inputStream& in, utility::outputStream& out)
+{
+ UErrorCode err = U_ZERO_ERROR;
+
+ // From buffers
+ char cpInBuffer[16]; // stream data put here
+ size_t outSize = ucnv_getMinCharSize(m_from) * sizeof(cpInBuffer) * sizeof(UChar);
+ UChar* uOutBuffer = new UChar[outSize]; // Unicode chars end up here
+
+ // Auto delete Unicode char buffer
+ vmime::utility::auto_ptr<UChar> cleanup(uOutBuffer);
+
+ // To buffers
+ // converted (char) data end up here
+ size_t cpOutBufferSz = ucnv_getMaxCharSize(m_to) * outSize;
+ char* cpOutBuffer = new char[cpOutBufferSz];
+ vmime::utility::auto_ptr<char> cleanupOut(cpOutBuffer);
+
+ // Set replacement chars for when converting from Unicode to codepage
+ icu::UnicodeString substString(m_options.invalidSequence.c_str());
+ ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err);
+
+ if (U_FAILURE(err))
+ throw exceptions::charset_conv_error("[ICU] Error setting replacement char.");
+
+ // Input data available
+ while (!in.eof())
+ {
+ // Read input data into buffer
+ size_t inLength = static_cast<size_t>(in.read(cpInBuffer, sizeof(cpInBuffer)));
+
+ // Beginning of read data
+ const char* source = &cpInBuffer[0];
+ const char* sourceLimit = source + inLength; // end + 1
+
+ UBool flush = in.eof(); // is this last run?
+
+ UErrorCode toErr;
+
+ // Loop until all source has been processed
+ do
+ {
+ // Set up target pointers
+ UChar* target = uOutBuffer;
+ UChar* targetLimit = target + outSize;
+
+ toErr = U_ZERO_ERROR;
+ ucnv_toUnicode(m_from, &target, targetLimit,
+ &source, sourceLimit, NULL, flush, &toErr);
+
+ if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr))
+ throw exceptions::charset_conv_error("[ICU] Error converting to Unicode from " + m_source.getName());
+
+ // The Unicode source is the buffer just written and the limit
+ // is where the previous conversion stopped (target is moved in the conversion)
+ const UChar* uSource = uOutBuffer;
+ UChar* uSourceLimit = target;
+ UErrorCode fromErr;
+
+ // Loop until converted chars are fully written
+ do
+ {
+ char* cpTarget = &cpOutBuffer[0];
+ const char* cpTargetLimit = cpOutBuffer + cpOutBufferSz;
+
+ fromErr = U_ZERO_ERROR;
+
+ // Write converted bytes (Unicode) to destination codepage
+ ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit,
+ &uSource, uSourceLimit, NULL, flush, &fromErr);
+
+ if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr))
+ throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName());
+
+ // Write to destination stream
+ out.write(cpOutBuffer, (cpTarget - cpOutBuffer));
+
+ } while (fromErr == U_BUFFER_OVERFLOW_ERROR);
+
+ } while (toErr == U_BUFFER_OVERFLOW_ERROR);
+ }
+}
+
+
+void charsetConverter_icu::convert(const string& in, string& out)
+{
+ if (m_source == m_dest)
+ {
+ // No conversion needed
+ out = in;
+ return;
+ }
+
+ out.clear();
+
+ utility::inputStreamStringAdapter is(in);
+ utility::outputStreamStringAdapter os(out);
+
+ convert(is, os);
+
+ os.flush();
+}
+
+
+ref <utility::charsetFilteredOutputStream> charsetConverter_icu::getFilteredOutputStream(utility::outputStream& os)
+{
+ // TODO: implement charsetFilteredOutputStream for ICU
+ return NULL;
+}
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_ICU
diff --git a/tests/parser/charsetFilteredOutputStreamTest.cpp b/tests/parser/charsetFilteredOutputStreamTest.cpp
index 08eeb63c..92c7a595 100644
--- a/tests/parser/charsetFilteredOutputStreamTest.cpp
+++ b/tests/parser/charsetFilteredOutputStreamTest.cpp
@@ -49,6 +49,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest)
vmime::utility::outputStreamStringAdapter os(output);
vmime::ref <vmime::utility::filteredOutputStream> cfos = cc->getFilteredOutputStream(os);
+ VASSERT_NOT_NULL("filteredOutputStream availability", cfos);
+
// føo = 66 c3 b8 6f [UTF8]
// føo = 66 c3 b8 6f [latin1]
@@ -79,6 +81,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest)
vmime::ref <vmime::utility::charsetFilteredOutputStream> os =
conv->getFilteredOutputStream(osa);
+ VASSERT_NOT_NULL("filteredOutputStream availability", os);
+
vmime::utility::inputStreamStringAdapter is(in);
vmime::utility::stream::value_type buffer[16];
@@ -116,6 +120,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest)
vmime::ref <vmime::utility::charsetFilteredOutputStream> os =
conv->getFilteredOutputStream(osa);
+ VASSERT_NOT_NULL("filteredOutputStream availability", os);
+
vmime::utility::inputStreamStringAdapter is(in);
vmime::utility::bufferedStreamCopy(is, *os);
@@ -151,6 +157,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest)
vmime::ref <vmime::utility::charsetFilteredOutputStream> os =
conv->getFilteredOutputStream(osa);
+ VASSERT_NOT_NULL("filteredOutputStream availability", os);
+
vmime::utility::inputStreamStringAdapter is(in);
vmime::utility::stream::value_type buffer[16];
@@ -189,6 +197,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest)
vmime::ref <vmime::utility::charsetFilteredOutputStream> os =
conv->getFilteredOutputStream(osa);
+ VASSERT_NOT_NULL("filteredOutputStream availability", os);
+
vmime::utility::inputStreamStringAdapter is(in);
vmime::utility::stream::value_type buffer[16];
diff --git a/tests/parser/charsetTest.cpp b/tests/parser/charsetTest.cpp
index 2aab7550..915b8560 100644
--- a/tests/parser/charsetTest.cpp
+++ b/tests/parser/charsetTest.cpp
@@ -141,7 +141,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest)
void testUTF7Support()
{
// Ensure UTF-7 is supported, because it is used for IMAP
- VASSERT_EQ("1", "VMime +ACY UTF-7 encoding", convertHelper("VMime & UTF-7 encoding", "utf-8", "utf-7"));
+ VASSERT_EQ("1", "VMime +- UTF-7 encoding", convertHelper("VMime + UTF-7 encoding", "utf-8", "utf-7"));
+ VASSERT_EQ("2", "f+APg-o", convertHelper("\x66\xc3\xb8\x6f", "utf-8", "utf-7"));
}
VMIME_TEST_SUITE_END
diff --git a/vmime/charsetConverter.hpp b/vmime/charsetConverter.hpp
index b7292d66..dcf90e48 100644
--- a/vmime/charsetConverter.hpp
+++ b/vmime/charsetConverter.hpp
@@ -104,6 +104,12 @@ public:
* @return a filtered output stream, or NULL if not supported
*/
virtual ref <utility::charsetFilteredOutputStream> getFilteredOutputStream(utility::outputStream& os) = 0;
+
+private:
+
+ static ref <charsetConverter> createGenericConverter
+ (const charset& source, const charset& dest,
+ const charsetConverterOptions& opts);
};
diff --git a/vmime/charsetConverter_iconv.hpp b/vmime/charsetConverter_iconv.hpp
index 77a6651c..a590b320 100644
--- a/vmime/charsetConverter_iconv.hpp
+++ b/vmime/charsetConverter_iconv.hpp
@@ -25,6 +25,12 @@
#define VMIME_CHARSETCONVERTER_ICONV_HPP_INCLUDED
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICONV
+
+
#include "vmime/charsetConverter.hpp"
@@ -121,4 +127,6 @@ private:
} // vmime
+#endif // VMIME_CHARSETCONV_LIB_IS_ICONV
+
#endif // VMIME_CHARSETCONVERTER_ICONV_HPP_INCLUDED
diff --git a/vmime/charsetConverter_icu.hpp b/vmime/charsetConverter_icu.hpp
new file mode 100755
index 00000000..ba0b82a9
--- /dev/null
+++ b/vmime/charsetConverter_icu.hpp
@@ -0,0 +1,84 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2013 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#ifndef VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
+#define VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICU
+
+
+#include "vmime/charsetConverter.hpp"
+
+
+struct UConverter;
+
+
+namespace vmime
+{
+
+
+/** A generic charset converter which uses ICU library.
+ */
+
+class charsetConverter_icu : public charsetConverter
+{
+public:
+
+ /** Construct and initialize an ICU charset converter.
+ *
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ */
+ charsetConverter_icu(const charset& source, const charset& dest,
+ const charsetConverterOptions& opts = charsetConverterOptions());
+
+ ~charsetConverter_icu();
+
+ void convert(const string& in, string& out);
+ void convert(utility::inputStream& in, utility::outputStream& out);
+
+ ref <utility::charsetFilteredOutputStream> getFilteredOutputStream(utility::outputStream& os);
+
+private:
+
+ UConverter* m_from;
+ UConverter* m_to;
+
+ charset m_source;
+ charset m_dest;
+
+ charsetConverterOptions m_options;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_ICU
+
+#endif // VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED