Кодирование / декодирование URL-адресов в C++

Кто-нибудь знает какой-нибудь хороший код на C++, который делает это?

Как насчет принятия ответа?

gsamaras 14.07.2016 01:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
85
1
130 301
19

Ответы 19

CGICC включает методы для кодирования и декодирования URL. form_urlencode и form_urldecode

Вы только что завели достойный разговор в нашем офисе с этой библиотекой.

J.J. 30.09.2008 23:35

На самом деле это самый простой и самый правильный код.

xryl669 03.02.2015 11:56

Отвечая на свой вопрос ...

libcurl имеет curl_easy_escape для кодирования.

Для декодирования curl_easy_unescape

Вы должны принять этот ответ, чтобы он был показан вверху (чтобы людям было проще).

Mouagip 04.11.2015 16:47

вам нужно использовать curl, чтобы это работало, и вам нужно освободить память

xinthose 05.11.2017 04:04

Связанный вопрос: почему curl unescape не обрабатывает замену '+' на пробел? Разве это не стандартная процедура при декодировании URL?

Stéphane 27.05.2019 09:59

string urlDecode(string &SRC) {
    string ret;
    char ch;
    int i, ii;
    for (i=0; i<SRC.length(); i++) {
        if (int(SRC[i])==37) {
            sscanf(SRC.substr(i+1,2).c_str(), "%x", &ii);
            ch=static_cast<char>(ii);
            ret+=ch;
            i=i+2;
        } else {
            ret+=SRC[i];
        }
    }
    return (ret);
}

не самый лучший, но работает нормально ;-)

Конечно, вы должны использовать '%' вместо 37.

John Zwinck 27.05.2014 17:05

Это не преобразует '+' в пробел

xryl669 03.02.2015 11:55

Добавление дополнения к рекомендации Билла об использовании libcurl: отличное предложение, которое будет обновлено:
через 3 года функция curl_escape устарела, поэтому для будущего использования лучше использовать curl_easy_escape.

Я столкнулся с этим вопросом при поиске api для декодирования URL-адреса в приложении win32 C++. Поскольку вопрос не совсем определяет платформу, предполагая, что окна - это не плохо.

InternetCanonicalizeUrl - это API для программ Windows. Подробнее здесь

        LPTSTR lpOutputBuffer = new TCHAR[1];
        DWORD dwSize = 1;
        BOOL fRes = ::InternetCanonicalizeUrl(strUrl, lpOutputBuffer, &dwSize, ICU_DECODE | ICU_NO_ENCODE);
        DWORD dwError = ::GetLastError();
        if (!fRes && dwError == ERROR_INSUFFICIENT_BUFFER)
        {
            delete lpOutputBuffer;
            lpOutputBuffer = new TCHAR[dwSize];
            fRes = ::InternetCanonicalizeUrl(strUrl, lpOutputBuffer, &dwSize, ICU_DECODE | ICU_NO_ENCODE);
            if (fRes)
            {
                //lpOutputBuffer has decoded url
            }
            else
            {
                //failed to decode
            }
            if (lpOutputBuffer !=NULL)
            {
                delete [] lpOutputBuffer;
                lpOutputBuffer = NULL;
            }
        }
        else
        {
            //some other error OR the input string url is just 1 char and was successfully decoded
        }

InternetCrackUrl (здесь) также, похоже, имеет флаги, чтобы указать, нужно ли декодировать URL

На днях я столкнулся с половиной этой проблемы с кодировкой. Недовольный доступными опциями, взглянув на этот пример кода C, я решил использовать свою собственную функцию кодирования URL-адресов C++:

#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>

using namespace std;

string url_encode(const string &value) {
    ostringstream escaped;
    escaped.fill('0');
    escaped << hex;

    for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
        string::value_type c = (*i);

        // Keep alphanumeric and other accepted characters intact
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            escaped << c;
            continue;
        }

        // Any other characters are percent-encoded
        escaped << uppercase;
        escaped << '%' << setw(2) << int((unsigned char) c);
        escaped << nouppercase;
    }

    return escaped.str();
}

Реализация функции декодирования предоставляется читателю в качестве упражнения. :П

