mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Introduce ctl::to_string()
This commit is contained in:
parent
acbabedf27
commit
e627bfa359
11 changed files with 432 additions and 40 deletions
2
Makefile
2
Makefile
|
@ -284,10 +284,10 @@ include third_party/ncurses/BUILD.mk # │
|
||||||
include third_party/readline/BUILD.mk # │
|
include third_party/readline/BUILD.mk # │
|
||||||
include third_party/libunwind/BUILD.mk # |
|
include third_party/libunwind/BUILD.mk # |
|
||||||
include third_party/libcxxabi/BUILD.mk # |
|
include third_party/libcxxabi/BUILD.mk # |
|
||||||
|
include third_party/double-conversion/BUILD.mk # │
|
||||||
include ctl/BUILD.mk # │
|
include ctl/BUILD.mk # │
|
||||||
include third_party/libcxx/BUILD.mk # │
|
include third_party/libcxx/BUILD.mk # │
|
||||||
include third_party/openmp/BUILD.mk # │
|
include third_party/openmp/BUILD.mk # │
|
||||||
include third_party/double-conversion/BUILD.mk # │
|
|
||||||
include third_party/pcre/BUILD.mk # │
|
include third_party/pcre/BUILD.mk # │
|
||||||
include third_party/less/BUILD.mk # │
|
include third_party/less/BUILD.mk # │
|
||||||
include net/https/BUILD.mk # │
|
include net/https/BUILD.mk # │
|
||||||
|
|
|
@ -21,6 +21,7 @@ CTL_A_DIRECTDEPS = \
|
||||||
LIBC_NEXGEN32E \
|
LIBC_NEXGEN32E \
|
||||||
LIBC_STDIO \
|
LIBC_STDIO \
|
||||||
LIBC_STR \
|
LIBC_STR \
|
||||||
|
THIRD_PARTY_DOUBLECONVERSION \
|
||||||
THIRD_PARTY_GDTOA \
|
THIRD_PARTY_GDTOA \
|
||||||
THIRD_PARTY_LIBCXXABI \
|
THIRD_PARTY_LIBCXXABI \
|
||||||
THIRD_PARTY_LIBUNWIND \
|
THIRD_PARTY_LIBUNWIND \
|
||||||
|
|
35
ctl/dubble.cc
Normal file
35
ctl/dubble.cc
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||||
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
|
//
|
||||||
|
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
// any purpose with or without fee is hereby granted, provided that the
|
||||||
|
// above copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include "dubble.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
const double_conversion::DoubleToStringConverter kDoubleToPrintfG(
|
||||||
|
double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
|
||||||
|
double_conversion::DoubleToStringConverter::NO_TRAILING_ZERO,
|
||||||
|
"inf",
|
||||||
|
"nan",
|
||||||
|
'e',
|
||||||
|
-6,
|
||||||
|
10, // let 32-bit ints be represented without exponent
|
||||||
|
6,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
} // namespace ctl
|
13
ctl/dubble.h
Normal file
13
ctl/dubble.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||||
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
|
#ifndef COSMOPOLITAN_CTL_DUBBLE_H_
|
||||||
|
#define COSMOPOLITAN_CTL_DUBBLE_H_
|
||||||
|
#include "third_party/double-conversion/double-to-string.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // COSMOPOLITAN_CTL_DUBBLE_H_
|
|
@ -17,11 +17,15 @@
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "ostream.h"
|
#include "ostream.h"
|
||||||
|
#include "dubble.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "string_view.h"
|
#include "string_view.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
|
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||||
|
|
||||||
ostream cout(stdout);
|
ostream cout(stdout);
|
||||||
ostream cerr(stderr);
|
ostream cerr(stderr);
|
||||||
|
|
||||||
|
@ -50,7 +54,7 @@ ostream&
|
||||||
ostream::operator<<(const char* str)
|
ostream::operator<<(const char* str)
|
||||||
{
|
{
|
||||||
if (good() && str)
|
if (good() && str)
|
||||||
if (fprintf(file_, "%s", str) < 0)
|
if (fputs(str, file_) < 0)
|
||||||
setstate(badbit);
|
setstate(badbit);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -67,35 +71,84 @@ ostream::operator<<(char c)
|
||||||
ostream&
|
ostream&
|
||||||
ostream::operator<<(int n)
|
ostream::operator<<(int n)
|
||||||
{
|
{
|
||||||
if (good())
|
if (good()) {
|
||||||
if (fprintf(file_, "%d", n) < 0)
|
char buf[12];
|
||||||
|
FormatInt32(buf, n);
|
||||||
|
if (fputs(buf, file_) < 0)
|
||||||
setstate(badbit);
|
setstate(badbit);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream&
|
||||||
|
ostream::operator<<(unsigned n)
|
||||||
|
{
|
||||||
|
if (good()) {
|
||||||
|
char buf[12];
|
||||||
|
FormatUint32(buf, n);
|
||||||
|
if (fputs(buf, file_) < 0)
|
||||||
|
setstate(badbit);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream&
|
ostream&
|
||||||
ostream::operator<<(long n)
|
ostream::operator<<(long n)
|
||||||
{
|
{
|
||||||
if (good())
|
if (good()) {
|
||||||
if (fprintf(file_, "%ld", n) < 0)
|
char buf[21];
|
||||||
|
FormatInt64(buf, n);
|
||||||
|
if (fputs(buf, file_) < 0)
|
||||||
setstate(badbit);
|
setstate(badbit);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream&
|
||||||
|
ostream::operator<<(unsigned long n)
|
||||||
|
{
|
||||||
|
if (good()) {
|
||||||
|
char buf[21];
|
||||||
|
FormatUint64(buf, n);
|
||||||
|
if (fputs(buf, file_) < 0)
|
||||||
|
setstate(badbit);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream&
|
||||||
|
ostream::operator<<(float f)
|
||||||
|
{
|
||||||
|
if (good()) {
|
||||||
|
char buf[128];
|
||||||
|
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||||
|
kDoubleToPrintfG.ToShortestSingle(f, &b);
|
||||||
|
b.Finalize();
|
||||||
|
if (fputs(buf, file_) < 0)
|
||||||
|
setstate(badbit);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream&
|
ostream&
|
||||||
ostream::operator<<(double d)
|
ostream::operator<<(double d)
|
||||||
{
|
{
|
||||||
if (good())
|
if (good()) {
|
||||||
if (fprintf(file_, "%f", d) < 0)
|
char buf[128];
|
||||||
|
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||||
|
kDoubleToPrintfG.ToShortest(d, &b);
|
||||||
|
b.Finalize();
|
||||||
|
if (fputs(buf, file_) < 0)
|
||||||
setstate(badbit);
|
setstate(badbit);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream&
|
ostream&
|
||||||
ostream::operator<<(const string_view& s)
|
ostream::operator<<(const string_view& s)
|
||||||
{
|
{
|
||||||
if (good())
|
if (good() && s.size())
|
||||||
if (fprintf(file_, "%.*s", (int)s.size(), s.data()) < 0)
|
if (!fwrite(s.data(), s.size(), 1, file_))
|
||||||
setstate(badbit);
|
setstate(badbit);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +159,7 @@ ostream::operator<<(bool b)
|
||||||
if (good()) {
|
if (good()) {
|
||||||
const char* value =
|
const char* value =
|
||||||
(flags() & boolalpha) ? (b ? "true" : "false") : (b ? "1" : "0");
|
(flags() & boolalpha) ? (b ? "true" : "false") : (b ? "1" : "0");
|
||||||
if (fprintf(file_, "%s", value) < 0)
|
if (fputs(value, file_) < 0)
|
||||||
setstate(badbit);
|
setstate(badbit);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -16,12 +16,15 @@ class ostream : public ios
|
||||||
virtual ~ostream();
|
virtual ~ostream();
|
||||||
|
|
||||||
ostream& operator<<(const char*);
|
ostream& operator<<(const char*);
|
||||||
|
ostream& operator<<(bool);
|
||||||
ostream& operator<<(char);
|
ostream& operator<<(char);
|
||||||
ostream& operator<<(int);
|
ostream& operator<<(int);
|
||||||
|
ostream& operator<<(unsigned);
|
||||||
ostream& operator<<(long);
|
ostream& operator<<(long);
|
||||||
|
ostream& operator<<(unsigned long);
|
||||||
|
ostream& operator<<(float);
|
||||||
ostream& operator<<(double);
|
ostream& operator<<(double);
|
||||||
ostream& operator<<(const ctl::string_view&);
|
ostream& operator<<(const ctl::string_view&);
|
||||||
ostream& operator<<(bool);
|
|
||||||
ostream& operator<<(ostream& (*)(ostream&));
|
ostream& operator<<(ostream& (*)(ostream&));
|
||||||
|
|
||||||
ostream& put(char);
|
ostream& put(char);
|
||||||
|
|
|
@ -17,28 +17,30 @@
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "ostringstream.h"
|
#include "ostringstream.h"
|
||||||
|
#include "dubble.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
|
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||||
|
|
||||||
ostringstream::ostringstream() : buffer_(), write_pos_(0)
|
ostringstream::ostringstream() : buffer_(), write_pos_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream::ostringstream(const ctl::string_view& str)
|
ostringstream::ostringstream(const string_view& str)
|
||||||
: buffer_(str), write_pos_(0)
|
: buffer_(str), write_pos_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ctl::string
|
string
|
||||||
ostringstream::str() const
|
ostringstream::str() const
|
||||||
{
|
{
|
||||||
return buffer_;
|
return buffer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ostringstream::str(const ctl::string& s)
|
ostringstream::str(const string& s)
|
||||||
{
|
{
|
||||||
buffer_ = s;
|
buffer_ = s;
|
||||||
write_pos_ = 0;
|
write_pos_ = 0;
|
||||||
|
@ -65,7 +67,7 @@ ostringstream::operator<<(char c)
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream&
|
ostringstream&
|
||||||
ostringstream::operator<<(const ctl::string_view& s)
|
ostringstream::operator<<(const string_view& s)
|
||||||
{
|
{
|
||||||
if (good()) {
|
if (good()) {
|
||||||
if (write_pos_ + s.size() <= buffer_.size()) {
|
if (write_pos_ + s.size() <= buffer_.size()) {
|
||||||
|
@ -82,36 +84,40 @@ ostringstream::operator<<(const ctl::string_view& s)
|
||||||
ostringstream&
|
ostringstream&
|
||||||
ostringstream::operator<<(int n)
|
ostringstream::operator<<(int n)
|
||||||
{
|
{
|
||||||
char temp[12];
|
if (good()) {
|
||||||
if (good())
|
char buf[12];
|
||||||
*this << ctl::string_view(temp, FormatInt32(temp, n) - temp);
|
*this << string_view(buf, FormatInt32(buf, n) - buf);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream&
|
ostringstream&
|
||||||
ostringstream::operator<<(unsigned int n)
|
ostringstream::operator<<(unsigned n)
|
||||||
{
|
{
|
||||||
char temp[12];
|
if (good()) {
|
||||||
if (good())
|
char buf[12];
|
||||||
*this << ctl::string_view(temp, FormatUint32(temp, n) - temp);
|
*this << string_view(buf, FormatUint32(buf, n) - buf);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream&
|
ostringstream&
|
||||||
ostringstream::operator<<(long n)
|
ostringstream::operator<<(long n)
|
||||||
{
|
{
|
||||||
char temp[21];
|
if (good()) {
|
||||||
if (good())
|
char buf[21];
|
||||||
*this << ctl::string_view(temp, FormatInt64(temp, n) - temp);
|
*this << string_view(buf, FormatInt64(buf, n) - buf);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream&
|
ostringstream&
|
||||||
ostringstream::operator<<(unsigned long n)
|
ostringstream::operator<<(unsigned long n)
|
||||||
{
|
{
|
||||||
char temp[21];
|
if (good()) {
|
||||||
if (good())
|
char buf[21];
|
||||||
*this << ctl::string_view(temp, FormatUint64(temp, n) - temp);
|
*this << string_view(buf, FormatUint64(buf, n) - buf);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +125,11 @@ ostringstream&
|
||||||
ostringstream::operator<<(float f)
|
ostringstream::operator<<(float f)
|
||||||
{
|
{
|
||||||
if (good()) {
|
if (good()) {
|
||||||
char temp[32];
|
char buf[128];
|
||||||
int len = snprintf(temp, sizeof(temp), "%g", f);
|
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||||
*this << ctl::string_view(temp, len);
|
kDoubleToPrintfG.ToShortestSingle(f, &b);
|
||||||
|
b.Finalize();
|
||||||
|
*this << string_view(buf);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -130,9 +138,11 @@ ostringstream&
|
||||||
ostringstream::operator<<(double d)
|
ostringstream::operator<<(double d)
|
||||||
{
|
{
|
||||||
if (good()) {
|
if (good()) {
|
||||||
char temp[32];
|
char buf[128];
|
||||||
int len = snprintf(temp, sizeof(temp), "%g", d);
|
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||||
*this << ctl::string_view(temp, len);
|
kDoubleToPrintfG.ToShortest(d, &b);
|
||||||
|
b.Finalize();
|
||||||
|
*this << string_view(buf);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
43
ctl/string.h
43
ctl/string.h
|
@ -338,11 +338,27 @@ class string
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string operator+(const char c) const noexcept
|
||||||
|
{
|
||||||
|
char s[2] = { c };
|
||||||
|
return strcat(*this, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
string operator+(const string& s) const noexcept
|
||||||
|
{
|
||||||
|
return strcat(*this, s);
|
||||||
|
}
|
||||||
|
|
||||||
string operator+(const ctl::string_view s) const noexcept
|
string operator+(const ctl::string_view s) const noexcept
|
||||||
{
|
{
|
||||||
return strcat(*this, s);
|
return strcat(*this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string operator+(const char* s) const noexcept
|
||||||
|
{
|
||||||
|
return strcat(*this, s);
|
||||||
|
}
|
||||||
|
|
||||||
int compare(const ctl::string_view s) const noexcept
|
int compare(const ctl::string_view s) const noexcept
|
||||||
{
|
{
|
||||||
return strcmp(*this, s);
|
return strcmp(*this, s);
|
||||||
|
@ -409,6 +425,33 @@ static_assert(sizeof(string) == __::string_size);
|
||||||
static_assert(sizeof(__::small_string) == __::string_size);
|
static_assert(sizeof(__::small_string) == __::string_size);
|
||||||
static_assert(sizeof(__::big_string) == __::string_size);
|
static_assert(sizeof(__::big_string) == __::string_size);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(int);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(long);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(long long);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(unsigned);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(unsigned long);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(unsigned long long);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(float);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(double);
|
||||||
|
|
||||||
|
ctl::string
|
||||||
|
to_string(long double);
|
||||||
|
|
||||||
} // namespace ctl
|
} // namespace ctl
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
|
|
109
ctl/to_string.cc
Normal file
109
ctl/to_string.cc
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||||
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
|
//
|
||||||
|
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
// any purpose with or without fee is hereby granted, provided that the
|
||||||
|
// above copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include "dubble.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/math.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "third_party/gdtoa/gdtoa.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(int value)
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
return { buf, FormatInt32(buf, value) - buf };
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(unsigned value)
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
return { buf, FormatUint32(buf, value) - buf };
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(long value)
|
||||||
|
{
|
||||||
|
char buf[21];
|
||||||
|
return { buf, FormatInt64(buf, value) - buf };
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(unsigned long value)
|
||||||
|
{
|
||||||
|
char buf[21];
|
||||||
|
return { buf, FormatUint64(buf, value) - buf };
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(long long value)
|
||||||
|
{
|
||||||
|
char buf[21];
|
||||||
|
return { buf, FormatInt64(buf, value) - buf };
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(unsigned long long value)
|
||||||
|
{
|
||||||
|
char buf[21];
|
||||||
|
return { buf, FormatUint64(buf, value) - buf };
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(float value)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||||
|
kDoubleToPrintfG.ToShortestSingle(value, &b);
|
||||||
|
b.Finalize();
|
||||||
|
return string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(double value)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||||
|
kDoubleToPrintfG.ToShortest(value, &b);
|
||||||
|
b.Finalize();
|
||||||
|
return string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
to_string(long double value)
|
||||||
|
{
|
||||||
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
|
return to_string((double)value);
|
||||||
|
#else
|
||||||
|
char buf[128];
|
||||||
|
#if LDBL_MANT_DIG == 113
|
||||||
|
g_Qfmt_p(buf, &value, 16, 128, NIK(2, 0, 0));
|
||||||
|
#elif LDBL_MANT_DIG == 64
|
||||||
|
g_xfmt_p(buf, &value, 16, 128, NIK(2, 0, 0));
|
||||||
|
#else
|
||||||
|
#error "unsupported long double"
|
||||||
|
#endif
|
||||||
|
return string(buf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ctl
|
|
@ -35,10 +35,9 @@ main()
|
||||||
|
|
||||||
// Test basic copy
|
// Test basic copy
|
||||||
ctl::copy(src.begin(), src.end(), dest.begin());
|
ctl::copy(src.begin(), src.end(), dest.begin());
|
||||||
for (size_t i = 0; i < 5; ++i) {
|
for (size_t i = 0; i < 5; ++i)
|
||||||
if (dest[i] != src[i])
|
if (dest[i] != src[i])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
// Test partial copy
|
// Test partial copy
|
||||||
ctl::array<int, 5> dest2 = { 0, 0, 0, 0, 0 };
|
ctl::array<int, 5> dest2 = { 0, 0, 0, 0, 0 };
|
||||||
|
@ -57,10 +56,9 @@ main()
|
||||||
// Test copy with empty range
|
// Test copy with empty range
|
||||||
ctl::array<int, 5> dest4 = { 0, 0, 0, 0, 0 };
|
ctl::array<int, 5> dest4 = { 0, 0, 0, 0, 0 };
|
||||||
ctl::copy(src.begin(), src.begin(), dest4.begin());
|
ctl::copy(src.begin(), src.begin(), dest4.begin());
|
||||||
for (size_t i = 0; i < 5; ++i) {
|
for (size_t i = 0; i < 5; ++i)
|
||||||
if (dest4[i] != 0)
|
if (dest4[i] != 0)
|
||||||
return 4;
|
return 4;
|
||||||
}
|
|
||||||
|
|
||||||
// Test copy return value
|
// Test copy return value
|
||||||
ctl::array<int, 5> dest5 = { 0, 0, 0, 0, 0 };
|
ctl::array<int, 5> dest5 = { 0, 0, 0, 0, 0 };
|
||||||
|
|
127
test/ctl/to_string_test.cc
Normal file
127
test/ctl/to_string_test.cc
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||||
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
|
//
|
||||||
|
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
// any purpose with or without fee is hereby granted, provided that the
|
||||||
|
// above copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include "ctl/string.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/limits.h"
|
||||||
|
#include "libc/math.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
|
||||||
|
// test integer conversion
|
||||||
|
{
|
||||||
|
if (ctl::to_string(0) != "0")
|
||||||
|
return 1;
|
||||||
|
if (ctl::to_string(3) != "3")
|
||||||
|
return 1;
|
||||||
|
if (ctl::to_string(INT32_MAX) != "2147483647")
|
||||||
|
return 2;
|
||||||
|
if (ctl::to_string(INT32_MIN) != "-2147483648")
|
||||||
|
return 3;
|
||||||
|
if (ctl::to_string(UINT32_MAX) != "4294967295")
|
||||||
|
return 4;
|
||||||
|
if (ctl::to_string(INT64_MAX) != "9223372036854775807")
|
||||||
|
return 5;
|
||||||
|
if (ctl::to_string(INT64_MIN) != "-9223372036854775808")
|
||||||
|
return 6;
|
||||||
|
if (ctl::to_string(UINT64_MAX) != "18446744073709551615")
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test float conversion
|
||||||
|
// we diverge from std::to_string(float) because it's garbage
|
||||||
|
{
|
||||||
|
if (ctl::to_string(0.f) != "0") // 0.000000
|
||||||
|
return 8;
|
||||||
|
if (ctl::to_string(-0.f) != "-0") // 0.000000
|
||||||
|
return 9;
|
||||||
|
if (ctl::to_string(3.f) != "3") // 3.000000
|
||||||
|
return 10;
|
||||||
|
if (ctl::to_string(3.14f) != "3.14") // 3.140000
|
||||||
|
return 11;
|
||||||
|
if (ctl::to_string(3.140001f) != "3.140001")
|
||||||
|
return 12;
|
||||||
|
if (ctl::to_string(1000000000.f) != "1000000000") // 1000000000.000000
|
||||||
|
return 12;
|
||||||
|
if (ctl::to_string(10000000000.f) != "1e+10") // 10000000000.000000
|
||||||
|
return 12;
|
||||||
|
if (ctl::to_string(NAN) != "nan")
|
||||||
|
return 13;
|
||||||
|
if (ctl::to_string(INFINITY) != "inf")
|
||||||
|
return 14;
|
||||||
|
if (ctl::to_string(-INFINITY) != "-inf")
|
||||||
|
return 15;
|
||||||
|
if (ctl::to_string(FLT_MIN) != "1.1754944e-38") // 0.000000 lool
|
||||||
|
return 16;
|
||||||
|
if (ctl::to_string(-FLT_MIN) != "-1.1754944e-38")
|
||||||
|
return 17;
|
||||||
|
if (ctl::to_string(FLT_MAX) != "3.4028235e+38")
|
||||||
|
return 18;
|
||||||
|
if (ctl::to_string(-FLT_MAX) != "-3.4028235e+38")
|
||||||
|
return 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test double conversion
|
||||||
|
{
|
||||||
|
if (ctl::to_string(0.) != "0")
|
||||||
|
return 20;
|
||||||
|
if (ctl::to_string(-0.) != "-0")
|
||||||
|
return 21;
|
||||||
|
if (ctl::to_string(3.) != "3")
|
||||||
|
return 22;
|
||||||
|
if (ctl::to_string(2147483647.) != "2147483647")
|
||||||
|
return 23;
|
||||||
|
if (ctl::to_string(-2147483648.) != "-2147483648")
|
||||||
|
return 23;
|
||||||
|
if (ctl::to_string(10000000000.) != "1e+10")
|
||||||
|
return 23;
|
||||||
|
if (ctl::to_string(3.14) != "3.14")
|
||||||
|
return 23;
|
||||||
|
if (ctl::to_string(3.140001) != "3.140001")
|
||||||
|
return 24;
|
||||||
|
if (ctl::to_string(DBL_MIN) != "2.2250738585072014e-308")
|
||||||
|
return 25;
|
||||||
|
if (ctl::to_string(-DBL_MIN) != "-2.2250738585072014e-308")
|
||||||
|
return 26;
|
||||||
|
if (ctl::to_string(DBL_MAX) != "1.7976931348623157e+308")
|
||||||
|
return 27;
|
||||||
|
if (ctl::to_string(-DBL_MAX) != "-1.7976931348623157e+308")
|
||||||
|
return 28;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test long double conversion
|
||||||
|
{
|
||||||
|
if (ctl::to_string(0.L) != "0")
|
||||||
|
return 29;
|
||||||
|
if (ctl::to_string(-0.L) != "-0")
|
||||||
|
return 30;
|
||||||
|
if (ctl::to_string(3.L) != "3")
|
||||||
|
return 31;
|
||||||
|
if (ctl::to_string(3.14L) != "3.14")
|
||||||
|
return 32;
|
||||||
|
if (ctl::to_string(LDBL_MAX) != "1.189731495357232e+4932")
|
||||||
|
return 33;
|
||||||
|
if (ctl::to_string(-LDBL_MAX) != "-1.189731495357232e+4932")
|
||||||
|
return 34;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
|
}
|
Loading…
Reference in a new issue