xref: /haiku/src/add-ons/kernel/file_systems/netfs/shared/RequestFlattener.cpp (revision 5a1d355fdf2747f80f8c46e2539f844a0b813346)
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