libzypp  10.5.0
PluginFrame.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include "zypp/base/LogTools.h"
00014 #include "zypp/base/String.h"
00015 
00016 #include "zypp/PluginFrame.h"
00017 
00018 using std::endl;
00019 
00021 namespace zypp
00022 { 
00023 
00025   //
00026   //    CLASS NAME : PluginFrame::Impl
00027   //
00029   struct PluginFrame::Impl
00030   {
00031     public:
00032       Impl()
00033       {}
00034 
00035       Impl( const std::string & command_r )
00036       { setCommand( command_r ); }
00037 
00038       Impl( const std::string & command_r, const std::string body_r )
00039         : _body( body_r )
00040       { setCommand( command_r ); }
00041 
00042       Impl( std::istream & stream_r );
00043 
00044     public:
00045       bool empty() const
00046       { return _command.empty() && _body.empty(); }
00047 
00048       const std::string & command() const
00049       { return _command; }
00050 
00051       void setCommand( const std::string & command_r )
00052       {
00053         if ( command_r.find( '\n' ) != std::string::npos )
00054           ZYPP_THROW( PluginFrameException( "Multiline command", command_r ) );
00055         _command = command_r;
00056       }
00057 
00058       const std::string & body() const
00059       { return _body; }
00060 
00061       std::string & bodyRef()
00062       { return _body; }
00063 
00064       void setBody( const std::string & body_r )
00065       { _body = body_r; }
00066 
00067     public:
00068       typedef std::pair<HeaderListIterator,HeaderListIterator> constKeyRange;
00069       typedef std::pair<HeaderList::iterator,HeaderList::iterator> KeyRange;
00070 
00071       HeaderList & headerList()
00072       { return _header; }
00073 
00074       const HeaderList & headerList() const
00075       { return _header; }
00076 
00077       const std::string & getHeader( const std::string & key_r ) const
00078       {
00079         constKeyRange r( _header.equal_range( key_r ) );
00080         if ( r.first == r.second )
00081           ZYPP_THROW( PluginFrameException( "No value for key", key_r ) );
00082         const std::string & ret( r.first->second );
00083         if ( ++r.first != r.second )
00084           ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
00085         return ret;
00086       }
00087 
00088       const std::string & getHeader( const std::string & key_r, const std::string & default_r ) const
00089       {
00090         constKeyRange r( _header.equal_range( key_r ) );
00091         if ( r.first == r.second )
00092           return default_r;
00093         const std::string & ret( r.first->second );
00094         if ( ++r.first != r.second )
00095           ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
00096         return ret;
00097       }
00098 
00099       const std::string & getHeaderNT( const std::string & key_r, const std::string & default_r ) const
00100       {
00101         HeaderListIterator iter( _header.find( key_r ) );
00102         return iter != _header.end() ? iter->second : default_r;
00103       }
00104 
00105       HeaderList::value_type mkHeaderPair( const std::string & key_r, const std::string & value_r )
00106       {
00107         if ( key_r.find_first_of( ":\n" ) != std::string::npos )
00108           ZYPP_THROW( PluginFrameException( "Illegal char in header key", key_r ) );
00109         if ( value_r.find_first_of( ":\n" ) != std::string::npos )
00110           ZYPP_THROW( PluginFrameException( "Illegal char in header value", value_r ) );
00111         return HeaderList::value_type( key_r, value_r );
00112       }
00113 
00114       void setHeader( const std::string & key_r, const std::string & value_r )
00115       {
00116         clearHeader( key_r );
00117         addHeader( key_r, value_r );
00118       }
00119 
00120       void addHeader( const std::string & key_r, const std::string & value_r )
00121       {
00122         _header.insert( mkHeaderPair( key_r, value_r ) );
00123       }
00124 
00125       void clearHeader( const std::string & key_r )
00126       {
00127         _header.erase( key_r );
00128       }
00129 
00130     public:
00131       std::ostream & writeTo( std::ostream & stream_r ) const;
00132 
00133     private:
00134       std::string _command;
00135       std::string _body;
00136       HeaderList  _header;
00137 
00138     public:
00140       static shared_ptr<Impl> nullimpl()
00141       {
00142         static shared_ptr<Impl> _nullimpl( new Impl );
00143         return _nullimpl;
00144       }
00145     private:
00146       friend Impl * rwcowClone<Impl>( const Impl * rhs );
00148       Impl * clone() const
00149       { return new Impl( *this ); }
00150   };
00152 
00154   inline std::ostream & operator<<( std::ostream & str, const PluginFrame::Impl & obj )
00155   {
00156     return str << "PluginFrame[" << obj.command() << "](" << obj.headerList().size() << "){" << obj.body().size() << "}";
00157   }
00158 
00159   PluginFrame::Impl::Impl( std::istream & stream_r )
00160   {
00161     //DBG << "Parse from " << stream_r << endl;
00162     if ( ! stream_r )
00163       ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
00164 
00165     // JFYI: stream status after getline():
00166     //  Bool  | Bits
00167     //  ------|---------------
00168     //  true  | [g___] >FOO< : FOO line was \n-terminated
00169     //  true  | [_e__] >BAA< : BAA before EOF, but not \n-terminated
00170     //  false | [_eF_] ><    : No valid data to consume
00171 
00172     //command
00173     _command = str::getline( stream_r );
00174     if ( ! stream_r.good() )
00175       ZYPP_THROW( PluginFrameException( "Missing NL after command" ) );
00176 
00177     // header
00178     do {
00179       std::string data = str::getline( stream_r );
00180       if ( ! stream_r.good() )
00181         ZYPP_THROW( PluginFrameException( "Missing NL after header" ) );
00182 
00183       if ( data.empty() )
00184         break;  // --> empty line sep. header and body
00185 
00186       std::string::size_type sep( data.find( ':') );
00187       if ( sep ==  std::string::npos )
00188         ZYPP_THROW( PluginFrameException( "Missing colon in header" ) );
00189 
00190       _header.insert( HeaderList::value_type( data.substr(0,sep), data.substr(sep+1) ) );
00191     } while ( true );
00192 
00193     // data
00194     _body = str::receiveUpTo( stream_r, '\0' );
00195     if ( ! stream_r.good() )
00196       ZYPP_THROW( PluginFrameException( "Missing NUL after body" ) );
00197   }
00198 
00199   std::ostream & PluginFrame::Impl::writeTo( std::ostream & stream_r ) const
00200   {
00201     //DBG << "Write " << *this << " to " << stream_r << endl;
00202     if ( ! stream_r )
00203       ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
00204 
00205     // command
00206     stream_r << _command << endl;
00207     // header
00208     for_( it, _header.begin(), _header.end() )
00209       stream_r << it->first << ':' << it->second << endl;
00210     // body
00211     stream_r << endl
00212              << _body << '\0';
00213 
00214     if ( ! stream_r )
00215       ZYPP_THROW( PluginFrameException( "Write error" ) );
00216     return stream_r;
00217   }
00218 
00220   //
00221   //    CLASS NAME : PluginFrame
00222   //
00224 
00225   const std::string & PluginFrame::ackCommand()
00226   {
00227     static std::string _val( "ACK" );
00228     return _val;
00229   }
00230 
00231   const std::string & PluginFrame::errorCommand()
00232   {
00233     static std::string _val( "ERROR" );
00234     return _val;
00235   }
00236 
00237   PluginFrame::PluginFrame()
00238     : _pimpl( Impl::nullimpl() )
00239   {}
00240 
00241   PluginFrame::PluginFrame( const std::string & command_r )
00242     : _pimpl( new Impl( command_r ) )
00243   {}
00244 
00245   PluginFrame::PluginFrame( const std::string & command_r, const std::string body_r )
00246     : _pimpl( new Impl( command_r, body_r ) )
00247   {}
00248 
00249   PluginFrame::PluginFrame( std::istream & stream_r )
00250     : _pimpl( new Impl( stream_r ) )
00251   {}
00252 
00253   bool PluginFrame::empty() const
00254   { return _pimpl->empty(); }
00255 
00256   const std::string & PluginFrame::command() const
00257   { return _pimpl->command(); }
00258 
00259   void  PluginFrame::setCommand( const std::string & command_r )
00260   { _pimpl->setCommand( command_r ); }
00261 
00262   const std::string & PluginFrame::body() const
00263   { return _pimpl->body(); }
00264 
00265   std::string & PluginFrame::bodyRef()
00266   { return _pimpl->bodyRef(); }
00267 
00268   void  PluginFrame::setBody( const std::string & body_r )
00269   { _pimpl->setBody( body_r ); }
00270 
00271   std::ostream & PluginFrame::writeTo( std::ostream & stream_r ) const
00272   { return _pimpl->writeTo( stream_r ); }
00273 
00274   PluginFrame::HeaderList & PluginFrame::headerList()
00275   { return _pimpl->headerList(); }
00276 
00277   const PluginFrame::HeaderList & PluginFrame::headerList() const
00278   { return _pimpl->headerList(); }
00279 
00280   const std::string & PluginFrame::getHeader( const std::string & key_r ) const
00281   { return _pimpl->getHeader( key_r ); }
00282 
00283   const std::string & PluginFrame::getHeader( const std::string & key_r, const std::string & default_r ) const
00284   { return _pimpl->getHeader( key_r, default_r ); }
00285 
00286   const std::string & PluginFrame::getHeaderNT( const std::string & key_r, const std::string & default_r ) const
00287   { return _pimpl->getHeaderNT( key_r, default_r ); }
00288 
00289   void PluginFrame::setHeader( const std::string & key_r, const std::string & value_r )
00290   { _pimpl->setHeader( key_r, value_r ); }
00291 
00292   void PluginFrame::addHeader( const std::string & key_r, const std::string & value_r )
00293   { _pimpl->addHeader( key_r, value_r ); }
00294 
00295   void PluginFrame::clearHeader( const std::string & key_r )
00296   { _pimpl->clearHeader( key_r ); }
00297 
00299 
00300   std::ostream & operator<<( std::ostream & str, const PluginFrame & obj )
00301   { return str << *obj._pimpl; }
00302 
00303   bool operator==( const PluginFrame & lhs, const PluginFrame & rhs )
00304   {
00305     return ( lhs._pimpl == rhs._pimpl )
00306         || (( lhs.command() ==  rhs.command() ) && ( lhs.headerList() == rhs.headerList() ) && ( lhs.body() == rhs.body() ));
00307   }
00308 
00310 } // namespace zypp