Imported Upstream version 17.23.5
[platform/upstream/libzypp.git] / zypp / base / LogTools.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/base/LogTools.h
10  *
11 */
12 #ifndef ZYPP_BASE_LOGTOOLS_H
13 #define ZYPP_BASE_LOGTOOLS_H
14
15 #include <iostream>
16 #include <string>
17 #include <vector>
18 #include <list>
19 #include <set>
20 #include <map>
21
22 #include <zypp/base/Hash.h>
23 #include <zypp/base/Logger.h>
24 #include <zypp/base/Iterator.h>
25 #include <zypp/APIConfig.h>
26
27 ///////////////////////////////////////////////////////////////////
28 namespace zypp
29 { /////////////////////////////////////////////////////////////////
30
31   using std::endl;
32
33   /** Print range defined by iterators (multiline style).
34    * \code
35    * intro [ pfx ITEM [ { sep ITEM }+ ] sfx ] extro
36    * \endcode
37    *
38    * The defaults print the range enclosed in \c {}, one item per
39    * line indented by 2 spaces.
40    * \code
41    * {
42    *   item1
43    *   item2
44    * }
45    * {} // on empty range
46    * \endcode
47    *
48    * A comma separated list enclosed in \c () would be:
49    * \code
50    * dumpRange( stream, begin, end, "(", "", ", ", "", ")" );
51    * // or shorter:
52    * dumpRangeLine( stream, begin, end );
53    * \endcode
54    *
55    * \note Some special handling is required for printing std::maps.
56    * Therefore iomaipulators \ref dumpMap, \ref dumpKeys and \ref dumpValues
57    * are provided.
58    * \code
59    * std::map<string,int> m;
60    * m["a"]=1;
61    * m["b"]=2;
62    * m["c"]=3;
63    *
64    * dumpRange( DBG, dumpMap(m).begin(), dumpMap(m).end() ) << endl;
65    * // {
66    * //   [a] = 1
67    * //   [b] = 2
68    * //   [c] = 3
69    * // }
70    * dumpRange( DBG, dumpKeys(m).begin(), dumpKeys(m).end() ) << endl;
71    * // {
72    * //   a
73    * //   b
74    * //   c
75    * // }
76    * dumpRange( DBG, dumpValues(m).begin(), dumpValues(m).end() ) << endl;
77    * // {
78    * //   1
79    * //   2
80    * //   3
81    * // }
82    * dumpRangeLine( DBG, dumpMap(m).begin(), dumpMap(m).end() ) << endl;
83    * // ([a] = 1, [b] = 2, [c] = 3)
84    * dumpRangeLine( DBG, dumpKeys(m).begin(), dumpKeys(m).end() ) << endl;
85    * // (a, b, c)
86    * dumpRangeLine( DBG, dumpValues(m).begin(), dumpValues(m).end() ) << endl;
87    * // (1, 2, 3)
88    * \endcode
89   */
90   template<class TIterator>
91     std::ostream & dumpRange( std::ostream & str,
92                               TIterator begin, TIterator end,
93                               const std::string & intro = "{",
94                               const std::string & pfx   = "\n  ",
95                               const std::string & sep   = "\n  ",
96                               const std::string & sfx   = "\n",
97                               const std::string & extro = "}" )
98     {
99       str << intro;
100       if ( begin != end )
101         {
102           str << pfx << *begin;
103           for (  ++begin; begin != end; ++begin )
104             str << sep << *begin;
105           str << sfx;
106         }
107       return str << extro;
108     }
109
110   /** Print range defined by iterators (single line style).
111    * \see dumpRange
112    */
113   template<class TIterator>
114     std::ostream & dumpRangeLine( std::ostream & str,
115                                   TIterator begin, TIterator end )
116     { return dumpRange( str, begin, end, "(", "", ", ", "", ")" ); }
117   /** \overload for container */
118   template<class TContainer>
119     std::ostream & dumpRangeLine( std::ostream & str, const TContainer & cont )
120     { return dumpRangeLine( str, cont.begin(), cont.end() ); }
121
122
123   ///////////////////////////////////////////////////////////////////
124   namespace iomanip
125   {
126     ///////////////////////////////////////////////////////////////////
127     /// \class RangeLine<TIterator>
128     /// \brief Iomanip helper printing dumpRangeLine style
129     ///////////////////////////////////////////////////////////////////
130     template<class TIterator>
131     struct RangeLine
132     {
133       RangeLine( TIterator begin, TIterator end )
134       : _begin( begin )
135       , _end( end )
136       {}
137       TIterator _begin;
138       TIterator _end;
139     };
140
141     /** \relates RangeLine<TIterator> */
142     template<class TIterator>
143     std::ostream & operator<<( std::ostream & str, const RangeLine<TIterator> & obj )
144     { return dumpRangeLine( str, obj._begin, obj._end ); }
145
146   } // namespce iomanip
147   ///////////////////////////////////////////////////////////////////
148
149   /** Iomanip printing dumpRangeLine style
150    * \code
151    *   std::vector<int> c( { 1, 1, 2, 3, 5, 8 } );
152    *   std::cout << rangeLine(c) << std::endl;
153    *   -> (1, 1, 2, 3, 5, 8)
154    * \endcode
155    */
156   template<class TIterator>
157   iomanip::RangeLine<TIterator> rangeLine( TIterator begin, TIterator end )
158   { return iomanip::RangeLine<TIterator>( begin, end ); }
159   /** \overload for container */
160   template<class TContainer>
161   auto rangeLine( const TContainer & cont ) -> decltype( rangeLine( cont.begin(), cont.end() ) )
162   { return rangeLine( cont.begin(), cont.end() ); }
163
164   template<class Tp>
165     std::ostream & operator<<( std::ostream & str, const std::vector<Tp> & obj )
166     { return dumpRange( str, obj.begin(), obj.end() ); }
167
168   template<class Tp, class TCmp, class TAlloc>
169     std::ostream & operator<<( std::ostream & str, const std::set<Tp,TCmp,TAlloc> & obj )
170     { return dumpRange( str, obj.begin(), obj.end() ); }
171
172   template<class Tp>
173     std::ostream & operator<<( std::ostream & str, const std::unordered_set<Tp> & obj )
174     { return dumpRange( str, obj.begin(), obj.end() ); }
175
176   template<class Tp>
177     std::ostream & operator<<( std::ostream & str, const std::multiset<Tp> & obj )
178     { return dumpRange( str, obj.begin(), obj.end() ); }
179
180   template<class Tp>
181     std::ostream & operator<<( std::ostream & str, const std::list<Tp> & obj )
182     { return dumpRange( str, obj.begin(), obj.end() ); }
183
184   template<class Tp>
185     std::ostream & operator<<( std::ostream & str, const Iterable<Tp> & obj )
186     { return dumpRange( str, obj.begin(), obj.end() ); }
187
188   ///////////////////////////////////////////////////////////////////
189   namespace _logtoolsdetail
190   { /////////////////////////////////////////////////////////////////
191
192     ///////////////////////////////////////////////////////////////////
193     // mapEntry
194     ///////////////////////////////////////////////////////////////////
195
196     /** std::pair wrapper for std::map output.
197      * Just because we want a special output format for std::pair
198      * used in a std::map. The mapped std::pair is printed as
199      * <tt>[key] = value</tt>.
200     */
201     template<class TPair>
202       class MapEntry
203       {
204       public:
205         MapEntry( const TPair & pair_r )
206         : _pair( &pair_r )
207         {}
208
209         const TPair & pair() const
210         { return *_pair; }
211
212       private:
213         const TPair *const _pair;
214       };
215
216     /** \relates MapEntry Stream output. */
217     template<class TPair>
218       std::ostream & operator<<( std::ostream & str, const MapEntry<TPair> & obj )
219       {
220         return str << '[' << obj.pair().first << "] = " << obj.pair().second;
221       }
222
223     /** \relates MapEntry Convenience function to create MapEntry from std::pair. */
224     template<class TPair>
225       MapEntry<TPair> mapEntry( const TPair & pair_r )
226       { return MapEntry<TPair>( pair_r ); }
227
228     ///////////////////////////////////////////////////////////////////
229     // dumpMap
230     ///////////////////////////////////////////////////////////////////
231
232     /** std::map wrapper for stream output.
233      * Uses a transform_iterator to wrap the std::pair into MapEntry.
234      *
235      */
236     template<class TMap>
237       class DumpMap
238       {
239       public:
240         typedef TMap                        MapType;
241         typedef typename TMap::value_type   PairType;
242         typedef MapEntry<PairType>          MapEntryType;
243
244         struct Transformer : public std::unary_function<PairType, MapEntryType>
245         {
246           MapEntryType operator()( const PairType & pair_r ) const
247           { return mapEntry( pair_r ); }
248         };
249
250         typedef transform_iterator<Transformer, typename MapType::const_iterator>
251                 MapEntry_const_iterator;
252
253       public:
254         DumpMap( const TMap & map_r )
255         : _map( &map_r )
256         {}
257
258         const TMap & map() const
259         { return *_map; }
260
261         MapEntry_const_iterator begin() const
262         { return make_transform_iterator( map().begin(), Transformer() ); }
263
264         MapEntry_const_iterator end() const
265         { return make_transform_iterator( map().end(), Transformer() );}
266
267       private:
268         const TMap *const _map;
269       };
270
271     /** \relates DumpMap Stream output. */
272     template<class TMap>
273       std::ostream & operator<<( std::ostream & str, const DumpMap<TMap> & obj )
274       { return dumpRange( str, obj.begin(), obj.end() ); }
275
276     /** \relates DumpMap Convenience function to create DumpMap from std::map. */
277     template<class TMap>
278       DumpMap<TMap> dumpMap( const TMap & map_r )
279       { return DumpMap<TMap>( map_r ); }
280
281     ///////////////////////////////////////////////////////////////////
282     // dumpKeys
283     ///////////////////////////////////////////////////////////////////
284
285     /** std::map wrapper for stream output of keys.
286      * Uses MapKVIterator iterate and write the key values.
287      * \code
288      * std::map<...> mymap;
289      * std::cout << dumpKeys(mymap) << std::endl;
290      * \endcode
291      */
292     template<class TMap>
293       class DumpKeys
294       {
295       public:
296         typedef typename MapKVIteratorTraits<TMap>::Key_const_iterator MapKey_const_iterator;
297
298       public:
299         DumpKeys( const TMap & map_r )
300         : _map( &map_r )
301         {}
302
303         const TMap & map() const
304         { return *_map; }
305
306         MapKey_const_iterator begin() const
307         { return make_map_key_begin( map() ); }
308
309         MapKey_const_iterator end() const
310         { return make_map_key_end( map() ); }
311
312       private:
313         const TMap *const _map;
314       };
315
316     /** \relates DumpKeys Stream output. */
317     template<class TMap>
318       std::ostream & operator<<( std::ostream & str, const DumpKeys<TMap> & obj )
319       { return dumpRange( str, obj.begin(), obj.end() ); }
320
321     /** \relates DumpKeys Convenience function to create DumpKeys from std::map. */
322     template<class TMap>
323       DumpKeys<TMap> dumpKeys( const TMap & map_r )
324       { return DumpKeys<TMap>( map_r ); }
325
326     ///////////////////////////////////////////////////////////////////
327     // dumpValues
328     ///////////////////////////////////////////////////////////////////
329
330     /** std::map wrapper for stream output of values.
331      * Uses MapKVIterator iterate and write the values.
332      * \code
333      * std::map<...> mymap;
334      * std::cout << dumpValues(mymap) << std::endl;
335      * \endcode
336      */
337     template<class TMap>
338       class DumpValues
339       {
340       public:
341         typedef typename MapKVIteratorTraits<TMap>::Value_const_iterator MapValue_const_iterator;
342
343       public:
344         DumpValues( const TMap & map_r )
345         : _map( &map_r )
346         {}
347
348         const TMap & map() const
349         { return *_map; }
350
351         MapValue_const_iterator begin() const
352         { return make_map_value_begin( map() ); }
353
354         MapValue_const_iterator end() const
355         { return make_map_value_end( map() ); }
356
357       private:
358         const TMap *const _map;
359       };
360
361     /** \relates DumpValues Stream output. */
362     template<class TMap>
363       std::ostream & operator<<( std::ostream & str, const DumpValues<TMap> & obj )
364       { return dumpRange( str, obj.begin(), obj.end() ); }
365
366     /** \relates DumpValues Convenience function to create DumpValues from std::map. */
367     template<class TMap>
368       DumpValues<TMap> dumpValues( const TMap & map_r )
369       { return DumpValues<TMap>( map_r ); }
370
371     /////////////////////////////////////////////////////////////////
372   } // namespace _logtoolsdetail
373   ///////////////////////////////////////////////////////////////////
374
375   // iomanipulator
376   using _logtoolsdetail::mapEntry;   // std::pair as '[key] = value'
377   using _logtoolsdetail::dumpMap;    // dumpRange '[key] = value'
378   using _logtoolsdetail::dumpKeys;   // dumpRange keys
379   using _logtoolsdetail::dumpValues; // dumpRange values
380
381   template<class TKey, class Tp>
382     std::ostream & operator<<( std::ostream & str, const std::map<TKey, Tp> & obj )
383     { return str << dumpMap( obj ); }
384
385   template<class TKey, class Tp>
386     std::ostream & operator<<( std::ostream & str, const std::unordered_map<TKey, Tp> & obj )
387     { return str << dumpMap( obj ); }
388
389   template<class TKey, class Tp>
390     std::ostream & operator<<( std::ostream & str, const std::multimap<TKey, Tp> & obj )
391     { return str << dumpMap( obj ); }
392
393   /** Print stream status bits.
394    * Prints the values of a streams \c good, \c eof, \c failed and \c bad bit.
395    *
396    * \code
397    *  [g___] - good
398    *  [_eF_] - eof and fail bit set
399    *  [__FB] - fail and bad bit set
400    * \endcode
401   */
402   inline std::ostream & operator<<( std::ostream & str, const std::basic_ios<char> & obj )
403   {
404     std::string ret( "[" );
405     ret += ( obj.good() ? 'g' : '_' );
406     ret += ( obj.eof()  ? 'e' : '_' );
407     ret += ( obj.fail() ? 'F' : '_' );
408     ret += ( obj.bad()  ? 'B' : '_' );
409     ret += "]";
410     return str << ret;
411   }
412
413   ///////////////////////////////////////////////////////////////////
414   // iomanipulator: str << dump(val) << ...
415   // calls:         std::ostream & dumpOn( std::ostream & str, const Type & obj )
416   ///////////////////////////////////////////////////////////////////
417
418   namespace detail
419   {
420     template<class Tp>
421     struct Dump
422     {
423       Dump( const Tp & obj_r ) : _obj( obj_r ) {}
424       const Tp & _obj;
425     };
426
427     template<class Tp>
428     std::ostream & operator<<( std::ostream & str, const Dump<Tp> & obj )
429     { return dumpOn( str, obj._obj ); }
430   }
431
432   template<class Tp>
433   detail::Dump<Tp> dump( const Tp & obj_r )
434   { return detail::Dump<Tp>(obj_r); }
435
436
437   /////////////////////////////////////////////////////////////////
438 } // namespace zypp
439 ///////////////////////////////////////////////////////////////////
440 #endif // ZYPP_BASE_LOGTOOLS_H