1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PluginFrame.cc
13 #include "zypp/base/LogTools.h"
14 #include "zypp/base/String.h"
16 #include "zypp/PluginFrame.h"
20 #undef ZYPP_BASE_LOGGER_LOGGROUP
21 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
29 // CLASS NAME : PluginFrame::Impl
31 /** PluginFrame implementation. */
32 struct PluginFrame::Impl
38 Impl( const std::string & command_r )
39 { setCommand( command_r ); }
41 Impl( const std::string & command_r, const std::string & body_r )
43 { setCommand( command_r ); }
45 Impl( const std::string & command_r, HeaderInitializerList contents_r )
46 { setCommand( command_r ); addHeader( contents_r ); }
48 Impl( const std::string & command_r, const std::string & body_r, HeaderInitializerList contents_r )
50 { setCommand( command_r ); addHeader( contents_r ); }
52 Impl( std::istream & stream_r );
56 { return _command.empty() && _body.empty(); }
58 const std::string & command() const
61 void setCommand( const std::string & command_r )
63 if ( command_r.find( '\n' ) != std::string::npos )
64 ZYPP_THROW( PluginFrameException( "Multiline command", command_r ) );
68 const std::string & body() const
71 std::string & bodyRef()
74 void setBody( const std::string & body_r )
78 typedef std::pair<HeaderListIterator,HeaderListIterator> constKeyRange;
79 typedef std::pair<HeaderList::iterator,HeaderList::iterator> KeyRange;
81 HeaderList & headerList()
84 const HeaderList & headerList() const
87 const std::string & getHeader( const std::string & key_r ) const
89 constKeyRange r( _header.equal_range( key_r ) );
90 if ( r.first == r.second )
91 ZYPP_THROW( PluginFrameException( "No value for key", key_r ) );
92 const std::string & ret( r.first->second );
93 if ( ++r.first != r.second )
94 ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
98 const std::string & getHeader( const std::string & key_r, const std::string & default_r ) const
100 constKeyRange r( _header.equal_range( key_r ) );
101 if ( r.first == r.second )
103 const std::string & ret( r.first->second );
104 if ( ++r.first != r.second )
105 ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
109 const std::string & getHeaderNT( const std::string & key_r, const std::string & default_r ) const
111 HeaderListIterator iter( _header.find( key_r ) );
112 return iter != _header.end() ? iter->second : default_r;
115 HeaderList::value_type mkHeaderPair( const std::string & key_r, const std::string & value_r )
117 if ( key_r.find_first_of( ":\n" ) != std::string::npos )
118 ZYPP_THROW( PluginFrameException( "Illegal char in header key", key_r ) );
119 if ( value_r.find_first_of( ":\n" ) != std::string::npos )
120 ZYPP_THROW( PluginFrameException( "Illegal char in header value", value_r ) );
121 return HeaderList::value_type( key_r, value_r );
124 void setHeader( const std::string & key_r, const std::string & value_r )
126 clearHeader( key_r );
127 addHeader( key_r, value_r );
130 void addHeader( const std::string & key_r, const std::string & value_r )
132 _header.insert( mkHeaderPair( key_r, value_r ) );
135 void addHeader( HeaderInitializerList contents_r )
137 for ( const auto & el : contents_r )
138 addHeader( el.first, el.second );
141 void clearHeader( const std::string & key_r )
143 _header.erase( key_r );
147 std::ostream & writeTo( std::ostream & stream_r ) const;
150 std::string _command;
155 /** Offer default Impl. */
156 static shared_ptr<Impl> nullimpl()
158 static shared_ptr<Impl> _nullimpl( new Impl );
162 friend Impl * rwcowClone<Impl>( const Impl * rhs );
163 /** clone for RWCOW_pointer */
165 { return new Impl( *this ); }
167 ///////////////////////////////////////////////////////////////////
169 /** \relates PluginFrame::Impl Stream output */
170 inline std::ostream & operator<<( std::ostream & str, const PluginFrame::Impl & obj )
172 return str << "PluginFrame[" << obj.command() << "](" << obj.headerList().size() << "){" << obj.body().size() << "}";
175 PluginFrame::Impl::Impl( std::istream & stream_r )
177 //DBG << "Parse from " << stream_r << endl;
179 ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
181 // JFYI: stream status after getline():
183 // ------|---------------
184 // true | [g___] >FOO< : FOO line was \n-terminated
185 // true | [_e__] >BAA< : BAA before EOF, but not \n-terminated
186 // false | [_eF_] >< : No valid data to consume
189 _command = str::getline( stream_r );
190 if ( ! stream_r.good() )
191 ZYPP_THROW( PluginFrameException( "Missing NL after command" ) );
195 std::string data = str::getline( stream_r );
196 if ( ! stream_r.good() )
197 ZYPP_THROW( PluginFrameException( "Missing NL after header" ) );
200 break; // --> empty line sep. header and body
202 std::string::size_type sep( data.find( ':') );
203 if ( sep == std::string::npos )
204 ZYPP_THROW( PluginFrameException( "Missing colon in header" ) );
206 _header.insert( HeaderList::value_type( data.substr(0,sep), data.substr(sep+1) ) );
210 _body = str::receiveUpTo( stream_r, '\0' );
211 if ( ! stream_r.good() )
212 ZYPP_THROW( PluginFrameException( "Missing NUL after body" ) );
215 std::ostream & PluginFrame::Impl::writeTo( std::ostream & stream_r ) const
217 //DBG << "Write " << *this << " to " << stream_r << endl;
219 ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
222 stream_r << _command << endl;
224 for_( it, _header.begin(), _header.end() )
225 stream_r << it->first << ':' << it->second << endl;
231 ZYPP_THROW( PluginFrameException( "Write error" ) );
235 ///////////////////////////////////////////////////////////////////
237 // CLASS NAME : PluginFrame
239 ///////////////////////////////////////////////////////////////////
241 const std::string & PluginFrame::ackCommand()
243 static std::string _val( "ACK" );
247 const std::string & PluginFrame::errorCommand()
249 static std::string _val( "ERROR" );
253 const std::string & PluginFrame::enomethodCommand()
255 static std::string _val( "_ENOMETHOD" );
259 PluginFrame::PluginFrame()
260 : _pimpl( Impl::nullimpl() )
263 PluginFrame::PluginFrame( const std::string & command_r )
264 : _pimpl( new Impl( command_r ) )
267 PluginFrame::PluginFrame( const std::string & command_r, const std::string & body_r )
268 : _pimpl( new Impl( command_r, body_r ) )
271 PluginFrame::PluginFrame( const std::string & command_r, HeaderInitializerList contents_r )
272 : _pimpl( new Impl( command_r, contents_r ) )
275 PluginFrame::PluginFrame( const std::string & command_r, const std::string & body_r, HeaderInitializerList contents_r )
276 : _pimpl( new Impl( command_r, body_r, contents_r ) )
279 PluginFrame::PluginFrame( std::istream & stream_r )
280 : _pimpl( new Impl( stream_r ) )
283 bool PluginFrame::empty() const
284 { return _pimpl->empty(); }
286 const std::string & PluginFrame::command() const
287 { return _pimpl->command(); }
289 void PluginFrame::setCommand( const std::string & command_r )
290 { _pimpl->setCommand( command_r ); }
292 const std::string & PluginFrame::body() const
293 { return _pimpl->body(); }
295 std::string & PluginFrame::bodyRef()
296 { return _pimpl->bodyRef(); }
298 void PluginFrame::setBody( const std::string & body_r )
299 { _pimpl->setBody( body_r ); }
301 std::ostream & PluginFrame::writeTo( std::ostream & stream_r ) const
302 { return _pimpl->writeTo( stream_r ); }
304 PluginFrame::HeaderList & PluginFrame::headerList()
305 { return _pimpl->headerList(); }
307 const PluginFrame::HeaderList & PluginFrame::headerList() const
308 { return _pimpl->headerList(); }
310 const std::string & PluginFrame::getHeader( const std::string & key_r ) const
311 { return _pimpl->getHeader( key_r ); }
313 const std::string & PluginFrame::getHeader( const std::string & key_r, const std::string & default_r ) const
314 { return _pimpl->getHeader( key_r, default_r ); }
316 const std::string & PluginFrame::getHeaderNT( const std::string & key_r, const std::string & default_r ) const
317 { return _pimpl->getHeaderNT( key_r, default_r ); }
319 void PluginFrame::setHeader( const std::string & key_r, const std::string & value_r )
320 { _pimpl->setHeader( key_r, value_r ); }
322 void PluginFrame::addHeader( const std::string & key_r, const std::string & value_r )
323 { _pimpl->addHeader( key_r, value_r ); }
325 void PluginFrame::addHeader( HeaderInitializerList contents_r )
326 { _pimpl->addHeader( contents_r ); }
328 void PluginFrame::clearHeader( const std::string & key_r )
329 { _pimpl->clearHeader( key_r ); }
331 ///////////////////////////////////////////////////////////////////
333 std::ostream & operator<<( std::ostream & str, const PluginFrame & obj )
334 { return str << *obj._pimpl; }
336 bool operator==( const PluginFrame & lhs, const PluginFrame & rhs )
338 return ( lhs._pimpl == rhs._pimpl )
339 || (( lhs.command() == rhs.command() ) && ( lhs.headerList() == rhs.headerList() ) && ( lhs.body() == rhs.body() ));
342 /////////////////////////////////////////////////////////////////
344 ///////////////////////////////////////////////////////////////////