libzypp 17.34.0
PluginFrame.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <iostream>
13#include <utility>
14#include <zypp/base/LogTools.h>
15#include <zypp/base/String.h>
16
17#include <zypp/PluginFrame.h>
18
19using std::endl;
20
21#undef ZYPP_BASE_LOGGER_LOGGROUP
22#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
23
25namespace zypp
26{
27
29 //
30 // CLASS NAME : PluginFrame::Impl
31 //
34 {
35 public:
37 {}
38
39 Impl( const std::string & command_r )
40 { setCommand( command_r ); }
41
42 Impl( const std::string & command_r, std::string &&body_r )
43 : _body(std::move( body_r ))
44 { setCommand( command_r ); }
45
48
49 Impl( const std::string & command_r, std::string &&body_r, HeaderInitializerList contents_r )
50 : _body(std::move( body_r ))
52
53 Impl( std::istream & stream_r );
54
55 public:
56 bool empty() const
57 { return _command.empty() && _body.empty(); }
58
59 const std::string & command() const
60 { return _command; }
61
62 void setCommand( const std::string & command_r )
63 {
64 if ( command_r.find( '\n' ) != std::string::npos )
65 ZYPP_THROW( PluginFrameException( "Multiline command", command_r ) );
67 }
68
69 const std::string & body() const
70 { return _body; }
71
72 std::string & bodyRef()
73 { return _body; }
74
75 void setBody( const std::string & body_r )
76 { _body = body_r; }
77
78 public:
79 using constKeyRange = std::pair<HeaderListIterator, HeaderListIterator>;
80 using KeyRange = std::pair<HeaderList::iterator, HeaderList::iterator>;
81
83 { return _header; }
84
85 const HeaderList & headerList() const
86 { return _header; }
87
88 const std::string & getHeader( const std::string & key_r ) const
89 {
90 constKeyRange r( _header.equal_range( key_r ) );
91 if ( r.first == r.second )
92 ZYPP_THROW( PluginFrameException( "No value for key", key_r ) );
93 const std::string & ret( r.first->second );
94 if ( ++r.first != r.second )
95 ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
96 return ret;
97 }
98
99 const std::string & getHeader( const std::string & key_r, const std::string & default_r ) const
100 {
101 constKeyRange r( _header.equal_range( key_r ) );
102 if ( r.first == r.second )
103 return default_r;
104 const std::string & ret( r.first->second );
105 if ( ++r.first != r.second )
106 ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
107 return ret;
108 }
109
110 const std::string & getHeaderNT( const std::string & key_r, const std::string & default_r ) const
111 {
113 return iter != _header.end() ? iter->second : default_r;
114 }
115
116 HeaderList::value_type mkHeaderPair( const std::string & key_r, const std::string & value_r )
117 {
118 if ( key_r.find_first_of( ":\n" ) != std::string::npos )
119 ZYPP_THROW( PluginFrameException( "Illegal char in header key", key_r ) );
120 if ( value_r.find_first_of( '\n' ) != std::string::npos )
121 ZYPP_THROW( PluginFrameException( "Illegal char in header value", value_r ) );
122 return HeaderList::value_type( key_r, value_r );
123 }
124
125 void setHeader( const std::string & key_r, const std::string & value_r )
126 {
129 }
130
131 void addHeader( const std::string & key_r, const std::string & value_r )
132 {
133 _header.insert( mkHeaderPair( key_r, value_r ) );
134 }
135
137 {
138 for ( const auto & el : contents_r )
139 addHeader( el.first, el.second );
140 }
141
142 void clearHeader( const std::string & key_r )
143 {
144 _header.erase( key_r );
145 }
146
147 public:
148 std::ostream & writeTo( std::ostream & stream_r ) const;
149
150 private:
151 std::string _command;
152 std::string _body;
154
155 public:
158 {
159 static shared_ptr<Impl> _nullimpl( new Impl );
160 return _nullimpl;
161 }
162 private:
163 friend Impl * rwcowClone<Impl>( const Impl * rhs );
165 Impl * clone() const
166 { return new Impl( *this ); }
167 };
169
171 inline std::ostream & operator<<( std::ostream & str, const PluginFrame::Impl & obj )
172 {
173 return str << "PluginFrame[" << obj.command() << "](" << obj.headerList().size() << "){" << obj.body().size() << "}";
174 }
175
177 {
178 //DBG << "Parse from " << stream_r << endl;
179 if ( ! stream_r )
180 ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
181
182 // JFYI: stream status after getline():
183 // Bool | Bits
184 // ------|---------------
185 // true | [g___] >FOO< : FOO line was \n-terminated
186 // true | [_e__] >BAA< : BAA before EOF, but not \n-terminated
187 // false | [_eF_] >< : No valid data to consume
188
189 //command
191 if ( ! stream_r.good() )
192 ZYPP_THROW( PluginFrameException( "Missing NL after command" ) );
193
194 // header
195 do {
196 std::string data = str::getline( stream_r );
197 if ( ! stream_r.good() )
198 ZYPP_THROW( PluginFrameException( "Missing NL after header" ) );
199
200 if ( data.empty() )
201 break; // --> empty line sep. header and body
202
203 std::string::size_type sep( data.find( ':') );
204 if ( sep == std::string::npos )
205 ZYPP_THROW( PluginFrameException( "Missing colon in header" ) );
206
207 _header.insert( HeaderList::value_type( data.substr(0,sep), data.substr(sep+1) ) );
208 } while ( true );
209
210 // data
212 if ( ! stream_r.good() )
213 ZYPP_THROW( PluginFrameException( "Missing NUL after body" ) );
214 }
215
216 std::ostream & PluginFrame::Impl::writeTo( std::ostream & stream_r ) const
217 {
218 //DBG << "Write " << *this << " to " << stream_r << endl;
219 if ( ! stream_r )
220 ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
221
222 // command
223 stream_r << _command << endl;
224 // header
225 for_( it, _header.begin(), _header.end() )
226 stream_r << it->first << ':' << it->second << endl;
227 // body
228 stream_r << endl
229 << _body << '\0';
230
231 if ( ! stream_r )
232 ZYPP_THROW( PluginFrameException( "Write error" ) );
233 return stream_r;
234 }
235
237 //
238 // CLASS NAME : PluginFrame
239 //
241
242 const std::string & PluginFrame::ackCommand()
243 {
244 static std::string _val( "ACK" );
245 return _val;
246 }
247
248 const std::string & PluginFrame::errorCommand()
249 {
250 static std::string _val( "ERROR" );
251 return _val;
252 }
253
254 const std::string & PluginFrame::enomethodCommand()
255 {
256 static std::string _val( "_ENOMETHOD" );
257 return _val;
258 }
259
261 : _pimpl( Impl::nullimpl() )
262 {}
263
264 PluginFrame::PluginFrame( const std::string & command_r )
265 : _pimpl( new Impl( command_r ) )
266 {}
267
268 PluginFrame::PluginFrame( const std::string & command_r, std::string body_r )
269 : _pimpl( new Impl( command_r, std::move(body_r) ) )
270 {}
271
275
277 : _pimpl( new Impl( command_r, std::move(body_r), contents_r ) )
278 {}
279
281 : _pimpl( new Impl( stream_r ) )
282 {}
283
285 { return _pimpl->empty(); }
286
287 const std::string & PluginFrame::command() const
288 { return _pimpl->command(); }
289
290 void PluginFrame::setCommand( const std::string & command_r )
291 { _pimpl->setCommand( command_r ); }
292
293 const std::string & PluginFrame::body() const
294 { return _pimpl->body(); }
295
296 std::string & PluginFrame::bodyRef()
297 { return _pimpl->bodyRef(); }
298
299 void PluginFrame::setBody( const std::string & body_r )
300 { _pimpl->setBody( body_r ); }
301
302 std::ostream & PluginFrame::writeTo( std::ostream & stream_r ) const
303 { return _pimpl->writeTo( stream_r ); }
304
306 { return _pimpl->headerList(); }
307
309 { return _pimpl->headerList(); }
310
311 const std::string & PluginFrame::getHeader( const std::string & key_r ) const
312 { return _pimpl->getHeader( key_r ); }
313
314 const std::string & PluginFrame::getHeader( const std::string & key_r, const std::string & default_r ) const
315 { return _pimpl->getHeader( key_r, default_r ); }
316
317 const std::string & PluginFrame::getHeaderNT( const std::string & key_r, const std::string & default_r ) const
318 { return _pimpl->getHeaderNT( key_r, default_r ); }
319
320 void PluginFrame::setHeader( const std::string & key_r, const std::string & value_r )
321 { _pimpl->setHeader( key_r, value_r ); }
322
323 void PluginFrame::addHeader( const std::string & key_r, const std::string & value_r )
324 { _pimpl->addHeader( key_r, value_r ); }
325
328
329 void PluginFrame::clearHeader( const std::string & key_r )
330 { _pimpl->clearHeader( key_r ); }
331
333
334 std::ostream & operator<<( std::ostream & str, const PluginFrame & obj )
335 { return str << *obj._pimpl; }
336
337 bool operator==( const PluginFrame & lhs, const PluginFrame & rhs )
338 {
339 return ( lhs._pimpl == rhs._pimpl )
340 || (( lhs.command() == rhs.command() ) && ( lhs.headerList() == rhs.headerList() ) && ( lhs.body() == rhs.body() ));
341 }
342
344} // namespace zypp
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
shared_ptr< Impl > _pimpl
Base class for PluginFrame Exception.
Command frame for communication with PluginScript.
Definition PluginFrame.h:41
static const std::string & ackCommand()
"ACK" command.
void setCommand(const std::string &command_r)
Set the frame command.
HeaderList::const_iterator HeaderListIterator
Header list iterator.
void setBody(const std::string &body_r)
Set the frame body.
const std::string & body() const
Return the frame body.
const std::initializer_list< std::pair< std::string, std::string > > & HeaderInitializerList
Definition PluginFrame.h:45
PluginFrame()
Default ctor (empty frame)
std::string & bodyRef()
Return a reference to the frame body.
void clearHeader(const std::string &key_r)
Remove all headers for key_r.
bool empty() const
Whether this is an empty frame.
static const std::string & enomethodCommand()
"_ENOMETHOD" command.
const std::string & command() const
Return the frame command.
void addHeader(const std::string &key_r, const std::string &value_r=std::string())
Add header for key_r leaving already existing headers for key_r unchanged.
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
static const std::string & errorCommand()
"ERROR" command.
const std::string & getHeader(const std::string &key_r) const
Return header value for key_r.
std::multimap< std::string, std::string > HeaderList
The header list.
HeaderList & headerList()
Modifyalble header list for internal use only.
void setHeader(const std::string &key_r, const std::string &value_r=std::string())
Set header for key_r removing all other occurrences of key_r.
const std::string & getHeaderNT(const std::string &key_r, const std::string &default_r=std::string()) const
Not throwing version returing one of the matching header values or default_r string.
std::ostream & writeTo(std::ostream &stream_r) const
Write frame to stream.
Definition Arch.h:364
String related utilities and Regular expression matching.
std::string receiveUpTo(std::istream &str, const char delim_r, bool returnDelim_r)
Return stream content up to the next ocurrence of delim_r or EOF delim_r, if found,...
Definition String.cc:489
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
Definition String.cc:479
Easy-to use interface to the ZYPP dependency resolver.
bool operator==(const SetRelation::Enum &lhs, const SetCompare &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
PluginFrame implementation.
std::ostream & writeTo(std::ostream &stream_r) const
const std::string & body() const
void setCommand(const std::string &command_r)
Impl(const std::string &command_r, HeaderInitializerList contents_r)
const std::string & getHeader(const std::string &key_r) const
Impl(const std::string &command_r, std::string &&body_r)
static shared_ptr< Impl > nullimpl()
Offer default Impl.
const std::string & command() const
const std::string & getHeaderNT(const std::string &key_r, const std::string &default_r) const
HeaderList & headerList()
Impl(const std::string &command_r)
const HeaderList & headerList() const
std::pair< HeaderListIterator, HeaderListIterator > constKeyRange
const std::string & getHeader(const std::string &key_r, const std::string &default_r) const
void setBody(const std::string &body_r)
std::string & bodyRef()
void setHeader(const std::string &key_r, const std::string &value_r)
void clearHeader(const std::string &key_r)
void addHeader(const std::string &key_r, const std::string &value_r)
std::pair< HeaderList::iterator, HeaderList::iterator > KeyRange
Impl * clone() const
clone for RWCOW_pointer
void addHeader(HeaderInitializerList contents_r)
HeaderList::value_type mkHeaderPair(const std::string &key_r, const std::string &value_r)
Impl(const std::string &command_r, std::string &&body_r, HeaderInitializerList contents_r)
std::ostream & operator<<(std::ostream &str, const PluginFrame::Impl &obj)
Stream output.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:429