Я считаю, что было бы более общим (в целом правильным) заменить "" на "% 20". Я соответствующим образом обновил код; не стесняйтесь откатывать назад, если не согласны.

Josh Kelley 15.07.2014 21:48

Нет, согласен. Также воспользовался шансом удалить этот бессмысленный вызов setw(0) (в то время я думал, что минимальная ширина останется установленной, пока я не верну ее обратно, но на самом деле она сбрасывается после следующего ввода).

xperroni 16.07.2014 02:19

На самом деле, это не преобразует '+' в пробел, поэтому не работает.

xryl669 03.02.2015 11:55

Разве вы не имеете в виду другое - конвертировать пробел до '+'? В любом случае, прочтите первый комментарий Джоша Келли, пробелы преобразуются в "% 20", что тоже хорошо.

xperroni 04.02.2015 05:36

Мне пришлось добавить std :: uppercase к строке «escaped << '%' << std :: uppercase << std :: setw (2) << int ((unsigned char) c);» В случае, если другие люди задаются вопросом, почему это возвращает, например,% 3a вместо% 3A

gumlym 11.09.2015 12:06

@gumlym, в этом нет необходимости. Согласно RFC 3984: «Заглавные шестнадцатеричные цифры от« A »до« F »эквивалентны строчным цифрам от« a »до« f », соответственно».

oferei 29.09.2015 17:12

Что ж, мне пришлось сделать это при попытке кодирования URL-адреса для создания подписи для amazon aws, и это не сработало, когда он вернул нижний регистр, он работал в верхнем регистре. Вот почему я разместил это

gumlym 29.09.2015 17:21

Фактически, RFC также говорит, что «[f] или согласованность, производители и нормализаторы URI должны использовать шестнадцатеричные цифры верхнего регистра для всех процентных кодировок». Так что это разумное изменение.

xperroni 30.09.2015 08:13

Мы должны добавить кое-что для потомков. Этот ответ обрабатывает Юникод! Есть много таких решений, которых нет.

Jonathan Henson 20.02.2016 00:58

Однако я не вижу смысла проверять "c> = 0" в условном выражении. Символы поступают из текстовой строки, которая должна содержать только допустимые коды символов. Единственный способ, которым он мог бы содержать отрицательные значения, заключался в том, что строка была повреждена или если ввод был намеренно создан для нарушения функции - и в обоих случаях вы могли также хочу завершить программу.

xperroni 21.02.2016 04:22

Это выглядит неправильно, потому что строки UTF-8 не поддерживаются (w3schools.com/tags/ref_urlencode.asp). Вроде работает только для Windows-1252

Skywalker13 01.12.2016 19:32

Проблема была как раз isalnum(c), его надо менять на isalnum((unsigned char) c)

Skywalker13 01.12.2016 19:44

Обратите внимание, что тип символа уже параметризован для value_type строки. Если вы хотите поддерживать UTF-8, правильное изменение - заменить ссылки на std::string, например, std::u8string в C++ 20.

xperroni 20.12.2018 23:15

инициализацию цикла for можно заменить на for (string::value_type c: value) с разделением первой инструкции

Stavros Avramidis 06.06.2019 18:07

Эта версия является чистой версией C и может дополнительно нормализовать путь к ресурсам. Использование его с C++ тривиально:

#include <string>
#include <iostream>

int main(int argc, char** argv)
{
    const std::string src("/some.url/foo/../bar/%2e/");
    std::cout << "src=\"" << src << "\"" << std::endl;

    // either do it the C++ conformant way:
    char* dst_buf = new char[src.size() + 1];
    urldecode(dst_buf, src.c_str(), 1);
    std::string dst1(dst_buf);
    delete[] dst_buf;
    std::cout << "dst1=\"" << dst1 << "\"" << std::endl;

    // or in-place with the &[0] trick to skip the new/delete
    std::string dst2;
    dst2.resize(src.size() + 1);
    dst2.resize(urldecode(&dst2[0], src.c_str(), 1));
    std::cout << "dst2=\"" << dst2 << "\"" << std::endl;
}

Выходы:

src = "/some.url/foo/../bar/%2e/"
dst1 = "/some.url/bar/"
dst2 = "/some.url/bar/"

