Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate to c++20 #726

Merged
merged 11 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/ubuntu_install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ jobs:
strategy:
matrix:
include:
- {shared: ON}
- {shared: OFF}
shared: [ON, OFF]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Setup Ninja
Expand Down
41 changes: 0 additions & 41 deletions .github/workflows/ubuntu_old.yml

This file was deleted.

7 changes: 3 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ project(ada
LANGUAGES C CXX
VERSION 2.9.2
)
set(CMAKE_CXX_STANDARD 17)
set(ADA_LIB_VERSION "2.9.2" CACHE STRING "ada library version")
set(ADA_LIB_SOVERSION "2" CACHE STRING "ada library soversion")

Expand Down Expand Up @@ -36,20 +35,20 @@ if(ADA_TESTING OR ADA_BENCHMARKS OR ADA_TOOLS)
CPMAddPackage(
NAME GTest
GITHUB_REPOSITORY google/googletest
VERSION 1.14.0
VERSION 1.15.2
OPTIONS "BUILD_GMOCK OFF" "INSTALL_GTEST OFF"
)
endif()
# We use simdjson in both the benchmarks and tests
if(Git_FOUND AND (ADA_TESTING OR ADA_BENCHMARKS))
CPMAddPackage("gh:simdjson/simdjson@3.9.1")
CPMAddPackage("gh:simdjson/simdjson@3.10.1")
endif()
# We use Google Benchmark, but it does not build under several 32-bit systems.
if(Git_FOUND AND ADA_BENCHMARKS AND (CMAKE_SIZEOF_VOID_P EQUAL 8))
CPMAddPackage(
NAME benchmark
GITHUB_REPOSITORY google/benchmark
GIT_TAG f91b6b4
VERSION 1.9.0
OPTIONS "BENCHMARK_ENABLE_TESTING OFF"
"BENCHMARK_ENABLE_INSTALL OFF"
"BENCHMARK_ENABLE_WERROR OFF"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ standard libraries, follow the RFC 3986. The following table illustrates possibl
### Requirements

The project is otherwise self-contained and it has no dependency.
A recent C++ compiler supporting C++17. We test GCC 9 or better, LLVM 10 or better and Microsoft Visual Studio 2022.
A recent C++ compiler supporting C++20. We test GCC 12 or better, LLVM 12 or better and Microsoft Visual Studio 2022.

## Ada is fast.

Expand Down Expand Up @@ -86,7 +86,7 @@ Linux or macOS users might follow the following instructions if they have a rece
```
2. Compile
```
c++ -std=c++17 -o demo demo.cpp
c++ -std=c++20 -o demo demo.cpp
```
3. `./demo`

Expand Down Expand Up @@ -279,7 +279,7 @@ E.g., if you grab our single-header C++ files (`ada.cpp` and `ada.h`), as well a
you can often compile a C program (`demo.c`) as follows under Linux/macOS systems:

```
c++ -c ada.cpp -std=c++17
c++ -c ada.cpp -std=c++20
cc -c demo.c
c++ demo.o ada.o -o cdemo
./cdemo
Expand Down
2 changes: 1 addition & 1 deletion cmake/ada-flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Expand Down
10 changes: 5 additions & 5 deletions fuzz/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@ mkdir build
AMALGAMATE_OUTPUT_PATH=./build/singleheader python3 singleheader/amalgamate.py

$CXX $CFLAGS $CXXFLAGS \
-std=c++17 \
-std=c++20 \
-I build/singleheader \
-c fuzz/parse.cc -o parse.o

$CXX $CFLAGS $CXXFLAGS $LIB_FUZZING_ENGINE parse.o \
-o $OUT/parse

$CXX $CFLAGS $CXXFLAGS \
-std=c++17 \
-std=c++20 \
-I build/singleheader \
-c fuzz/can_parse.cc -o can_parse.o

$CXX $CFLAGS $CXXFLAGS $LIB_FUZZING_ENGINE can_parse.o \
-o $OUT/can_parse

$CXX $CFLAGS $CXXFLAGS \
-std=c++17 \
-std=c++20 \
-I build/singleheader \
-c fuzz/idna.cc -o idna.o

$CXX $CFLAGS $CXXFLAGS $LIB_FUZZING_ENGINE idna.o \
-o $OUT/idna

$CXX $CFLAGS $CXXFLAGS \
-std=c++17 \
-std=c++20 \
-I build/singleheader \
-c fuzz/url_search_params.cc -o url_search_params.o

$CXX $CFLAGS $CXXFLAGS $LIB_FUZZING_ENGINE url_search_params.o \
-o $OUT/url_search_params

$CXX $CFLAGS $CXXFLAGS \
-std=c++17 \
-std=c++20 \
-I build/singleheader \
-c build/singleheader/ada.cpp -o ada.o

Expand Down
2 changes: 1 addition & 1 deletion fuzz/parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}

