1// RequestFlattener.cpp
2
3#include <ByteOrder.h>
4
5#include "RequestFlattener.h"
6
7// Writer
8
9// constructor
10Writer::Writer()
11{
12}
13
14// destructor
15Writer::~Writer()
16{
17}
18
19// Pad
20status_t
21Writer::Pad(int32 size)
22{
23	if (size <= 0)
24		return B_OK;
25
26	if (size > 8)
27		return B_BAD_VALUE;
28
29	char buffer[8];
30	return Write(buffer, size);
31}
32
33
34// DataIOWriter
35
36// constructor
37DataIOWriter::DataIOWriter(BDataIO* dataIO)
38	: Writer(),
39	  fDataIO(dataIO)
40{
41}
42
43// destructor
44DataIOWriter::~DataIOWriter()
45{
46}
47
48// Write
49status_t
50DataIOWriter::Write(const void* buffer, int32 size)
51{
52	ssize_t bytesWritten = fDataIO->Write(buffer, size);
53	if (bytesWritten < 0)
54		return bytesWritten;
55	if (bytesWritten != size)
56		return B_ERROR;
57	return B_OK;
58}
59
60
61// DummyWriter
62
63// constructor
64DummyWriter::DummyWriter()
65{
66}
67
68// destructor
69DummyWriter::~DummyWriter()
70{
71}
72
73// Write
74status_t
75DummyWriter::Write(const void* buffer, int32 size)
76{
77	return B_OK;
78}
79
80
81// RequestFlattener
82
83// constructor
84RequestFlattener::RequestFlattener(Writer* writer)
85	: RequestMemberVisitor(),
86	  fWriter(writer),
87	  fStatus(B_OK),
88	  fBytesWritten(0)
89{
90}
91
92// GetStatus
93status_t
94RequestFlattener::GetStatus() const
95{
96	return fStatus;
97}
98
99// GetBytesWritten
100int32
101RequestFlattener::GetBytesWritten() const
102{
103	return fBytesWritten;
104}
105
106// Visit
107void
108RequestFlattener::Visit(RequestMember* member, bool& data)
109{
110	uint8 netData = (data ? ~0 : 0);
111	Write(&netData, 1);
112}
113
114// Visit
115void
116RequestFlattener::Visit(RequestMember* member, int8& data)
117{
118	Write(&data, 1);
119}
120
121// Visit
122void
123RequestFlattener::Visit(RequestMember* member, uint8& data)
124{
125	Write(&data, 1);
126}
127
128// Visit
129void
130RequestFlattener::Visit(RequestMember* member, int16& data)
131{
132	int16 netData = B_HOST_TO_BENDIAN_INT16(data);
133	Write(&netData, 2);
134}
135
136// Visit
137void
138RequestFlattener::Visit(RequestMember* member, uint16& data)
139{
140	uint16 netData = B_HOST_TO_BENDIAN_INT16(data);
141	Write(&netData, 2);
142}
143
144// Visit
145void
146RequestFlattener::Visit(RequestMember* member, int32& data)
147{
148	int32 netData = B_HOST_TO_BENDIAN_INT32(data);
149	Write(&netData, 4);
150}
151
152// Visit
153void
154RequestFlattener::Visit(RequestMember* member, uint32& data)
155{
156	uint32 netData = B_HOST_TO_BENDIAN_INT32(data);
157	Write(&netData, 4);
158}
159
160// Visit
161void
162RequestFlattener::Visit(RequestMember* member, int64& data)
163{
164	int64 netData = B_HOST_TO_BENDIAN_INT64(data);
165	Write(&netData, 8);
166}
167
168// Visit
169void
170RequestFlattener::Visit(RequestMember* member, uint64& data)
171{
172	uint64 netData = B_HOST_TO_BENDIAN_INT64(data);
173	Write(&netData, 8);
174}
175
176// Visit
177void
178RequestFlattener::Visit(RequestMember* member, Data& data)
179{
180	WriteData(data.address, data.size);
181}
182
183// Visit
184void
185RequestFlattener::Visit(RequestMember* member, StringData& data)
186{
187	WriteData(data.address, data.size);
188}
189
190// Visit
191void
192RequestFlattener::Visit(RequestMember* member, RequestMember& subMember)
193{
194	subMember.ShowAround(this);
195}
196
197// Visit
198void
199RequestFlattener::Visit(RequestMember* member,
200	FlattenableRequestMember& subMember)
201{
202	if (fStatus != B_OK)
203		return;
204
205	status_t status = subMember.Flatten(this);
206	if (fStatus == B_OK)
207		fStatus = status;
208}
209
210
211// Write
212status_t
213RequestFlattener::Write(const void* buffer, int32 size)
214{
215	if (fStatus != B_OK)
216		return fStatus;
217
218	fStatus = fWriter->Write(buffer, size);
219	if (fStatus == B_OK)
220		fBytesWritten += size;
221
222	return fStatus;
223}
224
225// Align
226status_t
227RequestFlattener::Align(int32 align)
228{
229	if (fStatus != B_OK)
230		return fStatus;
231
232	if (align > 1) {
233		int32 newBytesWritten = fBytesWritten;
234		if (!(align & 0x3))
235			newBytesWritten = (fBytesWritten + 3) & ~0x3;
236		else if (!(align & 0x1))
237			newBytesWritten = (fBytesWritten + 1) & ~0x1;
238
239		if (newBytesWritten > fBytesWritten) {
240			fStatus = fWriter->Pad(newBytesWritten - fBytesWritten);
241			if (fStatus == B_OK)
242				fBytesWritten = newBytesWritten;
243		}
244	}
245
246	return fStatus;
247}
248
249// WriteBool
250status_t
251RequestFlattener::WriteBool(bool data)
252{
253	return Write(&data, 1);
254}
255
256// WriteInt32
257status_t
258RequestFlattener::WriteInt32(int32 data)
259{
260	int32 netData = B_HOST_TO_BENDIAN_INT32(data);
261	return Write(&netData, 4);
262}
263
264// WriteData
265status_t
266RequestFlattener::WriteData(const void* buffer, int32 size)
267{
268	if ((!buffer && size > 0) || size < 0)
269		return B_BAD_VALUE;
270
271	int32 netData = B_HOST_TO_BENDIAN_INT32(size);
272	Write(&netData, 4);
273	return Write(buffer, size);
274}
275
276// WriteString
277status_t
278RequestFlattener::WriteString(const char* string)
279{
280	int32 size = (string ? strlen(string) + 1 : 0);
281	return WriteData(string, size);
282}
283
284