euarel

A CLI tool for URL percent-encoding and percent-decoding text.


euarel

/

src

/

euarel.cc

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
#include "euarel.hh"

#include <cstdio>
#include <cctype>
#include <cstddef>

#include <string>

namespace OB::Euarel
{

std::string hex_encode(char const c);
char hex_decode(std::string const& s);

std::string hex_encode(char const c)
{
  char s[3];

  if (c & 0x80)
  {
    std::snprintf(&s[0], 3, "%02X",
      static_cast<unsigned int>(c & 0xff)
    );
  }
  else
  {
    std::snprintf(&s[0], 3, "%02X",
      static_cast<unsigned int>(c)
    );
  }

  return std::string(s);
}

char hex_decode(std::string const& s)
{
  unsigned int n;

  std::sscanf(s.data(), "%x", &n);

  return static_cast<char>(n);
}

std::string url_encode(std::string const& str, bool form)
{
  std::string res;
  res.reserve(str.size());

  for (auto const& e : str)
  {
    if (e == ' ' && form)
    {
      res += "+";
    }
    else if (std::isalnum(static_cast<unsigned char>(e)) ||
      e == '-' || e == '_' || e == '.' || e == '~')
    {
      res += e;
    }
    else
    {
      res += "%" + hex_encode(e);
    }
  }

  return res;
}

std::string url_decode(std::string const& str, bool form)
{
  std::string res;
  res.reserve(str.size());

  for (std::size_t i = 0; i < str.size(); ++i)
  {
    if (str[i] == '+' && form)
    {
      res += " ";
    }
    else if (str[i] == '%' && i + 2 < str.size() &&
      std::isxdigit(static_cast<unsigned char>(str[i + 1])) &&
      std::isxdigit(static_cast<unsigned char>(str[i + 2])))
    {
      res += hex_decode(str.substr(i + 1, 2));
      i += 2;
    }
    else
    {
      res += str[i];
    }
  }

  return res;
}

} // namespace OB::Euarel
Back to Top