1 //===-- Format specifier converter for scanf -------------------*- C++ -*-===//
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
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"
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
))
28 if (internal::isalpha(input
))
29 return to_lower(input
) + 10 - 'a';
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) {
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
);
45 LengthModifier lm
= to_conv
.length_modifier
;
47 case (LengthModifier::hh
):
48 *reinterpret_cast<unsigned char *>(output_ptr
) =
49 static_cast<unsigned char>(output_val
);
51 case (LengthModifier::h
):
52 *reinterpret_cast<unsigned short *>(output_ptr
) =
53 static_cast<unsigned short>(output_val
);
55 case (LengthModifier::NONE
):
56 *reinterpret_cast<unsigned int *>(output_ptr
) =
57 static_cast<unsigned int>(output_val
);
59 case (LengthModifier::l
):
60 *reinterpret_cast<unsigned long *>(output_ptr
) =
61 static_cast<unsigned long>(output_val
);
63 case (LengthModifier::ll
):
64 case (LengthModifier::L
):
65 *reinterpret_cast<unsigned long long *>(output_ptr
) =
66 static_cast<unsigned long long>(output_val
);
68 case (LengthModifier::j
):
69 *reinterpret_cast<uintmax_t *>(output_ptr
) =
70 static_cast<uintmax_t>(output_val
);
72 case (LengthModifier::z
):
73 *reinterpret_cast<size_t *>(output_ptr
) = static_cast<size_t>(output_val
);
75 case (LengthModifier::t
):
76 *reinterpret_cast<ptrdiff_t *>(output_ptr
) =
77 static_cast<ptrdiff_t>(output_val
);
82 LIBC_INLINE
void write_float_with_length(char *str
,
83 const FormatSection
&to_conv
) {
84 if ((to_conv
.flags
& NO_WRITE
) != 0) {
88 void *output_ptr
= to_conv
.output_ptr
;
90 LengthModifier lm
= to_conv
.length_modifier
;
92 case (LengthModifier::l
): {
93 auto value
= internal::strtofloatingpoint
<double>(str
);
94 *reinterpret_cast<double *>(output_ptr
) = value
;
97 case (LengthModifier::L
): {
98 auto value
= internal::strtofloatingpoint
<long double>(str
);
99 *reinterpret_cast<long double *>(output_ptr
) = value
;
103 auto value
= internal::strtofloatingpoint
<float>(str
);
104 *reinterpret_cast<float *>(output_ptr
) = value
;
110 } // namespace scanf_core
111 } // namespace LIBC_NAMESPACE
113 #endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_UTILS_H