This is an archive of the discontinued LLVM Phabricator instance.

[libc] add int to string for extended bases
ClosedPublic

Authored by michaelrj on Aug 5 2022, 3:07 PM.

Details

Summary

The default IntegerToString class only supports base 10, this patch adds
a version which supports any base between 2 and 36 inclusive. This will
be used in an upcoming patch.

Diff Detail

Event Timeline

michaelrj created this revision.Aug 5 2022, 3:07 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptAug 5 2022, 3:07 PM
michaelrj requested review of this revision.Aug 5 2022, 3:07 PM
lntue added inline comments.Aug 5 2022, 7:05 PM
libc/src/__support/integer_to_string.h
82

Look like a good candidate for clz builtin, unless it's only used for compile-time constants. In that case, it should be ok to bump this to C++20 and use consteval. Otherwise, you'll need to add inline for this.

109

Can we really do this? On the surface it looks equivalent to int(bool(2 <= Base)) <= 36 which is always true since `int(bool) is either 0 or 1.

150

why is the ; needed?

154

convert(val, conv_base, /*lowercase=*/ true) might be a bit easier to read.

Tests?

libc/src/__support/integer_to_string.h
100

You can avoid this with constexpr arrangement like this:

private:
  static constexpr size_t BUFSIZE_BASE10 = ...; // The current base 10 formula from IntegerToString
  static constexpr size_t BUFSIZE_COMMON = ...; // The formula below
public:
  static constexpr size_t BUFSIZE = Base == 10 ? BUFSIZE_BASE10 : BUFSIZE_COMMON;
123

Silently return? Can we perhaps return a boolean value to indicate success/failure?

michaelrj updated this revision to Diff 450875.Aug 8 2022, 10:55 AM
michaelrj marked 5 inline comments as done.

I wrote tests, but I accidentally put them in a later patch in the sequence. That is now fixed.

libc/src/__support/integer_to_string.h
82

it is used only for compile time constants. I don't know if we want to bump this to C++20, so I've marked it as constexpr inline for the moment. I think you're right that this could use clz, but since it's only at compile time I don't think that's necessary.

109

you're right, that doesn't work. Fixed.

123

we could, but this function is only called from the constructor so I'm not sure what we'd do with that information.

sivachandra added inline comments.Aug 8 2022, 11:54 PM
libc/src/__support/integer_to_string.h
82

AFAICT, this is a private function so can be a static private member of the converter class.

166

Based on the use case you have in D131302, a better design seems to be to use a template function and not a template class?

class IntegerToString {
public:
  template <typename T, uint8_t BASE>
  constexpr size_t bufsize() {
    return ...; // The BUFSIZE formula
  }

  template <typename T, uint8_t BASE,  cpp::enable_if_t<2 <= BASE && BASE <= 10, int> = 0>
  static constexpr cpp:optional<cpp::StringView> convert(T val, cpp::MutableArrayRef<char> &buffer) {
    // If This function can actually be a constexpr, then the below "if" will be optimized out.
    if (buffer.size() < bufsize<T, BASE>())
      return cpp::optional<cpp::StringView>();

    // Perform conversion and write it to buffer

    return cpp::StringView(...); // A StringView into the |buffer|
  }

  template <typename T, uint8_t BASE, cpp::enable_if_t<10 < BASE && BASE <= 36, int> = 0>
  static constexpr cpp:optional<cpp::StringView> convert(T val, cpp::MutableArrayRef<char> &buffer, bool lowercase) {
    ...
  }

};
michaelrj added inline comments.Aug 9 2022, 10:20 AM
libc/src/__support/integer_to_string.h
166

since the goal of that patch is to shrink the code size, I designed it to avoid templating the convert function because that would result in three copies of near-identical code with different bases. I do like the idea of using optional to wrap the StringView though, since that solves the problem of returns. I will consider the problem more.

sivachandra added inline comments.Aug 9 2022, 10:29 AM
libc/src/__support/integer_to_string.h
166

You can keep the business logic in a single non-template function and make only the user facing functions templates. As it stands, this patch is going to trigger multiple copies of convert for the combinations of T x BASE?

michaelrj updated this revision to Diff 451309.Aug 9 2022, 4:45 PM
michaelrj marked 2 inline comments as done.

updated to use a more logical organization. I've merged the BaseStringToInteger into StringToInteger, and added a static method that allows users to pass their own MutableArrayRef instead of being forced to use the IntegerToString object as the buffer's owner.

michaelrj marked 2 inline comments as done.Aug 9 2022, 4:45 PM
sivachandra accepted this revision.Aug 9 2022, 10:51 PM
sivachandra added inline comments.
libc/src/__support/integer_to_string.h
77

Looks like there is no use for a different STATIC_BASE. Can we just remove it?

This revision is now accepted and ready to land.Aug 9 2022, 10:51 PM
This revision was landed with ongoing or failed builds.Aug 10 2022, 11:28 AM
This revision was automatically updated to reflect the committed changes.