With this commit, <AK/Format.h> has a more supportive role and isn't
used directly.
Essentially, there now is a public 'vformat' function ('v' for vector)
which takes already type erased parameters. The name is choosen to
indicate that this function behaves similar to C-style functions taking
a va_list equivalent.
The interface for frontend users are now 'String::formatted' and
'StringBuilder::appendff'.
Two things I hate about C++:
1. 'int', 'signed int' and 'unsigned int' are two distinct types while
'char, 'signed char' and 'unsigned char' are *three* distinct types.
This is because 'signed int' is an alias for 'int' but 'signed char'
can't be an alias for 'char' because on some weird systems 'char' is
unsigned.
One might think why not do it the other way around, make 'int' an
alias for 'signed int' and 'char' an alias for whatever that is on
the platform, or make 'char' signed on all platforms. But who am I
to ask?
2. 'unsigned long' and 'unsigned long long' are always different types,
even if both are 64 bit numbers.
This commit fixes a few bugs that coming from this.
See Also: 1b3169f405.
OutputMemoryStream was originally a proxy for DuplexMemoryStream that
did not expose any reading API.
Now I need to add another class that is like OutputMemoryStream but only
for static buffers. My first idea was to make OutputMemoryStream do that
too, but I think it's much better to have a distinct class for that.
I originally wanted to call that class FixedOutputMemoryStream but that
name is really cumbersome and it's a bit unintuitive because
InputMemoryStream is already reading from a fixed buffer.
So let's just use DuplexMemoryStream instead of OutputMemoryStream for
any dynamic stuff and create a new OutputMemoryStream for static
buffers.
Leverage constexpr and __builtin_ffs for Bitmap::find_first. Also add
a variant Bitmap::find_one_anywhere that can start scanning at a
provided hint.
Also, merge Bitmap::fill_range into the already existing Bitmap::set_range
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)
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.
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.
This enables a nice warning in case a function becomes dead code. Also, add forgotten
header to Base64.cpp, which would cause an issue later when we enable -Wmissing-declarations.
This template class allows for easy generation of incompatible numeric types.
This is useful whenever code has to handle heterogenous data (like meters and
seconds) but the underlying data types are compatible (like int and int).
The motivation comes from the Kernel's inconsistent use of pid_t for process and
thread IDs even though the ID spaces are incompatible, and translating forth/back
is nontrivial.
Other uses could be units (as described above), or incompatible index systems.
A popular use in real life is image manipulation, when there are multiple
coordinate systems.
I accidently wrote `Span<RemoveConst<T>>` when I meant
`Span<RemoveConst<T>::Type>`.
Changing that wouldn't be enough though, this constructor can only be
defined if T is not const, otherwise it would redefine the copy
constructor. This can be avoided by overloading the cast operator.
The fact that JsonValues can contain 64-bit values isn't a JavaScript
compatible behavior in the first place, but as long as we're supporting
this, we should make sure it works correctly.
- Parsing invalid JSON no longer asserts
Instead of asserting when coming across malformed JSON,
JsonParser::parse now returns an Optional<JsonValue>.
- Disallow trailing commas in JSON objects and arrays
- No longer parse 'undefined', as that is a purely JS thing
- No longer allow non-whitespace after anything consumed by the initial
parse() call. Examples of things that were valid and no longer are:
- undefineddfz
- {"foo": 1}abcd
- [1,2,3]4
- JsonObject.for_each_member now iterates in original insertion order
Get rid of the weird old signature:
- int StringType::to_int(bool& ok) const
And replace it with sensible new signature:
- Optional<int> StringType::to_int() const
And move canonicalized_path() to a static method on LexicalPath.
This is to make it clear that FileSystemPath/canonicalized_path() only
perform *lexical* canonicalization.
The CMake runner looks at the return code if you don't set
the pattern. Since the AK test suite setup doesn't use return
codes, we were missing test failures.
FileSystemPath::has_extension was jumping through hoops and allocating
memory to do a case insensitive comparison needlessly. Extend the
existing String::ends_with method to allow the caller to specify the
case sensitivity required.
With 0 initial capacity, we don't allocate an underlying ByteBuffer
for the StringBuilder, which would then lead to a null String() being
returned from to_string().
This patch makes sure we always build a valid String.
When we switched the Bitmap code to operating 32 bits at a time,
we neglected to look in the trailing remainder bits after the last
full 32-bit word.
This patch fixes that and adds a couple of tests for Bitmap that I
hacked up while tracking down this bug.
I found this bug when noticing that the kernel would OOM while there
were still some pages left in the physical page allocator.
These methods search from the beginning or end of a string for the
first character in the input StringView and returns the position in
the string of the first match. Note that this is not a substring match.
Each comes with single char overloads for efficiency.
With relative filenames in the executable code, the executable is basically not
relocatable. This makes out-of-source builds unneccesery hard. This patchset moves
the relative link into the filesystem: that can be handled much easier :^)
This adds a replace functionality that replaces a string that contains
occurences of a "needle" by a "replacement" value. With "all_occurences"
enabled, all occurences are being replaced, otherwise only the first
occurence is being replaced.
FlyString is a flyweight string class that wraps a RefPtr<StringImpl>
known to be unique among the set of FlyStrings. The class is very
unoptimized at the moment.
When to use FlyString:
- When you want O(1) string comparison
- When you want to deduplicate a lot of identical strings
When not to use FlyString:
- For strings that don't need either of the above features
- For strings that are likely to be unique
This changes copyright holder to myself for the source code files that I've
created or have (almost) completely rewritten. Not included are the files
that were significantly changed by others even though it was me who originally
created them (think HtmlView), or the many other files I've contributed code to.