{
TextFiles содержит методы для работы с текстовыми файлами: сохранение, загрузка,
разбиение на массив строк, объединение массива строк.
Copyright © 2016, 2019, 2022–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit TextFiles;
{$MODE DELPHI}
interface
uses
Lang,
IOStreams;
{%region routine }
procedure saveStringsToStream(stream: Output; const strings: AnsiString_Array1d; count: int);
function loadStringsFromStream(stream: Input): AnsiString_Array1d;
function splitTextToStrings(const text: AnsiString): AnsiString_Array1d;
function makeTextStringOf(const strings: AnsiString_Array1d; count: int): AnsiString;
{%endregion}
implementation
{%region routine }
procedure saveStringsToStream(stream: Output; const strings: AnsiString_Array1d; count: int);
begin
stream.write(stringToByteArray(makeTextStringOf(strings, count)));
end;
function loadStringsFromStream(stream: Input): AnsiString_Array1d;
var
b: byte_Array1d;
begin
b := byte_Array1d_create(int(stream.available()));
stream.read(b);
result := splitTextToStrings(extractString(b, 0, length(b)));
end;
function splitTextToStrings(const text: AnsiString): AnsiString_Array1d;
const
CR = #13;
LF = #10;
var
i: int;
j: int;
len: int;
count: int;
strings: AnsiString_Array1d;
begin
len := length(text);
if len = 0 then begin
result := nil;
exit;
end;
count := 0;
strings := String_Array1d_create(1);
if (len >= 3) and (text[1] = #$ef) and (text[2] = #$bb) and (text[3] = #$bf) then begin
if len = 3 then begin
result := nil;
exit;
end;
i := 4;
end else begin
i := 1;
end;
j := i;
repeat
while (j <= len) and (not (text[j] in [CR, LF])) do begin
inc(j);
end;
if count = length(strings) then begin
result := String_Array1d_create((count shl 1) + 1);
arraycopy(strings, 0, result, 0, count);
strings := result;
result := nil;
end;
strings[count] := copy(text, i, j - i);
inc(count);
if j > len then begin
break;
end;
if (j < len) and (text[j] = CR) and (text[j + 1] = LF) then begin
inc(j, 2);
i := j;
continue;
end;
inc(j);
i := j;
until false;
if count < length(strings) then begin
result := String_Array1d_create(count);
arraycopy(strings, 0, result, 0, count);
exit;
end;
result := strings;
end;
function makeTextStringOf(const strings: AnsiString_Array1d; count: int): AnsiString;
var
i: int;
j: int;
len: int;
rlen: int;
str: AnsiString;
begin
len := min(length(strings), max(0, count)) - 1;
if len < 0 then begin
result := '';
exit;
end;
rlen := 0;
for i := 0 to len do begin
inc(rlen, length(strings[i]));
end;
inc(rlen, length(LINE_ENDING) * len);
result := String_create(rlen);
j := 1;
for i := 0 to len do begin
str := strings[i];
rlen := length(str);
move(str[1], result[j], rlen);
inc(j, rlen);
if i < len then begin
str := LINE_ENDING;
rlen := length(str);
move(str[1], result[j], rlen);
inc(j, rlen);
end;
end;
end;
{%endregion}
end.