Author: Jonas Devlieghere
Date: 2026-06-30T12:47:06-07:00
New Revision: 6ae0aab16af4c692ac0834fbdcd3bc2ce74a4147

URL: 
https://github.com/llvm/llvm-project/commit/6ae0aab16af4c692ac0834fbdcd3bc2ce74a4147
DIFF: 
https://github.com/llvm/llvm-project/commit/6ae0aab16af4c692ac0834fbdcd3bc2ce74a4147.diff

LOG: [ADT] Add printPercentEncoded to StringExtras (#206794)

Hoist URL query-component percent-encoding into llvm/ADT alongside the
other per-character string escapers (printEscapedString,
printHTMLEscaped, printLowerCase). Several near-identical copies of this
encoder exist across the tree, all using the same RFC 3986 charset.

Added: 
    

Modified: 
    lldb/source/Host/common/Host.cpp
    lldb/tools/lldb-dap/ClientLauncher.cpp
    llvm/include/llvm/ADT/StringExtras.h
    llvm/lib/Support/StringExtras.cpp
    llvm/unittests/ADT/StringExtrasTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Host/common/Host.cpp 
b/lldb/source/Host/common/Host.cpp
index b7a1020b4abd3..81d45f78559ce 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -660,13 +660,7 @@ llvm::Error Host::OpenURL(llvm::StringRef url) {
 std::string Host::URLEncode(llvm::StringRef str) {
   std::string out;
   llvm::raw_string_ostream os(out);
-  for (unsigned char c : str) {
-    if (std::isalnum(c) || llvm::StringRef("-_.~").contains(c))
-      os << c;
-    else
-      os << '%' << llvm::hexdigit((c >> 4) & 0xF, /*LowerCase=*/false)
-         << llvm::hexdigit(c & 0xF, /*LowerCase=*/false);
-  }
+  llvm::printPercentEncoded(str, os);
   return out;
 }
 

diff  --git a/lldb/tools/lldb-dap/ClientLauncher.cpp 
b/lldb/tools/lldb-dap/ClientLauncher.cpp
index 3244de9c5d0f0..7afedde8b8b0b 100644
--- a/lldb/tools/lldb-dap/ClientLauncher.cpp
+++ b/lldb/tools/lldb-dap/ClientLauncher.cpp
@@ -35,13 +35,8 @@ ClientLauncher::GetLauncher(ClientLauncher::Client client) {
 std::string VSCodeLauncher::URLEncode(llvm::StringRef str) {
   std::string out;
   llvm::raw_string_ostream os(out);
-  for (char c : str) {
-    if (std::isalnum(c) || llvm::StringRef("-_.~").contains(c))
-      os << c;
-    else
-      os << '%' << llvm::utohexstr(c, false, 2);
-  }
-  return os.str();
+  llvm::printPercentEncoded(str, os);
+  return out;
 }
 
 std::string

diff  --git a/llvm/include/llvm/ADT/StringExtras.h 
b/llvm/include/llvm/ADT/StringExtras.h
index e3cc6dcb25755..71e0c14c977a8 100644
--- a/llvm/include/llvm/ADT/StringExtras.h
+++ b/llvm/include/llvm/ADT/StringExtras.h
@@ -399,6 +399,12 @@ LLVM_ABI void printHTMLEscaped(StringRef String, 
raw_ostream &Out);
 /// printLowerCase - Print each character as lowercase if it is uppercase.
 LLVM_ABI void printLowerCase(StringRef String, raw_ostream &Out);
 
+/// Print each character of \p String percent-encoded for use as a URL
+/// query-component value (RFC 3986): unreserved characters (ALPHA, DIGIT,
+/// '-' '_' '.' '~') are written directly; every other byte becomes an
+/// uppercase %XX escape. Operates on raw bytes, so UTF-8 round-trips.
+LLVM_ABI void printPercentEncoded(StringRef String, raw_ostream &Out);
+
 /// Converts a string from camel-case to snake-case by replacing all uppercase
 /// letters with '_' followed by the letter in lowercase, except if the
 /// uppercase letter is the first character of the string.

diff  --git a/llvm/lib/Support/StringExtras.cpp 
b/llvm/lib/Support/StringExtras.cpp
index bb2fa49bcbbc9..2d08012c9195f 100644
--- a/llvm/lib/Support/StringExtras.cpp
+++ b/llvm/lib/Support/StringExtras.cpp
@@ -79,6 +79,15 @@ void llvm::printLowerCase(StringRef String, raw_ostream 
&Out) {
     Out << toLower(C);
 }
 
+void llvm::printPercentEncoded(StringRef String, raw_ostream &Out) {
+  for (unsigned char C : String) {
+    if (isAlnum(C) || StringRef("-_.~").contains(C))
+      Out << C;
+    else
+      Out << '%' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
+  }
+}
+
 std::string llvm::convertToSnakeFromCamelCase(StringRef input) {
   if (input.empty())
     return "";

diff  --git a/llvm/unittests/ADT/StringExtrasTest.cpp 
b/llvm/unittests/ADT/StringExtrasTest.cpp
index af88f88949b77..23ba1b0037b1e 100644
--- a/llvm/unittests/ADT/StringExtrasTest.cpp
+++ b/llvm/unittests/ADT/StringExtrasTest.cpp
@@ -189,6 +189,27 @@ TEST(StringExtrasTest, printHTMLEscaped) {
   EXPECT_EQ("ABCdef123&amp;&lt;&gt;&quot;&apos;", OS.str());
 }
 
+TEST(StringExtrasTest, printPercentEncoded) {
+  auto encode = [](StringRef In) {
+    std::string Str;
+    raw_string_ostream OS(Str);
+    printPercentEncoded(In, OS);
+    return Str;
+  };
+
+  // Unreserved characters pass through unchanged.
+  EXPECT_EQ("AZaz09-_.~", encode("AZaz09-_.~"));
+  // Reserved characters are percent-encoded with uppercase hex.
+  EXPECT_EQ("a%20b%26c%3Dd", encode("a b&c=d"));
+  EXPECT_EQ("%2F%3F%23", encode("/?#"));
+  // Multi-byte UTF-8 is encoded byte by byte.
+  EXPECT_EQ("%C3%A9", encode("\xC3\xA9"));
+  // High bytes must not sign-extend into an over-long escape.
+  EXPECT_EQ("%80", encode("\x80"));
+  // The empty string maps to the empty string.
+  EXPECT_EQ("", encode(""));
+}
+
 TEST(StringExtrasTest, ConvertToSnakeFromCamelCase) {
   auto testConvertToSnakeCase = [](llvm::StringRef input,
                                    llvm::StringRef expected) {


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to