// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef TOOLS_GN_STRING_OUTPUT_BUFFER_H_ #define TOOLS_GN_STRING_OUTPUT_BUFFER_H_ #include #include #include #include #include #include namespace base { class FilePath; } // namespace base class Err; // An append-only very large storage area for string data. Useful for the parts // of GN that need to generate huge output files (e.g. --ide=json will create // a 139 MiB project.json file for the Fuchsia build). // // Usage is the following: // // 1) Create instance. // // 2) Use operator<<, or Append() to append data to the instance. // // 3) Alternatively, create an std::ostream that takes its address as // argument, then use the output stream as usual to append data to it. // // StringOutputBuffer storage; // std::ostream out(&storage); // out << "Hello world!"; // // 4) Use ContentsEqual() to compare the instance's content with that of a // given file. // // 5) Use WriteToFile() to write the content to a given file. // class StringOutputBuffer : public std::streambuf { public: StringOutputBuffer() = default; // Convert content to single std::string instance. Useful for unit-testing. std::string str() const; // Return the number of characters stored in this instance. size_t size() const { return (pages_.size() - 1u) * kPageSize + pos_; } // Append string to this instance. void Append(const char* str, size_t len); void Append(std::string_view str); void Append(char c); StringOutputBuffer& operator<<(std::string_view str) { Append(str); return *this; } // Compare the content of this instance with that of the file at |file_path|. bool ContentsEqual(const base::FilePath& file_path) const; // Write the contents of this instance to a file at |file_path|. bool WriteToFile(const base::FilePath& file_path, Err* err) const; // Write the contents of this instance to a file at |file_path| unless the // file already exists and the contents are equal. bool WriteToFileIfChanged(const base::FilePath& file_path, Err* err) const; static size_t GetPageSizeForTesting() { return kPageSize; } protected: // Called by std::ostream to write |n| chars from |s|. std::streamsize xsputn(const char* s, std::streamsize n) override { Append(s, static_cast(n)); return n; } // Called by std::ostream to write a single character. int_type overflow(int_type ch) override { Append(static_cast(ch)); return 1; } private: // Return the number of free bytes in the current page. size_t page_free_size() const { return kPageSize - pos_; } static constexpr size_t kPageSize = 65536; using Page = std::array; size_t pos_ = kPageSize; std::vector> pages_; }; #endif // TOOLS_GN_STRING_OUTPUT_BUFFER_H_