fixup Fix to build with libxml 2.12.x (fixes #505)
[platform/upstream/libzypp.git] / zypp / ContentType.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/ContentType.h
10  */
11 #ifndef ZYPP_CONTENTTYPE_H
12 #define ZYPP_CONTENTTYPE_H
13
14 #include <iosfwd>
15 #include <string>
16 #include <stdexcept>
17
18 ///////////////////////////////////////////////////////////////////
19 namespace zypp
20 {
21   ///////////////////////////////////////////////////////////////////
22   /// \class ContentType
23   /// \brief Mime type like \c 'type/subtype' classification of content
24   ///
25   /// Used e.g. in \ref callback::UserData to describe the kind of
26   /// user data passed as \c void* to a callback. Neither type nor
27   /// subtype may contain a '/'.
28   ///////////////////////////////////////////////////////////////////
29   class ContentType
30   {
31   public:
32     /** Default ctor: empty */
33     ContentType()
34     {}
35
36     /** Ctor taking <tt>"type[/subtype]"</tt>
37      * \throws std::invalid_argument if string is malformed
38      */
39     explicit ContentType( std::string type_r )
40     {
41       std::string::size_type pos = type_r.find( "/" );
42       if ( pos != std::string::npos )
43       {
44         testAndSet( _subtype, type_r.substr( pos+1 ) );
45         type_r.erase( pos );
46       }
47       testAndSet( _type, std::move(type_r) );
48     }
49
50     /** Ctor taking type and subtype
51      * \throws std::invalid_argument if string is malformed
52      */
53     ContentType( std::string type_r, std::string subtype_r )
54     {
55       testAndSet( _type,    std::move(type_r) );
56       testAndSet( _subtype, std::move(subtype_r) );
57     }
58
59   public:
60     /** Get type */
61     const std::string & type() const
62     { return _type; }
63
64     /** Set type
65      * \throws std::invalid_argument if string is malformed
66      */
67     void type( std::string type_r )
68     { _type = std::move(type_r); }
69
70     /**  Get subtype */
71     const std::string & subtype() const
72     { return _subtype; }
73
74     /**  Set subtype
75      * \throws std::invalid_argument if string is malformed
76      */
77     void subtype( std::string subtype_r )
78     { _subtype = std::move(subtype_r); }
79
80   public:
81     /** Whether type and subtype are empty */
82     bool empty() const
83     { return emptyType() && emptySubtype(); }
84     /** Whether type is empty */
85     bool emptyType() const
86     { return _type.empty(); }
87     /** Whether subtype is empty */
88     bool emptySubtype() const
89     { return _subtype.empty(); }
90
91     /** Validate object in a boolean context: !empty */
92     explicit operator bool () const
93     { return !empty(); }
94
95     /** String representation <tt>"type[/subtype]"</tt> */
96     std::string asString() const
97     { std::string ret( type() ); if ( ! emptySubtype() ) { ret += "/"; ret += subtype(); } return ret; }
98
99   private:
100     void testAndSet( std::string & var_r, std::string val_r )
101     {
102       if ( val_r.find_first_of( "/ \t\r\n" ) != std::string::npos )
103         throw std::invalid_argument( "ContentType: illegal char in '" + val_r + "'" );
104       var_r = std::move(val_r);
105     }
106   private:
107     std::string _type;
108     std::string _subtype;
109   };
110
111   /** \relates ContentType Stream output */
112   inline std::ostream & operator<<( std::ostream & str, const ContentType & obj )
113   { return str << obj.asString(); }
114
115   /** \relates ContentType */
116   inline bool operator==( const ContentType & lhs, const ContentType & rhs )
117   { return lhs.type() == rhs.type() && lhs.subtype() == rhs.subtype(); }
118
119   /** \relates ContentType */
120   inline bool operator!=( const ContentType & lhs, const ContentType & rhs )
121   { return !( lhs == rhs ); }
122
123   /** \relates ContentType */
124   inline bool operator<( const ContentType & lhs, const ContentType & rhs )
125   { int cmp = lhs.type().compare( rhs.type() ); return cmp < 0 || ( cmp == 0 && lhs.subtype() < rhs.subtype() ); }
126
127   /** \relates ContentType */
128   inline bool operator<=( const ContentType & lhs, const ContentType & rhs )
129   { return lhs < rhs || lhs == rhs; }
130
131   /** \relates ContentType */
132   inline bool operator>( const ContentType & lhs, const ContentType & rhs )
133   { return !( lhs <= rhs ); }
134
135   /** \relates ContentType */
136   inline bool operator>=( const ContentType & lhs, const ContentType & rhs )
137   { return !( lhs < rhs ); }
138
139
140 } // namespace zypp
141 ///////////////////////////////////////////////////////////////////
142 #endif // ZYPP_CONTENTTYPE_H