1 | //===-- Format specifier converter implmentation 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 | #include "src/stdio/printf_core/converter.h" |
10 | |
11 | #include "src/stdio/printf_core/core_structs.h" |
12 | #include "src/stdio/printf_core/printf_config.h" |
13 | #include "src/stdio/printf_core/writer.h" |
14 | |
15 | // This option allows for replacing all of the conversion functions with custom |
16 | // replacements. This allows conversions to be replaced at compile time. |
17 | #ifndef LIBC_COPT_PRINTF_CONV_ATLAS |
18 | #include "src/stdio/printf_core/converter_atlas.h" |
19 | #else |
20 | #include LIBC_COPT_PRINTF_CONV_ATLAS |
21 | #endif |
22 | |
23 | #include <stddef.h> |
24 | |
25 | namespace LIBC_NAMESPACE { |
26 | namespace printf_core { |
27 | |
28 | int convert(Writer *writer, const FormatSection &to_conv) { |
29 | if (!to_conv.has_conv) |
30 | return writer->write(new_string: to_conv.raw_string); |
31 | |
32 | #if !defined(LIBC_COPT_PRINTF_DISABLE_FLOAT) && \ |
33 | defined(LIBC_COPT_PRINTF_HEX_LONG_DOUBLE) |
34 | if (to_conv.length_modifier == LengthModifier::L) { |
35 | switch (to_conv.conv_name) { |
36 | case 'f': |
37 | case 'F': |
38 | case 'e': |
39 | case 'E': |
40 | case 'g': |
41 | case 'G': |
42 | return convert_float_hex_exp(writer, to_conv); |
43 | default: |
44 | break; |
45 | } |
46 | } |
47 | #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT |
48 | |
49 | switch (to_conv.conv_name) { |
50 | case '%': |
51 | return writer->write(new_string: "%" ); |
52 | case 'c': |
53 | return convert_char(writer, to_conv); |
54 | case 's': |
55 | return convert_string(writer, to_conv); |
56 | case 'd': |
57 | case 'i': |
58 | case 'u': |
59 | case 'o': |
60 | case 'x': |
61 | case 'X': |
62 | case 'b': |
63 | case 'B': |
64 | return convert_int(writer, to_conv); |
65 | #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT |
66 | case 'f': |
67 | case 'F': |
68 | return convert_float_decimal(writer, to_conv); |
69 | case 'e': |
70 | case 'E': |
71 | return convert_float_dec_exp(writer, to_conv); |
72 | case 'a': |
73 | case 'A': |
74 | return convert_float_hex_exp(writer, to_conv); |
75 | case 'g': |
76 | case 'G': |
77 | return convert_float_dec_auto(writer, to_conv); |
78 | #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT |
79 | #ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT |
80 | case 'r': |
81 | case 'R': |
82 | case 'k': |
83 | case 'K': |
84 | return convert_fixed(writer, to_conv); |
85 | #endif // LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT |
86 | #ifndef LIBC_COPT_PRINTF_DISABLE_WRITE_INT |
87 | case 'n': |
88 | return convert_write_int(writer, to_conv); |
89 | #endif // LIBC_COPT_PRINTF_DISABLE_WRITE_INT |
90 | case 'p': |
91 | return convert_pointer(writer, to_conv); |
92 | default: |
93 | return writer->write(new_string: to_conv.raw_string); |
94 | } |
95 | return -1; |
96 | } |
97 | |
98 | } // namespace printf_core |
99 | } // namespace LIBC_NAMESPACE |
100 | |