/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "itkInternationalizationIOHelpers.h" #include // Some utility functions for the test #if defined(ITK_SUPPORTS_WCHAR_T_FILENAME_CSTYLEIO) && \ (defined(ITK_SUPPORTS_WCHAR_T_FILENAME_IOSTREAMS_CONSTRUCTORS) || defined(ITK_SUPPORTS_FDSTREAM_HPP)) # define LOCAL_USE_WIN32_WOPEN 1 #else # define LOCAL_USE_WIN32_WOPEN 0 #endif // Check if alpha.txt exists using _wfopen with a wstring on MSVC and mingw // and fopen with a UTF-8 char * otherwise bool checkAlphaExists() { #if LOCAL_USE_WIN32_WOPEN // mingw has _wfopen std::wstring wstr; wstr.push_back((wchar_t)(0x03B1)); wstr += L".txt"; FILE * tmp = _wfopen(wstr.c_str(), L"r"); #else std::string utf8_str; utf8_str.append(1, '\xCE'); utf8_str.append(1, '\xB1'); utf8_str += ".txt"; FILE * tmp = fopen(utf8_str.c_str(), "r"); #endif if (tmp != nullptr) { // closing is required at least for mingw to be able to delete the file afterwards fclose(tmp); return true; } return false; } // Try to delete alpha.txt using wunlink with a wstring on MSVC // and unlink with UTF-8 char * otherwise bool removeAlpha() { #if LOCAL_USE_WIN32_WOPEN // mingw has _wunlink std::wstring wstr; wstr.push_back((wchar_t)(0x03B1)); wstr += L".txt"; return (_wunlink(wstr.c_str()) != -1); #else std::string utf8_str; utf8_str.append(1, '\xCE'); utf8_str.append(1, '\xB1'); utf8_str += ".txt"; return (unlink(utf8_str.c_str()) != -1); #endif } // Temporarily use its own main to start by sorting out compilation problems // without too much annoyance to the rest of the world // main will then become // int itkUnicodeIOTest( int , char * [] ) int main(int, char *[]) { std::cout << "Starting unicode IO test." << std::endl; int nberror = 0; // Put alpha.txt encoded in utf8 within a std::string std::string utf8_str; utf8_str.append(1, '\xCE'); utf8_str.append(1, '\xB1'); utf8_str += ".txt"; // Check if we actually find it is a valid string if (!itk::i18n::IsStringEncodingValid(utf8_str)) { std::cout << "Wrongly detected invalid utf8 string." << std::endl; ++nberror; } #if LOCAL_USE_WIN32_WOPEN // Check that the string to wide string conversion works std::wstring utf16_str; utf16_str.push_back((wchar_t)(0x03B1)); utf16_str += L".txt"; const std::wstring fromutf8_utf16_str = itk::i18n::Utf8StringToWString(utf8_str); if (fromutf8_utf16_str != utf16_str) { std::cout << "Utf-8 to utf-16 conversion failed" << std::endl; ++nberror; } // Create a non utf8 std::string std::string bad_utf8_str; bad_utf8_str.push_back('\xCE'); bad_utf8_str.push_back('\xCE'); bad_utf8_str += ".txt"; // Check if we actually find it is a non-valid utf-8 string if (itk::i18n::IsStringEncodingValid(bad_utf8_str)) { std::cout << "Did not detect invalid utf8 string using windows API." << std::endl; ++nberror; } #endif // Start by removing alpha.txt if it exists removeAlpha(); // Create alpha.txt using utf8fopen FILE * wfile = itk::i18n::I18nFopen(utf8_str, "wb"); if (!checkAlphaExists()) { std::cout << "alpha.txt does not exist after utf8fopen." << std::endl; ++nberror; } if (wfile != nullptr) { fputs("test", wfile); fclose(wfile); } else { std::cout << "wfile is null." << std::endl; ++nberror; } FILE * rfile = itk::i18n::I18nFopen(utf8_str, "rb"); if (rfile != nullptr) { char teststring[10]; char * retptr = fgets(teststring, 10, rfile); if (retptr != nullptr) { std::cout << "teststring=" << teststring << std::endl; if (strcmp(teststring, "test") != 0) { std::cout << "teststring is not equal to test." << std::endl; ++nberror; } } else { std::cout << "Could not read from file after I18nFopen." << std::endl; ++nberror; } fclose(rfile); } else { std::cout << "rfile is null." << std::endl; ++nberror; } if (!removeAlpha()) { std::cout << "Could not remove alpha.txt after I18nFopen." << std::endl; ++nberror; } // Create alpha.txt using open and write to it using streams itk::i18n::I18nOfstream wstream(utf8_str.c_str(), std::ios::binary | std::ios::out); if (!checkAlphaExists()) { std::cout << "alpha.txt does not exist after I18nOfstream creation." << std::endl; ++nberror; } if (wstream.is_open()) { wstream << "teststream" << std::flush; } else { std::cout << "wstream is not open." << std::endl; ++nberror; } wstream.close(); itk::i18n::I18nIfstream rstream(utf8_str.c_str(), std::ios::binary | std::ios::in); if (rstream.is_open()) { std::string teststring; std::getline(rstream, teststring); std::cout << "teststring=" << teststring << std::endl; if (teststring != std::string("teststream")) { std::cout << "teststring is not equal to teststream." << std::endl; ++nberror; } rstream.close(); } else { std::cout << "rstream is not open." << std::endl; ++nberror; } if (!removeAlpha()) { std::cout << "Could not remove alpha.txt after I18nOfstream creation." << std::endl; ++nberror; } // Check number of errors if (nberror > 0) { std::cout << "Test failed with " << nberror << " errors." << std::endl; return EXIT_FAILURE; } std::cout << "Test passed." << std::endl; return EXIT_SUCCESS; }