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// TODO(mordante) Investigate
10// UNSUPPORTED: apple-clang
11
12// <fstream>
13
14// basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) override;
15
16// This test requires the fix to https://github.com/llvm/llvm-project/issues/60509 in the dylib,
17// which landed in 5afb937d8a30445642ccaf33866ee4cdd0713222.
18// XFAIL using-built-library-before-llvm-19
19
20#include <fstream>
21#include <cstddef>
22#include <cassert>
23
24#include "test_macros.h"
25
26template <class CharT>
27static std::size_t file_size(const char* filename) {
28 FILE* f = std::fopen(filename: filename, modes: "rb");
29 std::fseek(stream: f, off: 0, SEEK_END);
30 long result = std::ftell(stream: f);
31 std::fclose(stream: f);
32 return result;
33}
34
35// Helper class to expose some protected std::basic_filebuf<CharT> members.
36template <class CharT>
37struct filebuf : public std::basic_filebuf<CharT> {
38 CharT* base() { return this->pbase(); }
39 CharT* ptr() { return this->pptr(); }
40};
41
42template <class CharT>
43static void buffered_request() {
44 filebuf<CharT> buffer;
45
46 CharT b[10] = {0};
47 assert(buffer.pubsetbuf(b, 10) == &buffer);
48
49 buffer.open("test.dat", std::ios_base::out);
50 buffer.sputc(CharT('a'));
51 assert(b[0] == 'a');
52
53 buffer.close();
54 assert(file_size<CharT>("test.dat") == 1);
55}
56
57template <class CharT>
58static void unbuffered_request_before_open() {
59 filebuf<CharT> buffer;
60
61 assert(buffer.pubsetbuf(nullptr, 0) == &buffer);
62 assert(buffer.base() == nullptr);
63 assert(buffer.ptr() == nullptr);
64
65 buffer.open("test.dat", std::ios_base::out);
66 assert(buffer.base() == nullptr);
67 assert(buffer.ptr() == nullptr);
68
69 buffer.sputc(CharT('a'));
70 assert(buffer.base() == nullptr);
71 assert(buffer.ptr() == nullptr);
72
73 assert(file_size<CharT>("test.dat") == 1);
74}
75
76template <class CharT>
77static void unbuffered_request_after_open() {
78 filebuf<CharT> buffer;
79
80 buffer.open("test.dat", std::ios_base::out);
81
82 assert(buffer.pubsetbuf(nullptr, 0) == &buffer);
83 assert(buffer.base() == nullptr);
84 assert(buffer.ptr() == nullptr);
85
86 buffer.sputc(CharT('a'));
87 assert(buffer.base() == nullptr);
88 assert(buffer.ptr() == nullptr);
89
90 assert(file_size<CharT>("test.dat") == 1);
91}
92
93template <class CharT>
94static void unbuffered_request_after_open_ate() {
95 filebuf<CharT> buffer;
96
97 buffer.open("test.dat", std::ios_base::out | std::ios_base::ate);
98
99 assert(buffer.pubsetbuf(nullptr, 0) == &buffer);
100
101 buffer.sputc(CharT('a'));
102 assert(file_size<CharT>("test.dat") <= 1);
103 // on libc++ buffering is used by default.
104 LIBCPP_ASSERT(file_size<CharT>("test.dat") == 0);
105
106 buffer.close();
107 assert(file_size<CharT>("test.dat") == 1);
108}
109
110template <class CharT>
111static void test() {
112 buffered_request<CharT>();
113
114 unbuffered_request_before_open<CharT>();
115 unbuffered_request_after_open<CharT>();
116 unbuffered_request_after_open_ate<CharT>();
117}
118
119int main(int, char**) {
120 test<char>();
121
122#ifndef TEST_HAS_NO_WIDE_CHARACTERS
123 test<wchar_t>();
124#endif
125
126 return 0;
127}
128

source code of libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp