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 <ios> 20 #include <ostream> 21 #include <streambuf> 22 #include <string> 23 #include <utility> 24 25 #include "absl/base/config.h" 26 27 namespace absl { 28 ABSL_NAMESPACE_BEGIN 29 namespace strings_internal { 30 31 // The same as std::ostringstream but appends to a user-specified std::string, 32 // and is faster. It is ~70% faster to create, ~50% faster to write to, and 33 // completely free to extract the result std::string. 34 // 35 // std::string s; 36 // OStringStream strm(&s); 37 // strm << 42 << ' ' << 3.14; // appends to `s` 38 // 39 // The stream object doesn't have to be named. Starting from C++11 operator<< 40 // works with rvalues of std::ostream. 41 // 42 // std::string s; 43 // OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s` 44 // 45 // OStringStream is faster to create than std::ostringstream but it's still 46 // relatively slow. Avoid creating multiple streams where a single stream will 47 // do. 48 // 49 // Creates unnecessary instances of OStringStream: slow. 50 // 51 // std::string s; 52 // OStringStream(&s) << 42; 53 // OStringStream(&s) << ' '; 54 // OStringStream(&s) << 3.14; 55 // 56 // Creates a single instance of OStringStream and reuses it: fast. 57 // 58 // std::string s; 59 // OStringStream strm(&s); 60 // strm << 42; 61 // strm << ' '; 62 // strm << 3.14; 63 // 64 // Note: flush() has no effect. No reason to call it. 65 class OStringStream final : public std::ostream { 66 public: 67 // The argument can be null, in which case you'll need to call str(p) with a 68 // non-null argument before you can write to the stream. 69 // 70 // The destructor of OStringStream doesn't use the std::string. It's OK to 71 // destroy the std::string before the stream. OStringStream(std::string * str)72 explicit OStringStream(std::string* str) 73 : std::ostream(&buf_), buf_(str) {} OStringStream(OStringStream && that)74 OStringStream(OStringStream&& that) 75 : std::ostream(std::move(static_cast<std::ostream&>(that))), 76 buf_(that.buf_) { 77 rdbuf(&buf_); 78 } 79 OStringStream& operator=(OStringStream&& that) { 80 std::ostream::operator=(std::move(static_cast<std::ostream&>(that))); 81 buf_ = that.buf_; 82 rdbuf(&buf_); 83 return *this; 84 } 85 str()86 std::string* str() { return buf_.str(); } str()87 const std::string* str() const { return buf_.str(); } str(std::string * str)88 void str(std::string* str) { buf_.str(str); } 89 90 private: 91 class Streambuf final : public std::streambuf { 92 public: Streambuf(std::string * str)93 explicit Streambuf(std::string* str) : str_(str) {} 94 Streambuf(const Streambuf&) = default; 95 Streambuf& operator=(const Streambuf&) = default; 96 str()97 std::string* str() { return str_; } str()98 const std::string* str() const { return str_; } str(std::string * str)99 void str(std::string* str) { str_ = str; } 100 101 protected: 102 int_type overflow(int c) override; 103 std::streamsize xsputn(const char* s, std::streamsize n) override; 104 105 private: 106 std::string* str_; 107 } buf_; 108 }; 109 110 } // namespace strings_internal 111 ABSL_NAMESPACE_END 112 } // namespace absl 113 114 #endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ 115