1 //===-- Internal implementation header of vfprintf --------------*- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_VFPRINTF_INTERNAL_H 10 #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_VFPRINTF_INTERNAL_H 11 12 #include "src/__support/File/file.h" 13 #include "src/__support/arg_list.h" 14 #include "src/__support/macros/attributes.h" // For LIBC_INLINE 15 #include "src/__support/macros/config.h" 16 #include "src/stdio/printf_core/core_structs.h" 17 #include "src/stdio/printf_core/printf_main.h" 18 #include "src/stdio/printf_core/writer.h" 19 20 #include "hdr/types/FILE.h" 21 22 namespace LIBC_NAMESPACE_DECL { 23 24 namespace internal { 25 #ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE 26 LIBC_INLINE int ferror_unlocked(FILE *f) { 27 return reinterpret_cast<LIBC_NAMESPACE::File *>(f)->error_unlocked(); 28 } 29 30 LIBC_INLINE void flockfile(FILE *f) { 31 reinterpret_cast<LIBC_NAMESPACE::File *>(f)->lock(); 32 } 33 34 LIBC_INLINE void funlockfile(FILE *f) { 35 reinterpret_cast<LIBC_NAMESPACE::File *>(f)->unlock(); 36 } 37 38 LIBC_INLINE size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, 39 FILE *f) { 40 return reinterpret_cast<LIBC_NAMESPACE::File *>(f)->write_unlocked( 41 ptr, size * nmemb); 42 } 43 #else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) 44 LIBC_INLINE int ferror_unlocked(::FILE *f) { return ::ferror_unlocked(f); } 45 46 LIBC_INLINE void flockfile(::FILE *f) { ::flockfile(f); } 47 48 LIBC_INLINE void funlockfile(::FILE *f) { ::funlockfile(f); } 49 50 LIBC_INLINE size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, 51 ::FILE *f) { 52 return ::fwrite_unlocked(ptr, size, nmemb, f); 53 } 54 #endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE 55 } // namespace internal 56 57 namespace printf_core { 58 59 LIBC_INLINE int file_write_hook(cpp::string_view new_str, void *fp) { 60 ::FILE *target_file = reinterpret_cast<::FILE *>(fp); 61 // Write new_str to the target file. The logic preventing a zero-length write 62 // is in the writer, so we don't check here. 63 size_t written = internal::fwrite_unlocked(new_str.data(), sizeof(char), 64 new_str.size(), target_file); 65 if (written != new_str.size() || internal::ferror_unlocked(target_file)) 66 return FILE_WRITE_ERROR; 67 return WRITE_OK; 68 } 69 70 LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream, 71 const char *__restrict format, 72 internal::ArgList &args) { 73 constexpr size_t BUFF_SIZE = 1024; 74 char buffer[BUFF_SIZE]; 75 printf_core::WriteBuffer wb(buffer, BUFF_SIZE, &file_write_hook, 76 reinterpret_cast<void *>(stream)); 77 Writer writer(&wb); 78 internal::flockfile(stream); 79 int retval = printf_main(&writer, format, args); 80 int flushval = wb.overflow_write(""); 81 if (flushval != WRITE_OK) 82 retval = flushval; 83 internal::funlockfile(stream); 84 return retval; 85 } 86 87 } // namespace printf_core 88 } // namespace LIBC_NAMESPACE_DECL 89 90 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_VFPRINTF_INTERNAL_H 91