Compare commits

...
51 Commits
Author SHA1 Message Date
Justine Tunney 7996bf67b5 Release Cosmopolitan v3.5.7 2024-07-20 03:48:57 -07:00
Justine Tunney 626a5d02ee Add missing lock statement 2024-07-20 03:47:22 -07:00
Justine Tunney 527aaa41eb Prevent MODE=tiny ShowCrashReports() looping 2024-07-20 03:34:37 -07:00
Justine Tunney 421a819d88 Fix bug in munmap_test 2024-07-20 03:23:37 -07:00
Justine Tunney 3374cbba73 Release Cosmopolitan v3.5.6 2024-07-20 02:43:10 -07:00
Justine Tunney 2018cac11f Use better memory strategy on Windows
Rather than using the the rollo global to pick addresses, we select them
randomly now using a conservative vaspace.
2024-07-20 02:20:03 -07:00
Justine Tunney 6a5d4ed65b Fix bug with disabling sigaltstack() 2024-07-20 01:00:16 -07:00
Justine Tunney 493ffc9b7f Release Cosmopolitan v3.5.5 2024-07-19 22:33:17 -07:00
Justine Tunney 101fb3d9b3 Make some new Windows 10 memory APIs available 2024-07-19 22:26:49 -07:00
Justine Tunney f6ba270ff3 Add last commit to .git-blame-ignore-revs 2024-07-19 19:38:53 -07:00
Justine Tunney 86d884cce2 Get rid of .internal.h convention in LIBC_INTRIN 2024-07-19 19:38:00 -07:00
Justine Tunney 0ed916ad5c Fix a bug in example code 2024-07-19 19:11:28 -07:00
Justine Tunney 1029dcc597 Reduce default stack size from 256kb to 81kb
This is the same as Musl Libc. Please note it only applies to threads.
2024-07-19 14:18:06 -07:00
Ikko Eltociear Ashimine c697133a2d Fix typo in accept4-sysv.c (#1235) 2024-07-19 05:46:29 -07:00
Justine Tunney 1ff037df3c Add some documentation 2024-07-19 04:46:26 -07:00
Justine Tunney 567d8fe32d Create variables for page size 2024-07-18 21:16:53 -07:00
Justine Tunney 23dfb79d33 Fix minor suboptimalities in memory manager 2024-07-18 19:19:51 -07:00
Justine Tunney 76cea6c687 Squeeze more performance out of memory manager 2024-07-08 03:08:42 -07:00
Justine Tunney 63065cdd70 Make a test less intensive by default 2024-07-07 19:35:09 -07:00
Justine Tunney 3f2a1b696e Fix greenbean example
The memory leak detector was crashing. When using gc() you shouldn't use
the CheckForMemoryLeaks() function from inside the same function, due to
how it runs the atexit handlers.
2024-07-07 17:52:33 -07:00
Justine Tunney f590e96abd Work around QEMU bugs 2024-07-07 15:42:46 -07:00
Justine Tunney f7780de24b Make realloc() go 100x faster on Linux/NetBSD
Cosmopolitan now supports mremap(), which is only supported on Linux and
NetBSD. First, it allows memory mappings to be relocated without copying
them; this can dramatically speed up data structures like std::vector if
the array size grows larger than 256kb. The mremap() system call is also
10x faster than munmap() when shrinking large memory mappings.

There's now two functions, getpagesize() and getgransize() which help to
write portable code that uses mmap(MAP_FIXED). Alternative sysconf() may
be called with our new _SC_GRANSIZE. The madvise() system call now has a
better wrapper with improved documentation.
2024-07-07 12:40:30 -07:00
Justine Tunney 196942084b Recomment out accidental code 2024-07-06 19:57:47 -07:00
Justine Tunney 6be030cd7c Fix MODE=tinylinux build 2024-07-06 01:51:08 -07:00
Justine Tunney 8c645fa1ee Make mmap() scalable
It's now possible to create thousands of thousands of sparse independent
memory mappings, without any slowdown. The memory manager is better with
tracking memory protection now, particularly on Windows in a precise way
that can be restored during fork(). You now have the highest quality mem
manager possible. It's even better than some OSes like XNU, where mmap()
is implemented as an O(n) operation which means sadly things aren't much
improved over there. With this change the llamafile HTTP server endpoint
at /tokenize with a prompt of 50 tokens is now able to handle 2.6m r/sec
2024-07-05 23:26:00 -07:00
Justine Tunney 3756870635 Implement new red-black tree 2024-07-05 12:56:03 -07:00
Justine Tunney fc65422660 Remove __mmap() and __munmap() 2024-07-05 12:55:46 -07:00
Justine Tunney 01587de761 Simplify memory manager 2024-07-05 05:47:15 -07:00
Justine Tunney 5a9a08d1cf Fix regression in elf2pe program 2024-07-04 04:02:20 -07:00
Justine Tunney bd6d9ff99a Get deathstar demo working again on metal 2024-07-04 03:44:17 -07:00
Justine Tunney 15ea0524b3 Reduce code size of mandatory runtime
This change reduces o/tiny/examples/life from 44kb to 24kb in size since
it avoids linking mmap() when unnecessary. This is important, to helping
cosmo not completely lose touch with its roots.
2024-07-04 02:50:20 -07:00
Justine Tunney fdab49b30e Demonstrate signal safety of recursive mutexes 2024-07-04 02:47:52 -07:00
Justine Tunney 135d538b1d Make ctl::set use 30% less memory than libcxx 2024-07-04 02:46:27 -07:00
Justine Tunney 6dbc3fba18 Add AMD cache sizes to o//tool/viz/cpuid 2024-07-04 02:45:45 -07:00
Justine Tunney 70f77aad33 Release Cosmopolitan v3.5.4 2024-07-01 07:17:57 -07:00
Justine Tunney d0cd719375 Make more CTL fixes 2024-07-01 07:17:57 -07:00
Justine Tunney 61370983e1 Complete the Windows TLS fix made in e437bed00 2024-07-01 07:17:57 -07:00
Terror 72511ff0ac [Redbean] Add UuidV7 method (#1213)
To Complete #1140 add UUID version 7 to Redbean
2024-07-01 06:06:56 -07:00
Justine Tunney c1f8d0678c Mark ctl::to_string() noexcept 2024-07-01 05:54:59 -07:00
Justine Tunney e627bfa359 Introduce ctl::to_string() 2024-07-01 05:40:38 -07:00
Justine Tunney acbabedf27 Make CTL definitions less ambiguous 2024-07-01 03:48:28 -07:00
Justine Tunney 239f8ce76e Release Cosmopolitan v3.5.3 2024-07-01 02:07:56 -07:00
Justine Tunney ca4cf67eb8 Include more programs in cosmocc
The Cosmopolitan Compiler Collection now includes the following programs

- `ar.ape` is a faster alternative to `ar rcsD` for creating determistic
  static archives. It's ~10x faster than GNU because it isn't quadratic.
  It'll even outperform LLVM ar by 2x, thanks to writev/copy_file_range.

- `sha256sum.ape` is a faster alternative to the `sha256sum` command. It
  goes 2x faster since it leverages vectorized assembly implementations.

- `resymbol` is a brand new program we invented, like objcopy, that lets
  you rename all the global symbols in a .o file to have a new suffix or
  prefix. In the future, this will be used by cosmocc automatically when
  building -O3 math kernels, that need to be vectorized for all hardware

- `gzip.ape` is a faster version of the `gzip` command, that is included
  by most Linux distros. It gains better performance using Chromium Zlib
  which, once again, includes highly optimized assembly, that Mark Adler
  won't merge into the official MS-DOS compatible zlib codebase.

- `cocmd` is the cosmopolitan shell. It can function as a faster `sh -c`
  alternative than bash and dash as the `SHELL = /opt/cosmocc/bin/cocmd`
  at the top of your Makefile. Please note you should be using the cosmo
  fork of GNU make (already included), since normal make won't recognize
  this as a bourne-compatible shell and remove the execve() optimization
  which makes things slower. In some ways that's true. This doesn't have
  a complete POSIX shell implementation. However it's enough for cosmo's
  mono repo. It also implements faster behaviors in some respects.

The following programs are also introduced, which aren't as interesting.
The main reason why they're here is so Cosmopolitan's mono repo shall be
able to remove build/bootstrap/ in future editions. That way we can keep
build utilities better up to date, without bloating the git history much

- `chmod.ape` for hermeticity
- `cp.ape` for hermeticity
- `echo.ape` for hermeticity
- `objbincopy` is an objcopy-like tool that's used to build ape loader
- `package.ape` is used for strict dependency checking of object graph
- `rm.ape` for hermeticity
- `touch.ape` for hermeticity
2024-07-01 02:05:25 -07:00
Justine Tunney 78d3b86ec7 Fix Android support
Thanks to @aj47 (techfren.net) the new Cosmo memory manager is confirmed
to be working on Android!! The only issue turned out to be forgetting to
update the program address in the linker script. We now know w/ absolute
certainty that APE binaries as complex as llamafile, now work correctly.
2024-07-01 01:06:47 -07:00
Justine Tunney 44191b3f50 Add more type traits to CTL 2024-06-30 20:59:38 -07:00
Justine Tunney e437bed006 Fix crash caused when Windows needs a lot of TLS 2024-06-30 20:53:43 -07:00
Justine Tunney 76957983cf Make POSIX threads improvements
- Ensure SIGTHR isn't blocked in newly created threads
- Use TIB rather than thread_local for thread atexits
- Make POSIX thread keys atomic within thread
- Don't bother logging prctl() to --strace
- Log thread destructor names to --strace
2024-06-30 15:38:59 -07:00
Justine Tunney 387310c659 Fix issue with ctl::vector constructor 2024-06-30 02:26:38 -07:00
Justine Tunney 4cb5e21ba8 Introduce pthread_decimate_np() api
This is useful with CheckForMemoryLeaks().
2024-06-30 02:26:06 -07:00
Justine Tunney 1bf2d8e308 Further improve mmap() locking story
The way to use double linked lists, is to remove all the things you want
to work on, insert them into a new list on the stack. Then once you have
all the work items, you release the lock, do your work, and then lock it
again, to add the shelled out items back to a global freelist.
2024-06-29 17:12:43 -07:00
Justine Tunney 98e684622b Add iostream to CTL 2024-06-29 15:45:09 -07:00
785 changed files with 7375 additions and 3058 deletions

No files matched your search

+2
View File
@@ -25,3 +25,5 @@ c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
da8baf2aa5ce93b958aca90a0ae69f537806324b
# Run clang-format on most sources
369f9740de4534c28d0e81ab2afc99decbb9a3e6
# Get rid of .internal.h convention in LIBC_INTRIN
86d884cce24d773e298a2714c1e3d91ecab9be45
+2 -2
View File
@@ -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,9 +284,10 @@ 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 third_party/double-conversion/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 # │
include third_party/pcre/BUILD.mk # │
include third_party/less/BUILD.mk # │
include net/https/BUILD.mk # │
+1 -1
View File
@@ -12,7 +12,7 @@ OUTPUT_FORMAT("elf64-littleaarch64",
SECTIONS {
. = SEGMENT_START("text-segment", 0x010000000000);
. = SEGMENT_START("text-segment", 0x000800000000);
__executable_start = .;
. += SIZEOF_HEADERS;
Binary file not shown.
+6
View File
@@ -18,7 +18,13 @@ CTL_A_CHECKS = \
CTL_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_STDIO \
LIBC_STR \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
+20 -24
View File
@@ -11,59 +11,55 @@ struct allocator_traits
{
using allocator_type = Alloc;
using value_type = typename Alloc::value_type;
using pointer = typename Alloc::pointer;
using const_pointer = typename Alloc::const_pointer;
using pointer = typename Alloc::value_type*;
using const_pointer = const typename Alloc::value_type*;
using void_pointer = void*;
using const_void_pointer = const void*;
using difference_type = typename Alloc::difference_type;
using size_type = typename Alloc::size_type;
using difference_type = ptrdiff_t;
using size_type = size_t;
using propagate_on_container_copy_assignment = false_type;
using propagate_on_container_move_assignment = true_type;
using propagate_on_container_swap = false_type;
using is_always_equal = true_type;
using propagate_on_container_copy_assignment = ctl::false_type;
using propagate_on_container_move_assignment = ctl::true_type;
using propagate_on_container_swap = ctl::false_type;
using is_always_equal = ctl::true_type;
template<typename T>
using rebind_alloc = typename Alloc::template rebind<T>::other;
struct rebind_alloc
{
using other = typename Alloc::template rebind<T>::other;
};
template<typename T>
using rebind_traits = allocator_traits<rebind_alloc<T>>;
using rebind_traits = allocator_traits<typename rebind_alloc<T>::other>;
__attribute__((__always_inline__)) static pointer allocate(Alloc& a,
size_type n)
static pointer allocate(Alloc& a, size_type n)
{
return a.allocate(n);
}
__attribute__((__always_inline__)) static void deallocate(Alloc& a,
pointer p,
size_type n)
static void deallocate(Alloc& a, pointer p, size_type n)
{
a.deallocate(p, n);
}
template<typename T, typename... Args>
__attribute__((__always_inline__)) static void construct(Alloc& a,
T* p,
Args&&... args)
static void construct(Alloc& a, T* p, Args&&... args)
{
::new ((void*)p) T(static_cast<Args&&>(args)...);
}
template<typename T>
__attribute__((__always_inline__)) static void destroy(Alloc& a, T* p)
static void destroy(Alloc& a, T* p)
{
p->~T();
}
__attribute__((__always_inline__)) static size_type max_size(
const Alloc& a) noexcept
static size_type max_size(const Alloc& a) noexcept
{
return __PTRDIFF_MAX__ / sizeof(value_type);
return a.max_size();
}
__attribute__((__always_inline__)) static Alloc
select_on_container_copy_construction(const Alloc& a)
static Alloc select_on_container_copy_construction(const Alloc& a)
{
return a;
}
+6 -2
View File
@@ -37,24 +37,28 @@ struct array
constexpr reference at(size_type pos)
{
if (pos >= N)
throw ctl::out_of_range("out of range");
throw ctl::out_of_range();
return elems[pos];
}
constexpr const_reference at(size_type pos) const
{
if (pos >= N)
throw ctl::out_of_range("out of range");
throw ctl::out_of_range();
return elems[pos];
}
constexpr reference operator[](size_type pos)
{
if (pos >= N)
__builtin_trap();
return elems[pos];
}
constexpr const_reference operator[](size_type pos) const
{
if (pos >= N)
__builtin_trap();
return elems[pos];
}
+1 -1
View File
@@ -6,7 +6,7 @@
namespace ctl {
class bad_alloc : public exception
class bad_alloc : public ctl::exception
{
public:
bad_alloc() noexcept = default;
+8 -7
View File
@@ -16,15 +16,16 @@ template<typename T>
struct decay
{
private:
typedef typename remove_reference<T>::type U;
typedef typename ctl::remove_reference<T>::type U;
public:
typedef typename conditional<
is_array<U>::value,
typename remove_extent<U>::type*,
typename conditional<is_function<U>::value,
typename add_pointer<U>::type,
typename remove_cv<U>::type>::type>::type type;
typedef typename ctl::conditional<
ctl::is_array<U>::value,
typename ctl::remove_extent<U>::type*,
typename ctl::conditional<ctl::is_function<U>::value,
typename ctl::add_pointer<U>::type,
typename ctl::remove_cv<U>::type>::type>::type
type;
};
template<typename T>
+7 -5
View File
@@ -8,28 +8,30 @@
namespace ctl {
template<class InputIter>
constexpr typename iterator_traits<InputIter>::difference_type
constexpr typename ctl::iterator_traits<InputIter>::difference_type
distance_impl(InputIter first, InputIter last, input_iterator_tag)
{
typename iterator_traits<InputIter>::difference_type res(0);
typename ctl::iterator_traits<InputIter>::difference_type res(0);
for (; first != last; ++first)
++res;
return res;
}
template<class RandIter>
constexpr typename iterator_traits<RandIter>::difference_type
constexpr typename ctl::iterator_traits<RandIter>::difference_type
distance_impl(RandIter first, RandIter last, random_access_iterator_tag)
{
return last - first;
}
template<class InputIter>
constexpr typename iterator_traits<InputIter>::difference_type
constexpr typename ctl::iterator_traits<InputIter>::difference_type
distance(InputIter first, InputIter last)
{
return distance_impl(
first, last, typename iterator_traits<InputIter>::iterator_category());
first,
last,
typename ctl::iterator_traits<InputIter>::iterator_category());
}
} // namespace ctl
+35
View 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
View 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_
+2
View File
@@ -11,10 +11,12 @@ struct integral_constant
static constexpr T value = v;
typedef T value_type;
typedef integral_constant type;
constexpr operator value_type() const noexcept
{
return value;
}
constexpr value_type operator()() const noexcept
{
return value;
+39
View 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
View 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
View 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
View 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_
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_ABSTRACT_H_
#define CTL_IS_ABSTRACT_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_abstract : public ctl::integral_constant<bool, __is_abstract(T)>
{};
template<typename T>
inline constexpr bool is_abstract_v = __is_abstract(T);
} // namespace ctl
#endif // CTL_IS_ABSTRACT_H_
+3 -3
View File
@@ -7,15 +7,15 @@
namespace ctl {
template<typename T>
struct is_array : false_type
struct is_array : ctl::false_type
{};
template<typename T, size_t N>
struct is_array<T[N]> : true_type
struct is_array<T[N]> : ctl::true_type
{};
template<typename T>
struct is_array<T[]> : true_type
struct is_array<T[]> : ctl::true_type
{};
template<typename T>
+19
View File
@@ -0,0 +1,19 @@
// -*-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_IS_BASE_OF_H_
#define CTL_IS_BASE_OF_H_
#include "integral_constant.h"
namespace ctl {
template<typename Base, typename Derived>
struct is_base_of
: public ctl::integral_constant<bool, __is_base_of(Base, Derived)>
{};
template<typename Base, typename Derived>
inline constexpr bool is_base_of_v = __is_base_of(Base, Derived);
} // namespace ctl
#endif // CTL_IS_BASE_OF_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_CLASS_H_
#define CTL_IS_CLASS_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_class : public ctl::integral_constant<bool, __is_class(T)>
{};
template<typename T>
inline constexpr bool is_class_v = __is_class(T);
} // namespace ctl
#endif // CTL_IS_CLASS_H_
+19
View File
@@ -0,0 +1,19 @@
// -*-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_IS_CONSTRUCTIBLE_H_
#define CTL_IS_CONSTRUCTIBLE_H_
#include "integral_constant.h"
namespace ctl {
template<class _Tp, class... _Args>
struct is_constructible
: public ctl::integral_constant<bool, __is_constructible(_Tp, _Args...)>
{};
template<class _Tp, class... _Args>
inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
} // namespace ctl
#endif // CTL_IS_CONSTRUCTIBLE_H_
+4 -5
View File
@@ -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"
@@ -16,7 +15,7 @@ declval() noexcept;
namespace detail {
template<typename From, typename To, typename = void>
struct is_convertible_impl : false_type
struct is_convertible_impl : ctl::false_type
{};
template<typename From, typename To>
@@ -28,15 +27,15 @@ struct is_convertible_impl<From,
// Handle void types separately
template<>
struct is_convertible_impl<void, void> : true_type
struct is_convertible_impl<void, void> : ctl::true_type
{};
template<typename To>
struct is_convertible_impl<void, To> : false_type
struct is_convertible_impl<void, To> : ctl::false_type
{};
template<typename From>
struct is_convertible_impl<From, void> : false_type
struct is_convertible_impl<From, void> : ctl::false_type
{};
} // namespace detail
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_EMPTY_H_
#define CTL_IS_EMPTY_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_empty : public ctl::integral_constant<bool, __is_empty(T)>
{};
template<typename T>
inline constexpr bool is_empty_v = __is_empty(T);
} // namespace ctl
#endif // CTL_IS_EMPTY_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_ENUM_H_
#define CTL_IS_ENUM_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_enum : public ctl::integral_constant<bool, __is_enum(T)>
{};
template<typename T>
inline constexpr bool is_enum_v = __is_enum(T);
} // namespace ctl
#endif // CTL_IS_ENUM_H_
+25 -25
View File
@@ -8,111 +8,111 @@ namespace ctl {
// Primary template
template<class>
struct is_function : false_type
struct is_function : ctl::false_type
{};
// Specializations for various function types
// Regular functions
template<class Ret, class... Args>
struct is_function<Ret(Args...)> : true_type
struct is_function<Ret(Args...)> : ctl::true_type
{};
// Functions with cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) const> : true_type
struct is_function<Ret(Args...) const> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile> : true_type
struct is_function<Ret(Args...) volatile> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile> : true_type
struct is_function<Ret(Args...) const volatile> : ctl::true_type
{};
// Functions with ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...)&> : true_type
struct is_function<Ret(Args...)&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const&> : true_type
struct is_function<Ret(Args...) const&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile&> : true_type
struct is_function<Ret(Args...) volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile&> : true_type
struct is_function<Ret(Args...) const volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) &&> : true_type
struct is_function<Ret(Args...) &&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const&&> : true_type
struct is_function<Ret(Args...) const&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile&&> : true_type
struct is_function<Ret(Args...) volatile&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile&&> : true_type
struct is_function<Ret(Args...) const volatile&&> : ctl::true_type
{};
// Variadic functions
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...)> : true_type
struct is_function<Ret(Args..., ...)> : ctl::true_type
{};
// Variadic functions with cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const> : true_type
struct is_function<Ret(Args..., ...) const> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) volatile> : true_type
struct is_function<Ret(Args..., ...) volatile> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const volatile> : true_type
struct is_function<Ret(Args..., ...) const volatile> : ctl::true_type
{};
// Variadic functions with ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...)&> : true_type
struct is_function<Ret(Args..., ...)&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const&> : true_type
struct is_function<Ret(Args..., ...) const&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) volatile&> : true_type
struct is_function<Ret(Args..., ...) volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const volatile&> : true_type
struct is_function<Ret(Args..., ...) const volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) &&> : true_type
struct is_function<Ret(Args..., ...) &&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const&&> : true_type
struct is_function<Ret(Args..., ...) const&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) volatile&&> : true_type
struct is_function<Ret(Args..., ...) volatile&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const volatile&&> : true_type
struct is_function<Ret(Args..., ...) const volatile&&> : ctl::true_type
{};
} // namespace ctl
+16 -16
View File
@@ -7,67 +7,67 @@
namespace ctl {
template<typename T>
struct is_integral : false_type
struct is_integral : ctl::false_type
{};
template<>
struct is_integral<bool> : true_type
struct is_integral<bool> : ctl::true_type
{};
template<>
struct is_integral<char> : true_type
struct is_integral<char> : ctl::true_type
{};
template<>
struct is_integral<signed char> : true_type
struct is_integral<signed char> : ctl::true_type
{};
template<>
struct is_integral<unsigned char> : true_type
struct is_integral<unsigned char> : ctl::true_type
{};
template<>
struct is_integral<short> : true_type
struct is_integral<short> : ctl::true_type
{};
template<>
struct is_integral<unsigned short> : true_type
struct is_integral<unsigned short> : ctl::true_type
{};
template<>
struct is_integral<int> : true_type
struct is_integral<int> : ctl::true_type
{};
template<>
struct is_integral<unsigned int> : true_type
struct is_integral<unsigned int> : ctl::true_type
{};
template<>
struct is_integral<long> : true_type
struct is_integral<long> : ctl::true_type
{};
template<>
struct is_integral<unsigned long> : true_type
struct is_integral<unsigned long> : ctl::true_type
{};
template<>
struct is_integral<long long> : true_type
struct is_integral<long long> : ctl::true_type
{};
template<>
struct is_integral<unsigned long long> : true_type
struct is_integral<unsigned long long> : ctl::true_type
{};
template<>
struct is_integral<char16_t> : true_type
struct is_integral<char16_t> : ctl::true_type
{};
template<>
struct is_integral<char32_t> : true_type
struct is_integral<char32_t> : ctl::true_type
{};
template<>
struct is_integral<wchar_t> : true_type
struct is_integral<wchar_t> : ctl::true_type
{};
template<typename T>
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_POLYMORPHIC_H_
#define CTL_IS_POLYMORPHIC_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_polymorphic : public ctl::integral_constant<bool, __is_polymorphic(T)>
{};
template<typename T>
inline constexpr bool is_polymorphic_v = __is_polymorphic(T);
} // namespace ctl
#endif // CTL_IS_POLYMORPHIC_H_
+19
View File
@@ -0,0 +1,19 @@
// -*-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_IS_STANDARD_LAYOUT_H_
#define CTL_IS_STANDARD_LAYOUT_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_standard_layout
: public ctl::integral_constant<bool, __is_standard_layout(T)>
{};
template<typename T>
inline constexpr bool is_standard_layout_v = __is_standard_layout(T);
} // namespace ctl
#endif // CTL_IS_STANDARD_LAYOUT_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_TRIVIAL_H_
#define CTL_IS_TRIVIAL_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_trivial : public ctl::integral_constant<bool, __is_trivial(T)>
{};
template<typename T>
inline constexpr bool is_trivial_v = __is_trivial(T);
} // namespace ctl
#endif // CTL_IS_TRIVIAL_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-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_IS_UNION_H_
#define CTL_IS_UNION_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_union : public ctl::integral_constant<bool, __is_union(T)>
{};
template<typename T>
inline constexpr bool is_union_v = __is_union(T);
} // namespace ctl
#endif // CTL_IS_UNION_H_
+24
View File
@@ -0,0 +1,24 @@
// -*-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_IS_VOID_H_
#define CTL_IS_VOID_H_
#include "integral_constant.h"
#include "remove_cv.h"
namespace ctl {
template<typename>
struct is_void_ : public ctl::false_type
{};
template<>
struct is_void_<void> : public ctl::true_type
{};
template<typename _Tp>
struct is_void : public is_void_<typename ctl::remove_cv<_Tp>::type>::type
{};
} // namespace ctl
#endif // CTL_IS_VOID_H_
+237
View 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
View 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>>(ctl::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
View 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 ctl::string_view& str)
: buffer_(str), read_pos_(0)
{
}
ctl::string
istringstream::str() const
{
return buffer_;
}
void
istringstream::str(const ctl::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>>(ctl::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
View 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 ctl::string_view&);
string str() const;
void str(const string&);
istringstream& operator>>(char&);
istringstream& operator>>(char*);
istringstream& operator>>(ctl::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:
ctl::string buffer_;
size_t read_pos_;
template<typename T>
istringstream& read_numeric(T&);
};
} // namespace ctl
#endif // CTL_ISTRINGSTREAM_H_
+22 -11
View File
@@ -2,12 +2,33 @@
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ITERATOR_TRAITS_H_
#define CTL_ITERATOR_TRAITS_H_
#include "iterator.h"
#include "utility.h"
#include "void_t.h"
namespace ctl {
template<class Iterator>
template<typename Iterator, typename = void>
struct iterator_traits
{};
template<typename T>
struct iterator_traits<T*>
{
using difference_type = ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
using iterator_category = ctl::random_access_iterator_tag;
};
template<typename Iterator>
struct iterator_traits<Iterator,
ctl::void_t<typename Iterator::iterator_category,
typename Iterator::value_type,
typename Iterator::difference_type,
typename Iterator::pointer,
typename Iterator::reference>>
{
using iterator_category = typename Iterator::iterator_category;
using value_type = typename Iterator::value_type;
@@ -16,16 +37,6 @@ struct iterator_traits
using reference = typename Iterator::reference;
};
template<class T>
struct iterator_traits<T*>
{
using iterator_category = void*; // We don't actually use this
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
};
} // namespace ctl
#endif // CTL_ITERATOR_TRAITS_H_
+14 -14
View File
@@ -152,12 +152,12 @@ class map
Value& operator[](const Key& key)
{
return ((data_.insert(make_pair(key, Value()))).first)->second;
return ((data_.insert(ctl::make_pair(key, Value()))).first)->second;
}
Value& operator[](Key&& key)
{
return ((data_.insert(make_pair(ctl::move(key), Value()))).first)
return ((data_.insert(ctl::make_pair(ctl::move(key), Value()))).first)
->second;
}
@@ -165,7 +165,7 @@ class map
{
auto it = find(key);
if (it == end())
throw ctl::out_of_range("out of range");
throw ctl::out_of_range();
return it->second;
}
@@ -173,7 +173,7 @@ class map
{
auto it = find(key);
if (it == end())
throw ctl::out_of_range("out of range");
throw ctl::out_of_range();
return it->second;
}
@@ -244,7 +244,7 @@ class map
size_type erase(const Key& key)
{
return data_.erase(make_pair(key, Value()));
return data_.erase(ctl::make_pair(key, Value()));
}
void swap(map& other) noexcept
@@ -259,47 +259,47 @@ class map
iterator find(const Key& key)
{
return data_.find(make_pair(key, Value()));
return data_.find(ctl::make_pair(key, Value()));
}
const_iterator find(const Key& key) const
{
return data_.find(make_pair(key, Value()));
return data_.find(ctl::make_pair(key, Value()));
}
size_type count(const Key& key) const
{
return data_.count(make_pair(key, Value()));
return data_.count(ctl::make_pair(key, Value()));
}
iterator lower_bound(const Key& key)
{
return data_.lower_bound(make_pair(key, Value()));
return data_.lower_bound(ctl::make_pair(key, Value()));
}
const_iterator lower_bound(const Key& key) const
{
return data_.lower_bound(make_pair(key, Value()));
return data_.lower_bound(ctl::make_pair(key, Value()));
}
iterator upper_bound(const Key& key)
{
return data_.upper_bound(make_pair(key, Value()));
return data_.upper_bound(ctl::make_pair(key, Value()));
}
const_iterator upper_bound(const Key& key) const
{
return data_.upper_bound(make_pair(key, Value()));
return data_.upper_bound(ctl::make_pair(key, Value()));
}
ctl::pair<iterator, iterator> equal_range(const Key& key)
{
return data_.equal_range(make_pair(key, Value()));
return data_.equal_range(ctl::make_pair(key, Value()));
}
ctl::pair<const_iterator, const_iterator> equal_range(const Key& key) const
{
return data_.equal_range(make_pair(key, Value()));
return data_.equal_range(ctl::make_pair(key, Value()));
}
key_compare key_comp() const
+8 -4
View File
@@ -11,17 +11,20 @@ class mutex
public:
mutex()
{
pthread_mutex_init(&m_, nullptr);
if (pthread_mutex_init(&m_, nullptr))
__builtin_trap();
}
~mutex()
{
pthread_mutex_destroy(&m_);
if (pthread_mutex_destroy(&m_))
__builtin_trap();
}
void lock()
{
pthread_mutex_lock(&m_);
if (pthread_mutex_lock(&m_))
__builtin_trap();
}
bool try_lock()
@@ -31,7 +34,8 @@ class mutex
void unlock()
{
pthread_mutex_unlock(&m_);
if (pthread_mutex_unlock(&m_))
__builtin_trap();
}
// Delete copy constructor and assignment operator
+219
View File
@@ -0,0 +1,219 @@
// -*- 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 "dubble.h"
#include "libc/fmt/itoa.h"
#include "libc/stdio/stdio.h"
#include "string_view.h"
namespace ctl {
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
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 (fputs(str, file_) < 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()) {
char buf[12];
FormatInt32(buf, n);
if (fputs(buf, file_) < 0)
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;
}
ostream&
ostream::operator<<(long n)
{
if (good()) {
char buf[21];
FormatInt64(buf, n);
if (fputs(buf, file_) < 0)
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;
}
ostream&
ostream::operator<<(double d)
{
if (good()) {
char buf[128];
double_conversion::StringBuilder b(buf, sizeof(buf));
kDoubleToPrintfG.ToShortest(d, &b);
b.Finalize();
if (fputs(buf, file_) < 0)
setstate(badbit);
}
return *this;
}
ostream&
ostream::operator<<(const string_view& s)
{
if (good() && s.size())
if (!fwrite(s.data(), s.size(), 1, file_))
setstate(badbit);
return *this;
}
ostream&
ostream::operator<<(bool b)
{
if (good()) {
const char* value =
(flags() & boolalpha) ? (b ? "true" : "false") : (b ? "1" : "0");
if (fputs(value, file_) < 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
+56
View File
@@ -0,0 +1,56 @@
// -*-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<<(bool);
ostream& operator<<(char);
ostream& operator<<(int);
ostream& operator<<(unsigned);
ostream& operator<<(long);
ostream& operator<<(unsigned long);
ostream& operator<<(float);
ostream& operator<<(double);
ostream& operator<<(const ctl::string_view&);
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_
+150
View File
@@ -0,0 +1,150 @@
// -*- 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 "dubble.h"
#include "libc/fmt/itoa.h"
namespace ctl {
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
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)
{
if (good()) {
char buf[12];
*this << string_view(buf, FormatInt32(buf, n) - buf);
}
return *this;
}
ostringstream&
ostringstream::operator<<(unsigned n)
{
if (good()) {
char buf[12];
*this << string_view(buf, FormatUint32(buf, n) - buf);
}
return *this;
}
ostringstream&
ostringstream::operator<<(long n)
{
if (good()) {
char buf[21];
*this << string_view(buf, FormatInt64(buf, n) - buf);
}
return *this;
}
ostringstream&
ostringstream::operator<<(unsigned long n)
{
if (good()) {
char buf[21];
*this << string_view(buf, FormatUint64(buf, n) - buf);
}
return *this;
}
ostringstream&
ostringstream::operator<<(float f)
{
if (good()) {
char buf[128];
double_conversion::StringBuilder b(buf, sizeof(buf));
kDoubleToPrintfG.ToShortestSingle(f, &b);
b.Finalize();
*this << string_view(buf);
}
return *this;
}
ostringstream&
ostringstream::operator<<(double d)
{
if (good()) {
char buf[128];
double_conversion::StringBuilder b(buf, sizeof(buf));
kDoubleToPrintfG.ToShortest(d, &b);
b.Finalize();
*this << string_view(buf);
}
return *this;
}
} // namespace ctl
+36
View 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 ctl::string_view&);
ctl::string str() const;
void str(const ctl::string& s);
void clear();
ostringstream& operator<<(char);
ostringstream& operator<<(const ctl::string_view&);
ostringstream& operator<<(int);
ostringstream& operator<<(unsigned int);
ostringstream& operator<<(long);
ostringstream& operator<<(unsigned long);
ostringstream& operator<<(float);
ostringstream& operator<<(double);
private:
ctl::string buffer_;
size_t write_pos_;
};
} // namespace ctl
#endif // CTL_OSTRINGSTREAM_H_
+1 -1
View File
@@ -6,7 +6,7 @@
namespace ctl {
class out_of_range : public exception
class out_of_range : public ctl::exception
{
public:
out_of_range() noexcept = default;
+19
View File
@@ -0,0 +1,19 @@
// -*-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_REQUIRE_INPUT_ITERATOR_H_
#define CTL_REQUIRE_INPUT_ITERATOR_H_
#include "enable_if.h"
#include "is_convertible.h"
#include "iterator.h"
#include "iterator_traits.h"
namespace ctl {
template<typename InputIt>
using require_input_iterator = typename ctl::enable_if<
ctl::is_convertible<typename ctl::iterator_traits<InputIt>::iterator_category,
ctl::input_iterator_tag>::value>::type;
} // namespace ctl
#endif /* CTL_REQUIRE_INPUT_ITERATOR_H_ */
+6 -5
View File
@@ -13,11 +13,12 @@ class reverse_iterator
public:
using iterator_type = Iterator;
using iterator_category =
typename iterator_traits<Iterator>::iterator_category;
using value_type = typename iterator_traits<Iterator>::value_type;
using difference_type = typename iterator_traits<Iterator>::difference_type;
using pointer = typename iterator_traits<Iterator>::pointer;
using reference = typename iterator_traits<Iterator>::reference;
typename ctl::iterator_traits<Iterator>::iterator_category;
using value_type = typename ctl::iterator_traits<Iterator>::value_type;
using difference_type =
typename ctl::iterator_traits<Iterator>::difference_type;
using pointer = typename ctl::iterator_traits<Iterator>::pointer;
using reference = typename ctl::iterator_traits<Iterator>::reference;
constexpr reverse_iterator() : current()
{
+146 -125
View File
@@ -8,23 +8,39 @@
namespace ctl {
template<typename Key, typename Compare = less<Key>>
template<typename Key, typename Compare = ctl::less<Key>>
class set
{
struct rbtree
{
rbtree* left;
uintptr_t left_;
rbtree* right;
rbtree* parent;
bool is_red;
Key value;
rbtree* left() const
{
return (rbtree*)(left_ & -2);
}
void left(rbtree* val)
{
left_ = (uintptr_t)val | (left_ & 1);
}
bool is_red() const
{
return left_ & 1;
}
void is_red(bool val)
{
left_ &= -2;
left_ |= val;
}
rbtree(const Key& val)
: left(nullptr)
, right(nullptr)
, parent(nullptr)
, is_red(true)
, value(val)
: left_(1), right(nullptr), parent(nullptr), value(val)
{
}
};
@@ -85,14 +101,14 @@ class set
{
if (node_ == nullptr)
__builtin_trap();
if (node_->left) {
node_ = rightmost(node_->left);
if (node_->left()) {
node_ = rightmost(node_->left());
} else {
node_type* parent = node_->parent;
for (;;) {
if (parent == nullptr)
break;
if (node_ == parent->left) {
if (node_ == parent->left()) {
node_ = parent;
parent = parent->parent;
} else {
@@ -161,11 +177,11 @@ class set
reverse_iterator& operator++()
{
if (node_->left) {
node_ = rightmost(node_->left);
if (node_->left()) {
node_ = rightmost(node_->left());
} else {
node_type* parent = node_->parent;
while (parent && node_ == parent->left) {
while (parent && node_ == parent->left()) {
node_ = parent;
parent = parent->parent;
}
@@ -381,12 +397,12 @@ class set
size_ = 0;
}
pair<iterator, bool> insert(value_type&& value)
ctl::pair<iterator, bool> insert(value_type&& value)
{
return insert_node(new node_type(ctl::move(value)));
}
pair<iterator, bool> insert(const value_type& value)
ctl::pair<iterator, bool> insert(const value_type& value)
{
return insert_node(new node_type(value));
}
@@ -415,7 +431,7 @@ class set
}
template<class... Args>
pair<iterator, bool> emplace(Args&&... args)
ctl::pair<iterator, bool> emplace(Args&&... args)
{
value_type value(ctl::forward<Args>(args)...);
return insert(ctl::move(value));
@@ -451,12 +467,13 @@ class set
ctl::swap(size_, other.size_);
}
pair<iterator, iterator> equal_range(const key_type& key)
ctl::pair<iterator, iterator> equal_range(const key_type& key)
{
return { iterator(get_floor(key)), iterator(get_ceiling(key)) };
}
pair<const_iterator, const_iterator> equal_range(const key_type& key) const
ctl::pair<const_iterator, const_iterator> equal_range(
const key_type& key) const
{
return { const_iterator(get_floor(key)),
const_iterator(get_ceiling(key)) };
@@ -507,7 +524,7 @@ class set
{
size_type count = 0;
if (root_ != nullptr) {
if (root_->is_red)
if (root_->is_red())
// ILLEGAL TREE: root node must be black
__builtin_trap();
int black_height = -1;
@@ -522,8 +539,8 @@ class set
private:
static node_type* leftmost(node_type* node) noexcept
{
while (node && node->left)
node = node->left;
while (node && node->left())
node = node->left();
return node;
}
@@ -534,35 +551,35 @@ class set
return node;
}
static void clearer(node_type* node) noexcept
static optimizesize void clearer(node_type* node) noexcept
{
node_type* right;
for (; node; node = right) {
right = node->right;
clearer(node->left);
clearer(node->left());
delete node;
}
}
static node_type* copier(const node_type* node)
static optimizesize node_type* copier(const node_type* node)
{
if (node == nullptr)
return nullptr;
node_type* new_node = new node_type(node->value);
new_node->left = copier(node->left);
new_node->left(copier(node->left()));
new_node->right = copier(node->right);
if (new_node->left)
new_node->left->parent = new_node;
if (new_node->left())
new_node->left()->parent = new_node;
if (new_node->right)
new_node->right->parent = new_node;
return new_node;
}
static size_type tally(const node_type* node)
static optimizesize size_type tally(const node_type* node)
{
if (node == nullptr)
return 0;
return 1 + tally(node->left) + tally(node->right);
return 1 + tally(node->left()) + tally(node->right);
}
template<typename K>
@@ -571,7 +588,7 @@ class set
node_type* current = root_;
while (current != nullptr) {
if (comp_(key, current->value)) {
current = current->left;
current = current->left();
} else if (comp_(current->value, key)) {
current = current->right;
} else {
@@ -589,7 +606,7 @@ class set
while (current != nullptr) {
if (!comp_(current->value, key)) {
result = current;
current = current->left;
current = current->left();
} else {
current = current->right;
}
@@ -605,7 +622,7 @@ class set
while (current != nullptr) {
if (comp_(key, current->value)) {
result = current;
current = current->left;
current = current->left();
} else {
current = current->right;
}
@@ -613,11 +630,11 @@ class set
return result;
}
pair<iterator, bool> insert_node(node_type* node)
optimizesize ctl::pair<iterator, bool> insert_node(node_type* node)
{
if (root_ == nullptr) {
root_ = node;
root_->is_red = false;
root_->is_red(false);
size_++;
return { iterator(root_), true };
}
@@ -626,7 +643,7 @@ class set
while (current != nullptr) {
parent = current;
if (comp_(node->value, current->value)) {
current = current->left;
current = current->left();
} else if (comp_(current->value, node->value)) {
current = current->right;
} else {
@@ -635,7 +652,7 @@ class set
}
}
if (comp_(node->value, parent->value)) {
parent->left = node;
parent->left(node);
} else {
parent->right = node;
}
@@ -645,23 +662,23 @@ class set
return { iterator(node), true };
}
void erase_node(node_type* node)
optimizesize void erase_node(node_type* node)
{
node_type* y = node;
node_type* x = nullptr;
node_type* x_parent = nullptr;
bool y_original_color = y->is_red;
if (node->left == nullptr) {
bool y_original_color = y->is_red();
if (node->left() == nullptr) {
x = node->right;
transplant(node, node->right);
x_parent = node->parent;
} else if (node->right == nullptr) {
x = node->left;
transplant(node, node->left);
x = node->left();
transplant(node, node->left());
x_parent = node->parent;
} else {
y = leftmost(node->right);
y_original_color = y->is_red;
y_original_color = y->is_red();
x = y->right;
if (y->parent == node) {
if (x)
@@ -674,9 +691,9 @@ class set
x_parent = y->parent;
}
transplant(node, y);
y->left = node->left;
y->left->parent = y;
y->is_red = node->is_red;
y->left(node->left());
y->left()->parent = y;
y->is_red(node->is_red());
}
if (!y_original_color)
rebalance_after_erase(x, x_parent);
@@ -684,28 +701,28 @@ class set
--size_;
}
void left_rotate(node_type* x)
optimizesize void left_rotate(node_type* x)
{
node_type* y = x->right;
x->right = y->left;
if (y->left != nullptr)
y->left->parent = x;
x->right = y->left();
if (y->left() != nullptr)
y->left()->parent = x;
y->parent = x->parent;
if (x->parent == nullptr) {
root_ = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else if (x == x->parent->left()) {
x->parent->left(y);
} else {
x->parent->right = y;
}
y->left = x;
y->left(x);
x->parent = y;
}
void right_rotate(node_type* y)
optimizesize void right_rotate(node_type* y)
{
node_type* x = y->left;
y->left = x->right;
node_type* x = y->left();
y->left(x->right);
if (x->right != nullptr)
x->right->parent = y;
x->parent = y->parent;
@@ -714,18 +731,18 @@ class set
} else if (y == y->parent->right) {
y->parent->right = x;
} else {
y->parent->left = x;
y->parent->left(x);
}
x->right = y;
y->parent = x;
}
void transplant(node_type* u, node_type* v)
optimizesize void transplant(node_type* u, node_type* v)
{
if (u->parent == nullptr) {
root_ = v;
} else if (u == u->parent->left) {
u->parent->left = v;
} else if (u == u->parent->left()) {
u->parent->left(v);
} else {
u->parent->right = v;
}
@@ -733,10 +750,10 @@ class set
v->parent = u->parent;
}
void checker(const node_type* node,
const node_type* parent,
int black_count,
int& black_height) const
optimizesize void checker(const node_type* node,
const node_type* parent,
int black_count,
int& black_height) const
{
if (node == nullptr) {
// Leaf nodes are considered black
@@ -752,117 +769,121 @@ class set
// ILLEGAL TREE: Parent link is incorrect
__builtin_trap();
if (parent) {
if (parent->left == node && !comp_(node->value, parent->value))
if (parent->left() == node && !comp_(node->value, parent->value))
// ILLEGAL TREE: Binary search property violated on left child
__builtin_trap();
if (parent->right == node && !comp_(parent->value, node->value))
// ILLEGAL TREE: Binary search property violated on right child
__builtin_trap();
}
if (!node->is_red) {
if (!node->is_red()) {
black_count++;
} else if (parent != nullptr && parent->is_red) {
} else if (parent != nullptr && parent->is_red()) {
// ILLEGAL TREE: Red node has red child
__builtin_trap();
}
checker(node->left, node, black_count, black_height);
checker(node->left(), node, black_count, black_height);
checker(node->right, node, black_count, black_height);
}
void rebalance_after_insert(node_type* node)
optimizesize void rebalance_after_insert(node_type* node)
{
node->is_red = true;
while (node != root_ && node->parent->is_red) {
if (node->parent == node->parent->parent->left) {
node->is_red(true);
while (node != root_ && node->parent->is_red()) {
if (node->parent == node->parent->parent->left()) {
node_type* uncle = node->parent->parent->right;
if (uncle && uncle->is_red) {
node->parent->is_red = false;
uncle->is_red = false;
node->parent->parent->is_red = true;
if (uncle && uncle->is_red()) {
node->parent->is_red(false);
uncle->is_red(false);
node->parent->parent->is_red(true);
node = node->parent->parent;
} else {
if (node == node->parent->right) {
node = node->parent;
left_rotate(node);
}
node->parent->is_red = false;
node->parent->parent->is_red = true;
node->parent->is_red(false);
node->parent->parent->is_red(true);
right_rotate(node->parent->parent);
}
} else {
node_type* uncle = node->parent->parent->left;
if (uncle && uncle->is_red) {
node->parent->is_red = false;
uncle->is_red = false;
node->parent->parent->is_red = true;
node_type* uncle = node->parent->parent->left();
if (uncle && uncle->is_red()) {
node->parent->is_red(false);
uncle->is_red(false);
node->parent->parent->is_red(true);
node = node->parent->parent;
} else {
if (node == node->parent->left) {
if (node == node->parent->left()) {
node = node->parent;
right_rotate(node);
}
node->parent->is_red = false;
node->parent->parent->is_red = true;
node->parent->is_red(false);
node->parent->parent->is_red(true);
left_rotate(node->parent->parent);
}
}
}
root_->is_red = false;
root_->is_red(false);
}
void rebalance_after_erase(node_type* node, node_type* parent)
optimizesize void rebalance_after_erase(node_type* node, node_type* parent)
{
while (node != root_ && (node == nullptr || !node->is_red)) {
if (node == parent->left) {
while (node != root_ && (node == nullptr || !node->is_red())) {
if (node == parent->left()) {
node_type* sibling = parent->right;
if (sibling->is_red) {
sibling->is_red = false;
parent->is_red = true;
if (sibling->is_red()) {
sibling->is_red(false);
parent->is_red(true);
left_rotate(parent);
sibling = parent->right;
}
if ((sibling->left == nullptr || !sibling->left->is_red) &&
(sibling->right == nullptr || !sibling->right->is_red)) {
sibling->is_red = true;
if ((sibling->left() == nullptr ||
!sibling->left()->is_red()) &&
(sibling->right == nullptr || !sibling->right->is_red())) {
sibling->is_red(true);
node = parent;
parent = node->parent;
} else {
if (sibling->right == nullptr || !sibling->right->is_red) {
sibling->left->is_red = false;
sibling->is_red = true;
if (sibling->right == nullptr ||
!sibling->right->is_red()) {
sibling->left()->is_red(false);
sibling->is_red(true);
right_rotate(sibling);
sibling = parent->right;
}
sibling->is_red = parent->is_red;
parent->is_red = false;
sibling->right->is_red = false;
sibling->is_red(parent->is_red());
parent->is_red(false);
sibling->right->is_red(false);
left_rotate(parent);
node = root_;
break;
}
} else {
node_type* sibling = parent->left;
if (sibling->is_red) {
sibling->is_red = false;
parent->is_red = true;
node_type* sibling = parent->left();
if (sibling->is_red()) {
sibling->is_red(false);
parent->is_red(true);
right_rotate(parent);
sibling = parent->left;
sibling = parent->left();
}
if ((sibling->right == nullptr || !sibling->right->is_red) &&
(sibling->left == nullptr || !sibling->left->is_red)) {
sibling->is_red = true;
if ((sibling->right == nullptr || !sibling->right->is_red()) &&
(sibling->left() == nullptr ||
!sibling->left()->is_red())) {
sibling->is_red(true);
node = parent;
parent = node->parent;
} else {
if (sibling->left == nullptr || !sibling->left->is_red) {
sibling->right->is_red = false;
sibling->is_red = true;
if (sibling->left() == nullptr ||
!sibling->left()->is_red()) {
sibling->right->is_red(false);
sibling->is_red(true);
left_rotate(sibling);
sibling = parent->left;
sibling = parent->left();
}
sibling->is_red = parent->is_red;
parent->is_red = false;
sibling->left->is_red = false;
sibling->is_red(parent->is_red());
parent->is_red(false);
sibling->left()->is_red(false);
right_rotate(parent);
node = root_;
break;
@@ -870,7 +891,7 @@ class set
}
}
if (node != nullptr)
node->is_red = false;
node->is_red(false);
}
node_type* root_;
@@ -878,7 +899,7 @@ class set
Compare comp_;
};
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
bool
operator==(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
{
@@ -893,7 +914,7 @@ operator==(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
return true;
}
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
bool
operator<(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
{
@@ -908,35 +929,35 @@ operator<(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
return i == lhs.end() && j != rhs.end();
}
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
bool
operator!=(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
{
return !(lhs == rhs);
}
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
bool
operator<=(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
{
return !(rhs < lhs);
}
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
bool
operator>(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
{
return rhs < lhs;
}
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
bool
operator>=(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
{
return !(lhs < rhs);
}
template<class Key, typename Compare = less<Key>>
template<class Key, typename Compare = ctl::less<Key>>
void
swap(set<Key, Compare>& lhs, set<Key, Compare>& rhs) noexcept;
+80 -25
View File
@@ -9,7 +9,7 @@ namespace ctl {
class string;
string strcat(string_view, string_view) noexcept __wur;
ctl::string strcat(ctl::string_view, ctl::string_view) noexcept __wur;
namespace __ {
@@ -66,7 +66,7 @@ class string
*(((size_t*)blob) + 2) = __::sso_max << (sizeof(size_t) - 1) * 8;
}
string(const string_view s) noexcept
string(const ctl::string_view s) noexcept
{
if (s.n <= __::sso_max) {
__builtin_memcpy(blob, s.p, s.n);
@@ -89,7 +89,7 @@ class string
}
string(const char* const p) noexcept
: string(string_view(p, __builtin_strlen(p)))
: string(ctl::string_view(p, __builtin_strlen(p)))
{
}
@@ -104,7 +104,7 @@ class string
}
string(const char* const p, const size_t n) noexcept
: string(string_view(p, n))
: string(ctl::string_view(p, n))
{
}
@@ -125,17 +125,17 @@ class string
void append(char, size_t) noexcept;
void append(unsigned long) noexcept;
void append(const void*, size_t) noexcept;
string& insert(size_t, string_view) noexcept;
string& insert(size_t, ctl::string_view) noexcept;
string& erase(size_t = 0, size_t = npos) noexcept;
string substr(size_t = 0, size_t = npos) const noexcept;
string& replace(size_t, size_t, string_view) noexcept;
bool operator==(string_view) const noexcept;
bool operator!=(string_view) const noexcept;
bool contains(string_view) const noexcept;
bool ends_with(string_view) const noexcept;
bool starts_with(string_view) const noexcept;
string& replace(size_t, size_t, ctl::string_view) noexcept;
bool operator==(ctl::string_view) const noexcept;
bool operator!=(ctl::string_view) const noexcept;
bool contains(ctl::string_view) const noexcept;
bool ends_with(ctl::string_view) const noexcept;
bool starts_with(ctl::string_view) const noexcept;
size_t find(char, size_t = 0) const noexcept;
size_t find(string_view, size_t = 0) const noexcept;
size_t find(ctl::string_view, size_t = 0) const noexcept;
void swap(string& s) noexcept
{
@@ -302,14 +302,14 @@ class string
append(ch);
}
void append(const string_view s) noexcept
void append(const ctl::string_view s) noexcept
{
append(s.p, s.n);
}
operator string_view() const noexcept
operator ctl::string_view() const noexcept
{
return string_view(data(), size());
return ctl::string_view(data(), size());
}
string& operator=(const char* s) noexcept
@@ -319,7 +319,7 @@ class string
return *this;
}
string& operator=(const string_view s) noexcept
string& operator=(const ctl::string_view s) noexcept
{
clear();
append(s);
@@ -332,38 +332,66 @@ class string
return *this;
}
string& operator+=(const string_view s) noexcept
string& operator+=(const char* s) noexcept
{
append(s);
return *this;
}
string operator+(const string_view s) const noexcept
string& operator+=(const ctl::string s) noexcept
{
append(s);
return *this;
}
string& operator+=(const ctl::string_view s) noexcept
{
append(s);
return *this;
}
string operator+(const char c) const noexcept
{
char s[2] = { c };
return strcat(*this, s);
}
string operator+(const char* s) const noexcept
{
return strcat(*this, s);
}
int compare(const string_view s) const noexcept
string operator+(const string& s) const noexcept
{
return strcat(*this, s);
}
string operator+(const ctl::string_view s) const noexcept
{
return strcat(*this, s);
}
int compare(const ctl::string_view s) const noexcept
{
return strcmp(*this, s);
}
bool operator<(const string_view s) const noexcept
bool operator<(const ctl::string_view s) const noexcept
{
return compare(s) < 0;
}
bool operator<=(const string_view s) const noexcept
bool operator<=(const ctl::string_view s) const noexcept
{
return compare(s) <= 0;
}
bool operator>(const string_view s) const noexcept
bool operator>(const ctl::string_view s) const noexcept
{
return compare(s) > 0;
}
bool operator>=(const string_view s) const noexcept
bool operator>=(const ctl::string_view s) const noexcept
{
return compare(s) >= 0;
}
@@ -371,7 +399,7 @@ class string
private:
void destroy_big() noexcept;
void init_big(const string&) noexcept;
void init_big(string_view) noexcept;
void init_big(ctl::string_view) noexcept;
void init_big(size_t, char) noexcept;
__attribute__((__always_inline__)) bool isbig() const noexcept
@@ -395,7 +423,7 @@ class string
__b.c = c2 | ~__::big_mask;
}
friend string strcat(string_view, string_view) noexcept;
friend string strcat(ctl::string_view, ctl::string_view) noexcept;
union
{
@@ -409,6 +437,33 @@ static_assert(sizeof(string) == __::string_size);
static_assert(sizeof(__::small_string) == __::string_size);
static_assert(sizeof(__::big_string) == __::string_size);
ctl::string
to_string(int) noexcept;
ctl::string
to_string(long) noexcept;
ctl::string
to_string(long long) noexcept;
ctl::string
to_string(unsigned) noexcept;
ctl::string
to_string(unsigned long) noexcept;
ctl::string
to_string(unsigned long long) noexcept;
ctl::string
to_string(float) noexcept;
ctl::string
to_string(double) noexcept;
ctl::string
to_string(long double) noexcept;
} // namespace ctl
#pragma GCC diagnostic push
+3 -3
View File
@@ -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_STRINGVIEW_H_
#define COSMOPOLITAN_CTL_STRINGVIEW_H_
#ifndef CTL_STRINGVIEW_H_
#define CTL_STRINGVIEW_H_
#include "utility.h"
namespace ctl {
@@ -157,4 +157,4 @@ struct string_view
} // namespace ctl
#endif // COSMOPOLITAN_CTL_STRINGVIEW_H_
#endif // CTL_STRINGVIEW_H_
+109
View 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) noexcept
{
char buf[12];
return { buf, FormatInt32(buf, value) - buf };
}
string
to_string(unsigned value) noexcept
{
char buf[12];
return { buf, FormatUint32(buf, value) - buf };
}
string
to_string(long value) noexcept
{
char buf[21];
return { buf, FormatInt64(buf, value) - buf };
}
string
to_string(unsigned long value) noexcept
{
char buf[21];
return { buf, FormatUint64(buf, value) - buf };
}
string
to_string(long long value) noexcept
{
char buf[21];
return { buf, FormatInt64(buf, value) - buf };
}
string
to_string(unsigned long long value) noexcept
{
char buf[21];
return { buf, FormatUint64(buf, value) - buf };
}
string
to_string(float value) noexcept
{
char buf[128];
double_conversion::StringBuilder b(buf, sizeof(buf));
kDoubleToPrintfG.ToShortestSingle(value, &b);
b.Finalize();
return string(buf);
}
string
to_string(double value) noexcept
{
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) noexcept
{
#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
+3 -3
View File
@@ -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_
+15 -9
View File
@@ -15,6 +15,7 @@
#include "move_backward.h"
#include "move_iterator.h"
#include "out_of_range.h"
#include "require_input_iterator.h"
#include "reverse_iterator.h"
#include "uninitialized_fill.h"
#include "uninitialized_fill_n.h"
@@ -65,7 +66,7 @@ class vector
resize(count);
}
template<class InputIt>
template<class InputIt, typename = ctl::require_input_iterator<InputIt>>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator())
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
{
@@ -173,7 +174,7 @@ class vector
size_ = count;
}
template<class InputIt>
template<class InputIt, typename = ctl::require_input_iterator<InputIt>>
void assign(InputIt first, InputIt last)
{
clear();
@@ -189,24 +190,28 @@ class vector
reference at(size_type pos)
{
if (pos >= size_)
throw ctl::out_of_range("out of range");
throw ctl::out_of_range();
return data_[pos];
}
const_reference at(size_type pos) const
{
if (pos >= size_)
throw ctl::out_of_range("out of range");
throw ctl::out_of_range();
return data_[pos];
}
reference operator[](size_type pos)
{
if (pos >= size_)
__builtin_trap();
return data_[pos];
}
const_reference operator[](size_type pos) const
{
if (pos >= size_)
__builtin_trap();
return data_[pos];
}
@@ -368,7 +373,7 @@ class vector
return it;
}
template<class InputIt>
template<class InputIt, typename = ctl::require_input_iterator<InputIt>>
iterator insert(const_iterator pos, InputIt first, InputIt last)
{
difference_type count = ctl::distance(first, last);
@@ -406,16 +411,17 @@ class vector
return erase(pos, pos + 1);
}
iterator erase(const_iterator first, const_iterator last)
constexpr iterator erase(const_iterator first, const_iterator last)
{
difference_type index = first - begin();
difference_type count = last - first;
iterator it = begin() + index;
ctl::move(it + count, end(), it);
for (iterator move_it = it + count; move_it != end(); ++move_it, ++it)
*it = ctl::move(*move_it);
for (difference_type i = 0; i < count; ++i)
ctl::allocator_traits<Allocator>::destroy(alloc_, end() - i - 1);
size_ -= count;
return it;
return begin() + index;
}
void push_back(const T& value)
@@ -519,7 +525,7 @@ class vector
capacity_ = new_capacity;
}
Allocator alloc_;
[[no_unique_address]] Allocator alloc_;
pointer data_;
size_type size_;
size_type capacity_;
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/core/core.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/safemacros.h"
#include "libc/limits.h"
/**
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/safemacros.h"
#include "libc/intrin/weaken.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/itoa8.h"
#include "dsp/tty/tty.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/safemacros.h"
#include "libc/limits.h"
#include "libc/log/check.h"
+1 -1
View File
@@ -22,7 +22,7 @@
#include "dsp/tty/ttyrgb.h"
#include "dsp/tty/windex.h"
#include "libc/assert.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/safemacros.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
+2 -3
View File
@@ -7,9 +7,8 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
#include <cosmo.h>
#include <math.h>
void crash(long x0, long x1, long x2, //
double v0, double v1, double v2) {
+6 -4
View File
@@ -24,6 +24,7 @@
#include <sys/socket.h>
#include <time.h>
#include "libc/mem/leaks.h"
#include "libc/runtime/runtime.h"
/**
* @fileoverview greenbean lightweight threaded web server
@@ -288,10 +289,11 @@ int main(int argc, char *argv[]) {
// print all the ips that 0.0.0.0 would bind
// Cosmo's GetHostIps() API is much easier than ioctl(SIOCGIFCONF)
uint32_t *hostips;
for (hostips = gc(GetHostIps()), i = 0; hostips[i]; ++i) {
for (hostips = GetHostIps(), i = 0; hostips[i]; ++i) {
kprintf("listening on http://%hhu.%hhu.%hhu.%hhu:%hu\n", hostips[i] >> 24,
hostips[i] >> 16, hostips[i] >> 8, hostips[i], PORT);
}
free(hostips);
// secure the server
//
@@ -336,13 +338,12 @@ int main(int argc, char *argv[]) {
sigaddset(&block, SIGHUP);
sigaddset(&block, SIGQUIT);
pthread_attr_t attr;
int pagesz = getauxval(AT_PAGESZ);
unassert(!pthread_attr_init(&attr));
unassert(!pthread_attr_setstacksize(&attr, 65536));
unassert(!pthread_attr_setguardsize(&attr, pagesz));
unassert(!pthread_attr_setguardsize(&attr, getpagesize()));
unassert(!pthread_attr_setsigmask_np(&attr, &block));
unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0));
pthread_t *th = gc(calloc(threads, sizeof(pthread_t)));
pthread_t *th = calloc(threads, sizeof(pthread_t));
for (i = 0; i < threads; ++i) {
int rc;
++a_workers;
@@ -399,6 +400,7 @@ int main(int argc, char *argv[]) {
for (i = 0; i < threads; ++i) {
unassert(!pthread_join(th[i], 0));
}
free(th);
// close the server socket
if (!IsWindows())
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/safemacros.h"
#include "libc/inttypes.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
+1 -1
View File
@@ -122,7 +122,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/safemacros.h"
#include "libc/limits.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/struct/sigset.internal.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/describebacktrace.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/cachestat.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
int sys_cachestat(int, struct cachestat_range *, struct cachestat *, uint32_t);
+1 -1
View File
@@ -20,7 +20,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/errfuns.h"
/**
+1 -1
View File
@@ -20,7 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/fmt/wintime.internal.h"
#include "libc/intrin/getauxval.internal.h"
#include "libc/intrin/getauxval.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"
+2 -2
View File
@@ -18,8 +18,8 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/errfuns.h"
#include "libc/time.h"
+2 -2
View File
@@ -21,8 +21,8 @@
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/runtime/syslib.internal.h"
#ifdef __aarch64__
+2 -2
View File
@@ -22,8 +22,8 @@
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
+2 -2
View File
@@ -21,8 +21,8 @@
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/timeval.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/weaken.h"
+2 -2
View File
@@ -20,14 +20,14 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sock/syscall_fd.internal.h"
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/errfuns.h"
/**
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/limits.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/paths.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
+2 -2
View File
@@ -27,8 +27,8 @@
#include "libc/cosmo.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -23,7 +23,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -22,7 +22,7 @@
#include "libc/cosmo.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -23,7 +23,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
+2 -2
View File
@@ -22,8 +22,8 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/at.h"
+1 -1
View File
@@ -22,7 +22,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/errfuns.h"
/**
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/errfuns.h"
/**
+2 -2
View File
@@ -22,8 +22,8 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/consts/at.h"
/**
+2 -2
View File
@@ -19,8 +19,8 @@
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -20,7 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/struct/flock.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-nt.internal.h"
+2 -2
View File
@@ -24,8 +24,8 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -22,7 +22,7 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/sysv/consts/f.h"
/**
+1 -1
View File
@@ -23,7 +23,7 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/nt/files.h"
#include "libc/runtime/zipos.internal.h"
+1 -1
View File
@@ -26,7 +26,7 @@
#include "libc/elf/def.h"
#include "libc/elf/tinyelf.internal.h"
#include "libc/errno.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/intrin/directmap.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nt/enum/filelockflags.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
/**
* Acquires lock on file.
+2 -2
View File
@@ -19,14 +19,14 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/stat.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/fmt/wintime.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bsr.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/macros.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nt/enum/fileflagandattributes.h"
+2 -2
View File
@@ -20,8 +20,8 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/struct/stat.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
+2 -2
View File
@@ -23,8 +23,8 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/intrin/weaken.h"
#include "libc/log/log.h"
#include "libc/mem/alloca.h"
+2 -2
View File
@@ -19,11 +19,11 @@
#include "libc/calls/calls.h"
#include "libc/calls/cp.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/fds.h"
#include "libc/calls/struct/statfs-meta.internal.h"
#include "libc/calls/struct/statfs.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/strace.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/errfuns.h"
Loaded 100 of 785 files, more files were not shown because too many files have changed in this diff. Show more