00001
00025 #include "config.h"
00026 #include "libnebular.hpp"
00027 #include "libnebular-plugin.hpp"
00028 #include "utils.hpp"
00029 #include "libnebular-extra.templates.hpp"
00030
00031 #include <csetjmp>
00032
00033 #include <fstream>
00034
00035 #include <loki/Singleton.h>
00036
00037 #define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
00038 #include <loki/Functor.h>
00039
00040 namespace libnebular{
00041 using namespace std;
00042
00043 namespace bits{
00044 template Integer getHighestBitIndex<Integer>(Integer a);
00045 template Integer getContigLength<Integer>(Integer a);
00046 template bool areContig(Integer a);
00047 template bool areSubsetOf(Integer a, Integer b);
00048 template Integer generateContig<Integer>(Integer length);
00049 }
00050
00051 Error::Error(const std::string& msg):
00052 runtime_error(msg)
00053 {}
00054
00055 ThrowableError::ThrowableError(const std::string &msg):
00056 Error(std::string("<libnebular> ERROR: \n") + msg)
00057 {}
00058
00059
00060
00061 class Log::Impl_{
00062 private:
00063 friend class Log;
00064 friend class LogListener;
00065
00066 typedef Loki::SingletonHolder<
00067 Impl_
00068 > LogImplHolder;
00069
00070 typedef Loki::Functor<void, LOKI_TYPELIST_1(const string&)> CallbackStr;
00071
00072 CallbackStr warningCallback;
00073 CallbackStr infoCallback;
00074
00075 static Impl_ &get(){
00076 return LogImplHolder::Instance();
00077 }
00078
00079 public:
00080 Impl_():
00081 warningCallback(LogListener::emptyCallbackFunctionStr),
00082 infoCallback(LogListener::emptyCallbackFunctionStr)
00083 {}
00084
00085 ~Impl_() {}
00086 };
00087
00088 void Log::warning(const std::string &message){
00089 Impl_::get().warningCallback(message);
00090 }
00091
00092 void Log::info(const std::string &message){
00093 Impl_::get().infoCallback(message);
00094 }
00095
00096 void LogListener::setWarningCallback(LogListener::CallbackFunctionStr newWarningCallback){
00097 Log::Impl_::get().warningCallback = newWarningCallback;
00098 }
00099
00100 void LogListener::setWarningCallback(LogListener::CallbackStr newWarningCallback){
00101 Log::Impl_::get().warningCallback= newWarningCallback;
00102 }
00103
00104 void LogListener::setInfoCallback(LogListener::CallbackFunctionStr newInfoCallback){
00105 Log::Impl_::get().infoCallback = newInfoCallback;
00106 }
00107
00108 void LogListener::setInfoCallback(LogListener::CallbackStr newInfoCallback){
00109 Log::Impl_::get().infoCallback= newInfoCallback;
00110 }
00111
00112 void LogListener::emptyCallbackFunctionStr(const std::string &){
00113 }
00114
00115 NumberedStrings::NumberedStrings(Integer newNumStrings, const String *newTable):
00116 numStrings(newNumStrings),
00117 table(newTable)
00118 {}
00119
00120 NumberedStrings::~NumberedStrings()
00121 {}
00122
00123 Integer NumberedStrings::stringToIndex(const String &string) const{
00124 Integer index;
00125 for(
00126 index = 0;
00127 index < numStrings;
00128 index++
00129 ){
00130 if(String(table[index]) == string){
00131 return index;
00132 }
00133 }
00134 throw LIBNEBULAR_ERROR("Cannot convert string to index");
00135 }
00136
00137 const String NumberedStrings::indexToString(Integer index) const{
00138 if(index >= 0 && index <= numStrings){
00139 return String(table[index]);
00140 }else{
00141 throw LIBNEBULAR_ERROR("Cannot convert index to string");
00142 }
00143 }
00144
00145
00149
00150
00151 class PictureHandler;
00152
00153 class Picture::Impl_{
00154 private:
00155 friend class Picture;
00156
00157 Picture &picture;
00158 boost::shared_ptr<PictureHandler> aHandler;
00159
00163
00164 Impl_(Picture &newPicture):
00165 picture(newPicture),
00166 aHandler(boost::shared_ptr<PictureHandler>())
00167 {}
00168
00169 void attachChosenHandler(boost::shared_ptr<PictureHandler> newHandler){
00170 aHandler = newHandler;
00171 aHandler->setPicture(picture);
00172 }
00173
00174 void attachHandlerByPluginTest(
00175 bool (PicHandlerMgr::* test)(Picture&) const
00176 ){
00177 Core::get().makePluginsRegistered();
00178
00179 bool isFound = false;
00180 PluginIterator plugin;
00181 for(
00182 plugin = pluginBegin();
00183 plugin != pluginEnd();
00184 ++plugin
00185 ){
00186 isFound = ( (*plugin) .* test )(picture);
00187
00188 if(isFound){
00189 break;
00190 }
00191 }
00192 if(isFound){
00193 attachChosenHandler(
00194 plugin->createPictureHandler()
00195 );
00196 }else{
00197
00198 throw LIBNEBULAR_ERROR("Couldn\'t find appropriate file handler");
00199 }
00200 }
00201
00202 void detachFile(){
00203 boost::shared_ptr<PicturePropContainer> subtree =
00204 createSubtreeProxy<PicturePropContainer>(
00205 picture,
00206 "file/"
00207 );
00208 PicturePropContainer::PropKeyIterator key = subtree->propKeyBegin();
00209 while(key != subtree->propKeyEnd()){
00210 PicturePropContainer::PropKeyIterator prevKey = key;
00211 ++key;
00212 picture.unSet(*prevKey);
00213 }
00214 }
00215
00216 void detachBmSansData(){
00217 boost::shared_ptr<PicturePropContainer> subtree =
00218 createSubtreeProxy<PicturePropContainer>(
00219 picture,
00220 "bm/"
00221 );
00222 PicturePropContainer::PropKeyIterator key = subtree->propKeyBegin();
00223 while(key != subtree->propKeyEnd()){
00224 PicturePropContainer::PropKeyIterator prevKey = key;
00225 ++key;
00226 if(*prevKey != "bm/data"){
00227 picture.unSet(*prevKey);
00228 }
00229 }
00230 }
00231
00232 public:
00233 ~Impl_() {}
00234
00235 };
00236
00237 bool Picture::haveHandler() const{
00238 return (!isEmpty(pimpl_->aHandler));
00239 }
00240
00241
00243
00245
00246 void Picture::attachHandlerByFileExt(){
00247 pimpl_->attachHandlerByPluginTest(&PicHandlerMgr::isHandleableByFileExt);
00248 move("opt/file/url-extension", "file/url-extension");
00249 }
00250 void Picture::attachHandlerByContentMagic(){
00251 pimpl_->attachHandlerByPluginTest(&PicHandlerMgr::isHandleableByContentMagic);
00252 }
00253 void Picture::attachHandlerForWrite(){
00254 pimpl_->attachHandlerByPluginTest(&PicHandlerMgr::isWriteable);
00255 move("opt/file/mimetype", "file/mimetype");
00256 }
00257 void Picture::attachHandlerSomehow(){
00258 attachHandlerByContentMagic();
00259 }
00260 void Picture::makeHandlerSomehowAttached(){
00261 if(!haveHandler()){
00262 attachHandlerSomehow();
00263 }
00264 }
00265
00266
00267
00268 void Picture::readFileInfo(){
00269 pimpl_->detachFile();
00270 pimpl_->detachBmSansData();
00271 setDefaults();
00272
00273 makeHandlerSomehowAttached();
00274
00275 pimpl_->aHandler->readFileInfo();
00276
00277 move("opt/file/url", "file/url");
00278
00279 check<PropBmInfo>();
00280 checkUnusedOpts();
00281 set("file/loaded-info", true);
00282 }
00283
00284 void Picture::readBm(){
00285 if(
00286 !isSet("file/loaded-info") ||
00287 !get<bool>("file/loaded-info")
00288 ){
00289 readFileInfo();
00290 }
00291
00292 pimpl_->aHandler->readBm();
00293
00294 check<PropBmData>();
00295 checkUnusedOpts();
00296 set("file/loaded-bm-data", true);
00297 }
00298
00299 void Picture::write(){
00300 attachHandlerForWrite();
00301
00302 pimpl_->detachFile();
00303
00304 check<PropBmInfo>();
00305 check<PropBmData>();
00306
00307 pimpl_->aHandler->write();
00308
00309 move("opt/file/url", "file/url");
00310 checkUnusedOpts();
00311 }
00312
00313 Picture::~Picture() {}
00314 Picture::Picture():
00315 pimpl_( new Impl_(*this) )
00316 {}
00317
00318 Picture::Picture(const String& newUrl):
00319 pimpl_( new Impl_(*this) )
00320 {
00321 const String urlPropName = "opt/file/url";
00322 set(urlPropName, newUrl);
00323 }
00324
00325
00326
00327
00328
00329 PictureHandler::PictureHandler() {}
00330
00334 void PictureHandler::setPicture(Picture &newPic){
00335 pic = boost::shared_ptr<Picture>(
00336 &newPic,
00337 null_deleter()
00338 );
00339 }
00340
00341 PictureHandler::~PictureHandler(){
00343 }
00344
00345
00346
00348 void PicHandlerMgr::determineFileExt(Picture &pic){
00349 const String url = pic.get<String>("opt/file/url");
00350 size_t dotPos = url.rfind(".");
00351 if(dotPos != String::npos){
00352 pic.set("opt/file/url-extension",
00353 url.substr(dotPos+1)
00354 );
00355 }else{
00356 pic.set<String>("opt/file/url-extension",
00357 ""
00358 );
00359 }
00360 }
00361
00362 bool PicHandlerMgr::haveContentMagic(Picture &pictureFile, const Blob &magicData, Integer magicFileOffset){
00363 ifstream inStream(
00364 (pictureFile.get<String>("opt/file/url")).c_str(),
00365 ios::binary
00366 );
00367 if(inStream.fail()){
00368 throw LIBNEBULAR_ERROR("Failed to open file \"" + pictureFile.get<String>("opt/file/url") + "\"");
00369 }
00370 inStream.exceptions(ios::failbit | ios::badbit | ios::eofbit);
00371 inStream.seekg(magicFileOffset, ios::beg);
00372 return magicData.isSubseqFromCurPos(inStream);
00373 }
00374
00375 PicHandlerMgr::PicHandlerMgr() {}
00376 PicHandlerMgr::~PicHandlerMgr() {}
00377
00378
00379
00380
00381 RawCExceptionLongJmp::RawCExceptionLongJmp(
00382 Loki::Functor< void > newCleanupCode
00383 ):
00384 cleanupCode(newCleanupCode),
00385 isEnabled(false)
00386 {}
00387
00388 RawCExceptionLongJmp::~RawCExceptionLongJmp() {}
00389
00390 }
00391