8 changed files with 329 additions and 31 deletions
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Daniel Scharrer |
||||
* |
||||
* This software is provided 'as-is', without any express or implied |
||||
* warranty. In no event will the author(s) be held liable for any damages |
||||
* arising from the use of this software. |
||||
* |
||||
* Permission is granted to anyone to use this software for any purpose, |
||||
* including commercial applications, and to alter it and redistribute it |
||||
* freely, subject to the following restrictions: |
||||
* |
||||
* 1. The origin of this software must not be misrepresented; you must not |
||||
* claim that you wrote the original software. If you use this software |
||||
* in a product, an acknowledgment in the product documentation would be |
||||
* appreciated but is not required. |
||||
* 2. Altered source versions must be plainly marked as such, and must not be |
||||
* misrepresented as being the original software. |
||||
* 3. This notice may not be removed or altered from any source distribution. |
||||
*/ |
||||
|
||||
/*!
|
||||
* boost::filesystems::{i,o,}fstream doesn't support unicode names on windows |
||||
* Implement our own wrapper using boost::iostreams. |
||||
*/ |
||||
#ifndef INNOEXTRACT_UTIL_FSTREAM_HPP |
||||
#define INNOEXTRACT_UTIL_FSTREAM_HPP |
||||
|
||||
#if !defined(_WIN32) |
||||
|
||||
#include <boost/filesystem/fstream.hpp> |
||||
|
||||
namespace util { |
||||
|
||||
typedef boost::filesystem::ifstream ifstream; |
||||
typedef boost::filesystem::ofstream ofstream; |
||||
typedef boost::filesystem::fstream fstream; |
||||
|
||||
} // namespace util
|
||||
|
||||
#else // if defined(_WIN32)
|
||||
|
||||
#include <boost/filesystem/path.hpp> |
||||
#include <boost/iostreams/device/file_descriptor.hpp> |
||||
#include <boost/iostreams/stream.hpp> |
||||
|
||||
namespace util { |
||||
|
||||
/*!
|
||||
* {i,o,}fstream implementation with support for Unicode filenames. |
||||
* Create a subclass instead of a typedef to force boost::filesystem::path parameters. |
||||
*/ |
||||
template <typename Device> |
||||
class path_fstream : public boost::iostreams::stream<Device> { |
||||
|
||||
private: // disallow copying
|
||||
|
||||
path_fstream(const path_fstream &); |
||||
const path_fstream & operator=(const path_fstream &); |
||||
|
||||
typedef boost::filesystem::path path; |
||||
typedef boost::iostreams::stream<Device> base; |
||||
|
||||
Device & device() { return **this; } |
||||
|
||||
void fix_open_mode(std::ios_base::openmode mode); |
||||
|
||||
public: |
||||
|
||||
path_fstream() : base(Device()) { } |
||||
|
||||
explicit path_fstream(const path & p) : base(p) { } |
||||
|
||||
path_fstream(const path & p, std::ios_base::openmode mode) : base(p, mode) { |
||||
fix_open_mode(mode); |
||||
} |
||||
|
||||
void open(const path & p) { |
||||
base::close(); |
||||
base::open(p); |
||||
} |
||||
|
||||
void open(const path & p, std::ios_base::openmode mode) { |
||||
base::close(); |
||||
base::open(p, mode); |
||||
fix_open_mode(mode); |
||||
} |
||||
|
||||
bool is_open() { |
||||
return device().is_open(); // return the real open state, not base::is_open()
|
||||
} |
||||
|
||||
virtual ~path_fstream() { } |
||||
}; |
||||
|
||||
template <> |
||||
inline void path_fstream<boost::iostreams::file_descriptor_source> |
||||
::fix_open_mode(std::ios_base::openmode mode) { |
||||
if((mode & std::ios_base::ate) && is_open()) { |
||||
seekg(0, std::ios_base::end); |
||||
} |
||||
} |
||||
|
||||
template <> |
||||
inline void path_fstream<boost::iostreams::file_descriptor_sink> |
||||
::fix_open_mode(std::ios_base::openmode mode) { |
||||
if((mode & std::ios_base::ate) && is_open()) { |
||||
seekp(0, std::ios_base::end); |
||||
} |
||||
} |
||||
|
||||
template <> |
||||
inline void path_fstream<boost::iostreams::file_descriptor> |
||||
::fix_open_mode(std::ios_base::openmode mode) { |
||||
if((mode & std::ios_base::ate) && is_open()) { |
||||
seekg(0, std::ios_base::end); |
||||
seekp(0, std::ios_base::end); |
||||
} |
||||
} |
||||
|
||||
typedef path_fstream<boost::iostreams::file_descriptor_source> ifstream; |
||||
typedef path_fstream<boost::iostreams::file_descriptor_sink> ofstream; |
||||
typedef path_fstream<boost::iostreams::file_descriptor> fstream; |
||||
|
||||
} // namespace util
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // INNOEXTRACT_UTIL_FSTREAM_HPP
|
||||
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Daniel Scharrer |
||||
* |
||||
* This software is provided 'as-is', without any express or implied |
||||
* warranty. In no event will the author(s) be held liable for any damages |
||||
* arising from the use of this software. |
||||
* |
||||
* Permission is granted to anyone to use this software for any purpose, |
||||
* including commercial applications, and to alter it and redistribute it |
||||
* freely, subject to the following restrictions: |
||||
* |
||||
* 1. The origin of this software must not be misrepresented; you must not |
||||
* claim that you wrote the original software. If you use this software |
||||
* in a product, an acknowledgment in the product documentation would be |
||||
* appreciated but is not required. |
||||
* 2. Altered source versions must be plainly marked as such, and must not be |
||||
* misrepresented as being the original software. |
||||
* 3. This notice may not be removed or altered from any source distribution. |
||||
*/ |
||||
|
||||
#ifndef _WIN32 |
||||
#define _WIN32 |
||||
#endif |
||||
#include "util/windows.hpp" |
||||
|
||||
#include <locale> |
||||
#include <clocale> |
||||
|
||||
#include <windows.h> |
||||
|
||||
#include <boost/filesystem/path.hpp> |
||||
|
||||
#include "configure.hpp" |
||||
|
||||
#if INNOEXTRACT_HAVE_STD_CODECVT_UTF8_UTF16 |
||||
// C++11
|
||||
#include <codecvt> |
||||
namespace { typedef std::codecvt_utf8_utf16<wchar_t> utf8_codecvt; } |
||||
#else |
||||
// Using private Boost stuff - bad, but meh.
|
||||
#include <boost/filesystem/detail/utf8_codecvt_facet.hpp> |
||||
namespace { typedef boost::filesystem::detail::utf8_codecvt_facet utf8_codecvt; } |
||||
#endif |
||||
|
||||
// We really want main here, not utf8_main.
|
||||
#undef main |
||||
int main() { |
||||
|
||||
// We use UTF-8 for everything internally, as almost all modern operating systems
|
||||
// have standardized on that. However, as usual, Windows has to do its own thing
|
||||
// and only supports Unicode input/output via UCS-2^H^H^H^H^HUTF-16.
|
||||
|
||||
std::setlocale(LC_ALL, ""); |
||||
|
||||
// Get the UTF-16 command-line parameters and convert it them to UTF-8 ourself.
|
||||
int argc = __argc; |
||||
wchar_t ** wargv = __wargv; |
||||
char ** argv = new char *[argc + 1]; |
||||
argv[argc] = NULL; |
||||
for(int i = 0; i < argc; i++) { |
||||
int n = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, NULL); |
||||
argv[i] = new char[n]; |
||||
WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], n, NULL, NULL); |
||||
} |
||||
|
||||
// Tell boost::filesystem to interpret our path strings as UTF-8.
|
||||
std::locale global_locale = std::locale(); |
||||
std::locale utf8_locale(global_locale, new utf8_codecvt); |
||||
boost::filesystem::path::imbue(utf8_locale); |
||||
|
||||
return utf8_main(argc, argv); |
||||
} |
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Daniel Scharrer |
||||
* |
||||
* This software is provided 'as-is', without any express or implied |
||||
* warranty. In no event will the author(s) be held liable for any damages |
||||
* arising from the use of this software. |
||||
* |
||||
* Permission is granted to anyone to use this software for any purpose, |
||||
* including commercial applications, and to alter it and redistribute it |
||||
* freely, subject to the following restrictions: |
||||
* |
||||
* 1. The origin of this software must not be misrepresented; you must not |
||||
* claim that you wrote the original software. If you use this software |
||||
* in a product, an acknowledgment in the product documentation would be |
||||
* appreciated but is not required. |
||||
* 2. Altered source versions must be plainly marked as such, and must not be |
||||
* misrepresented as being the original software. |
||||
* 3. This notice may not be removed or altered from any source distribution. |
||||
*/ |
||||
|
||||
/*!
|
||||
* Compatibility wrapper to work around deficiencies in Microsoft® Windows™. |
||||
* Mostly deals with converting between UTF-8 and UTF-16 input/output. |
||||
* More precisely: |
||||
* - Converts wide char command-line arguments to UTF-8 and calls utf8_main(). |
||||
* - Sets an UTF-8 locale for boost::filesystem::path. |
||||
* This makes everything in boost::filesystem UTF-8 aware, except for {i,o,}fstream. |
||||
* For those, there are UTF-8 aware implementations in util/fstream.hpp |
||||
*/ |
||||
#ifndef INNOEXTRACT_UTIL_WINDOWS_HPP |
||||
#define INNOEXTRACT_UTIL_WINDOWS_HPP |
||||
|
||||
#if defined(_WIN32) |
||||
|
||||
//! Program entry point that will always receive UTF-8 encoded arguments.
|
||||
int utf8_main(int argc, char * argv[]); |
||||
|
||||
//! We define our own wrapper main(), so rename the real one.
|
||||
#define main utf8_main |
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // INNOEXTRACT_UTIL_WINDOWS_HPP
|
||||
Loading…
Reference in new issue