И собственно функция:

#include <stddef.h>
#include <ctype.h>

/**
 * decode a percent-encoded C string with optional path normalization
 *
 * The buffer pointed to by @dst must be at least strlen(@src) bytes.
 * Decoding stops at the first character from @src that decodes to null.
 * Path normalization will remove redundant slashes and slash+dot sequences,
 * as well as removing path components when slash+dot+dot is found. It will
 * keep the root slash (if one was present) and will stop normalization
 * at the first questionmark found (so query parameters won't be normalized).
 *
 * @param dst       destination buffer
 * @param src       source buffer
 * @param normalize perform path normalization if nonzero
 * @return          number of valid characters in @dst
 * @author          Johan Lindh <[email protected]>
 * @legalese        BSD licensed (http://opensource.org/licenses/BSD-2-Clause)
 */
ptrdiff_t urldecode(char* dst, const char* src, int normalize)
{
    char* org_dst = dst;
    int slash_dot_dot = 0;
    char ch, a, b;
    do {
        ch = *src++;
        if (ch == '%' && isxdigit(a = src[0]) && isxdigit(b = src[1])) {
            if (a < 'A') a -= '0';
            else if (a < 'a') a -= 'A' - 10;
            else a -= 'a' - 10;
            if (b < 'A') b -= '0';
            else if (b < 'a') b -= 'A' - 10;
            else b -= 'a' - 10;
            ch = 16 * a + b;
            src += 2;
        }
        if (normalize) {
            switch (ch) {
            case '/':
                if (slash_dot_dot < 3) {
                    /* compress consecutive slashes and remove slash-dot */
                    dst -= slash_dot_dot;
                    slash_dot_dot = 1;
                    break;
                }
                /* fall-through */
            case '?':
                /* at start of query, stop normalizing */
                if (ch == '?')
                    normalize = 0;
                /* fall-through */
            case '\0':
                if (slash_dot_dot > 1) {
                    /* remove trailing slash-dot-(dot) */
                    dst -= slash_dot_dot;
                    /* remove parent directory if it was two dots */
                    if (slash_dot_dot == 3)
                        while (dst > org_dst && *--dst != '/')
                            /* empty body */;
                    slash_dot_dot = (ch == '/') ? 1 : 0;
                    /* keep the root slash if any */
                    if (!slash_dot_dot && dst == org_dst && *dst == '/')
                        ++dst;
                }
                break;
            case '.':
                if (slash_dot_dot == 1 || slash_dot_dot == 2) {
                    ++slash_dot_dot;
                    break;
                }
                /* fall-through */
            default:
                slash_dot_dot = 0;
            }
        }
        *dst++ = ch;
    } while(ch);
    return (dst - org_dst) - 1;
}

Спасибо. Здесь нет необязательных путей. pastebin.com/RN5g7g9u

Julian 03.06.2014 08:09

Это не соответствует никаким рекомендациям и совершенно неверно по сравнению с тем, что просит автор (например, «+» не заменяется пробелом). Нормализация пути не имеет ничего общего с декодированием URL. Если вы намерены нормализовать свой путь, вы должны сначала разделить свой URL-адрес на части (схема, полномочия, путь, запрос, фрагмент), а затем применить любой алгоритм, который вам нравится, только на части пути.

xryl669 03.02.2015 12:04

cpp-netlib имеет функции

namespace boost {
  namespace network {
    namespace uri {    
      inline std::string decoded(const std::string &input);
      inline std::string encoded(const std::string &input);
    }
  }
}

они позволяют очень легко кодировать и декодировать строки URL.

Боже, спасибо. документация по cpp-netlib скудна. У вас есть ссылки на хорошие шпаргалки?

user249806 13.05.2017 16:12

В Windows API есть функции UrlEscape / UrlUnescape, экспортируемые shlwapi.dll для этой задачи.

примечание: UrlEscape не кодирует +

Orwellophile 16.10.2017 13:15

Пришлось делать это в проекте без Boost. Итак, я написал свой собственный. Я просто выложу на GitHub: https://github.com/corporateshark/LUrlParser

clParseURL URL = clParseURL::ParseURL( "https://name:[email protected]:80/path/res" );

