$search
00001 #include <typelib/value_ops.hh> 00002 #include <string.h> 00003 #include <boost/lexical_cast.hpp> 00004 #include <iostream> 00005 #include "value_ops_details.hh" 00006 #include <cstdio> 00007 00008 using namespace Typelib; 00009 using namespace boost; 00010 using namespace std; 00011 00012 void Typelib::display(std::ostream& io, MemoryLayout::const_iterator const begin, MemoryLayout::const_iterator const end) 00013 { 00014 io << "displaying memory layout of size " << end - begin << "\n"; 00015 for (MemoryLayout::const_iterator it = begin; it != end; ++it) 00016 { 00017 switch(*it) 00018 { 00019 case MemLayout::FLAG_MEMCPY: 00020 { 00021 size_t size = *(++it); 00022 io << "MEMCPY " << size << "\n"; 00023 break; 00024 } 00025 case MemLayout::FLAG_ARRAY: 00026 { 00027 size_t element_count = *(++it); 00028 io << "ARRAY " << element_count << "\n"; 00029 break; 00030 } 00031 case MemLayout::FLAG_SKIP: 00032 { 00033 size_t size = *(++it); 00034 io << "SKIP " << size << "\n"; 00035 break; 00036 } 00037 case MemLayout::FLAG_CONTAINER: 00038 { 00039 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00040 io << "CONTAINER " << type->getName() << "\n"; 00041 break; 00042 } 00043 case MemLayout::FLAG_END: 00044 { 00045 io << "END\n"; 00046 break; 00047 } 00048 default: 00049 { 00050 io << "in display(): unrecognized marshalling bytecode " << *it << " at " << (it - begin) << "\n"; 00051 throw UnknownLayoutBytecode(); 00052 } 00053 } 00054 } 00055 00056 } 00057 00058 00059 tuple<size_t, MemoryLayout::const_iterator> ValueOps::dump( 00060 uint8_t const* data, size_t in_offset, 00061 OutputStream& stream, MemoryLayout::const_iterator const begin, MemoryLayout::const_iterator const end) 00062 { 00063 MemoryLayout::const_iterator it; 00064 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00065 { 00066 switch(*it) 00067 { 00068 case MemLayout::FLAG_MEMCPY: 00069 { 00070 size_t size = *(++it); 00071 stream.write(data + in_offset, size); 00072 in_offset += size; 00073 break; 00074 } 00075 case MemLayout::FLAG_ARRAY: 00076 { 00077 size_t element_count = *(++it); 00078 MemoryLayout::const_iterator element_it = ++it; 00079 if (element_count == 0) 00080 it = MemLayout::skip_block(element_it, end); 00081 else 00082 { 00083 for (size_t i = 0; i < element_count; ++i) 00084 tie(in_offset, it) = dump(data, in_offset, stream, element_it, end); 00085 } 00086 00087 if (it == end || *it != MemLayout::FLAG_END) 00088 throw std::runtime_error("error in the marshalling bytecode: array does not end with FLAG_END"); 00089 00090 break; 00091 } 00092 case MemLayout::FLAG_SKIP: 00093 { 00094 size_t size = *(++it); 00095 in_offset += size; 00096 break; 00097 } 00098 case MemLayout::FLAG_CONTAINER: 00099 { 00100 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00101 // First, dump the element count into the stream 00102 void const* container_ptr = data + in_offset; 00103 in_offset += type->getSize(); 00104 00105 uint64_t element_count = type->getElementCount(container_ptr); 00106 stream.write(reinterpret_cast<uint8_t*>(&element_count), sizeof(element_count)); 00107 00108 if (element_count == 0) 00109 it = MemLayout::skip_block(++it, end); 00110 else 00111 it = type->dump(container_ptr, element_count, stream, ++it, end); 00112 00113 if (it == end || *it != MemLayout::FLAG_END) 00114 throw std::runtime_error("error in bytecode while dumping: container does not end with FLAG_END"); 00115 break; 00116 } 00117 default: 00118 throw UnknownLayoutBytecode(); 00119 } 00120 } 00121 00122 return make_tuple(in_offset, it); 00123 } 00124 00125 tuple<size_t, MemoryLayout::const_iterator> ValueOps::load( 00126 uint8_t* data, size_t out_offset, 00127 InputStream& stream, MemoryLayout::const_iterator const begin, MemoryLayout::const_iterator const end) 00128 { 00129 MemoryLayout::const_iterator it; 00130 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00131 { 00132 switch(*it) 00133 { 00134 case MemLayout::FLAG_MEMCPY: 00135 { 00136 size_t size = *(++it); 00137 stream.read(data + out_offset, size); 00138 out_offset += size; 00139 break; 00140 } 00141 case MemLayout::FLAG_ARRAY: 00142 { 00143 size_t element_count = *(++it); 00144 MemoryLayout::const_iterator element_it = ++it; 00145 00146 if (element_count == 0) 00147 it = MemLayout::skip_block(element_it, end); 00148 else 00149 { 00150 for (size_t i = 0; i < element_count; ++i) 00151 tie(out_offset, it) = 00152 load(data, out_offset, stream, element_it, end); 00153 } 00154 00155 if (*it != MemLayout::FLAG_END) 00156 throw std::runtime_error("bytecode error in load(): array does not end with FLAG_END"); 00157 00158 break; 00159 } 00160 case MemLayout::FLAG_SKIP: 00161 { 00162 size_t size = *(++it); 00163 out_offset += size; 00164 break; 00165 } 00166 case MemLayout::FLAG_CONTAINER: 00167 { 00168 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00169 void* container_ptr = data + out_offset; 00170 type->init(container_ptr); 00171 out_offset += type->getSize(); 00172 00173 uint64_t element_count; 00174 stream.read(reinterpret_cast<uint8_t*>(&element_count), sizeof(uint64_t)); 00175 if (element_count == 0) 00176 it = MemLayout::skip_block(++it, end); 00177 else 00178 { 00179 it = type->load(container_ptr, element_count, stream, ++it, end); 00180 } 00181 00182 if (it == end || *it != MemLayout::FLAG_END) 00183 throw std::runtime_error("bytecode error in load(): container does not end with FLAG_END"); 00184 break; 00185 } 00186 default: 00187 throw UnknownLayoutBytecode(); 00188 } 00189 } 00190 00191 return make_tuple(out_offset, it); 00192 } 00193 00194 00195 void Typelib::init(Value v) 00196 { 00197 MemoryLayout ops = layout_of(v.getType(), true); 00198 init(v, ops); 00199 } 00200 00201 void Typelib::init(Value v, MemoryLayout const& ops) 00202 { 00203 uint8_t* buffer = reinterpret_cast<uint8_t*>(v.getData()); 00204 init(buffer, ops); 00205 } 00206 00207 void Typelib::init(uint8_t* data, MemoryLayout const& ops) 00208 { 00209 ValueOps::init(data, ops.begin(), ops.end()); 00210 } 00211 00212 void Typelib::zero(Value v) 00213 { 00214 MemoryLayout ops = layout_of(v.getType(), true); 00215 zero(v, ops); 00216 } 00217 00218 void Typelib::zero(Value v, MemoryLayout const& ops) 00219 { 00220 uint8_t* buffer = reinterpret_cast<uint8_t*>(v.getData()); 00221 zero(buffer, ops); 00222 } 00223 00224 void Typelib::zero(uint8_t* data, MemoryLayout const& ops) 00225 { 00226 ValueOps::zero(data, ops.begin(), ops.end()); 00227 } 00228 00229 void Typelib::destroy(Value v) 00230 { 00231 uint8_t* buffer = reinterpret_cast<uint8_t*>(v.getData()); 00232 MemoryLayout ops = layout_of(v.getType(), true); 00233 destroy(buffer, ops); 00234 } 00235 00236 void Typelib::destroy(Value v, MemoryLayout const& ops) 00237 { 00238 destroy(reinterpret_cast<uint8_t*>(v.getData()), ops); 00239 } 00240 00241 void Typelib::destroy(uint8_t* data, MemoryLayout const& ops) 00242 { 00243 ValueOps::destroy(data, ops.begin(), ops.end()); 00244 } 00245 00246 void Typelib::copy(Value dst, Value src) 00247 { 00248 if (dst.getType() != src.getType()) 00249 throw std::runtime_error("requested copy with incompatible types"); 00250 00251 copy(dst.getData(), src.getData(), src.getType()); 00252 } 00253 00254 void Typelib::copy(void* dst, void* src, Type const& type) 00255 { 00256 if (dst == src) 00257 { 00258 // same object, nothing to do 00259 return; 00260 } 00261 00262 uint8_t* out_buffer = reinterpret_cast<uint8_t*>(dst); 00263 uint8_t* in_buffer = reinterpret_cast<uint8_t*>(src); 00264 MemoryLayout ops = layout_of(type); 00265 ValueOps::copy(out_buffer, in_buffer, ops.begin(), ops.end()); 00266 } 00267 00268 bool Typelib::compare(Value dst, Value src) 00269 { 00270 if (!dst.getType().canCastTo(src.getType())) 00271 return false; 00272 00273 return compare(dst.getData(), src.getData(), dst.getType()); 00274 } 00275 00276 bool Typelib::compare(void* dst, void* src, Type const& type) 00277 { 00278 uint8_t* out_buffer = reinterpret_cast<uint8_t*>(dst); 00279 uint8_t* in_buffer = reinterpret_cast<uint8_t*>(src); 00280 00281 MemoryLayout ret; 00282 MemLayout::Visitor visitor(ret); 00283 visitor.apply(type, false); 00284 00285 bool is_equal; 00286 tie(is_equal, tuples::ignore, tuples::ignore, tuples::ignore) = 00287 ValueOps::compare(out_buffer, in_buffer, ret.begin(), ret.end()); 00288 return is_equal; 00289 } 00290 00291 tuple<uint8_t*, MemoryLayout::const_iterator> 00292 Typelib::ValueOps::zero(uint8_t* buffer, 00293 MemoryLayout::const_iterator begin, 00294 MemoryLayout::const_iterator end) 00295 { 00296 00297 MemoryLayout::const_iterator it; 00298 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00299 { 00300 switch(*it) 00301 { 00302 case MemLayout::FLAG_MEMCPY: 00303 case MemLayout::FLAG_SKIP: 00304 { 00305 size_t size = *(++it); 00306 memset(buffer, 0, size); 00307 buffer += size; 00308 break; 00309 } 00310 00311 case MemLayout::FLAG_ARRAY: 00312 { 00313 size_t element_count = *(++it); 00314 MemoryLayout::const_iterator element_it = ++it; 00315 for (size_t i = 0; i < element_count; ++i) 00316 tie(buffer, it) = zero(buffer, element_it, end); 00317 00318 if (it == end || *it != MemLayout::FLAG_END) 00319 throw std::runtime_error("error in the marshalling bytecode at array end"); 00320 break; 00321 } 00322 00323 case MemLayout::FLAG_CONTAINER: 00324 { 00325 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00326 type->clear(buffer); 00327 it = MemLayout::skip_block(++it, end); 00328 buffer += type->getSize(); 00329 break; 00330 } 00331 00332 default: 00333 throw std::runtime_error("in zero(): unrecognized marshalling bytecode " + boost::lexical_cast<std::string>(*it)); 00334 } 00335 } 00336 00337 return make_tuple(buffer, it); 00338 } 00339 tuple<uint8_t*, MemoryLayout::const_iterator> 00340 Typelib::ValueOps::init(uint8_t* buffer, 00341 MemoryLayout::const_iterator begin, 00342 MemoryLayout::const_iterator end) 00343 { 00344 00345 MemoryLayout::const_iterator it; 00346 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00347 { 00348 switch(*it) 00349 { 00350 case MemLayout::FLAG_MEMCPY: 00351 case MemLayout::FLAG_SKIP: 00352 { 00353 buffer += *(++it); 00354 break; 00355 } 00356 00357 case MemLayout::FLAG_ARRAY: 00358 { 00359 size_t element_count = *(++it); 00360 MemoryLayout::const_iterator element_it = ++it; 00361 for (size_t i = 0; i < element_count; ++i) 00362 tie(buffer, it) = init(buffer, element_it, end); 00363 00364 if (it == end || *it != MemLayout::FLAG_END) 00365 throw std::runtime_error("error in the marshalling bytecode at array end"); 00366 break; 00367 } 00368 00369 case MemLayout::FLAG_CONTAINER: 00370 { 00371 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00372 type->init(buffer); 00373 it = MemLayout::skip_block(++it, end); 00374 buffer += type->getSize(); 00375 break; 00376 } 00377 00378 default: 00379 throw std::runtime_error("in init(): unrecognized marshalling bytecode " + boost::lexical_cast<std::string>(*it)); 00380 } 00381 } 00382 00383 return make_tuple(buffer, it); 00384 } 00385 00386 tuple<uint8_t*, MemoryLayout::const_iterator> 00387 Typelib::ValueOps::destroy(uint8_t* buffer, 00388 MemoryLayout::const_iterator begin, 00389 MemoryLayout::const_iterator end) 00390 { 00391 MemoryLayout::const_iterator it; 00392 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00393 { 00394 switch(*it) 00395 { 00396 case MemLayout::FLAG_MEMCPY: 00397 case MemLayout::FLAG_SKIP: 00398 { 00399 buffer += *(++it); 00400 break; 00401 } 00402 00403 case MemLayout::FLAG_ARRAY: 00404 { 00405 size_t element_count = *(++it); 00406 MemoryLayout::const_iterator element_it = ++it; 00407 for (size_t i = 0; i < element_count; ++i) 00408 tie(buffer, it) = destroy(buffer, element_it, end); 00409 00410 if (it == end || *it != MemLayout::FLAG_END) 00411 throw std::runtime_error("error in the marshalling bytecode at array end"); 00412 break; 00413 } 00414 00415 case MemLayout::FLAG_CONTAINER: 00416 { 00417 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00418 type->destroy(buffer); 00419 it = MemLayout::skip_block(it, end); 00420 buffer += type->getSize(); 00421 break; 00422 } 00423 00424 default: 00425 throw std::runtime_error("in destroy(): unrecognized marshalling bytecode " + boost::lexical_cast<std::string>(*it)); 00426 } 00427 } 00428 00429 return make_tuple(buffer, it); 00430 } 00431 00432 tuple<uint8_t*, uint8_t*, MemoryLayout::const_iterator> 00433 Typelib::ValueOps::copy(uint8_t* out_buffer, uint8_t* in_buffer, 00434 MemoryLayout::const_iterator begin, 00435 MemoryLayout::const_iterator end) 00436 { 00437 00438 MemoryLayout::const_iterator it; 00439 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00440 { 00441 switch(*it) 00442 { 00443 case MemLayout::FLAG_MEMCPY: 00444 { 00445 size_t size = *(++it); 00446 memcpy(out_buffer, in_buffer, size); 00447 out_buffer += size; 00448 in_buffer += size; 00449 break; 00450 } 00451 case MemLayout::FLAG_SKIP: 00452 { 00453 size_t size = *(++it); 00454 out_buffer += size; 00455 in_buffer += size; 00456 break; 00457 } 00458 case MemLayout::FLAG_ARRAY: 00459 { 00460 size_t element_count = *(++it); 00461 MemoryLayout::const_iterator element_it = ++it; 00462 for (size_t i = 0; i < element_count; ++i) 00463 tie(out_buffer, in_buffer, it) = 00464 copy(out_buffer, in_buffer, element_it, end); 00465 00466 if (it == end || *it != MemLayout::FLAG_END) 00467 throw std::runtime_error("error in the marshalling bytecode at array end"); 00468 break; 00469 } 00470 case MemLayout::FLAG_CONTAINER: 00471 { 00472 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00473 type->copy(out_buffer, in_buffer); 00474 it = MemLayout::skip_block(it, end); 00475 out_buffer += type->getSize(); 00476 in_buffer += type->getSize(); 00477 break; 00478 } 00479 default: 00480 throw std::runtime_error("in copy(): unrecognized marshalling bytecode " + boost::lexical_cast<std::string>(*it)); 00481 } 00482 } 00483 00484 return make_tuple(out_buffer, in_buffer, it); 00485 } 00486 00487 tuple<bool, uint8_t*, uint8_t*, MemoryLayout::const_iterator> 00488 Typelib::ValueOps::compare(uint8_t* out_buffer, uint8_t* in_buffer, 00489 MemoryLayout::const_iterator begin, 00490 MemoryLayout::const_iterator end) 00491 { 00492 00493 MemoryLayout::const_iterator it; 00494 for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it) 00495 { 00496 switch(*it) 00497 { 00498 case MemLayout::FLAG_MEMCPY: 00499 { 00500 size_t size = *(++it); 00501 if (memcmp(out_buffer, in_buffer, size)) 00502 return make_tuple(false, (uint8_t*)0, (uint8_t*)0, end); 00503 00504 out_buffer += size; 00505 in_buffer += size; 00506 break; 00507 } 00508 case MemLayout::FLAG_SKIP: 00509 { 00510 size_t size = *(++it); 00511 out_buffer += size; 00512 in_buffer += size; 00513 break; 00514 } 00515 case MemLayout::FLAG_ARRAY: 00516 { 00517 size_t element_count = *(++it); 00518 MemoryLayout::const_iterator element_it = ++it; 00519 for (size_t i = 0; i < element_count; ++i) 00520 { 00521 bool is_equal; 00522 tie(is_equal, out_buffer, in_buffer, it) = 00523 compare(out_buffer, in_buffer, element_it, end); 00524 if (!is_equal) 00525 return make_tuple(false, (uint8_t*)0, (uint8_t*)0, end); 00526 } 00527 00528 if (it == end || *it != MemLayout::FLAG_END) 00529 throw std::runtime_error("error in the marshalling bytecode at array end"); 00530 break; 00531 } 00532 case MemLayout::FLAG_CONTAINER: 00533 { 00534 Container const* type = reinterpret_cast<Container const*>(*(++it)); 00535 if (!type->compare(out_buffer, in_buffer)) 00536 return make_tuple(false, (uint8_t*)0, (uint8_t*)0, end); 00537 00538 it = MemLayout::skip_block(it, end); 00539 out_buffer += type->getSize(); 00540 in_buffer += type->getSize(); 00541 break; 00542 } 00543 default: 00544 throw std::runtime_error("in compare(): unrecognized marshalling bytecode " + boost::lexical_cast<std::string>(*it)); 00545 } 00546 } 00547 return make_tuple(true, out_buffer, in_buffer, it); 00548 } 00549 00550 00551 00552 std::vector<uint8_t> Typelib::dump(Value v) 00553 { 00554 std::vector<uint8_t> buffer; 00555 dump(v, buffer); 00556 return buffer; 00557 } 00558 00559 /*-------------------------------------------------- 00560 * Dump support to std::vector<uint8_t> 00561 */ 00562 struct VectorOutputStream : public OutputStream 00563 { 00564 std::vector<uint8_t>& buffer; 00565 VectorOutputStream(std::vector<uint8_t>& buffer) 00566 : buffer(buffer) {} 00567 00568 void write(uint8_t const* data, size_t size) 00569 { 00570 size_t out_index = buffer.size(); buffer.resize(out_index + size); 00571 memcpy(&buffer[out_index], data, size); 00572 } 00573 }; 00574 void Typelib::dump(Value v, std::vector<uint8_t>& buffer) 00575 { 00576 VectorOutputStream stream(buffer); 00577 return dump(v, stream); 00578 } 00579 void Typelib::dump(Value v, std::vector<uint8_t>& buffer, MemoryLayout const& ops) 00580 { 00581 VectorOutputStream stream(buffer); 00582 return dump(v, stream, ops); 00583 } 00584 void Typelib::dump(uint8_t const* v, std::vector<uint8_t>& buffer, MemoryLayout const& ops) 00585 { 00586 VectorOutputStream stream(buffer); 00587 return dump(v, stream, ops); 00588 } 00589 00590 /*-------------------------------------------------- 00591 * Dump support to std::ostream 00592 */ 00593 struct OstreamOutputStream : public OutputStream 00594 { 00595 std::ostream& stream; 00596 OstreamOutputStream(std::ostream& stream) 00597 : stream(stream) {} 00598 00599 void write(uint8_t const* data, size_t size) 00600 { 00601 stream.write(reinterpret_cast<char const*>(data), size); 00602 } 00603 }; 00604 void Typelib::dump(Value v, std::ostream& ostream) 00605 { 00606 OstreamOutputStream stream(ostream); 00607 return dump(v, stream); 00608 } 00609 void Typelib::dump(Value v, std::ostream& ostream, MemoryLayout const& ops) 00610 { 00611 OstreamOutputStream stream(ostream); 00612 return dump(v, stream, ops); 00613 } 00614 void Typelib::dump(uint8_t const* v, std::ostream& ostream, MemoryLayout const& ops) 00615 { 00616 OstreamOutputStream stream(ostream); 00617 return dump(v, stream, ops); 00618 } 00619 00620 00621 /*-------------------------------------------------- 00622 * Dump support to std::ostream 00623 */ 00624 struct FDOutputStream : public OutputStream 00625 { 00626 int fd; 00627 FDOutputStream(int fd) 00628 : fd(fd) {} 00629 00630 void write(uint8_t const* data, size_t size) 00631 { 00632 ::write(fd, data, size); 00633 } 00634 }; 00635 void Typelib::dump(Value v, int fd) 00636 { 00637 FDOutputStream stream(fd); 00638 return dump(v, stream); 00639 } 00640 void Typelib::dump(Value v, int fd, MemoryLayout const& ops) 00641 { 00642 FDOutputStream stream(fd); 00643 return dump(v, stream, ops); 00644 } 00645 void Typelib::dump(uint8_t const* v, int fd, MemoryLayout const& ops) 00646 { 00647 FDOutputStream stream(fd); 00648 return dump(v, stream, ops); 00649 } 00650 00651 00652 /*-------------------------------------------------- 00653 * Dump support to FILE 00654 */ 00655 struct FileOutputStream : public OutputStream 00656 { 00657 FILE* fd; 00658 FileOutputStream(FILE* fd) 00659 : fd(fd) {} 00660 00661 void write(uint8_t const* data, size_t size) 00662 { 00663 ::fwrite(data, size, 1, fd); 00664 } 00665 }; 00666 void Typelib::dump(Value v, FILE* fd) 00667 { 00668 FileOutputStream stream(fd); 00669 return dump(v, stream); 00670 } 00671 void Typelib::dump(Value v, FILE* fd, MemoryLayout const& ops) 00672 { 00673 FileOutputStream stream(fd); 00674 return dump(v, stream, ops); 00675 } 00676 void Typelib::dump(uint8_t const* v, FILE* fd, MemoryLayout const& ops) 00677 { 00678 FileOutputStream stream(fd); 00679 return dump(v, stream, ops); 00680 } 00681 00682 00683 /*-------------------------------------------------- 00684 * Dump support to a generic OutputStream instance 00685 */ 00686 void Typelib::dump(Value v, OutputStream& stream) 00687 { 00688 MemoryLayout ops; 00689 MemLayout::Visitor visitor(ops); 00690 visitor.apply(v.getType()); 00691 return dump(v, stream, ops); 00692 } 00693 void Typelib::dump(Value v, OutputStream& stream, MemoryLayout const& ops) 00694 { 00695 return dump(reinterpret_cast<uint8_t*>(v.getData()), stream, ops); 00696 } 00697 void Typelib::dump(uint8_t const* v, OutputStream& stream, MemoryLayout const& ops) 00698 { 00699 MemoryLayout::const_iterator end = ValueOps::dump( 00700 v, 0, stream, ops.begin(), ops.end()).get<1>(); 00701 if (end != ops.end()) 00702 throw std::runtime_error("internal error in the marshalling process"); 00703 } 00704 00705 00706 /*-------------------------------------------------- 00707 * Dump support to char* 00708 * 00709 * It is not using the generic dump() methods as it will return 0 on buffer 00710 * overrun or marshalling error, instead of throwing an exception 00711 */ 00712 struct ByteArrayOutputStream : public OutputStream 00713 { 00714 uint8_t* buffer; 00715 unsigned int buffer_size; 00716 unsigned int current; 00717 ByteArrayOutputStream(uint8_t* buffer, int buffer_size) 00718 : buffer(buffer), buffer_size(buffer_size), current(0) {} 00719 00720 void write(uint8_t const* data, size_t size) 00721 { 00722 if (current + size > buffer_size) 00723 throw std::exception(); 00724 00725 memcpy(&buffer[current], data, size); 00726 current += size; 00727 } 00728 }; 00729 int Typelib::dump(Value v, uint8_t* buffer, unsigned int buffer_size) 00730 { 00731 MemoryLayout ops; 00732 MemLayout::Visitor visitor(ops); 00733 visitor.apply(v.getType()); 00734 return dump(v, buffer, buffer_size, ops); 00735 } 00736 00737 int Typelib::dump(Value v, uint8_t* buffer, unsigned int buffer_size, MemoryLayout const& ops) 00738 { 00739 return dump(reinterpret_cast<uint8_t const*>(v.getData()), buffer, buffer_size, ops); 00740 } 00741 int Typelib::dump(uint8_t const* v, uint8_t* buffer, unsigned int buffer_size, MemoryLayout const& ops) 00742 { 00743 ByteArrayOutputStream stream(buffer, buffer_size); 00744 MemoryLayout::const_iterator end; 00745 try { 00746 end = ValueOps::dump( 00747 v, 0, stream, ops.begin(), ops.end()).get<1>(); 00748 } 00749 catch(std::exception const& e) { 00750 std::cout << "failed to marshal: " << e.what() << std::endl; 00751 return 0; 00752 } 00753 if (end != ops.end()) 00754 throw std::runtime_error("internal error in the marshalling process"); 00755 return stream.current; 00756 } 00757 00758 00759 00760 /*-------------------------------------------------- 00761 * Marshalling size calculations 00762 */ 00763 struct ByteCounterStream : public OutputStream 00764 { 00765 size_t result; 00766 ByteCounterStream() 00767 : result(0) {} 00768 00769 void write(uint8_t const* data, size_t size) 00770 { result += size; } 00771 }; 00772 size_t Typelib::getDumpSize(Value v) 00773 { 00774 MemoryLayout ops; 00775 MemLayout::Visitor visitor(ops); 00776 visitor.apply(v.getType()); 00777 return getDumpSize(v, ops); 00778 } 00779 size_t Typelib::getDumpSize(Value v, MemoryLayout const& ops) 00780 { return getDumpSize(reinterpret_cast<uint8_t const*>(v.getData()), ops); } 00781 size_t Typelib::getDumpSize(uint8_t const* v, MemoryLayout const& ops) 00782 { 00783 ByteCounterStream counter; 00784 ValueOps::dump(v, 0, counter, ops.begin(), ops.end()); 00785 return counter.result; 00786 } 00787 00788 00789 00790 00791 00792 00793 /*-------------------------------------------------- 00794 * Generic load support from InputStream 00795 */ 00796 void Typelib::load(Value v, InputStream& stream) 00797 { 00798 MemoryLayout ops = layout_of(v.getType()); 00799 return load(v, stream, ops); 00800 } 00801 void Typelib::load(Value v, InputStream& stream, MemoryLayout const& ops) 00802 { load(reinterpret_cast<uint8_t*>(v.getData()), v.getType(), stream, ops); } 00803 void Typelib::load(uint8_t* v, Type const& type, InputStream& stream, MemoryLayout const& ops) 00804 { 00805 MemoryLayout::const_iterator it; 00806 size_t out_offset; 00807 tie(out_offset, it) = 00808 ValueOps::load(v, 0, stream, ops.begin(), ops.end()); 00809 if (it != ops.end()) 00810 throw std::runtime_error("internal error in the memory layout"); 00811 } 00812 00813 /*-------------------------------------------------- 00814 * Load support from std::vector<uint8_t> 00815 */ 00816 struct VectorInputStream : public InputStream 00817 { 00818 std::vector<uint8_t> const& buffer; 00819 size_t in_index; 00820 00821 VectorInputStream(std::vector<uint8_t> const& buffer) 00822 : buffer(buffer), in_index(0) {} 00823 00824 void read(uint8_t* out_buffer, size_t size) 00825 { 00826 if (size + in_index > buffer.size()) 00827 throw std::runtime_error("error in load(): not enough data as input, expected at least " + lexical_cast<string>(size + in_index) + " bytes but got " + lexical_cast<string>(buffer.size())); 00828 00829 memcpy(&out_buffer[0], &buffer[in_index], size); 00830 in_index += size; 00831 } 00832 }; 00833 void Typelib::load(Value v, std::vector<uint8_t> const& buffer) 00834 { 00835 MemoryLayout ops = layout_of(v.getType()); 00836 return load(v, buffer, ops); 00837 } 00838 void Typelib::load(Value v, std::vector<uint8_t> const& buffer, MemoryLayout const& ops) 00839 { load(reinterpret_cast<uint8_t*>(v.getData()), v.getType(), buffer, ops); } 00840 void Typelib::load(uint8_t* v, Type const& type, std::vector<uint8_t> const& buffer, MemoryLayout const& ops) 00841 { 00842 MemoryLayout::const_iterator it; 00843 VectorInputStream stream(buffer); 00844 00845 size_t out_offset; 00846 tie(out_offset, it) = 00847 ValueOps::load(v, 0, stream, ops.begin(), ops.end()); 00848 if (it != ops.end()) 00849 throw std::runtime_error("internal error in the memory layout"); 00850 if (stream.in_index != buffer.size() && stream.in_index + type.getTrailingPadding() != buffer.size()) 00851 throw std::runtime_error("parts of the provided buffer has not been used (used " + 00852 lexical_cast<string>(stream.in_index) + " bytes, got " + lexical_cast<string>(buffer.size()) + "as input)"); 00853 } 00854 00855 00856 00857 00858 /*-------------------------------------------------- 00859 * Load support from uint8_t* 00860 */ 00861 struct ByteArrayInputStream : public InputStream 00862 { 00863 uint8_t const* buffer; 00864 unsigned int buffer_size; 00865 unsigned int in_index; 00866 00867 ByteArrayInputStream(uint8_t const* buffer, int buffer_size) 00868 : buffer(buffer), buffer_size(buffer_size), in_index(0) {} 00869 00870 void read(uint8_t* out_buffer, size_t size) 00871 { 00872 if (size + in_index > buffer_size) 00873 throw std::runtime_error("error in load(): not enough data as input, expected at least " + lexical_cast<string>(size + in_index) + " bytes but got " + lexical_cast<string>(buffer_size)); 00874 00875 memcpy(&out_buffer[0], &buffer[in_index], size); 00876 in_index += size; 00877 } 00878 }; 00879 void Typelib::load(Value v, uint8_t const* buffer, unsigned int buffer_size) 00880 { 00881 MemoryLayout ops = layout_of(v.getType()); 00882 return load(v, buffer, buffer_size, ops); 00883 } 00884 void Typelib::load(Value v, uint8_t const* buffer, unsigned int buffer_size, MemoryLayout const& ops) 00885 { load(reinterpret_cast<uint8_t*>(v.getData()), v.getType(), buffer, buffer_size, ops); } 00886 void Typelib::load(uint8_t* v, Type const& type, uint8_t const* buffer, unsigned int buffer_size, MemoryLayout const& ops) 00887 { 00888 MemoryLayout::const_iterator it; 00889 ByteArrayInputStream stream(buffer, buffer_size); 00890 00891 size_t out_offset; 00892 tie(out_offset, it) = 00893 ValueOps::load(v, 0, stream, ops.begin(), ops.end()); 00894 if (it != ops.end()) 00895 throw std::runtime_error("internal error in the memory layout"); 00896 if (stream.in_index != buffer_size && stream.in_index + type.getTrailingPadding() != buffer_size) 00897 throw std::runtime_error("parts of the provided buffer has not been used (used " + 00898 lexical_cast<string>(stream.in_index) + " bytes, got " + lexical_cast<string>(buffer_size) + "as input)"); 00899 } 00900 00901