xref: /haiku/src/kits/support/DataIO.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
1 /*
2  * Copyright 2005-2014 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stefano Ceccherini, burton666@libero.it
7  */
8 
9 
10 #include <DataIO.h>
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #include <Errors.h>
17 
18 
19 BDataIO::BDataIO()
20 {
21 }
22 
23 
24 BDataIO::~BDataIO()
25 {
26 }
27 
28 
29 ssize_t
30 BDataIO::Read(void* buffer, size_t size)
31 {
32 	return B_NOT_SUPPORTED;
33 }
34 
35 
36 ssize_t
37 BDataIO::Write(const void* buffer, size_t size)
38 {
39 	return B_NOT_SUPPORTED;
40 }
41 
42 
43 status_t
44 BDataIO::Flush()
45 {
46 	return B_OK;
47 }
48 
49 
50 status_t
51 BDataIO::ReadExactly(void* buffer, size_t size, size_t* _bytesRead)
52 {
53 	uint8* out = (uint8*)buffer;
54 	size_t bytesRemaining = size;
55 	status_t error = B_OK;
56 
57 	while (bytesRemaining > 0) {
58 		ssize_t bytesRead = Read(out, bytesRemaining);
59 		if (bytesRead < 0) {
60 			error = bytesRead;
61 			break;
62 		}
63 
64 		if (bytesRead == 0) {
65 			error = B_PARTIAL_READ;
66 			break;
67 		}
68 
69 		out += bytesRead;
70 		bytesRemaining -= bytesRead;
71 	}
72 
73 	if (_bytesRead != NULL)
74 		*_bytesRead = size - bytesRemaining;
75 
76 	return error;
77 }
78 
79 
80 status_t
81 BDataIO::WriteExactly(const void* buffer, size_t size, size_t* _bytesWritten)
82 {
83 	const uint8* in = (const uint8*)buffer;
84 	size_t bytesRemaining = size;
85 	status_t error = B_OK;
86 
87 	while (bytesRemaining > 0) {
88 		ssize_t bytesWritten = Write(in, bytesRemaining);
89 		if (bytesWritten < 0) {
90 			error = bytesWritten;
91 			break;
92 		}
93 
94 		if (bytesWritten == 0) {
95 			error = B_PARTIAL_WRITE;
96 			break;
97 		}
98 
99 		in += bytesWritten;
100 		bytesRemaining -= bytesWritten;
101 	}
102 
103 	if (_bytesWritten != NULL)
104 		*_bytesWritten = size - bytesRemaining;
105 
106 	return error;
107 }
108 
109 
110 // Private or Reserved
111 
112 BDataIO::BDataIO(const BDataIO &)
113 {
114 	// Copying not allowed
115 }
116 
117 
118 BDataIO &
119 BDataIO::operator=(const BDataIO &)
120 {
121 	// Copying not allowed
122 	return *this;
123 }
124 
125 
126 #if __GNUC__ == 2
127 
128 
129 extern "C" status_t
130 _ReservedDataIO1__7BDataIO(BDataIO* self)
131 {
132 	return self->BDataIO::Flush();
133 }
134 
135 
136 #else
137 
138 
139 // TODO: RELEASE: Remove!
140 
141 extern "C" status_t
142 _ZN7BDataIO16_ReservedDataIO1Ev(BDataIO* self)
143 {
144 	return self->BDataIO::Flush();
145 }
146 
147 
148 #endif
149 
150 
151 // FBC
152 void BDataIO::_ReservedDataIO2(){}
153 void BDataIO::_ReservedDataIO3(){}
154 void BDataIO::_ReservedDataIO4(){}
155 void BDataIO::_ReservedDataIO5(){}
156 void BDataIO::_ReservedDataIO6(){}
157 void BDataIO::_ReservedDataIO7(){}
158 void BDataIO::_ReservedDataIO8(){}
159 void BDataIO::_ReservedDataIO9(){}
160 void BDataIO::_ReservedDataIO10(){}
161 void BDataIO::_ReservedDataIO11(){}
162 void BDataIO::_ReservedDataIO12(){}
163 
164 
165 //	#pragma mark -
166 
167 
168 BPositionIO::BPositionIO()
169 {
170 }
171 
172 
173 BPositionIO::~BPositionIO()
174 {
175 }
176 
177 
178 ssize_t
179 BPositionIO::Read(void* buffer, size_t size)
180 {
181 	off_t curPos = Position();
182 	ssize_t result = ReadAt(curPos, buffer, size);
183 	if (result > 0)
184 		Seek(result, SEEK_CUR);
185 
186 	return result;
187 }
188 
189 
190 ssize_t
191 BPositionIO::Write(const void* buffer, size_t size)
192 {
193 	off_t curPos = Position();
194 	ssize_t result = WriteAt(curPos, buffer, size);
195 	if (result > 0)
196 		Seek(result, SEEK_CUR);
197 
198 	return result;
199 }
200 
201 
202 status_t
203 BPositionIO::ReadAtExactly(off_t position, void* buffer, size_t size,
204 	size_t* _bytesRead)
205 {
206 	uint8* out = (uint8*)buffer;
207 	size_t bytesRemaining = size;
208 	status_t error = B_OK;
209 
210 	while (bytesRemaining > 0) {
211 		ssize_t bytesRead = ReadAt(position, out, bytesRemaining);
212 		if (bytesRead < 0) {
213 			error = bytesRead;
214 			break;
215 		}
216 
217 		if (bytesRead == 0) {
218 			error = B_PARTIAL_READ;
219 			break;
220 		}
221 
222 		out += bytesRead;
223 		bytesRemaining -= bytesRead;
224 		position += bytesRead;
225 	}
226 
227 	if (_bytesRead != NULL)
228 		*_bytesRead = size - bytesRemaining;
229 
230 	return error;
231 }
232 
233 
234 status_t
235 BPositionIO::WriteAtExactly(off_t position, const void* buffer, size_t size,
236 	size_t* _bytesWritten)
237 {
238 	const uint8* in = (const uint8*)buffer;
239 	size_t bytesRemaining = size;
240 	status_t error = B_OK;
241 
242 	while (bytesRemaining > 0) {
243 		ssize_t bytesWritten = WriteAt(position, in, bytesRemaining);
244 		if (bytesWritten < 0) {
245 			error = bytesWritten;
246 			break;
247 		}
248 
249 		if (bytesWritten == 0) {
250 			error = B_PARTIAL_WRITE;
251 			break;
252 		}
253 
254 		in += bytesWritten;
255 		bytesRemaining -= bytesWritten;
256 		position += bytesWritten;
257 	}
258 
259 	if (_bytesWritten != NULL)
260 		*_bytesWritten = size - bytesRemaining;
261 
262 	return error;
263 }
264 
265 
266 status_t
267 BPositionIO::SetSize(off_t size)
268 {
269 	return B_ERROR;
270 }
271 
272 
273 status_t
274 BPositionIO::GetSize(off_t* size) const
275 {
276 	if (!size)
277 		return B_BAD_VALUE;
278 
279 	off_t currentPos = Position();
280 	if (currentPos < 0)
281 		return (status_t)currentPos;
282 
283 	*size = const_cast<BPositionIO*>(this)->Seek(0, SEEK_END);
284 	if (*size < 0)
285 		return (status_t)*size;
286 
287 	off_t pos = const_cast<BPositionIO*>(this)->Seek(currentPos, SEEK_SET);
288 
289 	if (pos != currentPos)
290 		return pos < 0 ? (status_t)pos : B_ERROR;
291 
292 	return B_OK;
293 }
294 
295 
296 // FBC
297 extern "C" void _ReservedPositionIO1__11BPositionIO() {}
298 void BPositionIO::_ReservedPositionIO2(){}
299 void BPositionIO::_ReservedPositionIO3(){}
300 void BPositionIO::_ReservedPositionIO4(){}
301 void BPositionIO::_ReservedPositionIO5(){}
302 void BPositionIO::_ReservedPositionIO6(){}
303 void BPositionIO::_ReservedPositionIO7(){}
304 void BPositionIO::_ReservedPositionIO8(){}
305 void BPositionIO::_ReservedPositionIO9(){}
306 void BPositionIO::_ReservedPositionIO10(){}
307 void BPositionIO::_ReservedPositionIO11(){}
308 void BPositionIO::_ReservedPositionIO12(){}
309 
310 
311 //	#pragma mark -
312 
313 
314 BMemoryIO::BMemoryIO(void* buffer, size_t length)
315 	:
316 	fReadOnly(false),
317 	fBuffer(static_cast<char*>(buffer)),
318 	fLength(length),
319 	fBufferSize(length),
320 	fPosition(0)
321 {
322 }
323 
324 
325 BMemoryIO::BMemoryIO(const void* buffer, size_t length)
326 	:
327 	fReadOnly(true),
328 	fBuffer(const_cast<char*>(static_cast<const char*>(buffer))),
329 	fLength(length),
330 	fBufferSize(length),
331 	fPosition(0)
332 {
333 }
334 
335 
336 BMemoryIO::~BMemoryIO()
337 {
338 }
339 
340 
341 ssize_t
342 BMemoryIO::ReadAt(off_t pos, void* buffer, size_t size)
343 {
344 	if (buffer == NULL || pos < 0)
345 		return B_BAD_VALUE;
346 
347 	ssize_t sizeRead = 0;
348 	if (pos < (off_t)fLength) {
349 		sizeRead = min_c((off_t)size, (off_t)fLength - pos);
350 		memcpy(buffer, fBuffer + pos, sizeRead);
351 	}
352 
353 	return sizeRead;
354 }
355 
356 
357 ssize_t
358 BMemoryIO::WriteAt(off_t pos, const void* buffer, size_t size)
359 {
360 	if (fReadOnly)
361 		return B_NOT_ALLOWED;
362 
363 	if (buffer == NULL || pos < 0)
364 		return B_BAD_VALUE;
365 
366 	ssize_t sizeWritten = 0;
367 	if (pos < (off_t)fBufferSize) {
368 		sizeWritten = min_c((off_t)size, (off_t)fBufferSize - pos);
369 		memcpy(fBuffer + pos, buffer, sizeWritten);
370 	}
371 
372 	if (pos + sizeWritten > (off_t)fLength)
373 		fLength = pos + sizeWritten;
374 
375 	return sizeWritten;
376 }
377 
378 
379 off_t
380 BMemoryIO::Seek(off_t position, uint32 seek_mode)
381 {
382 	switch (seek_mode) {
383 		case SEEK_SET:
384 			fPosition = position;
385 			break;
386 		case SEEK_CUR:
387 			fPosition += position;
388 			break;
389 		case SEEK_END:
390 			fPosition = fLength + position;
391 			break;
392 		default:
393 			break;
394 	}
395 
396 	return fPosition;
397 }
398 
399 
400 off_t
401 BMemoryIO::Position() const
402 {
403 	return fPosition;
404 }
405 
406 
407 status_t
408 BMemoryIO::SetSize(off_t size)
409 {
410 	if (fReadOnly)
411 		return B_NOT_ALLOWED;
412 
413 	if (size > (off_t)fBufferSize)
414 		return B_ERROR;
415 
416 	fLength = size;
417 
418 	return B_OK;
419 }
420 
421 
422 // Private or Reserved
423 
424 BMemoryIO::BMemoryIO(const BMemoryIO &)
425 {
426 	//Copying not allowed
427 }
428 
429 
430 BMemoryIO &
431 BMemoryIO::operator=(const BMemoryIO &)
432 {
433 	//Copying not allowed
434 	return *this;
435 }
436 
437 
438 // FBC
439 void BMemoryIO::_ReservedMemoryIO1(){}
440 void BMemoryIO::_ReservedMemoryIO2(){}
441 
442 
443 //	#pragma mark -
444 
445 
446 BMallocIO::BMallocIO()
447 	:
448 	fBlockSize(256),
449 	fMallocSize(0),
450 	fLength(0),
451 	fData(NULL),
452 	fPosition(0)
453 {
454 }
455 
456 
457 BMallocIO::~BMallocIO()
458 {
459 	free(fData);
460 }
461 
462 
463 ssize_t
464 BMallocIO::ReadAt(off_t pos, void* buffer, size_t size)
465 {
466 	if (buffer == NULL)
467 		return B_BAD_VALUE;
468 
469 	ssize_t sizeRead = 0;
470 	if (pos < (off_t)fLength) {
471 		sizeRead = min_c((off_t)size, (off_t)fLength - pos);
472 		memcpy(buffer, fData + pos, sizeRead);
473 	}
474 
475 	return sizeRead;
476 }
477 
478 
479 ssize_t
480 BMallocIO::WriteAt(off_t pos, const void* buffer, size_t size)
481 {
482 	if (buffer == NULL)
483 		return B_BAD_VALUE;
484 
485 	size_t newSize = max_c(pos + (off_t)size, (off_t)fLength);
486 	status_t error = B_OK;
487 
488 	if (newSize > fMallocSize)
489 		error = SetSize(newSize);
490 
491 	if (error == B_OK) {
492 		memcpy(fData + pos, buffer, size);
493 		if (pos + size > fLength)
494 			fLength = pos + size;
495 	}
496 
497 	return error != B_OK ? error : size;
498 }
499 
500 
501 off_t
502 BMallocIO::Seek(off_t position, uint32 seekMode)
503 {
504 	switch (seekMode) {
505 		case SEEK_SET:
506 			fPosition = position;
507 			break;
508 		case SEEK_END:
509 			fPosition = fLength + position;
510 			break;
511 		case SEEK_CUR:
512 			fPosition += position;
513 			break;
514 		default:
515 			break;
516 	}
517 	return fPosition;
518 }
519 
520 
521 off_t
522 BMallocIO::Position() const
523 {
524 	return fPosition;
525 }
526 
527 
528 status_t
529 BMallocIO::SetSize(off_t size)
530 {
531 	status_t error = B_OK;
532 	if (size == 0) {
533 		// size == 0, free the memory
534 		free(fData);
535 		fData = NULL;
536 		fMallocSize = 0;
537 	} else {
538 		// size != 0, see, if necessary to resize
539 		size_t newSize = (size + fBlockSize - 1) / fBlockSize * fBlockSize;
540 		if (size != (off_t)fMallocSize) {
541 			// we need to resize
542 			if (char* newData = static_cast<char*>(realloc(fData, newSize))) {
543 				// set the new area to 0
544 				if (newSize > fMallocSize)
545 					memset(newData + fMallocSize, 0, newSize - fMallocSize);
546 				fData = newData;
547 				fMallocSize = newSize;
548 			} else	// couldn't alloc the memory
549 				error = B_NO_MEMORY;
550 		}
551 	}
552 
553 	if (error == B_OK)
554 		fLength = size;
555 
556 	return error;
557 }
558 
559 
560 void
561 BMallocIO::SetBlockSize(size_t blockSize)
562 {
563 	if (blockSize == 0)
564 		blockSize = 1;
565 
566 	if (blockSize != fBlockSize)
567 		fBlockSize = blockSize;
568 }
569 
570 
571 const void*
572 BMallocIO::Buffer() const
573 {
574 	return fData;
575 }
576 
577 
578 size_t
579 BMallocIO::BufferLength() const
580 {
581 	return fLength;
582 }
583 
584 
585 // Private or Reserved
586 
587 BMallocIO::BMallocIO(const BMallocIO &)
588 {
589 	// copying not allowed...
590 }
591 
592 
593 BMallocIO &
594 BMallocIO::operator=(const BMallocIO &)
595 {
596 	// copying not allowed...
597 	return *this;
598 }
599 
600 
601 // FBC
602 void BMallocIO::_ReservedMallocIO1() {}
603 void BMallocIO::_ReservedMallocIO2() {}
604