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

Michael Jones via libc-commits libc-commits at lists.llvm.org
Wed Feb 12 13:35:22 PST 2025


================
@@ -0,0 +1,2329 @@
+//===-- Unittests for strftime --------------------------------------------===//
+//
+// 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 "hdr/types/struct_tm.h"
+#include "src/__support/CPP/array.h"
+#include "src/__support/integer_to_string.h"
+#include "src/time/strftime.h"
+#include "src/time/time_constants.h"
+#include "test/UnitTest/Test.h"
+
+// Copied from sprintf_test.cpp.
+// TODO: put this somewhere more reusable, it's handy.
+// Subtract 1 from sizeof(expected_str) to account for the null byte.
+#define EXPECT_STREQ_LEN(actual_written, actual_str, expected_str)             \
+  EXPECT_EQ(actual_written, sizeof(expected_str) - 1);                         \
+  EXPECT_STREQ(actual_str, expected_str);
+
+constexpr int get_adjusted_year(int year) {
+  // tm_year counts years since 1900, so subtract 1900 to get the tm_year for a
+  // given raw year.
+  return year - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE;
+}
+
+// TODO: Move this somewhere it can be reused. It seems like a useful tool to
+// have.
+// A helper class to generate simple padded numbers. It places the result in its
+// internal buffer, which is cleared on every call.
+class SimplePaddedNum {
+  static constexpr size_t BUFF_LEN = 16;
+  char buff[BUFF_LEN];
+  size_t cur_len; // length of string currently in buff
+
+  void clear_buff() {
+    // TODO: builtin_memset?
+    for (size_t i = 0; i < BUFF_LEN; ++i)
+      buff[i] = '\0';
+  }
+
+public:
+  SimplePaddedNum() = default;
+
+  // PRECONDITIONS: 0 < num < 2**31, min_width < 16
+  // Returns: Pointer to the start of the padded number as a string, stored in
+  // the internal buffer.
+  char *get_padded_num(int num, size_t min_width, char padding_char = '0') {
+    clear_buff();
+
+    // we're not handling the negative sign here, so padding on negative numbers
+    // will be incorrect. For this use case I consider that to be a reasonable
+    // tradeoff for simplicity. This is more meant for the cases where we can
+    // loop through all the possibilities, and for time those are all positive.
+    LIBC_NAMESPACE::IntegerToString<int> raw(num);
+    auto str = raw.view();
+    int leading_zeroes = min_width - raw.size();
+
+    size_t i = 0;
+    for (; static_cast<int>(i) < leading_zeroes; ++i)
+      buff[i] = padding_char;
+    for (size_t str_cur = 0; str_cur < str.size(); ++i, ++str_cur)
+      buff[i] = str[str_cur];
----------------
michaelrj-google wrote:

I've applied it, but I'm not sure if this optimization is necessary. Does the compiler not do this itself?

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


More information about the libc-commits mailing list