Imported Upstream version 15.0.0
[platform/upstream/libzypp.git] / zypp / PluginFrame.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/PluginFrame.h
10  *
11 */
12 #ifndef ZYPP_PLUGINFRAME_H
13 #define ZYPP_PLUGINFRAME_H
14
15 #include <iosfwd>
16 #include <string>
17 #include <map>
18
19 #include "zypp/base/PtrTypes.h"
20
21 #include "zypp/PluginFrameException.h"
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27   /** Command frame for communication with \ref PluginScript
28    *
29    * \code
30    *   COMMAND
31    *   key:value header lines
32    *
33    *   multiline body separated from header
34    *   by an empty line and terminated by NUL.
35    *   ^@
36    * \endcode
37    *
38    * \see PluginScript
39    */
40   class PluginFrame
41   {
42     friend std::ostream & operator<<( std::ostream & str, const PluginFrame & obj );
43     friend bool operator==( const PluginFrame & lhs, const PluginFrame & rhs );
44
45     typedef const std::initializer_list<std::pair<std::string,std::string>> & HeaderInitializerList;
46
47     public:
48       /** "ACK" command. */
49       static const std::string & ackCommand();
50       /** "ERROR" command. */
51       static const std::string & errorCommand();
52       /** "_ENOMETHOD" command. */
53       static const std::string & enomethodCommand();
54
55     public:
56       /** Default exception type */
57       typedef PluginFrameException Exception;
58
59       /** Default ctor (empty frame) */
60       PluginFrame();
61
62       /** Ctor taking the command
63        * \throw PluginFrameException If \ref setCommand throws
64        */
65       PluginFrame( const std::string & command_r );
66
67       /** Ctor taking command and body
68        * \throw PluginFrameException If \ref setCommand throws
69        */
70       PluginFrame( const std::string & command_r, const std::string & body_r );
71
72       /** Ctor taking the command and a HeaderInitializerList
73        * \throw PluginFrameException If \ref setCommand throws
74        */
75       PluginFrame( const std::string & command_r, HeaderInitializerList contents_r );
76
77       /** Ctor taking command, body and a HeaderInitializerList
78        * \throw PluginFrameException If \ref setCommand throws
79        */
80       PluginFrame( const std::string & command_r, const std::string & body_r, HeaderInitializerList contents_r );
81
82       /** Ctor reading frame data from a stream
83        * \throw PluginFrameException On error reading from stream
84        * \throw PluginFrameException On error parsing the data
85        */
86       PluginFrame( std::istream & stream_r );
87
88     public:
89       /** Whether this is an empty frame. */
90       bool empty() const;
91
92       /** Evaluate in a boolean context (empty frame) */
93       explicit operator bool() const
94       { return empty(); }
95
96     public:
97       /** Return the frame command. */
98       const std::string & command() const;
99
100       /** Set the frame command
101        * \throw PluginFrameException If illegal command string (e.g. multiline)
102        */
103       void setCommand( const std::string & command_r );
104
105       /** Convenience to identify an ACK command. */
106       bool isAckCommand() const
107       { return command() == ackCommand(); }
108
109       /** Convenience to identify an ERROR command. */
110       bool isErrorCommand() const
111       {return command() == errorCommand(); }
112
113       /** Convenience to identify an _ENOMETHOD command. */
114       bool isEnomethodCommand() const
115       {return command() == enomethodCommand(); }
116
117       /** Return the frame body. */
118       const std::string & body() const;
119
120       /** Return a reference to the frame body.
121        * This may avoid creating unnecessary copies if you
122        * want to manipulate large body data.
123        * \code
124        *   std::string tmp;
125        *   frame.bodyRef().swap( tmp );
126        * \endcode
127        */
128       std::string & bodyRef();
129
130       /** Set the frame body */
131       void setBody( const std::string & body_r );
132
133     public:
134       /** The header list */
135       typedef std::multimap<std::string, std::string> HeaderList;
136
137       /** Header list iterator */
138       typedef HeaderList::const_iterator HeaderListIterator;
139
140     private:
141       /** Modifyalble header list for internal use only. */
142       HeaderList & headerList();
143
144     public:
145       /** The header list. */
146       const HeaderList & headerList() const;
147
148       /** Whether header list is empty. */
149       bool headerEmpty() const
150       { return headerList().empty(); }
151
152       /** Return size of the header list. */
153       unsigned headerSize() const
154       { return headerList().size(); }
155
156       /** Return iterator pointing to the 1st header (or \ref headerEnd) */
157       HeaderListIterator headerBegin() const
158       { return headerList().begin(); }
159
160       /** Return iterator pointing behind the last header. */
161       HeaderListIterator headerEnd() const
162       { return headerList().end(); }
163
164       /** Clear the list of headers. */
165       void headerClear()
166       { headerList().clear(); }
167
168
169       /** Whether the header list contains at least one entry for \c key_r. */
170       bool hasKey( const std::string & key_r ) const
171       { return ! keyEmpty( key_r ); }
172
173       /** \overload */
174       bool keyEmpty( const std::string & key_r ) const
175       { return headerList().find( key_r ) == headerEnd(); }
176
177       /** Return number of header entires for \c key_r. */
178       bool keySize( const std::string & key_r ) const
179       { return headerList().count( key_r ); }
180
181       /** Return iterator pointing to the 1st header for \c key_r (or \ref keyEnd(key_r)) */
182       HeaderListIterator keyBegin( const std::string & key_r ) const
183       { return headerList().lower_bound( key_r ); }
184
185       /** Return iterator pointing behind the last header for \c key_r.*/
186       HeaderListIterator keyEnd( const std::string & key_r ) const
187       { return headerList().upper_bound( key_r ); }
188
189
190       /** Return header value for \c key_r.
191        * \throw PluginFrameException If no header for key_r exists.
192        * \throw PluginFrameException If multiple header for key_r exist.
193        */
194       const std::string & getHeader( const std::string & key_r ) const;
195
196       /** Return header value for \c key_r or \c default_r if it does not exist.
197        * \throw PluginFrameException If multiple header for key_r exist.
198        */
199       const std::string & getHeader( const std::string & key_r, const std::string & default_r ) const;
200
201       /** Not throwing version returing one of the matching header values or \c default_r string. */
202       const std::string & getHeaderNT( const std::string & key_r, const std::string & default_r = std::string() ) const;
203
204       /** Set header for \c key_r removing all other occurences of \c key_r.
205        * \throw PluginFrameException If key contains illegal chars (\c NL or \c :)
206        * \throw PluginFrameException If value contains illegal chars (\c NL)
207        */
208       void setHeader( const std::string & key_r, const std::string & value_r = std::string() );
209
210       /** Set a new header list
211        * \throw PluginFrameException If key contains illegal chars (\c NL or \c :)
212        * \throw PluginFrameException If value contains illegal chars (\c NL)
213        */
214       void setHeader( HeaderInitializerList contents_r )
215       { headerList().clear(); addHeader( contents_r ); }
216
217       /** Add header for \c key_r leaving already existing headers for \c key_r unchanged.
218        * \throw PluginFrameException If key contains illegal chars (\c NL or \c :)
219        * \throw PluginFrameException If value contains illegal chars (\c NL)
220        */
221       void addHeader( const std::string & key_r, const std::string & value_r = std::string() );
222       /** \overload taking an initializer_list */
223       void addHeader( HeaderInitializerList contents_r );
224
225       /** Remove all headers for \c key_r. */
226       void clearHeader( const std::string & key_r );
227
228     public:
229       /** Write frame to stream
230        * \throw PluginFrameException On error writing to stream
231        */
232       std::ostream & writeTo( std::ostream & stream_r ) const;
233
234       /** \overload Static version. */
235       static std::ostream & writeTo( std::ostream & stream_r, const PluginFrame & frame_r )
236       { return frame_r.writeTo( stream_r ); }
237
238       /** Read frame from stream
239        * \throw PluginFrameException If \ref PluginFrame(std::istream&) throws
240        */
241       std::istream & readFrom( std::istream & stream_r )
242       { *this = PluginFrame( stream_r ); return stream_r; }
243
244       /** \overload Static version. */
245       static std::istream & readFrom( std::istream & stream_r, PluginFrame & frame_r )
246       { frame_r = PluginFrame( stream_r ); return stream_r; }
247
248     public:
249       /** Implementation */
250       class Impl;
251     private:
252       /** Pointer to implementation */
253       RWCOW_pointer<Impl> _pimpl;
254   };
255
256   /** \relates PluginFrame Stream output for logging */
257   std::ostream & operator<<( std::ostream & str, const PluginFrame & obj );
258
259   /** \relates PluginFrame Stream output sending all data */
260   inline std::ostream & dumpOn( std::ostream & str, const PluginFrame & obj )
261   { return PluginFrame::writeTo( str, obj ); }
262
263   /** \relates PluginFrame Construct from stream. */
264   inline std::istream & operator>>( std::istream & str, PluginFrame & obj )
265   { return PluginFrame::readFrom( str, obj ); }
266
267   /** \relates PluginFrame Comparison based on content. */
268   bool operator==( const PluginFrame & lhs, const PluginFrame & rhs );
269
270   /** \relates PluginFrame Comparison based on content. */
271   inline bool operator!=( const PluginFrame & lhs, const PluginFrame & rhs )
272   { return( ! operator==( lhs, rhs ) ); }
273
274   /////////////////////////////////////////////////////////////////
275 } // namespace zypp
276 ///////////////////////////////////////////////////////////////////
277 #endif // ZYPP_PLUGINFRAME_H