1 { Copyright (C) 2005 Bas Steendijk and Peter Green
\r
2 For conditions of distribution and use, see copyright notice in zlib_license.txt
\r
3 which is included in the package
\r
4 ----------------------------------------------------------------------------- }
\r
12 {-$define bfifo_assert}
\r
15 {$ifdef bfifo_assert}
\r
21 bfifo_minallocsize:integer=4096;
\r
24 tfifo=class(tobject)
\r
27 lastallocsize:integer; //last seen before we freed the buffer
\r
28 lastalloccount:integer;
\r
31 function getallocsizeforsize(i:integer):integer;
\r
35 procedure add(data:pointer;len:integer);
\r
36 function get(var resultptr:pointer;len:integer):integer;
\r
37 procedure del(len:integer);
\r
38 destructor destroy; override;
\r
43 function tfifo.getallocsizeforsize(i:integer):integer;
\r
47 //get smallest power of two >= i and >= minallocsize
\r
49 if (i <= bfifo_minallocsize) then begin
\r
50 result := bfifo_minallocsize;
\r
55 for a := 1 to 31 do result := result or (i shr a);
\r
60 procedure tfifo.add;
\r
65 if len <= 0 then exit;
\r
67 {$ifdef bfifo_assert}
\r
68 if (size < 0) then raise exception.create('tfifo.add: size<0: '+inttostr(size));
\r
69 if (allocsize < 0) then raise exception.create('tfifo.add: allocsize<0: '+inttostr(allocsize));
\r
70 if assigned(p) and (size = 0) then raise exception.create('tfifo.add: p assigned and size=0');
\r
71 if assigned(p) and (allocsize = 0) then raise exception.create('tfifo.add: p assigned and allocsize=0');
\r
74 if not assigned(p) then begin
\r
75 {$ifdef bfifo_assert}
\r
76 if (size > 0) then raise exception.create('tfifo.add: p not assigned and size>0: '+inttostr(size));
\r
77 if (allocsize > 0) then raise exception.create('tfifo.add: p not assigned and allocsize>0: '+inttostr(allocsize));
\r
80 //no buffer is allocated, allocate big enough one now
\r
81 allocsize := getallocsizeforsize(len);
\r
83 //reuse the biggest size seen to avoid unnecessary growing of the buffer all the time, but sometimes shrink it
\r
84 //so an unnecessary big buffer isn't around forever
\r
85 inc(lastalloccount);
\r
86 if (lastalloccount and 7 = 0) then lastallocsize := getallocsizeforsize(lastallocsize div 2);
\r
88 if allocsize < lastallocsize then allocsize := lastallocsize;
\r
90 getmem(p,allocsize);
\r
93 end else if (head + len > allocsize) then begin
\r
94 //buffer is not big enough to add new data to the end
\r
96 if (size + len <= allocsize) then begin
\r
97 //it will fit if we move the data in the buffer to the start first
\r
98 if (size > 0) then move(pointer(taddrint(p) + tail)^,p^,size);
\r
99 //if (size > 0) then move(p[tail],p[0],size);
\r
103 allocsize := getallocsizeforsize(size + len);
\r
105 getmem(p2,allocsize);
\r
106 move(pointer(taddrint(p) + tail)^,p2^,size);
\r
114 {$ifdef bfifo_assert}
\r
115 if (head + len > allocsize) or (head < 0) then raise exception.create('tfifo.add: allocsize - head < len: '+inttostr(allocsize)+' '+inttostr(head)+' '+inttostr(len));
\r
116 if (not assigned(p)) then raise exception.create('tfifo.add: p '+inttostr(size));
\r
121 move(data^,pointer(taddrint(p) + head)^,len);
\r
125 function tfifo.get;
\r
127 if len > size then len := size;
\r
128 if len <= 0 then begin
\r
134 //return a pointer into the buffer without copying
\r
137 resultptr := pointer(taddrint(p) + tail);
\r
140 procedure tfifo.del;
\r
142 if len <= 0 then exit;
\r
144 {$ifdef bfifo_assert}
\r
145 if (size < 0) then raise exception.create('tfifo.del: size negative: '+inttostr(size));
\r
146 if (head - tail <> size) then raise exception.create('tfifo.del: size head tail: '+inttostr(size)+' '+inttostr(head)+' '+inttostr(tail));
\r
147 if (head > allocsize) then raise exception.create('tfifo.del: head allocsize: '+inttostr(head)+' '+inttostr(allocsize));
\r
150 if (len > size) then len := size;
\r
155 if (size <= 0) then begin
\r
156 if (allocsize > lastallocsize) then lastallocsize := allocsize;
\r
160 if assigned(p) then freemem(p);
\r
165 destructor tfifo.destroy;
\r
169 {$ifdef bfifo_assert}
\r
170 if assigned(p) then raise exception.create('tfifo.destroy: did not free '+inttostr(size)+' '+inttostr(allocsize));
\r