xref: /llvm-project/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp (revision 0547e573c555445e37db5c3bc92ee72274e19b69)
15afb937dSMark de Wever //===----------------------------------------------------------------------===//
25afb937dSMark de Wever //
35afb937dSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45afb937dSMark de Wever // See https://llvm.org/LICENSE.txt for license information.
55afb937dSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65afb937dSMark de Wever //
75afb937dSMark de Wever //===----------------------------------------------------------------------===//
85afb937dSMark de Wever 
95afb937dSMark de Wever // <fstream>
105afb937dSMark de Wever 
115afb937dSMark de Wever // basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) override;
125afb937dSMark de Wever 
13*0547e573SLouis Dionne // In C++23 and later, this test requires support for P2467R1 in the dylib (a3f17ba3febbd546f2342ffc780ac93b694fdc8d)
14*0547e573SLouis Dionne // XFAIL: (!c++03 && !c++11 && !c++14 && !c++17 && !c++20) && using-built-library-before-llvm-18
15*0547e573SLouis Dionne 
165afb937dSMark de Wever #include <fstream>
175afb937dSMark de Wever #include <cstddef>
185afb937dSMark de Wever #include <cassert>
195afb937dSMark de Wever 
205afb937dSMark de Wever #include "test_macros.h"
215afb937dSMark de Wever 
225afb937dSMark de Wever template <class CharT>
235afb937dSMark de Wever static std::size_t file_size(const char* filename) {
245afb937dSMark de Wever   FILE* f = std::fopen(filename, "rb");
255afb937dSMark de Wever   std::fseek(f, 0, SEEK_END);
265afb937dSMark de Wever   long result = std::ftell(f);
275afb937dSMark de Wever   std::fclose(f);
285afb937dSMark de Wever   return result;
295afb937dSMark de Wever }
305afb937dSMark de Wever 
315afb937dSMark de Wever // Helper class to expose some protected std::basic_filebuf<CharT> members.
325afb937dSMark de Wever template <class CharT>
335afb937dSMark de Wever struct filebuf : public std::basic_filebuf<CharT> {
345afb937dSMark de Wever   CharT* base() { return this->pbase(); }
355afb937dSMark de Wever   CharT* ptr() { return this->pptr(); }
365afb937dSMark de Wever };
375afb937dSMark de Wever 
385afb937dSMark de Wever template <class CharT>
395afb937dSMark de Wever static void buffered_request() {
405afb937dSMark de Wever   filebuf<CharT> buffer;
415afb937dSMark de Wever 
425afb937dSMark de Wever   CharT b[10] = {0};
435afb937dSMark de Wever   assert(buffer.pubsetbuf(b, 10) == &buffer);
445afb937dSMark de Wever 
455afb937dSMark de Wever   buffer.open("test.dat", std::ios_base::out);
465afb937dSMark de Wever   buffer.sputc(CharT('a'));
475afb937dSMark de Wever   assert(b[0] == 'a');
485afb937dSMark de Wever 
495afb937dSMark de Wever   buffer.close();
505afb937dSMark de Wever   assert(file_size<CharT>("test.dat") == 1);
515afb937dSMark de Wever }
525afb937dSMark de Wever 
535afb937dSMark de Wever template <class CharT>
545afb937dSMark de Wever static void unbuffered_request_before_open() {
555afb937dSMark de Wever   filebuf<CharT> buffer;
565afb937dSMark de Wever 
575afb937dSMark de Wever   assert(buffer.pubsetbuf(nullptr, 0) == &buffer);
585afb937dSMark de Wever   assert(buffer.base() == nullptr);
595afb937dSMark de Wever   assert(buffer.ptr() == nullptr);
605afb937dSMark de Wever 
615afb937dSMark de Wever   buffer.open("test.dat", std::ios_base::out);
625afb937dSMark de Wever   assert(buffer.base() == nullptr);
635afb937dSMark de Wever   assert(buffer.ptr() == nullptr);
645afb937dSMark de Wever 
655afb937dSMark de Wever   buffer.sputc(CharT('a'));
665afb937dSMark de Wever   assert(buffer.base() == nullptr);
675afb937dSMark de Wever   assert(buffer.ptr() == nullptr);
685afb937dSMark de Wever 
695afb937dSMark de Wever   assert(file_size<CharT>("test.dat") == 1);
705afb937dSMark de Wever }
715afb937dSMark de Wever 
725afb937dSMark de Wever template <class CharT>
735afb937dSMark de Wever static void unbuffered_request_after_open() {
745afb937dSMark de Wever   filebuf<CharT> buffer;
755afb937dSMark de Wever 
765afb937dSMark de Wever   buffer.open("test.dat", std::ios_base::out);
775afb937dSMark de Wever 
785afb937dSMark de Wever   assert(buffer.pubsetbuf(nullptr, 0) == &buffer);
795afb937dSMark de Wever   assert(buffer.base() == nullptr);
805afb937dSMark de Wever   assert(buffer.ptr() == nullptr);
815afb937dSMark de Wever 
825afb937dSMark de Wever   buffer.sputc(CharT('a'));
835afb937dSMark de Wever   assert(buffer.base() == nullptr);
845afb937dSMark de Wever   assert(buffer.ptr() == nullptr);
855afb937dSMark de Wever 
865afb937dSMark de Wever   assert(file_size<CharT>("test.dat") == 1);
875afb937dSMark de Wever }
885afb937dSMark de Wever 
895afb937dSMark de Wever template <class CharT>
905afb937dSMark de Wever static void unbuffered_request_after_open_ate() {
915afb937dSMark de Wever   filebuf<CharT> buffer;
925afb937dSMark de Wever 
935afb937dSMark de Wever   buffer.open("test.dat", std::ios_base::out | std::ios_base::ate);
945afb937dSMark de Wever 
955afb937dSMark de Wever   assert(buffer.pubsetbuf(nullptr, 0) == &buffer);
965afb937dSMark de Wever 
975afb937dSMark de Wever   buffer.sputc(CharT('a'));
985afb937dSMark de Wever   assert(file_size<CharT>("test.dat") <= 1);
995afb937dSMark de Wever   // on libc++ buffering is used by default.
1005afb937dSMark de Wever   LIBCPP_ASSERT(file_size<CharT>("test.dat") == 0);
1015afb937dSMark de Wever 
1025afb937dSMark de Wever   buffer.close();
1035afb937dSMark de Wever   assert(file_size<CharT>("test.dat") == 1);
1045afb937dSMark de Wever }
1055afb937dSMark de Wever 
1065afb937dSMark de Wever template <class CharT>
1075afb937dSMark de Wever static void test() {
1085afb937dSMark de Wever   buffered_request<CharT>();
1095afb937dSMark de Wever 
1105afb937dSMark de Wever   unbuffered_request_before_open<CharT>();
1115afb937dSMark de Wever   unbuffered_request_after_open<CharT>();
1125afb937dSMark de Wever   unbuffered_request_after_open_ate<CharT>();
1135afb937dSMark de Wever }
1145afb937dSMark de Wever 
1155afb937dSMark de Wever int main(int, char**) {
1165afb937dSMark de Wever   test<char>();
1175afb937dSMark de Wever 
1185afb937dSMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS
1195afb937dSMark de Wever   test<wchar_t>();
1205afb937dSMark de Wever #endif
1215afb937dSMark de Wever 
1225afb937dSMark de Wever   return 0;
1235afb937dSMark de Wever }
124