brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.5 KiB · 41df17b Raw
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