[libc-commits] [libc] [libc] Implement strftime (PR #111305)

Michael Jones via libc-commits libc-commits at lists.llvm.org
Wed Jan 8 15:26:13 PST 2025


================
@@ -0,0 +1,208 @@
+//===-- Format specifier converter for printf -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See htto_conv.times://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_NUM_CONVERTER_H
+#define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_NUM_CONVERTER_H
+
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/integer_to_string.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/printf_core/writer.h"
+#include "src/time/strftime_core/core_structs.h"
+#include "src/time/strftime_core/time_internal_def.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace strftime_core {
+
+namespace details {
+
+LIBC_INLINE cpp::optional<cpp::string_view>
+num_to_strview(uintmax_t num, cpp::span<char> bufref) {
+  return IntegerToString<uintmax_t>::format_to(bufref, num);
+}
+
+template <typename T> int count_digits(T num) {
+  if (num == 0)
+    return 1;
+  int digits = 0;
+  while (num > 0) {
+    num /= 10;
+    digits++;
+  }
+  return digits;
+}
+
+LIBC_INLINE int write_num_with_padding(int width, char padding, uintmax_t num,
+                                       printf_core::Writer *writer) {
+  cpp::array<char, IntegerToString<uintmax_t>::buffer_size()> buf;
+  int digits = count_digits(num);
+  int padding_needed = width - digits;
+
+  for (int _ = 0; _ < padding_needed; _++) {
+    RET_IF_RESULT_NEGATIVE(writer->write(padding));
+  }
+
+  return writer->write(*num_to_strview(num, buf));
+}
+
+} // namespace details
+
+namespace iso {
+
+/* Nonzero if YEAR is a leap year (every 4 years,
+   except every 100th isn't, and every 400th is).  */
+LIBC_INLINE bool is_leap(int year) {
+  return ((year % 4 == 0) && (year % 100 != 0 || year % 400 == 0));
+}
+
+static int iso_week_days(int yday, int wday) {
+  /* Add enough to the first operand of % to make it nonnegative.  */
+  int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
+  return (yday - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 +
+          ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
+}
+
+enum class IsoData {
+  GET_DATE,
+  GET_YEAR,
+};
+
+template <IsoData get_date_or_year>
+LIBC_INLINE int convert_iso(const FormatSection &to_conv) {
+  int year = to_conv.time->tm_year + YEAR_BASE;
+  int days = iso_week_days(to_conv.time->tm_yday, to_conv.time->tm_wday);
+
+  if (days < 0) {
+    /* This ISO week belongs to the previous year.  */
+    year--;
+    days = iso_week_days(to_conv.time->tm_yday + (365 + is_leap(year)),
+                         to_conv.time->tm_wday);
+  } else {
+    int d = iso_week_days(to_conv.time->tm_yday - (365 + is_leap(year)),
+                          to_conv.time->tm_wday);
+    if (0 <= d) {
+      /* This ISO week belongs to the next year.  */
+      year++;
+      days = d;
+    }
+  }
----------------
michaelrj-google wrote:

This section of code is copied from glibc: https://github.com/bminor/glibc/blob/master/time/strftime_l.c#L383

That's not acceptable both for licensing and for plagiarism reasons. Copying code from other projects - even open source ones - can cause significant legal issues. The license glibc uses is called the "LGPL" and the license LLVM uses is based on the "Apache License". I'd recommend at least researching both of these before making any more PRs.

https://github.com/llvm/llvm-project/pull/111305


More information about the libc-commits mailing list