libzypp
10.5.0
|
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