This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 418f6c527136ebc7eaecc6bd4e38adc05d147019 Author: Chris McFarlen <[email protected]> AuthorDate: Thu May 30 13:30:12 2024 -0500 Add ts::hex and ts::unhex (#11392) * Add ts::hex and ts::unhex * add license * add one more test case * Document hex/unhex functions (cherry picked from commit b0278b974261bf324dbd93807d0053c6a279e17f) --- include/tsutil/StringConvert.h | 93 +++++++++++++++++++++++++++++ src/cripts/Crypto.cc | 9 +-- src/cripts/Lulu.cc | 18 ++---- src/tsutil/CMakeLists.txt | 1 + src/tsutil/unit_tests/test_StringConvert.cc | 33 ++++++++++ 5 files changed, 136 insertions(+), 18 deletions(-) diff --git a/include/tsutil/StringConvert.h b/include/tsutil/StringConvert.h new file mode 100644 index 0000000000..3465b5c7da --- /dev/null +++ b/include/tsutil/StringConvert.h @@ -0,0 +1,93 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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 + + http://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. +*/ + +#pragma once + +#include <charconv> +#include <stdexcept> +#include <string> +#include <system_error> + +namespace ts +{ + +/** + * Convert input string into a hex string + * + * Each character in input is interpreted as an unsigned char and represented as a two-digit hex value [0-255] in the returned + * string. + * + * @param input Input string view + * @return The hex representation of the input string + * + * @note this is a specialization of boost::algorithms::hex + */ +inline std::string +hex(const std::string_view input) +{ + std::string result; + + result.resize(input.size() * 2); + + char *p = result.data(); + for (auto x : input) { + if (auto [ptr, err] = std::to_chars(p, result.data() + result.size(), x, 16); err == std::errc()) { + p = ptr; + } else { + throw std::runtime_error(std::make_error_code(err).message().c_str()); + } + } + + return result; +} + +/** + * Convert input hex string into a string + * + * The input string must have even size and be comprised of hex digits [0-f]. Each two-digit pair is converted from hex to a + * character in the resulting output string. + * + * @param input Input string view + * @return The unhexified result string + * + * @note this is a specialization of boost::algorithms::unhex + */ +inline std::string +unhex(const std::string_view input) +{ + std::string result; + + if (input.size() % 2 != 0) { + throw std::invalid_argument("input to unhex needs to be an even size"); + } + + result.resize(input.size() / 2); + + const char *p = input.data(); + for (auto &x : result) { + if (auto [ptr, err] = std::from_chars(p, p + 2, x, 16); err == std::errc()) { + p = ptr; + } else { + throw std::runtime_error(std::make_error_code(err).message().c_str()); + } + } + + return result; +} + +} // namespace ts diff --git a/src/cripts/Crypto.cc b/src/cripts/Crypto.cc index 9459b13686..c3f11a60bb 100644 --- a/src/cripts/Crypto.cc +++ b/src/cripts/Crypto.cc @@ -20,6 +20,7 @@ #include "cripts/Lulu.hpp" #include "cripts/Preamble.hpp" +#include "tsutil/StringConvert.h" // From ATS, seems high ... #define ENCODED_LEN(len) (((int)ceil(1.34 * (len) + 5)) + 1) @@ -110,17 +111,13 @@ Crypto::Escape::decode(Cript::string_view str) Cript::string Crypto::detail::Digest::hex() const { - // ToDo: Need to make this without Boost - // return boost::algorithm::hex(Cript::string(reinterpret_cast<const char *>(_hash), _length)); - return {reinterpret_cast<const char *>(_hash), _length}; + return ts::hex({reinterpret_cast<const char *>(_hash), _length}); } Cript::string Crypto::detail::Cipher::hex() const { - // ToDo: Need to make this without Boost - // return boost::algorithm::hex(_message); - return _message; + return ts::hex(_message); } Crypto::SHA256 diff --git a/src/cripts/Lulu.cc b/src/cripts/Lulu.cc index 567bc39171..6bdaefd47e 100644 --- a/src/cripts/Lulu.cc +++ b/src/cripts/Lulu.cc @@ -23,6 +23,8 @@ #include "cripts/Lulu.hpp" #include "cripts/Preamble.hpp" +#include "tsutil/StringConvert.h" + #if CRIPTS_HAS_MAXMIND #include <maxminddb.h> @@ -104,33 +106,25 @@ splitter(T input, char delim) Cript::string Cript::hex(const Cript::string &str) { - // ToDo: Need to make this without Boost - // return boost::algorithm::hex(str); - return str; + return ts::hex(str); } Cript::string Cript::hex(Cript::string_view sv) { - // ToDo: Need to make this without Boost - // return hex(Cript::string(sv)); - return Cript::string(sv); + return ts::hex(sv); } Cript::string Cript::unhex(const Cript::string &str) { - // ToDo: Need to make this without Boost - // return boost::algorithm::unhex(str); - return str; + return ts::unhex(str); } Cript::string Cript::unhex(Cript::string_view sv) { - // ToDo: Need to make this without Boost - // return unhex(Cript::string(sv)); - return Cript::string(sv); + return ts::unhex(sv); } Cript::string::operator integer() const diff --git a/src/tsutil/CMakeLists.txt b/src/tsutil/CMakeLists.txt index beca3c8a25..d018301f0c 100644 --- a/src/tsutil/CMakeLists.txt +++ b/src/tsutil/CMakeLists.txt @@ -75,6 +75,7 @@ if(BUILD_TESTING) unit_tests/test_LocalBuffer.cc unit_tests/test_PostScript.cc unit_tests/test_Strerror.cc + unit_tests/test_StringConvert.cc unit_tests/test_Regex.cc unit_tests/test_ts_meta.cc unit_tests/test_time_parser.cc diff --git a/src/tsutil/unit_tests/test_StringConvert.cc b/src/tsutil/unit_tests/test_StringConvert.cc new file mode 100644 index 0000000000..06f708b513 --- /dev/null +++ b/src/tsutil/unit_tests/test_StringConvert.cc @@ -0,0 +1,33 @@ +/** @file + + Unit tests for StringConvert + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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 + + http://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. + */ + +#include <catch.hpp> + +#include <tsutil/StringConvert.h> + +TEST_CASE("StringConvert", "[STE]") +{ + REQUIRE(ts::hex("01") == "3031"); + REQUIRE(ts::unhex("3031") == "01"); + REQUIRE(ts::hex("5pn2QM") == "35706e32514d"); +}
