forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc][c11] implement ctime (llvm#86567)
- Loading branch information
Showing
5 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//===-- Implementation of asctime function --------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "src/time/ctime.h" | ||
#include "src/__support/common.h" | ||
#include "src/__support/macros/config.h" | ||
#include "src/time/time_utils.h" | ||
|
||
namespace LIBC_NAMESPACE_DECL { | ||
|
||
using LIBC_NAMESPACE::time_utils::TimeConstants; | ||
|
||
LLVM_LIBC_FUNCTION(char *, ctime, (const struct tm *timeptr)) { | ||
static char buffer[TimeConstants::CTIME_BUFFER_SIZE]; | ||
return time_utils::ctime(timeptr, buffer, TimeConstants::CTIME_MAX_BYTES); | ||
} | ||
|
||
} // namespace LIBC_NAMESPACE_DECL |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//===-- Implementation header of ctime ------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_LIBC_SRC_TIME_CTIME_H | ||
#define LLVM_LIBC_SRC_TIME_CTIME_H | ||
|
||
#include "src/__support/macros/config.h" | ||
#include <time.h> | ||
|
||
namespace LIBC_NAMESPACE_DECL { | ||
|
||
char *ctime(const struct tm *timeptr); | ||
|
||
} // namespace LIBC_NAMESPACE_DECL | ||
|
||
#endif // LLVM_LIBC_SRC_TIME_CTIME_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
//===-- Unittests for ctime ---------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// make check-libc LIBC_TEST_TARGET=call_ctime VERBOSE=1 | ||
#include "src/errno/libc_errno.h" | ||
#include "src/time/ctime.h" | ||
#include "test/UnitTest/Test.h" | ||
#include "test/src/time/TmHelper.h" | ||
|
||
static inline char *call_ctime(struct tm *tm_data, int year, int month, | ||
int mday, int hour, int min, int sec, int wday, | ||
int yday) { | ||
LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data( | ||
tm_data, year, month, mday, hour, min, sec, wday, yday); | ||
return LIBC_NAMESPACE::ctime(tm_data); | ||
} | ||
|
||
TEST(LlvmLibcCtime, Nullptr) { | ||
char *result; | ||
result = LIBC_NAMESPACE::ctime(nullptr); | ||
ASSERT_ERRNO_EQ(EINVAL); | ||
ASSERT_STREQ(nullptr, result); | ||
} | ||
|
||
// Weekdays are in the range 0 to 6. Test passing invalid value in wday. | ||
TEST(LlvmLibcCtime, InvalidWday) { | ||
struct tm tm_data; | ||
|
||
// Test with wday = -1. | ||
call_ctime(&tm_data, | ||
1970, // year | ||
1, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
-1, // wday | ||
0); // yday | ||
ASSERT_ERRNO_EQ(EINVAL); | ||
|
||
// Test with wday = 7. | ||
call_ctime(&tm_data, | ||
1970, // year | ||
1, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
7, // wday | ||
0); // yday | ||
ASSERT_ERRNO_EQ(EINVAL); | ||
} | ||
|
||
// Months are from January to December. Test passing invalid value in month. | ||
TEST(LlvmLibcCtime, InvalidMonth) { | ||
struct tm tm_data; | ||
|
||
// Test with month = 0. | ||
call_ctime(&tm_data, | ||
1970, // year | ||
0, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
4, // wday | ||
0); // yday | ||
ASSERT_ERRNO_EQ(EINVAL); | ||
|
||
// Test with month = 13. | ||
call_ctime(&tm_data, | ||
1970, // year | ||
13, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
4, // wday | ||
0); // yday | ||
ASSERT_ERRNO_EQ(EINVAL); | ||
} | ||
|
||
TEST(LlvmLibcCtime, ValidWeekdays) { | ||
struct tm tm_data; | ||
char *result; | ||
// 1970-01-01 00:00:00. | ||
result = call_ctime(&tm_data, | ||
1970, // year | ||
1, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
4, // wday | ||
0); // yday | ||
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result); | ||
|
||
// 1970-01-03 00:00:00. | ||
result = call_ctime(&tm_data, | ||
1970, // year | ||
1, // month | ||
3, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
6, // wday | ||
0); // yday | ||
ASSERT_STREQ("Sat Jan 3 00:00:00 1970\n", result); | ||
|
||
// 1970-01-04 00:00:00. | ||
result = call_ctime(&tm_data, | ||
1970, // year | ||
1, // month | ||
4, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
0, // wday | ||
0); // yday | ||
ASSERT_STREQ("Sun Jan 4 00:00:00 1970\n", result); | ||
} | ||
|
||
TEST(LlvmLibcCtime, ValidMonths) { | ||
struct tm tm_data; | ||
char *result; | ||
// 1970-01-01 00:00:00. | ||
result = call_ctime(&tm_data, | ||
1970, // year | ||
1, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
4, // wday | ||
0); // yday | ||
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result); | ||
|
||
// 1970-02-01 00:00:00. | ||
result = call_ctime(&tm_data, | ||
1970, // year | ||
2, // month | ||
1, // day | ||
0, // hr | ||
0, // min | ||
0, // sec | ||
0, // wday | ||
0); // yday | ||
ASSERT_STREQ("Sun Feb 1 00:00:00 1970\n", result); | ||
|
||
// 1970-12-31 23:59:59. | ||
result = call_ctime(&tm_data, | ||
1970, // year | ||
12, // month | ||
31, // day | ||
23, // hr | ||
59, // min | ||
59, // sec | ||
4, // wday | ||
0); // yday | ||
ASSERT_STREQ("Thu Dec 31 23:59:59 1970\n", result); | ||
} | ||
|
||
TEST(LlvmLibcCtime, EndOf32BitEpochYear) { | ||
struct tm tm_data; | ||
char *result; | ||
// Test for maximum value of a signed 32-bit integer. | ||
// Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC. | ||
result = call_ctime(&tm_data, | ||
2038, // year | ||
1, // month | ||
19, // day | ||
3, // hr | ||
14, // min | ||
7, // sec | ||
2, // wday | ||
7); // yday | ||
ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result); | ||
} | ||
|
||
TEST(LlvmLibcCtime, Max64BitYear) { | ||
if (sizeof(time_t) == 4) | ||
return; | ||
// Mon Jan 1 12:50:50 2170 (200 years from 1970), | ||
struct tm tm_data; | ||
char *result; | ||
result = call_ctime(&tm_data, | ||
2170, // year | ||
1, // month | ||
1, // day | ||
12, // hr | ||
50, // min | ||
50, // sec | ||
1, // wday | ||
50); // yday | ||
ASSERT_STREQ("Mon Jan 1 12:50:50 2170\n", result); | ||
|
||
// Test for Tue Jan 1 12:50:50 in 2,147,483,647th year. | ||
// This test would cause buffer overflow and thus asctime returns nullptr. | ||
result = call_ctime(&tm_data, | ||
2147483647, // year | ||
1, // month | ||
1, // day | ||
12, // hr | ||
50, // min | ||
50, // sec | ||
2, // wday | ||
50); // yday | ||
ASSERT_ERRNO_EQ(EOVERFLOW); | ||
ASSERT_STREQ(nullptr, result); | ||
} |