value_ops.cc
Go to the documentation of this file.
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 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:41