1 | // Copyright 2017 The Abseil Authors. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #ifndef ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ |
16 | #define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ |
17 | |
18 | #include <cassert> |
19 | #include <ostream> |
20 | #include <streambuf> |
21 | #include <string> |
22 | |
23 | #include "absl/base/port.h" |
24 | |
25 | namespace absl { |
26 | namespace strings_internal { |
27 | |
28 | // The same as std::ostringstream but appends to a user-specified std::string, |
29 | // and is faster. It is ~70% faster to create, ~50% faster to write to, and |
30 | // completely free to extract the result std::string. |
31 | // |
32 | // std::string s; |
33 | // OStringStream strm(&s); |
34 | // strm << 42 << ' ' << 3.14; // appends to `s` |
35 | // |
36 | // The stream object doesn't have to be named. Starting from C++11 operator<< |
37 | // works with rvalues of std::ostream. |
38 | // |
39 | // std::string s; |
40 | // OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s` |
41 | // |
42 | // OStringStream is faster to create than std::ostringstream but it's still |
43 | // relatively slow. Avoid creating multiple streams where a single stream will |
44 | // do. |
45 | // |
46 | // Creates unnecessary instances of OStringStream: slow. |
47 | // |
48 | // std::string s; |
49 | // OStringStream(&s) << 42; |
50 | // OStringStream(&s) << ' '; |
51 | // OStringStream(&s) << 3.14; |
52 | // |
53 | // Creates a single instance of OStringStream and reuses it: fast. |
54 | // |
55 | // std::string s; |
56 | // OStringStream strm(&s); |
57 | // strm << 42; |
58 | // strm << ' '; |
59 | // strm << 3.14; |
60 | // |
61 | // Note: flush() has no effect. No reason to call it. |
62 | class OStringStream : private std::basic_streambuf<char>, public std::ostream { |
63 | public: |
64 | // The argument can be null, in which case you'll need to call str(p) with a |
65 | // non-null argument before you can write to the stream. |
66 | // |
67 | // The destructor of OStringStream doesn't use the std::string. It's OK to |
68 | // destroy the std::string before the stream. |
69 | explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {} |
70 | |
71 | std::string* str() { return s_; } |
72 | const std::string* str() const { return s_; } |
73 | void str(std::string* s) { s_ = s; } |
74 | |
75 | private: |
76 | using Buf = std::basic_streambuf<char>; |
77 | |
78 | Buf::int_type overflow(int c) override; |
79 | std::streamsize xsputn(const char* s, std::streamsize n) override; |
80 | |
81 | std::string* s_; |
82 | }; |
83 | |
84 | } // namespace strings_internal |
85 | } // namespace absl |
86 | |
87 | #endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ |
88 | |