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
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
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
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
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
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
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
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
00708
00709
00710
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
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
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
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
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