Fix string hexdecoding
[platform/upstream/libzypp.git] / zypp / base / IOStream.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/base/IOStream.h
10  *
11 */
12 #ifndef ZYPP_BASE_IOSTREAM_H
13 #define ZYPP_BASE_IOSTREAM_H
14
15 #include <iosfwd>
16 #include <boost/io/ios_state.hpp>
17
18 #include "zypp/base/Flags.h"
19 #include "zypp/base/PtrTypes.h"
20 #include "zypp/base/Function.h"
21 #include "zypp/base/NonCopyable.h"
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26   ///////////////////////////////////////////////////////////////////
27   /** Iostream related utilities.
28   */
29   namespace iostr
30   { /////////////////////////////////////////////////////////////////
31
32     /** Save and restore streams \c width, \c precision
33      * and \c fmtflags.
34      */
35     typedef boost::io::ios_base_all_saver IosFmtFlagsSaver;
36
37
38     /** Read one line from stream.
39      *
40      * Reads everything up to the next newline or EOF. newline
41      * is read but not returned.
42      *
43      * \see \ref forEachLine
44      */
45     std::string getline( std::istream & str );
46
47     /** Copy istream to ostream.
48      * \return reference to the ostream.
49      */
50     inline std::ostream & copy( std::istream & from_r, std::ostream & to_r )
51     {
52       if ( from_r && to_r )
53       {
54         char ch;
55         while ( from_r && from_r.get( ch ) )
56           to_r.put( ch );
57       }
58       return to_r;
59     }
60
61     /** Copy istream to ostream, prefixing each line with \a indent_r (default <tt>"> "</tt> ).
62      * \return reference to the ostream.
63      */
64     inline std::ostream & copyIndent( std::istream & from_r, std::ostream & to_r, const std::string & indent_r = "> " )
65     {
66       if ( from_r && to_r )
67       {
68         char ch;
69         bool indent = true;
70         while ( from_r && from_r.get( ch ) )
71         {
72           if ( indent )
73             to_r << indent_r;
74           indent = ( ch == '\n' );
75           to_r.put( ch );
76         }
77       }
78       return to_r;
79     }
80
81     /** Copy istream to ostream, prefixing each line with \a indent_r (default <tt>"> "</tt> ).
82      * \return reference to the ostream.
83      */
84     inline void tee( std::istream & from_r, std::ostream & to1_r, std::ostream & to2_r )
85     {
86       if ( from_r && ( to1_r ||to2_r ) )
87       {
88         char ch;
89         while ( from_r && from_r.get( ch ) )
90         {
91           to1_r.put( ch );
92           to2_r.put( ch );
93         }
94       }
95     }
96
97     ///////////////////////////////////////////////////////////////////
98     //
99     //  CLASS NAME : EachLine
100     //
101     /** Simple lineparser: Traverse each line in a file.
102      *
103      * \code
104      * std::ifstream infile( "somefile" );
105      * for( iostr::EachLine in( infile ); in; in.next() )
106      * {
107      *   DBG << *in << endl;
108      * }
109      * \endcode
110      */
111     class EachLine : private base::NonCopyable
112     {
113       public:
114         /** Ctor taking a stream and reading the 1st line from it. */
115         EachLine( std::istream & str_r, unsigned lineNo_r = 0 );
116
117         /** Whether \c this contains a valid line to consume. */
118         bool valid() const
119         { return _valid; }
120
121         /** Evaluate class in a boolean context. */
122         explicit operator bool() const
123         { return _valid; }
124
125         /** Return the current line number. */
126         unsigned lineNo() const
127         { return _lineNo; }
128
129         std::streamoff lineStart() const
130         { return _lineStart; };
131
132         /** Set current line number. */
133         void setLineNo( unsigned lineNo_r )
134         { _lineNo = lineNo_r; }
135
136         /** Access the current line. */
137         const std::string & operator*() const
138         { return _line; }
139         /** \overload non const access */
140         std::string & operator*()
141         { return _line; }
142
143         /** Access the current line. */
144         const std::string * operator->() const
145         { return &_line; }
146
147         /** Advance to next line. */
148         bool next();
149
150         /** Advance \a num_r lines. */
151         bool next( unsigned num_r )
152         {
153           while ( num_r-- && next() )
154             ; /* EMPTY */
155           return valid();
156         }
157
158       private:
159         std::istream & _str;
160         std::string    _line;
161         std::streamoff _lineStart;
162         unsigned       _lineNo;
163         bool           _valid;
164     };
165     ///////////////////////////////////////////////////////////////////
166
167     /** Simple lineparser: Call functor \a consume_r for each line.
168      *
169      * \param str_r istream to read from.
170      * \param consume_r callback function taking linenumber and content
171      *
172      * The loop is aborted if the callback  returns \c false.
173      *
174      * \code
175      *   iostr::forEachLine( InputStream( "/my/file/to/read.txt" ),
176      *                       []( int num_r, std::string line_r )->bool
177      *                       {
178      *                         MIL << " [" num_r << "]'" << line_r << "'" << endl;
179      *                         return true;
180      *                       } );
181      * \endcode
182      *
183      * \return Number if lines consumed (negative if aborted by callback).
184      */
185      int forEachLine( std::istream & str_r, function<bool(int, std::string)> consume_r );
186
187      /** \ref simpleParseFile modifications before consuming a line. */
188      enum ParseFlag
189      {
190        PF_LTRIM                 = 1 << 0,               //< left trim whitespace
191        PF_RTRIM                 = 1 << 1,               //< right trim whitespace
192        PF_TRIM                  = PF_LTRIM | PF_RTRIM,  //< trim whitespace
193        PF_SKIP_EMPTY            = 1 << 2,               //< skip lines containing whitespace only
194        PF_SKIP_SHARP_COMMENT    = 1 << 3                //< skip lines beginning with '#'
195      };
196      ZYPP_DECLARE_FLAGS( ParseFlags, ParseFlag );
197      ZYPP_DECLARE_OPERATORS_FOR_FLAGS( ParseFlags );
198
199      /** Simple lineparser optionally trimming and skipping comments. */
200      int simpleParseFile( std::istream & str_r, ParseFlags flags_r, function<bool(int, std::string)> consume_r );
201
202      /** \overload trimming lines, skipping '#'-comments and empty lines. */
203      inline int simpleParseFile( std::istream & str_r, function<bool(int, std::string)> consume_r )
204      { return simpleParseFile( str_r, PF_TRIM | PF_SKIP_EMPTY | PF_SKIP_SHARP_COMMENT , consume_r ); }
205
206     /////////////////////////////////////////////////////////////////
207   } // namespace iostr
208   ///////////////////////////////////////////////////////////////////
209   /////////////////////////////////////////////////////////////////
210 } // namespace zypp
211 ///////////////////////////////////////////////////////////////////
212 #endif // ZYPP_BASE_IOSTREAM_H