Commit graph

258 commits

Author SHA1 Message Date
Lenny Maiorani 6d6b3f9523 Badge: Access to underlying type
Problem:
- Access to the underlying type is not provided. This limits
  metaprogramming and usage in function templates.

Solution:
- Provide public access to the underlying type.
- Add test to ensure the underlying type is accessible.
2021-01-15 09:44:21 +01:00
Lenny Maiorani d11727ff28 AK: Implement generic any_of algorithm
Problem:
- Raw loops are often written to validate that any values in a
  container meet a predicate, but raw loops are not as expressive as
  functions implementing well-named algorithms and are error-prone.

Solution:
- Implement a very generic form of `any_of`.
2021-01-15 09:42:42 +01:00
AnotherTest 39442e6d4f AK: Add String{View,}::find(StringView)
I personally mistook `find_first_of(StringView)` to be analogous to this
so let's add a `find()` method that actually searches the string.
2021-01-12 23:36:20 +01:00
Andreas Kling 1a08ac72ad LibC+Everywhere: Remove open_with_path_length() in favor of open()
This API was a mostly gratuitous deviation from POSIX that gave up some
portability in exchange for avoiding the occasional strlen().

I don't think that was actually achieving anything valuable, so let's
just chill out and have the same open() API as everyone else. :^)
2021-01-12 23:34:01 +01:00
Lenny Maiorani e6f907a155 AK: Simplify constructors and conversions from nullptr_t
Problem:
- Many constructors are defined as `{}` rather than using the ` =
  default` compiler-provided constructor.
- Some types provide an implicit conversion operator from `nullptr_t`
  instead of requiring the caller to default construct. This violates
  the C++ Core Guidelines suggestion to declare single-argument
  constructors explicit
  (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c46-by-default-declare-single-argument-constructors-explicit).

Solution:
- Change default constructors to use the compiler-provided default
  constructor.
- Remove implicit conversion operators from `nullptr_t` and change
  usage to enforce type consistency without conversion.
2021-01-12 09:11:45 +01:00
Lenny Maiorani 1b2364846f SinglyLinkedList: Implement find in terms of AK::find
Problem:
- The implementation of `find` is coupled to the implementation of
  `SinglyLinkedList`.

Solution:
- Decouple the implementation of `find` from the class by using a
  generic `find` algorithm.
2021-01-11 19:45:05 +01:00
Lenny Maiorani 853cb8af5c DoublyLinkedList: Implement find in terms of AK::find
Problem:
- The implementation of `find` is coupled to the implementation of
  `DoublyLinkedList`.
- `append` and `prepend` are implemented multiple times so that
  r-value references can be moved from into the new node. This is
  probably not called very often because a pr-value or x-value needs
  to be used here.

Solution:
- Decouple the implementation of `find` from the class by using a
  generic `find` algorithm.
- Make `append` and `prepend` be function templates so that they can
  have binding references which can be forwarded.
2021-01-11 19:45:05 +01:00
Lenny Maiorani f99d1d3bd7 Vector: Implement find, find_if, find_first_matching in terms of AK::find*
Problem:
- The implementation of `find` is coupled to the implementation of `Vector`.
- `Vector::find` takes the predicate by value which might be expensive.

Solution:
- Decouple the implementation of `find` from `Vector` by using a
  generic `find` algorithm.
- Change the name of `find` with a predicate to `find_if` so that a
  binding reference can be used and the predicate can be forwarded to
  avoid copies.
- Change all the `find(pred)` call sites to use `find_if`.
2021-01-11 19:45:05 +01:00
Lenny Maiorani 4333a9a8d6 AK: Find a value in any container offering iterators
Problem:
- `find` is implemented inside of each container. This coupling
  requires that each container needs to individually provide `find`.

Solution:
- Decouple the `find` functionality from the container. This allows
  provides a `find` algorithm which can work with all
  containers. Containers can still provide their own `find` in the
  case where it can be optimized.
- This also allows for searching sub-ranges of a container rather than
  the entire container as some of the container-specific member
  functions enforced.

