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");
+}

Reply via email to