00001
00021 #include "config.h"
00022 #include "libnebular.hpp"
00023 #include "libnebular-plugin.hpp"
00024 #include "utils.hpp"
00025 #include "libnebular-extra.templates.hpp"
00026
00027 #include <map>
00028 #include <sstream>
00029 #include <algorithm>
00030
00031 #include <boost/lexical_cast.hpp>
00032 #include <boost/static_assert.hpp>
00033 #include <boost/functional/hash.hpp>
00034
00035 namespace libnebular{
00036 using namespace std;
00037
00038
00039
00040
00041 class Blob::Impl_{
00042 private:
00043 friend class Blob;
00044
00045 boost::shared_ptr<char> data;
00046 bool areDataCanBeReroomed;
00047 Integer dataSize, dataRoom;
00048
00049 Impl_():
00050 areDataCanBeReroomed(true),
00051 dataSize(0),
00052 dataRoom(0)
00053 {}
00054 public:
00055
00056 ~Impl_() {}
00057 };
00058
00059 char* Blob::getDataReadWrite(){
00060 if(!isEmpty(pimpl_->data) && !pimpl_->data.unique()){
00061
00062 boost::shared_ptr<char> dataOthers = pimpl_->data;
00063 pimpl_->data = boost::shared_ptr<char>();
00064
00065 prepareForSize(pimpl_->dataSize);
00066
00067 std::copy(
00068 dataOthers.get(),
00069 dataOthers.get()+pimpl_->dataSize,
00070 pimpl_->data.get()
00071 );
00072 }
00073
00074 return pimpl_->data.get();
00075 }
00076
00077 const char* Blob::getDataReadOnly() const{
00078 return pimpl_->data.get();
00079 }
00080
00081 size_t Blob::getDataHash() const{
00082 return boost::hash_range(
00083 getDataReadOnly(),
00084 getDataReadOnly() + getDataSize()
00085 );
00086 }
00087
00088 Integer Blob::getDataRoom() const{
00089 return pimpl_->dataRoom;
00090 }
00091
00092 void Blob::forsakeData(){
00093 if(!isEmpty(pimpl_->data) && !pimpl_->data.unique()){
00094 cleanupData();
00095 }
00096 }
00097
00098 void Blob::cleanupData(){
00099 pimpl_->data = boost::shared_ptr<char>();
00100 pimpl_->dataSize = 0;
00101 pimpl_->dataRoom = 0;
00102 pimpl_->areDataCanBeReroomed = true;
00103 }
00104
00105 Integer Blob::getDataSize() const{
00106 return pimpl_->dataSize;
00107 }
00108
00109 void Blob::setDataSize(Integer newSize){
00110 if(newSize > pimpl_->dataRoom){
00111 throw LIBNEBULAR_ERROR("In Blob: before setting new data size you should make sure that there is enough data room");
00112 }
00113 pimpl_->dataSize = newSize;
00114 }
00115
00116 void Blob::mAlloc(Integer newSize){
00117 pimpl_->data.reset(
00118 new char[newSize],
00119 boost::checked_array_deleter<char>()
00120 );
00121 pimpl_->dataRoom = newSize;
00122 pimpl_->areDataCanBeReroomed = true;
00123 }
00124 void Blob::attach(void *newMemory, Integer newDataRoom){
00125 pimpl_->data.reset(
00126 static_cast<char*>(newMemory),
00127 null_deleter()
00128 );
00129 pimpl_->dataRoom = newDataRoom;
00130 pimpl_->areDataCanBeReroomed = false;
00131 }
00132 void Blob::prepareForSize(Integer newDataSize){
00133 if(isCanBeReroomed()){
00135 mAlloc(newDataSize);
00136 }else{
00137 if(newDataSize > getDataRoom()){
00138 throw LIBNEBULAR_ERROR("Current ProbBlob cannot be reroomed");
00139 }else{
00140
00141 }
00142 }
00143 setDataSize(newDataSize);
00144 }
00145
00148 bool Blob::isCanBeReroomed() const{
00149 return pimpl_->areDataCanBeReroomed;
00150 }
00151
00152 void Blob::assign(Integer newSize, const char* newData){
00153 prepareForSize(newSize);
00154 std::copy(newData, newData+newSize, pimpl_->data.get());
00155 }
00156
00157 bool Blob::isSubseqFromCurPos(std::istream &inStream) const{
00158 char *curBlobChar = pimpl_->data.get();
00159 for(
00160 Integer index = 0;
00161 index < getDataSize();
00162 ++index
00163 ){
00164 char buf;
00165 inStream >> buf;
00166 if(buf != *curBlobChar){
00167 return false;
00168 }
00169
00170 ++curBlobChar;
00171 }
00172 return true;
00173 }
00174
00175 Blob::Blob():
00176 pimpl_(new Impl_)
00177 {
00178 BOOST_STATIC_ASSERT( sizeof(char) == 1 );
00179 }
00180
00181 Blob::Blob(Integer newSize, const char* newData):
00182 pimpl_(new Impl_)
00183 {
00184 BOOST_STATIC_ASSERT( sizeof(char) == 1 );
00185
00186 assign(newSize, newData);
00187 }
00188
00189 Blob::~Blob() {}
00190
00191 Blob Blob::createAndMAlloc(Integer newSize){
00192 Blob newBlob;
00193 newBlob.mAlloc(newSize);
00194 return newBlob;
00195 }
00196 Blob Blob::createAndAttach(void *newMemory, Integer newDataRoom){
00197 Blob newBlob;
00198 newBlob.attach(newMemory, newDataRoom);
00199 return newBlob;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 class PicturePropContainer::Impl_{
00209 public:
00215 class Property{
00216 private:
00217 enum ValueType{
00218 TYPE_NOT_SET,
00219 TYPE_PROP_STR,
00220 TYPE_PROP_BLOB
00221 } valueType;
00222
00223 struct Attribute{
00224 bool default_;
00225
00226 Attribute():
00227 default_(false)
00228 {}
00229
00230 Attribute(
00231 bool newDefault_
00232 ):
00233 default_(newDefault_)
00234 {}
00235 } attribute;
00236
00237 struct Placeholder{
00238 virtual ~Placeholder() {}
00239
00240 virtual Placeholder *clone() const = 0;
00241 };
00242
00243 template <typename T> struct Holder: public Placeholder{
00244 public:
00245 Holder(const T &newValue):
00246 held(newValue)
00247 {}
00248
00249 virtual Placeholder *clone() const{
00250 return new Holder(held);
00251 }
00252
00253 T held;
00254 };
00255
00256 Placeholder *content;
00257
00258 public:
00259 Property():
00260 valueType(TYPE_NOT_SET),
00261 attribute(),
00262 content(NULL)
00263 {}
00264
00265 Property(const Property &other):
00266 valueType(other.valueType),
00267 attribute(other.attribute),
00268 content(
00269 other.content ?
00270 other.content->clone() :
00271 NULL
00272 )
00273 {}
00274
00275 Property &swap(Property &rhs){
00276 std::swap(content, rhs.content);
00277 std::swap(attribute, rhs.attribute);
00278 std::swap(valueType, rhs.valueType);
00279 return (*this);
00280 }
00281
00282 Property &operator=(const Property &rhs){
00283 Property rhsCopy(rhs);
00284 swap(rhsCopy);
00285 return (*this);
00286 }
00287
00288 Property(
00289 const String &newValue,
00290 bool newIsDefault
00291 ):
00292 valueType(TYPE_PROP_STR),
00293 attribute(newIsDefault),
00294 content(new Holder<String>(newValue))
00295 {}
00296
00297 Property(
00298 const Blob &newValue,
00299 bool newIsDefault
00300 ):
00301 valueType(TYPE_PROP_BLOB),
00302 attribute(newIsDefault),
00303 content(new Holder<Blob>(newValue))
00304 {}
00305
00306 ~Property(){
00307 delete content;
00308 }
00309
00310 template <typename T> bool isTypedAs() const{
00311 return false;
00312 }
00313
00314 bool isDefault() const{
00315 return attribute.default_;
00316 }
00317
00318 void setDefault(bool newValue = true){
00319 attribute.default_ = newValue;
00320 }
00321
00322 template <typename R> R &getValueRef(){
00323 if(!isTypedAs<R>()){
00324 throw LIBNEBULAR_ERROR("Type of property have been chosen wrong");
00325 }
00326 return static_cast< Holder<R>* >(content)->held;
00327 }
00328
00329 template <typename R> const R getValue(){
00330 return getValueRef<R>();
00331 }
00332
00333 template <typename R> void setValue(const R &newValue){
00334 (getValueRef<R>()) = newValue;
00335 }
00336 };
00337
00338 public:
00339 virtual bool isSet(const String &key) const = 0;
00340 virtual void unSet(const String &key) = 0;
00341 virtual Property &getPropertyRef(const String &key) = 0;
00342 virtual void setProperty(const String &key, const Property &newValue) = 0;
00343
00344 void setDefault(const String &key, const String &value){
00345 setProperty(key, Property(value, true));
00346 }
00347
00348 virtual PropKeyIterator propKeyBegin() = 0;
00349 virtual PropKeyIterator propKeyEnd() = 0;
00350
00351 Impl_() {}
00352 virtual ~Impl_() {}
00353
00354 friend class PicturePropContainerSubtreeProxyImpl_;
00355 };
00356
00357 class PicturePropContainer::DefaultImpl_: public PicturePropContainer::Impl_{
00358 public:
00359 typedef map<String, Property> PropertyMap;
00360 private:
00361 PropertyMap propertyMap;
00362 public:
00363
00364 virtual bool isSet(const String &key) const{
00365 return
00366 propertyMap.find(key) != propertyMap.end();
00367 }
00368
00369 virtual void unSet(const String &key){
00370 size_t numErased =
00371 propertyMap.erase(key);
00372 if(numErased < 1){
00373 throw LIBNEBULAR_ERROR("\"PicturePropContainer\": attempt to access (and unset) non-existent property \"" + key + "\"");
00374 }
00375 }
00376
00377 virtual Property &getPropertyRef(const String &key){
00378 PropertyMap::iterator property = propertyMap.find(key);
00379 if(property != propertyMap.end()){
00380 return property->second;
00381 }else{
00382 throw LIBNEBULAR_ERROR("\"PicturePropContainer\": attempt to access to non-existent property \"" + key + "\"");
00383 }
00384 }
00385
00386 virtual void setProperty(const String &key, const Property &newValue){
00387 PropertyMap::iterator property = propertyMap.find(key);
00388 if(property != propertyMap.end()){
00389 property->second = newValue;
00390 }else{
00391 propertyMap[key] = newValue;
00392 }
00393 }
00394
00395 virtual PropKeyIterator propKeyBegin();
00396 virtual PropKeyIterator propKeyEnd();
00397
00398 DefaultImpl_() {}
00399 virtual ~DefaultImpl_() {}
00400 };
00401
00402
00403 class PicturePropContainer::PropKeyIterator::Impl_{
00404 private:
00405 friend class PicturePropContainer::PropKeyIterator;
00406
00407 typedef PicturePropContainer::DefaultImpl_::PropertyMap::iterator BaseIterator;
00408
00409 BaseIterator i;
00410
00411 public:
00413 static PicturePropContainer::PropKeyIterator toPropKeyIterator(
00414 BaseIterator newPluginListI
00415 ){
00416 PicturePropContainer::PropKeyIterator newPluginI;
00417 newPluginI.pimpl_->i = newPluginListI;
00418 return newPluginI;
00419 }
00420 };
00421
00422 template <> bool PicturePropContainer::Impl_::Property::isTypedAs<String>() const{
00423 return valueType == TYPE_PROP_STR;
00424 }
00425
00426 template <> bool PicturePropContainer::Impl_::Property::isTypedAs<Blob>() const{
00427 return valueType == TYPE_PROP_BLOB;
00428 }
00429
00430 template <> const String PicturePropContainer::Impl_::Property::getValue<String>(){
00431 if(!isTypedAs<Blob>()){
00432 return getValueRef<String>();
00433 }else{
00434 std::ostringstream streamOut;
00435 streamOut << "<Blob with hash value " << "0x" << hex << getValueRef<Blob>().getDataHash() << ">";
00436
00437 return streamOut.str();
00438 }
00439 }
00440
00441 PicturePropContainer::PropKeyIterator PicturePropContainer::DefaultImpl_::propKeyBegin(){
00442 return PicturePropContainer::PropKeyIterator::Impl_::toPropKeyIterator(
00443 propertyMap.begin()
00444 );
00445 }
00446 PicturePropContainer::PropKeyIterator PicturePropContainer::DefaultImpl_::propKeyEnd(){
00447 return PicturePropContainer::PropKeyIterator::Impl_::toPropKeyIterator(
00448 propertyMap.end()
00449 );
00450 }
00451
00452 void setDefault(
00453 PicturePropContainer &p,
00454 const String &key,
00455 const String &value
00456 ){
00457 p.pimpl_->setDefault(key, value);
00458 }
00459
00460 void PicturePropContainer::unSet(const String &key){
00461 pimpl_->unSet(key);
00462 }
00463
00464 void PicturePropContainer::move(const String &srcKey, const String &destKey){
00465 if(srcKey == destKey){
00466 return;
00467 }
00468
00469 pimpl_->setProperty(
00470 destKey,
00471 pimpl_->getPropertyRef(srcKey)
00472 );
00473 unSet(srcKey);
00474 }
00475
00476 bool PicturePropContainer::isSet(const String &key) const{
00477 return pimpl_->isSet(key);
00478 }
00479 bool PicturePropContainer::isDefault(const String &key) const{
00480 return pimpl_->getPropertyRef(key).isDefault();
00481 }
00482
00483 bool PicturePropContainer::isSetAndTrue(const String& key) const{
00484 return isSet(key) && get<bool>(key);
00485 }
00486
00487 void PicturePropContainer::acceptOpt(const String &acceptedKey){
00488 if(isSet(String("opt/") + acceptedKey)){
00489 move(String("opt/") + acceptedKey, acceptedKey);
00490 }
00491 }
00492
00493 void PicturePropContainer::setDefaultIfNotSet(const String &key, const String &defaultValue){
00494 if(!isSet(key)){
00495 setDefault(*this, key, defaultValue);
00496 }
00497 }
00498
00499 PicturePropContainer::PicturePropContainer():
00500 pimpl_(new DefaultImpl_)
00501 {}
00502
00503 PicturePropContainer::~PicturePropContainer() {}
00504
00505 String PicturePropContainer::castToPropString(
00506 const char *value
00507 ){
00508 return String(value);
00509 }
00510
00511 template<>
00512 String PicturePropContainer::castToPropString(const bool& arg)
00513 {
00514 std::ostringstream tmpOut;
00515 tmpOut << std::boolalpha << arg;
00516 return tmpOut.str();
00517 }
00518
00519 template<>
00520 bool PicturePropContainer::castFromPropString(const String& arg)
00521 {
00522 std::istringstream tmpOut(arg);
00523 bool result;
00524 tmpOut >> std::boolalpha >> result;
00525 return result;
00526 }
00527
00528 template<> const String PicturePropContainer::get<>(
00529 const String &key
00530 ) const{
00531 return pimpl_->getPropertyRef(key).getValue<String>();
00532 }
00533 template<> void PicturePropContainer::set<>(
00534 const String &key, const String &value
00535 ){
00536 pimpl_->setProperty(key, Impl_::Property(value, false));
00537 }
00538 template<> const Blob PicturePropContainer::get<>(
00539 const String &key
00540 ) const{
00541 return pimpl_->getPropertyRef(key).getValue<Blob>();
00542 }
00543 template<> void PicturePropContainer::set<>(
00544 const String &key, const Blob &value
00545 ){
00546 pimpl_->setProperty(key, Impl_::Property(value, false));
00547 }
00548
00549
00550
00552 #if !PROCESSED_BY_DOXYGEN
00553 template String PicturePropContainer::castToPropString(const String &);
00554 template String PicturePropContainer::castToPropString(const Integer &);
00555 template String PicturePropContainer::castToPropString(const Real &);
00556 template String PicturePropContainer::castToPropString(const bool &);
00557
00558 template String PicturePropContainer::castToPropString(const HexInteger<Integer> &);
00559
00560 #endif // PROCESSED_BY_DOXYGEN
00561
00562 template String PicturePropContainer::castFromPropString(const String &);
00563 template Integer PicturePropContainer::castFromPropString(const String &);
00564 template Real PicturePropContainer::castFromPropString(const String &);
00565 template bool PicturePropContainer::castFromPropString(const String &);
00566
00567 template int16_t PicturePropContainer::castFromPropString(const String &);
00568 template int32_t PicturePropContainer::castFromPropString(const String &);
00569 template uint16_t PicturePropContainer::castFromPropString(const String &);
00570 template uint32_t PicturePropContainer::castFromPropString(const String &);
00571
00572
00573
00574
00575
00576
00577 PicturePropContainer::PropKeyIterator::PropKeyIterator():
00578 pimpl_(new Impl_)
00579 {}
00580 PicturePropContainer::PropKeyIterator::~PropKeyIterator() {}
00581
00582
00583 PicturePropContainer::PropKeyIterator::PropKeyIterator(
00584 const PicturePropContainer::PropKeyIterator &src
00585 ):
00586 pimpl_(new Impl_)
00587 {
00588 (*this) = src;
00589 }
00590 PicturePropContainer::PropKeyIterator& PicturePropContainer::PropKeyIterator::operator=(
00591 const PicturePropContainer::PropKeyIterator &src
00592 ){
00593 (pimpl_->i) = (src.pimpl_->i);
00594 return *this;
00595 }
00596
00597 PicturePropContainer::PropKeyIterator& PicturePropContainer::PropKeyIterator::operator++(){
00598 ++( pimpl_->i );
00599 return *this;
00600 }
00601 PicturePropContainer::PropKeyIterator PicturePropContainer::PropKeyIterator::operator++(int){
00602 PropKeyIterator prevThis = *this;
00603 ( pimpl_->i )++;
00604 return prevThis;
00605 }
00606
00607 bool PicturePropContainer::PropKeyIterator::operator!=(const PicturePropContainer::PropKeyIterator &b) const{
00608 return ( pimpl_->i != b.pimpl_->i );
00609 }
00610 bool PicturePropContainer::PropKeyIterator::operator==(const PicturePropContainer::PropKeyIterator &b) const{
00611 return ( pimpl_->i == b.pimpl_->i );
00612 }
00613 PicturePropContainer::PropKeyIterator::value_type& PicturePropContainer::PropKeyIterator::operator*(){
00614 return pimpl_->i->first;
00615 }
00616 PicturePropContainer::PropKeyIterator::value_type* PicturePropContainer::PropKeyIterator::operator->(){
00617 return &(pimpl_->i->first);
00618 }
00619
00620
00621 PicturePropContainer::PropKeyIterator PicturePropContainer::propKeyBegin(){
00622 return pimpl_->propKeyBegin();
00623 }
00624 PicturePropContainer::PropKeyIterator PicturePropContainer::propKeyEnd(){
00625 return pimpl_->propKeyEnd();
00626 }
00627
00628
00629
00630 class PicturePropContainer::SubtreeProxyImpl_: public PicturePropContainer::Impl_{
00631 private:
00632 boost::shared_ptr<PicturePropContainer::Impl_> realSubject;
00633 String subTreePrefix;
00634
00636 class SpecialPrefixOrderLess: std::binary_function<const String&, const String&, bool>{
00637 private:
00638 const String prefix;
00639
00640 public:
00641 SpecialPrefixOrderLess(const String &newPrefix):
00642 prefix(newPrefix)
00643 {}
00644
00645 bool operator()(const String &a, const String &b){
00646 return
00647 a.substr(0, prefix.length()) <= prefix &&
00648 b.substr(0, prefix.length()) > prefix
00649 ;
00650 }
00651 };
00652
00653 public:
00654 virtual bool isSet(const String &key) const{
00655 return realSubject->isSet(subTreePrefix+key);
00656 }
00657
00658 virtual void unSet(const String &key){
00659 return realSubject->unSet(subTreePrefix+key);
00660 }
00661
00662 virtual Property &getPropertyRef(const String &key){
00663 return realSubject->getPropertyRef(subTreePrefix+key);
00664 }
00665
00666 virtual void setProperty(const String &key, const Property &newValue){
00667 return realSubject->setProperty(subTreePrefix+key, newValue);
00668 }
00669
00672 virtual PropKeyIterator propKeyBegin(){
00673 PropKeyIterator firstGtThanPrefix = std::lower_bound(
00674 realSubject->propKeyBegin(),
00675 realSubject->propKeyEnd(),
00676 subTreePrefix
00677 );
00678 if(
00679 firstGtThanPrefix != realSubject->propKeyEnd() &&
00680 firstGtThanPrefix->substr(0, subTreePrefix.length()) == subTreePrefix
00681 ){
00682 return firstGtThanPrefix;
00683 }else{
00684 return realSubject->propKeyEnd();
00685 }
00686 }
00687
00688 virtual PropKeyIterator propKeyEnd(){
00689 return std::upper_bound(
00690 realSubject->propKeyBegin(),
00691 realSubject->propKeyEnd(),
00692 subTreePrefix,
00693 SpecialPrefixOrderLess(subTreePrefix)
00694 );
00695 }
00696
00697 SubtreeProxyImpl_(
00698 PicturePropContainer &newRealSubject,
00699 const String &newSubTreePrefix
00700 ):
00701 realSubject(newRealSubject.pimpl_),
00702 subTreePrefix(newSubTreePrefix)
00703 {}
00704 virtual ~SubtreeProxyImpl_() {}
00705 };
00706
00707 template <class PicturePropContainerBased>
00708 boost::shared_ptr<PicturePropContainerBased>
00709 createSubtreeProxy(
00710 PicturePropContainer &realSubject,
00711 const String &subTreePrefix
00712 ){
00713 boost::shared_ptr<PicturePropContainerBased> proxy(new PicturePropContainerBased);
00714 proxy->PicturePropContainer::pimpl_ = boost::shared_ptr<PicturePropContainer::Impl_>(
00715 new PicturePropContainer::SubtreeProxyImpl_(
00716 realSubject,
00717 subTreePrefix
00718 )
00719 );
00720
00721 return proxy;
00722 }
00723
00724
00725 template boost::shared_ptr<PicturePropContainer> createSubtreeProxy<PicturePropContainer>(
00726 PicturePropContainer &realSubject,
00727 const String &subTreePrefix
00728 );
00729 template boost::shared_ptr<PictureProps> createSubtreeProxy<PictureProps>(
00730 PicturePropContainer &realSubject,
00731 const String &subTreePrefix
00732 );
00733 template boost::shared_ptr<Picture> createSubtreeProxy<Picture>(
00734 PicturePropContainer &realSubject,
00735 const String &subTreePrefix
00736 );
00737 }