Skip to content

Commit e627bfa

Browse files
committed
Introduce ctl::to_string()
1 parent acbabed commit e627bfa

File tree

11 files changed

+432
-40
lines changed

11 files changed

+432
-40
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,10 @@ include third_party/ncurses/BUILD.mk # │
284284
include third_party/readline/BUILD.mk #
285285
include third_party/libunwind/BUILD.mk # |
286286
include third_party/libcxxabi/BUILD.mk # |
287+
include third_party/double-conversion/BUILD.mk #
287288
include ctl/BUILD.mk #
288289
include third_party/libcxx/BUILD.mk #
289290
include third_party/openmp/BUILD.mk #
290-
include third_party/double-conversion/BUILD.mk #
291291
include third_party/pcre/BUILD.mk #
292292
include third_party/less/BUILD.mk #
293293
include net/https/BUILD.mk #

ctl/BUILD.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ CTL_A_DIRECTDEPS = \
2121
LIBC_NEXGEN32E \
2222
LIBC_STDIO \
2323
LIBC_STR \
24+
THIRD_PARTY_DOUBLECONVERSION \
2425
THIRD_PARTY_GDTOA \
2526
THIRD_PARTY_LIBCXXABI \
2627
THIRD_PARTY_LIBUNWIND \

ctl/dubble.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
2+
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
3+
//
4+
// Copyright 2024 Justine Alexandra Roberts Tunney
5+
//
6+
// Permission to use, copy, modify, and/or distribute this software for
7+
// any purpose with or without fee is hereby granted, provided that the
8+
// above copyright notice and this permission notice appear in all copies.
9+
//
10+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11+
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12+
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13+
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14+
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15+
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16+
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17+
// PERFORMANCE OF THIS SOFTWARE.
18+
19+
#include "dubble.h"
20+
21+
namespace ctl {
22+
23+
const double_conversion::DoubleToStringConverter kDoubleToPrintfG(
24+
double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
25+
double_conversion::DoubleToStringConverter::NO_TRAILING_ZERO,
26+
"inf",
27+
"nan",
28+
'e',
29+
-6,
30+
10, // let 32-bit ints be represented without exponent
31+
6,
32+
0,
33+
0);
34+
35+
} // namespace ctl

ctl/dubble.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
2+
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
3+
#ifndef COSMOPOLITAN_CTL_DUBBLE_H_
4+
#define COSMOPOLITAN_CTL_DUBBLE_H_
5+
#include "third_party/double-conversion/double-to-string.h"
6+
7+
namespace ctl {
8+
9+
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
10+
11+
} // namespace ctl
12+
13+
#endif // COSMOPOLITAN_CTL_DUBBLE_H_

ctl/ostream.cc

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717
// PERFORMANCE OF THIS SOFTWARE.
1818

1919
#include "ostream.h"
20+
#include "dubble.h"
21+
#include "libc/fmt/itoa.h"
2022
#include "libc/stdio/stdio.h"
2123
#include "string_view.h"
2224