if ( URL.IsValid() )
{
    cout << "Scheme    : " << URL.m_Scheme << endl;
    cout << "Host      : " << URL.m_Host << endl;
    cout << "Port      : " << URL.m_Port << endl;
    cout << "Path      : " << URL.m_Path << endl;
    cout << "Query     : " << URL.m_Query << endl;
    cout << "Fragment  : " << URL.m_Fragment << endl;
    cout << "User name : " << URL.m_UserName << endl;
    cout << "Password  : " << URL.m_Password << endl;
}

Ваша ссылка ведет к библиотеке, которая анализирует URL-адрес. Он не% -кодирует URL. (Или, по крайней мере, я не мог увидеть% где-либо в источнике.) Таким образом, я не думаю, что это отвечает на вопрос.

Martin Bonner supports Monica 20.11.2015 16:23

[Режим некроманта включен]
Наткнулся на этот вопрос, когда искал быстрое, современное, платформенно-независимое и элегантное решение. Мне не понравилось что-либо из вышеперечисленного, cpp-netlib будет победителем, но он имеет ужасающую уязвимость памяти в "декодированной" функции. Так что я придумал решение для духовной ци и кармы от Boost.

namespace bsq = boost::spirit::qi;
namespace bk = boost::spirit::karma;
bsq::int_parser<unsigned char, 16, 2, 2> hex_byte;
template <typename InputIterator>
struct unescaped_string
    : bsq::grammar<InputIterator, std::string(char const *)> {
  unescaped_string() : unescaped_string::base_type(unesc_str) {
    unesc_char.add("+", ' ');

    unesc_str = *(unesc_char | "%" >> hex_byte | bsq::char_);
  }

  bsq::rule<InputIterator, std::string(char const *)> unesc_str;
  bsq::symbols<char const, char const> unesc_char;
};

template <typename OutputIterator>
struct escaped_string : bk::grammar<OutputIterator, std::string(char const *)> {
  escaped_string() : escaped_string::base_type(esc_str) {

    esc_str = *(bk::char_("a-zA-Z0-9_.~-") | "%" << bk::right_align(2,0)[bk::hex]);
  }
  bk::rule<OutputIterator, std::string(char const *)> esc_str;
};

Использование вышеуказанного как следующее:

std::string unescape(const std::string &input) {
  std::string retVal;
  retVal.reserve(input.size());
  typedef std::string::const_iterator iterator_type;

  char const *start = "";
  iterator_type beg = input.begin();
  iterator_type end = input.end();
  unescaped_string<iterator_type> p;

  if (!bsq::parse(beg, end, p(start), retVal))
    retVal = input;
  return retVal;
}

std::string escape(const std::string &input) {
  typedef std::back_insert_iterator<std::string> sink_type;
  std::string retVal;
  retVal.reserve(input.size() * 3);
  sink_type sink(retVal);
  char const *start = "";

  escaped_string<sink_type> g;
  if (!bk::generate(sink, g(start), input))
    retVal = input;
  return retVal;
}

[Режим некроманта отключен]

EDIT01: исправлено заполнение нулями - особая благодарность Хартмуту Кайзеру
EDIT02: В прямом эфире на CoLiRu

Что такое «ужасающая уязвимость памяти» cpp-netlib? Вы можете дать краткое объяснение или ссылку?

Craig M. Brandenburg 08.07.2015 00:26

Об этом (проблеме) уже сообщалось, поэтому я не сообщал и на самом деле не помню ... что-то вроде нарушения доступа при попытке проанализировать недопустимую escape-последовательность или что-то в этом роде

kreuzerkrieg 08.07.2015 17:47

о, вот и все github.com/cpp-netlib/cpp-netlib/issues/501

kreuzerkrieg 08.07.2015 17:50

Спасибо за разъяснения!

Craig M. Brandenburg 08.07.2015 18:26

Обычно добавление "%" к значению int символа при кодировании не работает, значение предполагается в шестнадцатеричном эквиваленте. например, "/" - это "% 2F", а не "% 47".

Я думаю, что это лучшие и краткие решения как для кодирования, так и для декодирования URL-адресов (без особых зависимостей заголовков).

