platform.independent.streamformat.text.plain.pas

Переключить прокрутку окна
Загрузить этот исходный код

{
    platform.independent.streamformat.text.plain — модуль для чтения и записи
    простого текстового формата (text/plain, txt).

    Copyright © 2021, 2026 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или изменять
    её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
}

unit platform.independent.streamformat.text.plain;

    {$MODE DELPHI}

interface

    {%region} uses
        pascalx.lang,
        pascalx.io,
        pascalx.io.charset,
        pascalx.io.extension,
        platform.independent.streamformat,
        platform.independent.streamformat.text;
    {%endregion}

    {$TYPEINFO ON}
    {$CALLING REGISTER}

    const UNIT_NAME = 'platform.independent.streamformat.text.plain';

    {%region} type
        PlainCodec = class;

        PlainCodec = class(&Object,
            DataHolder, MutableDataHolder, InputAdapter, OutputAdapter, StreamAdapter,
            DataDecoder, DataEncoder, DataCodec, TextDecoder, TextEncoder, TextCodec,
            CharsetInputAdapter, CharsetOutputAdapter, CharsetStreamAdapter
        )
        protected
            fldEmpty: boolean;
            fldText: UnicodeString;
        public
            constructor create();
            procedure loadFromInputStream(stream: ByteReader); virtual; overload;
            procedure loadFromInputStream(stream: ByteReader; decoder: CharDecoder); virtual; overload;
            procedure saveToOutputStream(stream: ByteWriter); virtual; overload;
            procedure saveToOutputStream(stream: ByteWriter; encoder: CharEncoder); virtual; overload;
            procedure setText(const text: UnicodeString); virtual;
            procedure clear(); virtual;
            function isEmpty(): boolean; virtual;
            function getText(): UnicodeString; virtual;
        end;
    {%endregion}

implementation

    {$CALLING REGISTER}

    {%region  PlainCodec }
        constructor PlainCodec.create();
        begin
            inherited create();
            fldEmpty := true;
        end;

        procedure PlainCodec.loadFromInputStream(stream: ByteReader);
        begin
            loadFromInputStream(stream, nil);
        end;

        procedure PlainCodec.loadFromInputStream(stream: ByteReader; decoder: CharDecoder);
        var
            needFree: boolean;
            length: int;
            size: long;
            buffer: byte_Array1d;
            text: uchar_Array1d;
            sizeable: LimitedSizeExtension;
        begin
            if stream = nil then begin
                raise NullPointerException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer.argument'), [ CoAnsiString.create('stream') ]));
            end;
            sizeable := LimitedSizeExtension(stream.getExtension(LimitedSizeExtension));
            if sizeable = nil then begin
                raise InvalidStreamException.create(AnsiString.format(
                    AResource.readUnitResourceAsAnsiString(platform.independent.streamformat.UNIT_NAME, 'invalid-stream.input.unsupported-extension'), [
                        CoAnsiString.create(Lang.classFor(LimitedSizeExtension).getSimpleName())
                    ]
                ));
            end;
            size := sizeable.available();
            if (size < 0) or (size > CoInt.MAX_VALUE) then begin
                raise InvalidStreamException.create(AResource.readUnitResourceAsAnsiString(platform.independent.streamformat.UNIT_NAME, 'invalid-stream.input.size-too-large'));
            end;
            buffer := &Array.newByte1d(int(size));
            length := stream.read(buffer);
            if length <= 0 then begin
                fldEmpty := false;
                fldText := '';
                exit;
            end;
            needFree := false;
            if decoder = nil then begin
                needFree := true;
                decoder := Charset.getDefault().newDecoder();
            end;
            try
                text := decoder.decode(buffer, 0, length);
            finally
                if needFree then decoder.free();
            end;
            fldEmpty := false;
            fldText := UnicodeString.create(text);
        end;

        procedure PlainCodec.saveToOutputStream(stream: ByteWriter);
        begin
            saveToOutputStream(stream, nil);
        end;

        procedure PlainCodec.saveToOutputStream(stream: ByteWriter; encoder: CharEncoder);
        var
            needFree: boolean;
        begin
            if stream = nil then begin
                raise NullPointerException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer.argument'), [ CoAnsiString.create('stream') ]));
            end;
            if fldEmpty then begin
                raise EmptyAdapterException.create(AResource.readUnitResourceAsAnsiString(platform.independent.streamformat.UNIT_NAME, 'empty-adapter'));
            end;
            needFree := false;
            if encoder = nil then begin
                needFree := true;
                encoder := Charset.getDefault().newEncoder();
            end;
            try
                stream.write(encoder.encode(fldText));
            finally
                if needFree then encoder.free();
            end;
        end;

        procedure PlainCodec.setText(const text: UnicodeString);
        begin
            fldEmpty := false;
            fldText := text;
        end;

        procedure PlainCodec.clear();
        begin
            fldEmpty := true;
            fldText := '';
        end;

        function PlainCodec.isEmpty(): boolean;
        begin
            result := fldEmpty;
        end;

        function PlainCodec.getText(): UnicodeString;
        begin
            result := fldText;
        end;
    {%endregion}

end.