[libc++] Refactors fstream open. (#76617)

This moves the duplicated code to one new function.

This is a preparation to fix
https://github.com/llvm/llvm-project/issues/60509
This commit is contained in:
Mark de Wever 2024-03-03 13:23:41 +01:00 committed by GitHub
parent 22f34ea3b0
commit a5d3a1dbc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -279,6 +279,9 @@ public:
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_HIDE_FROM_ABI inline static const char* __make_mdstring(ios_base::openmode __mode) _NOEXCEPT;
# ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
_LIBCPP_HIDE_FROM_ABI inline static const wchar_t* __make_mdwstring(ios_base::openmode __mode) _NOEXCEPT;
# endif
protected:
// 27.9.1.5 Overridden virtual functions:
@ -314,6 +317,26 @@ private:
void __write_mode();
_LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
// There are multiple (__)open function, they use different C-API open
// function. After that call these functions behave the same. This function
// does that part and determines the final return value.
_LIBCPP_HIDE_FROM_ABI basic_filebuf* __do_open(FILE* __file, ios_base::openmode __mode) {
__file_ = __file;
if (!__file_)
return nullptr;
__om_ = __mode;
if (__mode & ios_base::ate) {
if (fseek(__file_, 0, SEEK_END)) {
fclose(__file_);
__file_ = nullptr;
return nullptr;
}
}
return this;
}
};
template <class _CharT, class _Traits>
@ -548,50 +571,79 @@ const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode _
__libcpp_unreachable();
}
# ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
template <class _CharT, class _Traits>
const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmode __mode) _NOEXCEPT {
switch (__mode & ~ios_base::ate) {
case ios_base::out:
case ios_base::out | ios_base::trunc:
return L"w";
case ios_base::out | ios_base::app:
case ios_base::app:
return L"a";
case ios_base::in:
return L"r";
case ios_base::in | ios_base::out:
return L"r+";
case ios_base::in | ios_base::out | ios_base::trunc:
return L"w+";
case ios_base::in | ios_base::out | ios_base::app:
case ios_base::in | ios_base::app:
return L"a+";
case ios_base::out | ios_base::binary:
case ios_base::out | ios_base::trunc | ios_base::binary:
return L"wb";
case ios_base::out | ios_base::app | ios_base::binary:
case ios_base::app | ios_base::binary:
return L"ab";
case ios_base::in | ios_base::binary:
return L"rb";
case ios_base::in | ios_base::out | ios_base::binary:
return L"r+b";
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
return L"w+b";
case ios_base::in | ios_base::out | ios_base::app | ios_base::binary:
case ios_base::in | ios_base::app | ios_base::binary:
return L"a+b";
# if _LIBCPP_STD_VER >= 23
case ios_base::out | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::noreplace:
return L"wx";
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace:
return L"w+x";
case ios_base::out | ios_base::binary | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
return L"wbx";
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
return L"w+bx";
# endif // _LIBCPP_STD_VER >= 23
default:
return nullptr;
}
__libcpp_unreachable();
}
# endif
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
basic_filebuf<_CharT, _Traits>* __rt = nullptr;
if (__file_ == nullptr) {
if (const char* __mdstr = __make_mdstring(__mode)) {
__rt = this;
__file_ = fopen(__s, __mdstr);
if (__file_) {
__om_ = __mode;
if (__mode & ios_base::ate) {
if (fseek(__file_, 0, SEEK_END)) {
fclose(__file_);
__file_ = nullptr;
__rt = nullptr;
}
}
} else
__rt = nullptr;
}
}
return __rt;
if (__file_)
return nullptr;
const char* __mdstr = __make_mdstring(__mode);
if (!__mdstr)
return nullptr;
return __do_open(fopen(__s, __mdstr), __mode);
}
template <class _CharT, class _Traits>
inline basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
basic_filebuf<_CharT, _Traits>* __rt = nullptr;
if (__file_ == nullptr) {
if (const char* __mdstr = __make_mdstring(__mode)) {
__rt = this;
__file_ = fdopen(__fd, __mdstr);
if (__file_) {
__om_ = __mode;
if (__mode & ios_base::ate) {
if (fseek(__file_, 0, SEEK_END)) {
fclose(__file_);
__file_ = nullptr;
__rt = nullptr;
}
}
} else
__rt = nullptr;
}
}
return __rt;
if (__file_)
return nullptr;
const char* __mdstr = __make_mdstring(__mode);
if (!__mdstr)
return nullptr;
return __do_open(fdopen(__fd, __mdstr), __mode);
}
# ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
@ -599,89 +651,13 @@ inline basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::__open(in
// and long mode strings.
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
basic_filebuf<_CharT, _Traits>* __rt = nullptr;
if (__file_ == nullptr) {
__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;
# if _LIBCPP_STD_VER >= 23
case ios_base::out | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::noreplace:
__mdstr = L"wx";
break;
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace:
__mdstr = L"w+x";
break;
case ios_base::out | ios_base::binary | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
__mdstr = L"wbx";
break;
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
__mdstr = L"w+bx";
break;
# endif // _LIBCPP_STD_VER >= 23
default:
__rt = nullptr;
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_ = nullptr;
__rt = nullptr;
}
}
} else
__rt = nullptr;
}
}
return __rt;
if (__file_)
return nullptr;
const wchar_t* __mdstr = __make_mdwstring(__mode);
if (!__mdstr)
return nullptr;
return __do_open(_wfopen(__s, __mdstr), __mode);
}
# endif