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 FreeSpace(std::size_t & n)17char *CharBuffer::FreeSpace(std::size_t &n) { 18 int offset{LastBlockOffset()}; 19 if (blocks_.empty()) { 20 blocks_.emplace_front(); 21 lastBlockEmpty_ = true; 22 } else if (offset == 0 && !lastBlockEmpty_) { 23 blocks_.emplace_back(); 24 lastBlockEmpty_ = true; 25 } 26 n = Block::capacity - offset; 27 return blocks_.back().data + offset; 28 } 29 Claim(std::size_t n)30void CharBuffer::Claim(std::size_t n) { 31 if (n > 0) { 32 bytes_ += n; 33 lastBlockEmpty_ = false; 34 } 35 } 36 Put(const char * data,std::size_t n)37std::size_t CharBuffer::Put(const char *data, std::size_t n) { 38 std::size_t chunk; 39 for (std::size_t at{0}; at < n; at += chunk) { 40 char *to{FreeSpace(chunk)}; 41 chunk = std::min(n - at, chunk); 42 Claim(chunk); 43 std::memcpy(to, data + at, chunk); 44 } 45 return bytes_ - n; 46 } 47 Put(const std::string & str)48std::size_t CharBuffer::Put(const std::string &str) { 49 return Put(str.data(), str.size()); 50 } 51 Marshal() const52std::string CharBuffer::Marshal() const { 53 std::string result; 54 std::size_t bytes{bytes_}; 55 result.reserve(bytes); 56 for (const Block &block : blocks_) { 57 std::size_t chunk{std::min(bytes, Block::capacity)}; 58 for (std::size_t j{0}; j < chunk; ++j) { 59 result += block.data[j]; 60 } 61 bytes -= chunk; 62 } 63 result.shrink_to_fit(); 64 CHECK(result.size() == bytes_); 65 return result; 66 } 67 } // namespace Fortran::parser 68