Note:
- @davidstone's talk from 2015 C++Now conference entitled "Functions
  Want to be Free" encourages this style:
  (https://www.youtube.com/watch?v=_lVlC0xzXDc), but it does come at
  the cost of composability.
- A logical follow-on to this is to provide a mechanism to use a
  short-hand function which automatically searches the entire
  container. This could automatically use the container-provided
  version if available so that functions which provide their own
  optimized version get the benefit.
2021-01-11 19:45:05 +01:00
Lenny Maiorani 700f213011 TestTypeTraits: Fix incorrectly namespaced nullptr_t
Problem:
- Clang ToT fails to build `AK/Tests/TestTypeTraits.cpp` because
  `nullptr_t` is missing the `std` namespace qualifier.

Solution:
- Prepend the namespace qualifier.
2021-01-10 18:20:14 +01:00
asynts 1160817a9e AK: Add Formatter<FormatString> as helper class. 2021-01-09 21:11:09 +01:00
AnotherTest f3ecea1fb3 AK: Add String{,View}::is_whitespace()
+Tests!
2021-01-03 10:47:29 +01:00
asynts 3aaece8733 AK: Remove redundant compare() functions. 2021-01-02 01:37:22 +01:00
asynts 632ff01e17 Piggyback: AK: Add formatter for std::nullptr_t. 2021-01-02 01:37:22 +01:00
asynts e77031ce67 AK: Deal with unsigned integers in binary search. 2021-01-01 22:23:13 +01:00
asynts a7c014125f AK: Add operator* and operator-> overloads in Optional. 2020-12-31 00:51:12 +01:00
asynts 7e62ffbc6e AK+Format: Remove TypeErasedFormatParams& from format function. 2020-12-30 20:33:53 +01:00
Andrew Kaster 7d49ea9836 AK: Replace some SFINAE with requires clauses, clean up existing ones
Add requires clauses to constraints on InputStream and OutputStream
operator<< / operator>>. Make the constraint on String::number a
requires clause instead of SFINAE. Also, fix some unecessary IsSame in
Trie where specialized traits exist for the given use cases.
2020-12-30 13:28:49 +01:00
Andrew Kaster b4eb734204 AK: Add tests for type traits and IndexSequence
Use TypeLists to add test for IsIntegral, IsFloatingPoint, IsVoid,
IsNullPointer, IsArithmetic, IsFundamental, and AddConst type traits.

More can "easily" be added once the TypeList and macro magic is squinted
at for long enough :).
2020-12-30 11:32:20 +01:00
Andrew Kaster 874df07ffd AK: Correct name in TestMain for TestTrie
Copy paste error :)
2020-12-30 11:32:20 +01:00
asynts 50d24e4f98 AK: Make binary_search signature more generic. 2020-12-30 02:13:30 +01:00
Linus Groh 1ed72cc580 AK: Add HashMap(std::initializer_list<Entry>) constructor
This allows us to construct a HashMap from an initializer list like so:

    HashMap<K, V> hash_map = { { K, V }, { K, V } { K, V } };
2020-12-29 15:22:15 +01:00
asynts 620b73b3d5 AK+Format: Accept unsigned long in replacement fields.
I ran into this exact but at least twenty times in Serenity alone. The
C++ Standard dictates that 'unsigned long' and 'unsigned long long' are
distinct types even though on most platforms they are usually both 64
bit integers.

Also it wasn't possible to evaluate IsIntegral<T> for types that were
not integers since it used MakeUnsigned<T> internally.
2020-12-29 02:36:32 +01:00
AnotherTest cbe0a8b403 AK: Allow trailing '*'s in a glob pattern to match nothing
Fixes part of #4607.
2020-12-29 02:35:52 +01:00
AnotherTest 1c9d28d212 AK: Fix busted Trie test
This wasn't testing anything ^^'
2020-12-26 12:32:27 +01:00
AnotherTest cb3348191b AK: Add a prefix tree implementation
`AK::Trie` can be keyed by any given hashable type, and can store any
metadata (including nothing at all).
Also adds a test.
2020-12-26 11:54:54 +01:00
Lenny Maiorani b2316701a8 Everywhere: void arguments to C functions
Problem:
- C functions with no arguments require a single `void` in the argument list.

Solution:
- Put the `void` in the argument list of functions in C header files.
2020-12-26 10:10:27 +01:00
Lenny Maiorani 8e1af483be CMake: Remove file globbing in AK/Tests
Problem:
- File globbing is performed at the time of build system
  generation. Any files which are not there at that time are not
  included. So, when a new file is added it is not built unless the
  build system is recreated.

Solution:
- Remove globbing from AK/Tests directory in favor of explicitly
  listing the files.
