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 ValueOps::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 void Typelib::dump(Value v, std::vector<uint8_t>& buffer)
00560 {
00561 MemoryLayout ops;
00562 MemLayout::Visitor visitor(ops);
00563 visitor.apply(v.getType());
00564 return dump(v, buffer, ops);
00565 }
00566
00567 void Typelib::dump(Value v, std::vector<uint8_t>& buffer, MemoryLayout const& ops)
00568 {
00569 dump(reinterpret_cast<uint8_t const*>(v.getData()), buffer, ops);
00570 }
00571
00572 struct ByteArrayOutputStream : public ValueOps::OutputStream
00573 {
00574 uint8_t* buffer;
00575 unsigned int buffer_size;
00576 unsigned int current;
00577 ByteArrayOutputStream(uint8_t* buffer, int buffer_size)
00578 : buffer(buffer), buffer_size(buffer_size), current(0) {}
00579
00580 void write(uint8_t const* data, size_t size)
00581 {
00582 if (current + size > buffer_size)
00583 throw std::exception();
00584
00585 memcpy(&buffer[current], data, size);
00586 current += size;
00587 }
00588 };
00589
00590 int Typelib::dump(uint8_t const* v, uint8_t* buffer, unsigned int buffer_size, MemoryLayout const& ops)
00591 {
00592 ByteArrayOutputStream stream(buffer, buffer_size);
00593 MemoryLayout::const_iterator end;
00594 try {
00595 end = ValueOps::dump(
00596 v, 0, stream, ops.begin(), ops.end()).get<1>();
00597 }
00598 catch(std::exception const& e) {
00599 std::cout << "failed to marshal: " << e.what() << std::endl;
00600 return 0;
00601 }
00602 if (end != ops.end())
00603 throw std::runtime_error("internal error in the marshalling process");
00604 return stream.current;
00605 }
00606
00607 int Typelib::dump(Value v, uint8_t* buffer, unsigned int buffer_size)
00608 {
00609 MemoryLayout ops;
00610 MemLayout::Visitor visitor(ops);
00611 visitor.apply(v.getType());
00612 return dump(v, buffer, buffer_size, ops);
00613 }
00614
00615 int Typelib::dump(Value v, uint8_t* buffer, unsigned int buffer_size, MemoryLayout const& ops)
00616 {
00617 return dump(reinterpret_cast<uint8_t const*>(v.getData()), buffer, buffer_size, ops);
00618 }
00619
00620 struct VectorOutputStream : public ValueOps::OutputStream
00621 {
00622 std::vector<uint8_t>& buffer;
00623 VectorOutputStream(std::vector<uint8_t>& buffer)
00624 : buffer(buffer) {}
00625
00626 void write(uint8_t const* data, size_t size)
00627 {
00628 size_t out_index = buffer.size(); buffer.resize(out_index + size);
00629 memcpy(&buffer[out_index], data, size);
00630 }
00631 };
00632
00633 void Typelib::dump(uint8_t const* v, std::vector<uint8_t>& buffer, MemoryLayout const& ops)
00634 {
00635 VectorOutputStream stream(buffer);
00636 MemoryLayout::const_iterator end = ValueOps::dump(
00637 v, 0, stream, ops.begin(), ops.end()).get<1>();
00638 if (end != ops.end())
00639 throw std::runtime_error("internal error in the marshalling process");
00640 }
00641
00642
00643 void Typelib::dump(Value v, std::ostream& stream)
00644 {
00645 MemoryLayout ops;
00646 MemLayout::Visitor visitor(ops);
00647 visitor.apply(v.getType());
00648 return dump(v, stream, ops);
00649 }
00650
00651 void Typelib::dump(Value v, std::ostream& stream, MemoryLayout const& ops)
00652 {
00653 dump(reinterpret_cast<uint8_t const*>(v.getData()), stream, ops);
00654 }
00655
00656 struct OstreamOutputStream : public ValueOps::OutputStream
00657 {
00658 std::ostream& stream;
00659 OstreamOutputStream(std::ostream& stream)
00660 : stream(stream) {}
00661
00662 void write(uint8_t const* data, size_t size)
00663 {
00664 stream.write(reinterpret_cast<char const*>(data), size);
00665 }
00666 };
00667
00668 void Typelib::dump(uint8_t const* v, std::ostream& ostream, MemoryLayout const& ops)
00669 {
00670 OstreamOutputStream stream(ostream);
00671 MemoryLayout::const_iterator end = ValueOps::dump(
00672 v, 0, stream, ops.begin(), ops.end()).get<1>();
00673 if (end != ops.end())
00674 throw std::runtime_error("internal error in the marshalling process");
00675 }
00676
00677 void Typelib::dump(Value v, int fd)
00678 {
00679 MemoryLayout ops;
00680 MemLayout::Visitor visitor(ops);
00681 visitor.apply(v.getType());
00682 return dump(v, fd, ops);
00683 }
00684
00685 void Typelib::dump(Value v, int fd, MemoryLayout const& ops)
00686 {
00687 dump(reinterpret_cast<uint8_t const*>(v.getData()), fd, ops);
00688 }
00689
00690 struct FDOutputStream : public ValueOps::OutputStream
00691 {
00692 int fd;
00693 FDOutputStream(int fd)
00694 : fd(fd) {}
00695
00696 void write(uint8_t const* data, size_t size)
00697 {
00698 ::write(fd, data, size);
00699 }
00700 };
00701
00702 void Typelib::dump(uint8_t const* v, int fd, MemoryLayout const& ops)
00703 {
00704 FDOutputStream stream(fd);
00705 MemoryLayout::const_iterator end = ValueOps::dump(
00706 v, 0, stream, ops.begin(), ops.end()).get<1>();
00707 if (end != ops.end())
00708 throw std::runtime_error("internal error in the marshalling process");
00709 }
00710
00711 void Typelib::dump(Value v, FILE* fd)
00712 {
00713 MemoryLayout ops;
00714 MemLayout::Visitor visitor(ops);
00715 visitor.apply(v.getType());
00716 return dump(v, fd, ops);
00717 }
00718
00719 void Typelib::dump(Value v, FILE* fd, MemoryLayout const& ops)
00720 {
00721 dump(reinterpret_cast<uint8_t const*>(v.getData()), fd, ops);
00722 }
00723
00724 struct FileOutputStream : public ValueOps::OutputStream
00725 {
00726 FILE* fd;
00727 FileOutputStream(FILE* fd)
00728 : fd(fd) {}
00729
00730 void write(uint8_t const* data, size_t size)
00731 {
00732 ::fwrite(data, size, 1, fd);
00733 }
00734 };
00735
00736 void Typelib::dump(uint8_t const* v, FILE* fd, MemoryLayout const& ops)
00737 {
00738 FileOutputStream stream(fd);
00739 MemoryLayout::const_iterator end = ValueOps::dump(
00740 v, 0, stream, ops.begin(), ops.end()).get<1>();
00741 if (end != ops.end())
00742 throw std::runtime_error("internal error in the marshalling process");
00743 }
00744
00745
00746 struct ByteCounterStream : public ValueOps::OutputStream
00747 {
00748 size_t result;
00749 ByteCounterStream()
00750 : result(0) {}
00751
00752 void write(uint8_t const* data, size_t size)
00753 { result += size; }
00754 };
00755
00756 size_t Typelib::getDumpSize(Value v)
00757 {
00758 MemoryLayout ops;
00759 MemLayout::Visitor visitor(ops);
00760 visitor.apply(v.getType());
00761 return getDumpSize(v, ops);
00762 }
00763 size_t Typelib::getDumpSize(Value v, MemoryLayout const& ops)
00764 { return getDumpSize(reinterpret_cast<uint8_t const*>(v.getData()), ops); }
00765 size_t Typelib::getDumpSize(uint8_t const* v, MemoryLayout const& ops)
00766 {
00767 ByteCounterStream counter;
00768 ValueOps::dump(v, 0, counter, ops.begin(), ops.end());
00769 return counter.result;
00770 }
00771
00772
00773 struct VectorInputStream : public ValueOps::InputStream
00774 {
00775 std::vector<uint8_t> const& buffer;
00776 size_t in_index;
00777
00778 VectorInputStream(std::vector<uint8_t> const& buffer)
00779 : buffer(buffer), in_index(0) {}
00780
00781 void read(uint8_t* out_buffer, size_t size)
00782 {
00783 if (size + in_index > buffer.size())
00784 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()));
00785
00786 memcpy(&out_buffer[0], &buffer[in_index], size);
00787 in_index += size;
00788 }
00789 };
00790
00791 void Typelib::load(Value v, std::vector<uint8_t> const& buffer)
00792 {
00793 MemoryLayout ops = layout_of(v.getType());
00794 return load(v, buffer, ops);
00795 }
00796
00797 void Typelib::load(Value v, std::vector<uint8_t> const& buffer, MemoryLayout const& ops)
00798 { load(reinterpret_cast<uint8_t*>(v.getData()), v.getType(), buffer, ops); }
00799
00800 void Typelib::load(uint8_t* v, Type const& type, std::vector<uint8_t> const& buffer, MemoryLayout const& ops)
00801 {
00802 MemoryLayout::const_iterator it;
00803 VectorInputStream stream(buffer);
00804
00805 size_t out_offset;
00806 tie(out_offset, it) =
00807 ValueOps::load(v, 0, stream, ops.begin(), ops.end());
00808 if (it != ops.end())
00809 throw std::runtime_error("internal error in the memory layout");
00810 if (stream.in_index != buffer.size() && stream.in_index + type.getTrailingPadding() != buffer.size())
00811 throw std::runtime_error("parts of the provided buffer has not been used (used " +
00812 lexical_cast<string>(stream.in_index) + " bytes, got " + lexical_cast<string>(buffer.size()) + "as input)");
00813 }
00814
00815 struct ByteArrayInputStream : public ValueOps::InputStream
00816 {
00817 uint8_t const* buffer;
00818 unsigned int buffer_size;
00819 unsigned int in_index;
00820
00821 ByteArrayInputStream(uint8_t const* buffer, int buffer_size)
00822 : buffer(buffer), buffer_size(buffer_size), 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
00834 void Typelib::load(Value v, uint8_t const* buffer, unsigned int buffer_size)
00835 {
00836 MemoryLayout ops = layout_of(v.getType());
00837 return load(v, buffer, buffer_size, ops);
00838 }
00839
00840 void Typelib::load(Value v, uint8_t const* buffer, unsigned int buffer_size, MemoryLayout const& ops)
00841 { load(reinterpret_cast<uint8_t*>(v.getData()), v.getType(), buffer, buffer_size, ops); }
00842
00843 void Typelib::load(uint8_t* v, Type const& type, uint8_t const* buffer, unsigned int buffer_size, MemoryLayout const& ops)
00844 {
00845 MemoryLayout::const_iterator it;
00846 ByteArrayInputStream stream(buffer, buffer_size);
00847
00848 size_t out_offset;
00849 tie(out_offset, it) =
00850 ValueOps::load(v, 0, stream, ops.begin(), ops.end());
00851 if (it != ops.end())
00852 throw std::runtime_error("internal error in the memory layout");
00853 if (stream.in_index != buffer_size && stream.in_index + type.getTrailingPadding() != buffer_size)
00854 throw std::runtime_error("parts of the provided buffer has not been used (used " +
00855 lexical_cast<string>(stream.in_index) + " bytes, got " + lexical_cast<string>(buffer_size) + "as input)");
00856 }
00857
00858