string urlEncode(string str){
    string new_str = "";
    char c;
    int ic;
    const char* chars = str.c_str();
    char bufHex[10];
    int len = strlen(chars);

    for(int i=0;i<len;i++){
        c = chars[i];
        ic = c;
        // uncomment this if you want to encode spaces with +
        /*if (c==' ') new_str += '+';   
        else */if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') new_str += c;
        else {
            sprintf(bufHex,"%X",c);
            if (ic < 16) 
                new_str += "%0"; 
            else
                new_str += "%";
            new_str += bufHex;
        }
    }
    return new_str;
 }

string urlDecode(string str){
    string ret;
    char ch;
    int i, ii, len = str.length();

    for (i=0; i < len; i++){
        if (str[i] != '%'){
            if (str[i] == '+')
                ret += ' ';
            else
                ret += str[i];
        }else{
            sscanf(str.substr(i + 1, 2).c_str(), "%x", &ii);
            ch = static_cast<char>(ii);
            ret += ch;
            i = i + 2;
        }
    }
    return ret;
}

if (ic < 16) new_str += "%0"; Для чего это питание ?? @tormuto @reliasn

KriyenKP 20.02.2017 15:26

@Kriyen используется для дополнения закодированного HEX нулем в начале, если в результате получается одна буква; поскольку от 0 до 15 в HEX - это от 0 до F.

tormuto 02.03.2017 02:45

Мне больше всего нравится такой подход. +1 за использование стандартных библиотек. Хотя есть две проблемы, которые нужно исправить. Я чех и использую букву «ý». Результат: «% 0FFFFFFC3% 0FFFFFFBD». Сначала использовать переключатель 16 не обязательно, так как utf8 гарантирует, что все конечные байты будут начинаться с 10, и, похоже, это не помогло моему многобайту. Вторая проблема - это FF, потому что не все компьютеры имеют одинаковое количество бит на int. Исправление заключалось в том, чтобы пропустить переключатель 16 (не требуется) и захватить последние два символа из буфера. (Я использовал stringstream, поскольку мне удобнее использовать строковый буфер). Еще дал точку. Как и рама

Volt 26.12.2017 00:58

@Volt, не могли бы вы опубликовать обновленный код в новом ответе? Вы упоминаете о проблемах, но этого недостаточно для очевидного решения.

gregn3 31.05.2018 02:49

В этом ответе есть некоторые проблемы, потому что он использует strlen. Во-первых, это не имеет смысла, потому что мы уже знаем размер строкового объекта, так что это пустая трата времени. Гораздо хуже то, что строка может содержать 0 байтов, которые могут быть потеряны из-за strlen. Также if (i <16) неэффективен, потому что это может быть покрыто самим printf с помощью "%%% 02X". И, наконец, c должен быть беззнаковым байтом, иначе вы получите эффект, который @Volt описывал с ведущим '0xFFF ...'.

Devolus 11.01.2019 11:18

сочные кусочки

#include <ctype.h> // isdigit, tolower

