Imported Upstream version 16.6.1
[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   ///////////////////////////////////////////////////////////////////
185   namespace _logtoolsdetail
186   { /////////////////////////////////////////////////////////////////
187
188     ///////////////////////////////////////////////////////////////////
189     // mapEntry
190     ///////////////////////////////////////////////////////////////////
191
192     /** std::pair wrapper for std::map output.
193      * Just because we want a special output format for std::pair
194      * used in a std::map. The mapped std::pair is printed as
195      * <tt>[key] = value</tt>.
196     */
197     template<class TPair>
198       class MapEntry
199       {
200       public:
201         MapEntry( const TPair & pair_r )
202         : _pair( &pair_r )
203         {}
204
205         const TPair & pair() const
206         { return *_pair; }
207
208       private:
209         const TPair *const _pair;
210       };
211
212     /** \relates MapEntry Stream output. */
213     template<class TPair>
214       std::ostream & operator<<( std::ostream & str, const MapEntry<TPair> & obj )
215       {
216         return str << '[' << obj.pair().first << "] = " << obj.pair().second;
217       }
218
219     /** \relates MapEntry Convenience function to create MapEntry from std::pair. */
220     template<class TPair>
221       MapEntry<TPair> mapEntry( const TPair & pair_r )
222       { return MapEntry<TPair>( pair_r ); }
223
224     ///////////////////////////////////////////////////////////////////
225     // dumpMap
226     ///////////////////////////////////////////////////////////////////
227
228     /** std::map wrapper for stream output.
229      * Uses a transform_iterator to wrap the std::pair into MapEntry.
230      *
231      */
232     template<class TMap>
233       class DumpMap
234       {
235       public:
236         typedef TMap                        MapType;
237         typedef typename TMap::value_type   PairType;
238         typedef MapEntry<PairType>          MapEntryType;
239
240         struct Transformer : public std::unary_function<PairType, MapEntryType>
241         {
242           MapEntryType operator()( const PairType & pair_r ) const
243           { return mapEntry( pair_r ); }
244         };
245
246         typedef transform_iterator<Transformer, typename MapType::const_iterator>
247                 MapEntry_const_iterator;
248
249       public:
250         DumpMap( const TMap & map_r )
251         : _map( &map_r )
252         {}
253
254         const TMap & map() const
255         { return *_map; }
256
257         MapEntry_const_iterator begin() const
258         { return make_transform_iterator( map().begin(), Transformer() ); }
259
260         MapEntry_const_iterator end() const
261         { return make_transform_iterator( map().end(), Transformer() );}
262
263       private:
264         const TMap *const _map;
265       };
266
267     /** \relates DumpMap Stream output. */
268     template<class TMap>
269       std::ostream & operator<<( std::ostream & str, const DumpMap<TMap> & obj )
270       { return dumpRange( str, obj.begin(), obj.end() ); }
271
272     /** \relates DumpMap Convenience function to create DumpMap from std::map. */
273     template<class TMap>
274       DumpMap<TMap> dumpMap( const TMap & map_r )
275       { return DumpMap<TMap>( map_r ); }
276
277     ///////////////////////////////////////////////////////////////////
278     // dumpKeys
279     ///////////////////////////////////////////////////////////////////
280
281     /** std::map wrapper for stream output of keys.
282      * Uses MapKVIterator iterate and write the key values.
283      * \code
284      * std::map<...> mymap;
285      * std::cout << dumpKeys(mymap) << std::endl;
286      * \endcode
287      */
288     template<class TMap>
289       class DumpKeys
290       {
291       public:
292         typedef typename MapKVIteratorTraits<TMap>::Key_const_iterator MapKey_const_iterator;
293
294       public:
295         DumpKeys( const TMap & map_r )
296         : _map( &map_r )
297         {}
298
299         const TMap & map() const
300         { return *_map; }
301
302         MapKey_const_iterator begin() const
303         { return make_map_key_begin( map() ); }
304
305         MapKey_const_iterator end() const
306         { return make_map_key_end( map() ); }
307
308       private:
309         const TMap *const _map;
310       };
311
312     /** \relates DumpKeys Stream output. */
313     template<class TMap>
314       std::ostream & operator<<( std::ostream & str, const DumpKeys<TMap> & obj )
315       { return dumpRange( str, obj.begin(), obj.end() ); }
316
317     /** \relates DumpKeys Convenience function to create DumpKeys from std::map. */
318     template<class TMap>
319       DumpKeys<TMap> dumpKeys( const TMap & map_r )
320       { return DumpKeys<TMap>( map_r ); }
321
322     ///////////////////////////////////////////////////////////////////
323     // dumpValues
324     ///////////////////////////////////////////////////////////////////
325
326     /** std::map wrapper for stream output of values.
327      * Uses MapKVIterator iterate and write the values.
328      * \code
329      * std::map<...> mymap;
330      * std::cout << dumpValues(mymap) << std::endl;
331      * \endcode
332      */
333     template<class TMap>
334       class DumpValues
335       {
336       public:
337         typedef typename MapKVIteratorTraits<TMap>::Value_const_iterator MapValue_const_iterator;
338
339       public:
340         DumpValues( const TMap & map_r )
341         : _map( &map_r )
342         {}
343
344         const TMap & map() const
345         { return *_map; }
346
347         MapValue_const_iterator begin() const
348         { return make_map_value_begin( map() ); }
349
350         MapValue_const_iterator end() const
351         { return make_map_value_end( map() ); }
352
353       private:
354         const TMap *const _map;
355       };
356
357     /** \relates DumpValues Stream output. */
358     template<class TMap>
359       std::ostream & operator<<( std::ostream & str, const DumpValues<TMap> & obj )
360       { return dumpRange( str, obj.begin(), obj.end() ); }
361
362     /** \relates DumpValues Convenience function to create DumpValues from std::map. */
363     template<class TMap>
364       DumpValues<TMap> dumpValues( const TMap & map_r )
365       { return DumpValues<TMap>( map_r ); }
366
367     /////////////////////////////////////////////////////////////////
368   } // namespace _logtoolsdetail
369   ///////////////////////////////////////////////////////////////////
370
371   // iomanipulator
372   using _logtoolsdetail::mapEntry;   // std::pair as '[key] = value'
373   using _logtoolsdetail::dumpMap;    // dumpRange '[key] = value'
374   using _logtoolsdetail::dumpKeys;   // dumpRange keys
375   using _logtoolsdetail::dumpValues; // dumpRange values
376
377   template<class TKey, class Tp>
378     std::ostream & operator<<( std::ostream & str, const std::map<TKey, Tp> & obj )
379     { return str << dumpMap( obj ); }
380
381   template<class TKey, class Tp>
382     std::ostream & operator<<( std::ostream & str, const std::unordered_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::multimap<TKey, Tp> & obj )
387     { return str << dumpMap( obj ); }
388
389   /** Print stream status bits.
390    * Prints the values of a streams \c good, \c eof, \c failed and \c bad bit.
391    *
392    * \code
393    *  [g___] - good
394    *  [_eF_] - eof and fail bit set
395    *  [__FB] - fail and bad bit set
396    * \endcode
397   */
398   inline std::ostream & operator<<( std::ostream & str, const std::basic_ios<char> & obj )
399   {
400     std::string ret( "[" );
401     ret += ( obj.good() ? 'g' : '_' );
402     ret += ( obj.eof()  ? 'e' : '_' );
403     ret += ( obj.fail() ? 'F' : '_' );
404     ret += ( obj.bad()  ? 'B' : '_' );
405     ret += "]";
406     return str << ret;
407   }
408
409   ///////////////////////////////////////////////////////////////////
410   // iomanipulator: str << dump(val) << ...
411   // calls:         std::ostream & dumpOn( std::ostream & str, const Type & obj )
412   ///////////////////////////////////////////////////////////////////
413
414   namespace detail
415   {
416     template<class Tp>
417     struct Dump
418     {
419       Dump( const Tp & obj_r ) : _obj( obj_r ) {}
420       const Tp & _obj;
421     };
422
423     template<class Tp>
424     std::ostream & operator<<( std::ostream & str, const Dump<Tp> & obj )
425     { return dumpOn( str, obj._obj ); }
426   }
427
428   template<class Tp>
429   detail::Dump<Tp> dump( const Tp & obj_r )
430   { return detail::Dump<Tp>(obj_r); }
431
432
433   /////////////////////////////////////////////////////////////////
434 } // namespace zypp
435 ///////////////////////////////////////////////////////////////////
436 #endif // ZYPP_BASE_LOGTOOLS_H