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