from_hex(char ch) {
  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

char to_hex(char code) {
  static char hex[] = "0123456789abcdef";
  return hex[code & 15];
}

отмечая, что

char d = from_hex(hex[0]) << 4 | from_hex(hex[1]);

как в

// %7B = '{'

char d = from_hex('7') << 4 | from_hex('B');

Вдохновленный xperroni, я написал декодер. Спасибо за указатель.

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

char from_hex(char ch) {
    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

string url_decode(string text) {
    char h;
    ostringstream escaped;
    escaped.fill('0');

    for (auto i = text.begin(), n = text.end(); i != n; ++i) {
        string::value_type c = (*i);

        if (c == '%') {
            if (i[1] && i[2]) {
                h = from_hex(i[1]) << 4 | from_hex(i[2]);
                escaped << h;
                i += 2;
            }
        } else if (c == '+') {
            escaped << ' ';
        } else {
            escaped << c;
        }
    }

    return escaped.str();
}

int main(int argc, char** argv) {
    string msg = "J%C3%B8rn!";
    cout << msg << endl;
    string decodemsg = url_decode(msg);
    cout << decodemsg << endl;

    return 0;
}

edit: удалены ненужные cctype и iomainip.

Блок «if (c == '%')» требует дополнительной проверки выхода за пределы, i [1] и / или i [2] могут быть за пределами text.end (). Я бы тоже переименовал «сбежавший» в «неэкранированный». "escaped.fill ('0');" вероятно не нужен.

roalz 23.03.2018 15:54

Пожалуйста, посмотрите мою версию. Он более оптимизирован. pastebin.com/g0zMLpsj

KoD 20.10.2020 13:55

Я знаю, что вопрос касается метода C++, но для тех, кому он может понадобиться, я придумал очень короткую функцию на простом C для кодирования строки. Он не создает новую строку, а изменяет существующую, что означает, что он должен иметь достаточный размер, чтобы вместить новую строку. Очень легко угнаться.

void urlEncode(char *string)
{
    char charToEncode;
    int posToEncode;
    while (((posToEncode=strspn(string,"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.~"))!=0) &&(posToEncode<strlen(string)))
    {
        charToEncode=string[posToEncode];
        memmove(string+posToEncode+3,string+posToEncode+1,strlen(string+posToEncode));
        string[posToEncode]='%';
        string[posToEncode+1] = "0123456789ABCDEF"[charToEncode>>4];
        string[posToEncode+2] = "0123456789ABCDEF"[charToEncode&0xf];
        string+=posToEncode+3;
    }
}

Вы можете использовать функцию g_uri_escape_string (), предоставленную glib.h. https://developer.gnome.org/glib/stable/glib-URI-Functions.html

#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
int main() {
    char *uri = "http://www.example.com?hello world";
    char *encoded_uri = NULL;
    //as per wiki (https://en.wikipedia.org/wiki/Percent-encoding)
    char *escape_char_str = "!*'();:@&=+$,/?#[]"; 
    encoded_uri = g_uri_escape_string(uri, escape_char_str, TRUE);
    printf("[%s]\n", encoded_uri);
    free(encoded_uri);

    return 0;
}

скомпилируйте его с помощью:

gcc encoding_URI.c `pkg-config --cflags --libs glib-2.0`

Другое решение доступно с использованием Библиотека глупостей Facebook: folly::uriEscape и folly::uriUnescape.

Я не смог найти здесь URI decode / unescape, который также декодирует 2- и 3-байтовые последовательности. Внесу свой вклад в мою собственную высокопроизводительную версию, которая на лету преобразует ввод c sting в wstring:

#include <string>

const char HEX2DEC[55] =
{
     0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
    -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,10,11,12, 13,14,15
};

#define __x2d__(s) HEX2DEC[*(s)-48]
#define __x2d2__(s) __x2d__(s) << 4 | __x2d__(s+1)

std::wstring decodeURI(const char * s) {
    unsigned char b;
    std::wstring ws;
    while (*s) {
        if (*s == '%')
            if ((b = __x2d2__(s + 1)) >= 0x80) {
                if (b >= 0xE0) { // three byte codepoint
                    ws += ((b & 0b00001111) << 12) | ((__x2d2__(s + 4) & 0b00111111) << 6) | (__x2d2__(s + 7) & 0b00111111);
                    s += 9;
                }
                else { // two byte codepoint
                    ws += (__x2d2__(s + 4) & 0b00111111) | (b & 0b00000011) << 6;
                    s += 6;
                }
            }
            else { // one byte codepoints
                ws += b;
                s += 3;
            }
        else { // no %
            ws += *s;
            s++;
        }
    }
    return ws;
}

#define __x2d2__(s) (__x2d__(s) << 4 | __x2d__(s+1)), и он должен быть собран с -WError.

Janek Olszak 13.06.2017 18:04

Извините, но "высокая производительность" при добавлении одиночных символов в wstring нереальна. По крайней мере, для reserve достаточно места, иначе у вас все время будут массовые перераспределения

Felix Dombek 18.08.2017 00:59

вы можете просто использовать функцию AtlEscapeUrl () из atlutil.h, просто просмотрите ее документацию о том, как ее использовать.

это будет работать только с окнами

kritzikratzi 22.01.2018 17:14

Да, я пробовал это в Windows.

Pratik 23.01.2018 10:06

Другие вопросы по теме