Skip to content

Commit f9ba898

Browse files
[𝘀𝗽𝗿] initial version
Created using spr 1.3.5
2 parents e575483 + 82d9e5b commit f9ba898

File tree

5 files changed

+408
-0
lines changed

5 files changed

+408
-0
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
//===- raw_ostream_proxy.h - Proxies for raw output streams -----*- C++ -*-===//
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+
#ifndef LLVM_SUPPORT_RAW_OSTREAM_PROXY_H
10+
#define LLVM_SUPPORT_RAW_OSTREAM_PROXY_H
11+
12+
#include "llvm/Support/raw_ostream.h"
13+
14+
namespace llvm {
15+
16+
/// Common bits for \a raw_ostream_proxy_adaptor<>, split out to dedup in
17+
/// template instantions.
18+
class raw_ostream_proxy_adaptor_base {
19+
protected:
20+
raw_ostream_proxy_adaptor_base(const raw_ostream_proxy_adaptor_base &) =
21+
delete;
22+
23+
explicit raw_ostream_proxy_adaptor_base(raw_ostream &OS)
24+
: OS(&OS), PreferredBufferSize(OS.GetBufferSize()) {
25+
// Drop OS's buffer to make this->flush() forward. This proxy will add a
26+
// buffer in its place.
27+
OS.SetUnbuffered();
28+
}
29+
30+
~raw_ostream_proxy_adaptor_base() {
31+
assert(!OS && "Derived objects should call resetProxiedOS()");
32+
}
33+
34+
/// Stop proxying the stream, taking the derived object by reference as \p
35+
/// ThisProxyOS. Updates \p ThisProxyOS to stop buffering before setting \a
36+
/// OS to \c nullptr, ensuring that future writes crash immediately.
37+
void resetProxiedOS(raw_ostream &ThisProxyOS) {
38+
ThisProxyOS.SetUnbuffered();
39+
OS = nullptr;
40+
}
41+
42+
bool hasProxiedOS() const { return OS; }
43+
raw_ostream &getProxiedOS() const {
44+
assert(OS && "raw_ostream_proxy_adaptor use after reset");
45+
return *OS;
46+
}
47+
size_t getPreferredBufferSize() const { return PreferredBufferSize; }
48+
49+
private:
50+
raw_ostream *OS;
51+
52+
/// Caches the value of OS->GetBufferSize() at construction time.
53+
size_t PreferredBufferSize;
54+
};
55+
56+
/// Adaptor to create a stream class that proxies another \a raw_ostream.
57+
///
58+
/// Use \a raw_ostream_proxy_adaptor<> directly to implement an abstract
59+
/// derived class of \a raw_ostream as a proxy. Otherwise use \a
60+
/// raw_ostream_proxy.
61+
///
62+
/// Most operations are forwarded to the proxied stream.
63+
///
64+
/// If the proxied stream is buffered, the buffer is dropped and moved to this
65+
/// stream. This allows \a flush() to work correctly, flushing immediately from
66+
/// the proxy through to the final stream, and avoids any wasteful
67+
/// double-buffering.
68+
///
69+
/// \a enable_colors() changes both the proxied stream and the proxy itself.
70+
/// \a is_displayed() and \a has_colors() are forwarded to the proxy. \a
71+
/// changeColor(), resetColor(), and \a reverseColor() are not forwarded, since
72+
/// they need to call \a flush() and the buffer lives in the proxy.
73+
template <class RawOstreamT = raw_ostream>
74+
class raw_ostream_proxy_adaptor : public RawOstreamT {
75+
void write_impl(const char *Ptr, size_t Size) override {
76+
getProxiedOS().write(Ptr, Size);
77+
}
78+
uint64_t current_pos() const override { return getProxiedOS().tell(); }
79+
size_t preferred_buffer_size() const override {
80+
return getPreferredBufferSize();
81+
}
82+
83+
public:
84+
void reserveExtraSpace(uint64_t ExtraSize) override {
85+
getProxiedOS().reserveExtraSpace(ExtraSize);
86+
}
87+
bool is_displayed() const override { return getProxiedOS().is_displayed(); }
88+
bool has_colors() const override { return getProxiedOS().has_colors(); }
89+
void enable_colors(bool enable) override {
90+
RawOstreamT::enable_colors(enable);
91+
getProxiedOS().enable_colors(enable);
92+
}
93+
bool hasProxiedOS() const { return OS; }
94+
raw_ostream &getProxiedOS() const {
95+
assert(OS && "raw_ostream_proxy_adaptor use after reset");
96+
return *OS;
97+
}
98+
size_t getPreferredBufferSize() const { return PreferredBufferSize; }
99+
100+
~raw_ostream_proxy_adaptor() override { resetProxiedOS(); }
101+
102+
protected:
103+
template <class... ArgsT>
104+
explicit raw_ostream_proxy_adaptor(raw_ostream &OS, ArgsT &&...Args)
105+
: RawOstreamT(std::forward<ArgsT>(Args)...), OS(&OS),
106+
PreferredBufferSize(OS.GetBufferSize()) {
107+
// Drop OS's buffer to make this->flush() forward. This proxy will add a
108+
// buffer in its place.
109+
OS.SetUnbuffered();
110+
}
111+
112+
/// Stop proxying the stream. Flush and set up a crash for future writes.
113+
///
114+
/// For example, this can simplify logic when a subclass might have a longer
115+
/// lifetime than the stream it proxies.
116+
void resetProxiedOS() {
117+
OS->SetUnbuffered();
118+
OS = nullptr;
119+
}
120+
121+
private:
122+
raw_ostream *OS;
123+
124+
/// Caches the value of OS->GetBufferSize() at construction time.
125+
size_t PreferredBufferSize;
126+
};
127+
128+
/// Adaptor for creating a stream that proxies a \a raw_pwrite_stream.
129+
template <class RawPwriteStreamT = raw_pwrite_stream>
130+
class raw_pwrite_stream_proxy_adaptor
131+
: public raw_ostream_proxy_adaptor<RawPwriteStreamT> {
132+
using RawOstreamAdaptorT = raw_ostream_proxy_adaptor<RawPwriteStreamT>;
133+
134+
void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override {
135+
this->flush();
136+
getProxiedOS().pwrite(Ptr, Size, Offset);
137+
}
138+
139+
protected:
140+
raw_pwrite_stream_proxy_adaptor() = default;
141+
template <class... ArgsT>
142+
explicit raw_pwrite_stream_proxy_adaptor(raw_pwrite_stream &OS,
143+
ArgsT &&...Args)
144+
: RawOstreamAdaptorT(OS, std::forward<ArgsT>(Args)...) {}
145+
146+
raw_pwrite_stream &getProxiedOS() const {
147+
return static_cast<raw_pwrite_stream &>(RawOstreamAdaptorT::getProxiedOS());
148+
}
149+
};
150+
151+
/// Non-owning proxy for a \a raw_ostream. Enables passing a stream into an
152+
/// API that takes ownership.
153+
class raw_ostream_proxy : public raw_ostream_proxy_adaptor<> {
154+
void anchor() override;
155+
156+
public:
157+
raw_ostream_proxy(raw_ostream &OS) : raw_ostream_proxy_adaptor<>(OS) {}
158+
};
159+
160+
/// Non-owning proxy for a \a raw_pwrite_stream. Enables passing a stream
161+
/// into an API that takes ownership.
162+
class raw_pwrite_stream_proxy : public raw_pwrite_stream_proxy_adaptor<> {
163+
void anchor() override;
164+
165+
public:
166+
raw_pwrite_stream_proxy(raw_pwrite_stream &OS)
167+
: raw_pwrite_stream_proxy_adaptor<>(OS) {}
168+
};
169+
170+
} // end namespace llvm
171+
172+
#endif // LLVM_SUPPORT_RAW_OSTREAM_PROXY_H

llvm/lib/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ add_llvm_component_library(LLVMSupport
261261
YAMLTraits.cpp
262262
raw_os_ostream.cpp
263263
raw_ostream.cpp
264+
raw_ostream_proxy.cpp
264265
raw_socket_stream.cpp
265266
regcomp.c
266267
regerror.c
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===- raw_ostream_proxy.cpp - Implement the raw_ostream proxies ----------===//
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+
#include "llvm/Support/raw_ostream_proxy.h"
10+
11+
using namespace llvm;
12+
13+
void raw_ostream_proxy::anchor() {}
14+
15+
void raw_pwrite_stream_proxy::anchor() {}

llvm/unittests/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ add_llvm_unittest(SupportTests
104104
formatted_raw_ostream_test.cpp
105105
raw_fd_stream_test.cpp
106106
raw_ostream_test.cpp
107+
raw_ostream_proxy_test.cpp
107108
raw_pwrite_stream_test.cpp
108109
raw_sha1_ostream_test.cpp
109110
raw_socket_stream_test.cpp

0 commit comments

Comments
 (0)