1 //===-- lib/Parser/char-buffer.cpp ----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "flang/Parser/char-buffer.h" 10 #include "flang/Common/idioms.h" 11 #include <algorithm> 12 #include <cstddef> 13 #include <cstring> 14 15 namespace Fortran::parser { 16 17 char *CharBuffer::FreeSpace(std::size_t &n) { 18 int offset{LastBlockOffset()}; 19 if (blocks_.empty()) { 20 blocks_.emplace_front(); 21 last_ = blocks_.begin(); 22 lastBlockEmpty_ = true; 23 } else if (offset == 0 && !lastBlockEmpty_) { 24 last_ = blocks_.emplace_after(last_); 25 lastBlockEmpty_ = true; 26 } 27 n = Block::capacity - offset; 28 return last_->data + offset; 29 } 30 31 void CharBuffer::Claim(std::size_t n) { 32 if (n > 0) { 33 bytes_ += n; 34 lastBlockEmpty_ = false; 35 } 36 } 37 38 std::size_t CharBuffer::Put(const char *data, std::size_t n) { 39 std::size_t chunk; 40 for (std::size_t at{0}; at < n; at += chunk) { 41 char *to{FreeSpace(chunk)}; 42 chunk = std::min(n - at, chunk); 43 Claim(chunk); 44 std::memcpy(to, data + at, chunk); 45 } 46 return bytes_ - n; 47 } 48 49 std::size_t CharBuffer::Put(const std::string &str) { 50 return Put(str.data(), str.size()); 51 } 52 53 std::string CharBuffer::Marshal() const { 54 std::string result; 55 std::size_t bytes{bytes_}; 56 result.reserve(bytes); 57 for (const Block &block : blocks_) { 58 std::size_t chunk{std::min(bytes, Block::capacity)}; 59 for (std::size_t j{0}; j < chunk; ++j) { 60 result += block.data[j]; 61 } 62 bytes -= chunk; 63 } 64 result.shrink_to_fit(); 65 CHECK(result.size() == bytes_); 66 return result; 67 } 68 } // namespace Fortran::parser 69