llvm.org GIT mirror llvm / 60d3962
add a new raw_ostream class which is an extremely high performance ostream that can *only* output data (no seeking, reading, etc). This is adapted from the clang "-E outputter", and is roughly 10% faster than stdio on darwin and 30% (or more) faster than std::ostream. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54855 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 11 years ago
2 changed file(s) with 234 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===--- raw_ostream.h - Raw output stream ---------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the raw_ostream class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_SUPPORT_RAW_OSTREAM_H
14 #define LLVM_SUPPORT_RAW_OSTREAM_H
15
16 #include
17
18 namespace llvm {
19
20 /// raw_ostream - This class implements an extremely fast bulk output stream
21 /// that can *only* output to a stream. It does not support seeking, reopening,
22 /// rewinding, line buffered disciplines etc. It is a simple buffer that outputs
23 /// a chunk at a time.
24 class raw_ostream {
25 protected:
26 char *OutBufStart, *OutBufEnd, *OutBufCur;
27 public:
28 raw_ostream() {
29 // Start out ready to flush.
30 OutBufStart = OutBufEnd = OutBufCur = 0;
31 }
32 virtual ~raw_ostream() {}
33
34 //===--------------------------------------------------------------------===//
35 // Configuration Interface
36 //===--------------------------------------------------------------------===//
37
38 /// SetBufferSize - Set the internal buffer size to the specified amount
39 /// instead of the default.
40 void SetBufferSize(unsigned Size) {
41 assert(Size >= 64 &&
42 "Buffer size must be somewhat large for invariants to hold");
43 flush();
44
45 delete [] OutBufStart;
46 OutBufStart = new char[Size];
47 OutBufEnd = OutBufStart+Size;
48 OutBufCur = OutBufStart;
49 }
50
51 //===--------------------------------------------------------------------===//
52 // Data Output Interface
53 //===--------------------------------------------------------------------===//
54
55 void flush() {
56 if (OutBufCur != OutBufStart)
57 flush_impl();
58 }
59
60 raw_ostream &operator<<(char C) {
61 if (OutBufCur >= OutBufEnd)
62 flush_impl();
63 *OutBufCur++ = C;
64 return *this;
65 }
66
67 raw_ostream &operator<<(const char *Str) {
68 return OutputData(Str, strlen(Str));
69 }
70
71 raw_ostream &OutputData(const char *Ptr, unsigned Size) {
72 if (OutBufCur+Size > OutBufEnd)
73 flush_impl();
74
75 // Handle short strings specially, memcpy isn't very good at very short
76 // strings.
77 switch (Size) {
78 // case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
79 case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
80 case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
81 case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
82 case 0: break;
83 default:
84 // Normally the string to emit is shorter than the buffer.
85 if (Size <= unsigned(OutBufEnd-OutBufStart)) {
86 memcpy(OutBufCur, Ptr, Size);
87 break;
88 }
89
90 // If emitting a string larger than our buffer, emit in chunks. In this
91 // case we know that we just flushed the buffer.
92 while (Size) {
93 unsigned NumToEmit = OutBufEnd-OutBufStart;
94 if (Size < NumToEmit) NumToEmit = Size;
95 assert(OutBufCur == OutBufStart);
96 memcpy(OutBufStart, Ptr, NumToEmit);
97 Ptr += NumToEmit;
98 OutBufCur = OutBufStart + NumToEmit;
99 flush_impl();
100 }
101 break;
102 }
103 OutBufCur += Size;
104 return *this;
105 }
106
107 //===--------------------------------------------------------------------===//
108 // Subclass Interface
109 //===--------------------------------------------------------------------===//
110
111 protected:
112
113 /// flush_impl - The is the piece of the class that is implemented by
114 /// subclasses. This outputs the currently buffered data and resets the
115 /// buffer to empty.
116 virtual void flush_impl() = 0;
117
118 /// HandleFlush - A stream's implementation of flush should call this after
119 /// emitting the bytes to the data sink.
120 void HandleFlush() {
121 if (OutBufStart == 0)
122 SetBufferSize(4096);
123 OutBufCur = OutBufStart;
124 }
125 private:
126 // An out of line virtual method to provide a home for the class vtable.
127 virtual void handle();
128 };
129
130 /// raw_fd_ostream - A raw_ostream that writes to a file descriptor.
131 ///
132 class raw_fd_ostream : public raw_ostream {
133 int FD;
134 bool ShouldClose;
135 public:
136 /// raw_fd_ostream - Open the specified file for writing. If an error occurs,
137 /// information about the error is put into ErrorInfo, and the stream should
138 /// be immediately destroyed.
139 raw_fd_ostream(const char *Filename, std::string &ErrorInfo);
140
141 /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If
142 /// ShouldClose is true, this closes the file when
143 raw_fd_ostream(int fd, bool shouldClose) : FD(fd), ShouldClose(shouldClose) {}
144
145 ~raw_fd_ostream();
146
147 /// flush_impl - The is the piece of the class that is implemented by
148 /// subclasses. This outputs the currently buffered data and resets the
149 /// buffer to empty.
150 virtual void flush_impl();
151 };
152
153 class raw_stdout_ostream : public raw_fd_ostream {
154 // An out of line virtual method to provide a home for the class vtable.
155 virtual void handle();
156 public:
157 raw_stdout_ostream();
158 };
159
160 class raw_stderr_ostream : public raw_fd_ostream {
161 // An out of line virtual method to provide a home for the class vtable.
162 virtual void handle();
163 public:
164 raw_stderr_ostream();
165 };
166
167 } // end llvm namespace
168
169 #endif
0 //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This implements support for bulk buffered stream output.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Support/raw_ostream.h"
14 using namespace llvm;
15
16 #if !defined(_MSC_VER)
17 #include
18 #else
19 #include
20 #define open(x,y,z) _open(x,y)
21 #define write(fd, start, size) _write(fd, start, size)
22 #define close(fd) _close(fd)
23 #endif
24
25 // An out of line virtual method to provide a home for the class vtable.
26 void raw_ostream::handle() {}
27
28 //===----------------------------------------------------------------------===//
29 // raw_fd_ostream
30 //===----------------------------------------------------------------------===//
31
32 /// raw_fd_ostream - Open the specified file for writing. If an error occurs,
33 /// information about the error is put into ErrorInfo, and the stream should
34 /// be immediately destroyed.
35 raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo) {
36 FD = open(Filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
37 if (FD < 0) {
38 ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
39 ShouldClose = false;
40 } else {
41 ShouldClose = true;
42 }
43 }
44
45 raw_fd_ostream::~raw_fd_ostream() {
46 flush();
47 if (ShouldClose)
48 close(FD);
49 }
50
51 void raw_fd_ostream::flush_impl() {
52 if (OutBufCur-OutBufStart)
53 write(FD, OutBufStart, OutBufCur-OutBufStart);
54 HandleFlush();
55 }
56
57
58 raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
59 raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
60
61 // An out of line virtual method to provide a home for the class vtable.
62 void raw_stdout_ostream::handle() {}
63 void raw_stderr_ostream::handle() {}