[libc-commits] [libc] [libc] Add strftime_l (PR #127767)

Petr Hosek via libc-commits libc-commits at lists.llvm.org
Thu Feb 20 18:33:43 PST 2025


https://github.com/petrhosek updated https://github.com/llvm/llvm-project/pull/127767

>From 6d9a58bd2835726c0b4304cc1030e8fc196de65c Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 13 Feb 2025 11:04:34 -0800
Subject: [PATCH 1/2] [libc] Add strftime_l

This is a (no-op) locale version of strftime.
---
 libc/config/baremetal/aarch64/entrypoints.txt |  2 ++
 libc/config/baremetal/arm/entrypoints.txt     |  2 ++
 libc/config/baremetal/riscv/entrypoints.txt   |  2 ++
 libc/config/linux/x86_64/entrypoints.txt      |  1 +
 libc/include/time.yaml                        | 11 +++++++
 libc/src/time/CMakeLists.txt                  | 14 ++++++++
 libc/src/time/strftime.cpp                    |  1 -
 libc/src/time/strftime_l.cpp                  | 33 +++++++++++++++++++
 libc/src/time/strftime_l.h                    | 25 ++++++++++++++
 9 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 libc/src/time/strftime_l.cpp
 create mode 100644 libc/src/time/strftime_l.h

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 44c4ab49e5c58..2c226ef176c08 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -248,6 +248,8 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.time.gmtime
     libc.src.time.gmtime_r
     libc.src.time.mktime
+    libc.src.time.strftime
+    libc.src.time.strftime_l
     libc.src.time.timespec_get
 
     # internal entrypoints
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 370b5462fe9e8..6fd1fce3ab245 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -248,6 +248,8 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.time.gmtime
     libc.src.time.gmtime_r
     libc.src.time.mktime
+    libc.src.time.strftime
+    libc.src.time.strftime_l
     libc.src.time.timespec_get
 
     # internal entrypoints
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 07311a60a17a2..5985c495bdaf2 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -244,6 +244,8 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.time.gmtime
     libc.src.time.gmtime_r
     libc.src.time.mktime
+    libc.src.time.strftime
+    libc.src.time.strftime_l
     libc.src.time.timespec_get
 
     # internal entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a4f6671a59789..2e3af00ec303d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1128,6 +1128,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.mktime
     libc.src.time.nanosleep
     libc.src.time.strftime
+    libc.src.time.strftime_l
     libc.src.time.time
     libc.src.time.timespec_get
 
diff --git a/libc/include/time.yaml b/libc/include/time.yaml
index 37ee824678cda..7bb25dbe85ac4 100644
--- a/libc/include/time.yaml
+++ b/libc/include/time.yaml
@@ -9,6 +9,7 @@ types:
   - type_name: time_t
   - type_name: clock_t
   - type_name: size_t
+  - type_name: locale_t
 enums: []
 objects: []
 functions:
@@ -100,6 +101,16 @@ functions:
       - type: size_t
       - type: const char *__restrict
       - type: const struct tm *__restrict
+  - name: strftime_l
+    standard:
+      - stdc
+    return_type: size_t
+    arguments:
+      - type: char *__restrict
+      - type: size_t
+      - type: const char *__restrict
+      - type: const struct tm *__restrict
+      - type: locale_t
   - name: time
     standard:
       - stdc
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 8332e8ab66f97..3b951df810011 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -150,6 +150,20 @@ add_entrypoint_object(
     libc.src.time.strftime_core.strftime_main
 )
 
+add_entrypoint_object(
+  strftime_l
+  SRCS
+    strftime_l.cpp
+  HDRS
+    strftime_l.h
+  DEPENDS
+    libc.hdr.types.locale_t
+    libc.hdr.types.size_t
+    libc.hdr.types.struct_tm
+    libc.src.stdio.printf_core.writer
+    libc.src.time.strftime_core.strftime_main
+)
+
 add_entrypoint_object(
   time
   SRCS
diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp
index 4b89bf2ea3a70..c19e58fbadf71 100644
--- a/libc/src/time/strftime.cpp
+++ b/libc/src/time/strftime.cpp
@@ -19,7 +19,6 @@ namespace LIBC_NAMESPACE_DECL {
 LLVM_LIBC_FUNCTION(size_t, strftime,
                    (char *__restrict buffer, size_t buffsz,
                     const char *__restrict format, const tm *timeptr)) {
-
   printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
   printf_core::Writer writer(&wb);
   int ret = strftime_core::strftime_main(&writer, format, timeptr);
diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp
new file mode 100644
index 0000000000000..3dee3c9728e59
--- /dev/null
+++ b/libc/src/time/strftime_l.cpp
@@ -0,0 +1,33 @@
+//===-- Implementation of strftime_l 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/strftime_l.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_tm.h"
+#include "include/llvm-libc-types/locale_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/printf_core/writer.h"
+#include "src/time/strftime_core/strftime_main.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// TODO: Add support for locales.
+LLVM_LIBC_FUNCTION(size_t, strftime_l,
+                   (char *__restrict buffer, size_t buffsz,
+                    const char *__restrict format,
+                    const struct tm *__restrict tp, locale_t)) {
+  printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
+  printf_core::Writer writer(&wb);
+  int ret = strftime_core::strftime_main(&writer, format, timeptr);
+  if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
+    wb.buff[wb.buff_cur] = '\0';
+  return (ret < 0 || static_cast<size_t>(ret) > buffsz) ? 0 : ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/strftime_l.h b/libc/src/time/strftime_l.h
new file mode 100644
index 0000000000000..158c4a63986b4
--- /dev/null
+++ b/libc/src/time/strftime_l.h
@@ -0,0 +1,25 @@
+//===-- Implementation header for strftime_l --------------------*- 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_STRFTIME_L_H
+#define LLVM_LIBC_SRC_TIME_STRFTIME_L_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_tm.h"
+#include "include/llvm-libc-types/locale_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+size_t strftime_l(char *__restrict buffer, size_t count,
+                  const char *__restrict format, const struct tm *__restrict tp,
+                  locale_t);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_STRFTIME_L_H

>From bebe86c40b0a57b53d6e4b21668ed06d2a9094d3 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 20 Feb 2025 18:33:21 -0800
Subject: [PATCH 2/2] Address review feedback

---
 libc/src/time/strftime_l.cpp | 6 +++---
 libc/src/time/strftime_l.h   | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp
index 3dee3c9728e59..e19c7c605cd4a 100644
--- a/libc/src/time/strftime_l.cpp
+++ b/libc/src/time/strftime_l.cpp
@@ -7,9 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/time/strftime_l.h"
+#include "hdr/types/locale_t.h"
 #include "hdr/types/size_t.h"
 #include "hdr/types/struct_tm.h"
-#include "include/llvm-libc-types/locale_t.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/stdio/printf_core/writer.h"
@@ -20,8 +20,8 @@ namespace LIBC_NAMESPACE_DECL {
 // TODO: Add support for locales.
 LLVM_LIBC_FUNCTION(size_t, strftime_l,
                    (char *__restrict buffer, size_t buffsz,
-                    const char *__restrict format,
-                    const struct tm *__restrict tp, locale_t)) {
+                    const char *__restrict format, const tm *timeptr,
+                    locale_t)) {
   printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
   printf_core::Writer writer(&wb);
   int ret = strftime_core::strftime_main(&writer, format, timeptr);
diff --git a/libc/src/time/strftime_l.h b/libc/src/time/strftime_l.h
index 158c4a63986b4..cc2313336d786 100644
--- a/libc/src/time/strftime_l.h
+++ b/libc/src/time/strftime_l.h
@@ -9,15 +9,15 @@
 #ifndef LLVM_LIBC_SRC_TIME_STRFTIME_L_H
 #define LLVM_LIBC_SRC_TIME_STRFTIME_L_H
 
+#include "hdr/types/locale_t.h"
 #include "hdr/types/size_t.h"
 #include "hdr/types/struct_tm.h"
-#include "include/llvm-libc-types/locale_t.h"
 #include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
 size_t strftime_l(char *__restrict buffer, size_t count,
-                  const char *__restrict format, const struct tm *__restrict tp,
+                  const char *__restrict format, const tm *timeptr,
                   locale_t);
 
 } // namespace LIBC_NAMESPACE_DECL



More information about the libc-commits mailing list