2020-12-23 20:51:29 +01:00
Sahan Fernando 1a12f964d4 AK: Test StringUtils::convert_to_int for different types 2020-12-21 00:15:44 +01:00
Lenny Maiorani 765936ebae
Everywhere: Switch from (void) to [[maybe_unused]] (#4473)
Problem:
- `(void)` simply casts the expression to void. This is understood to
  indicate that it is ignored, but this is really a compiler trick to
  get the compiler to not generate a warning.

Solution:
- Use the `[[maybe_unused]]` attribute to indicate the value is unused.

Note:
- Functions taking a `(void)` argument list have also been changed to
  `()` because this is not needed and shows up in the same grep
  command.
2020-12-21 00:09:48 +01:00
asynts 72cbca892a AK: Remove bogus test case for CircularDuplexStream. 2020-12-19 23:29:40 +01:00
xspager dd198e1a29 AK::URL: Fix setting the port number in the case it was the last element of the URL 2020-12-12 20:09:42 +01:00
AnotherTest ec4980e875 AK: Ensure dual_pivot_quick_sort does not copy the pivots
Also add a test that would fail to compile if quick_sort tries to copy
anything :P
2020-12-10 11:02:02 +01:00
asynts 5b104eedaf AK: Fix offset calculation error in DuplexMemoryStream::write. 2020-12-09 21:17:24 +01:00
asynts ce15c9a04c AK: Fix unsigned integer underflow in DuplexMemoryStream::write. 2020-12-09 21:17:24 +01:00
AnotherTest 036b39cdfd AK: Implement memmem() for iterator haystacks
This uses the KMP algorithm to implement the search.
Also replaces the slow route of the normal memmem() with KMP, which
should be fairly faster (O(n + m) as opposed to O(n * m)) :^)
2020-12-08 23:34:38 +01:00
Andrew Kaster 6919639190 AK: Add test for the will_be_destroyed and one_ref_left magic functions
Fixes a regression introduced by 5c1b3ce. The commit description there
asserts that the changes allow calling will_be_destroyed and
one_ref_left, which are not required to be const qualified. The
implementation in fact does require the methods to be const qualified,
because we forgot to add the const_cast inside the decltypes :^)
2020-12-06 15:49:33 +01:00
Linus Groh ba020a5907 AK: Fix logic error in urldecode() percent-decoding
We also need to append the raw consumed value if *either* of the two
characters after the % isn't a hex digit, not only if *both* aren't.

Fixes #4257.
2020-11-30 11:35:01 +01:00
Lenny Maiorani 840c3b501d NeverDestroyed: Add tests
Problem:
- It is difficult to refactor because there are no tests to bind the
functionality.
- Arguments are not forwarded correctly to the constructor.

Solution:
- Add tests.
- Change constructor to take forwarding references.
2020-11-22 10:54:33 +01:00
Lenny Maiorani 6e7e16a7ed AK: Implement generic all_of algorithm
Problem:
- Raw loops are often written to validate that all values in a
  container meet a predicate, but raw loops are not as expressive as
  functions implementing well-named algorithms and are error-prone.

Solution:
- Implement a very generic form of `all_of`.
2020-11-21 19:25:14 +01:00
Lenny Maiorani bdf3baa8ac MACAddress: AK::Array as member variable instead of C-array
Problem:
- C-style arrays do not automatically provide bounds checking and are
  less type safe overall.
- `__builtin_memcmp` is not a constant expression in the current gcc.

Solution:
- Change private m_data to be AK::Array.
- Eliminate constructor from C-style array.
- Change users of the C-style array constructor to use the default
  constructor.
- Change `operator==()` to be a hand-written comparison loop and let
  the optimizer figure out to use `memcmp`.
2020-11-20 21:18:14 +01:00
Lenny Maiorani 964d2e0dd0 MACAddress: constexpr support
Problem:
- `MACAddress` class is not usable in a compile-time context.
- `__builtin_memcpy` is not constexpr in gcc.

Solution:
- Decorate functions with `constexpr` keyword.
- Use default constructors and destructors.
- Change `__builtin_memcpy` to a hand-written `for` loop and let the
  compiler's optimizer take care of it.
