From 03a58856a428cf2befa68344cd9d61ca40e06ffe Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 01:50:40 -0500 Subject: [PATCH 01/59] re2 regex for BO_ and VAL_ messages --- opendbc/can/dbc.cc | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/opendbc/can/dbc.cc b/opendbc/can/dbc.cc index 8f361af1fd..c567c80e8a 100644 --- a/opendbc/can/dbc.cc +++ b/opendbc/can/dbc.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -14,11 +15,11 @@ #include "opendbc/can/common.h" #include "opendbc/can/common_dbc.h" -std::regex bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))"); +RE2 bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))"); std::regex sg_regexp(R"(^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); std::regex sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); -std::regex val_regexp(R"(VAL_ (\w+) (\w+) (\s*[-+]?[0-9]+\s+\".+?\"[^;]*))"); -std::regex val_split_regexp{R"([\"]+)"}; // split on " +RE2 val_regexp(R"(VAL_ (\w+) (\w+) (.*))"); +RE2 val_split_regexp(R"((([0-9]) \"(.+?)\"))"); #define DBC_ASSERT(condition, message) \ do { \ @@ -121,6 +122,7 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch std::string line; int line_num = 0; + std::string match1, match2, match3; std::smatch match; // TODO: see if we can speed up the regex statements in this loop, SG_ is specifically the slowest while (std::getline(stream, line)) { @@ -128,13 +130,13 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch line_num += 1; if (startswith(line, "BO_ ")) { // new group - bool ret = std::regex_match(line, match, bo_regexp); + bool ret = RE2::FullMatch(line, bo_regexp, &match1, &match2, &match3); DBC_ASSERT(ret, "bad BO: " << line); Msg& msg = dbc->msgs.emplace_back(); - address = msg.address = std::stoul(match[1].str()); // could be hex - msg.name = match[2].str(); - msg.size = std::stoul(match[3].str()); + address = msg.address = std::stoul(match1); // could be hex + msg.name = match2; + msg.size = std::stoul(match3); // check for duplicates DBC_ASSERT(address_set.find(address) == address_set.end(), "Duplicate message address: " << address << " (" << msg.name << ")"); @@ -176,21 +178,23 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch signal_name_sets[address].insert(sig.name); } else if (startswith(line, "VAL_ ")) { // new signal value/definition - bool ret = std::regex_search(line, match, val_regexp); + bool ret = RE2::FullMatch(line, val_regexp, &match1, &match2, &match3); DBC_ASSERT(ret, "bad VAL: " << line); auto& val = dbc->vals.emplace_back(); - val.address = std::stoul(match[1].str()); // could be hex - val.name = match[2].str(); + val.address = std::stoul(match1); // could be hex + val.name = match2; - auto defvals = match[3].str(); - std::sregex_token_iterator it{defvals.begin(), defvals.end(), val_split_regexp, -1}; + auto defvals = match3; // convert strings to UPPER_CASE_WITH_UNDERSCORES - std::vector words{it, {}}; - for (auto& w : words) { - w = trim(w); - std::transform(w.begin(), w.end(), w.begin(), ::toupper); - std::replace(w.begin(), w.end(), ' ', '_'); + std::vector words; + std::string full_match, number, word; + while (RE2::PartialMatch(defvals, val_split_regexp, &full_match, &number, &word)) { + std::transform(word.begin(), word.end(), word.begin(), ::toupper); + std::replace(word.begin(), word.end(), ' ', '_'); + word = trim(word); + words.push_back(number + " " + word); + defvals = defvals.substr(full_match.length(), defvals.length() - full_match.length()); } // join string std::stringstream s; From 268a89d4b38ad9bfd32121873bbd05fb21bb3348 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 02:38:26 -0500 Subject: [PATCH 02/59] old regex fully replaced --- opendbc/can/dbc.cc | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/opendbc/can/dbc.cc b/opendbc/can/dbc.cc index c567c80e8a..1934c5b34e 100644 --- a/opendbc/can/dbc.cc +++ b/opendbc/can/dbc.cc @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -16,8 +15,8 @@ #include "opendbc/can/common_dbc.h" RE2 bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))"); -std::regex sg_regexp(R"(^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); -std::regex sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); +RE2 sg_regexp(R"(^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); +RE2 sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); RE2 val_regexp(R"(VAL_ (\w+) (\w+) (.*))"); RE2 val_split_regexp(R"((([0-9]) \"(.+?)\"))"); @@ -122,8 +121,7 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch std::string line; int line_num = 0; - std::string match1, match2, match3; - std::smatch match; + std::string match1, match2, match3, match4, match5, match6, match7, ignore; // TODO: see if we can speed up the regex statements in this loop, SG_ is specifically the slowest while (std::getline(stream, line)) { line = trim(line); @@ -148,20 +146,18 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch } } else if (startswith(line, "SG_ ")) { // new signal - int offset = 0; - if (!std::regex_search(line, match, sg_regexp)) { - bool ret = std::regex_search(line, match, sgm_regexp); + if (!RE2::FullMatch(line, sg_regexp, &match1, &match2, &match3, &match4, &match5, &match6, &match7)) { + bool ret = RE2::FullMatch(line, sgm_regexp, &match1, &ignore, &match2, &match3, &match4, &match5, &match6, &match7); DBC_ASSERT(ret, "bad SG: " << line); - offset = 1; } Signal& sig = signals[address].emplace_back(); - sig.name = match[1].str(); - sig.start_bit = std::stoi(match[offset + 2].str()); - sig.size = std::stoi(match[offset + 3].str()); - sig.is_little_endian = std::stoi(match[offset + 4].str()) == 1; - sig.is_signed = match[offset + 5].str() == "-"; - sig.factor = std::stod(match[offset + 6].str()); - sig.offset = std::stod(match[offset + 7].str()); + sig.name = match1; + sig.start_bit = std::stoi(match2); + sig.size = std::stoi(match3); + sig.is_little_endian = std::stoi(match4) == 1; + sig.is_signed = match5 == "-"; + sig.factor = std::stod(match6); + sig.offset = std::stod(match7); set_signal_type(sig, checksum, dbc_name, line_num); if (sig.is_little_endian) { sig.lsb = sig.start_bit; @@ -190,9 +186,9 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch std::vector words; std::string full_match, number, word; while (RE2::PartialMatch(defvals, val_split_regexp, &full_match, &number, &word)) { + word = trim(word); std::transform(word.begin(), word.end(), word.begin(), ::toupper); std::replace(word.begin(), word.end(), ' ', '_'); - word = trim(word); words.push_back(number + " " + word); defvals = defvals.substr(full_match.length(), defvals.length() - full_match.length()); } From 0d49db3d601d8b0b5029603867974695560c575d Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 11:05:05 -0500 Subject: [PATCH 03/59] install and link re2 (Ubuntu CI only) --- .github/workflows/tests.yml | 4 +++- opendbc/can/SConscript | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ddbcbc2678..f80294ce37 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,4 +17,6 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: ./test.sh + - run: | + apt-get install -y --no-install-recommends libre2-dev + ./test.sh diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index 9f6825a93f..22f1b19fbb 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -15,8 +15,8 @@ libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAG lenv = envCython.Clone() lenv["LIBPATH"].append(Dir(".")) lenv["RPATH"] = [libdbc[0].dir.abspath, ] -parser = lenv.Program('parser_pyx.so', 'parser_pyx.pyx', LIBS=[common, libdbc[0].name]) -packer = lenv.Program('packer_pyx.so', 'packer_pyx.pyx', LIBS=[common, libdbc[0].name]) +parser = lenv.Program('parser_pyx.so', 'parser_pyx.pyx', LIBS=[common, libdbc[0].name, 're2']) +packer = lenv.Program('packer_pyx.so', 'packer_pyx.pyx', LIBS=[common, libdbc[0].name, 're2']) opendbc_python = Alias("opendbc_python", [parser, packer]) From 75627ee9334e86343170505eee36d0b311f630d1 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 11:07:30 -0500 Subject: [PATCH 04/59] install and link re2 (Ubuntu CI only) --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f80294ce37..e90c4eaa3c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,5 +18,5 @@ jobs: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - run: | - apt-get install -y --no-install-recommends libre2-dev - ./test.sh + apt-get install -y --no-install-recommends libre2-dev + ./test.sh From aa6425c5588d229977ee621dfe69409ed68aab08 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 11:08:54 -0500 Subject: [PATCH 05/59] install and link re2 (Ubuntu CI only) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e90c4eaa3c..68f1a14259 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,5 +18,5 @@ jobs: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - run: | - apt-get install -y --no-install-recommends libre2-dev + sudo apt-get install -y --no-install-recommends libre2-dev ./test.sh From 6322eaf449d998de0f1e1ed45eecf21dd9f4182d Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 11:19:43 -0500 Subject: [PATCH 06/59] install re2 (MacOS CI) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 68f1a14259..403dc8281d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,5 +18,5 @@ jobs: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - run: | - sudo apt-get install -y --no-install-recommends libre2-dev + [[ $OSTYPE = "darwin" ]] && brew install re2 || sudo apt-get install -y --no-install-recommends libre2-dev ./test.sh From 3a063e0e4707f15bb1e17abcdbd82dc1b1b25e21 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 11:28:46 -0500 Subject: [PATCH 07/59] debug os-aware library install --- .github/workflows/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 403dc8281d..3ce0f488ad 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,5 +18,6 @@ jobs: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - run: | - [[ $OSTYPE = "darwin" ]] && brew install re2 || sudo apt-get install -y --no-install-recommends libre2-dev + echo $OSTYPE + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 # TODO: move to container with re2 library built-in ./test.sh From ed4dcc36056039513b9f47df9ba38b6e4e62c566 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 11:44:03 -0500 Subject: [PATCH 08/59] =?UTF-8?q?link=20re2=20(macOS)=20=F0=9F=A4=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tests.yml | 1 - opendbc/can/SConscript | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3ce0f488ad..c987673b38 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,6 +18,5 @@ jobs: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - run: | - echo $OSTYPE [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 # TODO: move to container with re2 library built-in ./test.sh diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index 22f1b19fbb..047e88161c 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -8,7 +8,7 @@ src = ["dbc.cc", "parser.cc", "packer.cc", "common.cc"] # shared library for openpilot LINKFLAGS = envDBC["LINKFLAGS"] if arch == "Darwin": - LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib"] + LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib,-lre2"] libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAGS) # Build packer and parser From 951c72b1fd812292ce62298a81835b26422bd69d Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 12:11:16 -0500 Subject: [PATCH 09/59] WIP: debug macOS re2 linking --- .github/workflows/tests.yml | 2 ++ opendbc/can/SConscript | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c987673b38..60f95adf06 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,5 +18,7 @@ jobs: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - run: | + find /opt -name "re2.h" + find /usr -name "re2.h" [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 # TODO: move to container with re2 library built-in ./test.sh diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index 047e88161c..71b9a7934e 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -8,8 +8,8 @@ src = ["dbc.cc", "parser.cc", "packer.cc", "common.cc"] # shared library for openpilot LINKFLAGS = envDBC["LINKFLAGS"] if arch == "Darwin": - LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib,-lre2"] -libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAGS) + LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib"] +libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, 're2',], LINKFLAGS=LINKFLAGS) # Build packer and parser lenv = envCython.Clone() From 9b53af458401f0d82f4ccfefe6a151cb0d79ddb6 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 12:16:26 -0500 Subject: [PATCH 10/59] auto-install re2 when missing --- .github/workflows/tests.yml | 6 +----- test.sh | 7 +++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 60f95adf06..ddbcbc2678 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,8 +17,4 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: | - find /opt -name "re2.h" - find /usr -name "re2.h" - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 # TODO: move to container with re2 library built-in - ./test.sh + - run: ./test.sh diff --git a/test.sh b/test.sh index 3b2b847e6b..0fa0c52337 100755 --- a/test.sh +++ b/test.sh @@ -13,6 +13,13 @@ if ! command -v uv &>/dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh fi +mkdir $DIR/.tmp +echo '#include +RE2 x("");int main(void) {return 0;}' > .tmp/re2.c; g++ -o .tmp/re2.o .tmp/re2.c -lre2 && { + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 +} +rm -rf .tmp + uv sync --all-extras source .venv/bin/activate From 4f86c546e2165c2616f9cb61f696c3984c225988 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 12:25:20 -0500 Subject: [PATCH 11/59] auto-install re2 when missing --- test.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test.sh b/test.sh index 0fa0c52337..56a2ae2fd3 100755 --- a/test.sh +++ b/test.sh @@ -13,12 +13,16 @@ if ! command -v uv &>/dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh fi -mkdir $DIR/.tmp -echo '#include -RE2 x("");int main(void) {return 0;}' > .tmp/re2.c; g++ -o .tmp/re2.o .tmp/re2.c -lre2 && { +mkdir -p $DIR/.tmp +echo ' +#include +RE2 x("");int main(void) {return 0;} +' > $DIR/.tmp/re2.c +g++ -o $DIR/.tmp/re2.o $DIR/.tmp/re2.c -lre2 &>/dev/null || { + echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 } -rm -rf .tmp +rm -rf $DIR/.tmp uv sync --all-extras source .venv/bin/activate From 46a4ef512d2057beb49e61106c609556bc724017 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 12:36:39 -0500 Subject: [PATCH 12/59] auto-install re2 when missing --- test.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test.sh b/test.sh index 56a2ae2fd3..fb7511ce33 100755 --- a/test.sh +++ b/test.sh @@ -2,17 +2,11 @@ set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" -cd $DIR # TODO: why doesn't uv do this? export PYTHONPATH=$DIR # *** dependencies install *** -if ! command -v uv &>/dev/null; then - echo "'uv' is not installed. Installing 'uv'..." - curl -LsSf https://astral.sh/uv/install.sh | sh -fi - mkdir -p $DIR/.tmp echo ' #include @@ -24,6 +18,13 @@ g++ -o $DIR/.tmp/re2.o $DIR/.tmp/re2.c -lre2 &>/dev/null || { } rm -rf $DIR/.tmp +cd $DIR + +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh +fi + uv sync --all-extras source .venv/bin/activate From e1700e67fe8eb940cc0fe0786d28b6f723b1c8da Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 12:40:26 -0500 Subject: [PATCH 13/59] auto-install re2 when missing --- .github/workflows/tests.yml | 4 +++- test.sh | 13 ++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ddbcbc2678..310f16ad40 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,4 +17,6 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: ./test.sh + - run: | + [[ $OSTYPE = "darwin"* ]] && brew install re2 + ./test.sh diff --git a/test.sh b/test.sh index fb7511ce33..56a2ae2fd3 100755 --- a/test.sh +++ b/test.sh @@ -2,11 +2,17 @@ set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR # TODO: why doesn't uv do this? export PYTHONPATH=$DIR # *** dependencies install *** +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh +fi + mkdir -p $DIR/.tmp echo ' #include @@ -18,13 +24,6 @@ g++ -o $DIR/.tmp/re2.o $DIR/.tmp/re2.c -lre2 &>/dev/null || { } rm -rf $DIR/.tmp -cd $DIR - -if ! command -v uv &>/dev/null; then - echo "'uv' is not installed. Installing 'uv'..." - curl -LsSf https://astral.sh/uv/install.sh | sh -fi - uv sync --all-extras source .venv/bin/activate From bfb11a4451df19bc1f149db58cfc48efc596eeee Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 12:45:43 -0500 Subject: [PATCH 14/59] debug masOS re2 linking --- .github/workflows/tests.yml | 4 +--- test.sh | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 310f16ad40..ddbcbc2678 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,6 +17,4 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: | - [[ $OSTYPE = "darwin"* ]] && brew install re2 - ./test.sh + - run: ./test.sh diff --git a/test.sh b/test.sh index 56a2ae2fd3..14bf110b04 100755 --- a/test.sh +++ b/test.sh @@ -20,7 +20,7 @@ RE2 x("");int main(void) {return 0;} ' > $DIR/.tmp/re2.c g++ -o $DIR/.tmp/re2.o $DIR/.tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2; find /opt/homebrew/ -name "re2.h" } rm -rf $DIR/.tmp From c99145c2e572f4124566437cd195c13414d6aaaa Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 13:08:31 -0500 Subject: [PATCH 15/59] =?UTF-8?q?debug=20masOS=20re2=20linking=20?= =?UTF-8?q?=F0=9F=8F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- opendbc/can/SConscript | 2 +- test.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index 71b9a7934e..22f1b19fbb 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -9,7 +9,7 @@ src = ["dbc.cc", "parser.cc", "packer.cc", "common.cc"] LINKFLAGS = envDBC["LINKFLAGS"] if arch == "Darwin": LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib"] -libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, 're2',], LINKFLAGS=LINKFLAGS) +libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAGS) # Build packer and parser lenv = envCython.Clone() diff --git a/test.sh b/test.sh index 14bf110b04..56a2ae2fd3 100755 --- a/test.sh +++ b/test.sh @@ -20,7 +20,7 @@ RE2 x("");int main(void) {return 0;} ' > $DIR/.tmp/re2.c g++ -o $DIR/.tmp/re2.o $DIR/.tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2; find /opt/homebrew/ -name "re2.h" + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 } rm -rf $DIR/.tmp From 39c2eb62ec797031f4bc5e96d84f8987dba9dbc5 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 14:26:33 -0500 Subject: [PATCH 16/59] readme instructions updated + use all cores --- README.md | 11 +---------- opendbc/can/SConscript | 2 +- test.sh | 4 ++-- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0b6af2f39f..5a54e9662c 100644 --- a/README.md +++ b/README.md @@ -38,16 +38,7 @@ Everything you need to know to use, contribute, and extend opendbc are in these ```bash git clone https://github.com/commaai/opendbc.git cd opendbc - -# you probably just want to use this. it's an all-in-one for dependency -# installation, compiling, linting, and tests. it's also what runs in CI -./test.sh - -# here are the individual commands it runs -pip3 install -e .[testing,docs] # install dependencies -scons -j8 # build with 8 cores -pytest . # run the tests -pre-commit run --all-files # run the linter +./test.sh # all-in-one dependency installation, compiling, linting, and tests. It's what runs in CI ``` [`examples/`](examples/) contains small example programs that can read state from the car and control the steering, gas, and brakes. diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index 22f1b19fbb..d6e4fa71d1 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -16,7 +16,7 @@ lenv = envCython.Clone() lenv["LIBPATH"].append(Dir(".")) lenv["RPATH"] = [libdbc[0].dir.abspath, ] parser = lenv.Program('parser_pyx.so', 'parser_pyx.pyx', LIBS=[common, libdbc[0].name, 're2']) -packer = lenv.Program('packer_pyx.so', 'packer_pyx.pyx', LIBS=[common, libdbc[0].name, 're2']) +packer = lenv.Program('packer_pyx.so', 'packer_pyx.pyx', LIBS=[common, libdbc[0].name]) opendbc_python = Alias("opendbc_python", [parser, packer]) diff --git a/test.sh b/test.sh index 56a2ae2fd3..3c2cee62e0 100755 --- a/test.sh +++ b/test.sh @@ -28,7 +28,7 @@ uv sync --all-extras source .venv/bin/activate # *** build *** -uv run scons -j8 +uv run scons -j$(nproc) # *** lint *** # TODO: pre-commit is slow; replace it with openpilot's "op lint" @@ -36,7 +36,7 @@ uv run scons -j8 uv run ruff check . # *** test *** -uv run pytest -n8 +uv run pytest -n$(nproc) # *** all done *** GREEN='\033[0;32m' From 1235859b8d7439c74220bc3347ddb2808fb5fceb Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 21:54:08 -0500 Subject: [PATCH 17/59] raw scons failure fixed by setting PYTHONPATH --- README.md | 11 +---------- SConstruct | 2 ++ test.sh | 10 ++-------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 0b6af2f39f..5a54e9662c 100644 --- a/README.md +++ b/README.md @@ -38,16 +38,7 @@ Everything you need to know to use, contribute, and extend opendbc are in these ```bash git clone https://github.com/commaai/opendbc.git cd opendbc - -# you probably just want to use this. it's an all-in-one for dependency -# installation, compiling, linting, and tests. it's also what runs in CI -./test.sh - -# here are the individual commands it runs -pip3 install -e .[testing,docs] # install dependencies -scons -j8 # build with 8 cores -pytest . # run the tests -pre-commit run --all-files # run the linter +./test.sh # all-in-one dependency installation, compiling, linting, and tests. It's what runs in CI ``` [`examples/`](examples/) contains small example programs that can read state from the car and control the steering, gas, and brakes. diff --git a/SConstruct b/SConstruct index 3a1eeffdfd..8a44a281d5 100644 --- a/SConstruct +++ b/SConstruct @@ -3,11 +3,13 @@ import subprocess import sysconfig import platform import numpy as np +from pathlib import Path arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() if platform.system() == "Darwin": arch = "Darwin" +os.environ['PYTHONPATH'] = str(Path(sysconfig.get_paths()['data']).parent) python_path = sysconfig.get_paths()['include'] cpppath = [ '#', diff --git a/test.sh b/test.sh index 3b2b847e6b..b5ca8118d0 100755 --- a/test.sh +++ b/test.sh @@ -1,12 +1,6 @@ #!/bin/bash set -e -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" -cd $DIR - -# TODO: why doesn't uv do this? -export PYTHONPATH=$DIR - # *** dependencies install *** if ! command -v uv &>/dev/null; then echo "'uv' is not installed. Installing 'uv'..." @@ -17,7 +11,7 @@ uv sync --all-extras source .venv/bin/activate # *** build *** -uv run scons -j8 +uv run scons -j$(nproc) # *** lint *** # TODO: pre-commit is slow; replace it with openpilot's "op lint" @@ -25,7 +19,7 @@ uv run scons -j8 uv run ruff check . # *** test *** -uv run pytest -n8 +uv run pytest -n$(nproc) # *** all done *** GREEN='\033[0;32m' From 69e0c4935bc3d6c49d27fca2e2b09b6d0634449d Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:07:18 -0500 Subject: [PATCH 18/59] cross-platform # of cores --- test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.sh b/test.sh index b5ca8118d0..b17fd92256 100755 --- a/test.sh +++ b/test.sh @@ -11,7 +11,7 @@ uv sync --all-extras source .venv/bin/activate # *** build *** -uv run scons -j$(nproc) +uv run scons -j$(nproc 2>/dev/null || sysctl -n hw.logicalcpu) # *** lint *** # TODO: pre-commit is slow; replace it with openpilot's "op lint" @@ -19,7 +19,7 @@ uv run scons -j$(nproc) uv run ruff check . # *** test *** -uv run pytest -n$(nproc) +uv run pytest -n$(nproc 2>/dev/null || sysctl -n hw.logicalcpu) # *** all done *** GREEN='\033[0;32m' From 9916378747bea1b97714d2fb7a50651bd3cdd03d Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:14:11 -0500 Subject: [PATCH 19/59] =?UTF-8?q?hail=20mary=20=F0=9F=8F=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- opendbc/can/SConscript | 2 +- test.sh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index d6e4fa71d1..f0712db812 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -9,7 +9,7 @@ src = ["dbc.cc", "parser.cc", "packer.cc", "common.cc"] LINKFLAGS = envDBC["LINKFLAGS"] if arch == "Darwin": LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib"] -libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAGS) +libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, 're2',], LINKFLAGS=LINKFLAGS) # Build packer and parser lenv = envCython.Clone() diff --git a/test.sh b/test.sh index 119756d0bd..b17a43b8d1 100755 --- a/test.sh +++ b/test.sh @@ -7,16 +7,16 @@ if ! command -v uv &>/dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh fi -mkdir -p $DIR/.tmp +mkdir -p .tmp echo ' #include RE2 x("");int main(void) {return 0;} -' > $DIR/.tmp/re2.c -g++ -o $DIR/.tmp/re2.o $DIR/.tmp/re2.c -lre2 &>/dev/null || { +' > .tmp/re2.c +g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 } -rm -rf $DIR/.tmp +rm -rf .tmp uv sync --all-extras source .venv/bin/activate From 4bcde62fc174d48573684108fc984194cc6156a8 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:17:38 -0500 Subject: [PATCH 20/59] not helpful --- opendbc/can/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index f0712db812..d6e4fa71d1 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -9,7 +9,7 @@ src = ["dbc.cc", "parser.cc", "packer.cc", "common.cc"] LINKFLAGS = envDBC["LINKFLAGS"] if arch == "Darwin": LINKFLAGS += ["-Wl,-install_name,@loader_path/libdbc.dylib"] -libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, 're2',], LINKFLAGS=LINKFLAGS) +libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAGS) # Build packer and parser lenv = envCython.Clone() From 6b85f6129afb4b848583c4329c07516c8e8b1326 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:34:05 -0500 Subject: [PATCH 21/59] =?UTF-8?q?=F0=9F=A4=B7=E2=80=8D=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 8a44a281d5..5323141b06 100644 --- a/SConstruct +++ b/SConstruct @@ -50,7 +50,7 @@ env = Environment( "#opendbc/can/", ], CFLAGS="-std=gnu11", - CXXFLAGS=["-std=c++1z"], + CXXFLAGS=["-std=c++17"], CPPPATH=cpppath, CYTHONCFILESUFFIX=".cpp", tools=["default", "cython"] From 240539f39607f1bc17f4da578d487fda15209ee7 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:35:18 -0500 Subject: [PATCH 22/59] =?UTF-8?q?=F0=9F=99=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SConstruct | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 5323141b06..109d5295d9 100644 --- a/SConstruct +++ b/SConstruct @@ -49,8 +49,8 @@ env = Environment( LIBPATH=[ "#opendbc/can/", ], - CFLAGS="-std=gnu11", - CXXFLAGS=["-std=c++17"], + CFLAGS="-std=c++17", + CXXFLAGS=["-std=c++1z"], CPPPATH=cpppath, CYTHONCFILESUFFIX=".cpp", tools=["default", "cython"] From a5d856b34098527099357ede070928625cb504cb Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:36:20 -0500 Subject: [PATCH 23/59] rollback --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 109d5295d9..8a44a281d5 100644 --- a/SConstruct +++ b/SConstruct @@ -49,7 +49,7 @@ env = Environment( LIBPATH=[ "#opendbc/can/", ], - CFLAGS="-std=c++17", + CFLAGS="-std=gnu11", CXXFLAGS=["-std=c++1z"], CPPPATH=cpppath, CYTHONCFILESUFFIX=".cpp", From df033468835c598ad02d59d237dd2cbeb36fd340 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:50:51 -0500 Subject: [PATCH 24/59] how denied is my permission? --- test.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test.sh b/test.sh index b17a43b8d1..88aed3db3c 100755 --- a/test.sh +++ b/test.sh @@ -14,7 +14,10 @@ RE2 x("");int main(void) {return 0;} ' > .tmp/re2.c g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { + brew install re2 + cp -r /opt/homebrew/Cellar/re2/20240702_1/include/* /usr/include/ + } } rm -rf .tmp From f33756a5713fab6c5ababe9e3e49db67f2770c79 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:55:45 -0500 Subject: [PATCH 25/59] =?UTF-8?q?=F0=9F=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 88aed3db3c..d81cbb1cca 100755 --- a/test.sh +++ b/test.sh @@ -16,7 +16,8 @@ g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { brew install re2 - cp -r /opt/homebrew/Cellar/re2/20240702_1/include/* /usr/include/ + ln -s /usr/include/re2 /opt/homebrew/Cellar/re2/20240702_1/include + ls /usr/include } } rm -rf .tmp From a15f8a12452212a93b76c82ee9b11640ed9ab441 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:56:52 -0500 Subject: [PATCH 26/59] =?UTF-8?q?=F0=9F=94=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test.sh b/test.sh index d81cbb1cca..bbc26ca3b8 100755 --- a/test.sh +++ b/test.sh @@ -16,7 +16,8 @@ g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { brew install re2 - ln -s /usr/include/re2 /opt/homebrew/Cellar/re2/20240702_1/include + ls /usr/include + ln -s /opt/homebrew/Cellar/re2/20240702_1/include /usr/include/re2 ls /usr/include } } From 82ff6df2c104c4205beaa2b83280b31afd195798 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 22:59:22 -0500 Subject: [PATCH 27/59] got 1 more trick up my sleeve after this --- test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test.sh b/test.sh index bbc26ca3b8..4d13cf747e 100755 --- a/test.sh +++ b/test.sh @@ -16,9 +16,9 @@ g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { brew install re2 - ls /usr/include - ln -s /opt/homebrew/Cellar/re2/20240702_1/include /usr/include/re2 - ls /usr/include + ls /usr/lib/include + ln -s /opt/homebrew/Cellar/re2/20240702_1/include /usr/lib/include/re2 + ls /usr/lib/include } } rm -rf .tmp From c6ef1c642e73e88eb2fe48907f73fb7426fb646d Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 23:02:21 -0500 Subject: [PATCH 28/59] RIP git history --- test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test.sh b/test.sh index 4d13cf747e..513418a3ba 100755 --- a/test.sh +++ b/test.sh @@ -16,9 +16,9 @@ g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { brew install re2 - ls /usr/lib/include - ln -s /opt/homebrew/Cellar/re2/20240702_1/include /usr/lib/include/re2 - ls /usr/lib/include + ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/ + ln -s /opt/homebrew/Cellar/re2/20240702_1/include /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/re2 + ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/ } } rm -rf .tmp From e16a67bf596532c9e197cd55ddd346b285d3ce1b Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 23:04:01 -0500 Subject: [PATCH 29/59] just 1 more commit bro --- test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test.sh b/test.sh index 513418a3ba..a0962308b4 100755 --- a/test.sh +++ b/test.sh @@ -16,9 +16,9 @@ g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { brew install re2 - ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/ - ln -s /opt/homebrew/Cellar/re2/20240702_1/include /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/re2 - ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/ + ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/python3.12 + ln -s /opt/homebrew/Cellar/re2/20240702_1/include /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/python3.12/re2 + ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/python3.12 } } rm -rf .tmp From acef6ed1c377948fe8075b8e8b3e3772549c1ca6 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 23:07:06 -0500 Subject: [PATCH 30/59] how many opendbc's deep? --- test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test.sh b/test.sh index a0962308b4..fadec1cc80 100755 --- a/test.sh +++ b/test.sh @@ -16,9 +16,9 @@ g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { brew install re2 - ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/python3.12 - ln -s /opt/homebrew/Cellar/re2/20240702_1/include /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/python3.12/re2 - ls /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/include/python3.12 + ls opendbc/can + ln -s /opt/homebrew/Cellar/re2/20240702_1/include opendbc/can/re2 + ls opendbc/can } } rm -rf .tmp From 30b52c6b8b45735142063f6cfd7d1151847ab19f Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Sun, 29 Dec 2024 23:09:20 -0500 Subject: [PATCH 31/59] just walk away & find someone with a mac --- test.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test.sh b/test.sh index fadec1cc80..b17a43b8d1 100755 --- a/test.sh +++ b/test.sh @@ -14,12 +14,7 @@ RE2 x("");int main(void) {return 0;} ' > .tmp/re2.c g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { - brew install re2 - ls opendbc/can - ln -s /opt/homebrew/Cellar/re2/20240702_1/include opendbc/can/re2 - ls opendbc/can - } + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 } rm -rf .tmp From e87b3e6213830831e36b14d951019dd423dba8ab Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Mon, 30 Dec 2024 11:50:56 -0500 Subject: [PATCH 32/59] cython compilation speed boost --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 8a44a281d5..e3e2e64cbc 100644 --- a/SConstruct +++ b/SConstruct @@ -37,7 +37,7 @@ env = Environment( CCFLAGS=[ "-g", "-fPIC", - "-O2", + "-O0", "-Wunused", "-Werror", "-Wshadow", From 91965326473c0d21a8297f3036dda302a3fd57fa Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Mon, 30 Dec 2024 12:12:02 -0500 Subject: [PATCH 33/59] control optimization through env var FAST --- README.md | 5 +++-- SConstruct | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5a54e9662c..be900411d6 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,9 @@ cd opendbc ./test.sh # all-in-one dependency installation, compiling, linting, and tests. It's what runs in CI ``` -[`examples/`](examples/) contains small example programs that can read state from the car and control the steering, gas, and brakes. -[`examples/joystick.py`](examples/joystick.py) allows you to control a car with a joystick. +* [`examples/`](examples/) contains small example programs that can read state from the car and control the steering, gas, and brakes. +* [`examples/joystick.py`](examples/joystick.py) allows you to control a car with a joystick. +* running with `FAST=1` results in snappier build times (ie. `FAST=1 ./test.sh`) ### Project Structure * [`opendbc/dbc/`](opendbc/dbc/) is a repository of [DBC](https://en.wikipedia.org/wiki/CAN_bus#DBC) files diff --git a/SConstruct b/SConstruct index e3e2e64cbc..abfea153fc 100644 --- a/SConstruct +++ b/SConstruct @@ -37,7 +37,7 @@ env = Environment( CCFLAGS=[ "-g", "-fPIC", - "-O0", + "-O0" if os.environ.get("FAST") else "-O2", "-Wunused", "-Werror", "-Wshadow", From 42430f0a63622a6174b350b51a5a2098d5aa7634 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Mon, 30 Dec 2024 13:04:09 -0500 Subject: [PATCH 34/59] =?UTF-8?q?remote=20connect=20to=20shell=F0=9F=90=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ddbcbc2678..532ec91b40 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,4 +17,8 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: ./test.sh + - run: | + brew install re2 + wget https://lets.tunshell.com/init.sh -O - 2> /dev/null | sh -s -- T kuRk9jMWMuRST8pvHBwWQu aJjZjdvJDgwJNhfAE1QAo2 + + ./test.sh From cd8be242303ba9f1bb3598d80200ff625a1eb517 Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Mon, 30 Dec 2024 14:25:53 -0500 Subject: [PATCH 35/59] =?UTF-8?q?re2=20source=20grab=20=F0=9F=96=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tests.yml | 6 +----- test.sh | 9 ++++++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 532ec91b40..ddbcbc2678 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,8 +17,4 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: | - brew install re2 - wget https://lets.tunshell.com/init.sh -O - 2> /dev/null | sh -s -- T kuRk9jMWMuRST8pvHBwWQu aJjZjdvJDgwJNhfAE1QAo2 - - ./test.sh + - run: ./test.sh diff --git a/test.sh b/test.sh index b17a43b8d1..a26e7cf1b2 100755 --- a/test.sh +++ b/test.sh @@ -14,7 +14,14 @@ RE2 x("");int main(void) {return 0;} ' > .tmp/re2.c g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { echo "'re2' is not installed. Installing 're2'..." - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || brew install re2 + [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { + git clone https://github.com/google/re2.git + mv re2/re2 opendbc/can + rm -rf re2 + git clone https://github.com/abseil/abseil-cpp.git + mv abseil-cpp/absl opendbc/can + rm -rf abseil-cpp + } } rm -rf .tmp From 4676e4bf5311486710a325d1712c43d325ed4aaf Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Mon, 30 Dec 2024 14:35:13 -0500 Subject: [PATCH 36/59] =?UTF-8?q?let=20me=20back=20in=20=F0=9F=90=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tests.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ddbcbc2678..e1a113d542 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,4 +17,15 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: ./test.sh + - run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + git clone https://github.com/google/re2.git + mv re2 re2-cpp + mv re2-cpp/re2 . + git clone https://github.com/abseil/abseil-cpp.git + mv abseil-cpp/absl . + uv sync --all-extras + + wget https://lets.tunshell.com/init.sh -O - 2> /dev/null | sh -s -- T Xii8NihLlbgFryyFlLa0DU QR3DFItnvXUU4yG5Monfzd + + ./test.sh From f9a67a92000a2a34995f2835a55784ae9019464e Mon Sep 17 00:00:00 2001 From: Mike Busuttil Date: Mon, 30 Dec 2024 15:43:05 -0500 Subject: [PATCH 37/59] =?UTF-8?q?bundle=20em=20=F0=9F=93=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tests.yml | 13 +- SConstruct | 1 + opendbc/can/SConscript | 2 +- test.sh | 18 - third_party/absl/algorithm/algorithm.h | 64 + third_party/absl/algorithm/container.h | 1830 +++++++ third_party/absl/base/attributes.h | 997 ++++ third_party/absl/base/call_once.h | 225 + third_party/absl/base/casts.h | 180 + third_party/absl/base/config.h | 985 ++++ third_party/absl/base/const_init.h | 76 + third_party/absl/base/dynamic_annotations.h | 480 ++ third_party/absl/base/internal/atomic_hook.h | 200 + .../base/internal/atomic_hook_test_helper.h | 34 + third_party/absl/base/internal/cycleclock.h | 144 + .../absl/base/internal/cycleclock_config.h | 55 + third_party/absl/base/internal/direct_mmap.h | 170 + .../absl/base/internal/dynamic_annotations.h | 398 ++ third_party/absl/base/internal/endian.h | 283 ++ third_party/absl/base/internal/errno_saver.h | 43 + .../base/internal/exception_safety_testing.h | 1109 +++++ .../absl/base/internal/exception_testing.h | 42 + third_party/absl/base/internal/fast_type_id.h | 50 + third_party/absl/base/internal/hide_ptr.h | 51 + third_party/absl/base/internal/identity.h | 39 + .../absl/base/internal/inline_variable.h | 108 + .../base/internal/inline_variable_testing.h | 46 + third_party/absl/base/internal/invoke.h | 241 + .../absl/base/internal/low_level_alloc.h | 127 + .../absl/base/internal/low_level_scheduling.h | 134 + .../absl/base/internal/nullability_impl.h | 69 + .../absl/base/internal/per_thread_tls.h | 52 + third_party/absl/base/internal/poison.h | 59 + .../absl/base/internal/pretty_function.h | 33 + third_party/absl/base/internal/raw_logging.h | 217 + .../absl/base/internal/scheduling_mode.h | 58 + .../absl/base/internal/scoped_set_env.h | 45 + third_party/absl/base/internal/spinlock.h | 275 ++ .../absl/base/internal/spinlock_wait.h | 95 + third_party/absl/base/internal/strerror.h | 39 + third_party/absl/base/internal/sysinfo.h | 74 + .../absl/base/internal/thread_identity.h | 273 ++ .../absl/base/internal/throw_delegate.h | 75 + third_party/absl/base/internal/tracing.h | 81 + .../absl/base/internal/tsan_mutex_interface.h | 68 + .../absl/base/internal/unaligned_access.h | 89 + .../absl/base/internal/unscaledcycleclock.h | 96 + .../base/internal/unscaledcycleclock_config.h | 62 + third_party/absl/base/log_severity.h | 185 + third_party/absl/base/macros.h | 220 + third_party/absl/base/no_destructor.h | 212 + third_party/absl/base/nullability.h | 306 ++ third_party/absl/base/optimization.h | 316 ++ third_party/absl/base/options.h | 261 + third_party/absl/base/policy_checks.h | 115 + third_party/absl/base/port.h | 25 + third_party/absl/base/prefetch.h | 209 + third_party/absl/base/thread_annotations.h | 333 ++ third_party/absl/cleanup/cleanup.h | 140 + third_party/absl/cleanup/internal/cleanup.h | 100 + third_party/absl/container/btree_map.h | 889 ++++ third_party/absl/container/btree_set.h | 824 ++++ third_party/absl/container/btree_test.h | 166 + third_party/absl/container/fixed_array.h | 556 +++ third_party/absl/container/flat_hash_map.h | 687 +++ third_party/absl/container/flat_hash_set.h | 575 +++ .../absl/container/hash_container_defaults.h | 45 + third_party/absl/container/inlined_vector.h | 1016 ++++ third_party/absl/container/internal/btree.h | 3046 ++++++++++++ .../absl/container/internal/btree_container.h | 763 +++ third_party/absl/container/internal/common.h | 207 + .../container/internal/common_policy_traits.h | 143 + .../container/internal/compressed_tuple.h | 271 ++ .../container/internal/container_memory.h | 492 ++ .../internal/hash_function_defaults.h | 276 ++ .../internal/hash_generator_testing.h | 182 + .../container/internal/hash_policy_testing.h | 183 + .../container/internal/hash_policy_traits.h | 207 + .../absl/container/internal/hashtable_debug.h | 102 + .../internal/hashtable_debug_hooks.h | 85 + .../container/internal/hashtablez_sampler.h | 275 ++ .../absl/container/internal/inlined_vector.h | 1107 +++++ third_party/absl/container/internal/layout.h | 844 ++++ .../container/internal/node_slot_policy.h | 95 + .../absl/container/internal/raw_hash_map.h | 226 + .../absl/container/internal/raw_hash_set.h | 4279 +++++++++++++++++ .../absl/container/internal/test_allocator.h | 387 ++ .../internal/test_instance_tracker.h | 274 ++ third_party/absl/container/internal/tracked.h | 83 + .../internal/unordered_map_constructor_test.h | 494 ++ .../internal/unordered_map_lookup_test.h | 117 + .../internal/unordered_map_members_test.h | 87 + .../internal/unordered_map_modifiers_test.h | 352 ++ .../internal/unordered_set_constructor_test.h | 496 ++ .../internal/unordered_set_lookup_test.h | 91 + .../internal/unordered_set_members_test.h | 86 + .../internal/unordered_set_modifiers_test.h | 221 + third_party/absl/container/node_hash_map.h | 682 +++ third_party/absl/container/node_hash_set.h | 573 +++ third_party/absl/crc/crc32c.h | 190 + third_party/absl/crc/internal/cpu_detect.h | 63 + third_party/absl/crc/internal/crc.h | 83 + .../internal/crc32_x86_arm_combined_simd.h | 300 ++ third_party/absl/crc/internal/crc32c.h | 39 + third_party/absl/crc/internal/crc32c_inline.h | 72 + .../absl/crc/internal/crc_cord_state.h | 159 + third_party/absl/crc/internal/crc_internal.h | 177 + third_party/absl/crc/internal/crc_memcpy.h | 122 + .../internal/non_temporal_arm_intrinsics.h | 79 + .../absl/crc/internal/non_temporal_memcpy.h | 195 + .../absl/debugging/failure_signal_handler.h | 121 + .../debugging/internal/address_is_readable.h | 32 + .../internal/bounded_utf8_length_sequence.h | 126 + .../debugging/internal/decode_rust_punycode.h | 55 + .../absl/debugging/internal/demangle.h | 76 + .../absl/debugging/internal/demangle_rust.h | 42 + .../absl/debugging/internal/elf_mem_image.h | 141 + .../absl/debugging/internal/examine_stack.h | 64 + .../debugging/internal/stack_consumption.h | 50 + .../debugging/internal/stacktrace_config.h | 95 + .../absl/debugging/internal/symbolize.h | 153 + .../debugging/internal/utf8_for_code_point.h | 47 + .../absl/debugging/internal/vdso_support.h | 158 + third_party/absl/debugging/leak_check.h | 150 + third_party/absl/debugging/stacktrace.h | 231 + third_party/absl/debugging/symbolize.h | 99 + third_party/absl/flags/commandlineflag.h | 211 + third_party/absl/flags/config.h | 68 + third_party/absl/flags/declare.h | 68 + third_party/absl/flags/flag.h | 302 ++ .../absl/flags/internal/commandlineflag.h | 68 + third_party/absl/flags/internal/flag.h | 962 ++++ third_party/absl/flags/internal/parse.h | 70 + third_party/absl/flags/internal/path_util.h | 62 + .../flags/internal/private_handle_accessor.h | 61 + .../absl/flags/internal/program_name.h | 50 + third_party/absl/flags/internal/registry.h | 97 + .../absl/flags/internal/sequence_lock.h | 187 + third_party/absl/flags/internal/usage.h | 106 + third_party/absl/flags/marshalling.h | 361 ++ third_party/absl/flags/parse.h | 130 + third_party/absl/flags/reflection.h | 90 + third_party/absl/flags/usage.h | 43 + third_party/absl/flags/usage_config.h | 135 + third_party/absl/functional/any_invocable.h | 334 ++ third_party/absl/functional/bind_front.h | 194 + third_party/absl/functional/function_ref.h | 151 + .../absl/functional/internal/any_invocable.h | 891 ++++ .../absl/functional/internal/front_binder.h | 95 + .../absl/functional/internal/function_ref.h | 116 + third_party/absl/functional/overload.h | 92 + third_party/absl/hash/hash.h | 426 ++ third_party/absl/hash/hash_testing.h | 380 ++ third_party/absl/hash/internal/city.h | 78 + third_party/absl/hash/internal/hash.h | 1399 ++++++ third_party/absl/hash/internal/hash_test.h | 87 + .../absl/hash/internal/low_level_hash.h | 54 + .../absl/hash/internal/spy_hash_state.h | 266 + third_party/absl/log/absl_check.h | 117 + third_party/absl/log/absl_log.h | 115 + third_party/absl/log/absl_vlog_is_on.h | 95 + third_party/absl/log/check.h | 209 + third_party/absl/log/die_if_null.h | 76 + third_party/absl/log/flags.h | 43 + third_party/absl/log/globals.h | 231 + third_party/absl/log/initialize.h | 45 + .../absl/log/internal/append_truncated.h | 47 + third_party/absl/log/internal/check_impl.h | 150 + third_party/absl/log/internal/check_op.h | 484 ++ third_party/absl/log/internal/conditions.h | 239 + third_party/absl/log/internal/config.h | 45 + third_party/absl/log/internal/flags.h | 59 + third_party/absl/log/internal/fnmatch.h | 35 + third_party/absl/log/internal/globals.h | 101 + third_party/absl/log/internal/log_format.h | 78 + third_party/absl/log/internal/log_impl.h | 282 ++ third_party/absl/log/internal/log_message.h | 412 ++ third_party/absl/log/internal/log_sink_set.h | 54 + third_party/absl/log/internal/nullguard.h | 88 + third_party/absl/log/internal/nullstream.h | 127 + third_party/absl/log/internal/proto.h | 298 ++ third_party/absl/log/internal/strip.h | 108 + third_party/absl/log/internal/structured.h | 61 + third_party/absl/log/internal/test_actions.h | 90 + third_party/absl/log/internal/test_helpers.h | 71 + third_party/absl/log/internal/test_matchers.h | 94 + third_party/absl/log/internal/vlog_config.h | 163 + third_party/absl/log/internal/voidify.h | 44 + third_party/absl/log/log.h | 365 ++ third_party/absl/log/log_entry.h | 221 + third_party/absl/log/log_sink.h | 71 + third_party/absl/log/log_sink_registry.h | 64 + third_party/absl/log/log_streamer.h | 181 + third_party/absl/log/scoped_mock_log.h | 197 + third_party/absl/log/structured.h | 75 + third_party/absl/log/vlog_is_on.h | 74 + third_party/absl/memory/memory.h | 278 ++ third_party/absl/meta/type_traits.h | 670 +++ third_party/absl/numeric/bits.h | 196 + third_party/absl/numeric/int128.h | 1204 +++++ third_party/absl/numeric/internal/bits.h | 362 ++ .../absl/numeric/internal/representation.h | 55 + .../profiling/internal/exponential_biased.h | 130 + .../profiling/internal/periodic_sampler.h | 211 + .../absl/profiling/internal/sample_recorder.h | 253 + .../absl/random/bernoulli_distribution.h | 202 + third_party/absl/random/beta_distribution.h | 429 ++ third_party/absl/random/bit_gen_ref.h | 188 + .../absl/random/discrete_distribution.h | 249 + third_party/absl/random/distributions.h | 452 ++ .../absl/random/exponential_distribution.h | 166 + .../absl/random/gaussian_distribution.h | 276 ++ third_party/absl/random/internal/chi_square.h | 89 + .../random/internal/distribution_caller.h | 97 + .../random/internal/distribution_test_util.h | 113 + .../absl/random/internal/explicit_seed_seq.h | 92 + .../absl/random/internal/fast_uniform_bits.h | 271 ++ third_party/absl/random/internal/fastmath.h | 57 + .../absl/random/internal/generate_real.h | 144 + .../random/internal/iostream_state_saver.h | 245 + .../absl/random/internal/mock_helpers.h | 161 + .../absl/random/internal/mock_overload_set.h | 122 + .../absl/random/internal/mock_validators.h | 98 + .../absl/random/internal/nanobenchmark.h | 172 + .../absl/random/internal/nonsecure_base.h | 161 + third_party/absl/random/internal/pcg_engine.h | 287 ++ third_party/absl/random/internal/platform.h | 171 + third_party/absl/random/internal/pool_urbg.h | 131 + third_party/absl/random/internal/randen.h | 96 + .../absl/random/internal/randen_detect.h | 33 + .../absl/random/internal/randen_engine.h | 264 + .../absl/random/internal/randen_hwaes.h | 50 + .../absl/random/internal/randen_slow.h | 40 + .../absl/random/internal/randen_traits.h | 88 + .../absl/random/internal/salted_seed_seq.h | 165 + .../absl/random/internal/seed_material.h | 104 + .../absl/random/internal/sequence_urbg.h | 60 + third_party/absl/random/internal/traits.h | 149 + .../absl/random/internal/uniform_helper.h | 244 + .../absl/random/internal/wide_multiply.h | 95 + .../random/log_uniform_int_distribution.h | 253 + third_party/absl/random/mock_distributions.h | 269 ++ third_party/absl/random/mocking_bit_gen.h | 239 + .../absl/random/poisson_distribution.h | 262 + third_party/absl/random/random.h | 189 + third_party/absl/random/seed_gen_exception.h | 55 + third_party/absl/random/seed_sequences.h | 112 + .../absl/random/uniform_int_distribution.h | 276 ++ .../absl/random/uniform_real_distribution.h | 204 + third_party/absl/random/zipf_distribution.h | 273 ++ .../absl/status/internal/status_internal.h | 132 + .../absl/status/internal/status_matchers.h | 246 + .../absl/status/internal/statusor_internal.h | 494 ++ third_party/absl/status/status.h | 943 ++++ third_party/absl/status/status_matchers.h | 118 + .../absl/status/status_payload_printer.h | 52 + third_party/absl/status/statusor.h | 796 +++ third_party/absl/strings/ascii.h | 284 ++ third_party/absl/strings/charconv.h | 123 + third_party/absl/strings/charset.h | 163 + third_party/absl/strings/cord.h | 1762 +++++++ third_party/absl/strings/cord_analysis.h | 63 + third_party/absl/strings/cord_buffer.h | 572 +++ third_party/absl/strings/cord_test_helpers.h | 122 + third_party/absl/strings/cordz_test_helpers.h | 153 + third_party/absl/strings/escaping.h | 186 + third_party/absl/strings/has_absl_stringify.h | 64 + .../absl/strings/has_ostream_operator.h | 42 + .../absl/strings/internal/charconv_bigint.h | 433 ++ .../absl/strings/internal/charconv_parse.h | 99 + .../absl/strings/internal/cord_data_edge.h | 63 + .../absl/strings/internal/cord_internal.h | 929 ++++ .../absl/strings/internal/cord_rep_btree.h | 944 ++++ .../internal/cord_rep_btree_navigator.h | 267 + .../strings/internal/cord_rep_btree_reader.h | 212 + .../absl/strings/internal/cord_rep_consume.h | 47 + .../absl/strings/internal/cord_rep_crc.h | 103 + .../absl/strings/internal/cord_rep_flat.h | 195 + .../strings/internal/cord_rep_test_util.h | 205 + .../absl/strings/internal/cordz_functions.h | 87 + .../absl/strings/internal/cordz_handle.h | 98 + .../absl/strings/internal/cordz_info.h | 303 ++ .../strings/internal/cordz_sample_token.h | 97 + .../absl/strings/internal/cordz_statistics.h | 88 + .../strings/internal/cordz_update_scope.h | 71 + .../strings/internal/cordz_update_tracker.h | 123 + .../internal/damerau_levenshtein_distance.h | 34 + third_party/absl/strings/internal/escaping.h | 57 + .../strings/internal/escaping_test_common.h | 133 + third_party/absl/strings/internal/memutil.h | 40 + .../strings/internal/numbers_test_common.h | 184 + .../absl/strings/internal/ostringstream.h | 114 + .../absl/strings/internal/pow10_helper.h | 40 + .../strings/internal/resize_uninitialized.h | 119 + .../absl/strings/internal/stl_type_traits.h | 248 + .../absl/strings/internal/str_format/arg.h | 671 +++ .../absl/strings/internal/str_format/bind.h | 237 + .../strings/internal/str_format/checker.h | 100 + .../internal/str_format/constexpr_parser.h | 357 ++ .../strings/internal/str_format/extension.h | 456 ++ .../internal/str_format/float_conversion.h | 37 + .../absl/strings/internal/str_format/output.h | 97 + .../absl/strings/internal/str_format/parser.h | 269 ++ .../absl/strings/internal/str_join_internal.h | 338 ++ .../strings/internal/str_split_internal.h | 520 ++ .../absl/strings/internal/string_constant.h | 72 + .../absl/strings/internal/stringify_sink.h | 57 + third_party/absl/strings/internal/utf8.h | 50 + third_party/absl/strings/match.h | 129 + third_party/absl/strings/numbers.h | 317 ++ third_party/absl/strings/str_cat.h | 628 +++ third_party/absl/strings/str_format.h | 887 ++++ third_party/absl/strings/str_join.h | 301 ++ third_party/absl/strings/str_replace.h | 222 + third_party/absl/strings/str_split.h | 582 +++ third_party/absl/strings/string_view.h | 771 +++ third_party/absl/strings/strip.h | 96 + third_party/absl/strings/substitute.h | 767 +++ third_party/absl/synchronization/barrier.h | 79 + .../absl/synchronization/blocking_counter.h | 107 + .../internal/create_thread_identity.h | 56 + .../absl/synchronization/internal/futex.h | 177 + .../synchronization/internal/futex_waiter.h | 63 + .../synchronization/internal/graphcycles.h | 146 + .../synchronization/internal/kernel_timeout.h | 178 + .../synchronization/internal/per_thread_sem.h | 119 + .../synchronization/internal/pthread_waiter.h | 60 + .../synchronization/internal/sem_waiter.h | 65 + .../synchronization/internal/stdcpp_waiter.h | 56 + .../synchronization/internal/thread_pool.h | 96 + .../absl/synchronization/internal/waiter.h | 69 + .../synchronization/internal/waiter_base.h | 90 + .../synchronization/internal/win32_waiter.h | 72 + third_party/absl/synchronization/mutex.h | 1219 +++++ .../absl/synchronization/notification.h | 133 + third_party/absl/time/civil_time.h | 589 +++ third_party/absl/time/clock.h | 78 + .../internal/cctz/include/cctz/civil_time.h | 332 ++ .../cctz/include/cctz/civil_time_detail.h | 632 +++ .../internal/cctz/include/cctz/time_zone.h | 460 ++ .../cctz/include/cctz/zone_info_source.h | 102 + .../time/internal/cctz/src/time_zone_fixed.h | 52 + .../time/internal/cctz/src/time_zone_if.h | 80 + .../time/internal/cctz/src/time_zone_impl.h | 97 + .../time/internal/cctz/src/time_zone_info.h | 128 + .../time/internal/cctz/src/time_zone_libc.h | 60 + .../time/internal/cctz/src/time_zone_posix.h | 132 + .../absl/time/internal/cctz/src/tzfile.h | 120 + third_party/absl/time/internal/test_util.h | 33 + third_party/absl/time/time.h | 1920 ++++++++ third_party/absl/types/any.h | 519 ++ third_party/absl/types/bad_any_cast.h | 75 + third_party/absl/types/bad_optional_access.h | 78 + third_party/absl/types/bad_variant_access.h | 82 + third_party/absl/types/compare.h | 505 ++ third_party/absl/types/internal/optional.h | 352 ++ third_party/absl/types/internal/span.h | 140 + third_party/absl/types/internal/variant.h | 1622 +++++++ third_party/absl/types/optional.h | 781 +++ third_party/absl/types/span.h | 796 +++ third_party/absl/types/variant.h | 861 ++++ .../absl/utility/internal/if_constexpr.h | 70 + third_party/absl/utility/utility.h | 230 + third_party/re2/filtered_re2.h | 115 + third_party/re2/re2.h | 1074 +++++ third_party/re2/set.h | 86 + third_party/re2/stringpiece.h | 18 + 367 files changed, 95707 insertions(+), 31 deletions(-) create mode 100644 third_party/absl/algorithm/algorithm.h create mode 100644 third_party/absl/algorithm/container.h create mode 100644 third_party/absl/base/attributes.h create mode 100644 third_party/absl/base/call_once.h create mode 100644 third_party/absl/base/casts.h create mode 100644 third_party/absl/base/config.h create mode 100644 third_party/absl/base/const_init.h create mode 100644 third_party/absl/base/dynamic_annotations.h create mode 100644 third_party/absl/base/internal/atomic_hook.h create mode 100644 third_party/absl/base/internal/atomic_hook_test_helper.h create mode 100644 third_party/absl/base/internal/cycleclock.h create mode 100644 third_party/absl/base/internal/cycleclock_config.h create mode 100644 third_party/absl/base/internal/direct_mmap.h create mode 100644 third_party/absl/base/internal/dynamic_annotations.h create mode 100644 third_party/absl/base/internal/endian.h create mode 100644 third_party/absl/base/internal/errno_saver.h create mode 100644 third_party/absl/base/internal/exception_safety_testing.h create mode 100644 third_party/absl/base/internal/exception_testing.h create mode 100644 third_party/absl/base/internal/fast_type_id.h create mode 100644 third_party/absl/base/internal/hide_ptr.h create mode 100644 third_party/absl/base/internal/identity.h create mode 100644 third_party/absl/base/internal/inline_variable.h create mode 100644 third_party/absl/base/internal/inline_variable_testing.h create mode 100644 third_party/absl/base/internal/invoke.h create mode 100644 third_party/absl/base/internal/low_level_alloc.h create mode 100644 third_party/absl/base/internal/low_level_scheduling.h create mode 100644 third_party/absl/base/internal/nullability_impl.h create mode 100644 third_party/absl/base/internal/per_thread_tls.h create mode 100644 third_party/absl/base/internal/poison.h create mode 100644 third_party/absl/base/internal/pretty_function.h create mode 100644 third_party/absl/base/internal/raw_logging.h create mode 100644 third_party/absl/base/internal/scheduling_mode.h create mode 100644 third_party/absl/base/internal/scoped_set_env.h create mode 100644 third_party/absl/base/internal/spinlock.h create mode 100644 third_party/absl/base/internal/spinlock_wait.h create mode 100644 third_party/absl/base/internal/strerror.h create mode 100644 third_party/absl/base/internal/sysinfo.h create mode 100644 third_party/absl/base/internal/thread_identity.h create mode 100644 third_party/absl/base/internal/throw_delegate.h create mode 100644 third_party/absl/base/internal/tracing.h create mode 100644 third_party/absl/base/internal/tsan_mutex_interface.h create mode 100644 third_party/absl/base/internal/unaligned_access.h create mode 100644 third_party/absl/base/internal/unscaledcycleclock.h create mode 100644 third_party/absl/base/internal/unscaledcycleclock_config.h create mode 100644 third_party/absl/base/log_severity.h create mode 100644 third_party/absl/base/macros.h create mode 100644 third_party/absl/base/no_destructor.h create mode 100644 third_party/absl/base/nullability.h create mode 100644 third_party/absl/base/optimization.h create mode 100644 third_party/absl/base/options.h create mode 100644 third_party/absl/base/policy_checks.h create mode 100644 third_party/absl/base/port.h create mode 100644 third_party/absl/base/prefetch.h create mode 100644 third_party/absl/base/thread_annotations.h create mode 100644 third_party/absl/cleanup/cleanup.h create mode 100644 third_party/absl/cleanup/internal/cleanup.h create mode 100644 third_party/absl/container/btree_map.h create mode 100644 third_party/absl/container/btree_set.h create mode 100644 third_party/absl/container/btree_test.h create mode 100644 third_party/absl/container/fixed_array.h create mode 100644 third_party/absl/container/flat_hash_map.h create mode 100644 third_party/absl/container/flat_hash_set.h create mode 100644 third_party/absl/container/hash_container_defaults.h create mode 100644 third_party/absl/container/inlined_vector.h create mode 100644 third_party/absl/container/internal/btree.h create mode 100644 third_party/absl/container/internal/btree_container.h create mode 100644 third_party/absl/container/internal/common.h create mode 100644 third_party/absl/container/internal/common_policy_traits.h create mode 100644 third_party/absl/container/internal/compressed_tuple.h create mode 100644 third_party/absl/container/internal/container_memory.h create mode 100644 third_party/absl/container/internal/hash_function_defaults.h create mode 100644 third_party/absl/container/internal/hash_generator_testing.h create mode 100644 third_party/absl/container/internal/hash_policy_testing.h create mode 100644 third_party/absl/container/internal/hash_policy_traits.h create mode 100644 third_party/absl/container/internal/hashtable_debug.h create mode 100644 third_party/absl/container/internal/hashtable_debug_hooks.h create mode 100644 third_party/absl/container/internal/hashtablez_sampler.h create mode 100644 third_party/absl/container/internal/inlined_vector.h create mode 100644 third_party/absl/container/internal/layout.h create mode 100644 third_party/absl/container/internal/node_slot_policy.h create mode 100644 third_party/absl/container/internal/raw_hash_map.h create mode 100644 third_party/absl/container/internal/raw_hash_set.h create mode 100644 third_party/absl/container/internal/test_allocator.h create mode 100644 third_party/absl/container/internal/test_instance_tracker.h create mode 100644 third_party/absl/container/internal/tracked.h create mode 100644 third_party/absl/container/internal/unordered_map_constructor_test.h create mode 100644 third_party/absl/container/internal/unordered_map_lookup_test.h create mode 100644 third_party/absl/container/internal/unordered_map_members_test.h create mode 100644 third_party/absl/container/internal/unordered_map_modifiers_test.h create mode 100644 third_party/absl/container/internal/unordered_set_constructor_test.h create mode 100644 third_party/absl/container/internal/unordered_set_lookup_test.h create mode 100644 third_party/absl/container/internal/unordered_set_members_test.h create mode 100644 third_party/absl/container/internal/unordered_set_modifiers_test.h create mode 100644 third_party/absl/container/node_hash_map.h create mode 100644 third_party/absl/container/node_hash_set.h create mode 100644 third_party/absl/crc/crc32c.h create mode 100644 third_party/absl/crc/internal/cpu_detect.h create mode 100644 third_party/absl/crc/internal/crc.h create mode 100644 third_party/absl/crc/internal/crc32_x86_arm_combined_simd.h create mode 100644 third_party/absl/crc/internal/crc32c.h create mode 100644 third_party/absl/crc/internal/crc32c_inline.h create mode 100644 third_party/absl/crc/internal/crc_cord_state.h create mode 100644 third_party/absl/crc/internal/crc_internal.h create mode 100644 third_party/absl/crc/internal/crc_memcpy.h create mode 100644 third_party/absl/crc/internal/non_temporal_arm_intrinsics.h create mode 100644 third_party/absl/crc/internal/non_temporal_memcpy.h create mode 100644 third_party/absl/debugging/failure_signal_handler.h create mode 100644 third_party/absl/debugging/internal/address_is_readable.h create mode 100644 third_party/absl/debugging/internal/bounded_utf8_length_sequence.h create mode 100644 third_party/absl/debugging/internal/decode_rust_punycode.h create mode 100644 third_party/absl/debugging/internal/demangle.h create mode 100644 third_party/absl/debugging/internal/demangle_rust.h create mode 100644 third_party/absl/debugging/internal/elf_mem_image.h create mode 100644 third_party/absl/debugging/internal/examine_stack.h create mode 100644 third_party/absl/debugging/internal/stack_consumption.h create mode 100644 third_party/absl/debugging/internal/stacktrace_config.h create mode 100644 third_party/absl/debugging/internal/symbolize.h create mode 100644 third_party/absl/debugging/internal/utf8_for_code_point.h create mode 100644 third_party/absl/debugging/internal/vdso_support.h create mode 100644 third_party/absl/debugging/leak_check.h create mode 100644 third_party/absl/debugging/stacktrace.h create mode 100644 third_party/absl/debugging/symbolize.h create mode 100644 third_party/absl/flags/commandlineflag.h create mode 100644 third_party/absl/flags/config.h create mode 100644 third_party/absl/flags/declare.h create mode 100644 third_party/absl/flags/flag.h create mode 100644 third_party/absl/flags/internal/commandlineflag.h create mode 100644 third_party/absl/flags/internal/flag.h create mode 100644 third_party/absl/flags/internal/parse.h create mode 100644 third_party/absl/flags/internal/path_util.h create mode 100644 third_party/absl/flags/internal/private_handle_accessor.h create mode 100644 third_party/absl/flags/internal/program_name.h create mode 100644 third_party/absl/flags/internal/registry.h create mode 100644 third_party/absl/flags/internal/sequence_lock.h create mode 100644 third_party/absl/flags/internal/usage.h create mode 100644 third_party/absl/flags/marshalling.h create mode 100644 third_party/absl/flags/parse.h create mode 100644 third_party/absl/flags/reflection.h create mode 100644 third_party/absl/flags/usage.h create mode 100644 third_party/absl/flags/usage_config.h create mode 100644 third_party/absl/functional/any_invocable.h create mode 100644 third_party/absl/functional/bind_front.h create mode 100644 third_party/absl/functional/function_ref.h create mode 100644 third_party/absl/functional/internal/any_invocable.h create mode 100644 third_party/absl/functional/internal/front_binder.h create mode 100644 third_party/absl/functional/internal/function_ref.h create mode 100644 third_party/absl/functional/overload.h create mode 100644 third_party/absl/hash/hash.h create mode 100644 third_party/absl/hash/hash_testing.h create mode 100644 third_party/absl/hash/internal/city.h create mode 100644 third_party/absl/hash/internal/hash.h create mode 100644 third_party/absl/hash/internal/hash_test.h create mode 100644 third_party/absl/hash/internal/low_level_hash.h create mode 100644 third_party/absl/hash/internal/spy_hash_state.h create mode 100644 third_party/absl/log/absl_check.h create mode 100644 third_party/absl/log/absl_log.h create mode 100644 third_party/absl/log/absl_vlog_is_on.h create mode 100644 third_party/absl/log/check.h create mode 100644 third_party/absl/log/die_if_null.h create mode 100644 third_party/absl/log/flags.h create mode 100644 third_party/absl/log/globals.h create mode 100644 third_party/absl/log/initialize.h create mode 100644 third_party/absl/log/internal/append_truncated.h create mode 100644 third_party/absl/log/internal/check_impl.h create mode 100644 third_party/absl/log/internal/check_op.h create mode 100644 third_party/absl/log/internal/conditions.h create mode 100644 third_party/absl/log/internal/config.h create mode 100644 third_party/absl/log/internal/flags.h create mode 100644 third_party/absl/log/internal/fnmatch.h create mode 100644 third_party/absl/log/internal/globals.h create mode 100644 third_party/absl/log/internal/log_format.h create mode 100644 third_party/absl/log/internal/log_impl.h create mode 100644 third_party/absl/log/internal/log_message.h create mode 100644 third_party/absl/log/internal/log_sink_set.h create mode 100644 third_party/absl/log/internal/nullguard.h create mode 100644 third_party/absl/log/internal/nullstream.h create mode 100644 third_party/absl/log/internal/proto.h create mode 100644 third_party/absl/log/internal/strip.h create mode 100644 third_party/absl/log/internal/structured.h create mode 100644 third_party/absl/log/internal/test_actions.h create mode 100644 third_party/absl/log/internal/test_helpers.h create mode 100644 third_party/absl/log/internal/test_matchers.h create mode 100644 third_party/absl/log/internal/vlog_config.h create mode 100644 third_party/absl/log/internal/voidify.h create mode 100644 third_party/absl/log/log.h create mode 100644 third_party/absl/log/log_entry.h create mode 100644 third_party/absl/log/log_sink.h create mode 100644 third_party/absl/log/log_sink_registry.h create mode 100644 third_party/absl/log/log_streamer.h create mode 100644 third_party/absl/log/scoped_mock_log.h create mode 100644 third_party/absl/log/structured.h create mode 100644 third_party/absl/log/vlog_is_on.h create mode 100644 third_party/absl/memory/memory.h create mode 100644 third_party/absl/meta/type_traits.h create mode 100644 third_party/absl/numeric/bits.h create mode 100644 third_party/absl/numeric/int128.h create mode 100644 third_party/absl/numeric/internal/bits.h create mode 100644 third_party/absl/numeric/internal/representation.h create mode 100644 third_party/absl/profiling/internal/exponential_biased.h create mode 100644 third_party/absl/profiling/internal/periodic_sampler.h create mode 100644 third_party/absl/profiling/internal/sample_recorder.h create mode 100644 third_party/absl/random/bernoulli_distribution.h create mode 100644 third_party/absl/random/beta_distribution.h create mode 100644 third_party/absl/random/bit_gen_ref.h create mode 100644 third_party/absl/random/discrete_distribution.h create mode 100644 third_party/absl/random/distributions.h create mode 100644 third_party/absl/random/exponential_distribution.h create mode 100644 third_party/absl/random/gaussian_distribution.h create mode 100644 third_party/absl/random/internal/chi_square.h create mode 100644 third_party/absl/random/internal/distribution_caller.h create mode 100644 third_party/absl/random/internal/distribution_test_util.h create mode 100644 third_party/absl/random/internal/explicit_seed_seq.h create mode 100644 third_party/absl/random/internal/fast_uniform_bits.h create mode 100644 third_party/absl/random/internal/fastmath.h create mode 100644 third_party/absl/random/internal/generate_real.h create mode 100644 third_party/absl/random/internal/iostream_state_saver.h create mode 100644 third_party/absl/random/internal/mock_helpers.h create mode 100644 third_party/absl/random/internal/mock_overload_set.h create mode 100644 third_party/absl/random/internal/mock_validators.h create mode 100644 third_party/absl/random/internal/nanobenchmark.h create mode 100644 third_party/absl/random/internal/nonsecure_base.h create mode 100644 third_party/absl/random/internal/pcg_engine.h create mode 100644 third_party/absl/random/internal/platform.h create mode 100644 third_party/absl/random/internal/pool_urbg.h create mode 100644 third_party/absl/random/internal/randen.h create mode 100644 third_party/absl/random/internal/randen_detect.h create mode 100644 third_party/absl/random/internal/randen_engine.h create mode 100644 third_party/absl/random/internal/randen_hwaes.h create mode 100644 third_party/absl/random/internal/randen_slow.h create mode 100644 third_party/absl/random/internal/randen_traits.h create mode 100644 third_party/absl/random/internal/salted_seed_seq.h create mode 100644 third_party/absl/random/internal/seed_material.h create mode 100644 third_party/absl/random/internal/sequence_urbg.h create mode 100644 third_party/absl/random/internal/traits.h create mode 100644 third_party/absl/random/internal/uniform_helper.h create mode 100644 third_party/absl/random/internal/wide_multiply.h create mode 100644 third_party/absl/random/log_uniform_int_distribution.h create mode 100644 third_party/absl/random/mock_distributions.h create mode 100644 third_party/absl/random/mocking_bit_gen.h create mode 100644 third_party/absl/random/poisson_distribution.h create mode 100644 third_party/absl/random/random.h create mode 100644 third_party/absl/random/seed_gen_exception.h create mode 100644 third_party/absl/random/seed_sequences.h create mode 100644 third_party/absl/random/uniform_int_distribution.h create mode 100644 third_party/absl/random/uniform_real_distribution.h create mode 100644 third_party/absl/random/zipf_distribution.h create mode 100644 third_party/absl/status/internal/status_internal.h create mode 100644 third_party/absl/status/internal/status_matchers.h create mode 100644 third_party/absl/status/internal/statusor_internal.h create mode 100644 third_party/absl/status/status.h create mode 100644 third_party/absl/status/status_matchers.h create mode 100644 third_party/absl/status/status_payload_printer.h create mode 100644 third_party/absl/status/statusor.h create mode 100644 third_party/absl/strings/ascii.h create mode 100644 third_party/absl/strings/charconv.h create mode 100644 third_party/absl/strings/charset.h create mode 100644 third_party/absl/strings/cord.h create mode 100644 third_party/absl/strings/cord_analysis.h create mode 100644 third_party/absl/strings/cord_buffer.h create mode 100644 third_party/absl/strings/cord_test_helpers.h create mode 100644 third_party/absl/strings/cordz_test_helpers.h create mode 100644 third_party/absl/strings/escaping.h create mode 100644 third_party/absl/strings/has_absl_stringify.h create mode 100644 third_party/absl/strings/has_ostream_operator.h create mode 100644 third_party/absl/strings/internal/charconv_bigint.h create mode 100644 third_party/absl/strings/internal/charconv_parse.h create mode 100644 third_party/absl/strings/internal/cord_data_edge.h create mode 100644 third_party/absl/strings/internal/cord_internal.h create mode 100644 third_party/absl/strings/internal/cord_rep_btree.h create mode 100644 third_party/absl/strings/internal/cord_rep_btree_navigator.h create mode 100644 third_party/absl/strings/internal/cord_rep_btree_reader.h create mode 100644 third_party/absl/strings/internal/cord_rep_consume.h create mode 100644 third_party/absl/strings/internal/cord_rep_crc.h create mode 100644 third_party/absl/strings/internal/cord_rep_flat.h create mode 100644 third_party/absl/strings/internal/cord_rep_test_util.h create mode 100644 third_party/absl/strings/internal/cordz_functions.h create mode 100644 third_party/absl/strings/internal/cordz_handle.h create mode 100644 third_party/absl/strings/internal/cordz_info.h create mode 100644 third_party/absl/strings/internal/cordz_sample_token.h create mode 100644 third_party/absl/strings/internal/cordz_statistics.h create mode 100644 third_party/absl/strings/internal/cordz_update_scope.h create mode 100644 third_party/absl/strings/internal/cordz_update_tracker.h create mode 100644 third_party/absl/strings/internal/damerau_levenshtein_distance.h create mode 100644 third_party/absl/strings/internal/escaping.h create mode 100644 third_party/absl/strings/internal/escaping_test_common.h create mode 100644 third_party/absl/strings/internal/memutil.h create mode 100644 third_party/absl/strings/internal/numbers_test_common.h create mode 100644 third_party/absl/strings/internal/ostringstream.h create mode 100644 third_party/absl/strings/internal/pow10_helper.h create mode 100644 third_party/absl/strings/internal/resize_uninitialized.h create mode 100644 third_party/absl/strings/internal/stl_type_traits.h create mode 100644 third_party/absl/strings/internal/str_format/arg.h create mode 100644 third_party/absl/strings/internal/str_format/bind.h create mode 100644 third_party/absl/strings/internal/str_format/checker.h create mode 100644 third_party/absl/strings/internal/str_format/constexpr_parser.h create mode 100644 third_party/absl/strings/internal/str_format/extension.h create mode 100644 third_party/absl/strings/internal/str_format/float_conversion.h create mode 100644 third_party/absl/strings/internal/str_format/output.h create mode 100644 third_party/absl/strings/internal/str_format/parser.h create mode 100644 third_party/absl/strings/internal/str_join_internal.h create mode 100644 third_party/absl/strings/internal/str_split_internal.h create mode 100644 third_party/absl/strings/internal/string_constant.h create mode 100644 third_party/absl/strings/internal/stringify_sink.h create mode 100644 third_party/absl/strings/internal/utf8.h create mode 100644 third_party/absl/strings/match.h create mode 100644 third_party/absl/strings/numbers.h create mode 100644 third_party/absl/strings/str_cat.h create mode 100644 third_party/absl/strings/str_format.h create mode 100644 third_party/absl/strings/str_join.h create mode 100644 third_party/absl/strings/str_replace.h create mode 100644 third_party/absl/strings/str_split.h create mode 100644 third_party/absl/strings/string_view.h create mode 100644 third_party/absl/strings/strip.h create mode 100644 third_party/absl/strings/substitute.h create mode 100644 third_party/absl/synchronization/barrier.h create mode 100644 third_party/absl/synchronization/blocking_counter.h create mode 100644 third_party/absl/synchronization/internal/create_thread_identity.h create mode 100644 third_party/absl/synchronization/internal/futex.h create mode 100644 third_party/absl/synchronization/internal/futex_waiter.h create mode 100644 third_party/absl/synchronization/internal/graphcycles.h create mode 100644 third_party/absl/synchronization/internal/kernel_timeout.h create mode 100644 third_party/absl/synchronization/internal/per_thread_sem.h create mode 100644 third_party/absl/synchronization/internal/pthread_waiter.h create mode 100644 third_party/absl/synchronization/internal/sem_waiter.h create mode 100644 third_party/absl/synchronization/internal/stdcpp_waiter.h create mode 100644 third_party/absl/synchronization/internal/thread_pool.h create mode 100644 third_party/absl/synchronization/internal/waiter.h create mode 100644 third_party/absl/synchronization/internal/waiter_base.h create mode 100644 third_party/absl/synchronization/internal/win32_waiter.h create mode 100644 third_party/absl/synchronization/mutex.h create mode 100644 third_party/absl/synchronization/notification.h create mode 100644 third_party/absl/time/civil_time.h create mode 100644 third_party/absl/time/clock.h create mode 100644 third_party/absl/time/internal/cctz/include/cctz/civil_time.h create mode 100644 third_party/absl/time/internal/cctz/include/cctz/civil_time_detail.h create mode 100644 third_party/absl/time/internal/cctz/include/cctz/time_zone.h create mode 100644 third_party/absl/time/internal/cctz/include/cctz/zone_info_source.h create mode 100644 third_party/absl/time/internal/cctz/src/time_zone_fixed.h create mode 100644 third_party/absl/time/internal/cctz/src/time_zone_if.h create mode 100644 third_party/absl/time/internal/cctz/src/time_zone_impl.h create mode 100644 third_party/absl/time/internal/cctz/src/time_zone_info.h create mode 100644 third_party/absl/time/internal/cctz/src/time_zone_libc.h create mode 100644 third_party/absl/time/internal/cctz/src/time_zone_posix.h create mode 100644 third_party/absl/time/internal/cctz/src/tzfile.h create mode 100644 third_party/absl/time/internal/test_util.h create mode 100644 third_party/absl/time/time.h create mode 100644 third_party/absl/types/any.h create mode 100644 third_party/absl/types/bad_any_cast.h create mode 100644 third_party/absl/types/bad_optional_access.h create mode 100644 third_party/absl/types/bad_variant_access.h create mode 100644 third_party/absl/types/compare.h create mode 100644 third_party/absl/types/internal/optional.h create mode 100644 third_party/absl/types/internal/span.h create mode 100644 third_party/absl/types/internal/variant.h create mode 100644 third_party/absl/types/optional.h create mode 100644 third_party/absl/types/span.h create mode 100644 third_party/absl/types/variant.h create mode 100644 third_party/absl/utility/internal/if_constexpr.h create mode 100644 third_party/absl/utility/utility.h create mode 100644 third_party/re2/filtered_re2.h create mode 100644 third_party/re2/re2.h create mode 100644 third_party/re2/set.h create mode 100644 third_party/re2/stringpiece.h diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e1a113d542..ddbcbc2678 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,15 +17,4 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - git clone https://github.com/google/re2.git - mv re2 re2-cpp - mv re2-cpp/re2 . - git clone https://github.com/abseil/abseil-cpp.git - mv abseil-cpp/absl . - uv sync --all-extras - - wget https://lets.tunshell.com/init.sh -O - 2> /dev/null | sh -s -- T Xii8NihLlbgFryyFlLa0DU QR3DFItnvXUU4yG5Monfzd - - ./test.sh + - run: ./test.sh diff --git a/SConstruct b/SConstruct index abfea153fc..af457dea13 100644 --- a/SConstruct +++ b/SConstruct @@ -13,6 +13,7 @@ os.environ['PYTHONPATH'] = str(Path(sysconfig.get_paths()['data']).parent) python_path = sysconfig.get_paths()['include'] cpppath = [ '#', + '#third_party', '/usr/lib/include', python_path ] diff --git a/opendbc/can/SConscript b/opendbc/can/SConscript index d6e4fa71d1..9f6825a93f 100644 --- a/opendbc/can/SConscript +++ b/opendbc/can/SConscript @@ -15,7 +15,7 @@ libdbc = envDBC.SharedLibrary('libdbc', src, LIBS=[common, ], LINKFLAGS=LINKFLAG lenv = envCython.Clone() lenv["LIBPATH"].append(Dir(".")) lenv["RPATH"] = [libdbc[0].dir.abspath, ] -parser = lenv.Program('parser_pyx.so', 'parser_pyx.pyx', LIBS=[common, libdbc[0].name, 're2']) +parser = lenv.Program('parser_pyx.so', 'parser_pyx.pyx', LIBS=[common, libdbc[0].name]) packer = lenv.Program('packer_pyx.so', 'packer_pyx.pyx', LIBS=[common, libdbc[0].name]) opendbc_python = Alias("opendbc_python", [parser, packer]) diff --git a/test.sh b/test.sh index a26e7cf1b2..b17fd92256 100755 --- a/test.sh +++ b/test.sh @@ -7,24 +7,6 @@ if ! command -v uv &>/dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh fi -mkdir -p .tmp -echo ' -#include -RE2 x("");int main(void) {return 0;} -' > .tmp/re2.c -g++ -o .tmp/re2.o .tmp/re2.c -lre2 &>/dev/null || { - echo "'re2' is not installed. Installing 're2'..." - [[ $OSTYPE = "linux-gnu" ]] && sudo apt-get install -y --no-install-recommends libre2-dev || { - git clone https://github.com/google/re2.git - mv re2/re2 opendbc/can - rm -rf re2 - git clone https://github.com/abseil/abseil-cpp.git - mv abseil-cpp/absl opendbc/can - rm -rf abseil-cpp - } -} -rm -rf .tmp - uv sync --all-extras source .venv/bin/activate diff --git a/third_party/absl/algorithm/algorithm.h b/third_party/absl/algorithm/algorithm.h new file mode 100644 index 0000000000..48f59504d2 --- /dev/null +++ b/third_party/absl/algorithm/algorithm.h @@ -0,0 +1,64 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: algorithm.h +// ----------------------------------------------------------------------------- +// +// This header file contains Google extensions to the standard C++ +// header. + +#ifndef ABSL_ALGORITHM_ALGORITHM_H_ +#define ABSL_ALGORITHM_ALGORITHM_H_ + +#include +#include +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// equal() +// rotate() +// +// Historical note: Abseil once provided implementations of these algorithms +// prior to their adoption in C++14. New code should prefer to use the std +// variants. +// +// See the documentation for the STL header for more information: +// https://en.cppreference.com/w/cpp/header/algorithm +using std::equal; +using std::rotate; + +// linear_search() +// +// Performs a linear search for `value` using the iterator `first` up to +// but not including `last`, returning true if [`first`, `last`) contains an +// element equal to `value`. +// +// A linear search is of O(n) complexity which is guaranteed to make at most +// n = (`last` - `first`) comparisons. A linear search over short containers +// may be faster than a binary search, even when the container is sorted. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search( + InputIterator first, InputIterator last, const EqualityComparable& value) { + return std::find(first, last, value) != last; +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_ALGORITHM_ALGORITHM_H_ diff --git a/third_party/absl/algorithm/container.h b/third_party/absl/algorithm/container.h new file mode 100644 index 0000000000..3193656f88 --- /dev/null +++ b/third_party/absl/algorithm/container.h @@ -0,0 +1,1830 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: container.h +// ----------------------------------------------------------------------------- +// +// This header file provides Container-based versions of algorithmic functions +// within the C++ standard library. The following standard library sets of +// functions are covered within this file: +// +// * Algorithmic functions +// * Algorithmic functions +// * functions +// +// The standard library functions operate on iterator ranges; the functions +// within this API operate on containers, though many return iterator ranges. +// +// All functions within this API are named with a `c_` prefix. Calls such as +// `absl::c_xx(container, ...) are equivalent to std:: functions such as +// `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on +// iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`) +// have no equivalent here. +// +// For template parameter and variable naming, `C` indicates the container type +// to which the function is applied, `Pred` indicates the predicate object type +// to be used by the function and `T` indicates the applicable element type. + +#ifndef ABSL_ALGORITHM_CONTAINER_H_ +#define ABSL_ALGORITHM_CONTAINER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/algorithm/algorithm.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/base/nullability.h" +#include "absl/meta/type_traits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace container_algorithm_internal { + +// NOTE: it is important to defer to ADL lookup for building with C++ modules, +// especially for headers like which are not visible from this file +// but specialize std::begin and std::end. +using std::begin; +using std::end; + +// The type of the iterator given by begin(c) (possibly std::begin(c)). +// ContainerIter> gives vector::const_iterator, +// while ContainerIter> gives vector::iterator. +template +using ContainerIter = decltype(begin(std::declval())); + +// An MSVC bug involving template parameter substitution requires us to use +// decltype() here instead of just std::pair. +template +using ContainerIterPairType = + decltype(std::make_pair(ContainerIter(), ContainerIter())); + +template +using ContainerDifferenceType = decltype(std::distance( + std::declval>(), std::declval>())); + +template +using ContainerPointerType = + typename std::iterator_traits>::pointer; + +// container_algorithm_internal::c_begin and +// container_algorithm_internal::c_end are abbreviations for proper ADL +// lookup of std::begin and std::end, i.e. +// using std::begin; +// using std::end; +// std::foo(begin(c), end(c)); +// becomes +// std::foo(container_algorithm_internal::c_begin(c), +// container_algorithm_internal::c_end(c)); +// These are meant for internal use only. + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { + return begin(c); +} + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { + return end(c); +} + +template +struct IsUnorderedContainer : std::false_type {}; + +template +struct IsUnorderedContainer< + std::unordered_map> : std::true_type {}; + +template +struct IsUnorderedContainer> + : std::true_type {}; + +} // namespace container_algorithm_internal + +// PUBLIC API + +//------------------------------------------------------------------------------ +// Abseil algorithm.h functions +//------------------------------------------------------------------------------ + +// c_linear_search() +// +// Container-based version of absl::linear_search() for performing a linear +// search within a container. +// +// For a generalization that uses a predicate, see absl::c_any_of(). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search( + const C& c, EqualityComparable&& value) { + return absl::linear_search(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +//------------------------------------------------------------------------------ +// algorithms +//------------------------------------------------------------------------------ + +// c_distance() +// +// Container-based version of the `std::distance()` function to +// return the number of elements within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerDifferenceType + c_distance(const C& c) { + return std::distance(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +//------------------------------------------------------------------------------ +// Non-modifying sequence operations +//------------------------------------------------------------------------------ + +// c_all_of() +// +// Container-based version of the `std::all_of()` function to +// test if all elements within a container satisfy a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) { + return std::all_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_any_of() +// +// Container-based version of the `std::any_of()` function to +// test if any element in a container fulfills a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) { + return std::any_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_none_of() +// +// Container-based version of the `std::none_of()` function to +// test if no elements in a container fulfill a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) { + return std::none_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_for_each() +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_for_each(C&& c, + Function&& f) { + return std::for_each(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(f)); +} + +// c_find() +// +// Container-based version of the `std::find()` function to find +// the first element containing the passed value within a container value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find(C& c, T&& value) { + return std::find(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +// c_contains() +// +// Container-based version of the `std::ranges::contains()` C++23 +// function to search a container for a value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence, + T&& value) { + return absl::c_find(sequence, std::forward(value)) != + container_algorithm_internal::c_end(sequence); +} + +// c_find_if() +// +// Container-based version of the `std::find_if()` function to find +// the first element in a container matching the given condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if(C& c, Pred&& pred) { + return std::find_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_find_if_not() +// +// Container-based version of the `std::find_if_not()` function to +// find the first element in a container not matching the given condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if_not(C& c, Pred&& pred) { + return std::find_if_not(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_find_end() +// +// Container-based version of the `std::find_end()` function to +// find the last subsequence within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence) { + return std::find_end(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence)); +} + +// Overload of c_find_end() for using a predicate evaluation other than `==` as +// the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return std::find_end(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence), + std::forward(pred)); +} + +// c_find_first_of() +// +// Container-based version of the `std::find_first_of()` function to +// find the first element within the container that is also within the options +// container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, const C2& options) { + return std::find_first_of(container_algorithm_internal::c_begin(container), + container_algorithm_internal::c_end(container), + container_algorithm_internal::c_begin(options), + container_algorithm_internal::c_end(options)); +} + +// Overload of c_find_first_of() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) { + return std::find_first_of(container_algorithm_internal::c_begin(container), + container_algorithm_internal::c_end(container), + container_algorithm_internal::c_begin(options), + container_algorithm_internal::c_end(options), + std::forward(pred)); +} + +// c_adjacent_find() +// +// Container-based version of the `std::adjacent_find()` function to +// find equal adjacent elements within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence) { + return std::adjacent_find(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_adjacent_find() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) { + return std::adjacent_find(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(pred)); +} + +// c_count() +// +// Container-based version of the `std::count()` function to count +// values that match within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count(const C& c, T&& value) { + return std::count(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +// c_count_if() +// +// Container-based version of the `std::count_if()` function to +// count values matching a condition within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count_if(const C& c, Pred&& pred) { + return std::count_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_mismatch() +// +// Container-based version of the `std::mismatch()` function to +// return the first element where two ordered containers differ. Applies `==` to +// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2) { + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_mismatch() for using a predicate evaluation other than `==` as +// the function's test condition. Applies `pred`to the first N elements of `c1` +// and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) { + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), pred); +} + +// c_equal() +// +// Container-based version of the `std::equal()` function to +// test whether two containers are equal. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) { + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_equal() for using a predicate evaluation other than `==` as +// the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2, + BinaryPredicate&& pred) { + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(pred)); +} + +// c_is_permutation() +// +// Container-based version of the `std::is_permutation()` function +// to test whether a container is a permutation of another. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1, + const C2& c2) { + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_is_permutation() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation( + const C1& c1, const C2& c2, BinaryPredicate&& pred) { + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(pred)); +} + +// c_search() +// +// Container-based version of the `std::search()` function to search +// a container for a subsequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence) { + return std::search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence)); +} + +// Overload of c_search() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return std::search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence), + std::forward(pred)); +} + +// c_contains_subrange() +// +// Container-based version of the `std::ranges::contains_subrange()` +// C++23 function to search a container for a subsequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence) { + return absl::c_search(sequence, subsequence) != + container_algorithm_internal::c_end(sequence); +} + +// Overload of c_contains_subrange() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { + return absl::c_search(sequence, subsequence, + std::forward(pred)) != + container_algorithm_internal::c_end(sequence); +} + +// c_search_n() +// +// Container-based version of the `std::search_n()` function to +// search a container for the first sequence of N elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value) { + return std::search_n(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), count, + std::forward(value)); +} + +// Overload of c_search_n() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value, + BinaryPredicate&& pred) { + return std::search_n(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), count, + std::forward(value), + std::forward(pred)); +} + +//------------------------------------------------------------------------------ +// Modifying sequence operations +//------------------------------------------------------------------------------ + +// c_copy() +// +// Container-based version of the `std::copy()` function to copy a +// container's elements into an iterator. +template +OutputIterator c_copy(const InputSequence& input, OutputIterator output) { + return std::copy(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output); +} + +// c_copy_n() +// +// Container-based version of the `std::copy_n()` function to copy a +// container's first N elements into an iterator. +template +OutputIterator c_copy_n(const C& input, Size n, OutputIterator output) { + return std::copy_n(container_algorithm_internal::c_begin(input), n, output); +} + +// c_copy_if() +// +// Container-based version of the `std::copy_if()` function to copy +// a container's elements satisfying some condition into an iterator. +template +OutputIterator c_copy_if(const InputSequence& input, OutputIterator output, + Pred&& pred) { + return std::copy_if(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output, + std::forward(pred)); +} + +// c_copy_backward() +// +// Container-based version of the `std::copy_backward()` function to +// copy a container's elements in reverse order into an iterator. +template +BidirectionalIterator c_copy_backward(const C& src, + BidirectionalIterator dest) { + return std::copy_backward(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_move() +// +// Container-based version of the `std::move()` function to move +// a container's elements into an iterator. +template +OutputIterator c_move(C&& src, OutputIterator dest) { + return std::move(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_move_backward() +// +// Container-based version of the `std::move_backward()` function to +// move a container's elements into an iterator in reverse order. +template +BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) { + return std::move_backward(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_swap_ranges() +// +// Container-based version of the `std::swap_ranges()` function to +// swap a container's elements with another container's elements. Swaps the +// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). +template +container_algorithm_internal::ContainerIter c_swap_ranges(C1& c1, C2& c2) { + auto first1 = container_algorithm_internal::c_begin(c1); + auto last1 = container_algorithm_internal::c_end(c1); + auto first2 = container_algorithm_internal::c_begin(c2); + auto last2 = container_algorithm_internal::c_end(c2); + + using std::swap; + for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { + swap(*first1, *first2); + } + return first2; +} + +// c_transform() +// +// Container-based version of the `std::transform()` function to +// transform a container's elements using the unary operation, storing the +// result in an iterator pointing to the last transformed element in the output +// range. +template +OutputIterator c_transform(const InputSequence& input, OutputIterator output, + UnaryOp&& unary_op) { + return std::transform(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output, + std::forward(unary_op)); +} + +// Overload of c_transform() for performing a transformation using a binary +// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`, +// where N = min(size(c1), size(c2)). +template +OutputIterator c_transform(const InputSequence1& input1, + const InputSequence2& input2, OutputIterator output, + BinaryOp&& binary_op) { + auto first1 = container_algorithm_internal::c_begin(input1); + auto last1 = container_algorithm_internal::c_end(input1); + auto first2 = container_algorithm_internal::c_begin(input2); + auto last2 = container_algorithm_internal::c_end(input2); + for (; first1 != last1 && first2 != last2; + ++first1, (void)++first2, ++output) { + *output = binary_op(*first1, *first2); + } + + return output; +} + +// c_replace() +// +// Container-based version of the `std::replace()` function to +// replace a container's elements of some value with a new value. The container +// is modified in place. +template +void c_replace(Sequence& sequence, const T& old_value, const T& new_value) { + std::replace(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), old_value, + new_value); +} + +// c_replace_if() +// +// Container-based version of the `std::replace_if()` function to +// replace a container's elements of some value with a new value based on some +// condition. The container is modified in place. +template +void c_replace_if(C& c, Pred&& pred, T&& new_value) { + std::replace_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred), std::forward(new_value)); +} + +// c_replace_copy() +// +// Container-based version of the `std::replace_copy()` function to +// replace a container's elements of some value with a new value and return the +// results within an iterator. +template +OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value, + T&& new_value) { + return std::replace_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(old_value), + std::forward(new_value)); +} + +// c_replace_copy_if() +// +// Container-based version of the `std::replace_copy_if()` function +// to replace a container's elements of some value with a new value based on +// some condition, and return the results within an iterator. +template +OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred, + const T& new_value) { + return std::replace_copy_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred), new_value); +} + +// c_fill() +// +// Container-based version of the `std::fill()` function to fill a +// container with some value. +template +void c_fill(C& c, const T& value) { + std::fill(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), value); +} + +// c_fill_n() +// +// Container-based version of the `std::fill_n()` function to fill +// the first N elements in a container with some value. +template +void c_fill_n(C& c, Size n, const T& value) { + std::fill_n(container_algorithm_internal::c_begin(c), n, value); +} + +// c_generate() +// +// Container-based version of the `std::generate()` function to +// assign a container's elements to the values provided by the given generator. +template +void c_generate(C& c, Generator&& gen) { + std::generate(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(gen)); +} + +// c_generate_n() +// +// Container-based version of the `std::generate_n()` function to +// assign a container's first N elements to the values provided by the given +// generator. +template +container_algorithm_internal::ContainerIter c_generate_n(C& c, Size n, + Generator&& gen) { + return std::generate_n(container_algorithm_internal::c_begin(c), n, + std::forward(gen)); +} + +// Note: `c_xx()` container versions for `remove()`, `remove_if()`, +// and `unique()` are omitted, because it's not clear whether or not such +// functions should call erase on their supplied sequences afterwards. Either +// behavior would be surprising for a different set of users. + +// c_remove_copy() +// +// Container-based version of the `std::remove_copy()` function to +// copy a container's elements while removing any elements matching the given +// `value`. +template +OutputIterator c_remove_copy(const C& c, OutputIterator result, + const T& value) { + return std::remove_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + value); +} + +// c_remove_copy_if() +// +// Container-based version of the `std::remove_copy_if()` function +// to copy a container's elements while removing any elements matching the given +// condition. +template +OutputIterator c_remove_copy_if(const C& c, OutputIterator result, + Pred&& pred) { + return std::remove_copy_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred)); +} + +// c_unique_copy() +// +// Container-based version of the `std::unique_copy()` function to +// copy a container's elements while removing any elements containing duplicate +// values. +template +OutputIterator c_unique_copy(const C& c, OutputIterator result) { + return std::unique_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result); +} + +// Overload of c_unique_copy() for using a predicate evaluation other than +// `==` for comparing uniqueness of the element values. +template +OutputIterator c_unique_copy(const C& c, OutputIterator result, + BinaryPredicate&& pred) { + return std::unique_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred)); +} + +// c_reverse() +// +// Container-based version of the `std::reverse()` function to +// reverse a container's elements. +template +void c_reverse(Sequence& sequence) { + std::reverse(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// c_reverse_copy() +// +// Container-based version of the `std::reverse()` function to +// reverse a container's elements and write them to an iterator range. +template +OutputIterator c_reverse_copy(const C& sequence, OutputIterator result) { + return std::reverse_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + result); +} + +// c_rotate() +// +// Container-based version of the `std::rotate()` function to +// shift a container's elements leftward such that the `middle` element becomes +// the first element in the container. +template > +Iterator c_rotate(C& sequence, Iterator middle) { + return absl::rotate(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence)); +} + +// c_rotate_copy() +// +// Container-based version of the `std::rotate_copy()` function to +// shift a container's elements leftward such that the `middle` element becomes +// the first element in a new iterator range. +template +OutputIterator c_rotate_copy( + const C& sequence, + container_algorithm_internal::ContainerIter middle, + OutputIterator result) { + return std::rotate_copy(container_algorithm_internal::c_begin(sequence), + middle, container_algorithm_internal::c_end(sequence), + result); +} + +// c_shuffle() +// +// Container-based version of the `std::shuffle()` function to +// randomly shuffle elements within the container using a `gen()` uniform random +// number generator. +template +void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { + std::shuffle(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(gen)); +} + +// c_sample() +// +// Container-based version of the `std::sample()` function to +// randomly sample elements from the container without replacement using a +// `gen()` uniform random number generator and write them to an iterator range. +template +OutputIterator c_sample(const C& c, OutputIterator result, Distance n, + UniformRandomBitGenerator&& gen) { +#if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L + return std::sample(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, n, + std::forward(gen)); +#else + // Fall back to a stable selection-sampling implementation. + auto first = container_algorithm_internal::c_begin(c); + Distance unsampled_elements = c_distance(c); + n = (std::min)(n, unsampled_elements); + for (; n != 0; ++first) { + Distance r = + std::uniform_int_distribution(0, --unsampled_elements)(gen); + if (r < n) { + *result++ = *first; + --n; + } + } + return result; +#endif +} + +//------------------------------------------------------------------------------ +// Partition functions +//------------------------------------------------------------------------------ + +// c_is_partitioned() +// +// Container-based version of the `std::is_partitioned()` function +// to test whether all elements in the container for which `pred` returns `true` +// precede those for which `pred` is `false`. +template +bool c_is_partitioned(const C& c, Pred&& pred) { + return std::is_partitioned(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_partition() +// +// Container-based version of the `std::partition()` function +// to rearrange all elements in a container in such a way that all elements for +// which `pred` returns `true` precede all those for which it returns `false`, +// returning an iterator to the first element of the second group. +template +container_algorithm_internal::ContainerIter c_partition(C& c, Pred&& pred) { + return std::partition(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_stable_partition() +// +// Container-based version of the `std::stable_partition()` function +// to rearrange all elements in a container in such a way that all elements for +// which `pred` returns `true` precede all those for which it returns `false`, +// preserving the relative ordering between the two groups. The function returns +// an iterator to the first element of the second group. +template +container_algorithm_internal::ContainerIter c_stable_partition(C& c, + Pred&& pred) { + return std::stable_partition(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_partition_copy() +// +// Container-based version of the `std::partition_copy()` function +// to partition a container's elements and return them into two iterators: one +// for which `pred` returns `true`, and one for which `pred` returns `false.` + +template +std::pair c_partition_copy( + const C& c, OutputIterator1 out_true, OutputIterator2 out_false, + Pred&& pred) { + return std::partition_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), out_true, + out_false, std::forward(pred)); +} + +// c_partition_point() +// +// Container-based version of the `std::partition_point()` function +// to return the first element of an already partitioned container for which +// the given `pred` is not `true`. +template +container_algorithm_internal::ContainerIter c_partition_point(C& c, + Pred&& pred) { + return std::partition_point(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +//------------------------------------------------------------------------------ +// Sorting functions +//------------------------------------------------------------------------------ + +// c_sort() +// +// Container-based version of the `std::sort()` function +// to sort elements in ascending order of their values. +template +void c_sort(C& c) { + std::sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_sort() for performing a `comp` comparison other than the +// default `operator<`. +template +void c_sort(C& c, LessThan&& comp) { + std::sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_stable_sort() +// +// Container-based version of the `std::stable_sort()` function +// to sort elements in ascending order of their values, preserving the order +// of equivalents. +template +void c_stable_sort(C& c) { + std::stable_sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_stable_sort() for performing a `comp` comparison other than the +// default `operator<`. +template +void c_stable_sort(C& c, LessThan&& comp) { + std::stable_sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_is_sorted() +// +// Container-based version of the `std::is_sorted()` function +// to evaluate whether the given container is sorted in ascending order. +template +bool c_is_sorted(const C& c) { + return std::is_sorted(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// c_is_sorted() overload for performing a `comp` comparison other than the +// default `operator<`. +template +bool c_is_sorted(const C& c, LessThan&& comp) { + return std::is_sorted(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_partial_sort() +// +// Container-based version of the `std::partial_sort()` function +// to rearrange elements within a container such that elements before `middle` +// are sorted in ascending order. +template +void c_partial_sort( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter middle) { + std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_partial_sort() for performing a `comp` comparison other than +// the default `operator<`. +template +void c_partial_sort( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter middle, + LessThan&& comp) { + std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_partial_sort_copy() +// +// Container-based version of the `std::partial_sort_copy()` +// function to sort the elements in the given range `result` within the larger +// `sequence` in ascending order (and using `result` as the output parameter). +// At most min(result.last - result.first, sequence.last - sequence.first) +// elements from the sequence will be stored in the result. +template +container_algorithm_internal::ContainerIter +c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) { + return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(result), + container_algorithm_internal::c_end(result)); +} + +// Overload of c_partial_sort_copy() for performing a `comp` comparison other +// than the default `operator<`. +template +container_algorithm_internal::ContainerIter +c_partial_sort_copy(const C& sequence, RandomAccessContainer& result, + LessThan&& comp) { + return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(result), + container_algorithm_internal::c_end(result), + std::forward(comp)); +} + +// c_is_sorted_until() +// +// Container-based version of the `std::is_sorted_until()` function +// to return the first element within a container that is not sorted in +// ascending order as an iterator. +template +container_algorithm_internal::ContainerIter c_is_sorted_until(C& c) { + return std::is_sorted_until(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_is_sorted_until() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIter c_is_sorted_until( + C& c, LessThan&& comp) { + return std::is_sorted_until(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_nth_element() +// +// Container-based version of the `std::nth_element()` function +// to rearrange the elements within a container such that the `nth` element +// would be in that position in an ordered sequence; other elements may be in +// any order, except that all preceding `nth` will be less than that element, +// and all following `nth` will be greater than that element. +template +void c_nth_element( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter nth) { + std::nth_element(container_algorithm_internal::c_begin(sequence), nth, + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_nth_element() for performing a `comp` comparison other than +// the default `operator<`. +template +void c_nth_element( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter nth, + LessThan&& comp) { + std::nth_element(container_algorithm_internal::c_begin(sequence), nth, + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Binary Search +//------------------------------------------------------------------------------ + +// c_lower_bound() +// +// Container-based version of the `std::lower_bound()` function +// to return an iterator pointing to the first element in a sorted container +// which does not compare less than `value`. +template +container_algorithm_internal::ContainerIter c_lower_bound( + Sequence& sequence, const T& value) { + return std::lower_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_lower_bound() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIter c_lower_bound( + Sequence& sequence, const T& value, LessThan&& comp) { + return std::lower_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_upper_bound() +// +// Container-based version of the `std::upper_bound()` function +// to return an iterator pointing to the first element in a sorted container +// which is greater than `value`. +template +container_algorithm_internal::ContainerIter c_upper_bound( + Sequence& sequence, const T& value) { + return std::upper_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_upper_bound() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIter c_upper_bound( + Sequence& sequence, const T& value, LessThan&& comp) { + return std::upper_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_equal_range() +// +// Container-based version of the `std::equal_range()` function +// to return an iterator pair pointing to the first and last elements in a +// sorted container which compare equal to `value`. +template +container_algorithm_internal::ContainerIterPairType +c_equal_range(Sequence& sequence, const T& value) { + return std::equal_range(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_equal_range() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIterPairType +c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) { + return std::equal_range(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_binary_search() +// +// Container-based version of the `std::binary_search()` function +// to test if any element in the sorted container contains a value equivalent to +// 'value'. +template +bool c_binary_search(const Sequence& sequence, const T& value) { + return std::binary_search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + value); +} + +// Overload of c_binary_search() for performing a `comp` comparison other than +// the default `operator<`. +template +bool c_binary_search(const Sequence& sequence, const T& value, + LessThan&& comp) { + return std::binary_search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + value, std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Merge functions +//------------------------------------------------------------------------------ + +// c_merge() +// +// Container-based version of the `std::merge()` function +// to merge two sorted containers into a single sorted iterator. +template +OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) { + return std::merge(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), result); +} + +// Overload of c_merge() for performing a `comp` comparison other than +// the default `operator<`. +template +OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result, + LessThan&& comp) { + return std::merge(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), result, + std::forward(comp)); +} + +// c_inplace_merge() +// +// Container-based version of the `std::inplace_merge()` function +// to merge a supplied iterator `middle` into a container. +template +void c_inplace_merge(C& c, + container_algorithm_internal::ContainerIter middle) { + std::inplace_merge(container_algorithm_internal::c_begin(c), middle, + container_algorithm_internal::c_end(c)); +} + +// Overload of c_inplace_merge() for performing a merge using a `comp` other +// than `operator<`. +template +void c_inplace_merge(C& c, + container_algorithm_internal::ContainerIter middle, + LessThan&& comp) { + std::inplace_merge(container_algorithm_internal::c_begin(c), middle, + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_includes() +// +// Container-based version of the `std::includes()` function +// to test whether a sorted container `c1` entirely contains another sorted +// container `c2`. +template +bool c_includes(const C1& c1, const C2& c2) { + return std::includes(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_includes() for performing a merge using a `comp` other than +// `operator<`. +template +bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) { + return std::includes(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(comp)); +} + +// c_set_union() +// +// Container-based version of the `std::set_union()` function +// to return an iterator containing the union of two containers; duplicate +// values are not copied into the output. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) { + return std::set_union(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_union() for performing a merge using a `comp` other than +// `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output, + LessThan&& comp) { + return std::set_union(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_intersection() +// +// Container-based version of the `std::set_intersection()` function +// to return an iterator containing the intersection of two sorted containers. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_intersection(const C1& c1, const C2& c2, + OutputIterator output) { + // In debug builds, ensure that both containers are sorted with respect to the + // default comparator. std::set_intersection requires the containers be sorted + // using operator<. + assert(absl::c_is_sorted(c1)); + assert(absl::c_is_sorted(c2)); + return std::set_intersection(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_intersection() for performing a merge using a `comp` other +// than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_intersection(const C1& c1, const C2& c2, + OutputIterator output, LessThan&& comp) { + // In debug builds, ensure that both containers are sorted with respect to the + // default comparator. std::set_intersection requires the containers be sorted + // using the same comparator. + assert(absl::c_is_sorted(c1, comp)); + assert(absl::c_is_sorted(c2, comp)); + return std::set_intersection(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_difference() +// +// Container-based version of the `std::set_difference()` function +// to return an iterator containing elements present in the first container but +// not in the second. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_difference(const C1& c1, const C2& c2, + OutputIterator output) { + return std::set_difference(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_difference() for performing a merge using a `comp` other +// than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_difference(const C1& c1, const C2& c2, + OutputIterator output, LessThan&& comp) { + return std::set_difference(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_symmetric_difference() +// +// Container-based version of the `std::set_symmetric_difference()` +// function to return an iterator containing elements present in either one +// container or the other, but not both. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, + OutputIterator output) { + return std::set_symmetric_difference( + container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_symmetric_difference() for performing a merge using a +// `comp` other than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, + OutputIterator output, + LessThan&& comp) { + return std::set_symmetric_difference( + container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Heap functions +//------------------------------------------------------------------------------ + +// c_push_heap() +// +// Container-based version of the `std::push_heap()` function +// to push a value onto a container heap. +template +void c_push_heap(RandomAccessContainer& sequence) { + std::push_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_push_heap() for performing a push operation on a heap using a +// `comp` other than `operator<`. +template +void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::push_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_pop_heap() +// +// Container-based version of the `std::pop_heap()` function +// to pop a value from a heap container. +template +void c_pop_heap(RandomAccessContainer& sequence) { + std::pop_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_pop_heap() for performing a pop operation on a heap using a +// `comp` other than `operator<`. +template +void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::pop_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_make_heap() +// +// Container-based version of the `std::make_heap()` function +// to make a container a heap. +template +void c_make_heap(RandomAccessContainer& sequence) { + std::make_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_make_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::make_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_sort_heap() +// +// Container-based version of the `std::sort_heap()` function +// to sort a heap into ascending order (after which it is no longer a heap). +template +void c_sort_heap(RandomAccessContainer& sequence) { + std::sort_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_sort_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::sort_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_is_heap() +// +// Container-based version of the `std::is_heap()` function +// to check whether the given container is a heap. +template +bool c_is_heap(const RandomAccessContainer& sequence) { + return std::is_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_is_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) { + return std::is_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_is_heap_until() +// +// Container-based version of the `std::is_heap_until()` function +// to find the first element in a given container which is not in heap order. +template +container_algorithm_internal::ContainerIter +c_is_heap_until(RandomAccessContainer& sequence) { + return std::is_heap_until(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_is_heap_until() for performing heap comparisons using a +// `comp` other than `operator<` +template +container_algorithm_internal::ContainerIter +c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) { + return std::is_heap_until(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Min/max +//------------------------------------------------------------------------------ + +// c_min_element() +// +// Container-based version of the `std::min_element()` function +// to return an iterator pointing to the element with the smallest value, using +// `operator<` to make the comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence) { + return std::min_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_min_element() for performing a `comp` comparison other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence, LessThan&& comp) { + return std::min_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_max_element() +// +// Container-based version of the `std::max_element()` function +// to return an iterator pointing to the element with the largest value, using +// `operator<` to make the comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence) { + return std::max_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_max_element() for performing a `comp` comparison other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence, LessThan&& comp) { + return std::max_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_minmax_element() +// +// Container-based version of the `std::minmax_element()` function +// to return a pair of iterators pointing to the elements containing the +// smallest and largest values, respectively, using `operator<` to make the +// comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c) { + return std::minmax_element(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_minmax_element() for performing `comp` comparisons other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c, LessThan&& comp) { + return std::minmax_element(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Lexicographical Comparisons +//------------------------------------------------------------------------------ + +// c_lexicographical_compare() +// +// Container-based version of the `std::lexicographical_compare()` +// function to lexicographically compare (e.g. sort words alphabetically) two +// container sequences. The comparison is performed using `operator<`. Note +// that capital letters ("A-Z") have ASCII values less than lowercase letters +// ("a-z"). +template +bool c_lexicographical_compare(const Sequence1& sequence1, + const Sequence2& sequence2) { + return std::lexicographical_compare( + container_algorithm_internal::c_begin(sequence1), + container_algorithm_internal::c_end(sequence1), + container_algorithm_internal::c_begin(sequence2), + container_algorithm_internal::c_end(sequence2)); +} + +// Overload of c_lexicographical_compare() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +bool c_lexicographical_compare(const Sequence1& sequence1, + const Sequence2& sequence2, LessThan&& comp) { + return std::lexicographical_compare( + container_algorithm_internal::c_begin(sequence1), + container_algorithm_internal::c_end(sequence1), + container_algorithm_internal::c_begin(sequence2), + container_algorithm_internal::c_end(sequence2), + std::forward(comp)); +} + +// c_next_permutation() +// +// Container-based version of the `std::next_permutation()` function +// to rearrange a container's elements into the next lexicographically greater +// permutation. +template +bool c_next_permutation(C& c) { + return std::next_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_next_permutation() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +bool c_next_permutation(C& c, LessThan&& comp) { + return std::next_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_prev_permutation() +// +// Container-based version of the `std::prev_permutation()` function +// to rearrange a container's elements into the next lexicographically lesser +// permutation. +template +bool c_prev_permutation(C& c) { + return std::prev_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_prev_permutation() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +bool c_prev_permutation(C& c, LessThan&& comp) { + return std::prev_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// algorithms +//------------------------------------------------------------------------------ + +// c_iota() +// +// Container-based version of the `std::iota()` function +// to compute successive values of `value`, as if incremented with `++value` +// after each element is written, and write them to the container. +template +void c_iota(Sequence& sequence, const T& value) { + std::iota(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// c_accumulate() +// +// Container-based version of the `std::accumulate()` function +// to accumulate the element values of a container to `init` and return that +// accumulation by value. +// +// Note: Due to a language technicality this function has return type +// absl::decay_t. As a user of this function you can casually read +// this as "returns T by value" and assume it does the right thing. +template +decay_t c_accumulate(const Sequence& sequence, T&& init) { + return std::accumulate(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(init)); +} + +// Overload of c_accumulate() for using a binary operations other than +// addition for computing the accumulation. +template +decay_t c_accumulate(const Sequence& sequence, T&& init, + BinaryOp&& binary_op) { + return std::accumulate(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(init), + std::forward(binary_op)); +} + +// c_inner_product() +// +// Container-based version of the `std::inner_product()` function +// to compute the cumulative inner product of container element pairs. +// +// Note: Due to a language technicality this function has return type +// absl::decay_t. As a user of this function you can casually read +// this as "returns T by value" and assume it does the right thing. +template +decay_t c_inner_product(const Sequence1& factors1, const Sequence2& factors2, + T&& sum) { + return std::inner_product(container_algorithm_internal::c_begin(factors1), + container_algorithm_internal::c_end(factors1), + container_algorithm_internal::c_begin(factors2), + std::forward(sum)); +} + +// Overload of c_inner_product() for using binary operations other than +// `operator+` (for computing the accumulation) and `operator*` (for computing +// the product between the two container's element pair). +template +decay_t c_inner_product(const Sequence1& factors1, const Sequence2& factors2, + T&& sum, BinaryOp1&& op1, BinaryOp2&& op2) { + return std::inner_product(container_algorithm_internal::c_begin(factors1), + container_algorithm_internal::c_end(factors1), + container_algorithm_internal::c_begin(factors2), + std::forward(sum), std::forward(op1), + std::forward(op2)); +} + +// c_adjacent_difference() +// +// Container-based version of the `std::adjacent_difference()` +// function to compute the difference between each element and the one preceding +// it and write it to an iterator. +template +OutputIt c_adjacent_difference(const InputSequence& input, + OutputIt output_first) { + return std::adjacent_difference(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first); +} + +// Overload of c_adjacent_difference() for using a binary operation other than +// subtraction to compute the adjacent difference. +template +OutputIt c_adjacent_difference(const InputSequence& input, + OutputIt output_first, BinaryOp&& op) { + return std::adjacent_difference(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first, std::forward(op)); +} + +// c_partial_sum() +// +// Container-based version of the `std::partial_sum()` function +// to compute the partial sum of the elements in a sequence and write them +// to an iterator. The partial sum is the sum of all element values so far in +// the sequence. +template +OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first) { + return std::partial_sum(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first); +} + +// Overload of c_partial_sum() for using a binary operation other than addition +// to compute the "partial sum". +template +OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first, + BinaryOp&& op) { + return std::partial_sum(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first, std::forward(op)); +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_ALGORITHM_CONTAINER_H_ diff --git a/third_party/absl/base/attributes.h b/third_party/absl/base/attributes.h new file mode 100644 index 0000000000..0b94ae43b7 --- /dev/null +++ b/third_party/absl/base/attributes.h @@ -0,0 +1,997 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file defines macros for declaring attributes for functions, +// types, and variables. +// +// These macros are used within Abseil and allow the compiler to optimize, where +// applicable, certain function calls. +// +// Most macros here are exposing GCC or Clang features, and are stubbed out for +// other compilers. +// +// GCC attributes documentation: +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html +// +// Most attributes in this file are already supported by GCC 4.7. However, some +// of them are not supported in older version of Clang. Thus, we check +// `__has_attribute()` first. If the check fails, we check if we are on GCC and +// assume the attribute exists on GCC (which is verified on GCC 4.7). + +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + +#ifndef ABSL_BASE_ATTRIBUTES_H_ +#define ABSL_BASE_ATTRIBUTES_H_ + +#include "absl/base/config.h" + +// ABSL_HAVE_ATTRIBUTE +// +// A function-like feature checking macro that is a wrapper around +// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a +// nonzero constant integer if the attribute is supported or 0 if not. +// +// It evaluates to zero if `__has_attribute` is not defined by the compiler. +// +// GCC: https://gcc.gnu.org/gcc-5/changes.html +// Clang: https://clang.llvm.org/docs/LanguageExtensions.html +#ifdef __has_attribute +#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) +#else +#define ABSL_HAVE_ATTRIBUTE(x) 0 +#endif + +// ABSL_HAVE_CPP_ATTRIBUTE +// +// A function-like feature checking macro that accepts C++11 style attributes. +// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 +// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't +// find `__has_cpp_attribute`, will evaluate to 0. +#if defined(__cplusplus) && defined(__has_cpp_attribute) +// NOTE: requiring __cplusplus above should not be necessary, but +// works around https://bugs.llvm.org/show_bug.cgi?id=23435. +#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 +#endif + +// ----------------------------------------------------------------------------- +// Function Attributes +// ----------------------------------------------------------------------------- +// +// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +// Clang: https://clang.llvm.org/docs/AttributeReference.html + +// ABSL_PRINTF_ATTRIBUTE +// ABSL_SCANF_ATTRIBUTE +// +// Tells the compiler to perform `printf` format string checking if the +// compiler supports it; see the 'format' attribute in +// . +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__scanf__, string_index, first_to_check))) +#else +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) +#endif + +// ABSL_ATTRIBUTE_ALWAYS_INLINE +// ABSL_ATTRIBUTE_NOINLINE +// +// Forces functions to either inline or not inline. Introduced in gcc 3.1. +#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 +#else +#define ABSL_ATTRIBUTE_ALWAYS_INLINE +#endif + +#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 +#else +#define ABSL_ATTRIBUTE_NOINLINE +#endif + +// ABSL_ATTRIBUTE_NO_TAIL_CALL +// +// Prevents the compiler from optimizing away stack frames for functions which +// end in a call to another function. +#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) +#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ + __attribute__((optimize("no-optimize-sibling-calls"))) +#else +#define ABSL_ATTRIBUTE_NO_TAIL_CALL +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 +#endif + +// ABSL_ATTRIBUTE_WEAK +// +// Tags a function as weak for the purposes of compilation and linking. +// Weak attributes did not work properly in LLVM's Windows backend before +// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 +// for further information. Weak attributes do not work across DLL boundary. +// The MinGW compiler doesn't complain about the weak attribute until the link +// step, presumably because Windows doesn't use ELF binaries. +#if (ABSL_HAVE_ATTRIBUTE(weak) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + (!defined(_WIN32) || \ + (defined(__clang__) && __clang_major__ >= 9 && \ + !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \ + !defined(__MINGW32__) +#undef ABSL_ATTRIBUTE_WEAK +#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) +#define ABSL_HAVE_ATTRIBUTE_WEAK 1 +#else +#define ABSL_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_WEAK 0 +#endif + +// ABSL_ATTRIBUTE_NONNULL +// +// Tells the compiler either (a) that a particular function parameter +// should be a non-null pointer, or (b) that all pointer arguments should +// be non-null. +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +// +// Args are indexed starting at 1. +// +// For non-static class member functions, the implicit `this` argument +// is arg 1, and the first explicit argument is arg 2. For static class member +// functions, there is no implicit `this`, and the first explicit argument is +// arg 1. +// +// Example: +// +// /* arg_a cannot be null, but arg_b can */ +// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); +// +// class C { +// /* arg_a cannot be null, but arg_b can */ +// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); +// +// /* arg_a cannot be null, but arg_b can */ +// static void StaticMethod(void* arg_a, void* arg_b) +// ABSL_ATTRIBUTE_NONNULL(1); +// }; +// +// If no arguments are provided, then all pointer arguments should be non-null. +// +// /* No pointer arguments may be null. */ +// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); +// +// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but +// ABSL_ATTRIBUTE_NONNULL does not. +#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) +#else +#define ABSL_ATTRIBUTE_NONNULL(...) +#endif + +// ABSL_ATTRIBUTE_NORETURN +// +// Tells the compiler that a given function never returns. +// +// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over +// this macro. +#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define ABSL_ATTRIBUTE_NORETURN +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +// +// Tells the AddressSanitizer (or other memory testing tools) to ignore a given +// function. Useful for cases when a function reads random locations on stack, +// calls _exit from a cloned subprocess, deliberately accesses buffer +// out of bounds or does other scary things with memory. +// NOTE: GCC supports AddressSanitizer(asan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ + ABSL_HAVE_ATTRIBUTE(no_sanitize_address) +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \ + _MSC_VER >= 1928 +// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) +#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize) +// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU +// features to detect similar bugs with less CPU and memory overhead. +// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11. +// https://gcc.gnu.org/gcc-11/changes.html +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \ + __attribute__((no_sanitize("hwaddress"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +// +// Tells the MemorySanitizer to relax the handling of a given function. All "Use +// of uninitialized value" warnings from such functions will be suppressed, and +// all values loaded from memory will be considered fully initialized. This +// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute +// above, but deals with initialized-ness rather than addressability issues. +// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +// +// Tells the ThreadSanitizer to not instrument a given function. +// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +// +// Tells the UndefinedSanitizer to ignore a given function. Useful for cases +// where certain behavior (eg. division by zero) is being used intentionally. +// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. +// https://gcc.gnu.org/gcc-4.9/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_CFI +// +// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. +// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__) +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +// +// Tells the SafeStack to not instrument a given function. +// See https://clang.llvm.org/docs/SafeStack.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ + __attribute__((no_sanitize("safe-stack"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +#endif + +// ABSL_ATTRIBUTE_RETURNS_NONNULL +// +// Tells the compiler that a particular function never returns a null pointer. +#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) +#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define ABSL_ATTRIBUTE_RETURNS_NONNULL +#endif + +// ABSL_HAVE_ATTRIBUTE_SECTION +// +// Indicates whether labeled sections are supported. Weak symbol support is +// a prerequisite. Labeled sections are not supported on Darwin/iOS. +#ifdef ABSL_HAVE_ATTRIBUTE_SECTION +#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set +#elif (ABSL_HAVE_ATTRIBUTE(section) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_SECTION 1 + +// ABSL_ATTRIBUTE_SECTION +// +// Tells the compiler/linker to put a given function into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. Any function annotated with +// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into +// whatever section its caller is placed into. +// +#ifndef ABSL_ATTRIBUTE_SECTION +#define ABSL_ATTRIBUTE_SECTION(name) \ + __attribute__((section(#name))) __attribute__((noinline)) +#endif + +// ABSL_ATTRIBUTE_SECTION_VARIABLE +// +// Tells the compiler/linker to put a given variable into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. +#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE +#ifdef _AIX +// __attribute__((section(#name))) on AIX is achieved by using the `.csect` +// psudo op which includes an additional integer as part of its syntax indcating +// alignment. If data fall under different alignments then you might get a +// compilation error indicating a `Section type conflict`. +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#else +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) +#endif +#endif + +// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +// +// A weak section declaration to be used as a global declaration +// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link +// even without functions with ABSL_ATTRIBUTE_SECTION(name). +// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's +// a no-op on ELF but not on Mach-O. +// +#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ + extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ + extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK +#endif +#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#endif + +// ABSL_ATTRIBUTE_SECTION_START +// +// Returns `void*` pointers to start/end of a section of code with +// functions having ABSL_ATTRIBUTE_SECTION(name). +// Returns 0 if no such functions exist. +// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and +// link. +// +#define ABSL_ATTRIBUTE_SECTION_START(name) \ + (reinterpret_cast(__start_##name)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ + (reinterpret_cast(__stop_##name)) + +#else // !ABSL_HAVE_ATTRIBUTE_SECTION + +#define ABSL_HAVE_ATTRIBUTE_SECTION 0 + +// provide dummy definitions +#define ABSL_ATTRIBUTE_SECTION(name) +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) + +#endif // ABSL_ATTRIBUTE_SECTION + +// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +// +// Support for aligning the stack on 32-bit x86. +#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ + (defined(__GNUC__) && !defined(__clang__)) +#if defined(__i386__) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ + __attribute__((force_align_arg_pointer)) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#elif defined(__x86_64__) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#else // !__i386__ && !__x86_64 +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#endif // __i386__ +#else +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#endif + +// ABSL_MUST_USE_RESULT +// +// Tells the compiler to warn about unused results. +// +// For code or headers that are assured to only build with C++17 and up, prefer +// just using the standard `[[nodiscard]]` directly over this macro. +// +// When annotating a function, it must appear as the first part of the +// declaration or definition. The compiler will warn if the return value from +// such a function is unused: +// +// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); +// AllocateSprocket(); // Triggers a warning. +// +// When annotating a class, it is equivalent to annotating every function which +// returns an instance. +// +// class ABSL_MUST_USE_RESULT Sprocket {}; +// Sprocket(); // Triggers a warning. +// +// Sprocket MakeSprocket(); +// MakeSprocket(); // Triggers a warning. +// +// Note that references and pointers are not instances: +// +// Sprocket* SprocketPointer(); +// SprocketPointer(); // Does *not* trigger a warning. +// +// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result +// warning. For that, warn_unused_result is used only for clang but not for gcc. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 +// +// Note: past advice was to place the macro after the argument list. +// +// TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is +// compliant with the stricter [[nodiscard]]. +#if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) +#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD +// +// Tells GCC that a function is hot or cold. GCC can use this information to +// improve static analysis, i.e. a conditional branch to a cold function +// is likely to be not-taken. +// This annotation is used for function declarations. +// +// Example: +// +// int foo() ABSL_ATTRIBUTE_HOT; +#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) +#else +#define ABSL_ATTRIBUTE_HOT +#endif + +#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) +#else +#define ABSL_ATTRIBUTE_COLD +#endif + +// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS +// +// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT +// macro used as an attribute to mark functions that must always or never be +// instrumented by XRay. Currently, this is only supported in Clang/LLVM. +// +// For reference on the LLVM XRay instrumentation, see +// http://llvm.org/docs/XRay.html. +// +// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration +// will always get the XRay instrumentation sleds. These sleds may introduce +// some binary size and runtime overhead and must be used sparingly. +// +// These attributes only take effect when the following conditions are met: +// +// * The file/target is built in at least C++11 mode, with a Clang compiler +// that supports XRay attributes. +// * The file/target is built with the -fxray-instrument flag set for the +// Clang/LLVM compiler. +// * The function is defined in the translation unit (the compiler honors the +// attribute in either the definition or the declaration, and must match). +// +// There are cases when, even when building with XRay instrumentation, users +// might want to control specifically which functions are instrumented for a +// particular build using special-case lists provided to the compiler. These +// special case lists are provided to Clang via the +// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The +// attributes in source take precedence over these special-case lists. +// +// To disable the XRay attributes at build-time, users may define +// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific +// packages/targets, as this may lead to conflicting definitions of functions at +// link-time. +// +// XRay isn't currently supported on Android: +// https://github.com/android/ndk/issues/368 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ + !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) +#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] +#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) +#define ABSL_XRAY_LOG_ARGS(N) \ + [[clang::xray_always_instrument, clang::xray_log_args(N)]] +#else +#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] +#endif +#else +#define ABSL_XRAY_ALWAYS_INSTRUMENT +#define ABSL_XRAY_NEVER_INSTRUMENT +#define ABSL_XRAY_LOG_ARGS(N) +#endif + +// ABSL_ATTRIBUTE_REINITIALIZES +// +// Indicates that a member function reinitializes the entire object to a known +// state, independent of the previous state of the object. +// +// The clang-tidy check bugprone-use-after-move allows member functions marked +// with this attribute to be called on objects that have been moved from; +// without the attribute, this would result in a use-after-move warning. +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) +#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#else +#define ABSL_ATTRIBUTE_REINITIALIZES +#endif + +// ----------------------------------------------------------------------------- +// Variable Attributes +// ----------------------------------------------------------------------------- + +// ABSL_ATTRIBUTE_UNUSED +// +// Prevents the compiler from complaining about variables that appear unused. +// +// For code or headers that are assured to only build with C++17 and up, prefer +// just using the standard '[[maybe_unused]]' directly over this macro. +// +// Due to differences in positioning requirements between the old, compiler +// specific __attribute__ syntax and the now standard [[maybe_unused]], this +// macro does not attempt to take advantage of '[[maybe_unused]]'. +#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) +#undef ABSL_ATTRIBUTE_UNUSED +#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ABSL_ATTRIBUTE_UNUSED +#endif + +// ABSL_ATTRIBUTE_INITIAL_EXEC +// +// Tells the compiler to use "initial-exec" mode for a thread-local variable. +// See http://people.redhat.com/drepper/tls.pdf for the gory details. +#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) +#else +#define ABSL_ATTRIBUTE_INITIAL_EXEC +#endif + +// ABSL_ATTRIBUTE_PACKED +// +// Instructs the compiler not to use natural alignment for a tagged data +// structure, but instead to reduce its alignment to 1. +// +// Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing +// so can cause atomic variables to be mis-aligned and silently violate +// atomicity on x86. +// +// This attribute can either be applied to members of a structure or to a +// structure in its entirety. Applying this attribute (judiciously) to a +// structure in its entirety to optimize the memory footprint of very +// commonly-used structs is fine. Do not apply this attribute to a structure in +// its entirety if the purpose is to control the offsets of the members in the +// structure. Instead, apply this attribute only to structure members that need +// it. +// +// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the +// natural alignment of structure members not annotated is preserved. Aligned +// member accesses are faster than non-aligned member accesses even if the +// targeted microprocessor supports non-aligned accesses. +#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) +#else +#define ABSL_ATTRIBUTE_PACKED +#endif + +// ABSL_ATTRIBUTE_FUNC_ALIGN +// +// Tells the compiler to align the function start at least to certain +// alignment boundary +#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) +#endif + +// ABSL_FALLTHROUGH_INTENDED +// +// Annotates implicit fall-through between switch labels, allowing a case to +// indicate intentional fallthrough and turn off warnings about any lack of a +// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by +// a semicolon and can be used in most places where `break` can, provided that +// no statements exist between it and the next switch label. +// +// Example: +// +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations +// // in comments +// } else { +// return x; +// } +// case 42: +// ... +// +// Notes: When supported, GCC and Clang can issue a warning on switch labels +// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See +// clang documentation on language extensions for details: +// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough +// +// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has +// no effect on diagnostics. In any case this macro has no effect on runtime +// behavior and performance of code. + +#ifdef ABSL_FALLTHROUGH_INTENDED +#error "ABSL_FALLTHROUGH_INTENDED should not be defined." +#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#else +#define ABSL_FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +// ABSL_DEPRECATED() +// +// Marks a deprecated class, struct, enum, function, method and variable +// declarations. The macro argument is used as a custom diagnostic message (e.g. +// suggestion of a better alternative). +// +// For code or headers that are assured to only build with C++14 and up, prefer +// just using the standard `[[deprecated("message")]]` directly over this macro. +// +// Examples: +// +// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; +// +// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} +// +// template +// ABSL_DEPRECATED("Use DoThat() instead") +// void DoThis(); +// +// enum FooEnum { +// kBar ABSL_DEPRECATED("Use kBaz instead"), +// }; +// +// Every usage of a deprecated entity will trigger a warning when compiled with +// GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain +// turns this warning off by default, instead relying on clang-tidy to report +// new uses of deprecated code. +#if ABSL_HAVE_ATTRIBUTE(deprecated) +#define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) +#else +#define ABSL_DEPRECATED(message) +#endif + +// When deprecating Abseil code, it is sometimes necessary to turn off the +// warning within Abseil, until the deprecated code is actually removed. The +// deprecated code can be surrounded with these directives to achieve that +// result. +// +// class ABSL_DEPRECATED("Use Bar instead") Foo; +// +// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +// Baz ComputeBazFromFoo(Foo f); +// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#if defined(__GNUC__) || defined(__clang__) +// Clang also supports these GCC pragmas. +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("warning(push)") _Pragma("warning(disable: 4996)") +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("warning(pop)") +#else +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#endif // defined(__GNUC__) || defined(__clang__) + +// ABSL_CONST_INIT +// +// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will +// not compile (on supported platforms) unless the variable has a constant +// initializer. This is useful for variables with static and thread storage +// duration, because it guarantees that they will not suffer from the so-called +// "static init order fiasco". +// +// This attribute must be placed on the initializing declaration of the +// variable. Some compilers will give a -Wmissing-constinit warning when this +// attribute is placed on some other declaration but missing from the +// initializing declaration. +// +// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can +// also be used in a non-initializing declaration to tell the compiler that a +// variable is already initialized, reducing overhead that would otherwise be +// incurred by a hidden guard variable. Thus annotating all declarations with +// this attribute is recommended to potentially enhance optimization. +// +// Example: +// +// class MyClass { +// public: +// ABSL_CONST_INIT static MyType my_var; +// }; +// +// ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...); +// +// For code or headers that are assured to only build with C++20 and up, prefer +// just using the standard `constinit` keyword directly over this macro. +// +// Note that this attribute is redundant if the variable is declared constexpr. +#if defined(__cpp_constinit) && __cpp_constinit >= 201907L +#define ABSL_CONST_INIT constinit +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) +#define ABSL_CONST_INIT [[clang::require_constant_initialization]] +#else +#define ABSL_CONST_INIT +#endif + +// ABSL_ATTRIBUTE_PURE_FUNCTION +// +// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" +// functions. A function is pure if its return value is only a function of its +// arguments. The pure attribute prohibits a function from modifying the state +// of the program that is observable by means other than inspecting the +// function's return value. Declaring such functions with the pure attribute +// allows the compiler to avoid emitting some calls in repeated invocations of +// the function with the same argument values. +// +// Example: +// +// ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t); +#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] +#elif ABSL_HAVE_ATTRIBUTE(pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) +#else +// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since +// pure functions are useless if its return is ignored. +#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_CONST_FUNCTION +// +// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const" +// functions. A const function is similar to a pure function, with one +// exception: Pure functions may return value that depend on a non-volatile +// object that isn't provided as a function argument, while the const function +// is guaranteed to return the same result given the same arguments. +// +// Example: +// +// ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d); +#if defined(_MSC_VER) && !defined(__clang__) +// Put the MSVC case first since MSVC seems to parse const as a C++ keyword. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]] +#elif ABSL_HAVE_ATTRIBUTE(const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const)) +#else +// Since const functions are more restrictive pure function, we'll fallback to a +// pure function if the const attribute is not handled. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#endif + +// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function +// parameter or implicit object parameter is retained by the return value of the +// annotated function (or, for a parameter of a constructor, in the value of the +// constructed object). This attribute causes warnings to be produced if a +// temporary object does not live long enough. +// +// When applied to a reference parameter, the referenced object is assumed to be +// retained by the return value of the function. When applied to a non-reference +// parameter (for example, a pointer or a class type), all temporaries +// referenced by the parameter are assumed to be retained by the return value of +// the function. +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound +// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]] +#elif ABSL_HAVE_ATTRIBUTE(lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) +#else +#define ABSL_ATTRIBUTE_LIFETIME_BOUND +#endif + +// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it +// points to, similarly to a span, string_view, or other non-owning reference +// type. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template +// StringView(const R&); +// }; +// +// StringView f(std::string s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional sv) { return *sv; } +// +// See the following links for details: +// https://reviews.llvm.org/D64448 +// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]] +#else +#define ABSL_ATTRIBUTE_VIEW +#endif + +// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or +// similar class that owns all the data that it points to. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template +// StringView(const R&); +// }; +// +// struct ABSL_ATTRIBUTE_OWNER String {}; +// +// StringView f(String s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional sv) { return *sv; } +// +// See the following links for details: +// https://reviews.llvm.org/D64448 +// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]] +#else +#define ABSL_ATTRIBUTE_OWNER +#endif + +// ABSL_ATTRIBUTE_TRIVIAL_ABI +// Indicates that a type is "trivially relocatable" -- meaning it can be +// relocated without invoking the constructor/destructor, using a form of move +// elision. +// +// From a memory safety point of view, putting aside destructor ordering, it's +// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location +// can change over the course of its lifetime: if a constructor can be run one +// place, and then the object magically teleports to another place where some +// methods are run, and then the object teleports to yet another place where it +// is destroyed. This is notably not true for self-referential types, where the +// move-constructor must keep the self-reference up to date. If the type changed +// location without invoking the move constructor, it would have a dangling +// self-reference. +// +// The use of this teleporting machinery means that the number of paired +// move/destroy operations can change, and so it is a bad idea to apply this to +// a type meant to count the number of moves. +// +// Warning: applying this can, rarely, break callers. Objects passed by value +// will be destroyed at the end of the call, instead of the end of the +// full-expression containing the call. In addition, it changes the ABI +// of functions accepting this type by value (e.g. to pass in registers). +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi +// +// b/321691395 - This is currently disabled in open-source builds since +// compiler support differs. If system libraries compiled with GCC are mixed +// with libraries compiled with Clang, types will have different ideas about +// their ABI, leading to hard to debug crashes. +#define ABSL_ATTRIBUTE_TRIVIAL_ABI + +// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS +// +// Indicates a data member can be optimized to occupy no space (if it is empty) +// and/or its tail padding can be used for other members. +// +// For code that is assured to only build with C++20 or later, prefer using +// the standard attribute `[[no_unique_address]]` directly instead of this +// macro. +// +// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address +// Current versions of MSVC have disabled `[[no_unique_address]]` since it +// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for +// situations when it can be assured that it is desired. Since Abseil does not +// claim ABI compatibility in mixed builds, we can offer it unconditionally. +#if defined(_MSC_VER) && _MSC_VER >= 1929 +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address) +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_UNINITIALIZED +// +// GCC and Clang support a flag `-ftrivial-auto-var-init=