PluginFrame.cc
Go to the documentation of this file.00001
00002
00003
00004
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
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
00162 if ( ! stream_r )
00163 ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 _command = str::getline( stream_r );
00174 if ( ! stream_r.good() )
00175 ZYPP_THROW( PluginFrameException( "Missing NL after command" ) );
00176
00177
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;
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
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
00202 if ( ! stream_r )
00203 ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
00204
00205
00206 stream_r << _command << endl;
00207
00208 for_( it, _header.begin(), _header.end() )
00209 stream_r << it->first << ':' << it->second << endl;
00210
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
00222
00224
00225 PluginFrame::PluginFrame()
00226 : _pimpl( Impl::nullimpl() )
00227 {}
00228
00229 PluginFrame::PluginFrame( const std::string & command_r )
00230 : _pimpl( new Impl( command_r ) )
00231 {}
00232
00233 PluginFrame::PluginFrame( const std::string & command_r, const std::string body_r )
00234 : _pimpl( new Impl( command_r, body_r ) )
00235 {}
00236
00237 PluginFrame::PluginFrame( std::istream & stream_r )
00238 : _pimpl( new Impl( stream_r ) )
00239 {}
00240
00241 bool PluginFrame::empty() const
00242 { return _pimpl->empty(); }
00243
00244 const std::string & PluginFrame::command() const
00245 { return _pimpl->command(); }
00246
00247 void PluginFrame::setCommand( const std::string & command_r )
00248 { _pimpl->setCommand( command_r ); }
00249
00250 const std::string & PluginFrame::body() const
00251 { return _pimpl->body(); }
00252
00253 std::string & PluginFrame::bodyRef()
00254 { return _pimpl->bodyRef(); }
00255
00256 void PluginFrame::setBody( const std::string & body_r )
00257 { _pimpl->setBody( body_r ); }
00258
00259 std::ostream & PluginFrame::writeTo( std::ostream & stream_r ) const
00260 { return _pimpl->writeTo( stream_r ); }
00261
00262 PluginFrame::HeaderList & PluginFrame::headerList()
00263 { return _pimpl->headerList(); }
00264
00265 const PluginFrame::HeaderList & PluginFrame::headerList() const
00266 { return _pimpl->headerList(); }
00267
00268 const std::string & PluginFrame::getHeader( const std::string & key_r ) const
00269 { return _pimpl->getHeader( key_r ); }
00270
00271 const std::string & PluginFrame::getHeader( const std::string & key_r, const std::string & default_r ) const
00272 { return _pimpl->getHeader( key_r, default_r ); }
00273
00274 const std::string & PluginFrame::getHeaderNT( const std::string & key_r, const std::string & default_r ) const
00275 { return _pimpl->getHeaderNT( key_r, default_r ); }
00276
00277 void PluginFrame::setHeader( const std::string & key_r, const std::string & value_r )
00278 { _pimpl->setHeader( key_r, value_r ); }
00279
00280 void PluginFrame::addHeader( const std::string & key_r, const std::string & value_r )
00281 { _pimpl->addHeader( key_r, value_r ); }
00282
00283 void PluginFrame::clearHeader( const std::string & key_r )
00284 { _pimpl->clearHeader( key_r ); }
00285
00287
00288 std::ostream & operator<<( std::ostream & str, const PluginFrame & obj )
00289 { return str << *obj._pimpl; }
00290
00291 bool operator==( const PluginFrame & lhs, const PluginFrame & rhs )
00292 {
00293 return lhs._pimpl == rhs._pimpl
00294 || lhs.command() == rhs.command() && lhs.headerList() == rhs.headerList() && lhs.body() == rhs.body();
00295 }
00296
00298 }