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