RawByteString призвана сохранить кодировку строк при написании "универсальных" функций, у которых кодировка на выходе такая же, как на входе, а работают с данными как с сфрыми байтами.
Вот и я тоже, написал свои Explode, Implode и милую
- Код: Выделить всё
Function StrReplace (S, zamenjaemoe, zamenjajushee: RawByteString): RawByteString; overload;
var a: array of RawByteString;
begin
a:= Explode(zamenjaemoe, s);
Result:= Implode(zamenjajushee, a);
end;
-- и получил на выходе анус. Всё упало.
Вопрос на миллион баксов: какая кодировка у пустой строки?..
Прааавильно, cp1251 Хоть одна пустая строка затёсывается в работу с utf8 как с RawByteString - и всё исходит на говно.
Пришлось допатчить:
- Код: Выделить всё
function Implode(separator: RawByteString; a: RawByteStringArray): RawByteString; overload;
var i, sl, al, l: integer;
begin
//a friendly reminder: strings in Pascal index from 1, not 0
Result:= '';
sl:= Length(separator);
l:= 0;
for i:=0 to High(a) do l+= Length(a[i]);
l+= sl * (Length(a) - 1);
SetLength(Result, l);
l:= 0;
for i:=0 to High(a) do begin
if i > 0 then begin
if sl > 0 then MOVE(separator[1], Result[l + 1], sl * SizeOf(separator[1])); //copying as a binary blob
l+= sl;
end;
al:= Length(a[i]);
if al > 0 then MOVE(a[i][1], Result[l + 1], al * Sizeof(separator[1]));
l+= al;
end;
{$if FPC_FULLVERSION>30000}
//assigns string's character set in FPC 3
SetCodePage(Result, StringCodePage(separator), false);
for i:= 0 to High(a) do
// There is a HUGE pitfall in that an empty string's character set
// is always system default
// So we have to scan for an non-empty string
if (a[i] <> '') then begin
SetCodePage(Result, StringCodePage(a[i]), false);
break;
end;
{$endif}
end;
Фрагмент, использующий это:
(TFileNameString = Utf8String в текущей инкарнации на всех платформах)
- Код: Выделить всё
function UnmangleFileName (a: TFileNameString): TFileNameString;
begin
Result:= StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(StrReplace(
StrReplace(StrReplace(StrReplace(
a, '{$PLATFORM}', SystemSuffix),
'{$HOMEDIR}', Mother^.State.HomePath),
'{$INSDIR}', Mother^.State.InstallPath),
'{$USERNAME}', Mother^.State.UserName),
'{$APPDATA}', Mother^.State.AppDataDir),
'{$MODULE}', Mother^.State.ModuleBaseDir),
'{$CACHE}', Mother^.State.CacheDir),
'{$SAVES}', Mother^.State.SessionDir),
'{$EMPTY}', TFileNameString(''));
Result:= OptiPath(ExtractFilePath(Result)) + ExtractFilename(Result);
end;