Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -247,6 +247,7 @@ # if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_ARM) || defined(__arm__)) # define _LIBCPP_HAS_BITSCAN64 # endif +# define _LIBCPP_HAS_OPEN_WITH_WCHAR # if defined(_LIBCPP_MSVCRT) # define _LIBCPP_HAS_QUICK_EXIT # endif Index: include/fstream =================================================================== --- include/fstream +++ include/fstream @@ -212,6 +212,9 @@ bool is_open() const; #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE basic_filebuf* open(const char* __s, ios_base::openmode __mode); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + basic_filebuf* open(const wchar_t* __s, ios_base::openmode __mode); +#endif _LIBCPP_INLINE_VISIBILITY basic_filebuf* open(const string& __s, ios_base::openmode __mode); #endif @@ -551,6 +554,90 @@ return __rt; } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +// This is basically the same as the char* overload except that it uses _wfopen +// and long mode strings. +template +basic_filebuf<_CharT, _Traits>* +basic_filebuf<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) +{ + basic_filebuf<_CharT, _Traits>* __rt = 0; + if (__file_ == 0) + { + __rt = this; + const wchar_t* __mdstr; + switch (__mode & ~ios_base::ate) + { + case ios_base::out: + case ios_base::out | ios_base::trunc: + __mdstr = L"w"; + break; + case ios_base::out | ios_base::app: + case ios_base::app: + __mdstr = L"a"; + break; + case ios_base::in: + __mdstr = L"r"; + break; + case ios_base::in | ios_base::out: + __mdstr = L"r+"; + break; + case ios_base::in | ios_base::out | ios_base::trunc: + __mdstr = L"w+"; + break; + case ios_base::in | ios_base::out | ios_base::app: + case ios_base::in | ios_base::app: + __mdstr = L"a+"; + break; + case ios_base::out | ios_base::binary: + case ios_base::out | ios_base::trunc | ios_base::binary: + __mdstr = L"wb"; + break; + case ios_base::out | ios_base::app | ios_base::binary: + case ios_base::app | ios_base::binary: + __mdstr = L"ab"; + break; + case ios_base::in | ios_base::binary: + __mdstr = L"rb"; + break; + case ios_base::in | ios_base::out | ios_base::binary: + __mdstr = L"r+b"; + break; + case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary: + __mdstr = L"w+b"; + break; + case ios_base::in | ios_base::out | ios_base::app | ios_base::binary: + case ios_base::in | ios_base::app | ios_base::binary: + __mdstr = L"a+b"; + break; + default: + __rt = 0; + break; + } + if (__rt) + { + __file_ = _wfopen(__s, __mdstr); + if (__file_) + { + __om_ = __mode; + if (__mode & ios_base::ate) + { + if (fseek(__file_, 0, SEEK_END)) + { + fclose(__file_); + __file_ = 0; + __rt = 0; + } + } + } + else + __rt = 0; + } + } + return __rt; +} +#endif + template inline basic_filebuf<_CharT, _Traits>* @@ -1017,6 +1104,10 @@ #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE _LIBCPP_INLINE_VISIBILITY explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + _LIBCPP_INLINE_VISIBILITY + explicit basic_ifstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::in); +#endif _LIBCPP_INLINE_VISIBILITY explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in); #endif @@ -1036,6 +1127,9 @@ bool is_open() const; #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE void open(const char* __s, ios_base::openmode __mode = ios_base::in); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in); +#endif void open(const string& __s, ios_base::openmode __mode = ios_base::in); #endif _LIBCPP_INLINE_VISIBILITY @@ -1062,6 +1156,17 @@ this->setstate(ios_base::failbit); } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +template +inline +basic_ifstream<_CharT, _Traits>::basic_ifstream(const wchar_t* __s, ios_base::openmode __mode) + : basic_istream(&__sb_) +{ + if (__sb_.open(__s, __mode | ios_base::in) == 0) + this->setstate(ios_base::failbit); +} +#endif + template inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::openmode __mode) @@ -1139,6 +1244,18 @@ this->setstate(ios_base::failbit); } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +template +void +basic_ifstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) +{ + if (__sb_.open(__s, __mode | ios_base::in)) + this->clear(); + else + this->setstate(ios_base::failbit); +} +#endif + template void basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) @@ -1176,6 +1293,10 @@ basic_ofstream(); _LIBCPP_INLINE_VISIBILITY explicit basic_ofstream(const char* __s, ios_base::openmode __mode = ios_base::out); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + _LIBCPP_INLINE_VISIBILITY + explicit basic_ofstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::out); +#endif _LIBCPP_INLINE_VISIBILITY explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out); #ifndef _LIBCPP_CXX03_LANG @@ -1194,6 +1315,9 @@ bool is_open() const; #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE void open(const char* __s, ios_base::openmode __mode = ios_base::out); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::out); +#endif void open(const string& __s, ios_base::openmode __mode = ios_base::out); #endif _LIBCPP_INLINE_VISIBILITY @@ -1220,6 +1344,17 @@ this->setstate(ios_base::failbit); } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +template +inline +basic_ofstream<_CharT, _Traits>::basic_ofstream(const wchar_t* __s, ios_base::openmode __mode) + : basic_ostream(&__sb_) +{ + if (__sb_.open(__s, __mode | ios_base::out) == 0) + this->setstate(ios_base::failbit); +} +#endif + template inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::openmode __mode) @@ -1297,6 +1432,18 @@ this->setstate(ios_base::failbit); } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +template +void +basic_ofstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) +{ + if (__sb_.open(__s, __mode | ios_base::out)) + this->clear(); + else + this->setstate(ios_base::failbit); +} +#endif + template void basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) @@ -1335,6 +1482,10 @@ #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE _LIBCPP_INLINE_VISIBILITY explicit basic_fstream(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + _LIBCPP_INLINE_VISIBILITY + explicit basic_fstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); +#endif _LIBCPP_INLINE_VISIBILITY explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); #endif @@ -1354,6 +1505,9 @@ bool is_open() const; #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); +#endif void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); #endif _LIBCPP_INLINE_VISIBILITY @@ -1380,6 +1534,17 @@ this->setstate(ios_base::failbit); } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +template +inline +basic_fstream<_CharT, _Traits>::basic_fstream(const wchar_t* __s, ios_base::openmode __mode) + : basic_iostream(&__sb_) +{ + if (__sb_.open(__s, __mode) == 0) + this->setstate(ios_base::failbit); +} +#endif + template inline basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openmode __mode) @@ -1457,6 +1622,18 @@ this->setstate(ios_base::failbit); } +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +template +void +basic_fstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) +{ + if (__sb_.open(__s, __mode)) + this->clear(); + else + this->setstate(ios_base::failbit); +} +#endif + template void basic_fstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) Index: test/libcxx/input.output/file.streams/fstreams/fstream.cons/wchar_pointer.pass.cpp =================================================================== --- test/libcxx/input.output/file.streams/fstreams/fstream.cons/wchar_pointer.pass.cpp +++ test/libcxx/input.output/file.streams/fstreams/fstream.cons/wchar_pointer.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template > +// class basic_fstream + +// explicit basic_fstream(const wchar_t* s, ios_base::openmode mode = ios_base::in | ios_base::out); + +#include +#include +#include "platform_support.h" + +int main() +{ +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + std::wstring temp = get_wide_temp_file_name(); + { + std::fstream fs(temp.c_str(), std::ios_base::in | std::ios_base::out + | std::ios_base::trunc); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + } + _wremove(temp.c_str()); + { + std::wfstream fs(temp.c_str(), std::ios_base::in | std::ios_base::out + | std::ios_base::trunc); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + } + _wremove(temp.c_str()); +#endif +} Index: test/libcxx/input.output/file.streams/fstreams/fstream.members/open_wchar_pointer.pass.cpp =================================================================== --- test/libcxx/input.output/file.streams/fstreams/fstream.members/open_wchar_pointer.pass.cpp +++ test/libcxx/input.output/file.streams/fstreams/fstream.members/open_wchar_pointer.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template > +// class basic_fstream + +// void open(const wchar_t* s, ios_base::openmode mode = ios_base::in|ios_base::out); + +#include +#include +#include "platform_support.h" + +int main() +{ +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + std::wstring temp = get_wide_temp_file_name(); + { + std::fstream fs; + assert(!fs.is_open()); + fs.open(temp.c_str(), std::ios_base::in | std::ios_base::out + | std::ios_base::trunc); + assert(fs.is_open()); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + } + _wremove(temp.c_str()); + { + std::wfstream fs; + assert(!fs.is_open()); + fs.open(temp.c_str(), std::ios_base::in | std::ios_base::out + | std::ios_base::trunc); + assert(fs.is_open()); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + } + _wremove(temp.c_str()); +#endif +} Index: test/libcxx/input.output/file.streams/fstreams/ifstream.cons/test.dat =================================================================== --- test/libcxx/input.output/file.streams/fstreams/ifstream.cons/test.dat +++ test/libcxx/input.output/file.streams/fstreams/ifstream.cons/test.dat @@ -0,0 +1 @@ +3.25 \ No newline at end of file Index: test/libcxx/input.output/file.streams/fstreams/ifstream.cons/wchar_pointer.pass.cpp =================================================================== --- test/libcxx/input.output/file.streams/fstreams/ifstream.cons/wchar_pointer.pass.cpp +++ test/libcxx/input.output/file.streams/fstreams/ifstream.cons/wchar_pointer.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template > +// class basic_ifstream + +// explicit basic_ifstream(const wchar_t* s, ios_base::openmode mode = ios_base::in); + +#include +#include + +int main() +{ +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + { + std::ifstream fs(L"test.dat"); + double x = 0; + fs >> x; + assert(x == 3.25); + } + // std::ifstream(const wchar_t*, std::ios_base::openmode) is tested in + // test/libcxx/input.output/file.streams/fstreams/ofstream.cons/wchar_pointer.pass.cpp + // which creates writable files. + { + std::wifstream fs(L"test.dat"); + double x = 0; + fs >> x; + assert(x == 3.25); + } + // std::wifstream(const wchar_t*, std::ios_base::openmode) is tested in + // test/libcxx/input.output/file.streams/fstreams/ofstream.cons/wchar_pointer.pass.cpp + // which creates writable files. +#endif +} Index: test/libcxx/input.output/file.streams/fstreams/ifstream.members/open_wchar_pointer.pass.cpp =================================================================== --- test/libcxx/input.output/file.streams/fstreams/ifstream.members/open_wchar_pointer.pass.cpp +++ test/libcxx/input.output/file.streams/fstreams/ifstream.members/open_wchar_pointer.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template > +// class basic_ifstream + +// void open(const wchar_t* s, ios_base::openmode mode = ios_base::in); + +#include +#include + +int main() +{ +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + { + std::ifstream fs; + assert(!fs.is_open()); + char c = 'a'; + fs >> c; + assert(fs.fail()); + assert(c == 'a'); + fs.open(L"test.dat"); + assert(fs.is_open()); + fs >> c; + assert(c == 'r'); + } + { + std::wifstream fs; + assert(!fs.is_open()); + wchar_t c = L'a'; + fs >> c; + assert(fs.fail()); + assert(c == L'a'); + fs.open(L"test.dat"); + assert(fs.is_open()); + fs >> c; + assert(c == L'r'); + } +#endif +} Index: test/libcxx/input.output/file.streams/fstreams/ifstream.members/test.dat =================================================================== --- test/libcxx/input.output/file.streams/fstreams/ifstream.members/test.dat +++ test/libcxx/input.output/file.streams/fstreams/ifstream.members/test.dat @@ -0,0 +1 @@ +r \ No newline at end of file Index: test/libcxx/input.output/file.streams/fstreams/ofstream.cons/wchar_pointer.pass.cpp =================================================================== --- test/libcxx/input.output/file.streams/fstreams/ofstream.cons/wchar_pointer.pass.cpp +++ test/libcxx/input.output/file.streams/fstreams/ofstream.cons/wchar_pointer.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template > +// class basic_ofstream + +// explicit basic_ofstream(const wchar_t* s, ios_base::openmode mode = ios_base::out); + +#include +#include +#include "platform_support.h" + +int main() +{ +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + std::wstring temp = get_wide_temp_file_name(); + { + std::ofstream fs(temp.c_str()); + fs << 3.25; + } + { + std::ifstream fs(temp.c_str()); + double x = 0; + fs >> x; + assert(x == 3.25); + } + { + std::ifstream fs(temp.c_str(), std::ios_base::out); + double x = 0; + fs >> x; + assert(x == 3.25); + } + _wremove(temp.c_str()); + { + std::wofstream fs(temp.c_str()); + fs << 3.25; + } + { + std::wifstream fs(temp.c_str()); + double x = 0; + fs >> x; + assert(x == 3.25); + } + { + std::wifstream fs(temp.c_str(), std::ios_base::out); + double x = 0; + fs >> x; + assert(x == 3.25); + } + _wremove(temp.c_str()); +#endif +} Index: test/libcxx/input.output/file.streams/fstreams/ofstream.members/open_wchar_pointer.pass.cpp =================================================================== --- test/libcxx/input.output/file.streams/fstreams/ofstream.members/open_wchar_pointer.pass.cpp +++ test/libcxx/input.output/file.streams/fstreams/ofstream.members/open_wchar_pointer.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template > +// class basic_ofstream + +// void open(const wchar_t* s, ios_base::openmode mode = ios_base::out); + +#include +#include +#include "platform_support.h" + +int main() +{ +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR + std::wstring temp = get_wide_temp_file_name(); + { + std::ofstream fs; + assert(!fs.is_open()); + char c = 'a'; + fs << c; + assert(fs.fail()); + fs.open(temp.c_str()); + assert(fs.is_open()); + fs << c; + } + { + std::ifstream fs(temp.c_str()); + char c = 0; + fs >> c; + assert(c == 'a'); + } + _wremove(temp.c_str()); + { + std::wofstream fs; + assert(!fs.is_open()); + wchar_t c = L'a'; + fs << c; + assert(fs.fail()); + fs.open(temp.c_str()); + assert(fs.is_open()); + fs << c; + } + { + std::wifstream fs(temp.c_str()); + wchar_t c = 0; + fs >> c; + assert(c == L'a'); + } + _wremove(temp.c_str()); +#endif +} Index: test/support/platform_support.h =================================================================== --- test/support/platform_support.h +++ test/support/platform_support.h @@ -54,6 +54,8 @@ #include #include +#include +#include #include #if defined(_WIN32) || defined(__MINGW32__) #include // _mktemp_s @@ -97,6 +99,16 @@ return Name; #endif } + +#ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR +inline +std::wstring get_wide_temp_file_name() +{ + return std::wstring_convert >().from_bytes( + get_temp_file_name()); +} +#endif // _LIBCPP_HAS_OPEN_WITH_WCHAR + #endif // __CloudABI__ #endif // PLATFORM_SUPPORT_H