1 // RequestFlattener.cpp
2
3 #include <ByteOrder.h>
4
5 #include "RequestFlattener.h"
6
7 // Writer
8
9 // constructor
Writer()10 Writer::Writer()
11 {
12 }
13
14 // destructor
~Writer()15 Writer::~Writer()
16 {
17 }
18
19 // Pad
20 status_t
Pad(int32 size)21 Writer::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
DataIOWriter(BDataIO * dataIO)37 DataIOWriter::DataIOWriter(BDataIO* dataIO)
38 : Writer(),
39 fDataIO(dataIO)
40 {
41 }
42
43 // destructor
~DataIOWriter()44 DataIOWriter::~DataIOWriter()
45 {
46 }
47
48 // Write
49 status_t
Write(const void * buffer,int32 size)50 DataIOWriter::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
DummyWriter()64 DummyWriter::DummyWriter()
65 {
66 }
67
68 // destructor
~DummyWriter()69 DummyWriter::~DummyWriter()
70 {
71 }
72
73 // Write
74 status_t
Write(const void * buffer,int32 size)75 DummyWriter::Write(const void* buffer, int32 size)
76 {
77 return B_OK;
78 }
79
80
81 // RequestFlattener
82
83 // constructor
RequestFlattener(Writer * writer)84 RequestFlattener::RequestFlattener(Writer* writer)
85 : RequestMemberVisitor(),
86 fWriter(writer),
87 fStatus(B_OK),
88 fBytesWritten(0)
89 {
90 }
91
92 // GetStatus
93 status_t
GetStatus() const94 RequestFlattener::GetStatus() const
95 {
96 return fStatus;
97 }
98
99 // GetBytesWritten
100 int32
GetBytesWritten() const101 RequestFlattener::GetBytesWritten() const
102 {
103 return fBytesWritten;
104 }
105
106 // Visit
107 void
Visit(RequestMember * member,bool & data)108 RequestFlattener::Visit(RequestMember* member, bool& data)
109 {
110 uint8 netData = (data ? ~0 : 0);
111 Write(&netData, 1);
112 }
113
114 // Visit
115 void
Visit(RequestMember * member,int8 & data)116 RequestFlattener::Visit(RequestMember* member, int8& data)
117 {
118 Write(&data, 1);
119 }
120
121 // Visit
122 void
Visit(RequestMember * member,uint8 & data)123 RequestFlattener::Visit(RequestMember* member, uint8& data)
124 {
125 Write(&data, 1);
126 }
127
128 // Visit
129 void
Visit(RequestMember * member,int16 & data)130 RequestFlattener::Visit(RequestMember* member, int16& data)
131 {
132 int16 netData = B_HOST_TO_BENDIAN_INT16(data);
133 Write(&netData, 2);
134 }
135
136 // Visit
137 void
Visit(RequestMember * member,uint16 & data)138 RequestFlattener::Visit(RequestMember* member, uint16& data)
139 {
140 uint16 netData = B_HOST_TO_BENDIAN_INT16(data);
141 Write(&netData, 2);
142 }
143
144 // Visit
145 void
Visit(RequestMember * member,int32 & data)146 RequestFlattener::Visit(RequestMember* member, int32& data)
147 {
148 int32 netData = B_HOST_TO_BENDIAN_INT32(data);
149 Write(&netData, 4);
150 }
151
152 // Visit
153 void
Visit(RequestMember * member,uint32 & data)154 RequestFlattener::Visit(RequestMember* member, uint32& data)
155 {
156 uint32 netData = B_HOST_TO_BENDIAN_INT32(data);
157 Write(&netData, 4);
158 }
159
160 // Visit
161 void
Visit(RequestMember * member,int64 & data)162 RequestFlattener::Visit(RequestMember* member, int64& data)
163 {
164 int64 netData = B_HOST_TO_BENDIAN_INT64(data);
165 Write(&netData, 8);
166 }
167
168 // Visit
169 void
Visit(RequestMember * member,uint64 & data)170 RequestFlattener::Visit(RequestMember* member, uint64& data)
171 {
172 uint64 netData = B_HOST_TO_BENDIAN_INT64(data);
173 Write(&netData, 8);
174 }
175
176 // Visit
177 void
Visit(RequestMember * member,Data & data)178 RequestFlattener::Visit(RequestMember* member, Data& data)
179 {
180 WriteData(data.address, data.size);
181 }
182
183 // Visit
184 void
Visit(RequestMember * member,StringData & data)185 RequestFlattener::Visit(RequestMember* member, StringData& data)
186 {
187 WriteData(data.address, data.size);
188 }
189
190 // Visit
191 void
Visit(RequestMember * member,RequestMember & subMember)192 RequestFlattener::Visit(RequestMember* member, RequestMember& subMember)
193 {
194 subMember.ShowAround(this);
195 }
196
197 // Visit
198 void
Visit(RequestMember * member,FlattenableRequestMember & subMember)199 RequestFlattener::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
212 status_t
Write(const void * buffer,int32 size)213 RequestFlattener::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
226 status_t
Align(int32 align)227 RequestFlattener::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
250 status_t
WriteBool(bool data)251 RequestFlattener::WriteBool(bool data)
252 {
253 return Write(&data, 1);
254 }
255
256 // WriteInt32
257 status_t
WriteInt32(int32 data)258 RequestFlattener::WriteInt32(int32 data)
259 {
260 int32 netData = B_HOST_TO_BENDIAN_INT32(data);
261 return Write(&netData, 4);
262 }
263
264 // WriteData
265 status_t
WriteData(const void * buffer,int32 size)266 RequestFlattener::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
277 status_t
WriteString(const char * string)278 RequestFlattener::WriteString(const char* string)
279 {
280 int32 size = (string ? strlen(string) + 1 : 0);
281 return WriteData(string, size);
282 }
283
284