| // Copyright 2020 The Fuchsia Authors |
| // |
| // 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 |
| |
| #include <stdarg.h> |
| #include <stdio.h> |
| |
| #include <ktl/algorithm.h> |
| |
| namespace { |
| |
| class String { |
| public: |
| String() = delete; |
| String(char* buf, size_t size) : buffer_(buf), capacity_(size) {} |
| |
| FILE* file() { return &file_; } |
| |
| ~String() { |
| if (capacity_ > 0) { |
| buffer_[pos_] = '\0'; |
| } |
| } |
| |
| private: |
| FILE file_{&Callback, this}; |
| char* buffer_; |
| size_t capacity_; |
| size_t pos_ = 0; |
| |
| int Write(ktl::string_view str) { |
| // The capacity includes the NUL terminator not written here. |
| if (pos_ + 1 < capacity_) { |
| size_t copy = ktl::min(str.size(), capacity_ - 1 - pos_); |
| memcpy(&buffer_[pos_], str.data(), copy); |
| pos_ += copy; |
| } |
| return static_cast<int>(str.size()); |
| } |
| |
| static int Callback(void* ptr, ktl::string_view str) { |
| return static_cast<String*>(ptr)->Write(str); |
| } |
| }; |
| |
| } // namespace |
| |
| int vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { |
| String out{buf, len}; |
| return vfprintf(out.file(), fmt, args); |
| } |
| |
| int snprintf(char* buf, size_t len, const char* fmt, ...) { |
| va_list args; |
| va_start(args, fmt); |
| int result = vsnprintf(buf, len, fmt, args); |
| va_end(args); |
| return result; |
| } |