Subversion Repositories Kolibri OS

Rev

Rev 7693 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7696 akron1 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
7696 akron1 4
    Copyright (c) 2018-2019, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE FILES;
9
 
10
IMPORT UTILS, C := COLLECTIONS, CONSOLE;
11
 
12
 
13
TYPE
14
 
15
    FILE* = POINTER TO RECORD (C.ITEM)
16
 
17
        ptr: INTEGER;
18
 
19
        buffer: ARRAY 64*1024 OF BYTE;
20
        count:  INTEGER
21
 
22
    END;
23
 
24
VAR
25
 
26
    files: C.COLLECTION;
27
 
28
 
29
PROCEDURE copy (src: ARRAY OF BYTE; src_idx: INTEGER; VAR dst: ARRAY OF BYTE; dst_idx: INTEGER; bytes: INTEGER);
30
BEGIN
31
    WHILE bytes > 0 DO
32
        dst[dst_idx] := src[src_idx];
33
        INC(dst_idx);
34
        INC(src_idx);
35
        DEC(bytes)
36
    END
37
END copy;
38
 
39
 
40
PROCEDURE flush (file: FILE): INTEGER;
41
VAR
42
    res: INTEGER;
43
 
44
BEGIN
45
    IF file # NIL THEN
46
        res := UTILS.FileWrite(file.ptr, file.buffer, file.count);
47
        IF res < 0 THEN
48
            res := 0
49
        END
50
    ELSE
51
        res := 0
52
    END
53
 
54
    RETURN res
55
END flush;
56
 
57
 
58
PROCEDURE NewFile (): FILE;
59
VAR
60
    file:  FILE;
61
    citem: C.ITEM;
62
 
63
BEGIN
64
    citem := C.pop(files);
65
    IF citem = NIL THEN
66
        NEW(file)
67
    ELSE
68
        file := citem(FILE)
69
    END
70
 
71
    RETURN file
72
END NewFile;
73
 
74
 
75
PROCEDURE create* (name: ARRAY OF CHAR): FILE;
76
VAR
77
    file: FILE;
78
    ptr:  INTEGER;
79
 
80
BEGIN
81
    ptr := UTILS.FileCreate(name);
82
 
83
    IF ptr > 0 THEN
84
        file := NewFile();
85
        file.ptr := ptr;
86
        file.count := 0
87
    ELSE
88
        file := NIL
89
    END
90
 
91
    RETURN file
92
END create;
93
 
94
 
95
PROCEDURE open* (name: ARRAY OF CHAR): FILE;
96
VAR
97
    file: FILE;
98
    ptr:  INTEGER;
99
 
100
BEGIN
101
    ptr := UTILS.FileOpen(name);
102
 
103
    IF ptr > 0 THEN
104
        file := NewFile();
105
        file.ptr := ptr;
106
        file.count := -1
107
    ELSE
108
        file := NIL
109
    END
110
 
111
    RETURN file
112
END open;
113
 
114
 
115
PROCEDURE close* (VAR file: FILE);
116
VAR
117
    n: INTEGER;
118
 
119
BEGIN
120
    IF file # NIL THEN
121
 
122
        IF file.count > 0 THEN
123
            n := flush(file)
124
        END;
125
 
126
        file.count := -1;
127
 
128
        UTILS.FileClose(file.ptr);
129
        file.ptr := 0;
130
 
131
        C.push(files, file);
132
        file := NIL
133
    END
134
END close;
135
 
136
 
7696 akron1 137
PROCEDURE read* (file: FILE; VAR chunk: ARRAY OF CHAR; bytes: INTEGER): INTEGER;
7597 akron1 138
VAR
139
    res: INTEGER;
140
 
141
BEGIN
142
    IF file # NIL THEN
143
        res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0));
144
        IF res < 0 THEN
145
            res := 0
146
        END
147
    ELSE
148
        res := 0
149
    END
150
 
151
    RETURN res
152
END read;
153
 
154
 
155
PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER;
156
VAR
157
    free, n, k, res, idx: INTEGER;
158
 
159
BEGIN
160
    idx := 0;
161
    res := 0;
162
    IF (file # NIL) & (file.count >= 0) THEN
163
 
164
        free := LEN(file.buffer) - file.count;
165
        WHILE bytes > 0 DO
166
            n := MIN(free, bytes);
167
            copy(chunk, idx, file.buffer, file.count, n);
168
            INC(res, n);
169
            DEC(free, n);
170
            DEC(bytes, n);
171
            INC(idx, n);
172
            INC(file.count, n);
173
            IF free = 0 THEN
174
                k := flush(file);
175
                IF k # LEN(file.buffer) THEN
176
                    bytes := 0;
177
                    DEC(res, n)
178
                ELSE
179
                    file.count := 0;
180
                    free := LEN(file.buffer)
181
                END
182
            END
183
        END
184
 
185
    END
186
 
187
    RETURN res
188
END write;
189
 
190
 
191
PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN;
192
VAR
193
    res: BOOLEAN;
194
 
195
BEGIN
196
    res := TRUE;
197
    IF (file # NIL) & (file.count >= 0) THEN
198
        IF file.count = LEN(file.buffer) THEN
199
            IF flush(file) # LEN(file.buffer) THEN
200
                res := FALSE
201
            ELSE
202
                file.buffer[0] := byte;
203
                file.count := 1
204
            END
205
        ELSE
206
            file.buffer[file.count] := byte;
207
            INC(file.count)
208
        END
209
    ELSE
210
        res := FALSE
211
    END
212
 
213
    RETURN res
214
END WriteByte;
215
 
216
 
217
BEGIN
218
    files := C.create()
7696 akron1 219
END FILES.