diff options
Diffstat (limited to 'lib/libc/include/string-file.h')
| -rw-r--r-- | lib/libc/include/string-file.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/lib/libc/include/string-file.h b/lib/libc/include/string-file.h new file mode 100644 index 0000000..1632933 --- /dev/null +++ b/lib/libc/include/string-file.h @@ -0,0 +1,79 @@ +// 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_ |
