@@ -22,201 +22,246 @@ SOFTWARE.
2222}
2323{ $A+,I-,S-,R-,D-,L-,Q-,F-,G-,O-,B-}
2424UNIT DBU;
25-
25+ { =========================================================================
26+ This is unit implements dbu files (like a .dbt) - container for memo fields.
27+ ========================================================================= }
2628INTERFACE
2729
2830USES System2;
2931
32+ CONST
33+ DBU_BLOCK_SIZE = 512 ;
34+
3035TYPE
36+ DBU_REC = RECORD
37+ next : LONGINT;
38+ size : WORD;
39+ END ;
40+
3141PDBUFile = ^DBUFile;
3242DBUFile=RECORD
33- f : PBFILE;
34- idx : PBFIle;
35- first_free : WORD;
43+ f : BFILE;
44+ header : DBU_REC;
45+ crec : DBU_REC;
46+ crecno : LONGINT;
47+ needupdate : BOOLEAN;
48+ data : PCHAR;
3649END ;
3750
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);
51+ PROCEDURE dbu_reset (VAR f : DBUFile; fname : STRING; blk_size : WORD);
52+ PROCEDURE dbu_rewrite (VAR f : DBUFile; fname : STRING; blk_size : WORD);
53+ PROCEDURE dbu_rewrite_memfile (VAR f : DBUFile; blk_size : WORD);
4654
47- IMPLEMENTATION
55+ FUNCTION dbu_isopen ( VAR f : DBUFile) : BOOLEAN;
4856
49- CONST
50- BLOCK_SIZE_KB = 16 ;
51- BLOCK_SIZE = BLOCK_SIZE_KB * 1024 ;
57+ PROCEDURE dbu_get ( VAR f : DBUFile; rec : LONGINT; VAR b; size : WORD);
58+ FUNCTION dbu_put ( VAR f : DBUFile; VAR b; size : WORD) : LONGINT ;
59+ FUNCTION dbu_size ( VAR f : DBUFile; rec : LONGINT) : LONGINT ;
5260
53- PROCEDURE L_Append (VAR d : DBUFile);
54- VAR i : INTEGER;
55- n : ARRAY [1 ..1024 ] OF CHAR;
61+ PROCEDURE dbu_free (VAR f : DBUFile; rec : LONGINT);
62+
63+ PROCEDURE dbu_close (VAR f : DBUFile);
64+
65+ IMPLEMENTATION
66+
67+ PROCEDURE dbu_load (VAR f : DBUFile);
5668BEGIN
57- FillChar(n, SizeOf(n), #0 );
58- FOR i := 1 TO BLOCK_SIZE_KB DO BlockWrite(d.f^, n, SizeOf(n));
69+ Seek(f.f, f.crecno * f.header.size);
70+ BlockRead(f.f, f.crec, SizeOf(DBU_REC));
71+ BlockRead(f.f, f.data[0 ], f.header.size - SizeOf(DBU_REC));
72+ f.needupdate := FALSE;
5973END ;
6074
61- FUNCTION L_Size (VAR d : DBUFile) : WORD;
62- VAR r1 : WORD;
63- r2 : WORD;
75+ PROCEDURE dbu_update (VAR f : DBUFile);
6476BEGIN
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;
77+ IF (f.needupdate) AND (f.crecno <> 0 ) THEN BEGIN
78+ Seek(f.f, f.crecno * f.header.size);
79+ BlockWrite(f.f, f.crec, SizeOf(DBU_REC));
80+ BlockWrite(f.f, f.data[0 ], f.header.size - SizeOf(DBU_REC));
81+ END ;
82+ f.needupdate := FALSE;
6883END ;
6984
70- PROCEDURE L_Seek (VAR d : DBUFile; page : WORD );
71- VAR npage : WORD;
72- sz : WORD ;
85+ PROCEDURE dbu_go (VAR f : DBUFile; recno : LONGINT );
86+ VAR
87+ nofs : LONGINT ;
7388BEGIN
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 ;
89+ IF recno = f.crecno THEN EXIT ;
90+ dbu_update(f);
91+ nofs := recno * f.header.size ;
92+ FillChar(f.data[ 0 ], f.header.size - SizeOf(DBUFile), # 0 );
93+ f.crec.next := 0 ;
94+ f.crec.size := 0 ;
95+ WHILE nofs > FileSize(f.f) DO BEGIN
96+ Seek(f.f, (FileSize(f.f) DIV f.header.size) * f.header.size) ;
97+ BlockWrite(f.f, f.crec, SizeOf(DBU_REC) );
98+ BlockWrite(f.f, f.data[ 0 ], f.header.size - SizeOf(DBU_REC)) ;
8499 END ;
85- Seek(d.f^, page SHL 14 ) ;
86- Seek(d.idx^, page SHL 1 );
100+ f.crecno := recno ;
101+ dbu_load(f );
87102END ;
88103
89- PROCEDURE DBU_Reset (VAR d : DBUFile; VAR f, idx : BFile );
104+ PROCEDURE dbu_reset (VAR f : DBUFile; fname : STRING; blk_size : WORD );
90105BEGIN
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);
106+ FillChar(f, SizeOf(DBUFile), #0 );
107+ Assign(f.f, fname);
108+ Reset(f.f);
109+ IF NOT IsOpen(f.f) THEN dbu_rewrite(f, fname, blk_size)
110+ ELSE IF SizeOf(DBU_REC) <> BlockRead(f.f, f.header, SizeOf(DBU_REC)) THEN BEGIN
111+ Close(f.f);
112+ dbu_rewrite(f, fname, blk_size);
113+ END ELSE BEGIN
114+ GetMem(f.data, blk_size - SizeOf(DBUFile));
115+ FillChar(f.data[0 ], f.header.size - SizeOf(DBUFile), #0 );
116+ BlockWrite(f.f, f.data[0 ], f.header.size - SizeOf(DBU_REC));
117+ END ;
98118END ;
99119
100- FUNCTION DBU_IsOpen (VAR d : DBUFile) : BOOLEAN ;
120+ PROCEDURE dbu_rewrite (VAR f : DBUFile; fname : STRING; blk_size : WORD) ;
101121BEGIN
102- DBU_IsOpen := IsOpen(d.f^) AND IsOpen(d.idx^);
122+ FillChar(f, SizeOf(DBUFile), #0 );
123+ Assign(f.f, fname);
124+ ReWrite(f.f);
125+ IF IsOpen(f.f) THEN BEGIN
126+ f.header.next := 0 ;
127+ f.header.size := blk_size;
128+ GetMem(f.data, f.header.size - SizeOf(DBUFile));
129+ FillChar(f.data[0 ], f.header.size - SizeOf(DBUFile), #0 );
130+ Seek(f.f, 0 );
131+ BlockWrite(f.f, f.header, SizeOf(DBU_REC));
132+ BlockWrite(f.f, f.data[0 ], f.header.size - SizeOf(DBU_REC));
133+ END ;
103134END ;
104135
105- PROCEDURE DBU_ReWrite (VAR d : DBUFile; VAR f, idx : BFile );
136+ PROCEDURE dbu_rewrite_memfile (VAR f : DBUFile; blk_size : WORD );
106137BEGIN
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^) ;
138+ FillChar(f , SizeOf(DBUFile), #0 );
139+ ReWriteMemFile (f.f) ;
140+ IF IsOpen(f.f) THEN BEGIN
141+ f.header.next := 0 ;
142+ f.header.size := blk_size ;
143+ GetMem(f.data, f.header.size - SizeOf(DBUFile) );
144+ FillChar(f.data[ 0 ], f.header.size - SizeOf(DBUFile), # 0 );
145+ Seek(f.f, 0 );
146+ BlockWrite(f.f, f.header, SizeOf(DBU_REC) );
147+ BlockWrite(f.f, f.data[ 0 ], f.header.size - SizeOf(DBU_REC) );
148+ END ;
118149END ;
119150
120- PROCEDURE DBU_Close (VAR d : DBUFile);
151+ FUNCTION dbu_isopen (VAR f : DBUFile) : BOOLEAN ;
121152BEGIN
122- Seek(d.idx^, 0 );
123- WriteWord(d.idx^, d.first_free);
124- Close(d.f^);
125- Close(d.idx^);
153+ dbu_isopen := IsOpen(f.f);
126154END ;
127155
128- FUNCTION DBU_Create (VAR d : DBUFile) : WORD;
129- VAR r : WORD;
156+ PROCEDURE dbu_close (VAR f : DBUFile);
130157BEGIN
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;
158+ IF NOT IsOpen(f.f) THEN EXIT;
159+ dbu_update(f);
160+ Seek(f.f, 0 );
161+ FillChar(f.data[0 ], f.header.size - SizeOf(DBUFile), #0 );
162+ BlockWrite(f.f, f.header, SizeOf(DBU_REC));
163+ BlockWrite(f.f, f.data[0 ], f.header.size - SizeOf(DBU_REC));
164+ Close(f.f);
165+ IF f.data <> NIL THEN FreeMem(f.data, f.header.size - SizeOf(DBUFile));
166+ FillChar(f, SizeOf(DBUFile), #0 );
137167END ;
138168
139-
140- PROCEDURE DBU_Free (VAR d : DBUFile; h : WORD);
141- VAR next : WORD;
169+ PROCEDURE dbu_free (VAR f : DBUFile; rec : LONGINT);
170+ VAR n : LONGINT;
142171BEGIN
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;
172+ IF NOT IsOpen(f.f) THEN EXIT;
173+ WHILE rec <> 0 DO BEGIN
174+ dbu_go(f, rec);
175+ n := f.crec.next;
176+ f.crec.next := f.header.next;
177+ f.crec.size := 0 ;
178+ f.needupdate := TRUE;
179+ f.header.next := rec;
180+ rec := n;
148181 END ;
149182END ;
150183
151- FUNCTION next_page (VAR d : DBUFile; cpage : WORD ) : WORD ;
152- VAR npage : WORD ;
184+ FUNCTION dbu_alloc (VAR f : DBUFile) : LONGINT ;
185+ VAR r : LONGINT ;
153186BEGIN
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);
187+ IF f.header.next <> 0 THEN BEGIN
188+ r := f.header.next;
189+ dbu_go(f, r);
190+ f.header.next := f.crec.next;
191+ END ELSE BEGIN
192+ r := FileSize(f.f) DIV f.header.size;
165193 END ;
166- next_page := npage;
194+ dbu_go(f, r);
195+ f.crec.next := 0 ;
196+ f.crec.size := 0 ;
197+ f.needupdate := TRUE;
198+ dbu_alloc := r;
167199END ;
168200
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;
201+ FUNCTION dbu_size (VAR f : DBUFile; rec : LONGINT) : LONGINT;
202+ VAR r : LONGINT;
174203BEGIN
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);
204+ r := 0 ;
205+ IF IsOpen(f.f) THEN BEGIN
206+ WHILE rec <> 0 DO BEGIN
207+ dbu_go(f, rec);
208+ Inc(r, f.crec.size);
209+ rec := f.crec.next;
210+ END ;
192211 END ;
212+ dbu_size := r;
193213END ;
194214
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;
215+ PROCEDURE dbu_get (VAR f : DBUFile; rec : LONGINT; VAR b; size : WORD);
216+ VAR p : PCHAR;
217+ g : WORD;
201218BEGIN
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);
219+ IF NOT IsOpen(f.f) THEN EXIT;
220+ p := @b;
221+ WHILE (size <> 0 ) AND (rec <> 0 ) DO BEGIN
222+ dbu_go(f, rec);
223+ g := f.crec.size;
224+ IF g > size THEN g := size;
225+ Move(f.data[0 ], p[0 ], g);
226+ Dec(size, g);
227+ Inc(p, g);
228+ rec := f.crec.next;
208229 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);
230+ END ;
231+
232+ FUNCTION dbu_put (VAR f : DBUFile; VAR b; size : WORD) : LONGINT;
233+ VAR r, pr, c : LONGINT;
234+ p : PCHAR;
235+ g : WORD;
236+ bs : WORD;
237+ BEGIN
238+ r := 0 ;
239+ IF IsOpen(f.f) THEN BEGIN
240+ p := @b;
241+ bs := f.header.size - SizeOf(DBUFile);
242+ r := dbu_alloc(f);
243+ pr := r;
244+ g := size;
245+ IF g > bs THEN g := bs;
246+ Move(p, f.data[0 ], g);
247+ Dec(size, g);
248+ Inc(p, g);
249+ WHILE size <> 0 DO BEGIN
250+ c := dbu_alloc(f);
251+ dbu_go(f, pr);
252+ f.crec.next := c;
253+ f.needupdate := TRUE;
254+ dbu_go(f, c);
255+ g := size;
256+ IF g > bs THEN g := bs;
257+ Move(p, f.data[0 ], g);
258+ f.crec.size := g;
259+ Dec(size, g);
260+ Inc(p, g);
261+ f.needupdate := TRUE;
262+ END ;
219263 END ;
264+ dbu_put := r;
220265END ;
221266
222267END .
0 commit comments