| // 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 <array> |
| #include <memory> |
| #include <streambuf> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| 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<size_t>(n)); |
| return n; |
| } |
| |
| // Called by std::ostream to write a single character. |
| int_type overflow(int_type ch) override { |
| Append(static_cast<char>(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<char, kPageSize>; |
| |
| size_t pos_ = kPageSize; |
| std::vector<std::unique_ptr<Page>> pages_; |
| }; |
| |
| #endif // TOOLS_GN_STRING_OUTPUT_BUFFER_H_ |