11#include " runtime/datetime/timelib_wrapper.h"
22
3+ #include < string_view>
4+
35#include " kphp/timelib/timelib.h"
46#include " runtime-common/stdlib/time/timelib-functions.h"
57#if ASAN_ENABLED
@@ -39,28 +41,36 @@ void set_time_value(array<mixed>& dst, const char* name, int64_t value) {
3941}
4042
4143array<mixed> dump_errors (const timelib_error_container& error) {
44+ static constexpr std::string_view WARNING_COUNT{" warning_count" };
45+ static constexpr std::string_view WARNINGS{" warnings" };
46+ static constexpr std::string_view ERROR_COUNT{" error_count" };
47+ static constexpr std::string_view ERRORS{" errors" };
48+
4249 array<mixed> result;
4350
4451 array<string> result_warnings;
4552 result_warnings.reserve (error.warning_count , false );
4653 for (int i = 0 ; i < error.warning_count ; i++) {
4754 result_warnings.set_value (error.warning_messages [i].position , string (error.warning_messages [i].message ));
4855 }
49- result.set_value (string (" warning_count " ), error.warning_count );
50- result.set_value (string (" warnings " ), result_warnings);
56+ result.set_value (string (WARNING_COUNT. data (), WARNING_COUNT. size () ), error.warning_count );
57+ result.set_value (string (WARNINGS. data (), WARNINGS. size () ), result_warnings);
5158
5259 array<string> result_errors;
5360 result_errors.reserve (error.error_count , false );
5461 for (int i = 0 ; i < error.error_count ; i++) {
5562 result_errors.set_value (error.error_messages [i].position , string (error.error_messages [i].message ));
5663 }
57- result.set_value (string (" error_count " ), error.error_count );
58- result.set_value (string (" errors " ), result_errors);
64+ result.set_value (string (ERROR_COUNT. data (), ERROR_COUNT. size () ), error.error_count );
65+ result.set_value (string (ERRORS. data (), ERRORS. size () ), result_errors);
5966
6067 return result;
6168}
6269
6370array<mixed> create_date_parse_array (timelib_time* t, timelib_error_container* error) {
71+ static constexpr std::string_view FRACTION{" fraction" };
72+ static constexpr std::string_view IS_LOCALTIME{" is_localtime" };
73+
6474 array<mixed> result;
6575
6676 // note: we're setting the result array keys in the same order as PHP does
@@ -73,56 +83,72 @@ array<mixed> create_date_parse_array(timelib_time* t, timelib_error_container* e
7383 set_time_value (result, " second" , t->s );
7484
7585 if (t->us == TIMELIB_UNSET) {
76- result.set_value (string (" fraction " ), false );
86+ result.set_value (string (FRACTION. data (), FRACTION. size () ), false );
7787 } else {
78- result.set_value (string (" fraction " ), static_cast <double >(t->us ) / 1000000.0 );
88+ result.set_value (string (FRACTION. data (), FRACTION. size () ), static_cast <double >(t->us ) / 1000000.0 );
7989 }
8090
8191 result.merge_with (dump_errors (*error));
8292
83- result.set_value (string (" is_localtime " ), static_cast <bool >(t->is_localtime ));
93+ result.set_value (string (IS_LOCALTIME. data (), IS_LOCALTIME. size () ), static_cast <bool >(t->is_localtime ));
8494
8595 if (t->is_localtime ) {
96+ static constexpr std::string_view IS_DST{" is_dst" };
97+ static constexpr std::string_view TZ_ABBR{" tz_abbr" };
98+ static constexpr std::string_view TZ_ID{" tz_id" };
99+
86100 set_time_value (result, " zone_type" , t->zone_type );
87101 switch (t->zone_type ) {
88102 case TIMELIB_ZONETYPE_OFFSET:
89103 set_time_value (result, " zone" , t->z );
90- result.set_value (string (" is_dst " ), static_cast <bool >(t->dst ));
104+ result.set_value (string (IS_DST. data (), IS_DST. size () ), static_cast <bool >(t->dst ));
91105 break ;
92106 case TIMELIB_ZONETYPE_ID:
93107 if (t->tz_abbr ) {
94- result.set_value (string (" tz_abbr " ), string (t->tz_abbr ));
108+ result.set_value (string (TZ_ABBR. data (), TZ_ABBR. size () ), string (t->tz_abbr ));
95109 }
96110 if (t->tz_info ) {
97- result.set_value (string (" tz_id " ), string (t->tz_info ->name ));
111+ result.set_value (string (TZ_ID. data (), TZ_ID. size () ), string (t->tz_info ->name ));
98112 }
99113 break ;
100114 case TIMELIB_ZONETYPE_ABBR:
101115 set_time_value (result, " zone" , t->z );
102- result.set_value (string (" is_dst " ), static_cast <bool >(t->dst ));
103- result.set_value (string (" tz_abbr " ), string (t->tz_abbr ));
116+ result.set_value (string (IS_DST. data (), IS_DST. size () ), static_cast <bool >(t->dst ));
117+ result.set_value (string (TZ_ABBR. data (), TZ_ABBR. size () ), string (t->tz_abbr ));
104118 break ;
105119 }
106120 }
107121 if (t->have_relative ) {
122+ static constexpr std::string_view YEAR{" year" };
123+ static constexpr std::string_view MONTH{" month" };
124+ static constexpr std::string_view DAY{" day" };
125+ static constexpr std::string_view HOUR{" hour" };
126+ static constexpr std::string_view MINUTE{" minute" };
127+ static constexpr std::string_view SECOND{" second" };
128+ static constexpr std::string_view RELATIVE{" relative" };
129+
108130 array<mixed> relative;
109- relative.set_value (string (" year " ), t->relative .y );
110- relative.set_value (string (" month " ), t->relative .m );
111- relative.set_value (string (" day " ), t->relative .d );
112- relative.set_value (string (" hour " ), t->relative .h );
113- relative.set_value (string (" minute " ), t->relative .i );
114- relative.set_value (string (" second " ), t->relative .s );
131+ relative.set_value (string (YEAR. data (), YEAR. size () ), t->relative .y );
132+ relative.set_value (string (MONTH. data (), MONTH. size () ), t->relative .m );
133+ relative.set_value (string (DAY. data (), DAY. size () ), t->relative .d );
134+ relative.set_value (string (HOUR. data (), HOUR. size () ), t->relative .h );
135+ relative.set_value (string (MINUTE. data (), MINUTE. size () ), t->relative .i );
136+ relative.set_value (string (SECOND. data (), SECOND. size () ), t->relative .s );
115137 if (t->relative .have_weekday_relative ) {
116- relative.set_value (string (" weekday" ), t->relative .weekday );
138+ static constexpr std::string_view WEEKDAY{" weekday" };
139+
140+ relative.set_value (string (WEEKDAY.data (), WEEKDAY.size ()), t->relative .weekday );
117141 }
118142 if (t->relative .have_special_relative && (t->relative .special .type == TIMELIB_SPECIAL_WEEKDAY)) {
119- relative.set_value (string (" weekdays" ), t->relative .special .amount );
143+ static constexpr std::string_view WEEKDAYS{" weekdays" };
144+
145+ relative.set_value (string (WEEKDAYS.data (), WEEKDAYS.size ()), t->relative .special .amount );
120146 }
121147 if (t->relative .first_last_day_of ) {
122148 string key = string (t->relative .first_last_day_of == TIMELIB_SPECIAL_FIRST_DAY_OF_MONTH ? " first_day_of_month" : " last_day_of_month" );
123149 relative.set_value (key, true );
124150 }
125- result.set_value (string (" relative " ), relative);
151+ result.set_value (string (RELATIVE. data (), RELATIVE. size () ), relative);
126152 }
127153
128154 return result;
@@ -272,9 +298,14 @@ std::pair<timelib_time*, string> php_timelib_date_initialize(const string& tz_na
272298 update_errors_warnings (err, script_guard);
273299
274300 if (err && err->error_count ) {
275- // spit out the first library error message, at least
276301 timelib_time_dtor (t);
277- return {nullptr , string{" Failed to parse time string " }.append (1 , ' (' ).append (time_str).append (" ) " ).append (kphp::timelib::gen_error_msg (err))};
302+
303+ // spit out the first library error message, at least
304+ static constexpr std::string_view MESSAGE_PREFIX{" Failed to parse time string " };
305+
306+ string err_msg{MESSAGE_PREFIX.data (), MESSAGE_PREFIX.size ()};
307+ err_msg.reserve_at_least (MESSAGE_PREFIX.size () + 1 + time_str.size () + 2 );
308+ return {nullptr , err_msg.append (1 , ' (' ).append (time_str).append (' )' ).append (' ' ).append (kphp::timelib::gen_error_msg (err))};
278309 }
279310
280311 timelib_tzinfo* tzi = nullptr ;
@@ -365,7 +396,11 @@ std::pair<bool, string> php_timelib_date_modify(timelib_time* t, const string& m
365396
366397 if (err && err->error_count ) {
367398 // spit out the first library error message, at least
368- return {false , string{" Failed to parse time string " }.append (1 , ' (' ).append (modifier).append (" ) " ).append (kphp::timelib::gen_error_msg (err))};
399+ static constexpr std::string_view MESSAGE_PREFIX{" Failed to parse time string " };
400+
401+ string err_msg{MESSAGE_PREFIX.data (), MESSAGE_PREFIX.size ()};
402+ err_msg.reserve_at_least (MESSAGE_PREFIX.size () + 1 + modifier.size () + 2 );
403+ return {false , err_msg.append (1 , ' (' ).append (modifier).append (' )' ).append (' ' ).append (kphp::timelib::gen_error_msg (err))};
369404 }
370405
371406 std::memcpy (&t->relative , &tmp_time->relative , sizeof (timelib_rel_time));
@@ -508,7 +543,12 @@ std::pair<timelib_rel_time*, string> php_timelib_date_interval_initialize(const
508543 if (p) {
509544 timelib_rel_time_dtor (p);
510545 }
511- return {nullptr , string{" Unknown or bad format (" }.append (format).append (1 , ' )' )};
546+
547+ static constexpr std::string_view MESSAGE_PREFIX{" Unknown or bad format (" };
548+
549+ string err_msg{MESSAGE_PREFIX.data (), MESSAGE_PREFIX.size ()};
550+ err_msg.reserve_at_least (MESSAGE_PREFIX.size () + format.size () + 1 );
551+ return {nullptr , err_msg.append (format).append (1 , ' )' )};
512552 }
513553
514554 if (p) {
@@ -521,7 +561,12 @@ std::pair<timelib_rel_time*, string> php_timelib_date_interval_initialize(const
521561 return {timelib_diff (b, e), {}};
522562 }
523563
524- return {nullptr , string{" Failed to parse interval (" }.append (format).append (1 , ' )' )};
564+ static constexpr std::string_view MESSAGE_PREFIX{" Failed to parse interval (" };
565+
566+ string err_msg{MESSAGE_PREFIX.data (), MESSAGE_PREFIX.size ()};
567+ err_msg.reserve_at_least (MESSAGE_PREFIX.size () + format.size () + 1 );
568+
569+ return {nullptr , err_msg.append (format).append (1 , ' )' )};
525570}
526571
527572void php_timelib_date_interval_remove (timelib_rel_time* t) {
@@ -540,10 +585,11 @@ std::pair<timelib_rel_time*, string> php_timelib_date_interval_create_from_date_
540585 vk::final_action error_deleter{[err]() { timelib_error_container_dtor (err); }};
541586
542587 if (err->error_count > 0 ) {
543- string error_msg{" Unknown or bad format (" };
544- error_msg.append (time_str).append (1 , ' )' ).append (" at position " ).append (err->error_messages [0 ].position );
545- error_msg.append (" (" ).append (1 , err->error_messages [0 ].character ? err->error_messages [0 ].character : ' ' ).append (" ): " );
546- error_msg.append (err->error_messages [0 ].message );
588+ static constexpr std::string_view MESSAGE_PREFIX{" Unknown or bad format (" };
589+
590+ string error_msg{MESSAGE_PREFIX.data (), MESSAGE_PREFIX.size ()};
591+ error_msg.reserve_at_least (MESSAGE_PREFIX.size () + time_str.size () + 2 );
592+ error_msg.append (time_str).append (1 , ' )' ).append (1 , ' ' ).append (kphp::timelib::gen_error_msg (err));
547593 return {nullptr , std::move (error_msg)};
548594 }
549595 return {timelib_rel_time_clone (&time->relative ), {}};
0 commit comments