libzypp 8.13.6
|
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 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 } // namespace zypp