// Only used for avoiding dead-code elimination
printf("length of url is %d\n", length);
printf("length of url is %zu\n", length);

return 0;
} // extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
2 changes: 1 addition & 1 deletion include/ada/character_sets-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = {
// F8 F9 FA FB FC FD FE FF
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80};

ada_really_inline bool bit_at(const uint8_t a[], const uint8_t i) {
ada_really_inline constexpr bool bit_at(const uint8_t a[], const uint8_t i) {
return !!(a[i >> 3] & (1 << (i & 7)));
}

Expand Down
2 changes: 1 addition & 1 deletion include/ada/character_sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* @brief Includes the definitions for unicode character sets.
*/
namespace ada::character_sets {
ada_really_inline bool bit_at(const uint8_t a[], uint8_t i);
ada_really_inline constexpr bool bit_at(const uint8_t a[], uint8_t i);
} // namespace ada::character_sets

#endif // ADA_CHARACTER_SETS_H
36 changes: 12 additions & 24 deletions include/ada/checkers-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,28 @@
#ifndef ADA_CHECKERS_INL_H
#define ADA_CHECKERS_INL_H

#include "ada/common_defs.h"

#include <algorithm>
#include <bit>
#include <string_view>
#include <cstring>

namespace ada::checkers {

inline bool has_hex_prefix_unsafe(std::string_view input) {
constexpr bool has_hex_prefix_unsafe(std::string_view input) {
// This is actually efficient code, see has_hex_prefix for the assembly.
uint32_t value_one = 1;
bool is_little_endian = (reinterpret_cast<char*>(&value_one)[0] == 1);
uint16_t word0x{};
std::memcpy(&word0x, "0x", 2); // we would use bit_cast in C++20 and the
// function could be constexpr.
uint16_t two_first_bytes{};
std::memcpy(&two_first_bytes, input.data(), 2);
if (is_little_endian) {
constexpr bool is_little_endian = std::endian::native == std::endian::little;
constexpr auto word0x =
std::bit_cast<uint16_t>(static_cast<uint16_t>(0x7830));
uint16_t two_first_bytes =
static_cast<uint16_t>(input[0]) |
static_cast<uint16_t>((static_cast<uint16_t>(input[1]) << 8));
if constexpr (is_little_endian) {
two_first_bytes |= 0x2000;
} else {
two_first_bytes |= 0x020;
}
return two_first_bytes == word0x;
}

inline bool has_hex_prefix(std::string_view input) {
constexpr bool has_hex_prefix(std::string_view input) {
return input.size() >= 2 && has_hex_prefix_unsafe(input);
}

Expand All @@ -42,26 +38,18 @@ constexpr bool is_alpha(char x) noexcept {
return (to_lower(x) >= 'a') && (to_lower(x) <= 'z');
}

inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept {
constexpr bool is_windows_drive_letter(std::string_view input) noexcept {
return input.size() >= 2 &&
(is_alpha(input[0]) && ((input[1] == ':') || (input[1] == '|'))) &&
((input.size() == 2) || (input[2] == '/' || input[2] == '\\' ||
input[2] == '?' || input[2] == '#'));
}

inline constexpr bool is_normalized_windows_drive_letter(
constexpr bool is_normalized_windows_drive_letter(
std::string_view input) noexcept {
return input.size() >= 2 && (is_alpha(input[0]) && (input[1] == ':'));
}

ada_really_inline bool begins_with(std::string_view view,
std::string_view prefix) {
// in C++20, you have view.begins_with(prefix)
// std::equal is constexpr in C++20
return view.size() >= prefix.size() &&
std::equal(prefix.begin(), prefix.end(), view.begin());
}

} // namespace ada::checkers

#endif // ADA_CHECKERS_INL_H
11 changes: 2 additions & 9 deletions include/ada/checkers.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ constexpr bool is_alpha(char x) noexcept;
*
* @see has_hex_prefix
*/
inline bool has_hex_prefix_unsafe(std::string_view input);
constexpr bool has_hex_prefix_unsafe(std::string_view input);
/**
* @private
* Check whether a string starts with 0x or 0X.
*/
inline bool has_hex_prefix(std::string_view input);
constexpr bool has_hex_prefix(std::string_view input);

/**
* @private
Expand Down Expand Up @@ -79,13 +79,6 @@ inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept;
inline constexpr bool is_normalized_windows_drive_letter(
std::string_view input) noexcept;

/**
* @private
* @warning Will be removed when Ada requires C++20.
*/
ada_really_inline bool begins_with(std::string_view view,
std::string_view prefix);

/**
* @private
* Returns true if an input is an ipv4 address. It is assumed that the string
Expand Down
4 changes: 2 additions & 2 deletions include/ada/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ ada_really_inline void remove_ascii_tab_or_newline(std::string& input) noexcept;
* Return the substring from input going from index pos to the end.
* This function cannot throw.
*/
ada_really_inline std::string_view substring(std::string_view input,
size_t pos) noexcept;
ada_really_inline constexpr std::string_view substring(std::string_view input,
size_t pos) noexcept;

/**
* @private
Expand Down
4 changes: 2 additions & 2 deletions include/ada/url-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ inline std::ostream &operator<<(std::ostream &out, const ada::url &u) {
out.host_start = out.protocol_end;
out.host_end = out.host_start;

if (!has_opaque_path && checkers::begins_with(path, "//")) {
if (!has_opaque_path && path.starts_with("//")) {
// If url's host is null, url does not have an opaque path, url's path's
// size is greater than 1, and url's path[0] is the empty string, then
// append U+002F (/) followed by U+002E (.) to output.
Expand Down Expand Up @@ -196,7 +196,7 @@ inline void url::copy_scheme(const ada::url &u) {
if (port.has_value()) {
output += ":" + get_port();
}
} else if (!has_opaque_path && checkers::begins_with(path, "//")) {
} else if (!has_opaque_path && path.starts_with("//")) {
// If url's host is null, url does not have an opaque path, url's path's
// size is greater than 1, and url's path[0] is the empty string, then
// append U+002F (/) followed by U+002E (.) to output.
Expand Down
4 changes: 2 additions & 2 deletions include/ada/url_aggregator-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ inline void url_aggregator::update_base_authority(
base.protocol_end, base.host_start - base.protocol_end);
ada_log("url_aggregator::update_base_authority ", input);

bool input_starts_with_dash = checkers::begins_with(input, "//");
bool input_starts_with_dash = input.starts_with("//");
uint32_t diff = components.host_start - components.protocol_end;

buffer.erase(components.protocol_end,
Expand Down Expand Up @@ -267,7 +267,7 @@ inline void url_aggregator::update_base_pathname(const std::string_view input) {
ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
ADA_ASSERT_TRUE(validate());

const bool begins_with_dashdash = checkers::begins_with(input, "//");
const bool begins_with_dashdash = input.starts_with("//");
if (!begins_with_dashdash && has_dash_dot()) {
ada_log("url_aggregator::update_base_pathname has /.: \n", to_diagram());
// We must delete the ./
Expand Down
6 changes: 3 additions & 3 deletions singleheader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ This will create two new files (ada.h and ada.cpp).
You can then compile the demo file as follows:

```
c++ -std=c++17 -c demo.cpp
c++ -std=c++20 -c demo.cpp
```

It will produce a binary file (e.g., demo.o) which contains ada.cpp.

```
c++ -std=c++17 -o demo demo.cpp
c++ -std=c++20 -o demo demo.cpp
./demo
```

Expand All @@ -29,7 +29,7 @@ You may build and link using CMake (--target demo), because CMake can configure
You may also build a C executable.

```
c++ -c ada.cpp -std=c++17
c++ -c ada.cpp -std=c++20
cc -c demo.c
c++ demo.o ada.o -o cdemo
./cdemo
Expand Down
4 changes: 2 additions & 2 deletions src/checkers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept {
return false;
}
// It must start with 0x.
if (!std::equal(view.begin(), view.begin() + 2, "0x")) {
if (!view.starts_with("0x")) {
return false;
}
// We must allow "0x".
Expand All @@ -59,7 +59,7 @@ ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept {
// for use with path_signature, we include all characters that need percent
// encoding.
static constexpr std::array<uint8_t, 256> path_signature_table =
[]() constexpr {
[]() consteval {
std::array<uint8_t, 256> result{};
for (size_t i = 0; i < 256; i++) {
if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
Expand Down
Loading