2 * Copyright 2001-2008 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT license
6 * Stefano Ceccherini, burton666@libero.it
17 BBufferIO::BBufferIO(BPositionIO
* stream
, size_t bufferSize
, bool ownsStream
)
23 fBufferIsDirty(false),
24 fOwnsStream(ownsStream
)
27 fBufferSize
= max_c(bufferSize
, 512);
28 fPosition
= stream
->Position();
30 // What can we do if this malloc fails ?
31 // I think R5 uses new, but doesn't catch the thrown exception
32 // (if you specify a very big buffer, the application just
33 // terminates with abort).
34 fBuffer
= (char*)malloc(fBufferSize
);
38 BBufferIO::~BBufferIO()
41 // Write pending changes to the stream
53 BBufferIO::ReadAt(off_t pos
, void* buffer
, size_t size
)
55 // We refuse to crash, even if
56 // you were lazy and didn't give a valid
57 // stream on construction.
63 // If the amount of data we want doesn't fit in the buffer, just
64 // read it directly from the disk (and don't touch the buffer).
65 if (size
> fBufferSize
|| fBuffer
== NULL
) {
68 return fStream
->ReadAt(pos
, buffer
, size
);
71 // If the data we are looking for is not in the buffer...
72 if (size
> fBufferUsed
74 || pos
> fBufferStart
+ (off_t
)fBufferUsed
75 || pos
+ size
> fBufferStart
+ fBufferUsed
) {
77 // If there are pending writes, do them.
81 // ...cache as much as we can from the stream
82 ssize_t sizeRead
= fStream
->ReadAt(pos
, fBuffer
, fBufferSize
);
86 fBufferUsed
= sizeRead
;
87 if (fBufferUsed
> 0) {
88 // The data is buffered starting from this offset
93 size
= min_c(size
, fBufferUsed
);
95 // copy data from the cache to the given buffer
96 memcpy(buffer
, fBuffer
+ pos
- fBufferStart
, size
);
103 BBufferIO::WriteAt(off_t pos
, const void* buffer
, size_t size
)
110 // If data doesn't fit into the buffer, write it directly to the stream
111 if (size
> fBufferSize
|| fBuffer
== NULL
)
112 return fStream
->WriteAt(pos
, buffer
, size
);
114 // If we have cached data in the buffer, whose offset into the stream
115 // is > 0, and the buffer isn't dirty, drop the data.
116 if (!fBufferIsDirty
&& fBufferStart
> pos
) {
121 // If we want to write beyond the cached data...
122 if (pos
> fBufferStart
+ (off_t
)fBufferUsed
123 || pos
< fBufferStart
) {
127 // Can we just cache from the beginning?
128 if (pos
+ size
<= fBufferSize
)
132 read
= fStream
->ReadAt(where
, fBuffer
, fBufferSize
);
135 fBufferStart
= where
;
139 memcpy(fBuffer
+ pos
- fBufferStart
, buffer
, size
);
141 fBufferIsDirty
= true;
142 fBufferUsed
= max_c((size
+ pos
), fBufferUsed
);
149 BBufferIO::Seek(off_t position
, uint32 seekMode
)
154 off_t newPosition
= fPosition
;
158 newPosition
+= position
;
161 newPosition
= position
;
166 status_t status
= fStream
->GetSize(&size
);
170 newPosition
= size
- position
;
178 fPosition
= newPosition
;
184 BBufferIO::Position() const
191 BBufferIO::SetSize(off_t size
)
196 return fStream
->SetSize(size
);
206 // Write the cached data to the stream
207 ssize_t bytesWritten
= fStream
->WriteAt(fBufferStart
, fBuffer
, fBufferUsed
);
208 if (bytesWritten
> 0)
209 fBufferIsDirty
= false;
211 return (bytesWritten
< 0) ? bytesWritten
: B_OK
;
216 BBufferIO::Stream() const
223 BBufferIO::BufferSize() const
230 BBufferIO::OwnsStream() const
237 BBufferIO::SetOwnsStream(bool ownsStream
)
239 fOwnsStream
= ownsStream
;
244 BBufferIO::PrintToStream() const
246 printf("stream %p\n", fStream
);
247 printf("buffer %p\n", fBuffer
);
248 printf("start %" B_PRId64
"\n", fBufferStart
);
249 printf("used %ld\n", fBufferUsed
);
250 printf("phys %ld\n", fBufferSize
);
251 printf("dirty %s\n", (fBufferIsDirty
) ? "true" : "false");
252 printf("owns %s\n", (fOwnsStream
) ? "true" : "false");
256 // #pragma mark - FBC padding
259 // These functions are here to maintain future binary
261 status_t
BBufferIO::_Reserved_BufferIO_0(void*) { return B_ERROR
; }
262 status_t
BBufferIO::_Reserved_BufferIO_1(void*) { return B_ERROR
; }
263 status_t
BBufferIO::_Reserved_BufferIO_2(void*) { return B_ERROR
; }
264 status_t
BBufferIO::_Reserved_BufferIO_3(void*) { return B_ERROR
; }
265 status_t
BBufferIO::_Reserved_BufferIO_4(void*) { return B_ERROR
; }