This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new b0278b9742 Add ts::hex and ts::unhex (#11392)
b0278b9742 is described below
commit b0278b974261bf324dbd93807d0053c6a279e17f
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
---
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 48e3df46b1..0265e105b6 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");
+}