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