"Fossies" - the Fresh Open Source Software Archive

Member "devtodo-0.1.20/src/Loaders.cc" (28 Jun 2007, 9019 Bytes) of package /linux/privat/old/devtodo-0.1.20.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Loaders.cc" see the Fossies "Dox" file reference documentation.

    1 #include <sys/stat.h>
    2 #include <unistd.h>
    3 #include "Loaders.h"
    4 #include "Strings.h"
    5 #include "support.h"
    6 #include "config.h"
    7 
    8 using namespace str;
    9 
   10 Loader getLoaders() {
   11 Loader out;
   12 
   13     out["xml"] = xmlLoad;
   14     out["binary"] = binaryLoad;
   15     return out;
   16 }
   17 
   18 Saver getSavers() {
   19 Saver out;
   20 
   21     out["xml"] = xmlSave;
   22     out["binary"] = binarySave;
   23     return out;
   24 }
   25 
   26 void checkVersion(string const &version) {
   27 vector<string> vtdver = str::split(".", version);
   28 vector<string> vmyver = str::split(".", VERSION);
   29 int tdver[3], myver[3];
   30 
   31     if (options.verbose > 1)
   32         cout << "todo: loading database version '" << version << "' (binary version is '" << VERSION << "')" << endl;
   33 
   34     if (vtdver.size() != 3) throw load_error("invalid database version number '" + version + "'");
   35 
   36     tdver[0] = destringify<int>(vtdver[0]);
   37     tdver[1] = destringify<int>(vtdver[1]);
   38     tdver[2] = destringify<int>(vtdver[2]);
   39 
   40     myver[0] = destringify<int>(vmyver[0]);
   41     myver[1] = destringify<int>(vmyver[1]);
   42     myver[2] = destringify<int>(vmyver[2]);
   43 
   44     if (tdver[0] != myver[0] || tdver[1] != myver[1]) {
   45         cerr << "todo: error, version of database (" << version << ") is different than binary (" << VERSION << ")" << endl;
   46         exit(1);
   47     }
   48     // minor version differences shouldn't be fatal
   49     if (tdver[2] > myver[2]) cerr << "warning: version of database (" << version << ") is more recent than binary (" << VERSION << ")" << endl;
   50 }
   51 
   52 void xmlParse(TodoDB &outdb, vector<XML*>::const_iterator begin, 
   53     vector<XML*>::const_iterator end, multiset<Todo> &out) {
   54     for (vector<XML*>::const_iterator i = begin; i != end; i++) {
   55     XML &x = *(*i);
   56 
   57         switch (x.type()) {
   58             case XML::Element : {
   59                 if (x.name() == "title") {
   60                     outdb.titleText = trim((*x.child().begin())->body());
   61                     break;
   62                 } else
   63                 if (x.name() == "note") {
   64                 Todo todo;
   65                 // const_cast so I can use attrib[...]
   66                 map<string, string> &attrib = *const_cast<map<string, string>* >(&x.attrib());
   67 
   68                     if (attrib.find("priority") == attrib.end() || attrib.find("time") == attrib.end())
   69                         throw load_error("require both 'priority' and 'time' attributes for 'note' element");
   70 
   71                     if (attrib.find("done") != attrib.end()) {
   72                             todo.done = true;
   73                             todo.doneTime = destringify<time_t>(attrib["done"]);
   74                         } else
   75                             todo.done = false;
   76 
   77                     todo.priority = desymbolisePriority(attrib["priority"]);
   78                     todo.text = trim((*x.child().begin())->body());
   79                     todo.added = destringify<time_t>(attrib["time"]);
   80                     todo.db = &outdb;
   81 
   82                     for (vector<XML*>::const_iterator j = x.child().begin(); j != x.child().end(); ++j)
   83                         if ((*j)->name() == "comment") {
   84                             todo.comment = trim((*(*j)->child().begin())->body());
   85                             break;
   86                         }
   87 
   88                     xmlParse(outdb, x.child().begin(), x.child().end(), *todo.child);
   89                     out.insert(todo);
   90                 } else if (x.name() == "link") {
   91                 TodoDB *newDb = new TodoDB();
   92                 Todo todo;
   93                 map<string, string> &attrib = *const_cast<map<string, string>* >(&x.attrib());
   94 
   95                     if (attrib.find("priority") == attrib.end() || attrib.find("filename") == attrib.end() || attrib.find("time") == attrib.end())
   96                         throw load_error("require 'priority', 'time', and 'filename' attributes for 'link' element");
   97 
   98                     try {
   99                         if (outdb.basepath == "" || attrib["filename"][0] == '/')
  100                             newDb->load(attrib["filename"]);
  101                         else
  102                             newDb->load(outdb.basepath + "/" + attrib["filename"]);
  103                         if (newDb->titleText == "") {
  104                             if (newDb->basepath == "")
  105                                 todo.text = attrib["filename"];
  106                             else
  107                                 todo.text = newDb->basepath.substr(newDb->basepath.rfind("/") + 1);
  108                         }
  109                         else
  110                             todo.text = newDb->titleText;
  111 
  112                         delete todo.child;
  113 
  114                         
  115                         todo.type = Todo::Link;
  116                         todo.child = &newDb->todo;
  117                         todo.priority = desymbolisePriority(attrib["priority"]);
  118                         todo.todofile = attrib["filename"];
  119                         todo.db = newDb;
  120 
  121                         out.insert(todo);
  122                     } catch (...) {
  123                         delete newDb;
  124                     }
  125                 } else
  126                 if (x.name() != "comment")
  127                     throw load_error("expected 'note' element, got '" + x.name() + "'");
  128             }
  129             break;
  130             default :
  131             break;
  132         }
  133     }
  134 
  135     // number the items
  136 int n = 1;
  137     for (multiset<Todo>::iterator i = out.begin(); i != out.end(); ++i, ++n) {
  138     Todo &t = const_cast<Todo&>(*i);
  139         
  140         t.index = n;
  141     }
  142 }
  143 
  144 bool xmlLoad(TodoDB &todo, string const &file) {
  145 ifstream in(file.c_str());
  146 
  147     if (in.bad()||in.fail()||in.eof()) return false;
  148 struct stat s;
  149     stat(file.c_str(), &s);
  150 
  151 char *str;
  152     str = new char[s.st_size + 1];
  153 
  154     in.read(str, s.st_size);
  155     str[s.st_size] = 0;
  156 
  157 XML x(str);
  158 
  159     if (x.name() != "todo")
  160         throw load_error("primary element not 'todo'");
  161 map<string, string> const &attrib = x.attrib();
  162 
  163     // do version checking
  164     if (attrib.find("version") != attrib.end())
  165         checkVersion(const_cast<map<string, string>&>(attrib)["version"]);
  166 
  167     xmlParse(todo, x.child().begin(), x.child().end(), todo.todo);
  168     return true;
  169 }
  170 
  171 void xmlSave(TodoDB const &db, multiset<Todo> const &todo, ostream &of, int ind) {
  172     for (multiset<Todo>::const_iterator i = todo.begin(); i != todo.end(); i++) {
  173         if (i->type == Todo::Link) {
  174             of  << string(ind * 4, ' ') << "<link"
  175                 << " filename=\"" << i->todofile << "\""
  176                 << " priority=\"" << symbolisePriority(i->priority) << "\""
  177                 << " time=\"" << i->added << "\""
  178                 << "/>" << endl;
  179 
  180             if (i->db)
  181                 i->db->save(i->todofile);
  182 
  183             /* Restore the TODODB environment variable. */
  184 string envar = "TODODB=" + db.filename;
  185 
  186             putenv(strdup(const_cast<char*>(envar.c_str())));
  187 
  188         } else {
  189             of  << string(ind * 4, ' ') << "<note"
  190                 << " priority=\"" << symbolisePriority((*i).priority) << "\""
  191                 << " time=\"" << (*i).added << "\"";
  192             if ((*i).done) {
  193                 of  << " done=\"" << (*i).doneTime<< "\"";
  194             }
  195             of << ">" << endl;
  196             of << string((ind + 1) * 4, ' ');
  197             of << htmlify((*i).text) << endl;
  198             if ((*i).comment != "") {
  199                 of << string((ind + 1) * 4, ' ');
  200                 of << "<comment>" << endl;
  201                 of << string((ind + 2) * 4, ' ');
  202                 of << htmlify((*i).comment) << endl;
  203                 of << string((ind + 1) * 4, ' ');
  204                 of << "</comment>" << endl;
  205             }
  206             xmlSave(db, *i->child, of, ind + 1);
  207             of << string(ind * 4, ' ');
  208             of << "</note>" << endl;
  209         }
  210     }
  211 }
  212 
  213 bool xmlSave(TodoDB const &todo, string const &file) {
  214     if (todo.isDirty())
  215     {
  216     ofstream of(file.c_str());
  217 
  218         if (of.bad()) return false;
  219         if (options.verbose > 1)
  220             cout << "todo: saving to database '" << file << "'" << endl;
  221         of << "<?xml version=\"1.0\"?>" << endl;
  222         of << "<todo version=\"" << VERSION << "\">" << endl;
  223         if (todo.titleText != "")
  224             of  << "    <title>" << endl 
  225                 << "        " << todo.titleText << endl
  226                 << "    </title>" << endl;
  227 
  228         /* Set the TODODB environment variable. */
  229     string envar = "TODODB=" + todo.filename;
  230 
  231         putenv(strdup(const_cast<char*>(envar.c_str())));
  232 
  233         xmlSave(todo, todo.todo, of, 1);
  234         of << "</todo>" << endl;
  235         of.close();
  236         return true;
  237     }
  238     else
  239     {
  240     ofstream out("/dev/null");
  241 
  242         xmlSave(todo, todo.todo, out, 1);
  243         return false;
  244     }
  245 }
  246 
  247 void binaryLoad(ifstream &in, int &n) {
  248     in.read((char *)&n, sizeof(n));
  249 }
  250 
  251 void binaryLoad(ifstream &in, string &str) {
  252 int size;
  253 
  254     binaryLoad(in, size);
  255 char buffer[size + 1];
  256     in.read(buffer, size);
  257     buffer[size] = 0;
  258     str = buffer;
  259 }
  260 
  261 void binaryLoad(TodoDB &db, ifstream &in, multiset<Todo> &out) {
  262 int n;
  263 
  264     binaryLoad(in, n);
  265     for (int i = 0; i < n; i++) {
  266     Todo t;
  267     int tmp;
  268 
  269         binaryLoad(in, tmp); t.priority = (Todo::Priority)tmp;
  270         binaryLoad(in, tmp); t.added = tmp;
  271         binaryLoad(in, tmp); t.doneTime = tmp;
  272         if (t.doneTime) t.done = true;
  273         binaryLoad(in, t.text);
  274         binaryLoad(db, in, *t.child);
  275 
  276         t.db = &db;
  277         out.insert(t);
  278     }
  279 
  280     // number the items
  281     n = 1;
  282     for (multiset<Todo>::iterator i = out.begin(); i != out.end(); ++i, ++n) {
  283     Todo &t = const_cast<Todo&>(*i);
  284         
  285         t.index = n;
  286     }
  287 }
  288 
  289 bool binaryLoad(TodoDB &out, string const &file) {
  290 ifstream in(file.c_str());
  291 
  292     if (in.bad()||in.fail()||in.eof()) return false;
  293 char buffer[5];
  294 
  295     in.read(buffer, 4);
  296     buffer[4] = 0;
  297     if (string(buffer) != "TODO") return false;
  298 string version;
  299     binaryLoad(in, version);
  300     checkVersion(version);
  301     binaryLoad(in, out.titleText);
  302     binaryLoad(out, in, out.todo);
  303     return true;
  304 }
  305 
  306 void binarySave(ofstream &of, int n) {
  307     of.write((char*)&n, sizeof(n));
  308 }
  309 
  310 void binarySave(ofstream &of, string const &str) {
  311     binarySave(of, str.size());
  312     of.write(str.c_str(), str.size());
  313 }
  314 
  315 void binarySave(ofstream &of, multiset<Todo> const &db) {
  316     binarySave(of, db.size());
  317     for (multiset<Todo>::const_iterator i = db.begin(); i != db.end(); ++i) {
  318         binarySave(of, (*i).priority);
  319         binarySave(of, (*i).added);
  320         if ((*i).done)
  321             binarySave(of, (*i).doneTime);
  322         else
  323             binarySave(of, 0);
  324         binarySave(of, (*i).text);
  325         binarySave(of, *i->child);
  326     }
  327 }
  328 
  329 bool binarySave(TodoDB const &in, string const &file) {
  330 ofstream of(file.c_str());
  331 
  332     if (of.bad()) return false;
  333 
  334 string envar = "TODODB=" + in.filename;
  335 
  336     putenv(strdup(const_cast<char*>(envar.c_str())));
  337 
  338     of.write("TODO", 4);
  339     binarySave(of, VERSION);
  340     binarySave(of, in.titleText);
  341     binarySave(of, in.todo);
  342     return true;
  343 }
  344