blob: 16329334be59de268887aaf56715aa62af058bd8 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors
// Copyright (c) 2008 Travis Geiselbrecht
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_
#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_
#ifdef __cplusplus
#include <stdio.h>
#include <ktl/algorithm.h>
#include <ktl/span.h>
#include <ktl/string_view.h>
// FILE* wrapper over a string.
class StringFile : public FILE {
public:
StringFile() = delete;
StringFile(const StringFile &) = delete;
StringFile operator=(const StringFile &) = delete;
explicit StringFile(ktl::span<char> s) : FILE(this), buffer_(s) {}
~StringFile() = default;
// Adds a null character at the end of the current buffer and returns a view
// into the written section.
ktl::span<char> take() &&;
// Returns |str.size()| and writes as much of |str| as it would fit in the
// buffer [offest_, size - 1) while reserving the last byte for null
// character.
int Write(ktl::string_view str);
// Returns a region representing the currently used portion of the buffer.
ktl::span<char> used_region() const {
return (offset_ > 0) ? ktl::span<char>{buffer_.data(), offset_} : ktl::span<char>{};
}
// Returns a region representing the remaining unused space in the buffer,
// _not_ including the space reserved for the final null character.
ktl::span<char> available_region() const {
const size_t available = ktl::max<size_t>(buffer_.size() - offset_, 1) - 1;
return (available > 0) ? ktl::span<char>{buffer_.data() + offset_, available}
: ktl::span<char>{};
}
// Skip up to |amt| bytes in the buffer, advancing the write pointer as if we
// had written data, but without actually changing the buffer.
void Skip(size_t amt) {
amt = ktl::min(amt, available_region().size());
offset_ += amt;
}
// Provide two ways for users to convert the currently used buffer into a
// string_view. Given a string file |S|, users may say either:
//
// 1) S.as_string_view(); // or
// 2) static_cast<ktl::string_view>(S);
//
// to perform the conversion.
//
ktl::string_view as_string_view() const {
return (offset_ > 0) ? ktl::string_view{buffer_.data(), offset_} : ktl::string_view{};
}
explicit operator ktl::string_view() const { return this->as_string_view(); }
private:
ktl::span<char> buffer_;
size_t offset_ = 0;
};
#endif // __cplusplus
#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_