Warning: This file is not a C or C++ file. It does not have highlighting.

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/macros/config.h"
13
14#include "src/__support/CPP/string_view.h"
15#include "src/__support/CPP/type_traits.h"
16#include "src/__support/FPUtil/FPBits.h"
17#include "src/stdio/printf_core/printf_config.h"
18
19#include <inttypes.h>
20#include <stddef.h>
21
22namespace LIBC_NAMESPACE_DECL {
23namespace printf_core {
24
25// These length modifiers match the length modifiers in the format string, which
26// is why they are formatted differently from the rest of the file.
27enum class LengthModifier { hh, h, l, ll, j, z, t, L, w, wf, none };
28
29struct LengthSpec {
30 LengthModifier lm;
31 size_t bit_width;
32};
33
34enum FormatFlags : uint8_t {
35 LEFT_JUSTIFIED = 0x01, // -
36 FORCE_SIGN = 0x02, // +
37 SPACE_PREFIX = 0x04, // space
38 ALTERNATE_FORM = 0x08, // #
39 LEADING_ZEROES = 0x10, // 0
40
41 // These flags come from the GNU extensions which aren't yet implemented.
42 // group_decimals = 0x20, // '
43 // locale_digits = 0x40, // I
44};
45
46struct FormatSection {
47 bool has_conv;
48
49 cpp::string_view raw_string;
50
51 // Format Specifier Values
52 FormatFlags flags = FormatFlags(0);
53 LengthModifier length_modifier = LengthModifier::none;
54 size_t bit_width = 0;
55 int min_width = 0;
56 int precision = -1;
57
58 // Needs to be large enough to hold a long double. Special case handling for
59 // the PowerPC double double type because it has no FPBits interface.
60#ifdef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
61 UInt128 conv_val_raw;
62#else
63 fputil::FPBits<long double>::StorageType conv_val_raw;
64#endif // LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
65 void *conv_val_ptr;
66
67 char conv_name;
68
69 // This operator is only used for testing and should be automatically
70 // optimized out for release builds.
71 LIBC_INLINE bool operator==(const FormatSection &other) const {
72 if (has_conv != other.has_conv)
73 return false;
74
75 if (raw_string != other.raw_string)
76 return false;
77
78 if (has_conv) {
79 if (!((static_cast<uint8_t>(flags) ==
80 static_cast<uint8_t>(other.flags)) &&
81 (min_width == other.min_width) && (precision == other.precision) &&
82 (bit_width == other.bit_width) &&
83 (length_modifier == other.length_modifier) &&
84 (conv_name == other.conv_name)))
85 return false;
86
87 if (conv_name == 'p' || conv_name == 'n' || conv_name == 's')
88 return (conv_val_ptr == other.conv_val_ptr);
89 else if (conv_name != '%')
90 return (conv_val_raw == other.conv_val_raw);
91 }
92 return true;
93 }
94};
95
96enum PrimaryType : uint8_t {
97 Unknown = 0,
98 Float = 1,
99 Pointer = 2,
100 Integer = 3,
101 FixedPoint = 4,
102};
103
104// TypeDesc stores the information about a type that is relevant to printf in
105// a relatively compact manner.
106struct TypeDesc {
107 uint8_t size;
108 PrimaryType primary_type;
109 LIBC_INLINE constexpr bool operator==(const TypeDesc &other) const {
110 return (size == other.size) && (primary_type == other.primary_type);
111 }
112};
113
114template <typename T> LIBC_INLINE constexpr TypeDesc type_desc_from_type() {
115 if constexpr (cpp::is_same_v<T, void>) {
116 return TypeDesc{0, PrimaryType::Unknown};
117 } else {
118 constexpr bool IS_POINTER = cpp::is_pointer_v<T>;
119 constexpr bool IS_FLOAT = cpp::is_floating_point_v<T>;
120#ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
121 constexpr bool IS_FIXED_POINT = cpp::is_fixed_point_v<T>;
122#else
123 constexpr bool IS_FIXED_POINT = false;
124#endif // LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
125
126 return TypeDesc{sizeof(T), IS_POINTER ? PrimaryType::Pointer
127 : IS_FLOAT ? PrimaryType::Float
128 : IS_FIXED_POINT ? PrimaryType::FixedPoint
129 : PrimaryType::Integer};
130 }
131}
132
133// This is the value to be returned by conversions when no error has occurred.
134constexpr int WRITE_OK = 0;
135// These are the printf return values for when an error has occurred. They are
136// all negative, and should be distinct.
137constexpr int FILE_WRITE_ERROR = -1;
138constexpr int FILE_STATUS_ERROR = -2;
139constexpr int NULLPTR_WRITE_ERROR = -3;
140constexpr int INT_CONVERSION_ERROR = -4;
141constexpr int FIXED_POINT_CONVERSION_ERROR = -5;
142constexpr int ALLOCATION_ERROR = -6;
143} // namespace printf_core
144} // namespace LIBC_NAMESPACE_DECL
145
146#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H
147

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of libc/src/stdio/printf_core/core_structs.h