Back to index

scribus-ng  1.3.4.dfsg+svn20071115
digester.h
Go to the documentation of this file.
00001 /*
00002  *  digester.h
00003  *  
00004  *
00005  *  Created by Andreas Vox on 02.06.06.
00006  *  Copyright 2006 under GPL2. All rights reserved.
00007  *
00008  */
00009 
00010 
00011 
00012 #ifndef DIGESTER_H
00013 #define DIGESTER_H
00014 
00015 #include <cassert>
00016 #include <iostream>
00017 #include <vector>
00018 #include <map>
00019 #include <string>
00020 #include <typeinfo>
00021 
00022 #include "desaxe_conf.h"
00023 #include "saxhandler.h"
00024 
00025 
00026 //#define DESAXE_DEBUG 1
00027 
00028 namespace desaxe {
00029        
00030 class Action;
00031 class RuleState;
00032 
00033 
00034 namespace PRIVATE {
00035        
00036        class VarPtr
00037        {
00038        public:
00039               void* ptr;
00040               std::string type;
00041        };
00042 
00043        
00044        template<class ObjType>
00045        inline
00046        VarPtr mkcell(ObjType* obj)
00047        {
00048               VarPtr result;
00049               result.ptr = obj;//  result.ptr = const_cast<void*>(static_cast<const void*>(obj)); //??
00050               result.type = typeid(obj).name();
00051               return result;
00052        }
00053        
00054        
00055        template<class ObjType>
00056        inline
00057        void chkcell(const VarPtr& cell, std::vector<VarPtr>* stack = NULL)
00058        {
00059               ObjType* dummy = NULL;
00060               if( cell.type != typeid(dummy).name() )
00061               {
00062                      std::cerr << "requested type '" << typeid(dummy).name() << "' doesnt match cell type '" << cell.type << "'\n";
00063                      if (stack)
00064                      {
00065                             int i=0;
00066                             std::vector<VarPtr>::iterator it;
00067                             for (it = stack->begin(); it != stack->end(); ++it)
00068                             {
00069                                    std::cerr << i++ << "\t" << (*it).type << "\t" << (*it).ptr << "\n";
00070                             }
00071                      }
00072                      assert (false);
00073               }
00074        }
00075        
00076 
00077 
00078 class Patch {
00079 public:
00080        // internal linked list
00081        Patch* next;
00082        Patch(Patch* nxt) : next(nxt) {}
00083        
00084        virtual void run(VarPtr lnk) = 0;
00085        virtual ~Patch() {}
00086 };
00087 
00088 
00089 } // namespace PRIVATE      
00090 
00091 
00092 
00100 class Digester : public SaxHandler {      
00101 public:
00102        Digester();
00103        Digester& operator=(const Digester& other);
00104        virtual ~Digester();
00105        void addRule(const Xml_string& pattern, Action action);
00106        
00107        void parseFile(const Xml_string& filename);
00108        void parseMemory(const char* data, unsigned int length);
00109        
00110        template<class ObjType>
00111               ObjType*  result();  
00112        int nrOfErrors() const;
00113        const Xml_string getError(int i) const;
00114        
00115 // called by SAX parser:
00116        void beginDoc();
00117        void endDoc();
00118        void begin(const Xml_string& tag, Xml_attr attr);
00119        void end(const Xml_string& tag);
00120        void chars(const Xml_string& text);
00121        
00122 // used by actions:
00123        void fail();
00124        void error(const Xml_string& msg);
00125        
00126        template<class ObjType>
00127        ObjType*  top(unsigned int offset = 0);
00128        
00129        template<class ObjType>
00130        ObjType*  bottom(unsigned int offset = 0);
00131        
00132        template<class ObjType>
00133        void setResult(      ObjType* res );
00134        
00135        void pop();
00136        void popn(unsigned int number);
00137        
00138        template<class ObjType>
00139        void push(ObjType* obj);
00140        
00141 //  used to resolve idrefs and for general storage      
00142        template<class ObjType>
00143               ObjType*  lookup(const Xml_string& idref);       
00144        template<class ObjType>
00145               void store(const Xml_string& idref, ObjType* res );
00146        
00147 //  used to resolve idrefs if use is before definition
00148        template<class LinkType>
00149               void patchCall(const Xml_string& idref, void (*fun)(LinkType*) );
00150        template<class ObjType, class LinkType>
00151               void patchInvoke(const Xml_string& idref, ObjType* obj, void (ObjType::*fun)(LinkType*) );
00152        
00153        // used to insert "/" where necessary
00154        static Xml_string concat(const Xml_string& pattern1, const Xml_string& pattern2);
00155 
00156 private:
00157        RuleState* 
00158               state;
00159        
00160        std::vector<PRIVATE::VarPtr> 
00161               objects;
00162        
00163        std::map<Xml_string, PRIVATE::VarPtr> 
00164               storage;
00165 
00166        std::map<Xml_string, PRIVATE::Patch*>
00167               patches;
00168        
00169        PRIVATE::VarPtr 
00170               result_;
00171        
00172        std::vector<Xml_string> 
00173               errors;
00174 };
00175 
00176 
00177 
00178 template<class ObjType>
00179 inline
00180 ObjType*  Digester::top(unsigned int offset) 
00181 {
00182 #ifdef DESAXE_DEBUG
00183        std::cerr << "top(" << offset << ") of " << objects.size() << "\n";
00184 #endif
00185        unsigned int count = objects.size();
00186        assert (offset < count); 
00187        PRIVATE::chkcell<ObjType>(objects[count - offset - 1], &objects);
00188 #ifdef DESAXE_DEBUG
00189        std::cerr << "stack-> " << static_cast<ObjType*>(objects[count - offset - 1].ptr) << "\n";
00190 #endif
00191        
00192        return static_cast<ObjType*>(objects[count - offset - 1].ptr);
00193 }
00194 
00195 
00196 template<class ObjType>
00197 inline
00198 ObjType*  Digester::bottom(unsigned int offset) 
00199 { 
00200 #ifdef DESAXE_DEBUG
00201        std::cerr << "bottom(" << offset << ") of " << objects.size() << "\n";
00202 #endif
00203        unsigned int count = objects.size();
00204        assert (offset < count); 
00205        PRIVATE::chkcell<ObjType> (objects[offset]);
00206        return static_cast<ObjType*>(objects[offset].ptr);
00207 }
00208 
00209 
00210 template<class ObjType>
00211 inline
00212 ObjType*  Digester::result() 
00213 { 
00214        ObjType* dummy = NULL;
00215        if (result_.type != typeid(dummy).name())
00216               return NULL;
00217 #ifdef DESAXE_DEBUG
00218        std::cerr << "result-> " << static_cast<ObjType*>(result_.ptr) << "\n";
00219 #endif
00220        return static_cast<ObjType*>(result_.ptr);
00221 }
00222 
00223 
00224 template<class ObjType>
00225 inline
00226 void Digester::setResult(ObjType* res) 
00227 { 
00228 #ifdef DESAXE_DEBUG
00229        std::cerr << res << " ->result\n";
00230 #endif
00231        result_ = PRIVATE::mkcell(res);
00232 }
00233 
00234 
00235 inline
00236 void Digester::pop()
00237 {
00238        unsigned int count = (unsigned int) objects.size();
00239        assert (1 <= count);
00240        objects.pop_back();
00241 }
00242 
00243 inline
00244 void Digester::popn(unsigned int number)
00245 {
00246        unsigned int count = (unsigned int) objects.size();
00247        assert (number <= count);
00248        objects.resize(count - number);
00249 }
00250 
00251 
00252 template<class ObjType>
00253 inline
00254 void Digester::push(ObjType* obj)
00255 {
00256 #ifdef DESAXE_DEBUG
00257        std::cerr << "stack<- " << obj << "\n";
00258 #endif
00259        objects.push_back(PRIVATE::mkcell(obj));
00260 }
00261 
00262 
00263 // now lookup / store / patch business
00264 
00265 namespace PRIVATE {
00266        
00267        template <class LinkType>
00268        struct Patch1 : public Patch
00269        {
00270               typedef void (*FunType1)(LinkType*);
00271               FunType1 fun;
00272               
00273               Patch1(FunType1 fn, Patch* nxt = NULL) : Patch(nxt), fun(fn) {}
00274               
00275               void run(VarPtr link) 
00276               { 
00277                      fun( static_cast<LinkType*>(link.ptr) ); 
00278               }
00279        };
00280        
00281        
00282        template <class ObjType, class LinkType>
00283               struct Patch2 : public Patch
00284        {
00285               typedef void (ObjType::*FunType2)(LinkType*);
00286               ObjType* obj;
00287               FunType2 fun;
00288               
00289               Patch2(ObjType* ob, FunType2 fn, Patch* nxt = NULL) : Patch(nxt), obj(ob), fun(fn) {}
00290 
00291               void run(VarPtr link)
00292               {
00293                      (obj->*fun)( static_cast<LinkType*>(link.ptr) ); 
00294               }
00295        };
00296        
00297        
00298        inline
00299        void runPatches(Patch*& list, VarPtr link)
00300        {
00301               while (list)
00302               {
00303                      Patch* nxt = list->next;
00304                      list->run(link);
00305                      delete list;
00306                      list = nxt;
00307               }
00308        }
00309        
00310        inline
00311        void deletePatches(std::map<Xml_string, Patch*>& patches)
00312        {
00313               std::map<Xml_string, Patch*>::iterator it;
00314               for (it = patches.begin(); it != patches.end(); ++it)
00315               {
00316                      Patch* list = it->second;
00317                      while (list)
00318                      {
00319                             Patch* nxt = list->next;
00320                             delete list;
00321                             list = nxt;
00322                      }
00323               }
00324               patches.clear();
00325        }
00326 
00327        
00328 //     template<> class Patch1<void>;
00329 //     template<> class Patch2<VarPtr,void>;
00330        
00331 } //namespace PRIVATE
00332 
00333 
00334 
00335 template<class ObjType>
00336 inline
00337 ObjType*  Digester::lookup(const Xml_string& idref) 
00338 { 
00339        using namespace PRIVATE;
00340 
00341        std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
00342        if (cell == storage.end())
00343        {
00344 #ifdef DESAXE_DEBUG
00345               std::cerr << "lookup[" << idref << "]-> NULL\n";
00346 #endif
00347               return NULL;
00348        }
00349        else
00350        {
00351               chkcell<ObjType> (cell->second);
00352 #ifdef DESAXE_DEBUG
00353               std::cerr << "lookup[" << idref << "]-> " << static_cast<ObjType*>(cell->second.ptr) << "\n";
00354 #endif
00355               return static_cast<ObjType*>(cell->second.ptr);
00356        }
00357 }
00358 
00359 
00360 
00361 template<class ObjType>
00362 inline
00363 void Digester::store(const Xml_string& idref, ObjType* obj) 
00364 {
00365        using namespace PRIVATE;
00366 #ifdef DESAXE_DEBUG
00367        std::cerr << "store[" << idref << "] <- " << obj << "\n";
00368 #endif
00369        storage[idref] = mkcell(obj);
00370        runPatches(patches[idref], storage[idref]);
00371 }
00372 
00373 
00374 
00375 template<class LinkType>
00376 void Digester::patchCall(const Xml_string& idref, void (*fun)(LinkType*) )
00377 {
00378        using namespace PRIVATE;
00379        
00380        std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
00381        if (cell == storage.end())
00382        {
00383               patches[idref] = new Patch1<LinkType>(fun, patches[idref] );
00384        }
00385        else
00386        {
00387               Patch1<LinkType>(fun).run(cell->second);
00388        }
00389 }
00390 
00391 
00392 template<class ObjType, class LinkType>
00393 void Digester::patchInvoke(const Xml_string& idref, ObjType* obj, void (ObjType::*fun)(LinkType*) )
00394 {
00395        using namespace PRIVATE;
00396        
00397        std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
00398        if (cell == storage.end())
00399        {
00400               patches[idref] = new Patch2<ObjType,LinkType>(obj, fun, patches[idref] );
00401        }
00402        else
00403        {
00404               Patch2<ObjType,LinkType>(obj, fun).run(cell->second);
00405        }
00406 }
00407 
00408 } // namespace desaxe
00409 
00410 #endif