1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // <fstream> 10 11 // basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) override; 12 13 // In C++23 and later, this test requires support for P2467R1 in the dylib (a3f17ba3febbd546f2342ffc780ac93b694fdc8d) 14 // XFAIL: (!c++03 && !c++11 && !c++14 && !c++17 && !c++20) && using-built-library-before-llvm-18 15 16 #include <fstream> 17 #include <cstddef> 18 #include <cassert> 19 20 #include "test_macros.h" 21 22 template <class CharT> 23 static std::size_t file_size(const char* filename) { 24 FILE* f = std::fopen(filename, "rb"); 25 std::fseek(f, 0, SEEK_END); 26 long result = std::ftell(f); 27 std::fclose(f); 28 return result; 29 } 30 31 // Helper class to expose some protected std::basic_filebuf<CharT> members. 32 template <class CharT> 33 struct filebuf : public std::basic_filebuf<CharT> { 34 CharT* base() { return this->pbase(); } 35 CharT* ptr() { return this->pptr(); } 36 }; 37 38 template <class CharT> 39 static void buffered_request() { 40 filebuf<CharT> buffer; 41 42 CharT b[10] = {0}; 43 assert(buffer.pubsetbuf(b, 10) == &buffer); 44 45 buffer.open("test.dat", std::ios_base::out); 46 buffer.sputc(CharT('a')); 47 assert(b[0] == 'a'); 48 49 buffer.close(); 50 assert(file_size<CharT>("test.dat") == 1); 51 } 52 53 template <class CharT> 54 static void unbuffered_request_before_open() { 55 filebuf<CharT> buffer; 56 57 assert(buffer.pubsetbuf(nullptr, 0) == &buffer); 58 assert(buffer.base() == nullptr); 59 assert(buffer.ptr() == nullptr); 60 61 buffer.open("test.dat", std::ios_base::out); 62 assert(buffer.base() == nullptr); 63 assert(buffer.ptr() == nullptr); 64 65 buffer.sputc(CharT('a')); 66 assert(buffer.base() == nullptr); 67 assert(buffer.ptr() == nullptr); 68 69 assert(file_size<CharT>("test.dat") == 1); 70 } 71 72 template <class CharT> 73 static void unbuffered_request_after_open() { 74 filebuf<CharT> buffer; 75 76 buffer.open("test.dat", std::ios_base::out); 77 78 assert(buffer.pubsetbuf(nullptr, 0) == &buffer); 79 assert(buffer.base() == nullptr); 80 assert(buffer.ptr() == nullptr); 81 82 buffer.sputc(CharT('a')); 83 assert(buffer.base() == nullptr); 84 assert(buffer.ptr() == nullptr); 85 86 assert(file_size<CharT>("test.dat") == 1); 87 } 88 89 template <class CharT> 90 static void unbuffered_request_after_open_ate() { 91 filebuf<CharT> buffer; 92 93 buffer.open("test.dat", std::ios_base::out | std::ios_base::ate); 94 95 assert(buffer.pubsetbuf(nullptr, 0) == &buffer); 96 97 buffer.sputc(CharT('a')); 98 assert(file_size<CharT>("test.dat") <= 1); 99 // on libc++ buffering is used by default. 100 LIBCPP_ASSERT(file_size<CharT>("test.dat") == 0); 101 102 buffer.close(); 103 assert(file_size<CharT>("test.dat") == 1); 104 } 105 106 template <class CharT> 107 static void test() { 108 buffered_request<CharT>(); 109 110 unbuffered_request_before_open<CharT>(); 111 unbuffered_request_after_open<CharT>(); 112 unbuffered_request_after_open_ate<CharT>(); 113 } 114 115 int main(int, char**) { 116 test<char>(); 117 118 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 119 test<wchar_t>(); 120 #endif 121 122 return 0; 123 } 124