pascalx.io.vfs.pas

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

{
    pascalx.io.vfs — модуль для создания взаимодействия с файловыми системами.

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

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

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

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

unit pascalx.io.vfs;

{$MODE DELPHI}

interface

uses
    pascalx.lang,
    pascalx.io;

{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}

{%region public }
const { значения для FileAttributes }
    ATTR_READONLY = int($0001);
    ATTR_HIDDEN = int($0002);
    ATTR_SYSTEM = int($0004);
    ATTR_DIRECTORY = int($0010);
    ATTR_ARCHIVE = int($0020);

type
    ReadOnlyVirtualFileSystem = interface;
    WriteableVirtualFileSystem = interface;
    FileAttributes = class;
    FileEnumeration = class;
    ClosedFileException = class;
    FileSystemNotAttachedException = class;
    VirtualFileSystemException = class;
    DirectoryOperationException = class;
    DirectoryCreationException = class;
    DirectoryDeletionException = class;
    FileOperationException = class;
    FileCreationException = class;
    FileDeletionException = class;
    TruncationNotSupportedException = class;
    PositioningNotSupportedException = class;
    MoveOperationException = class;
    NotFoundException = class;
    ObjectNotFoundException = class;
    DirectoryNotFoundException = class;
    FileNotFoundException = class;
    FileSystemSecurityException = class;

    ReadOnlyVirtualFileSystem = interface(_Interface) ['{A4028ED3-0A67-452D-BCE4-183D51910320}']
        function getObjectNameMaximumLength(): int;
        function findFirst(): FileEnumeration; overload;
        function findFirst(const objectName: UnicodeString): FileEnumeration; overload;
        function openFileForReading(const fileName: UnicodeString): InputStream;
        procedure readAttributes(const objectName: UnicodeString; objectAttr: FileAttributes);
    end;

    WriteableVirtualFileSystem = interface(ReadOnlyVirtualFileSystem) ['{A4028ED3-0A67-452D-BCE4-183D51910321}']
        function openFile(const fileName: UnicodeString): IOStream;
        function openFileForAppending(const fileName: UnicodeString): OutputStream;
        function createFile(const fileName: UnicodeString): OutputStream;
        procedure createDirectory(const directoryName: UnicodeString);
        procedure deleteFile(const fileName: UnicodeString);
        procedure deleteDirectory(const directoryName: UnicodeString);
        procedure move(const oldObjectName, newObjectName: UnicodeString);
        procedure writeAttributes(const objectName: UnicodeString; objectAttr: FileAttributes);
    end;

    FileAttributes = class(_Object)
    private
        attributes: int;
        creationTime: long;
        lastWriteTime: long;
        lastAccessTime: long;
    public
        constructor create(); overload;
        constructor create(source: FileAttributes); overload;
        constructor create(attributes: int; creationTime, lastWriteTime, lastAccessTime: long); overload;
        function isDirectory(): boolean;
        function isReadOnly(): boolean;
        function isArchive(): boolean;
        function isHidden(): boolean;
        function isSystem(): boolean;
        function getAttributes(): int;
        function getCreationTime(): long;
        function getLastWriteTime(): long;
        function getLastAccessTime(): long;
        procedure setAttributes(attributes: int); overload;
        procedure setAttributes(attributes: int; creationTime, lastWriteTime, lastAccessTime: long); virtual; overload;
    end;

    FileEnumeration = class(FileAttributes)
    private
        size: long;
        name: UnicodeString;
    protected
        procedure setAttributes(attributes: int; creationTime, lastWriteTime, lastAccessTime, size: long; const name: UnicodeString); virtual; overload;
    public
        constructor create(); overload;
        constructor create(attributes: int; creationTime, lastWriteTime, lastAccessTime, size: long; const name: UnicodeString); overload;
        function getSize(): long;
        function getName(): UnicodeString;
        function findNext(): boolean; virtual; abstract;
        procedure close(); virtual;
    end;

    ClosedFileException = class(IOException);

    FileSystemNotAttachedException = class(IOException);

    VirtualFileSystemException = class(IOException)
    public
        function getObjectName(): UnicodeString; virtual; abstract;
        procedure setObjectName(const objectName: UnicodeString); virtual; abstract;
    end;

    DirectoryOperationException = class(VirtualFileSystemException)
    private
        fDirectoryName: UnicodeString;
    public
        constructor create(const directoryName: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
        function getObjectName(): UnicodeString; override;
        procedure setObjectName(const objectName: UnicodeString); override;
    published
        property directoryName: UnicodeString read fDirectoryName write fDirectoryName;
    end;

    DirectoryCreationException = class(DirectoryOperationException);

    DirectoryDeletionException = class(DirectoryOperationException);

    FileOperationException = class(VirtualFileSystemException)
    private
        fFileName: UnicodeString;
    public
        constructor create(const fileName: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
        function getObjectName(): UnicodeString; override;
        procedure setObjectName(const objectName: UnicodeString); override;
    published
        property fileName: UnicodeString read fFileName write fFileName;
    end;

    FileCreationException = class(FileOperationException);

    FileDeletionException = class(FileOperationException);

    TruncationNotSupportedException = class(FileOperationException);

    PositioningNotSupportedException = class(FileOperationException);

    MoveOperationException = class(VirtualFileSystemException)
    private
        fOldObjectName: UnicodeString;
        fNewObjectName: UnicodeString;
    public
        constructor create(const oldObjectName, newObjectName: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
        function getObjectName(): UnicodeString; override;
        procedure setObjectName(const objectName: UnicodeString); override;
    published
        property oldObjectName: UnicodeString read fOldObjectName write fOldObjectName;
        property newObjectName: UnicodeString read fNewObjectName write fNewObjectName;
    end;

    NotFoundException = class(VirtualFileSystemException)
    protected
        fName: UnicodeString;
    public
        constructor create(const name: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function getObjectName(): UnicodeString; override;
        procedure setObjectName(const objectName: UnicodeString); override;
    published
        property name: UnicodeString read fName write fName;
    end;

    ObjectNotFoundException = class(NotFoundException)
    public
        constructor create(const objectName: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
    end;

    DirectoryNotFoundException = class(NotFoundException)
    public
        constructor create(const directoryName: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
    end;

    FileNotFoundException = class(NotFoundException)
    public
        constructor create(const fileName: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
    end;

    FileSystemSecurityException = class(SecurityException)
    private
        fName: UnicodeString;
    public
        constructor create(const name: UnicodeString; const message: AnsiString = ''; helpContext: int = 0);
        function toString(): AnsiString; override;
    published
        property name: UnicodeString read fName write fName;
    end;

resourcestring
    msgClosedFile = 'Файл закрыт';
    msgFileSystemNotAttached = 'Файловая система недоступна';
    msgDirectoryCreationError = 'Ошибка создания папки';
    msgDirectoryDeletionError = 'Ошибка удаления папки';
    msgFileCreationError = 'Ошибка открытия файла';
    msgFileDeletionError = 'Ошибка удаления файла';
    msgMoveError = 'Ошибка перемещения объекта';
    msgObjectNotFound = 'Объект не найден';
    msgDirectoryNotFound = 'Папка не найдена';
    msgFileNotFound = 'Файл не найден';
    msgFileReadError = 'Ошибка чтения файла';
    msgFileWriteError = 'Ошибка записи файла';
    strObject = 'Объект';
    strDirectory = 'Папка';
    strFile = 'Файл';
    strOldName = 'Старое имя';
    strNewName = 'Новое имя';
{%endregion}

implementation

{%region FileAttributes }
    constructor FileAttributes.create();
    begin
        inherited create();
    end;

    constructor FileAttributes.create(source: FileAttributes);
    begin
        inherited create();
        if source = nil then exit;
        self.attributes := source.attributes;
        self.creationTime := source.creationTime;
        self.lastWriteTime := source.lastWriteTime;
        self.lastAccessTime := source.lastAccessTime;
    end;

    constructor FileAttributes.create(attributes: int; creationTime, lastWriteTime, lastAccessTime: long);
    begin
        inherited create();
        self.attributes := attributes;
        self.creationTime := creationTime;
        self.lastWriteTime := lastWriteTime;
        self.lastAccessTime := lastAccessTime;
    end;

    function FileAttributes.isDirectory(): boolean;
    begin
        result := (attributes and ATTR_DIRECTORY) <> 0;
    end;

    function FileAttributes.isReadOnly(): boolean;
    begin
        result := (attributes and ATTR_READONLY) <> 0;
    end;

    function FileAttributes.isArchive(): boolean;
    begin
        result := (attributes and ATTR_ARCHIVE) <> 0;
    end;

    function FileAttributes.isHidden(): boolean;
    begin
        result := (attributes and ATTR_HIDDEN) <> 0;
    end;

    function FileAttributes.isSystem(): boolean;
    begin
        result := (attributes and ATTR_SYSTEM) <> 0;
    end;

    function FileAttributes.getAttributes(): int;
    begin
        result := attributes;
    end;

    function FileAttributes.getCreationTime(): long;
    begin
        result := creationTime;
    end;

    function FileAttributes.getLastWriteTime(): long;
    begin
        result := lastWriteTime;
    end;

    function FileAttributes.getLastAccessTime(): long;
    begin
        result := lastAccessTime;
    end;

    procedure FileAttributes.setAttributes(attributes: int);
    begin
        setAttributes(attributes, creationTime, lastWriteTime, lastAccessTime);
    end;

    procedure FileAttributes.setAttributes(attributes: int; creationTime, lastWriteTime, lastAccessTime: long);
    begin
        self.attributes := attributes;
        self.creationTime := creationTime;
        self.lastWriteTime := lastWriteTime;
        self.lastAccessTime := lastAccessTime;
    end;
{%endregion}

{%region FileEnumeration }
    procedure FileEnumeration.setAttributes(attributes: int; creationTime, lastWriteTime, lastAccessTime, size: long; const name: UnicodeString);
    begin
        inherited setAttributes(attributes, creationTime, lastWriteTime, lastAccessTime);
        self.size := size;
        self.name := name;
    end;

    constructor FileEnumeration.create();
    begin
        inherited create();
    end;

    constructor FileEnumeration.create(attributes: int; creationTime, lastWriteTime, lastAccessTime, size: long; const name: UnicodeString);
    begin
        inherited create(attributes, creationTime, lastWriteTime, lastAccessTime);
        self.size := size;
        self.name := name;
    end;

    function FileEnumeration.getSize(): long;
    begin
        result := size;
    end;

    function FileEnumeration.getName(): UnicodeString;
    begin
        result := name;
    end;

    procedure FileEnumeration.close();
    begin
        free();
    end;
{%endregion}

{%region DirectoryOperationException }
    constructor DirectoryOperationException.create(const directoryName: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(message, helpContext);
        self.fDirectoryName := directoryName;
    end;

    function DirectoryOperationException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strDirectory + ': ' + stringToUTF8(fDirectoryName);
    end;

    function DirectoryOperationException.getObjectName(): UnicodeString;
    begin
        result := fDirectoryName;
    end;

    procedure DirectoryOperationException.setObjectName(const objectName: UnicodeString);
    begin
        self.fDirectoryName := objectName;
    end;
{%endregion}

{%region FileOperationException }
    constructor FileOperationException.create(const fileName: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(message, helpContext);
        self.fFileName := fileName;
    end;

    function FileOperationException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strFile + ': ' + stringToUTF8(fFileName);
    end;

    function FileOperationException.getObjectName(): UnicodeString;
    begin
        result := fFileName;
    end;

    procedure FileOperationException.setObjectName(const objectName: UnicodeString);
    begin
        self.fFileName := objectName;
    end;
{%endregion}

{%region MoveOperationException }
    constructor MoveOperationException.create(const oldObjectName, newObjectName: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(message, helpContext);
        self.fOldObjectName := oldObjectName;
        self.fNewObjectName := newObjectName;
    end;

    function MoveOperationException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strOldName + ': ' + stringToUTF8(fOldObjectName) + LINE_ENDING + strNewName + ': ' + stringToUTF8(fNewObjectName);
    end;

    function MoveOperationException.getObjectName(): UnicodeString;
    begin
        result := fOldObjectName;
    end;

    procedure MoveOperationException.setObjectName(const objectName: UnicodeString);
    begin
        self.fOldObjectName := objectName;
    end;
{%endregion}

{%region NotFoundException }
    constructor NotFoundException.create(const name: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(message, helpContext);
        self.fName := name;
    end;

    function NotFoundException.getObjectName(): UnicodeString;
    begin
        result := fName;
    end;

    procedure NotFoundException.setObjectName(const objectName: UnicodeString);
    begin
        self.fName := objectName;
    end;
{%endregion}

{%region ObjectNotFoundException }
    constructor ObjectNotFoundException.create(const objectName: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(objectName, message, helpContext);
    end;

    function ObjectNotFoundException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strObject + ': ' + stringToUTF8(fName);
    end;
{%endregion}

{%region DirectoryNotFoundException }
    constructor DirectoryNotFoundException.create(const directoryName: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(directoryName, message, helpContext);
    end;

    function DirectoryNotFoundException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strDirectory + ': ' + stringToUTF8(fName);
    end;
{%endregion}

{%region FileNotFoundException }
    constructor FileNotFoundException.create(const fileName: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(fileName, message, helpContext);
    end;

    function FileNotFoundException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strFile + ': ' + stringToUTF8(fName);
    end;
{%endregion}

{%region FileSystemSecurityException }
    constructor FileSystemSecurityException.create(const name: UnicodeString; const message: AnsiString; helpContext: int);
    begin
        inherited create(message, helpContext);
        self.fName := name;
    end;

    function FileSystemSecurityException.toString(): AnsiString;
    begin
        result := inherited toString() + LINE_ENDING + strObject + ': ' + stringToUTF8(fName);
    end;
{%endregion}

initialization
    classInfoAdd([
        typeInfo(ReadOnlyVirtualFileSystem),
        typeInfo(WriteableVirtualFileSystem)
    ]);

end.