- Add tests to ensure compile-time capabilities.
2020-11-19 14:03:47 +01:00
AnotherTest 4c343c5f26 AK: Fix OOB access in DuplexMemoryStream::offset_of()
This fixes an OOB access when the last read/written chunk is empty (as we _just_
started on a new chunk).
Also adds a test case to TestMemoryStream.
Found via human fuzzing in the shell:
```sh
for $(cat /dev/urandom) {
    clear
    match $it {
        ?* as (x) {
            echo $x
            sleep 1
        }
    }
}
```
would assert at some point.
2020-11-17 17:07:39 +01:00
Linus Groh d6a4c0c79e AK: Trim whitespace in StringUtils::convert_to_{int,uint,uint_from_hex}()
Personally I found this unintuitive at first, but it is in line with
strtol(), Python's int() or JavaScript's parseInt(), so I guess it makes
sense.

Fixes #4097.
2020-11-17 09:48:35 +01:00
Lenny Maiorani fd97f23cef MACAddress: Unit testing for basic functionality
Problem:
- There are no unit tests for `MACAddress` class. This makes it
  difficult to refactor and ensure the same behavior.
- `m_data` private member variable is uninitialized leading to undefined
  behavior of `is_zero()`.

Solution:
- Add unit tests to cover basic functionality.
- Initialize `m_data`.
2020-11-17 09:47:50 +01:00
Lenny Maiorani 2a06b026ef Vector: C++20 equality operators
Problem:
- C++20 changes the way equality operators are generated. This results
  in overload ambiguity as reported by clang.

Solution:
- Remove `AK::Vector::operator!=` because it will be automatically
  generated in terms of `AK::Vector::operator==`.
- Change `AK::Vector::operator==` to be a function template so that
  overload resolution is not confused about `a == b` vs `b == a`.
- Add tests to ensure the behavior works.

Notes:
- There is more info available at
  https://brevzin.github.io/c++/2019/07/28/comparisons-cpp20/ for
  deeper discussion about overload resolution, operator rewriting, and
  generated functions.
2020-11-16 10:06:23 +01:00
Linus Groh d3ee3fc68a AK: Fix StringUtils::contains() case insensitive search
It would incorrectly return false if needle was at the end the string.
2020-11-14 10:11:26 +01:00
Lenny Maiorani f5ced347e6 AK: Prefer using instead of typedef
Problem:
- `typedef` is a keyword which comes from C and carries with it old
  syntax that is hard to read.
- Creating type aliases with the `using` keyword allows for easier
  future maintenance because it supports template syntax.
- There is inconsistent use of `typedef` vs `using`.

Solution:
- Use `clang-tidy`'s checker called `modernize-use-using` to update
  the syntax to use the newer syntax.
- Remove unused functions to make `clang-tidy` happy.
- This results in consistency within the codebase.
2020-11-12 10:19:04 +01:00
Lenny Maiorani 72d019f4a4 IPv4Address: constexpr support
Problem:
- IPv4Address class cannot be used in a compile-time context.
- A union is used by initializing one of the members and reading the
  non-active member. This is undefined behavior and not permitted in a
  `constexpr` context.

Solution:
- Eliminate undefined behavior by changing to a simple `u32` for
  storage instead of the union and performing mask/shift calculations
  for obtaining the individual octets.
- Decorate functions with `constexpr` where possible. Currently string
  formatting and optionals are not `constexpr`-capable so functions
  using those are left out.
- Modify tests to validate functionality in a `constexpr` context in
  addition to the run-time tests already being run. This ensures that
  functionality is the same in both contexts.
2020-11-11 12:18:25 +01:00
Tom 75f61fe3d9 AK: Make RefPtr, NonnullRefPtr, WeakPtr thread safe
This makes most operations thread safe, especially so that they
can safely be used in the Kernel. This includes obtaining a strong
reference from a weak reference, which now requires an explicit
call to WeakPtr::strong_ref(). Another major change is that
Weakable::make_weak_ref() may require the explicit target type.
Previously we used reinterpret_cast in WeakPtr, assuming that it
can be properly converted. But WeakPtr does not necessarily have
the knowledge to be able to do this. Instead, we now ask the class
itself to deliver a WeakPtr to the type that we want.

Also, WeakLink is no longer specific to a target type. The reason
for this is that we want to be able to safely convert e.g. WeakPtr<T>
to WeakPtr<U>, and before this we just reinterpret_cast the internal
WeakLink<T> to WeakLink<U>, which is a bold assumption that it would
actually produce the correct code. Instead, WeakLink now operates
on just a raw pointer and we only make those constructors/operators
available if we can verify that it can be safely cast.

In order to guarantee thread safety, we now use the least significant
bit in the pointer for locking purposes. This also means that only
properly aligned pointers can be used.
2020-11-10 19:11:52 +01:00