72 lines · c
1//===-- Internal Implementation of asprintf ---------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/func/free.h"10#include "hdr/func/malloc.h"11#include "hdr/func/realloc.h"12#include "src/__support/arg_list.h"13#include "src/__support/error_or.h"14#include "src/stdio/printf_core/core_structs.h"15#include "src/stdio/printf_core/printf_main.h"16#include "src/stdio/printf_core/writer.h"17 18namespace LIBC_NAMESPACE_DECL {19namespace printf_core {20 21LIBC_INLINE int resize_overflow_hook(cpp::string_view new_str, void *target) {22 WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> *wb =23 reinterpret_cast<24 WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> *>(target);25 size_t new_size = new_str.size() + wb->buff_cur;26 const bool isBuffOnStack = (wb->buff == wb->init_buff);27 char *new_buff = static_cast<char *>(28 isBuffOnStack ? malloc(new_size + 1)29 : realloc(wb->buff, new_size + 1)); // +1 for null30 if (new_buff == nullptr) {31 if (wb->buff != wb->init_buff)32 free(wb->buff);33 return ALLOCATION_ERROR;34 }35 if (isBuffOnStack)36 inline_memcpy(new_buff, wb->buff, wb->buff_cur);37 wb->buff = new_buff;38 inline_memcpy(wb->buff + wb->buff_cur, new_str.data(), new_str.size());39 wb->buff_cur = new_size;40 wb->buff_len = new_size;41 return printf_core::WRITE_OK;42}43 44constexpr size_t DEFAULT_BUFFER_SIZE = 200;45 46LIBC_INLINE ErrorOr<size_t> vasprintf_internal(char **ret,47 const char *__restrict format,48 internal::ArgList args) {49 char init_buff_on_stack[DEFAULT_BUFFER_SIZE];50 printf_core::WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> wb(51 init_buff_on_stack, DEFAULT_BUFFER_SIZE, resize_overflow_hook);52 printf_core::Writer writer(wb);53 54 auto ret_val = printf_core::printf_main(&writer, format, args);55 if (!ret_val.has_value()) {56 *ret = nullptr;57 return ret_val;58 }59 if (wb.buff == init_buff_on_stack) {60 *ret = static_cast<char *>(malloc(ret_val.value() + 1));61 if (ret == nullptr)62 return Error(ALLOCATION_ERROR);63 inline_memcpy(*ret, wb.buff, ret_val.value());64 } else {65 *ret = wb.buff;66 }67 (*ret)[ret_val.value()] = '\0';68 return ret_val;69}70} // namespace printf_core71} // namespace LIBC_NAMESPACE_DECL72