libc: Move gmtime_r into common
gmtime_r() has been in the minimal libc for years, however it was not added to expcetions due to an overlook. In order to do this however, it has to be moved first to the common libc area, so that it's available to any libc that may not implement it. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
109a045e57
commit
0966be01fc
|
@ -5,6 +5,7 @@ zephyr_system_include_directories(include)
|
|||
zephyr_library()
|
||||
zephyr_library_property(ALLOW_EMPTY TRUE)
|
||||
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_ABORT source/stdlib/abort.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_GMTIME_R source/time/gmtime_r.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_TIME source/time/time.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_MALLOC source/stdlib/malloc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_STRNLEN source/string/strnlen.c)
|
||||
|
|
|
@ -6,6 +6,11 @@ config COMMON_LIBC_ABORT
|
|||
help
|
||||
common implementation of abort().
|
||||
|
||||
config COMMON_LIBC_GMTIME_R
|
||||
bool
|
||||
help
|
||||
common implementation of gmtime_r().
|
||||
|
||||
config COMMON_LIBC_TIME
|
||||
bool
|
||||
help
|
||||
|
|
97
lib/libc/common/source/time/gmtime_r.c
Normal file
97
lib/libc/common/source/time/gmtime_r.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* The time_civil_from_days function is derived directly from public
|
||||
* domain content written by Howard Hinnant and available at:
|
||||
* http://howardhinnant.github.io/date_algorithms.html#civil_from_days
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
/* A signed type with the representation of time_t without its
|
||||
* implications.
|
||||
*/
|
||||
typedef time_t bigint_type;
|
||||
|
||||
/** Convert a UNIX time to civil time.
|
||||
*
|
||||
* This converts integral seconds since (before) 1970-01-01T00:00:00
|
||||
* to the POSIX standard civil time representation. Any adjustments
|
||||
* due to time zone, leap seconds, or a different epoch must be
|
||||
* applied to @p time before invoking this function.
|
||||
*
|
||||
* @param time the time represented as seconds.
|
||||
*
|
||||
* @return the time information for corresponding to the provided
|
||||
* instant.
|
||||
*
|
||||
* @see http://howardhinnant.github.io/date_algorithms.html#civil_from_days
|
||||
*/
|
||||
static void time_civil_from_days(bigint_type z,
|
||||
struct tm *ZRESTRICT tp)
|
||||
{
|
||||
tp->tm_wday = (z >= -4) ? ((z + 4) % 7) : ((z + 5) % 7 + 6);
|
||||
z += 719468;
|
||||
|
||||
bigint_type era = ((z >= 0) ? z : (z - 146096)) / 146097;
|
||||
unsigned int doe = (z - era * (bigint_type)146097);
|
||||
unsigned int yoe = (doe - doe / 1460U + doe / 36524U - doe / 146096U)
|
||||
/ 365U;
|
||||
bigint_type y = (time_t)yoe + era * 400;
|
||||
unsigned int doy = doe - (365U * yoe + yoe / 4U - yoe / 100U);
|
||||
unsigned int mp = (5U * doy + 2U) / 153U;
|
||||
unsigned int d = doy - (153U * mp + 2U) / 5U + 1U;
|
||||
unsigned int m = mp + ((mp < 10) ? 3 : -9);
|
||||
|
||||
tp->tm_year = y + (m <= 2) - 1900;
|
||||
tp->tm_mon = m - 1;
|
||||
tp->tm_mday = d;
|
||||
|
||||
/* Everything above is explained on the referenced page, but
|
||||
* doy is relative to --03-01 and we need it relative to
|
||||
* --01-01.
|
||||
*
|
||||
* doy=306 corresponds to --01-01, doy=364 to --02-28, and
|
||||
* doy=365 to --02-29. So we can just subtract 306 to handle
|
||||
* January and February.
|
||||
*
|
||||
* For doy<306 we have to add the number of days before
|
||||
* --03-01, which is 59 in a common year and 60 in a leap
|
||||
* year. Note that the first year in the era is a leap year.
|
||||
*/
|
||||
if (doy >= 306U) {
|
||||
tp->tm_yday = doy - 306U;
|
||||
} else {
|
||||
tp->tm_yday = doy + 59U + (((yoe % 4U == 0U) && (yoe % 100U != 0U)) || (yoe == 0U));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a UNIX time to civil time.
|
||||
*
|
||||
* This converts integral seconds since (before) 1970-01-01T00:00:00
|
||||
* to the POSIX standard civil time representation. Any adjustments
|
||||
* due to time zone, leap seconds, or a different epoch must be
|
||||
* applied to @p time before invoking this function.
|
||||
*/
|
||||
struct tm *gmtime_r(const time_t *ZRESTRICT timep,
|
||||
struct tm *ZRESTRICT result)
|
||||
{
|
||||
time_t z = *timep;
|
||||
bigint_type days = (z >= 0 ? z : z - 86399) / 86400;
|
||||
unsigned int rem = z - days * 86400;
|
||||
|
||||
*result = (struct tm){ 0 };
|
||||
|
||||
time_civil_from_days(days, result);
|
||||
|
||||
result->tm_hour = rem / 60U / 60U;
|
||||
rem -= result->tm_hour * 60 * 60;
|
||||
result->tm_min = rem / 60;
|
||||
result->tm_sec = rem - result->tm_min * 60;
|
||||
|
||||
return result;
|
||||
}
|
|
@ -79,6 +79,7 @@ config MINIMAL_LIBC_RAND
|
|||
config MINIMAL_LIBC_TIME
|
||||
bool "Time functions"
|
||||
select COMMON_LIBC_TIME if POSIX_CLOCK
|
||||
select COMMON_LIBC_GMTIME_R
|
||||
default y
|
||||
help
|
||||
Enable time() and gmtime_r() for the minimal libc.
|
||||
|
|
|
@ -4,99 +4,9 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* The time_civil_from_days function is derived directly from public
|
||||
* domain content written by Howard Hinnant and available at:
|
||||
* http://howardhinnant.github.io/date_algorithms.html#civil_from_days
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <zephyr/sys/libc-hooks.h>
|
||||
|
||||
/* A signed type with the representation of time_t without its
|
||||
* implications.
|
||||
*/
|
||||
typedef time_t bigint_type;
|
||||
|
||||
/** Convert a UNIX time to civil time.
|
||||
*
|
||||
* This converts integral seconds since (before) 1970-01-01T00:00:00
|
||||
* to the POSIX standard civil time representation. Any adjustments
|
||||
* due to time zone, leap seconds, or a different epoch must be
|
||||
* applied to @p time before invoking this function.
|
||||
*
|
||||
* @param time the time represented as seconds.
|
||||
*
|
||||
* @return the time information for corresponding to the provided
|
||||
* instant.
|
||||
*
|
||||
* @see http://howardhinnant.github.io/date_algorithms.html#civil_from_days
|
||||
*/
|
||||
static void time_civil_from_days(bigint_type z,
|
||||
struct tm *ZRESTRICT tp)
|
||||
{
|
||||
tp->tm_wday = (z >= -4) ? ((z + 4) % 7) : ((z + 5) % 7 + 6);
|
||||
z += 719468;
|
||||
|
||||
bigint_type era = ((z >= 0) ? z : (z - 146096)) / 146097;
|
||||
unsigned int doe = (z - era * (bigint_type)146097);
|
||||
unsigned int yoe = (doe - doe / 1460U + doe / 36524U - doe / 146096U)
|
||||
/ 365U;
|
||||
bigint_type y = (time_t)yoe + era * 400;
|
||||
unsigned int doy = doe - (365U * yoe + yoe / 4U - yoe / 100U);
|
||||
unsigned int mp = (5U * doy + 2U) / 153U;
|
||||
unsigned int d = doy - (153U * mp + 2U) / 5U + 1U;
|
||||
unsigned int m = mp + ((mp < 10) ? 3 : -9);
|
||||
|
||||
tp->tm_year = y + (m <= 2) - 1900;
|
||||
tp->tm_mon = m - 1;
|
||||
tp->tm_mday = d;
|
||||
|
||||
/* Everything above is explained on the referenced page, but
|
||||
* doy is relative to --03-01 and we need it relative to
|
||||
* --01-01.
|
||||
*
|
||||
* doy=306 corresponds to --01-01, doy=364 to --02-28, and
|
||||
* doy=365 to --02-29. So we can just subtract 306 to handle
|
||||
* January and February.
|
||||
*
|
||||
* For doy<306 we have to add the number of days before
|
||||
* --03-01, which is 59 in a common year and 60 in a leap
|
||||
* year. Note that the first year in the era is a leap year.
|
||||
*/
|
||||
if (doy >= 306U) {
|
||||
tp->tm_yday = doy - 306U;
|
||||
} else {
|
||||
tp->tm_yday = doy + 59U + (((yoe % 4U == 0U) && (yoe % 100U != 0U)) || (yoe == 0U));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a UNIX time to civil time.
|
||||
*
|
||||
* This converts integral seconds since (before) 1970-01-01T00:00:00
|
||||
* to the POSIX standard civil time representation. Any adjustments
|
||||
* due to time zone, leap seconds, or a different epoch must be
|
||||
* applied to @p time before invoking this function.
|
||||
*/
|
||||
struct tm *gmtime_r(const time_t *ZRESTRICT timep,
|
||||
struct tm *ZRESTRICT result)
|
||||
{
|
||||
time_t z = *timep;
|
||||
bigint_type days = (z >= 0 ? z : z - 86399) / 86400;
|
||||
unsigned int rem = z - days * 86400;
|
||||
|
||||
*result = (struct tm){ 0 };
|
||||
|
||||
time_civil_from_days(days, result);
|
||||
|
||||
result->tm_hour = rem / 60U / 60U;
|
||||
rem -= result->tm_hour * 60 * 60;
|
||||
result->tm_min = rem / 60;
|
||||
result->tm_sec = rem - result->tm_min * 60;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS
|
||||
static Z_LIBC_DATA struct tm gmtime_result;
|
||||
|
||||
|
|
Loading…
Reference in a new issue