1 //===-- Core Structures for printf ------------------------------*- 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_CORE_STRUCTS_H 10 #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H 11 12 #include "src/__support/CPP/StringView.h" 13 #include "src/__support/FPUtil/FPBits.h" 14 15 #include <inttypes.h> 16 #include <stddef.h> 17 18 namespace __llvm_libc { 19 namespace printf_core { 20 21 // These length modifiers match the length modifiers in the format string, which 22 // is why they are formatted differently from the rest of the file. 23 enum class LengthModifier { hh, h, l, ll, j, z, t, L, none }; 24 25 enum FormatFlags : uint8_t { 26 LEFT_JUSTIFIED = 0x01, // - 27 FORCE_SIGN = 0x02, // + 28 SPACE_PREFIX = 0x04, // space 29 ALTERNATE_FORM = 0x08, // # 30 LEADING_ZEROES = 0x10, // 0 31 32 // These flags come from the GNU extensions which aren't yet implemented. 33 // group_decimals = 0x20, // ' 34 // locale_digits = 0x40, // I 35 }; 36 37 struct FormatSection { 38 bool has_conv; 39 40 const char *__restrict raw_string; 41 size_t raw_len; 42 43 // Format Specifier Values 44 FormatFlags flags = FormatFlags(0); 45 LengthModifier length_modifier = LengthModifier::none; 46 int min_width = 0; 47 int precision = -1; 48 49 // Needs to be large enough to hold a long double. 50 fputil::FPBits<long double>::UIntType conv_val_raw; 51 void *conv_val_ptr; 52 53 char conv_name; 54 55 // This operator is only used for testing and should be automatically 56 // optimized out for release builds. 57 bool operator==(const FormatSection &other) { 58 if (has_conv != other.has_conv) 59 return false; 60 61 if (!cpp::StringView(raw_string, raw_len) 62 .equals(cpp::StringView(other.raw_string, other.raw_len))) 63 return false; 64 65 if (has_conv) { 66 if (!((static_cast<uint8_t>(flags) == 67 static_cast<uint8_t>(other.flags)) && 68 (min_width == other.min_width) && (precision == other.precision) && 69 (length_modifier == other.length_modifier) && 70 (conv_name == other.conv_name))) 71 return false; 72 73 if (conv_name == 'p' || conv_name == 'n' || conv_name == 's') 74 return (conv_val_ptr == other.conv_val_ptr); 75 else if (conv_name != '%') 76 return (conv_val_raw == other.conv_val_raw); 77 } 78 return true; 79 } 80 }; 81 82 // This is the value to be returned by conversions when no error has occurred. 83 constexpr int WRITE_OK = 0; 84 // These are the printf return values for when an error has occurred. They are 85 // all negative, and should be distinct. 86 constexpr int FILE_WRITE_ERROR = -1; 87 constexpr int FILE_STATUS_ERROR = -2; 88 constexpr int NULLPTR_WRITE_ERROR = -3; 89 90 } // namespace printf_core 91 } // namespace __llvm_libc 92 93 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H 94