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 ABSL_NAMESPACE_BEGIN 27 namespace strings_internal { 28 29 // The same as std::ostringstream but appends to a user-specified std::string, 30 // and is faster. It is ~70% faster to create, ~50% faster to write to, and 31 // completely free to extract the result std::string. 32 // 33 // std::string s; 34 // OStringStream strm(&s); 35 // strm << 42 << ' ' << 3.14; // appends to `s` 36 // 37 // The stream object doesn't have to be named. Starting from C++11 operator<< 38 // works with rvalues of std::ostream. 39 // 40 // std::string s; 41 // OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s` 42 // 43 // OStringStream is faster to create than std::ostringstream but it's still 44 // relatively slow. Avoid creating multiple streams where a single stream will 45 // do. 46 // 47 // Creates unnecessary instances of OStringStream: slow. 48 // 49 // std::string s; 50 // OStringStream(&s) << 42; 51 // OStringStream(&s) << ' '; 52 // OStringStream(&s) << 3.14; 53 // 54 // Creates a single instance of OStringStream and reuses it: fast. 55 // 56 // std::string s; 57 // OStringStream strm(&s); 58 // strm << 42; 59 // strm << ' '; 60 // strm << 3.14; 61 // 62 // Note: flush() has no effect. No reason to call it. 63 class OStringStream : private std::basic_streambuf<char>, public std::ostream { 64 public: 65 // The argument can be null, in which case you'll need to call str(p) with a 66 // non-null argument before you can write to the stream. 67 // 68 // The destructor of OStringStream doesn't use the std::string. It's OK to 69 // destroy the std::string before the stream. OStringStream(std::string * s)70 explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {} 71 str()72 std::string* str() { return s_; } str()73 const std::string* str() const { return s_; } str(std::string * s)74 void str(std::string* s) { s_ = s; } 75 76 private: 77 using Buf = std::basic_streambuf<char>; 78 79 Buf::int_type overflow(int c) override; 80 std::streamsize xsputn(const char* s, std::streamsize n) override; 81 82 std::string* s_; 83 }; 84 85 } // namespace strings_internal 86 ABSL_NAMESPACE_END 87 } // namespace absl 88 89 #endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ 90