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 {
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.
59 fputil::FPBits<long double>::StorageType conv_val_raw;
60 void *conv_val_ptr;
61
62 char conv_name;
63
64 // This operator is only used for testing and should be automatically
65 // optimized out for release builds.
66 LIBC_INLINE bool operator==(const FormatSection &other) const {
67 if (has_conv != other.has_conv)
68 return false;
69
70 if (raw_string != other.raw_string)
71 return false;
72
73 if (has_conv) {
74 if (!((static_cast<uint8_t>(flags) ==
75 static_cast<uint8_t>(other.flags)) &&
76 (min_width == other.min_width) && (precision == other.precision) &&
77 (bit_width == other.bit_width) &&
78 (length_modifier == other.length_modifier) &&
79 (conv_name == other.conv_name)))
80 return false;
81
82 if (conv_name == 'p' || conv_name == 'n' || conv_name == 's')
83 return (conv_val_ptr == other.conv_val_ptr);
84 else if (conv_name != '%')
85 return (conv_val_raw == other.conv_val_raw);
86 }
87 return true;
88 }
89};
90
91enum PrimaryType : uint8_t {
92 Unknown = 0,
93 Float = 1,
94 Pointer = 2,
95 Integer = 3,
96 FixedPoint = 4,
97};
98
99// TypeDesc stores the information about a type that is relevant to printf in
100// a relatively compact manner.
101struct TypeDesc {
102 uint8_t size;
103 PrimaryType primary_type;
104 LIBC_INLINE constexpr bool operator==(const TypeDesc &other) const {
105 return (size == other.size) && (primary_type == other.primary_type);
106 }
107};
108
109template <typename T> LIBC_INLINE constexpr TypeDesc type_desc_from_type() {
110 if constexpr (cpp::is_same_v<T, void>) {
111 return TypeDesc{.size: 0, .primary_type: PrimaryType::Unknown};
112 } else {
113 constexpr bool IS_POINTER = cpp::is_pointer_v<T>;
114 constexpr bool IS_FLOAT = cpp::is_floating_point_v<T>;
115#ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
116 constexpr bool IS_FIXED_POINT = cpp::is_fixed_point_v<T>;
117#else
118 constexpr bool IS_FIXED_POINT = false;
119#endif // LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
120
121 return TypeDesc{.size: sizeof(T), .primary_type: IS_POINTER ? PrimaryType::Pointer
122 : IS_FLOAT ? PrimaryType::Float
123 : IS_FIXED_POINT ? PrimaryType::FixedPoint
124 : PrimaryType::Integer};
125 }
126}
127
128// This is the value to be returned by conversions when no error has occurred.
129constexpr int WRITE_OK = 0;
130// These are the printf return values for when an error has occurred. They are
131// all negative, and should be distinct.
132constexpr int FILE_WRITE_ERROR = -1;
133constexpr int FILE_STATUS_ERROR = -2;
134constexpr int NULLPTR_WRITE_ERROR = -3;
135constexpr int INT_CONVERSION_ERROR = -4;
136constexpr int FIXED_POINT_CONVERSION_ERROR = -5;
137
138} // namespace printf_core
139} // namespace LIBC_NAMESPACE
140
141#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CORE_STRUCTS_H
142

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