URL Encoder - процентное кодирование
Модератор: Модераторы
URL Encoder - процентное кодирование
Здравствуйте, мне нужно сделать процентное кодирование строки для получения URL. Решение нашел в синапсе, но уж больно оно древнее.
В теме про Lazarus 1.6 многие удивлялись: зачем нужен доступ к символу в строке по индексу? Мол и без него все хорошо.
Так вот все найденные мной решения процентного кодирования - отрыжка Delphi ({$MODE DELPHI}) с доступом к символам по индексу и прочими пережитками (проверка наличия во множестве символа - in и т.п.).
А существует ли вообще библиотека с модным UTF8 кодированием?
В теме про Lazarus 1.6 многие удивлялись: зачем нужен доступ к символу в строке по индексу? Мол и без него все хорошо.
Так вот все найденные мной решения процентного кодирования - отрыжка Delphi ({$MODE DELPHI}) с доступом к символам по индексу и прочими пережитками (проверка наличия во множестве символа - in и т.п.).
А существует ли вообще библиотека с модным UTF8 кодированием?
У меня вообще наверное ни одна программа без обращения к строке по индексу работать не сможет ... Удобно ведь... да UTF8 ну и что ?
Бред это ! Если так уж нужно перекодирую в Win-1251 обработаю и верну обратно в UTF8...
И вообще UTF8 уродливая пародия на UTF16 ! Нужно перейти на полностью 2 байтовую кодировку и забить болт на тупые костыли !
Бред это ! Если так уж нужно перекодирую в Win-1251 обработаю и верну обратно в UTF8...
И вообще UTF8 уродливая пародия на UTF16 ! Нужно перейти на полностью 2 байтовую кодировку и забить болт на тупые костыли !
resident,
я вам одну простую вещь сейчас скажу: там, где используется URL-кодированная строка, ничего кроме ASCII в этом коде быть не может.
Или вы про посимвольный доступ к исходной строке? Вот тут не помню, URL-кодирование разве не побайтное?
http://en.wikipedia.org/wiki/Percent-encoding
я вам одну простую вещь сейчас скажу: там, где используется URL-кодированная строка, ничего кроме ASCII в этом коде быть не может.
Или вы про посимвольный доступ к исходной строке? Вот тут не помню, URL-кодирование разве не побайтное?
http://en.wikipedia.org/wiki/Percent-encoding
Since the publication of RFC 1738 in 1994 it has been specified[1] that schemes that provide for the representation of binary data in a URI must divide the data into 8-bit bytes and percent-encode each byte in the same manner as above.
...
The generic URI syntax mandates that new URI schemes that provide for the representation of character data in a URI must, in effect, represent characters from the unreserved set without translation, and should convert all other characters to bytes according to UTF-8, and then percent-encode those values. This requirement was introduced in January 2005 with the publication of RFC 3986.
>>А существует ли вообще библиотека с модным UTF8 кодированием?
Фу таким быть)) Сейчас в моду входит какраз UTF16 - в fpc уже появилось, в lcl пока нет
UTF8 - можно сказать "ретро" из старых, светлых времен 2.6.x))
По теме: не нужен посимвольный доступ. Используйте побайтовый. подсмотрите в педевикии что из себя представляет utf8 в байтах и вперед. Получится компактнее и думаю быстрее чем с "посимвольным".
Фу таким быть)) Сейчас в моду входит какраз UTF16 - в fpc уже появилось, в lcl пока нет
UTF8 - можно сказать "ретро" из старых, светлых времен 2.6.x))
По теме: не нужен посимвольный доступ. Используйте побайтовый. подсмотрите в педевикии что из себя представляет utf8 в байтах и вперед. Получится компактнее и думаю быстрее чем с "посимвольным".
- Ichthyander
- энтузиаст
- Сообщения: 701
- Зарегистрирован: 04.04.2007 08:32:43
- Откуда: Астрахань
- Контактная информация:
А чем решение в синапсе не понравилось? Я его всегда юзаю. Вкрай можно его доработать [и кинуть исходники автору
]
bormant писал(а):Или вы про посимвольный доступ к исходной строке? Вот тут не помню, URL-кодирование разве не побайтное?
Так и есть.
zub писал(а):Сейчас в моду входит какраз UTF16 - в fpc уже появилось, в lcl пока нет
Внезапно. Чем они раньше думали, когда UTF8 согласовывали.
zub писал(а):Получится компактнее и думаю быстрее чем с "посимвольным".
Действительно, все решение в несколько строк получилось.
Код: Выделить всё
type
TDoNotEncodeUsASCIICharsSet = set of Char;
function StrToPercentTriplet(const Str: string; const DoNotEncodeUsASCIICharsSet: TDoNotEncodeUsASCIICharsSet = []): string;
var
i: integer;
ByteValue: integer;
begin
Result := '';
for i := 1 to Length(Str) do
begin
ByteValue := Integer(Str[i]);
if (ByteValue < 128) and (Str[i] in DoNotEncodeUsASCIICharsSet) then
Result := Result + Str[i] else
Result := Result + '%' + IntToHex(ByteValue, 2);
end;
end;
function StrToUrl(const Str: string): string;
const
UnreservedCharacters: set of Char = ['A'..'Z', 'a'..'z', '0'..'9', '-', '.', '_', '~'];
begin
Result := StrToPercentTriplet(Str, UnreservedCharacters);
end;
Ichthyander писал(а):А чем решение в синапсе не понравилось?
1) Не удовлетворяет стандарту RFC 3986
2) Всякие Mode Delphi, Ansistring не хочу видеть, хочу чтоб все модно было.
>>хочу чтоб все модно было.
надо избавиться от конструкций типа
надо избавиться от конструкций типа
Код: Выделить всё
Result := Result + ...zub писал(а):надо избавиться от конструкций типа
Вредители какие-то.
Да ну к черту такую моду.
http://listingimg.s3.amazonaws.com/DjFly-NashaRasha.mp3
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
zub, а по моему, очень удобно.
конечно удобно. но медленно
Такое "модно" было во времена string[255], но не с длинными строками
Такое "модно" было во времена string[255], но не с длинными строками
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
zub, работа со строками никогда не была особо быстрой. Хотя со временем это становится не так актуально -- скорости растут.
Возможно, дело еще и в реализации самих библиотек работы со строками.
Возможно, дело еще и в реализации самих библиотек работы со строками.
Такая "работа" конечно быстрой быть не может.
Если сделать нормально - будет на порядок быстрее
Добавлено спустя 1 час 43 минуты 28 секунд:
Вот собственно что у меня получилось:
Преобразование байта в хекс сделано навскидку, не прверял, если и неправильно - на скорость это не влияет. Рядом с ексешником должен лежать файл warandpeace.txt с чемто большим в UTF8, я для теста юзал войну и мир Толстого.
результат налицо))
Смысл в том чтоб не прибавлять по байтику, а сделать 2 прохода. в первом посчитать длину строки с результатом, во втором присваивать байтики в уже созданую строку
Если сделать нормально - будет на порядок быстрее
Добавлено спустя 1 час 43 минуты 28 секунд:
Вот собственно что у меня получилось:
Код: Выделить всё
program encodetest;
uses
sysutils;
type
TDoNotEncodeUsASCIICharsSet = set of Char;
function StrToPercentTriplet(const Str: string; const DoNotEncodeUsASCIICharsSet: TDoNotEncodeUsASCIICharsSet = []): string;
var
i: integer;
ByteValue: integer;
begin
Result := '';
for i := 1 to Length(Str) do
begin
ByteValue := ord(Str[i]);
if (ByteValue < 128) and (Str[i] in DoNotEncodeUsASCIICharsSet) then
Result := Result + Str[i] else
Result := Result + '%' + IntToHex(ByteValue, 2);
end;
end;
function StrToUrl(const Str: string): string;
const
UnreservedCharacters: set of Char = ['A'..'Z', 'a'..'z', '0'..'9', '-', '.', '_', '~'];
begin
Result := StrToPercentTriplet(Str, UnreservedCharacters);
end;
function FastStrToPercentTriplet(const Str: string;var ResultString:string; const DoNotEncodeUsASCIICharsSet: TDoNotEncodeUsASCIICharsSet = []): integer;
const
_Hex:array[0..15] of char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
var
i: integer;
ByteValue: byte;
begin
result:=1;
for i := 1 to Length(Str) do
begin
ByteValue := ord(Str[i]);
if (ByteValue < 128) and (Str[i] in DoNotEncodeUsASCIICharsSet)
then
begin
if length(ResultString)>0 then
ResultString[result]:=Str[i];
inc(result);
end
else
begin
if length(ResultString)>0
then
begin
ResultString[result]:='%';
inc(result);
ResultString[result]:=_Hex[(ByteValue and $f0) shr 4];
inc(result);
ResultString[result]:=_Hex[ByteValue and $0f];;
inc(result);
end
else
inc(result,3);
end;
end;
end;
function FastStrToUrl(const Str: string;var ResultString:string): string;
const
UnreservedCharacters: set of Char = ['A'..'Z', 'a'..'z', '0'..'9', '-', '.', '_', '~'];
var
Resultlength:integer;
begin
ResultString:='';
Resultlength := FastStrToPercentTriplet(Str,ResultString,UnreservedCharacters);
setlength(ResultString,Resultlength);
FastStrToPercentTriplet(Str,ResultString,UnreservedCharacters);
end;
function CallLevNikolayevichTolstoy:string;
var
fhandle,filelength:integer;
begin
fhandle:=fileopen('warandpeace.txt',fmShareDenyNone);
filelength:=FileSeek(fhandle,0,2);
FileSeek(fhandle,0,0);
setlength(result,filelength);
FileRead(fhandle,result[1],filelength);
fileclose(fhandle)
end;
var
WarAndPeace,EncodedWarAndPeace:string;
Time:TDateTime;
begin
WarAndPeace:=CallLevNikolayevichTolstoy;
time:=now;
EncodedWarAndPeace:=StrToUrl(WarAndPeace);
writeln('StrToUrl ',((now-time)*10e4):2:3,'sec');
EncodedWarAndPeace:='';
time:=now;
EncodedWarAndPeace:=FastStrToUrl(WarAndPeace,EncodedWarAndPeace);
writeln('FastStrToUrl ',((now-time)*10e4):2:3,'sec');
end.Преобразование байта в хекс сделано навскидку, не прверял, если и неправильно - на скорость это не влияет. Рядом с ексешником должен лежать файл warandpeace.txt с чемто большим в UTF8, я для теста юзал войну и мир Толстого.
результат налицо))
E:\encodetest>encodetest.exe
StrToUrl 0.279sec
FastStrToUrl 0.020sec
Смысл в том чтоб не прибавлять по байтику, а сделать 2 прохода. в первом посчитать длину строки с результатом, во втором присваивать байтики в уже созданую строку
