ITK
4.1.0
Insight Segmentation and Registration Toolkit
|
00001 /*========================================================================= 00002 * 00003 * Copyright Insight Software Consortium 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0.txt 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 * 00017 *=========================================================================*/ 00018 #ifndef __itkInternationalizationIOHelpers_h 00019 #define __itkInternationalizationIOHelpers_h 00020 00021 // This header provides some helper functions to deal with unicode filenames 00022 // It is mainly directed towards being able to use utf-8 encoded filenames 00023 // on windows. 00024 // This should help better dealing with internationalization (a.k.a i18n) 00025 00026 #include "itkMacro.h" 00027 #include "itkIOConfigure.h" 00028 00029 #ifdef ITK_HAVE_UNISTD_H 00030 #include <unistd.h> // for unlink 00031 #else 00032 #include <io.h> 00033 #endif 00034 00035 #include <stdio.h> 00036 #include <fcntl.h> 00037 #include <iostream> 00038 #include <string> 00039 #include <sys/stat.h> 00040 00041 // Find out how to handle unicode filenames on windows: 00042 // * VS>=8.0 has _wopen and _wfopen and can open a (i/o)fstream using a wide 00043 // string 00044 // * VS7.x and MinGW have _wopen and _wfopen but cannot open a 00045 // (i/o)fstream using a wide string. They can however compile fdstream 00046 00047 #if defined( ITK_SUPPORTS_WCHAR_T_FILENAME_CSTYLEIO ) \ 00048 && ( defined( ITK_SUPPORTS_WCHAR_T_FILENAME_IOSTREAMS_CONSTRUCTORS ) || defined( ITK_SUPPORTS_FDSTREAM_HPP ) ) 00049 #define LOCAL_USE_WIN32_WOPEN 1 00050 #include <windows.h> // required by winnls.h 00051 #include <winnls.h> // for MultiByteToWideChar 00052 #else 00053 #define LOCAL_USE_WIN32_WOPEN 0 00054 #endif 00055 00056 #if ( LOCAL_USE_WIN32_WOPEN && defined( ITK_SUPPORTS_WCHAR_T_FILENAME_IOSTREAMS_CONSTRUCTORS ) ) \ 00057 || ( !LOCAL_USE_WIN32_WOPEN ) 00058 #define LOCAL_USE_FDSTREAM 0 00059 #include <fstream> 00060 #else 00061 #define LOCAL_USE_FDSTREAM 1 00062 #include "itkfdstream/fdstream.hpp" 00063 #endif 00064 00065 namespace itk 00066 { 00067 namespace i18n 00068 { 00069 // Check if the string is correctly encoded 00070 #if LOCAL_USE_WIN32_WOPEN 00071 inline bool IsStringEncodingValid(const std::string & str) 00072 { 00073 // Check if the string is really encoded in utf-8 using windows API 00074 // MultiByteToWideChar returns 0 if there was a problem during conversion 00075 // when given the MB_ERR_INVALID_CHARS flag 00076 const int utf16_size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), 00077 static_cast< int >( str.length() ), 0, 0); 00078 00079 return ( utf16_size != 0 ); 00080 } 00081 00082 #else 00083 inline bool IsStringEncodingValid( const std::string & itkNotUsed(str) ) 00084 { 00085 return true; 00086 } 00087 00088 #endif 00089 00090 #if LOCAL_USE_WIN32_WOPEN 00091 // Convert a utf8 encoded std::string to a utf16 encoded wstring on windows 00092 inline std::wstring Utf8StringToWString(const std::string & str) 00093 { 00094 // We do not set the MB_ERR_INVALID_CHARS to do an approximate conversion when 00095 // non 00096 // utf8 characters are found. An alternative would be to throw an exception 00097 00098 // First get the size 00099 const int utf16_size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), 00100 static_cast< int >( str.length() ), 0, 0); 00101 00102 // Now do the conversion 00103 std::wstring wstr; 00104 00105 wstr.resize(utf16_size); 00106 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), 00107 static_cast< int >( str.length() ), &wstr[0], utf16_size); 00108 00109 return wstr; 00110 } 00111 00112 #endif 00113 00114 // Get a file descriptor from a filename (using utf8 to wstring 00115 // on windows if requested) without specifying any specific permissions 00116 inline int I18nOpen(const std::string & str, const int & flags) 00117 { 00118 #if LOCAL_USE_WIN32_WOPEN 00119 // mingw has _wopen 00120 // Convert to utf16 00121 const std::wstring str_utf16 = Utf8StringToWString(str); 00122 return _wopen(str_utf16.c_str(), flags); 00123 #else 00124 return open(str.c_str(), flags); 00125 #endif 00126 } 00127 00128 // Get a file descriptor from a filename (using utf8 to wstring 00129 // on windows if requested) 00130 inline int I18nOpen(const std::string & str, const int & flags, const int & mode) 00131 { 00132 #if LOCAL_USE_WIN32_WOPEN 00133 // mingw has _wopen 00134 // Convert to utf16 00135 const std::wstring str_utf16 = Utf8StringToWString(str); 00136 return _wopen(str_utf16.c_str(), flags, mode); 00137 #else 00138 return open(str.c_str(), flags, mode); 00139 #endif 00140 } 00141 00142 // Reading wrapper around I18nOpen to avoid explicitely specifying the flags 00143 inline int I18nOpenForReading(const std::string & str) 00144 { 00145 #if LOCAL_USE_WIN32_WOPEN 00146 return I18nOpen(str, _O_RDONLY | _O_BINARY); 00147 #else 00148 return I18nOpen(str, O_RDONLY); 00149 #endif 00150 } 00151 00152 // Writing wrapper around I18nOpen to avoid explicitely specifying the flags 00153 inline int I18nOpenForWriting(const std::string & str, const bool append = false) 00154 { 00155 #if LOCAL_USE_WIN32_WOPEN 00156 if ( !append ) { return I18nOpen(str, _O_WRONLY | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE); } 00157 else { return I18nOpen(str, _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY, _S_IREAD | _S_IWRITE); } 00158 #else 00159 if ( !append ) { return I18nOpen(str, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); } 00160 else { return I18nOpen(str, O_WRONLY | O_CREAT | O_APPEND, S_IREAD | S_IWRITE); } 00161 #endif 00162 } 00163 00164 // Get a FILE * pointer from a filename (using utf8 to wstring 00165 // on windows if requested) 00166 inline FILE * I18nFopen(const std::string & str, const std::string & mode) 00167 { 00168 #if LOCAL_USE_WIN32_WOPEN 00169 // Convert to utf16 00170 const std::wstring str_utf16 = Utf8StringToWString(str); 00171 const std::wstring mode_utf16 = Utf8StringToWString(mode); 00172 return _wfopen( str_utf16.c_str(), mode_utf16.c_str() ); 00173 #else 00174 return fopen( str.c_str(), mode.c_str() ); 00175 #endif 00176 } 00177 00178 #if LOCAL_USE_FDSTREAM 00179 class I18nOfstream:public std::ostream 00180 { 00181 public: 00182 I18nOfstream(const char *str, 00183 std::ios_base::openmode mode = std::ios_base::out): 00184 std::ostream(0), 00185 m_fd( I18nOpenForWriting(str, ( mode & std::ios::app ) ? true:false) ), 00186 m_buf(m_fd) 00187 { 00189 this->rdbuf(&m_buf); 00190 } 00191 00192 ~I18nOfstream() { this->close(); } 00193 00194 bool is_open() { return ( m_fd != -1 ); } 00195 00196 void close() 00197 { 00198 if ( m_fd != -1 ) { ::close(m_fd); } 00199 m_fd = -1; 00200 } 00201 00202 private: 00203 int m_fd; 00204 itk::fdoutbuf m_buf; 00205 }; 00206 00207 class I18nIfstream:public std::istream 00208 { 00209 public: 00210 I18nIfstream(const char *str, 00211 std::ios_base::openmode mode = std::ios_base::in): 00212 std::istream(0), 00213 m_fd( I18nOpenForReading(str) ), 00214 m_buf(m_fd) 00215 { 00217 (void) mode; 00218 this->rdbuf(&m_buf); 00219 } 00220 00221 ~I18nIfstream() { this->close(); } 00222 00223 bool is_open() { return ( m_fd != -1 ); } 00224 00225 void close() 00226 { 00227 if ( m_fd != -1 ) { ::close(m_fd); } 00228 m_fd = -1; 00229 } 00230 00231 private: 00232 int m_fd; 00233 itk::fdinbuf m_buf; 00234 }; 00235 #elif LOCAL_USE_WIN32_WOPEN 00236 class I18nOfstream:public std::ofstream 00237 { 00238 public: 00239 I18nOfstream(const char *str, std::ios_base::openmode mode = std::ios_base::out): 00240 std::ofstream(Utf8StringToWString(str).c_str(), mode) 00241 {} 00242 }; 00243 00244 class I18nIfstream:public std::ifstream 00245 { 00246 public: 00247 I18nIfstream(const char *str, std::ios_base::openmode mode = std::ios_base::in): 00248 std::ifstream(Utf8StringToWString(str).c_str(), mode) 00249 {} 00250 }; 00251 #else 00252 typedef std::ofstream I18nOfstream; 00253 typedef std::ifstream I18nIfstream; 00254 #endif 00255 } // end namespace 00256 } // end namespace 00257 00258 #undef LOCAL_USE_WIN32_WOPEN 00259 #undef LOCAL_USE_FDSTREAM 00260 00261 #endif /* __itkInternationalizationIOHelpers_h */ 00262