libept
sources.h
Go to the documentation of this file.
00001 
00006 #include <iterator>
00007 #include <iostream>
00008 #include <sstream>
00009 #include <string>
00010 
00011 #include <wibble/range.h>
00012 #include <wibble/mixin.h>
00013 
00014 #ifndef EPT_SOURCES_H
00015 #define EPT_SOURCES_H
00016 
00017 namespace ept {
00018 
00019 struct Sources {
00020     struct Entry : wibble::mixin::Comparable< Entry > {
00021         typedef wibble::Range< std::string > StringRange;
00022         typedef wibble::Consumer< std::string > StringConsumer;
00023         typedef std::vector< std::string > StringVector;
00024         struct Word { std::string s; };
00025         enum Type { Binary, Source, Comment };
00026         Entry( bool e = false, Type t = Comment,
00027                std::string u = "", std::string d = "",
00028                StringRange c = wibble::range( *new StringVector ) )
00029             : m_enabled( e ), m_type( t ), m_url( u ), m_dist( d )
00030         {
00031             c.output( wibble::consumer( m_components ) );
00032         }
00033 
00034         Entry( const Entry &e )
00035             : m_enabled( e.m_enabled ), m_type( e.m_type ), m_url( e.m_url ),
00036               m_dist( e.m_dist ), m_comment( e.m_comment )
00037         {
00038             wibble::range( e.m_components ).output( wibble::consumer( m_components ) );
00039         }
00040 
00041         bool operator< ( const Entry &o ) const {
00042             if (type() < o.type())
00043                 return true;
00044             if (enabled() < o.enabled())
00045                 return true;
00046             if (url() < o.url())
00047                 return true;
00048             if (distribution() < o.distribution())
00049                 return true;
00050             if (components() < o.components())
00051                 return true;
00052             if (comment() < o.comment())
00053                 return true;
00054             return false;
00055         }
00056 
00057         bool operator== ( const Entry &e ) const {
00058             return not ( ( *this < e ) || ( e < *this ) );
00059         }
00060 
00061         std::string components() const {
00062             std::ostringstream s;
00063             std::copy( m_components.begin(), m_components.end(),
00064                        std::ostream_iterator< std::string >( s, " " ) );
00065             return s.str();
00066         }
00067 
00068         void setComponents( const std::string &s ) {
00069             std::istringstream i( s );
00070             m_components.clear();
00071             std::copy( std::istream_iterator< std::string >( i ),
00072                        std::istream_iterator< std::string >(),
00073                        wibble::consumer( m_components ) );
00074         }
00075 
00076         std::string typeString() const {
00077             switch (type())
00078             {
00079                 case Binary: return "deb";
00080                 case Source: return "deb-src";
00081                 case Comment: return "comment";
00082             }
00083         }
00084 
00085         void setTypeString( const std::string &s ) {
00086             if (s == "deb") setType( Binary );
00087             if (s == "deb-src") setType( Source );
00088             if (s == "comment") setType( Comment );
00089         }
00090 
00091         std::string distribution() const { return m_dist; }
00092         void setDistribution( const std::string &s ) { m_dist = s; }
00093 
00094         std::string url() const { return m_url; }
00095         void setUrl( const std::string &s ) { m_url = s; }
00096 
00097         bool enabled() const { return m_enabled; }
00098         void setEnabled( bool e ) { m_enabled = e; }
00099 
00100         std::string comment() const { return m_comment; }
00101         void setComment( const std::string &s ) { m_comment = s; }
00102 
00103         Type type() const { return m_type; }
00104         void setType( Type t ) {
00105             m_type = t;
00106             if (t == Comment) setEnabled( false );
00107         }
00108 
00109         friend std::istream &operator >>( std::istream &i, Entry &s );
00110 
00111         protected:
00112 
00113         bool m_enabled;
00114         Type m_type;
00115         std::string m_url;
00116         std::string m_dist;
00117         StringVector m_components;
00118         std::string m_comment;
00119     };
00120     void add( const Entry &e ) {
00121         wibble::consumer( m_entries ).consume( e );
00122     }
00123     void clear() { m_entries.clear(); }
00124     void disable( const Entry & );
00125     void enable( const Entry & );
00126     wibble::Range< Entry > entries() const {
00127         return wibble::range( m_entries );
00128     }
00129     friend std::istream &operator >>( std::istream &i, Sources &s );
00130 protected:
00131     std::vector< Entry > m_entries;
00132 };
00133 
00134 inline std::istream &operator >>( std::istream &i, Sources::Entry::Word &w )
00135 {
00136     bool bracket = false, quote = false, started = false;
00137     char c;
00138     w.s = "";
00139     while (!i.eof()) {
00140         c = i.get();
00141         if (started && !quote && !bracket && isspace( c ))
00142             break;
00143         if (!isspace( c ))
00144             started = true;
00145         if (started)
00146             w.s += c;
00147         if (bracket && c == ']')
00148             bracket = false;
00149         if (quote && c == '"')
00150             quote = false;
00151         if (!quote && c == '[')
00152             bracket = true;
00153         if (!bracket && c == '"')
00154             quote = true;
00155     }
00156     return i;
00157 }
00158 
00159 inline std::istream &operator >>( std::istream &i, Sources::Entry &e ) {
00160     std::string line, tmp;
00161     std::getline( i, line );
00162     std::istringstream l( line );
00163     // std::cerr << "parsing line: " << line << std::endl;
00164     l >> tmp;
00165     e.setEnabled( true );
00166     if (tmp[0] == '#') {
00167         if (tmp.size() > 1)
00168             tmp = tmp.substr(1);
00169         else
00170             l >> tmp;
00171         e.setEnabled( false );
00172     }
00173     // std::cerr << "type: " << tmp << std::endl;
00174     if (tmp == "deb" || tmp == "deb-src") {
00175         e.setTypeString( tmp );
00176     } else {
00177         // std::cerr << "comment: '" << line << "'" << std::endl;
00178         e.setType( Sources::Entry::Comment );
00179         e.setEnabled( false );
00180         e.setComment( line );
00181         return i;
00182     }
00183     Sources::Entry::Word w;
00184     l >> w; e.m_url = w.s;
00185     l >> w; e.m_dist = w.s;
00186     e.m_components.clear();
00187     std::copy( std::istream_iterator< std::string >( l ),
00188                std::istream_iterator< std::string >(),
00189                wibble::consumer( e.m_components ) );
00190     return i;
00191 }
00192 
00193 inline std::ostream &operator <<( std::ostream &o, const Sources::Entry &e )
00194 {
00195     if (e.type() == Sources::Entry::Comment)
00196         return o << e.comment();
00197     if (! e.enabled())
00198         o << "# ";
00199     o << e.typeString();
00200     o << " " << e.url() << " " << e.distribution() << " " << e.components();
00201     return o;
00202 }
00203 
00204 inline std::istream &operator >>( std::istream &i, Sources &s ) {
00205     std::copy( std::istream_iterator< Sources::Entry >( i ),
00206                std::istream_iterator< Sources::Entry >(),
00207                wibble::consumer( s.m_entries ) );
00208     return i;
00209 }
00210 
00211 inline std::ostream &operator <<( std::ostream &o, const Sources &s ) {
00212     std::copy( s.entries().begin(), s.entries().end(),
00213                std::ostream_iterator< Sources::Entry >( o, "\n" ) );
00214     return o;
00215 }
00216 
00217 }
00218 
00219 #endif
00220 // vim:set ts=4 sw=4: