99#ifndef LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_COMPOSITE_CONVERTER_H
1010#define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_COMPOSITE_CONVERTER_H
1111
12+ #include " hdr/types/struct_tm.h"
1213#include " src/__support/CPP/string_view.h"
1314#include " src/__support/macros/config.h"
1415#include " src/stdio/printf_core/writer.h"
2122namespace LIBC_NAMESPACE_DECL {
2223namespace strftime_core {
2324
25+ LIBC_INLINE IntFormatSection
26+ get_specific_int_format (const tm *timeptr, const FormatSection &base_to_conv,
27+ char new_conv_name, int TRAILING_CONV_LEN = -1 ) {
28+ // a negative padding will be treated as the default
29+ const int NEW_MIN_WIDTH =
30+ TRAILING_CONV_LEN > 0 ? base_to_conv.min_width - TRAILING_CONV_LEN : 0 ;
31+ FormatSection new_conv = base_to_conv;
32+ new_conv.conv_name = new_conv_name;
33+ new_conv.min_width = NEW_MIN_WIDTH;
34+
35+ IntFormatSection result = get_int_format (new_conv, timeptr);
36+
37+ // If the user set the padding, but it's below the width of the trailing
38+ // conversions, then there should be no padding.
39+ if (base_to_conv.min_width > 0 && NEW_MIN_WIDTH < 0 )
40+ result.pad_to_len = 0 ;
41+
42+ return result;
43+ }
44+
2445LIBC_INLINE int convert_date_us (printf_core::Writer *writer,
2546 const FormatSection &to_conv,
2647 const tm *timeptr) {
2748 // format is %m/%d/%y (month/day/year)
2849 // we only pad the first conversion, and we assume all the other values are in
2950 // their valid ranges.
30- const size_t trailing_conv_len = 1 + 2 + 1 + 2 ; // sizeof("/01/02")
51+ constexpr int TRAILING_CONV_LEN = 1 + 2 + 1 + 2 ; // sizeof("/01/02")
3152 IntFormatSection year_conv;
3253 IntFormatSection mon_conv;
3354 IntFormatSection mday_conv;
3455
35- {
36- FormatSection raw_mon_conv = to_conv;
37- raw_mon_conv.conv_name = ' m' ;
38-
39- const int requested_padding = to_conv.min_width - trailing_conv_len;
40- // a negative padding will be treated as the default
41- raw_mon_conv.min_width = requested_padding;
42-
43- mon_conv = get_int_format (raw_mon_conv, timeptr);
44-
45- // If the user set the padding, but it's below the width of the trailing
46- // conversions, then there should be no padding.
47- if (to_conv.min_width > 0 && requested_padding < 0 )
48- mon_conv.pad_to_len = 0 ;
49- }
50- {
51- FormatSection raw_mday_conv = to_conv;
52- raw_mday_conv.conv_name = ' d' ;
53- raw_mday_conv.min_width = 0 ;
54-
55- mday_conv = get_int_format (raw_mday_conv, timeptr);
56- }
57- {
58- FormatSection raw_year_conv = to_conv;
59- raw_year_conv.conv_name = ' y' ;
60- raw_year_conv.min_width = 0 ;
61-
62- year_conv = get_int_format (raw_year_conv, timeptr);
63- }
56+ mon_conv = get_specific_int_format (timeptr, to_conv, ' m' , TRAILING_CONV_LEN);
57+ mday_conv = get_specific_int_format (timeptr, to_conv, ' d' );
58+ year_conv = get_specific_int_format (timeptr, to_conv, ' y' );
6459
6560 RET_IF_RESULT_NEGATIVE (write_padded_int (writer, mon_conv));
6661 RET_IF_RESULT_NEGATIVE (writer->write (' /' ));
@@ -77,40 +72,14 @@ LIBC_INLINE int convert_date_iso(printf_core::Writer *writer,
7772 // format is "%Y-%m-%d" (year-month-day)
7873 // we only pad the first conversion, and we assume all the other values are in
7974 // their valid ranges.
80- const size_t trailing_conv_len = 1 + 2 + 1 + 2 ; // sizeof("-01-02")
75+ constexpr int TRAILING_CONV_LEN = 1 + 2 + 1 + 2 ; // sizeof("-01-02")
8176 IntFormatSection year_conv;
8277 IntFormatSection mon_conv;
8378 IntFormatSection mday_conv;
8479
85- {
86- FormatSection raw_year_conv = to_conv;
87- raw_year_conv.conv_name = ' Y' ;
88-
89- const int requested_padding = to_conv.min_width - trailing_conv_len;
90- // a negative padding will be treated as the default
91- raw_year_conv.min_width = requested_padding;
92-
93- year_conv = get_int_format (raw_year_conv, timeptr);
94-
95- // If the user set the padding, but it's below the width of the trailing
96- // conversions, then there should be no padding.
97- if (to_conv.min_width > 0 && requested_padding < 0 )
98- year_conv.pad_to_len = 0 ;
99- }
100- {
101- FormatSection raw_mon_conv = to_conv;
102- raw_mon_conv.conv_name = ' m' ;
103- raw_mon_conv.min_width = 0 ;
104-
105- mon_conv = get_int_format (raw_mon_conv, timeptr);
106- }
107- {
108- FormatSection raw_mday_conv = to_conv;
109- raw_mday_conv.conv_name = ' d' ;
110- raw_mday_conv.min_width = 0 ;
111-
112- mday_conv = get_int_format (raw_mday_conv, timeptr);
113- }
80+ year_conv = get_specific_int_format (timeptr, to_conv, ' Y' , TRAILING_CONV_LEN);
81+ mon_conv = get_specific_int_format (timeptr, to_conv, ' m' );
82+ mday_conv = get_specific_int_format (timeptr, to_conv, ' d' );
11483
11584 RET_IF_RESULT_NEGATIVE (write_padded_int (writer, year_conv));
11685 RET_IF_RESULT_NEGATIVE (writer->write (' -' ));
@@ -127,42 +96,17 @@ LIBC_INLINE int convert_time_am_pm(printf_core::Writer *writer,
12796 // format is "%I:%M:%S %p" (hour:minute:second AM/PM)
12897 // we only pad the first conversion, and we assume all the other values are in
12998 // their valid ranges.
130- const size_t trailing_conv_len = 1 + 2 + 1 + 2 + 1 + 2 ; // sizeof(":01:02 AM")
99+ constexpr int TRAILING_CONV_LEN =
100+ 1 + 2 + 1 + 2 + 1 + 2 ; // sizeof(":01:02 AM")
131101 IntFormatSection hour_conv;
132102 IntFormatSection min_conv;
133103 IntFormatSection sec_conv;
134104
135105 const time_utils::TMReader time_reader (timeptr);
136106
137- {
138- FormatSection raw_hour_conv = to_conv;
139- raw_hour_conv.conv_name = ' I' ;
140-
141- const int requested_padding = to_conv.min_width - trailing_conv_len;
142- // a negative padding will be treated as the default
143- raw_hour_conv.min_width = requested_padding;
144-
145- hour_conv = get_int_format (raw_hour_conv, timeptr);
146-
147- // If the user set the padding, but it's below the width of the trailing
148- // conversions, then there should be no padding.
149- if (to_conv.min_width > 0 && requested_padding < 0 )
150- hour_conv.pad_to_len = 0 ;
151- }
152- {
153- FormatSection raw_min_conv = to_conv;
154- raw_min_conv.conv_name = ' M' ;
155- raw_min_conv.min_width = 0 ;
156-
157- min_conv = get_int_format (raw_min_conv, timeptr);
158- }
159- {
160- FormatSection raw_sec_conv = to_conv;
161- raw_sec_conv.conv_name = ' S' ;
162- raw_sec_conv.min_width = 0 ;
163-
164- sec_conv = get_int_format (raw_sec_conv, timeptr);
165- }
107+ hour_conv = get_specific_int_format (timeptr, to_conv, ' I' , TRAILING_CONV_LEN);
108+ min_conv = get_specific_int_format (timeptr, to_conv, ' M' );
109+ sec_conv = get_specific_int_format (timeptr, to_conv, ' S' );
166110
167111 RET_IF_RESULT_NEGATIVE (write_padded_int (writer, hour_conv));
168112 RET_IF_RESULT_NEGATIVE (writer->write (' :' ));
@@ -181,32 +125,13 @@ LIBC_INLINE int convert_time_minute(printf_core::Writer *writer,
181125 // format is "%H:%M" (hour:minute)
182126 // we only pad the first conversion, and we assume all the other values are in
183127 // their valid ranges.
184- const size_t trailing_conv_len = 1 + 2 ; // sizeof(":01")
128+ constexpr int TRAILING_CONV_LEN = 1 + 2 ; // sizeof(":01")
185129 IntFormatSection hour_conv;
186130 IntFormatSection min_conv;
187131
188- {
189- FormatSection raw_hour_conv = to_conv;
190- raw_hour_conv.conv_name = ' H' ;
191-
192- const int requested_padding = to_conv.min_width - trailing_conv_len;
193- // a negative padding will be treated as the default
194- raw_hour_conv.min_width = requested_padding;
132+ hour_conv = get_specific_int_format (timeptr, to_conv, ' H' , TRAILING_CONV_LEN);
133+ min_conv = get_specific_int_format (timeptr, to_conv, ' M' );
195134
196- hour_conv = get_int_format (raw_hour_conv, timeptr);
197-
198- // If the user set the padding, but it's below the width of the trailing
199- // conversions, then there should be no padding.
200- if (to_conv.min_width > 0 && requested_padding < 0 )
201- hour_conv.pad_to_len = 0 ;
202- }
203- {
204- FormatSection raw_min_conv = to_conv;
205- raw_min_conv.conv_name = ' M' ;
206- raw_min_conv.min_width = 0 ;
207-
208- min_conv = get_int_format (raw_min_conv, timeptr);
209- }
210135 RET_IF_RESULT_NEGATIVE (write_padded_int (writer, hour_conv));
211136 RET_IF_RESULT_NEGATIVE (writer->write (' :' ));
212137 RET_IF_RESULT_NEGATIVE (write_padded_int (writer, min_conv));
@@ -220,40 +145,14 @@ LIBC_INLINE int convert_time_second(printf_core::Writer *writer,
220145 // format is "%H:%M:%S" (hour:minute:second)
221146 // we only pad the first conversion, and we assume all the other values are in
222147 // their valid ranges.
223- const size_t trailing_conv_len = 1 + 2 + 1 + 2 ; // sizeof(":01:02")
148+ constexpr int TRAILING_CONV_LEN = 1 + 2 + 1 + 2 ; // sizeof(":01:02")
224149 IntFormatSection hour_conv;
225150 IntFormatSection min_conv;
226151 IntFormatSection sec_conv;
227152
228- {
229- FormatSection raw_hour_conv = to_conv;
230- raw_hour_conv.conv_name = ' H' ;
231-
232- const int requested_padding = to_conv.min_width - trailing_conv_len;
233- // a negative padding will be treated as the default
234- raw_hour_conv.min_width = requested_padding;
235-
236- hour_conv = get_int_format (raw_hour_conv, timeptr);
237-
238- // If the user set the padding, but it's below the width of the trailing
239- // conversions, then there should be no padding.
240- if (to_conv.min_width > 0 && requested_padding < 0 )
241- hour_conv.pad_to_len = 0 ;
242- }
243- {
244- FormatSection raw_min_conv = to_conv;
245- raw_min_conv.conv_name = ' M' ;
246- raw_min_conv.min_width = 0 ;
247-
248- min_conv = get_int_format (raw_min_conv, timeptr);
249- }
250- {
251- FormatSection raw_sec_conv = to_conv;
252- raw_sec_conv.conv_name = ' S' ;
253- raw_sec_conv.min_width = 0 ;
254-
255- sec_conv = get_int_format (raw_sec_conv, timeptr);
256- }
153+ hour_conv = get_specific_int_format (timeptr, to_conv, ' H' , TRAILING_CONV_LEN);
154+ min_conv = get_specific_int_format (timeptr, to_conv, ' M' );
155+ sec_conv = get_specific_int_format (timeptr, to_conv, ' S' );
257156
258157 RET_IF_RESULT_NEGATIVE (write_padded_int (writer, hour_conv));
259158 RET_IF_RESULT_NEGATIVE (writer->write (' :' ));
@@ -273,33 +172,22 @@ LIBC_INLINE int convert_full_date_time(printf_core::Writer *writer,
273172 // their valid ranges.
274173 // sizeof("Sun Jan 12 03:45:06 2025")
275174 const size_t full_conv_len = 3 + 1 + 3 + 1 + 2 + 1 + 8 + 1 + 4 ;
276- // use the full conv lent because
175+ // use the full conv len because this isn't being passed to a proper converter
176+ // that will handle the width of the leading conversion. Instead it has to be
177+ // handled below.
277178 const int requested_padding = to_conv.min_width - full_conv_len;
278179
279180 cpp::string_view wday_str = unwrap_opt (time_reader.get_weekday_short_name ());
280181 cpp::string_view month_str = unwrap_opt (time_reader.get_month_short_name ());
281182 IntFormatSection mday_conv;
282- FormatSection raw_time_conv = to_conv;
283183 IntFormatSection year_conv;
284184
285- {
286- FormatSection raw_mday_conv = to_conv;
287- raw_mday_conv.conv_name = ' e' ;
288- raw_mday_conv.min_width = 0 ;
289-
290- mday_conv = get_int_format (raw_mday_conv, timeptr);
291- }
292- {
293- FormatSection raw_year_conv = to_conv;
294- raw_year_conv.conv_name = ' Y' ;
295- raw_year_conv.min_width = 0 ;
185+ mday_conv = get_specific_int_format (timeptr, to_conv, ' e' );
186+ year_conv = get_specific_int_format (timeptr, to_conv, ' Y' );
296187
297- year_conv = get_int_format (raw_year_conv, timeptr);
298- }
299- {
300- raw_time_conv.conv_name = ' T' ;
301- raw_time_conv.min_width = 0 ;
302- }
188+ FormatSection raw_time_conv = to_conv;
189+ raw_time_conv.conv_name = ' T' ;
190+ raw_time_conv.min_width = 0 ;
303191
304192 if (requested_padding > 0 )
305193 RET_IF_RESULT_NEGATIVE (writer->write (' ' , requested_padding));
0 commit comments