Skip to content

Commit f074836

Browse files
clean up compoisite conversions and address comments
1 parent 60e6280 commit f074836

File tree

14 files changed

+73
-195
lines changed

14 files changed

+73
-195
lines changed

libc/include/time.yaml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,6 @@ functions:
100100
- type: size_t
101101
- type: const char *__restrict
102102
- type: const struct tm *__restrict
103-
- name: strftime_l
104-
standard:
105-
- stdc
106-
return_type: size_t
107-
arguments:
108-
- type: char *__restrict
109-
- type: size_t
110-
- type: const char *__restrict
111-
- type: const struct tm *__restrict
112-
- type: locale_t
113103
- name: time
114104
standard:
115105
- stdc

libc/src/time/strftime.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
1818

1919
LLVM_LIBC_FUNCTION(size_t, strftime,
2020
(char *__restrict buffer, size_t buffsz,
21-
const char *__restrict format, const struct tm *timeptr)) {
21+
const char *__restrict format, const tm *timeptr)) {
2222

2323
printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
2424
printf_core::Writer writer(&wb);

libc/src/time/strftime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
namespace LIBC_NAMESPACE_DECL {
1717

1818
size_t strftime(char *__restrict, size_t max, const char *__restrict format,
19-
const struct tm *timeptr);
19+
const tm *timeptr);
2020

2121
} // namespace LIBC_NAMESPACE_DECL
2222

libc/src/time/strftime_core/composite_converter.h

Lines changed: 49 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
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"
@@ -21,46 +22,40 @@
2122
namespace LIBC_NAMESPACE_DECL {
2223
namespace 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+
2445
LIBC_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));

libc/src/time/strftime_core/converter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "hdr/types/struct_tm.h"
910
#include "src/__support/macros/config.h"
1011
#include "src/stdio/printf_core/writer.h"
1112
#include "src/time/strftime_core/core_structs.h"

libc/src/time/strftime_core/converter.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
#ifndef LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_CONVERTER_H
1010
#define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_CONVERTER_H
1111

12+
#include "hdr/types/struct_tm.h"
1213
#include "src/stdio/printf_core/writer.h"
1314
#include "src/time/strftime_core/core_structs.h"
1415

15-
#include <stddef.h>
16-
1716
namespace LIBC_NAMESPACE_DECL {
1817
namespace strftime_core {
1918

libc/src/time/strftime_core/core_structs.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "hdr/types/struct_tm.h"
1313
#include "src/__support/CPP/string_view.h"
1414

15-
#include <inttypes.h>
15+
#include <stdint.h>
1616

1717
namespace LIBC_NAMESPACE_DECL {
1818
namespace strftime_core {
@@ -28,12 +28,12 @@ enum FormatFlags : uint8_t {
2828
};
2929

3030
struct FormatSection {
31-
bool has_conv;
32-
cpp::string_view raw_string;
31+
bool has_conv = false;
32+
cpp::string_view raw_string = {};
3333

3434
FormatFlags flags = FormatFlags(0);
35-
ConvModifier modifier;
36-
char conv_name;
35+
ConvModifier modifier = ConvModifier::none;
36+
char conv_name = '\0';
3737
int min_width = 0;
3838
};
3939

libc/src/time/strftime_core/num_converter.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_NUM_CONVERTER_H
1010
#define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_NUM_CONVERTER_H
1111

12+
#include "hdr/types/struct_tm.h"
1213
#include "src/__support/CPP/string_view.h"
1314
#include "src/__support/integer_to_string.h"
1415
#include "src/__support/macros/config.h"
@@ -23,9 +24,9 @@ namespace strftime_core {
2324
using DecFmt = IntegerToString<uintmax_t>;
2425

2526
struct IntFormatSection {
26-
uintmax_t num;
27-
char sign_char;
28-
size_t pad_to_len;
27+
uintmax_t num = 0;
28+
char sign_char = '\0';
29+
size_t pad_to_len = 0;
2930
char padding_char = '0';
3031
};
3132

0 commit comments

Comments
 (0)