/* Web Polygraph http://www.web-polygraph.org/ * (C) 2003-2006 The Measurement Factory * Licensed under the Apache License, Version 2.0 */ #ifndef POLYGRAPH__BASE_ILOG_H #define POLYGRAPH__BASE_ILOG_H #include "xstd/h/iostream.h" #include "xstd/Time.h" #include "xstd/Size.h" #include "xstd/NetDouble.h" #include "xstd/BigSize.h" #include "xstd/String.h" #include "xstd/Array.h" #include "xstd/NetAddr.h" #include "base/Progress.h" // some environments do not know better than #define these #ifdef getc #undef getc #endif #ifdef putc #undef putc #endif // every log entry has this prefix class LogEntryPx { public: LogEntryPx(): theCat(-1), theTag(-1) {} bool good() const; operator void*() const { return theTag > 0 ? (void*)-1 : 0; } ILog &load(ILog &il); ostream &print(ostream &os) const; public: Size theSize; // size, including the header int theCat; // logging category int theTag; // logging tag }; inline ostream &operator <<(ostream &os, const LogEntryPx &px) { return px.print(os); } // binary log, input interface class ILog { public: typedef void (Manip)(class ILog &); public: ILog(); ~ILog(); void stream(const String &aFileName, istream *aStream); const String &fileName() const { return theFileName; } istream *stream() { return theStream; } operator void*() { return theStream && theStream->good() ? theStream : 0; } char getc() { char c; get(&c, 1); return c; } bool getb() { return getc() != 0; } int geti() { int x; return(geti(x)); } int geti(int &x) { get(&x, sizeof(x)); return x = ntohl(x); } int geti(int *&xs, int &count); // returns count sockaddr_storage &geta(struct sockaddr_storage &a) { get(&a, SizeOf(a)); return a; } String &gets(String &s); LogEntryPx begEntry(); void endEntry(); bool eoe() { return theStream->tellg() >= theEntryEnd; } const Progress &progress() const { return theProgress; } protected: void getHeader(); void get(void *buf, int len) { theStream->read((char*)buf, len); } protected: istream *theStream; String theFileName; streampos theEntryEnd; // end of the current entry (last+1) LogEntryPx theCurPx; // prefix of the current entry Progress theProgress; // current "local time", #errs, etc. }; /* logging of common types */ inline ILog &operator >>(ILog &il, LogEntryPx &px) { return px.load(il); } inline ILog &operator >>(ILog &il, char &c) { c = il.getc(); return il; } inline ILog &operator >>(ILog &il, bool &b) { b = il.getb(); return il; } inline ILog &operator >>(ILog &il, int &x) { il.geti(x); return il; } inline ILog &operator >>(ILog &il, double &x) { NetDouble nd; il >> nd.mnt >> nd.exp; x = nd; return il; } inline ILog &operator >>(ILog &il, String &s) { il.gets(s); return il; } inline ILog &operator >>(ILog &il, Time &t) { t.tv_sec = il.geti(); t.tv_usec = il.geti(); return il; } inline ILog &operator >>(ILog &il, BigSize &bs) { return il >> bs.theAcc >> bs.theCnt; } inline ILog &operator >>(ILog &il, Size &sz) { return il >> sz.theSize; } inline ILog &operator >>(ILog &il, NetAddr &a) { struct sockaddr_storage ss; il.geta(ss); a = NetAddr(ss); return il; } inline ILog &operator >>(ILog &il, ILog::Manip m) { m(il); return il; } template inline ILog &operator >>(ILog &log, Array &a) { const int cnt = log.geti(); if (a.count()) { // use existing entries Assert(cnt <= a.count()); for (int i = 0; i < cnt; ++i) log >> a.item(i); } else { for (int i = 0; i < cnt; ++i) { Item item; log >> item; a << item; } } return log; } // load array of not-null pointers to items #ifdef COMPILER_CAN_HANDLE_NONTRIVIAL_TEMPLATES template inline void ILogLoadPtrs(ILog &log, Array &a) { const int cnt = log.geti(); if (a.count()) { // use existing entries Assert(cnt <= a.count()); for (int i = 0; i < cnt; ++i) { Assert(a.item(i)); log >> *a.item(i); } } else { for (int i = 0; i < cnt; ++i) { a.append(new Item); log >> *a.item(i); } } } #else # define ILogLoadPtrs(log, a, Item) { \ const int cnt = (log).geti(); \ if ((a).count()) { \ Assert(cnt <= (a).count()); \ for (int i = 0; i < cnt; ++i) { \ Assert((a).item(i)); \ (log) >> *(a).item(i); \ } \ } else { \ for (int i = 0; i < cnt; ++i) { \ (a).append(new Item); \ (log) >> *(a).item(i); \ } \ } \ } #endif #endif