-
Notifications
You must be signed in to change notification settings - Fork 110
[k2] add Date/Time classes to light runtime #1481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
d1df9ec to
244c045
Compare
49fc0f4 to
a96050c
Compare
apolyakov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed and noted some comments. Please, take into account that these comments should be applied to whole PR, not only the places where I left those comments
58b34bb to
eb0dc06
Compare
| std::expected<rel_time, error_container> parse_interval(std::string_view formatted_interval) noexcept { | ||
| timelib_time* b{nullptr}; | ||
| timelib_time* e{nullptr}; | ||
| kphp::memory::libc_alloc_guard _{}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not create it until it's actually used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved down
| kphp::memory::libc_alloc_guard _{}; | ||
| vk::final_action e_deleter{[e]() { free(e); }}; | ||
| vk::final_action b_deleter{[b]() { free(b); }}; | ||
| timelib_rel_time* p{nullptr}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see usage of your timelib types, e.g. kphp::timelib::rel_time here. It can be a test for their usability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the best place to test type wrappers. Wrapped types should be used with wrapped functions, not within wrapped functions. Here, we're using raw timelib functions, which require raw timelib types.
Of course, we could define our own pointer holder, which would provide access to the pointer by reference. But that seems as overkill to me. See the "kshamazov/datetime-structs" branch for an implementation example.
| return std::unexpected{error_container{errors, kphp::timelib::details::error_container_destructor}}; | ||
| } | ||
|
|
||
| time add_time_interval(const kphp::timelib::time& t, const kphp::timelib::rel_time& interval) noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to define everything in cpp file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
|
|
||
| } // namespace | ||
|
|
||
| time_offset construct_time_offset(const kphp::timelib::time& t) noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see fully qualified type here. I don't want to make C++ compiler's job, i.e. name lookup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
| now->tz_info = time->tz_info; | ||
| now->zone_type = TIMELIB_ZONETYPE_ID; | ||
|
|
||
| namespace chrono = std::chrono; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case it's not a problem, but let's not introduce bad pattern into runtime: do not mix objects that are designed to be allocated/deallocated in the context of libc_alloc_guard with objects that are not designed for that, e.g. every other object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand you. But I moved chrono objects up
| return std::make_pair(std::move(res), std::move(errors)); | ||
| } | ||
|
|
||
| void set_date(kphp::timelib::time& t, int64_t y, int64_t m, int64_t d) noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any reason to define such function in the header
| instance_timelib_zone_cache.put(tzinfo); | ||
| return tzinfo; | ||
| int errc{}; // it's intentionally declared as 'int' since timelib_parse_tzfile accepts 'int' | ||
| kphp::timelib::tzinfo tzinfo{timelib_parse_tzfile(name.data(), tzdb, std::addressof(errc)), kphp::timelib::details::tzinfo_destructor}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems you've missed libc_alloc_guard here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
| if (tzinfo == nullptr || tzinfo->name == nullptr) [[unlikely]] { | ||
| return; | ||
| } | ||
| put(std::move(tzinfo)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's refactor this a bit to make sure put is not called while libc_alloc_guard is active
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
89d240b to
92b7f45
Compare
|
|
||
| namespace kphp::timelib { | ||
|
|
||
| using static_buf = std::array<char, 128>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
|
|
||
| inline std::expected<std::pair<kphp::timelib::time_holder, kphp::timelib::error_container_holder>, kphp::timelib::error_container_holder> | ||
| parse_time(std::string_view formatted_time) noexcept { | ||
| timelib_error_container* errors{}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to make kphp::timelib::error_container_holder{nullptr, ...} constructed as soon as possible, e.g. before any branches to make memory leak here impossible. Same for other functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
| t->y = y; | ||
| t->m = 1; | ||
| t->d = 1; | ||
| std::memset(std::addressof(t->relative), 0, sizeof(t->relative)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing include for <cstring>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
| return std::unexpected{kphp::timelib::error_container_holder{errors, kphp::timelib::details::error_container_destructor}}; | ||
| } | ||
|
|
||
| kphp::timelib::rel_time_holder get_time_interval(const kphp::timelib::time_holder& time1, const kphp::timelib::time_holder& time2, bool absolute) noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this definition to header file as its small enough to be inlined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
| if (datetime.empty()) [[unlikely]] { | ||
| std::expected<std::pair<kphp::timelib::time_holder, kphp::timelib::error_container_holder>, kphp::timelib::error_container_holder> | ||
| parse_time(std::string_view formatted_time, const kphp::timelib::time_holder& t) noexcept { | ||
| auto expected{parse_time(formatted_time)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use fully qualified names. Otherwise, it's so simple to understand where the function goes from
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
| inline class_instance<C$DateTimeZone> f$DateTimeZone$$__construct(const class_instance<C$DateTimeZone>& self, const string& timezone) noexcept { | ||
| auto expected_tzi{kphp::timelib::get_timezone_info({timezone.c_str(), timezone.size()})}; | ||
| if (!expected_tzi.has_value()) [[unlikely]] { | ||
| static constexpr std::string_view before_timezone{"DateTimeZone::__construct(): Unknown or bad timezone ("}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use capital letters for static variables. Please, also check other files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
| } | ||
|
|
||
| inline string f$DateTimeZone$$getName(const class_instance<C$DateTimeZone>& self) noexcept { | ||
| return string{self->tzi->get()->name}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We can't create new
stringon everygetNameinvocation - We can't skip safety checks. In case you're 'almost sure' bad thing won't happen, add
kphp::log::assertion
| result.set_value(string{"weekday", 7}, string{weekday.data(), static_cast<string::size_type>(weekday.size())}); | ||
| result.set_value(string{"month", 5}, string{month.data(), static_cast<string::size_type>(month.size())}); | ||
| result.set_value(string{"weekday", 7}, string{weekday}); | ||
| result.set_value(string{"month", 5}, string{month}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: actually we can use std::strlen here as in modern compilers it's implemented as constexpr
| return date_time; | ||
| } | ||
|
|
||
| class_instance<C$DateTimeImmutable> f$DateTimeImmutable$$createFromMutable(const class_instance<C$DateTime>& object) noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this to the header file
| } | ||
| }; | ||
|
|
||
| inline class_instance<C$DateInterval> f$DateInterval$$__construct(const class_instance<C$DateInterval>& self, const string& duration) noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be moved to cpp file
This first part of implementing Date/Time classes. Here implemented: