1 // RequestFlattener.cpp 2 3 #include <ByteOrder.h> 4 5 #include "RequestFlattener.h" 6 7 // Writer 8 9 // constructor 10 Writer::Writer() 11 { 12 } 13 14 // destructor 15 Writer::~Writer() 16 { 17 } 18 19 // Pad 20 status_t 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 37 DataIOWriter::DataIOWriter(BDataIO* dataIO) 38 : Writer(), 39 fDataIO(dataIO) 40 { 41 } 42 43 // destructor 44 DataIOWriter::~DataIOWriter() 45 { 46 } 47 48 // Write 49 status_t 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 64 DummyWriter::DummyWriter() 65 { 66 } 67 68 // destructor 69 DummyWriter::~DummyWriter() 70 { 71 } 72 73 // Write 74 status_t 75 DummyWriter::Write(const void* buffer, int32 size) 76 { 77 return B_OK; 78 } 79 80 81 // RequestFlattener 82 83 // constructor 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 94 RequestFlattener::GetStatus() const 95 { 96 return fStatus; 97 } 98 99 // GetBytesWritten 100 int32 101 RequestFlattener::GetBytesWritten() const 102 { 103 return fBytesWritten; 104 } 105 106 // Visit 107 void 108 RequestFlattener::Visit(RequestMember* member, bool& data) 109 { 110 uint8 netData = (data ? ~0 : 0); 111 Write(&netData, 1); 112 } 113 114 // Visit 115 void 116 RequestFlattener::Visit(RequestMember* member, int8& data) 117 { 118 Write(&data, 1); 119 } 120 121 // Visit 122 void 123 RequestFlattener::Visit(RequestMember* member, uint8& data) 124 { 125 Write(&data, 1); 126 } 127 128 // Visit 129 void 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 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 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 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 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 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 178 RequestFlattener::Visit(RequestMember* member, Data& data) 179 { 180 WriteData(data.address, data.size); 181 } 182 183 // Visit 184 void 185 RequestFlattener::Visit(RequestMember* member, StringData& data) 186 { 187 WriteData(data.address, data.size); 188 } 189 190 // Visit 191 void 192 RequestFlattener::Visit(RequestMember* member, RequestMember& subMember) 193 { 194 subMember.ShowAround(this); 195 } 196 197 // Visit 198 void 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 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 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 251 RequestFlattener::WriteBool(bool data) 252 { 253 return Write(&data, 1); 254 } 255 256 // WriteInt32 257 status_t 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 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 278 RequestFlattener::WriteString(const char* string) 279 { 280 int32 size = (string ? strlen(string) + 1 : 0); 281 return WriteData(string, size); 282 } 283 284