1/*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include <io_requests.h>
7
8#include "IORequest.h"
9
10
11// #pragma mark - static helpers
12
13
14static status_t
15transfer_io_request_data(io_request* request, void* buffer, size_t size,
16	bool writeToRequest)
17{
18	if (writeToRequest == request->IsWrite()
19		|| request->RemainingBytes() < size) {
20		return B_BAD_VALUE;
21	}
22
23	// lock the request buffer memory, if it is user memory
24	IOBuffer* ioBuffer = request->Buffer();
25	if (ioBuffer->IsUser() && !ioBuffer->IsMemoryLocked()) {
26		status_t error = ioBuffer->LockMemory(request->TeamID(),
27			!writeToRequest);
28		if (error != B_OK)
29			return error;
30	}
31
32	// read/write
33	off_t offset = request->Offset() + request->TransferredBytes();
34	status_t error = writeToRequest
35		? request->CopyData(buffer, offset, size)
36		: request->CopyData(offset, buffer, size);
37	if (error != B_OK)
38		return error;
39
40	request->Advance(size);
41	return B_OK;
42}
43
44
45// #pragma mark - public API
46
47
48/*!	Returns whether the given I/O request is a write request. */
49bool
50io_request_is_write(const io_request* request)
51{
52	return request->IsWrite();
53}
54
55
56/*!	Returns whether the I/O request has VIP status. */
57bool
58io_request_is_vip(const io_request* request)
59{
60	return (request->Flags() & B_VIP_IO_REQUEST) != 0;
61}
62
63
64/*!	Returns the read/write offset of the given I/O request.
65	This is the immutable offset the request was created with;
66	read_from_io_request() and write_to_io_request() don't change it.
67*/
68off_t
69io_request_offset(const io_request* request)
70{
71	return request->Offset();
72}
73
74
75/*!	Returns the read/write length of the given I/O request.
76	This is the immutable length the request was created with;
77	read_from_io_request() and write_to_io_request() don't change it.
78*/
79off_t
80io_request_length(const io_request* request)
81{
82	return request->Length();
83}
84
85
86/*!	Reads data from the given I/O request into the given buffer and advances
87	the request's transferred data pointer.
88	Multiple calls to read_from_io_request() are allowed, but the total size
89	must not exceed io_request_length(request).
90*/
91status_t
92read_from_io_request(io_request* request, void* buffer, size_t size)
93{
94	return transfer_io_request_data(request, buffer, size, false);
95}
96
97
98/*!	Writes data from the given buffer to the given I/O request and advances
99	the request's transferred data pointer.
100	Multiple calls to write_to_io_request() are allowed, but the total size
101	must not exceed io_request_length(request).
102*/
103status_t
104write_to_io_request(io_request* request, const void* buffer, size_t size)
105{
106	return transfer_io_request_data(request, (void*)buffer, size, true);
107}
108
109
110/*!	Sets the given I/O request's status and notifies listeners that the request
111	is finished.
112*/
113void
114notify_io_request(io_request* request, status_t status)
115{
116	request->SetStatusAndNotify(status);
117}
118