1+ { MIT License
2+
3+ Copyright (c) 2022 Viacheslav Komenda
4+
5+ Permission is hereby granted, free of charge, to any person obtaining a copy
6+ of this software and associated documentation files (the "Software"), to deal
7+ in the Software without restriction, including without limitation the rights
8+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ copies of the Software, and to permit persons to whom the Software is
10+ furnished to do so, subject to the following conditions:
11+
12+ The above copyright notice and this permission notice shall be included in all
13+ copies or substantial portions of the Software.
14+
15+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+ SOFTWARE.
22+ }
23+ { $A+,I-,S-,R-,D-,L-,Q-,F-,G-,O-,B-}
24+ UNIT DBU;
25+
26+ INTERFACE
27+
28+ USES System2;
29+
30+ TYPE
31+ PDBUFile = ^DBUFile;
32+ DBUFile=RECORD
33+ f : PBFILE;
34+ idx : PBFIle;
35+ first_free : WORD;
36+ END ;
37+
38+ PROCEDURE DBU_Reset (VAR d : DBUFile; VAR f, idx : BFile);
39+ PROCEDURE DBU_ReWrite (VAR d : DBUFile; VAR f, idx : BFile);
40+ FUNCTION DBU_IsOpen (VAR d : DBUFile) : BOOLEAN;
41+ FUNCTION DBU_Create (VAR d : DBUFile) : WORD;
42+ PROCEDURE DBU_Read (VAR d : DBUFile; h : WORD; ofs : DWORD; VAR mem; size : WORD);
43+ PROCEDURE DBU_Write (VAR d : DBUFile; h : WORD; ofs : DWORD; VAR mem; size : WORD);
44+ PROCEDURE DBU_Free (VAR d : DBUFile; h : WORD);
45+ PROCEDURE DBU_Close (VAR d : DBUFile);
46+
47+ IMPLEMENTATION
48+
49+ CONST
50+ BLOCK_SIZE_KB = 16 ;
51+ BLOCK_SIZE = BLOCK_SIZE_KB * 1024 ;
52+
53+ PROCEDURE L_Append (VAR d : DBUFile);
54+ VAR i : INTEGER;
55+ n : ARRAY [1 ..1024 ] OF CHAR;
56+ BEGIN
57+ FillChar(n, SizeOf(n), #0 );
58+ FOR i := 1 TO BLOCK_SIZE_KB DO BlockWrite(d.f^, n, SizeOf(n));
59+ END ;
60+
61+ FUNCTION L_Size (VAR d : DBUFile) : WORD;
62+ VAR r1 : WORD;
63+ r2 : WORD;
64+ BEGIN
65+ r1 := FileSize(d.f^) SHR 14 ;
66+ r2 := FileSize(d.idx^) SHR 2 ;
67+ IF r1 > r2 THEN L_Size := r2 ELSE L_Size := r1;
68+ END ;
69+
70+ PROCEDURE L_Seek (VAR d : DBUFile; page : WORD);
71+ VAR npage : WORD;
72+ sz : WORD;
73+ BEGIN
74+ sz := L_Size(d);
75+ IF (sz < page) THEN BEGIN
76+ Seek(d.f^, sz SHL 14 );
77+ Seek(d.idx^, sz SHL 1 );
78+ WHILE sz <= page DO BEGIN
79+ L_Append(d);
80+ WriteWord(d.idx^, d.first_free);
81+ d.first_free := sz;
82+ sz := L_Size(d);
83+ END ;
84+ END ;
85+ Seek(d.f^, page SHL 14 );
86+ Seek(d.idx^, page SHL 1 );
87+ END ;
88+
89+ PROCEDURE DBU_Reset (VAR d : DBUFile; VAR f, idx : BFile);
90+ BEGIN
91+ FillChar(d, SizeOf(DBUFile), #0 );
92+ d.f := @f;
93+ d.idx := @idx;
94+ IF (NOT EOF(d.f^)) AND (NOT EOF(d.idx^)) THEN BEGIN
95+ Seek(d.idx^, 0 );
96+ d.first_free := ReadWord(d.idx^);
97+ END ELSE DBU_ReWrite(d, f, idx);
98+ END ;
99+
100+ FUNCTION DBU_IsOpen (VAR d : DBUFile) : BOOLEAN;
101+ BEGIN
102+ DBU_IsOpen := IsOpen(d.f^) AND IsOpen(d.idx^);
103+ END ;
104+
105+ PROCEDURE DBU_ReWrite (VAR d : DBUFile; VAR f, idx : BFile);
106+ BEGIN
107+ FillChar(d, SizeOf(DBUFile), #0 );
108+ d.f := @f;
109+ d.idx := @idx;
110+
111+ Seek(d.f^, 0 );
112+ L_Append(d);
113+ Truncate(d.f^);
114+
115+ Seek(d.idx^, 0 );
116+ WriteWord(d.idx^, 0 );
117+ Truncate(d.idx^);
118+ END ;
119+
120+ PROCEDURE DBU_Close (VAR d : DBUFile);
121+ BEGIN
122+ Seek(d.idx^, 0 );
123+ WriteWord(d.idx^, d.first_free);
124+ Close(d.f^);
125+ Close(d.idx^);
126+ END ;
127+
128+ FUNCTION DBU_Create (VAR d : DBUFile) : WORD;
129+ VAR r : WORD;
130+ BEGIN
131+ IF d.first_free = 0 THEN L_Seek(d, L_Size(d) + 1 );
132+ r := d.first_free;
133+ L_Seek(d, r);
134+ WriteWord(d.idx^, 0 );
135+ Seek(d.idx^, FilePos(d.idx^) - SizeOf(WORD));
136+ DBU_Create := r;
137+ END ;
138+
139+
140+ PROCEDURE DBU_Free (VAR d : DBUFile; h : WORD);
141+ VAR next : WORD;
142+ BEGIN
143+ WHILE h <> 0 DO BEGIN
144+ next := GetWord(d.idx^, h SHL 1 );
145+ SetWord(d.idx^, h SHL 1 , d.first_free);
146+ d.first_free := h;
147+ h := next;
148+ END ;
149+ END ;
150+
151+ FUNCTION next_page (VAR d : DBUFile; cpage : WORD) : WORD;
152+ VAR npage : WORD;
153+ BEGIN
154+ Seek(d.idx^, cpage SHL 2 );
155+ npage := ReadWord(d.idx^);
156+ IF npage = 0 THEN BEGIN
157+ IF d.first_free = 0 THEN L_Seek(d, (L_Size(d) + 1 ));
158+ npage := d.first_free;
159+ Seek(d.idx^, d.first_free SHL 1 );
160+ d.first_free := ReadWord(d.idx^);
161+ Seek(d.idx^, d.first_free SHL 1 );
162+ WriteWord(d.idx^, 0 );
163+ Seek(d.idx^, cpage SHL 1 );
164+ WriteWord(d.idx^, npage);
165+ END ;
166+ next_page := npage;
167+ END ;
168+
169+ PROCEDURE DBU_Write (VAR d : DBUFile; h : WORD; ofs : DWORD; VAR mem; size : WORD);
170+ VAR page : WORD;
171+ pofs : WORD;
172+ p : PCHAR;
173+ s : WORD;
174+ BEGIN
175+ page := ofs SHR 14 ;
176+ pofs := ofs AND $3FFF;
177+ p := @mem;
178+ WHILE page <> 0 DO BEGIN
179+ h := next_page(d, h);
180+ Dec(page);
181+ END ;
182+ WHILE size <> 0 DO BEGIN
183+ L_Seek(d, h);
184+ s := size;
185+ IF s > (BLOCK_SIZE - pofs) THEN s := BLOCK_SIZE - pofs;
186+ IF pofs <> 0 THEN Seek(d.f^, FilePos(d.f^) + pofs);
187+ BlockWrite(d.f^, p[0 ], s);
188+ pofs := 0 ;
189+ Dec(size, s);
190+ Inc(p, s);
191+ h := next_page(d, h);
192+ END ;
193+ END ;
194+
195+ PROCEDURE DBU_Read (VAR d : DBUFile; h : WORD; ofs : DWORD; VAR mem; size : WORD);
196+ VAR page : WORD;
197+ pofs : WORD;
198+ p : PCHAR;
199+ s : WORD;
200+ r : WORD;
201+ BEGIN
202+ page := ofs SHR 14 ;
203+ pofs := ofs AND $3FFF;
204+ p := @mem;
205+ WHILE page <> 0 DO BEGIN
206+ h := next_page(d, h);
207+ Dec(page);
208+ END ;
209+ WHILE size <> 0 DO BEGIN
210+ L_Seek(d, h);
211+ s := size;
212+ IF s > (BLOCK_SIZE - pofs) THEN s := BLOCK_SIZE - pofs;
213+ IF pofs <> 0 THEN Seek(d.f^, FilePos(d.f^) + pofs);
214+ BlockRead(d.f^, p[0 ], s);
215+ pofs := 0 ;
216+ Dec(size, s);
217+ Inc(p, s);
218+ h := next_page(d, h);
219+ END ;
220+ END ;
221+
222+ END .
0 commit comments