00001 // Copyright 2017 The Abseil Authors. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #ifndef ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ 00016 #define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ 00017 00018 #include <cassert> 00019 #include <ostream> 00020 #include <streambuf> 00021 #include <string> 00022 00023 #include "absl/base/port.h" 00024 00025 namespace absl { 00026 namespace strings_internal { 00027 00028 // The same as std::ostringstream but appends to a user-specified std::string, 00029 // and is faster. It is ~70% faster to create, ~50% faster to write to, and 00030 // completely free to extract the result std::string. 00031 // 00032 // std::string s; 00033 // OStringStream strm(&s); 00034 // strm << 42 << ' ' << 3.14; // appends to `s` 00035 // 00036 // The stream object doesn't have to be named. Starting from C++11 operator<< 00037 // works with rvalues of std::ostream. 00038 // 00039 // std::string s; 00040 // OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s` 00041 // 00042 // OStringStream is faster to create than std::ostringstream but it's still 00043 // relatively slow. Avoid creating multiple streams where a single stream will 00044 // do. 00045 // 00046 // Creates unnecessary instances of OStringStream: slow. 00047 // 00048 // std::string s; 00049 // OStringStream(&s) << 42; 00050 // OStringStream(&s) << ' '; 00051 // OStringStream(&s) << 3.14; 00052 // 00053 // Creates a single instance of OStringStream and reuses it: fast. 00054 // 00055 // std::string s; 00056 // OStringStream strm(&s); 00057 // strm << 42; 00058 // strm << ' '; 00059 // strm << 3.14; 00060 // 00061 // Note: flush() has no effect. No reason to call it. 00062 class OStringStream : private std::basic_streambuf<char>, public std::ostream { 00063 public: 00064 // The argument can be null, in which case you'll need to call str(p) with a 00065 // non-null argument before you can write to the stream. 00066 // 00067 // The destructor of OStringStream doesn't use the std::string. It's OK to 00068 // destroy the std::string before the stream. 00069 explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {} 00070 00071 std::string* str() { return s_; } 00072 const std::string* str() const { return s_; } 00073 void str(std::string* s) { s_ = s; } 00074 00075 private: 00076 using Buf = std::basic_streambuf<char>; 00077 00078 Buf::int_type overflow(int c) override; 00079 std::streamsize xsputn(const char* s, std::streamsize n) override; 00080 00081 std::string* s_; 00082 }; 00083 00084 } // namespace strings_internal 00085 } // namespace absl 00086 00087 #endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_