| // 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 <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; | 
 |  | 
 |   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_ |