[libc][NFC] Move aligned access implementations to separate header
[llvm-project.git] / libc / src / stdio / printf_core / core_structs.h
blob771d5a8cff437e5666b2896d99df8f50d29917b1
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 //===----------------------------------------------------------------------===//
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"
15 #include <inttypes.h>
16 #include <stddef.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 {
38 bool has_conv;
40 cpp::string_view raw_string;
42 // Format Specifier Values
43 FormatFlags flags = FormatFlags(0);
44 LengthModifier length_modifier = LengthModifier::none;
45 int min_width = 0;
46 int precision = -1;
48 // Needs to be large enough to hold a long double.
49 fputil::FPBits<long double>::UIntType conv_val_raw;
50 void *conv_val_ptr;
52 char conv_name;
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)
58 return false;
60 if (raw_string != other.raw_string)
61 return false;
63 if (has_conv) {
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)))
69 return false;
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);
76 return true;
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.
84 struct TypeDesc {
85 uint8_t size;
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};
95 } else {
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