#ifndef LLVM_LIBC_SRC_TIME_TIME_UTILS_H
#define LLVM_LIBC_SRC_TIME_TIME_UTILS_H
#include <stddef.h>
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/errno/libc_errno.h"
#include "src/time/mktime.h"
#include <stdint.h>
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
enum Month : int {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER
};
struct TimeConstants {
static constexpr int SECONDS_PER_MIN = 60;
static constexpr int MINUTES_PER_HOUR = 60;
static constexpr int HOURS_PER_DAY = 24;
static constexpr int DAYS_PER_WEEK = 7;
static constexpr int MONTHS_PER_YEAR = 12;
static constexpr int DAYS_PER_NON_LEAP_YEAR = 365;
static constexpr int DAYS_PER_LEAP_YEAR = 366;
static constexpr int SECONDS_PER_HOUR = SECONDS_PER_MIN * MINUTES_PER_HOUR;
static constexpr int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
static constexpr int NUMBER_OF_SECONDS_IN_LEAP_YEAR =
DAYS_PER_LEAP_YEAR * SECONDS_PER_DAY;
static constexpr int TIME_YEAR_BASE = 1900;
static constexpr int EPOCH_YEAR = 1970;
static constexpr int EPOCH_WEEK_DAY = 4;
static constexpr int ASCTIME_BUFFER_SIZE = 256;
static constexpr int ASCTIME_MAX_BYTES = 26;
static constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST =
(946684800LL + SECONDS_PER_DAY * (31 + 29));
static constexpr int WEEK_DAY_OF2000_MARCH_FIRST = 3;
static constexpr int DAYS_PER400_YEARS =
(DAYS_PER_NON_LEAP_YEAR * 400) + (400 / 4) - 3;
static constexpr int DAYS_PER100_YEARS =
(DAYS_PER_NON_LEAP_YEAR * 100) + (100 / 4) - 1;
static constexpr int DAYS_PER4_YEARS = (DAYS_PER_NON_LEAP_YEAR * 4) + 1;
static constexpr int END_OF32_BIT_EPOCH_YEAR = 2038;
static constexpr time_t OUT_OF_RANGE_RETURN_VALUE = -1;
};
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
LIBC_INLINE time_t out_of_range() {
libc_errno = EOVERFLOW;
return TimeConstants::OUT_OF_RANGE_RETURN_VALUE;
}
LIBC_INLINE void invalid_value() { libc_errno = EINVAL; }
LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
size_t bufferLength) {
if (timeptr == nullptr || buffer == nullptr) {
invalid_value();
return nullptr;
}
if (timeptr->tm_wday < 0 ||
timeptr->tm_wday > (TimeConstants::DAYS_PER_WEEK - 1)) {
invalid_value();
return nullptr;
}
if (timeptr->tm_mon < 0 ||
timeptr->tm_mon > (TimeConstants::MONTHS_PER_YEAR - 1)) {
invalid_value();
return nullptr;
}
static const char *week_days_name[TimeConstants::DAYS_PER_WEEK] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static const char *months_name[TimeConstants::MONTHS_PER_YEAR] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int written_size = __builtin_snprintf(
buffer, bufferLength, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
if (written_size < 0)
return nullptr;
if (static_cast<size_t>(written_size) >= bufferLength) {
out_of_range();
return nullptr;
}
return buffer;
}
LIBC_INLINE struct tm *gmtime_internal(const time_t *timer, struct tm *result) {
int64_t seconds = *timer;
if (update_from_seconds(seconds, result) < 0) {
out_of_range();
return nullptr;
}
return result;
}
}
}
#endif