mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Add iostream to CTL
This commit is contained in:
parent
617ddfee93
commit
98e684622b
20 changed files with 1531 additions and 7 deletions
2
Makefile
2
Makefile
|
@ -256,7 +256,6 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
|
|||
include libc/proc/BUILD.mk # │ You can now use threads
|
||||
include libc/dlopen/BUILD.mk # │ You can now use processes
|
||||
include libc/thread/BUILD.mk # │ You can finally call malloc()
|
||||
include ctl/BUILD.mk # │
|
||||
include third_party/zlib/BUILD.mk # │
|
||||
include libc/stdio/BUILD.mk # │
|
||||
include tool/hello/BUILD.mk # │
|
||||
|
@ -285,6 +284,7 @@ include third_party/ncurses/BUILD.mk # │
|
|||
include third_party/readline/BUILD.mk # │
|
||||
include third_party/libunwind/BUILD.mk # |
|
||||
include third_party/libcxxabi/BUILD.mk # |
|
||||
include ctl/BUILD.mk # │
|
||||
include third_party/libcxx/BUILD.mk # │
|
||||
include third_party/openmp/BUILD.mk # │
|
||||
include third_party/double-conversion/BUILD.mk # │
|
||||
|
|
|
@ -18,7 +18,11 @@ CTL_A_CHECKS = \
|
|||
CTL_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
THIRD_PARTY_LIBUNWIND \
|
||||
|
||||
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
|
|
39
ctl/ios.cc
Normal file
39
ctl/ios.cc
Normal file
|
@ -0,0 +1,39 @@
|
|||
// -*- 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 "ios.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
ios::ios(FILE* file) : file_(file)
|
||||
{
|
||||
}
|
||||
|
||||
ios::~ios() = default;
|
||||
|
||||
ios&
|
||||
ios::operator=(ios&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
27
ctl/ios.h
Normal file
27
ctl/ios.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
// -*-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 CTL_IOS_H_
|
||||
#define CTL_IOS_H_
|
||||
#include "ios_base.h"
|
||||
|
||||
struct FILE;
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class ios : public ios_base
|
||||
{
|
||||
public:
|
||||
explicit ios(FILE*);
|
||||
virtual ~ios();
|
||||
|
||||
protected:
|
||||
ios& operator=(ios&&) noexcept;
|
||||
FILE* file_;
|
||||
|
||||
private:
|
||||
ios(const ios&) = delete;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IOS_H_
|
118
ctl/ios_base.cc
Normal file
118
ctl/ios_base.cc
Normal file
|
@ -0,0 +1,118 @@
|
|||
// -*- 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 "ios_base.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
ios_base::ios_base() : state_(goodbit), flags_(skipws | dec)
|
||||
{
|
||||
}
|
||||
|
||||
ios_base::~ios_base() = default;
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::flags() const
|
||||
{
|
||||
return static_cast<ios_base::fmtflags>(flags_);
|
||||
}
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::flags(fmtflags fmtfl)
|
||||
{
|
||||
int old = flags_;
|
||||
flags_ = fmtfl;
|
||||
return static_cast<ios_base::fmtflags>(old);
|
||||
}
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::setf(fmtflags fmtfl)
|
||||
{
|
||||
int old = flags_;
|
||||
flags_ |= fmtfl;
|
||||
return static_cast<ios_base::fmtflags>(old);
|
||||
}
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::setf(fmtflags fmtfl, fmtflags mask)
|
||||
{
|
||||
int old = flags_;
|
||||
flags_ = (flags_ & ~mask) | (fmtfl & mask);
|
||||
return static_cast<ios_base::fmtflags>(old);
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::unsetf(fmtflags mask)
|
||||
{
|
||||
flags_ &= ~mask;
|
||||
}
|
||||
|
||||
ios_base::iostate
|
||||
ios_base::rdstate() const
|
||||
{
|
||||
return static_cast<ios_base::iostate>(state_);
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::clear(int state)
|
||||
{
|
||||
state_ = state;
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::setstate(int state)
|
||||
{
|
||||
state_ |= state;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::good() const
|
||||
{
|
||||
return state_ == goodbit;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::eof() const
|
||||
{
|
||||
return (state_ & eofbit) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::fail() const
|
||||
{
|
||||
return (state_ & (failbit | badbit)) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::bad() const
|
||||
{
|
||||
return (state_ & badbit) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::operator!() const
|
||||
{
|
||||
return fail();
|
||||
}
|
||||
|
||||
ios_base::operator bool() const
|
||||
{
|
||||
return !fail();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
86
ctl/ios_base.h
Normal file
86
ctl/ios_base.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
// -*-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 CTL_IOS_BASE_H_
|
||||
#define CTL_IOS_BASE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class ios_base
|
||||
{
|
||||
public:
|
||||
typedef size_t streamsize;
|
||||
|
||||
enum iostate
|
||||
{
|
||||
goodbit = 0,
|
||||
badbit = 1,
|
||||
failbit = 2,
|
||||
eofbit = 4
|
||||
};
|
||||
|
||||
enum fmtflags
|
||||
{
|
||||
boolalpha = 1 << 0,
|
||||
dec = 1 << 1,
|
||||
fixed = 1 << 2,
|
||||
hex = 1 << 3,
|
||||
internal = 1 << 4,
|
||||
left = 1 << 5,
|
||||
oct = 1 << 6,
|
||||
right = 1 << 7,
|
||||
scientific = 1 << 8,
|
||||
showbase = 1 << 9,
|
||||
showpoint = 1 << 10,
|
||||
showpos = 1 << 11,
|
||||
skipws = 1 << 12,
|
||||
unitbuf = 1 << 13,
|
||||
uppercase = 1 << 14,
|
||||
adjustfield = left | right | internal,
|
||||
basefield = dec | oct | hex,
|
||||
floatfield = scientific | fixed
|
||||
};
|
||||
|
||||
enum openmode
|
||||
{
|
||||
app = 1 << 0,
|
||||
binary = 1 << 1,
|
||||
in = 1 << 2,
|
||||
out = 1 << 3,
|
||||
trunc = 1 << 4,
|
||||
ate = 1 << 5
|
||||
};
|
||||
|
||||
protected:
|
||||
ios_base();
|
||||
virtual ~ios_base();
|
||||
|
||||
int state_;
|
||||
int flags_;
|
||||
|
||||
public:
|
||||
fmtflags flags() const;
|
||||
fmtflags flags(fmtflags);
|
||||
fmtflags setf(fmtflags);
|
||||
fmtflags setf(fmtflags, fmtflags);
|
||||
void unsetf(fmtflags);
|
||||
|
||||
iostate rdstate() const;
|
||||
void clear(int = goodbit);
|
||||
void setstate(int);
|
||||
|
||||
bool good() const;
|
||||
bool eof() const;
|
||||
bool fail() const;
|
||||
bool bad() const;
|
||||
|
||||
bool operator!() const;
|
||||
explicit operator bool() const;
|
||||
|
||||
private:
|
||||
ios_base(const ios_base&) = delete;
|
||||
ios_base& operator=(const ios_base&) = delete;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IOS_BASE_H_
|
|
@ -2,7 +2,6 @@
|
|||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_CONVERTIBLE_H_
|
||||
#define CTL_IS_CONVERTIBLE_H_
|
||||
|
||||
#include "ctl/integral_constant.h"
|
||||
#include "ctl/void_t.h"
|
||||
|
||||
|
|
237
ctl/istream.cc
Normal file
237
ctl/istream.cc
Normal file
|
@ -0,0 +1,237 @@
|
|||
// -*- 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 "istream.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "numeric_limits.h"
|
||||
#include "string.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
istream cin(stdin);
|
||||
|
||||
istream::~istream() = default;
|
||||
|
||||
istream::istream(FILE* file) : ios(file), gcount_(0)
|
||||
{
|
||||
}
|
||||
|
||||
istream::istream(istream&& other) noexcept
|
||||
: ios(other.file_), gcount_(other.gcount_)
|
||||
{
|
||||
other.file_ = nullptr;
|
||||
other.gcount_ = 0;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator=(istream&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
ios::operator=(ctl::move(other));
|
||||
gcount_ = other.gcount_;
|
||||
other.gcount_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(char& c)
|
||||
{
|
||||
gcount_ = 0;
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit | failbit);
|
||||
} else {
|
||||
c = static_cast<char>(ch);
|
||||
gcount_ = 1;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(int& n)
|
||||
{
|
||||
if (fscanf(file_, "%d", &n) != 1)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(long& n)
|
||||
{
|
||||
if (fscanf(file_, "%ld", &n) != 1)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(double& d)
|
||||
{
|
||||
if (fscanf(file_, "%f", &d) != 1)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(ctl::string& s)
|
||||
{
|
||||
char buffer[1024];
|
||||
if (fscanf(file_, "%1023s", buffer) == 1) {
|
||||
s = buffer;
|
||||
} else {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(bool& b)
|
||||
{
|
||||
char buffer[6];
|
||||
if (fscanf(file_, "%5s", buffer) == 1) {
|
||||
if (strcmp(buffer, "true") == 0 || strcmp(buffer, "1") == 0) {
|
||||
b = true;
|
||||
} else if (strcmp(buffer, "false") == 0 || strcmp(buffer, "0") == 0) {
|
||||
b = false;
|
||||
} else {
|
||||
setstate(failbit);
|
||||
}
|
||||
} else {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(istream& (*manip)(istream&))
|
||||
{
|
||||
return manip(*this);
|
||||
}
|
||||
|
||||
int
|
||||
istream::get()
|
||||
{
|
||||
gcount_ = 0;
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit);
|
||||
} else {
|
||||
gcount_ = 1;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::get(char& c)
|
||||
{
|
||||
int ch = get();
|
||||
if (ch != EOF)
|
||||
c = static_cast<char>(ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::getline(char* s, streamsize n)
|
||||
{
|
||||
return getline(s, n, '\n');
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::getline(char* s, streamsize n, char delim)
|
||||
{
|
||||
gcount_ = 0;
|
||||
if (n <= 0) {
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
while (gcount_ < n - 1) {
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit);
|
||||
break;
|
||||
}
|
||||
if (ch == delim)
|
||||
break;
|
||||
s[gcount_++] = static_cast<char>(ch);
|
||||
}
|
||||
s[gcount_] = '\0';
|
||||
if (gcount_ == 0)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::read(char* s, streamsize n)
|
||||
{
|
||||
gcount_ = fread(s, 1, n, file_);
|
||||
if (gcount_ < n) {
|
||||
setstate(eofbit);
|
||||
if (gcount_ == 0)
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream::streamsize
|
||||
istream::gcount() const
|
||||
{
|
||||
return gcount_;
|
||||
}
|
||||
|
||||
int
|
||||
istream::peek()
|
||||
{
|
||||
int ch = fgetc(file_);
|
||||
if (ch != EOF) {
|
||||
ungetc(ch, file_);
|
||||
} else {
|
||||
setstate(eofbit);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::ignore(streamsize n, int delim)
|
||||
{
|
||||
gcount_ = 0;
|
||||
while (gcount_ < n) {
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit);
|
||||
break;
|
||||
}
|
||||
++gcount_;
|
||||
if (ch == delim)
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
ws(istream& is)
|
||||
{
|
||||
int ch;
|
||||
while ((ch = is.peek()) != EOF && isspace(ch))
|
||||
is.get();
|
||||
return is;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
53
ctl/istream.h
Normal file
53
ctl/istream.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
// -*-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 CTL_ISTREAM_H_
|
||||
#define CTL_ISTREAM_H_
|
||||
#include "ios.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string;
|
||||
|
||||
class istream : public ios
|
||||
{
|
||||
public:
|
||||
istream() = delete;
|
||||
explicit istream(FILE*);
|
||||
virtual ~istream();
|
||||
|
||||
istream& operator>>(char&);
|
||||
istream& operator>>(int&);
|
||||
istream& operator>>(long&);
|
||||
istream& operator>>(double&);
|
||||
istream& operator>>(bool&);
|
||||
istream& operator>>(string&);
|
||||
istream& operator>>(istream& (*)(istream&));
|
||||
|
||||
int get();
|
||||
istream& get(char&);
|
||||
istream& getline(char*, streamsize);
|
||||
istream& getline(char*, streamsize, char);
|
||||
istream& read(char*, streamsize);
|
||||
streamsize gcount() const;
|
||||
|
||||
int peek();
|
||||
istream& ignore(streamsize = 1, int = -1);
|
||||
|
||||
istream(istream&&) noexcept;
|
||||
istream& operator=(istream&&) noexcept;
|
||||
|
||||
private:
|
||||
streamsize gcount_;
|
||||
|
||||
istream(const istream&) = delete;
|
||||
istream& operator=(const istream&) = delete;
|
||||
};
|
||||
|
||||
extern istream cin;
|
||||
|
||||
istream&
|
||||
ws(istream& is);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ISTREAM_H_
|
221
ctl/istringstream.cc
Normal file
221
ctl/istringstream.cc
Normal file
|
@ -0,0 +1,221 @@
|
|||
// -*- 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 "istringstream.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
istringstream::istringstream() : buffer_(), read_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
istringstream::istringstream(const string_view& str)
|
||||
: buffer_(str), read_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
string
|
||||
istringstream::str() const
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
void
|
||||
istringstream::str(const string& s)
|
||||
{
|
||||
buffer_ = s;
|
||||
read_pos_ = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(char& c)
|
||||
{
|
||||
if (good() && read_pos_ < buffer_.size()) {
|
||||
c = buffer_[read_pos_++];
|
||||
} else {
|
||||
setstate(ios_base::failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(char* s)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
while (read_pos_ < buffer_.size() && isspace(buffer_[read_pos_]))
|
||||
++read_pos_;
|
||||
|
||||
size_t start = read_pos_;
|
||||
while (read_pos_ < buffer_.size() && !isspace(buffer_[read_pos_])) {
|
||||
s[read_pos_ - start] = buffer_[read_pos_];
|
||||
++read_pos_;
|
||||
}
|
||||
s[read_pos_ - start] = '\0';
|
||||
|
||||
if (start == read_pos_) {
|
||||
setstate(ios_base::failbit);
|
||||
} else if (read_pos_ == buffer_.size()) {
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(string& s)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
s.clear();
|
||||
while (read_pos_ < buffer_.size() && isspace(buffer_[read_pos_]))
|
||||
++read_pos_;
|
||||
|
||||
while (read_pos_ < buffer_.size() && !isspace(buffer_[read_pos_])) {
|
||||
s.push_back(buffer_[read_pos_]);
|
||||
++read_pos_;
|
||||
}
|
||||
|
||||
if (s.empty()) {
|
||||
setstate(ios_base::failbit);
|
||||
} else if (read_pos_ == buffer_.size()) {
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
istringstream&
|
||||
istringstream::read_numeric(T& value)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
while (read_pos_ < buffer_.size() && isspace(buffer_[read_pos_]))
|
||||
++read_pos_;
|
||||
|
||||
// size_t start = read_pos_;
|
||||
bool is_negative = false;
|
||||
if (read_pos_ < buffer_.size() &&
|
||||
(buffer_[read_pos_] == '-' || buffer_[read_pos_] == '+')) {
|
||||
is_negative = (buffer_[read_pos_] == '-');
|
||||
++read_pos_;
|
||||
}
|
||||
|
||||
T result = 0;
|
||||
bool valid = false;
|
||||
while (read_pos_ < buffer_.size() && isdigit(buffer_[read_pos_])) {
|
||||
result = result * 10 + (buffer_[read_pos_] - '0');
|
||||
++read_pos_;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
value = is_negative ? -result : result;
|
||||
if (read_pos_ == buffer_.size())
|
||||
setstate(ios_base::eofbit);
|
||||
} else {
|
||||
setstate(ios_base::failbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(short& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(unsigned short& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(int& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(unsigned int& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(long& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(unsigned long& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(float& f)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
char* end;
|
||||
f = strtof(buffer_.c_str() + read_pos_, &end);
|
||||
|
||||
if (end == buffer_.c_str() + read_pos_) {
|
||||
setstate(ios_base::failbit);
|
||||
} else {
|
||||
read_pos_ = end - buffer_.c_str();
|
||||
if (read_pos_ == buffer_.size())
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(double& d)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
char* end;
|
||||
d = strtod(buffer_.c_str() + read_pos_, &end);
|
||||
|
||||
if (end == buffer_.c_str() + read_pos_) {
|
||||
setstate(ios_base::failbit);
|
||||
} else {
|
||||
read_pos_ = end - buffer_.c_str();
|
||||
if (read_pos_ == buffer_.size())
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
41
ctl/istringstream.h
Normal file
41
ctl/istringstream.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
// -*-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 CTL_ISTRINGSTREAM_H_
|
||||
#define CTL_ISTRINGSTREAM_H_
|
||||
#include "ios_base.h"
|
||||
#include "string.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class istringstream : public ios_base
|
||||
{
|
||||
public:
|
||||
istringstream();
|
||||
explicit istringstream(const string_view&);
|
||||
|
||||
string str() const;
|
||||
void str(const string&);
|
||||
|
||||
istringstream& operator>>(char&);
|
||||
istringstream& operator>>(char*);
|
||||
istringstream& operator>>(string&);
|
||||
istringstream& operator>>(short&);
|
||||
istringstream& operator>>(unsigned short&);
|
||||
istringstream& operator>>(int&);
|
||||
istringstream& operator>>(unsigned int&);
|
||||
istringstream& operator>>(long&);
|
||||
istringstream& operator>>(unsigned long&);
|
||||
istringstream& operator>>(float&);
|
||||
istringstream& operator>>(double&);
|
||||
|
||||
private:
|
||||
string buffer_;
|
||||
size_t read_pos_;
|
||||
|
||||
template<typename T>
|
||||
istringstream& read_numeric(T&);
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ISTRINGSTREAM_H_
|
166
ctl/ostream.cc
Normal file
166
ctl/ostream.cc
Normal file
|
@ -0,0 +1,166 @@
|
|||
// -*- 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 "ostream.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "string_view.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
ostream cout(stdout);
|
||||
ostream cerr(stderr);
|
||||
|
||||
ostream::~ostream() = default;
|
||||
|
||||
ostream::ostream(FILE* file) : ios(file)
|
||||
{
|
||||
}
|
||||
|
||||
ostream::ostream(ostream&& other) noexcept : ios(other.file_)
|
||||
{
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator=(ostream&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(const char* str)
|
||||
{
|
||||
if (good() && str)
|
||||
if (fprintf(file_, "%s", str) < 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(char c)
|
||||
{
|
||||
if (good())
|
||||
if (fputc(c, file_) == EOF)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(int n)
|
||||
{
|
||||
if (good())
|
||||
if (fprintf(file_, "%d", n) < 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(long n)
|
||||
{
|
||||
if (good())
|
||||
if (fprintf(file_, "%ld", n) < 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(double d)
|
||||
{
|
||||
if (good())
|
||||
if (fprintf(file_, "%f", d) < 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(const string_view& s)
|
||||
{
|
||||
if (good())
|
||||
if (fprintf(file_, "%.*s", (int)s.size(), s.data()) < 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(bool b)
|
||||
{
|
||||
if (good()) {
|
||||
const char* value =
|
||||
(flags() & boolalpha) ? (b ? "true" : "false") : (b ? "1" : "0");
|
||||
if (fprintf(file_, "%s", value) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(ostream& (*manip)(ostream&))
|
||||
{
|
||||
return manip(*this);
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::put(char c)
|
||||
{
|
||||
if (good())
|
||||
if (fputc(c, file_) == EOF)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::write(const char* s, streamsize n)
|
||||
{
|
||||
if (good())
|
||||
if (fwrite(s, 1, n, file_) != static_cast<size_t>(n))
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::flush()
|
||||
{
|
||||
if (good())
|
||||
if (fflush(file_) != 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
endl(ostream& os)
|
||||
{
|
||||
return os.put('\n').flush();
|
||||
}
|
||||
|
||||
ostream&
|
||||
ends(ostream& os)
|
||||
{
|
||||
return os.put('\0');
|
||||
}
|
||||
|
||||
ostream&
|
||||
flush(ostream& os)
|
||||
{
|
||||
return os.flush();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
53
ctl/ostream.h
Normal file
53
ctl/ostream.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
// -*-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 CTL_OSTREAM_H_
|
||||
#define CTL_OSTREAM_H_
|
||||
#include "ios.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string_view;
|
||||
|
||||
class ostream : public ios
|
||||
{
|
||||
public:
|
||||
ostream() = delete;
|
||||
explicit ostream(FILE*);
|
||||
virtual ~ostream();
|
||||
|
||||
ostream& operator<<(const char*);
|
||||
ostream& operator<<(char);
|
||||
ostream& operator<<(int);
|
||||
ostream& operator<<(long);
|
||||
ostream& operator<<(double);
|
||||
ostream& operator<<(const string_view&);
|
||||
ostream& operator<<(bool);
|
||||
ostream& operator<<(ostream& (*)(ostream&));
|
||||
|
||||
ostream& put(char);
|
||||
ostream& write(const char*, streamsize);
|
||||
ostream& flush();
|
||||
|
||||
ostream(ostream&&) noexcept;
|
||||
ostream& operator=(ostream&&) noexcept;
|
||||
|
||||
private:
|
||||
ostream(const ostream&) = delete;
|
||||
ostream& operator=(const ostream&) = delete;
|
||||
};
|
||||
|
||||
extern ostream cout;
|
||||
extern ostream cerr;
|
||||
|
||||
ostream&
|
||||
endl(ostream&);
|
||||
|
||||
ostream&
|
||||
ends(ostream&);
|
||||
|
||||
ostream&
|
||||
flush(ostream&);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OSTREAM_H_
|
140
ctl/ostringstream.cc
Normal file
140
ctl/ostringstream.cc
Normal file
|
@ -0,0 +1,140 @@
|
|||
// -*- 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 "ostringstream.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
ostringstream::ostringstream() : buffer_(), write_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ostringstream::ostringstream(const string_view& str)
|
||||
: buffer_(str), write_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
string
|
||||
ostringstream::str() const
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
void
|
||||
ostringstream::str(const string& s)
|
||||
{
|
||||
buffer_ = s;
|
||||
write_pos_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ostringstream::clear()
|
||||
{
|
||||
ios_base::clear();
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(char c)
|
||||
{
|
||||
if (good()) {
|
||||
if (write_pos_ < buffer_.size()) {
|
||||
buffer_[write_pos_++] = c;
|
||||
} else {
|
||||
buffer_.push_back(c);
|
||||
++write_pos_;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(const string_view& s)
|
||||
{
|
||||
if (good()) {
|
||||
if (write_pos_ + s.size() <= buffer_.size()) {
|
||||
buffer_.replace(write_pos_, s.size(), s);
|
||||
} else {
|
||||
buffer_.replace(write_pos_, buffer_.size() - write_pos_, s);
|
||||
buffer_.append(s.substr(buffer_.size() - write_pos_));
|
||||
}
|
||||
write_pos_ += s.size();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(int n)
|
||||
{
|
||||
char temp[12];
|
||||
if (good())
|
||||
*this << string_view(temp, FormatInt32(temp, n) - temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(unsigned int n)
|
||||
{
|
||||
char temp[12];
|
||||
if (good())
|
||||
*this << string_view(temp, FormatUint32(temp, n) - temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(long n)
|
||||
{
|
||||
char temp[21];
|
||||
if (good())
|
||||
*this << string_view(temp, FormatInt64(temp, n) - temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(unsigned long n)
|
||||
{
|
||||
char temp[21];
|
||||
if (good())
|
||||
*this << string_view(temp, FormatUint64(temp, n) - temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(float f)
|
||||
{
|
||||
if (good()) {
|
||||
char temp[32];
|
||||
int len = snprintf(temp, sizeof(temp), "%g", f);
|
||||
*this << string_view(temp, len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(double d)
|
||||
{
|
||||
if (good()) {
|
||||
char temp[32];
|
||||
int len = snprintf(temp, sizeof(temp), "%g", d);
|
||||
*this << string_view(temp, len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
36
ctl/ostringstream.h
Normal file
36
ctl/ostringstream.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
// -*-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 CTL_OSTRINGSTREAM_H_
|
||||
#define CTL_OSTRINGSTREAM_H_
|
||||
#include "ios_base.h"
|
||||
#include "string.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class ostringstream : public ios_base
|
||||
{
|
||||
public:
|
||||
ostringstream();
|
||||
explicit ostringstream(const string_view&);
|
||||
|
||||
string str() const;
|
||||
void str(const string& s);
|
||||
void clear();
|
||||
|
||||
ostringstream& operator<<(char);
|
||||
ostringstream& operator<<(const string_view&);
|
||||
ostringstream& operator<<(int);
|
||||
ostringstream& operator<<(unsigned int);
|
||||
ostringstream& operator<<(long);
|
||||
ostringstream& operator<<(unsigned long);
|
||||
ostringstream& operator<<(float);
|
||||
ostringstream& operator<<(double);
|
||||
|
||||
private:
|
||||
string buffer_;
|
||||
size_t write_pos_;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OSTRINGSTREAM_H_
|
|
@ -1,7 +1,7 @@
|
|||
// -*-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_UTILITY_H_
|
||||
#define COSMOPOLITAN_CTL_UTILITY_H_
|
||||
#ifndef CTL_UTILITY_H_
|
||||
#define CTL_UTILITY_H_
|
||||
#include "remove_reference.h"
|
||||
|
||||
namespace ctl {
|
||||
|
@ -66,4 +66,4 @@ declval() noexcept;
|
|||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_UTILITY_H_
|
||||
#endif // CTL_UTILITY_H_
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#define SYSDEBUG 0
|
||||
#endif
|
||||
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _LOCKTRACE 0 /* not configurable w/ flag yet */
|
||||
|
|
|
@ -14,10 +14,11 @@ TEST_CTL_TESTS = $(TEST_CTL_COMS:%=%.ok)
|
|||
TEST_CTL_DIRECTDEPS = \
|
||||
CTL \
|
||||
LIBC_CALLS \
|
||||
LIBC_STDIO \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_STDIO \
|
||||
LIBC_STDIO \
|
||||
LIBC_THREAD \
|
||||
THIRD_PARTY_LIBCXX \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
|
|
163
test/ctl/istringstream_test.cc
Normal file
163
test/ctl/istringstream_test.cc
Normal file
|
@ -0,0 +1,163 @@
|
|||
// -*- 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/istringstream.h"
|
||||
#include "libc/mem/leaks.h"
|
||||
|
||||
// #include <sstream>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
// Test default constructor
|
||||
{
|
||||
ctl::istringstream iss;
|
||||
if (iss.eof())
|
||||
return 1;
|
||||
if (!iss.good())
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test constructor with initial string
|
||||
{
|
||||
ctl::istringstream iss("Hello, world!");
|
||||
if (iss.str() != "Hello, world!")
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Test reading a char
|
||||
{
|
||||
ctl::istringstream iss("A");
|
||||
char c;
|
||||
iss >> c;
|
||||
if (c != 'A' || !iss.good())
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Test reading a string
|
||||
{
|
||||
ctl::istringstream iss("Hello World");
|
||||
ctl::string s;
|
||||
iss >> s;
|
||||
if (s != "Hello" || !iss.good())
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Test reading multiple strings
|
||||
{
|
||||
ctl::istringstream iss("One Two Three");
|
||||
ctl::string s1, s2, s3;
|
||||
iss >> s1 >> s2 >> s3;
|
||||
if (s1 != "One" || s2 != "Two" || s3 != "Three" || iss.good() ||
|
||||
!iss.eof())
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Test reading integers
|
||||
{
|
||||
ctl::istringstream iss("123 -456 789");
|
||||
int a, b, c;
|
||||
iss >> a >> b >> c;
|
||||
if (a != 123 || b != -456 || c != 789 || iss.good() || !iss.eof())
|
||||
return 6;
|
||||
}
|
||||
|
||||
// Test reading floating-point numbers
|
||||
{
|
||||
ctl::istringstream iss("3.14 -2.718");
|
||||
float f;
|
||||
double d;
|
||||
iss >> f >> d;
|
||||
if (f != 3.14f || d != -2.718 || iss.good() || !iss.eof())
|
||||
return 7;
|
||||
}
|
||||
|
||||
// Test reading past the end of the stream
|
||||
{
|
||||
ctl::istringstream iss("42");
|
||||
int n;
|
||||
iss >> n;
|
||||
if (n != 42 || iss.good() || !iss.eof())
|
||||
return 8;
|
||||
iss >> n;
|
||||
if (iss.good())
|
||||
return 9;
|
||||
if (!iss.eof())
|
||||
return 10;
|
||||
}
|
||||
|
||||
// Test reading invalid data
|
||||
{
|
||||
ctl::istringstream iss("not_a_number");
|
||||
int n;
|
||||
iss >> n;
|
||||
if (iss.good() || !iss.fail())
|
||||
return 11;
|
||||
}
|
||||
|
||||
// Test str() setter
|
||||
{
|
||||
ctl::istringstream iss;
|
||||
iss.str("New content");
|
||||
if (iss.str() != "New content" || !iss.good())
|
||||
return 12;
|
||||
}
|
||||
|
||||
// Test reading after setting a new string
|
||||
{
|
||||
ctl::istringstream iss("Old content");
|
||||
iss.str("New content");
|
||||
ctl::string s;
|
||||
iss >> s;
|
||||
if (s != "New" || !iss.good())
|
||||
return 13;
|
||||
}
|
||||
|
||||
// Test reading a mixture of types
|
||||
{
|
||||
ctl::istringstream iss("42 3.14 Hello");
|
||||
int i;
|
||||
double d;
|
||||
ctl::string s;
|
||||
iss >> i >> d >> s;
|
||||
if (i != 42 || d != 3.14 || s != "Hello" || iss.good() || !iss.eof())
|
||||
return 14;
|
||||
}
|
||||
|
||||
// Test reading with leading whitespace
|
||||
{
|
||||
ctl::istringstream iss(" 42");
|
||||
int n;
|
||||
iss >> n;
|
||||
if (n != 42 || iss.good() || !iss.eof())
|
||||
return 15;
|
||||
}
|
||||
|
||||
// Test clear() only affects error state, not content
|
||||
{
|
||||
ctl::istringstream iss("Test");
|
||||
iss.setstate(ctl::ios_base::failbit);
|
||||
iss.clear();
|
||||
if (!iss.good() || iss.str() != "Test")
|
||||
return 16;
|
||||
}
|
||||
|
||||
CheckForMemoryLeaks();
|
||||
}
|
140
test/ctl/ostringstream_test.cc
Normal file
140
test/ctl/ostringstream_test.cc
Normal file
|
@ -0,0 +1,140 @@
|
|||
// -*- 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/ostringstream.h"
|
||||
#include "libc/mem/leaks.h"
|
||||
|
||||
// #include <sstream>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
// Test default constructor and basic string insertion
|
||||
{
|
||||
ctl::ostringstream oss;
|
||||
oss << "Hello, world!";
|
||||
if (oss.str() != "Hello, world!")
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test constructor with initial string (overwrite mode)
|
||||
{
|
||||
ctl::ostringstream oss("Initial content");
|
||||
oss << "New";
|
||||
if (oss.str() != "Newtial content")
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Test overwrite and append behavior
|
||||
{
|
||||
ctl::ostringstream oss("Hello, world!");
|
||||
oss << "Hi";
|
||||
if (oss.str() != "Hillo, world!")
|
||||
return 3;
|
||||
oss << " Earth";
|
||||
if (oss.str() != "Hi Earthorld!")
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Test multiple insertions of different types
|
||||
{
|
||||
ctl::ostringstream oss;
|
||||
oss << "Int: " << 42 << ", Float: " << 3.14f << ", Double: " << 2.718;
|
||||
if (oss.str() != "Int: 42, Float: 3.14, Double: 2.718")
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Test char insertion
|
||||
{
|
||||
ctl::ostringstream oss("ABCDEF");
|
||||
oss << 'X' << 'Y' << 'Z';
|
||||
if (oss.str() != "XYZDEF")
|
||||
return 6;
|
||||
}
|
||||
|
||||
// Test unsigned types
|
||||
{
|
||||
ctl::ostringstream oss("Numbers: ");
|
||||
unsigned int ui = 12345;
|
||||
unsigned long ul = 67890UL;
|
||||
oss << ui << " " << ul;
|
||||
if (oss.str() != "12345 67890")
|
||||
return 7;
|
||||
}
|
||||
|
||||
// Test long type
|
||||
{
|
||||
ctl::ostringstream oss("Long: ");
|
||||
long l = -9876543210L;
|
||||
oss << l;
|
||||
if (oss.str() != "-9876543210")
|
||||
return 8;
|
||||
}
|
||||
|
||||
// Test clear() method
|
||||
{
|
||||
ctl::ostringstream oss("not that kind of clear");
|
||||
oss.clear();
|
||||
if (!oss.good() || oss.str() != "not that kind of clear")
|
||||
return 9;
|
||||
}
|
||||
|
||||
// Test str() setter method
|
||||
{
|
||||
ctl::ostringstream oss;
|
||||
oss.str("New content");
|
||||
oss << "Old";
|
||||
if (oss.str() != "Old content")
|
||||
return 10;
|
||||
}
|
||||
|
||||
// Test chaining of insertion operators
|
||||
{
|
||||
ctl::ostringstream oss("Start: ");
|
||||
oss << "Chain " << 1 << " " << 2.0 << " " << 'Z';
|
||||
if (oss.str() != "Chain 1 2 Z")
|
||||
return 11;
|
||||
}
|
||||
|
||||
// Test insertion when stream is not in good state
|
||||
{
|
||||
ctl::ostringstream oss("Original");
|
||||
oss.setstate(ctl::ios_base::failbit);
|
||||
oss << "This should not be inserted";
|
||||
if (oss.str() != "Original")
|
||||
return 12;
|
||||
}
|
||||
|
||||
// Test with larger amounts of data
|
||||
{
|
||||
ctl::ostringstream oss("Prefix: ");
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
oss << "Line " << i << "\n";
|
||||
}
|
||||
ctl::string result = oss.str();
|
||||
if (result.substr(0, 14) != "Line 0\nLine 1\n")
|
||||
return 13;
|
||||
if (result.substr(result.length() - 8) != "ine 999\n")
|
||||
return 14;
|
||||
}
|
||||
|
||||
CheckForMemoryLeaks();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue