The implementation in LibC did a timestamp->day-of-week conversion
which looks like a valuable thing to have. But we only need it in
time_to_tm, where we already computed year/month/day -- so let's
consolidate on the day_of_week function in DateTime (which is
getting extracted to AK).
The JS tests pointed out that the implementation in DateTime
had an off-by-one in the month when doing the leap year check,
so this change fixes that bug.
Specifically:
- post-increment actually implemented pre-increment
- helper-templates that provided operator{+,-,*,/}() couldn't possibly work,
because the interface of add (etc) were incompatible (not taking a Checked<>,
and returning void)
Consider the following scenario:
if(condition)
FOO();
else
bar();
Suppose FOO is defined as follows:
#define FOO() { bar(); baz(); }
Then it expands to the following:
if(condition)
// Syntax error, we are not allowed to put a semicolon at the end.
{ bar(); baz(); };
else
bar();
If we define FOO as follows:
#define FOO() do { bar(); baz(); } while(false)
Then it expands to the following:
if(condition)
do { bar(); baz(); } while(false);
else
bar();
Which is correct.
MemoryManager cannot use the Singleton class because
MemoryManager::initialize is called before the global constructors
are run. That caused the Singleton to be re-initialized, causing
it to create another MemoryManager instance.
Fixes#3226
In particular: consistent rounding and extreme values.
Before, rounding was something like 'away from 0.999...', which led to
surprising corner cases in which the value was rounded up.
Now, rounding is always 'down'.
This even works for 0xffffffff, and also for 0xffffffffffffffffULL on 64-bit.
This makes error messages more useful during debugging.
Old:
START Running test compare_views
FAIL: ../AK/Tests/TestStringView.cpp:59: EXPECT_EQ(view1, "foobar") failed
New:
START Running test compare_views
FAIL: ../AK/Tests/TestStringView.cpp:59: EXPECT_EQ(view1, "foobar") failed: LHS="foo", RHS="foobar"
Previously, it would just print something with 'FAIL' to stderr which
would be picked up by CTest. However, some code assumes that
ASSERT_NOT_REACHED() doesn't return, for example:
bool foo(int value) {
switch(value) {
case 0:
return true;
case 1:
return false;
default:
ASSERT_NOT_REACHED();
}
// warning: control reaches end of non-void function
}
Thankfully, this hasn't happened in any other code yet, but it happened
while I was trying something out. Using '==' on two ByteBuffers to check
whether they're equal seemed straight-forward, so I ran into the trap.
This seems to be because ByteBuffer implements 'operator bool', and C++
considers bool to be an integer type. Thus, when trying to find a way to
evaluate '==', it attempts integer promotion, which in turn finds 'operator bool'.
This explains why all non-empty buffers seem to be equal, but different from the
empty one. Also, why comparison seems to be implemented.
clang-format automatically sorts include statements that are in a
'block'. Adding a whitespace prevents this. It is crutial that
<AK/TestSuite.h> is included first because it redefines some macros.
Previously, the implementation would produce one Vector<u8> which
would contain the whole decompressed data. That can be a lot and
even exhaust memory.
With these changes it is still necessary to store the whole input data
in one piece (I am working on this next,) but the output can be read
block by block. (That's not optimal either because blocks can be
arbitrarily large, but it's good for now.)
This class is similar to BufferStream because it is possible to both
read and write to it. However, it differs in the following ways:
- DuplexMemoryStream keeps a history of 64KiB and discards the rest,
BufferStream always keeps everything around.
- DuplexMemoryStream tracks reading and writing seperately, the
following is valid:
DuplexMemoryStream stream;
stream << 42;
int value;
stream >> value;
For BufferStream it would read:
BufferStream stream;
stream << 42;
int value;
stream.seek(0);
stream >> value;
In the future I would like to replace all usages of BufferStream with
InputMemoryStream, OutputMemoryStream (doesn't exist yet) and
DuplexMemoryStream. For now I just add DuplexMemoryStream though.
Fatal errors can not be handeled and lead to an assertion error when the
stream is destroyed. It makes no sense to delay the assertion failure,
instead of setting m_fatal, an assertion should be done directly.
Two changes were made
1. copy_to() and copy_trimmed_to() now return how many bytes were
copied.
2. The argument was changed to Span<typename RemoveConst<T>::Type>
because the following would not work:
ReadonlyBytes bytes0;
Bytes bytes1;
// Won't work because this calls Span<const u8>::copy_to(Span<u8>)
// but the method was defined as Span<const u8>::copy_to(Span<const u8>)
bytes0.copy_to(bytes1);