2325
namespace ctl {
2426

27+
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
28+
2529
ostream cout(stdout);
2630
ostream cerr(stderr);
2731

@@ -50,7 +54,7 @@ ostream&
5054
ostream::operator<<(const char* str)
5155
{
5256
if (good() && str)
53-
if (fprintf(file_, "%s", str) < 0)
57+
if (fputs(str, file_) < 0)
5458
setstate(badbit);
5559
return *this;
5660
}
@@ -67,35 +71,84 @@ ostream::operator<<(char c)
6771
ostream&
6872
ostream::operator<<(int n)
6973
{
70-
if (good())
71-
if (fprintf(file_, "%d", n) < 0)
74+
if (good()) {
75+
char buf[12];
76+
FormatInt32(buf, n);
77+
if (fputs(buf, file_) < 0)
78+
setstate(badbit);
79+
}
80+
return *this;
81+
}
82+
83+
ostream&
84+
ostream::operator<<(unsigned n)
85+
{
86+
if (good()) {
87+
char buf[12];
88+
FormatUint32(buf, n);
89+
if (fputs(buf, file_) < 0)
7290
setstate(badbit);
91+
}
7392
return *this;
7493
}
7594

7695
ostream&
7796
ostream::operator<<(long n)
7897
{
79-
if (good())
80-
if (fprintf(file_, "%ld", n) < 0)
98+
if (good()) {
99+
char buf[21];
100+
FormatInt64(buf, n);
101+
if (fputs(buf, file_) < 0)
81102
setstate(badbit);
103+
}
104+
return *this;
105+
}
106+
107+
ostream&
108+
ostream::operator<<(unsigned long n)
109+
{
110+
if (good()) {
111+
char buf[21];
112+
FormatUint64(buf, n);
113+
if (fputs(buf, file_) < 0)
114+
setstate(badbit);
115+
}
116+
return *this;
117+
}
118+
119+
ostream&
120+
ostream::operator<<(float f)
121+
{
122+
if (good()) {
123+
char buf[128];
124+
double_conversion::StringBuilder b(buf, sizeof(buf));
125+
kDoubleToPrintfG.ToShortestSingle(f, &b);
126+
b.Finalize();
127+
if (fputs(buf, file_) < 0)
128+
setstate(badbit);
129+
}
82130
return *this;
83131
}
84132

85133
ostream&
86134
ostream::operator<<(double d)
87135
{
88-
if (good())
89-
if (fprintf(file_, "%f", d) < 0)
136+
if (good()) {
137+
char buf[128];
138+
double_conversion::StringBuilder b(buf, sizeof(buf));
139+
kDoubleToPrintfG.ToShortest(d, &b);
140+
b.Finalize();
141+
if (fputs(buf, file_) < 0)
90142
setstate(badbit);
143+
}
91144
return *this;
92145
}
93146

94147
ostream&
95148
ostream::operator<<(const string_view& s)
96149
{
97-
if (good())
98-
if (fprintf(file_, "%.*s", (int)s.size(), s.data()) < 0)
150+
if (good() && s.size())
151+
if (!fwrite(s.data(), s.size(), 1, file_))
99152
setstate(badbit);
100153
return *this;
101154
}
@@ -106,7 +159,7 @@ ostream::operator<<(bool b)
106159
if (good()) {
107160
const char* value =
108161
(flags() & boolalpha) ? (b ? "true" : "false") : (b ? "1" : "0");
109-
if (fprintf(file_, "%s", value) < 0)
162+
if (fputs(value, file_) < 0)
110163
setstate(badbit);
111164
}
112165
return *this;

ctl/ostream.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ class ostream : public ios
1616
virtual ~ostream();
1717

1818
ostream& operator<<(const char*);
19+
ostream& operator<<(bool);
1920
ostream& operator<<(char);
2021
ostream& operator<<(int);
22+
ostream& operator<<(unsigned);
2123
ostream& operator<<(long);
24+
ostream& operator<<(unsigned long);
25+
ostream& operator<<(float);
2226
ostream& operator<<(double);
2327
ostream& operator<<(const ctl::string_view&);
24-
ostream& operator<<(bool);
2528
ostream& operator<<(ostream& (*)(ostream&));
2629

2730
ostream& put(char);

ctl/ostringstream.cc

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,30 @@
1717
// PERFORMANCE OF THIS SOFTWARE.
1818

1919
#include "ostringstream.h"
20+
#include "dubble.h"
2021
#include "libc/fmt/itoa.h"
21-
#include "libc/stdio/stdio.h"
2222

2323
namespace ctl {
2424

25+
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
26+
2527
ostringstream::ostringstream() : buffer_(), write_pos_(0)
2628
{
2729
}
2830

29-
ostringstream::ostringstream(const ctl::string_view& str)
31+
ostringstream::ostringstream(const string_view& str)
3032
: buffer_(str), write_pos_(0)
3133
{
3234
}
3335

34-
ctl::string
36+
string
3537
ostringstream::str() const
3638
{
3739
return buffer_;
3840
}
3941

4042
void
41-
ostringstream::str(const ctl::string& s)
43+
ostringstream::str(const string& s)
4244
{
4345
buffer_ = s;
4446
write_pos_ = 0;
@@ -65,7 +67,7 @@ ostringstream::operator<<(char c)
6567
}
6668

6769
ostringstream&
68-
ostringstream::operator<<(const ctl::string_view& s)
70+
ostringstream::operator<<(const string_view& s)
6971
{
7072
if (good()) {
7173
if (write_pos_ + s.size() <= buffer_.size()) {
@@ -82,46 +84,52 @@ ostringstream::operator<<(const ctl::string_view& s)
8284
ostringstream&
8385
ostringstream::operator<<(int n)
8486
{
85-
char temp[12];
86-
if (good())
87-
*this << ctl::string_view(temp, FormatInt32(temp, n) - temp);
87+
if (good()) {
88+
char buf[12];
89+
*this << string_view(buf, FormatInt32(buf, n) - buf);
90+
}
8891
return *this;
8992
}
9093

9194
ostringstream&
92-
ostringstream::operator<<(unsigned int n)
95+
ostringstream::operator<<(unsigned n)
9396
{
94-
char temp[12];
95-
if (good())
96-
*this << ctl::string_view(temp, FormatUint32(temp, n) - temp);
97+
if (good()) {
98+
char buf[12];
99+
*this << string_view(buf, FormatUint32(buf, n) - buf);
100+
}
97101
return *this;
98102
}
99103

100104
ostringstream&
101105
ostringstream::operator<<(long n)
102106
{
103-
char temp[21];
104-
if (good())
105-
*this << ctl::string_view(temp, FormatInt64(temp, n) - temp);
107+
if (good()) {
108+
char buf[21];
109+
*this << string_view(buf, FormatInt64(buf, n) - buf);
110+
}
106111
return *this;
107112
}
108113

109114
ostringstream&
110115
ostringstream::operator<<(unsigned long n)
111116
{
112-
char temp[21];
113-
if (good())
114-
*this << ctl::string_view(temp, FormatUint64(temp, n) - temp);
117+
if (good()) {
118+
char buf[21];
119+
*this << string_view(buf, FormatUint64(buf, n) - buf);
120+
}
115121
return *this;
116122
}
117123

118124
ostringstream&
119125
ostringstream::operator<<(float f)
120126
{
121127
if (good()) {
122-
char temp[32];
123-
int len = snprintf(temp, sizeof(temp), "%g", f);
124-
*this << ctl::string_view(temp, len);
128+
char buf[128];
129+
double_conversion::StringBuilder b(buf, sizeof(buf));
130+
kDoubleToPrintfG.ToShortestSingle(f, &b);
131+
b.Finalize();
132+
*this << string_view(buf);
125133
}
126134
return *this;
127135
}
@@ -130,9 +138,11 @@ ostringstream&
130138
ostringstream::operator<<(double d)
131139
{
132140
if (good()) {
133-
char temp[32];
134-
int len = snprintf(temp, sizeof(temp), "%g", d);
135-
*this << ctl::string_view(temp, len);
141+
char buf[128];
142+
double_conversion::StringBuilder b(buf, sizeof(buf));
143+
kDoubleToPrintfG.ToShortest(d, &b);
144+
b.Finalize();
145+
*this << string_view(buf);
136146
}
137147
return *this;
138148
}

0 commit comments

Comments
 (0)