value_ops.cc
Go to the documentation of this file.
00001 #include <boost/cstdint.hpp>
00002 #include <typelib/value_ops.hh>
00003 #include <string.h>
00004 #include <boost/lexical_cast.hpp>
00005 #include <iostream>
00006 #include "value_ops_details.hh"
00007 #include <cstdio>
00008 
00009 using namespace Typelib;
00010 using namespace boost;
00011 using namespace std;
00012 
00013 void Typelib::display(std::ostream& io, MemoryLayout::const_iterator const begin, MemoryLayout::const_iterator const end)
00014 {
00015     io << "displaying memory layout of size " << end - begin << "\n";
00016     for (MemoryLayout::const_iterator it = begin; it != end; ++it)
00017     {
00018         switch(*it)
00019         {
00020             case MemLayout::FLAG_MEMCPY:
00021             {
00022                 size_t size = *(++it);
00023                 io << "MEMCPY " << size << "\n";
00024                 break;
00025             }
00026             case MemLayout::FLAG_ARRAY:
00027             {
00028                 size_t element_count = *(++it);
00029                 io << "ARRAY " << element_count << "\n";
00030                 break;
00031             }
00032             case MemLayout::FLAG_SKIP:
00033             {
00034                 size_t size  = *(++it);
00035                 io << "SKIP " << size << "\n";
00036                 break;
00037             }
00038             case MemLayout::FLAG_CONTAINER:
00039             {
00040                 Container const* type = reinterpret_cast<Container const*>(*(++it));
00041                 io << "CONTAINER " << type->getName() << "\n";
00042                 break;
00043             }
00044             case MemLayout::FLAG_END:
00045             {
00046                 io << "END\n";
00047                 break;
00048             }
00049             default:
00050             {
00051                 io << "in display(): unrecognized marshalling bytecode " << *it << " at " << (it - begin) << "\n";
00052                 throw UnknownLayoutBytecode();
00053             }
00054         }
00055     }
00056 
00057 }
00058 
00059 
00060 tuple<size_t, MemoryLayout::const_iterator> ValueOps::dump(
00061         boost::uint8_t const* data, size_t in_offset,
00062         OutputStream& stream, MemoryLayout::const_iterator const begin, MemoryLayout::const_iterator const end)
00063 {
00064     MemoryLayout::const_iterator it;
00065     for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it)
00066     {
00067         switch(*it)
00068         {
00069             case MemLayout::FLAG_MEMCPY:
00070             {
00071                 size_t size = *(++it);
00072                 stream.write(data + in_offset, size);
00073                 in_offset += size;
00074                 break;
00075             }
00076             case MemLayout::FLAG_ARRAY:
00077             {
00078                 size_t element_count = *(++it);
00079                 MemoryLayout::const_iterator element_it = ++it;
00080                 if (element_count == 0)
00081                     it = MemLayout::skip_block(element_it, end);
00082                 else
00083                 {
00084                     for (size_t i = 0; i < element_count; ++i)
00085                         tie(in_offset, it) = dump(data, in_offset, stream, element_it, end);
00086                 }
00087 
00088                 if (it == end || *it != MemLayout::FLAG_END)
00089                     throw std::runtime_error("error in the marshalling bytecode: array does not end with FLAG_END");
00090 
00091                 break;
00092             }
00093             case MemLayout::FLAG_SKIP:
00094             {
00095                 size_t size  = *(++it);
00096                 in_offset += size;
00097                 break;
00098             }
00099             case MemLayout::FLAG_CONTAINER:
00100             {
00101                 Container const* type = reinterpret_cast<Container const*>(*(++it));
00102                 // First, dump the element count into the stream
00103                 void const* container_ptr  = data + in_offset;
00104                 in_offset += type->getSize();
00105 
00106                 boost::uint64_t element_count = type->getElementCount(container_ptr);
00107                 stream.write(reinterpret_cast< boost::uint8_t* >(&element_count), sizeof(element_count));
00108 
00109                 if (element_count == 0)
00110                     it = MemLayout::skip_block(++it, end);
00111                 else
00112                     it = type->dump(container_ptr, element_count, stream, ++it, end);
00113 
00114                 if (it == end || *it != MemLayout::FLAG_END)
00115                     throw std::runtime_error("error in bytecode while dumping: container does not end with FLAG_END");
00116                 break;
00117             }
00118             default:
00119                 throw UnknownLayoutBytecode();
00120         }
00121     }
00122 
00123     return make_tuple(in_offset, it);
00124 }
00125 
00126 tuple<size_t, MemoryLayout::const_iterator> ValueOps::load(
00127         boost::uint8_t* data, size_t out_offset,
00128         InputStream& stream, MemoryLayout::const_iterator const begin, MemoryLayout::const_iterator const end)
00129 {
00130     MemoryLayout::const_iterator it;
00131     for (it = begin; it != end && *it != MemLayout::FLAG_END; ++it)
00132     {
00133         switch(*it)
00134         {
00135             case MemLayout::FLAG_MEMCPY:
00136             {
00137                 size_t size = *(++it);
00138                 stream.read(data + out_offset, size);
00139                 out_offset += size;
00140                 break;
00141             }
00142             case MemLayout::FLAG_ARRAY:
00143             {
00144                 size_t element_count = *(++it);
00145                 MemoryLayout::const_iterator element_it = ++it;
00146 
00147                 if (element_count == 0)
00148                     it = MemLayout::skip_block(element_it, end);
00149                 else
00150                 {
00151                     for (size_t i = 0; i < element_count; ++i)
00152                         tie(out_offset, it) =
00153                             load(data, out_offset, stream, element_it, end);
00154                 }
00155 
00156                 if (*it != MemLayout::FLAG_END)
00157                     throw std::runtime_error("bytecode error in load(): array does not end with FLAG_END");
00158 
00159                 break;
00160             }
00161             case MemLayout::FLAG_SKIP:
00162             {
00163                 size_t size  = *(++it);
00164                 out_offset += size;
00165                 break;
00166             }
00167             case MemLayout::FLAG_CONTAINER:
00168             {
00169                 Container const* type = reinterpret_cast<Container const*>(*(++it));
00170                 void* container_ptr  = data + out_offset;
00171                 out_offset += type->getSize();
00172 
00173                 boost::uint64_t element_count;
00174                 stream.read(reinterpret_cast< boost::uint8_t* >(&element_count), sizeof( boost::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     boost::uint8_t* buffer = reinterpret_cast< boost::uint8_t* >(v.getData());
00204     init(buffer, ops);
00205 }
00206 
00207 void Typelib::init(boost::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     boost::uint8_t* buffer = reinterpret_cast< boost::uint8_t* >(v.getData());
00221     zero(buffer, ops);
00222 }
00223 
00224 void Typelib::zero(boost::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     boost::uint8_t* buffer = reinterpret_cast< boost::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< boost::uint8_t* >(v.getData()), ops);
00239 }
00240 
00241 void Typelib::destroy(boost::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     boost::uint8_t* out_buffer = reinterpret_cast< boost::uint8_t* >(dst);
00263     boost::uint8_t* in_buffer  = reinterpret_cast< boost::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     boost::uint8_t* out_buffer = reinterpret_cast< boost::uint8_t* >(dst);
00279     boost::uint8_t* in_buffer  = reinterpret_cast< boost::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< boost::uint8_t*, MemoryLayout::const_iterator>
00292     Typelib::ValueOps::zero(boost::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< boost::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< boost::uint8_t*, MemoryLayout::const_iterator>
00387     Typelib::ValueOps::destroy(boost::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< boost::uint8_t*, boost::uint8_t*, MemoryLayout::const_iterator>
00433     Typelib::ValueOps::copy(boost::uint8_t* out_buffer, boost::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, boost::uint8_t*, boost::uint8_t*, MemoryLayout::const_iterator>
00488     Typelib::ValueOps::compare(boost::uint8_t* out_buffer, boost::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, (boost::uint8_t*)0, (boost::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, (boost::uint8_t*)0, (boost::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, (boost::uint8_t*)0, (boost::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< boost::uint8_t > Typelib::dump(Value v)
00553 {
00554     std::vector< boost::uint8_t > buffer;
00555     dump(v, buffer);
00556     return buffer;
00557 }
00558 
00559 /*--------------------------------------------------
00560  * Dump support to std::vector< boost::uint8_t >
00561  */
00562 struct VectorOutputStream : public OutputStream
00563 {
00564     std::vector< boost::uint8_t >& buffer;
00565     VectorOutputStream(std::vector< boost::uint8_t >& buffer)
00566         : buffer(buffer) {}
00567 
00568     void write(boost::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< boost::uint8_t >& buffer)
00575 {
00576     VectorOutputStream stream(buffer);
00577     return dump(v, stream);
00578 }
00579 void Typelib::dump(Value v, std::vector< boost::uint8_t >& buffer, MemoryLayout const& ops)
00580 {
00581     VectorOutputStream stream(buffer);
00582     return dump(v, stream, ops);
00583 }
00584 void Typelib::dump( boost::uint8_t const* v, std::vector< boost::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(boost::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(boost::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(boost::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(boost::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(boost::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(boost::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< boost::uint8_t* >(v.getData()), stream, ops);
00696 }
00697 void Typelib::dump(boost::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     boost::uint8_t* buffer;
00715     unsigned int   buffer_size;
00716     unsigned int   current;
00717     ByteArrayOutputStream(boost::uint8_t* buffer, int buffer_size)
00718         : buffer(buffer), buffer_size(buffer_size), current(0) {}
00719 
00720     void write(boost::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, boost::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, boost::uint8_t* buffer, unsigned int buffer_size, MemoryLayout const& ops)
00738 {
00739     return dump(reinterpret_cast< boost::uint8_t const* >(v.getData()), buffer, buffer_size, ops);
00740 }
00741 int Typelib::dump(boost::uint8_t const* v, boost::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(boost::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< boost::uint8_t const* >(v.getData()), ops); }
00781 size_t Typelib::getDumpSize(boost::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< boost::uint8_t* >(v.getData()), v.getType(), stream, ops); }
00803 void Typelib::load(boost::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< boost::uint8_t >
00815  */
00816 struct VectorInputStream : public InputStream
00817 {
00818     std::vector< boost::uint8_t > const& buffer;
00819     size_t in_index;
00820 
00821     VectorInputStream(std::vector< boost::uint8_t > const& buffer)
00822         : buffer(buffer), in_index(0) {}
00823 
00824     void read(boost::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< boost::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< boost::uint8_t > const& buffer, MemoryLayout const& ops)
00839 { load(reinterpret_cast< boost::uint8_t* >(v.getData()), v.getType(), buffer, ops); }
00840 void Typelib::load(boost::uint8_t* v, Type const& type, std::vector< boost::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     boost::uint8_t const* buffer;
00864     unsigned int buffer_size;
00865     unsigned int in_index;
00866 
00867     ByteArrayInputStream(boost::uint8_t const* buffer, int buffer_size)
00868         : buffer(buffer), buffer_size(buffer_size), in_index(0) {}
00869 
00870     void read(boost::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, boost::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, boost::uint8_t const* buffer, unsigned int buffer_size, MemoryLayout const& ops)
00885 { load(reinterpret_cast< boost::uint8_t* >(v.getData()), v.getType(), buffer, buffer_size, ops); }
00886 void Typelib::load(boost::uint8_t* v, Type const& type, boost::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 Sat Jun 8 2019 18:49:22