1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_OSTREAMS_H_
6#define V8_OSTREAMS_H_
7
8#include <cstddef>
9#include <cstdio>
10#include <cstring>
11#include <ostream> // NOLINT
12#include <streambuf>
13
14#include "include/v8config.h"
15#include "src/base/macros.h"
16#include "src/globals.h"
17
18namespace v8 {
19namespace internal {
20
21class V8_EXPORT_PRIVATE OFStreamBase : public std::streambuf {
22 public:
23 explicit OFStreamBase(FILE* f);
24 ~OFStreamBase() override = default;
25
26 protected:
27 FILE* const f_;
28
29 int sync() override;
30 int_type overflow(int_type c) override;
31 std::streamsize xsputn(const char* s, std::streamsize n) override;
32};
33
34// Output buffer and stream writing into debugger's command window.
35class V8_EXPORT_PRIVATE DbgStreamBuf : public std::streambuf {
36 public:
37 DbgStreamBuf();
38 ~DbgStreamBuf();
39
40 private:
41 int sync() override;
42 int overflow(int c) override;
43
44 char data_[256];
45};
46
47class DbgStdoutStream : public std::ostream {
48 public:
49 DbgStdoutStream();
50 ~DbgStdoutStream() = default;
51
52 private:
53 DbgStreamBuf streambuf_;
54};
55
56// An output stream writing to a file.
57class V8_EXPORT_PRIVATE OFStream : public std::ostream {
58 public:
59 explicit OFStream(FILE* f);
60 ~OFStream() override = default;
61
62 private:
63 OFStreamBase buf_;
64};
65
66#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
67class V8_EXPORT_PRIVATE AndroidLogStream : public std::streambuf {
68 public:
69 virtual ~AndroidLogStream();
70
71 protected:
72 std::streamsize xsputn(const char* s, std::streamsize n) override;
73
74 private:
75 std::string line_buffer_;
76};
77
78class StdoutStream : public std::ostream {
79 public:
80 StdoutStream() : std::ostream(&stream_) {}
81
82 private:
83 AndroidLogStream stream_;
84};
85#else
86class StdoutStream : public OFStream {
87 public:
88 StdoutStream() : OFStream(stdout) {}
89};
90#endif
91
92// Wrappers to disambiguate uint16_t and uc16.
93struct AsUC16 {
94 explicit AsUC16(uint16_t v) : value(v) {}
95 uint16_t value;
96};
97
98
99struct AsUC32 {
100 explicit AsUC32(int32_t v) : value(v) {}
101 int32_t value;
102};
103
104
105struct AsReversiblyEscapedUC16 {
106 explicit AsReversiblyEscapedUC16(uint16_t v) : value(v) {}
107 uint16_t value;
108};
109
110struct AsEscapedUC16ForJSON {
111 explicit AsEscapedUC16ForJSON(uint16_t v) : value(v) {}
112 uint16_t value;
113};
114
115// Output the given value as hex, with a minimum width and optional prefix (0x).
116// E.g. AsHex(23, 3, true) produces "0x017". Produces an empty string if both
117// {min_width} and the value are 0.
118struct AsHex {
119 explicit AsHex(uint64_t v, uint8_t min_width = 1, bool with_prefix = false)
120 : value(v), min_width(min_width), with_prefix(with_prefix) {}
121 uint64_t value;
122 uint8_t min_width;
123 bool with_prefix;
124
125 static AsHex Address(Address a) {
126 return AsHex(a, kSystemPointerHexDigits, true);
127 }
128};
129
130// Output the given value as hex, separated in individual bytes.
131// E.g. AsHexBytes(0x231712, 4) produces "12 17 23 00" if output as little
132// endian (default), and "00 23 17 12" as big endian. Produces an empty string
133// if both {min_bytes} and the value are 0.
134struct AsHexBytes {
135 enum ByteOrder { kLittleEndian, kBigEndian };
136 explicit AsHexBytes(uint64_t v, uint8_t min_bytes = 1,
137 ByteOrder byte_order = kLittleEndian)
138 : value(v), min_bytes(min_bytes), byte_order(byte_order) {}
139 uint64_t value;
140 uint8_t min_bytes;
141 ByteOrder byte_order;
142};
143
144template <typename T>
145struct PrintIteratorRange {
146 T start;
147 T end;
148 PrintIteratorRange(T start, T end) : start(start), end(end) {}
149};
150
151// Print any collection which can be iterated via std::begin and std::end.
152// {Iterator} is the common type of {std::begin} and {std::end} called on a
153// {const T&}. This function is only instantiable if that type exists.
154template <typename T, typename Iterator = typename std::common_type<
155 decltype(std::begin(std::declval<const T&>())),
156 decltype(std::end(std::declval<const T&>()))>::type>
157PrintIteratorRange<Iterator> PrintCollection(const T& collection) {
158 return {std::begin(collection), std::end(collection)};
159}
160
161// Writes the given character to the output escaping everything outside of
162// printable/space ASCII range. Additionally escapes '\' making escaping
163// reversible.
164std::ostream& operator<<(std::ostream& os, const AsReversiblyEscapedUC16& c);
165
166// Same as AsReversiblyEscapedUC16 with additional escaping of \n, \r, " and '.
167V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
168 const AsEscapedUC16ForJSON& c);
169
170// Writes the given character to the output escaping everything outside
171// of printable ASCII range.
172std::ostream& operator<<(std::ostream& os, const AsUC16& c);
173
174// Writes the given character to the output escaping everything outside
175// of printable ASCII range.
176std::ostream& operator<<(std::ostream& os, const AsUC32& c);
177
178V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const AsHex& v);
179V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
180 const AsHexBytes& v);
181
182template <typename T>
183std::ostream& operator<<(std::ostream& os, const PrintIteratorRange<T>& range) {
184 const char* comma = "";
185 os << "[";
186 for (T it = range.start; it != range.end; ++it, comma = ", ") {
187 os << comma << *it;
188 }
189 os << "]";
190 return os;
191}
192
193} // namespace internal
194} // namespace v8
195
196#endif // V8_OSTREAMS_H_
197