Subversion Repositories Kolibri OS

Rev

Rev 7696 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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