Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libc / src / stdio / scanf_core / converter_utils.h
bloba14f35796d27f2f1ba9124ba36382a01d9e414ce
1 //===-- Format specifier converter for scanf -------------------*- 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_SCANF_CORE_CONVERTER_UTILS_H
10 #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_UTILS_H
12 #include "src/__support/common.h"
13 #include "src/__support/ctype_utils.h"
14 #include "src/__support/str_to_float.h"
15 #include "src/stdio/scanf_core/core_structs.h"
16 #include "src/stdio/scanf_core/reader.h"
18 #include <stddef.h>
20 namespace LIBC_NAMESPACE {
21 namespace scanf_core {
23 LIBC_INLINE constexpr char to_lower(char a) { return a | 32; }
25 LIBC_INLINE constexpr int b36_char_to_int(char input) {
26 if (internal::isdigit(input))
27 return input - '0';
28 if (internal::isalpha(input))
29 return to_lower(input) + 10 - 'a';
30 return 0;
33 LIBC_INLINE void write_int_with_length(uintmax_t output_val,
34 const FormatSection &to_conv) {
35 if ((to_conv.flags & NO_WRITE) != 0) {
36 return;
38 void *output_ptr = to_conv.output_ptr;
39 // The %p conversion uses this function, and is always void*.
40 if (to_conv.conv_name == 'p') {
41 *reinterpret_cast<void **>(output_ptr) =
42 reinterpret_cast<void *>(output_val);
43 return;
45 LengthModifier lm = to_conv.length_modifier;
46 switch (lm) {
47 case (LengthModifier::hh):
48 *reinterpret_cast<unsigned char *>(output_ptr) =
49 static_cast<unsigned char>(output_val);
50 break;
51 case (LengthModifier::h):
52 *reinterpret_cast<unsigned short *>(output_ptr) =
53 static_cast<unsigned short>(output_val);
54 break;
55 case (LengthModifier::NONE):
56 *reinterpret_cast<unsigned int *>(output_ptr) =
57 static_cast<unsigned int>(output_val);
58 break;
59 case (LengthModifier::l):
60 *reinterpret_cast<unsigned long *>(output_ptr) =
61 static_cast<unsigned long>(output_val);
62 break;
63 case (LengthModifier::ll):
64 case (LengthModifier::L):
65 *reinterpret_cast<unsigned long long *>(output_ptr) =
66 static_cast<unsigned long long>(output_val);
67 break;
68 case (LengthModifier::j):
69 *reinterpret_cast<uintmax_t *>(output_ptr) =
70 static_cast<uintmax_t>(output_val);
71 break;
72 case (LengthModifier::z):
73 *reinterpret_cast<size_t *>(output_ptr) = static_cast<size_t>(output_val);
74 break;
75 case (LengthModifier::t):
76 *reinterpret_cast<ptrdiff_t *>(output_ptr) =
77 static_cast<ptrdiff_t>(output_val);
78 break;
82 LIBC_INLINE void write_float_with_length(char *str,
83 const FormatSection &to_conv) {
84 if ((to_conv.flags & NO_WRITE) != 0) {
85 return;
88 void *output_ptr = to_conv.output_ptr;
90 LengthModifier lm = to_conv.length_modifier;
91 switch (lm) {
92 case (LengthModifier::l): {
93 auto value = internal::strtofloatingpoint<double>(str);
94 *reinterpret_cast<double *>(output_ptr) = value;
95 break;
97 case (LengthModifier::L): {
98 auto value = internal::strtofloatingpoint<long double>(str);
99 *reinterpret_cast<long double *>(output_ptr) = value;
100 break;
102 default: {
103 auto value = internal::strtofloatingpoint<float>(str);
104 *reinterpret_cast<float *>(output_ptr) = value;
105 break;
110 } // namespace scanf_core
111 } // namespace LIBC_NAMESPACE
113 #endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_UTILS_H