1 //===-- Core Structures for printf ------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H
10 #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H
12 #include "src/__support/CPP/string_view.h"
13 #include "src/__support/FPUtil/FPBits.h"
18 namespace __llvm_libc
{
19 namespace printf_core
{
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
};
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
32 // These flags come from the GNU extensions which aren't yet implemented.
33 // group_decimals = 0x20, // '
34 // locale_digits = 0x40, // I
37 struct FormatSection
{
40 cpp::string_view raw_string
;
42 // Format Specifier Values
43 FormatFlags flags
= FormatFlags(0);
44 LengthModifier length_modifier
= LengthModifier::none
;
48 // Needs to be large enough to hold a long double.
49 fputil::FPBits
<long double>::UIntType conv_val_raw
;
54 // This operator is only used for testing and should be automatically
55 // optimized out for release builds.
56 bool operator==(const FormatSection
&other
) {
57 if (has_conv
!= other
.has_conv
)
60 if (raw_string
!= other
.raw_string
)
64 if (!((static_cast<uint8_t>(flags
) ==
65 static_cast<uint8_t>(other
.flags
)) &&
66 (min_width
== other
.min_width
) && (precision
== other
.precision
) &&
67 (length_modifier
== other
.length_modifier
) &&
68 (conv_name
== other
.conv_name
)))
71 if (conv_name
== 'p' || conv_name
== 'n' || conv_name
== 's')
72 return (conv_val_ptr
== other
.conv_val_ptr
);
73 else if (conv_name
!= '%')
74 return (conv_val_raw
== other
.conv_val_raw
);
80 enum PrimaryType
: uint8_t { Unknown
= 0, Float
= 1, Pointer
= 2, Integer
= 3 };
82 // TypeDesc stores the information about a type that is relevant to printf in
83 // a relatively compact manner.
86 PrimaryType primary_type
;
87 LIBC_INLINE
constexpr bool operator==(const TypeDesc
&other
) const {
88 return (size
== other
.size
) && (primary_type
== other
.primary_type
);
92 template <typename T
> LIBC_INLINE
constexpr TypeDesc
type_desc_from_type() {
93 if constexpr (cpp::is_same_v
<T
, void>) {
94 return TypeDesc
{0, PrimaryType::Unknown
};
96 constexpr bool isPointer
= cpp::is_pointer_v
<T
>;
97 constexpr bool isFloat
= cpp::is_floating_point_v
<T
>;
98 return TypeDesc
{sizeof(T
), isPointer
? PrimaryType::Pointer
99 : isFloat
? PrimaryType::Float
100 : PrimaryType::Integer
};
104 // This is the value to be returned by conversions when no error has occurred.
105 constexpr int WRITE_OK
= 0;
106 // These are the printf return values for when an error has occurred. They are
107 // all negative, and should be distinct.
108 constexpr int FILE_WRITE_ERROR
= -1;
109 constexpr int FILE_STATUS_ERROR
= -2;
110 constexpr int NULLPTR_WRITE_ERROR
= -3;
111 constexpr int INT_CONVERSION_ERROR
= -4;
113 } // namespace printf_core
114 } // namespace __llvm_libc
116 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H