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//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_UTILS_H
10#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_UTILS_H
11
12#include "src/__support/ctype_utils.h"
13#include "src/__support/str_to_float.h"
14#include "src/stdio/scanf_core/core_structs.h"
15
16#include <stddef.h>
17
18namespace LIBC_NAMESPACE {
19namespace scanf_core {
20
21LIBC_INLINE constexpr char to_lower(char a) { return a | 32; }
22
23LIBC_INLINE constexpr int b36_char_to_int(char input) {
24 if (internal::isdigit(ch: input))
25 return input - '0';
26 if (internal::isalpha(ch: input))
27 return to_lower(a: input) + 10 - 'a';
28 return 0;
29}
30
31LIBC_INLINE void write_int_with_length(uintmax_t output_val,
32 const FormatSection &to_conv) {
33 if ((to_conv.flags & NO_WRITE) != 0) {
34 return;
35 }
36 void *output_ptr = to_conv.output_ptr;
37 // The %p conversion uses this function, and is always void*.
38 if (to_conv.conv_name == 'p') {
39 *reinterpret_cast<void **>(output_ptr) =
40 reinterpret_cast<void *>(output_val);
41 return;
42 }
43 LengthModifier lm = to_conv.length_modifier;
44 switch (lm) {
45 case (LengthModifier::hh):
46 *reinterpret_cast<unsigned char *>(output_ptr) =
47 static_cast<unsigned char>(output_val);
48 break;
49 case (LengthModifier::h):
50 *reinterpret_cast<unsigned short *>(output_ptr) =
51 static_cast<unsigned short>(output_val);
52 break;
53 case (LengthModifier::NONE):
54 *reinterpret_cast<unsigned int *>(output_ptr) =
55 static_cast<unsigned int>(output_val);
56 break;
57 case (LengthModifier::l):
58 *reinterpret_cast<unsigned long *>(output_ptr) =
59 static_cast<unsigned long>(output_val);
60 break;
61 case (LengthModifier::ll):
62 case (LengthModifier::L):
63 *reinterpret_cast<unsigned long long *>(output_ptr) =
64 static_cast<unsigned long long>(output_val);
65 break;
66 case (LengthModifier::j):
67 *reinterpret_cast<uintmax_t *>(output_ptr) =
68 static_cast<uintmax_t>(output_val);
69 break;
70 case (LengthModifier::z):
71 *reinterpret_cast<size_t *>(output_ptr) = static_cast<size_t>(output_val);
72 break;
73 case (LengthModifier::t):
74 *reinterpret_cast<ptrdiff_t *>(output_ptr) =
75 static_cast<ptrdiff_t>(output_val);
76 break;
77 }
78}
79
80LIBC_INLINE void write_float_with_length(char *str,
81 const FormatSection &to_conv) {
82 if ((to_conv.flags & NO_WRITE) != 0) {
83 return;
84 }
85
86 void *output_ptr = to_conv.output_ptr;
87
88 LengthModifier lm = to_conv.length_modifier;
89 switch (lm) {
90 case (LengthModifier::l): {
91 auto value = internal::strtofloatingpoint<double>(src: str);
92 *reinterpret_cast<double *>(output_ptr) = value;
93 break;
94 }
95 case (LengthModifier::L): {
96 auto value = internal::strtofloatingpoint<long double>(src: str);
97 *reinterpret_cast<long double *>(output_ptr) = value;
98 break;
99 }
100 default: {
101 auto value = internal::strtofloatingpoint<float>(src: str);
102 *reinterpret_cast<float *>(output_ptr) = value;
103 break;
104 }
105 }
106}
107
108} // namespace scanf_core
109} // namespace LIBC_NAMESPACE
110
111#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_UTILS_H
112

source code of libc/src/stdio/scanf_core/converter_utils.h