From 1df3343b6ea382aaecf8520afa913efcef0b11a1 Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Fri, 25 Jul 2014 12:49:21 +0200 Subject: [PATCH] Add ContentType helper for callbacks --- tests/zypp/CMakeLists.txt | 1 + tests/zypp/ContentType_test.cc | 65 +++++++++++++++++++ zypp/CMakeLists.txt | 1 + zypp/ContentType.h | 144 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 tests/zypp/ContentType_test.cc create mode 100644 zypp/ContentType.h diff --git a/tests/zypp/CMakeLists.txt b/tests/zypp/CMakeLists.txt index 0655d1a..acafee6 100644 --- a/tests/zypp/CMakeLists.txt +++ b/tests/zypp/CMakeLists.txt @@ -9,6 +9,7 @@ ADD_TESTS( Arch Capabilities CheckSum + ContentType CpeId Date Dup diff --git a/tests/zypp/ContentType_test.cc b/tests/zypp/ContentType_test.cc new file mode 100644 index 0000000..97346e6 --- /dev/null +++ b/tests/zypp/ContentType_test.cc @@ -0,0 +1,65 @@ +#include +#include +#include "zypp/ContentType.h" + +using std::cout; +using std::endl; + +using zypp::ContentType; + +BOOST_AUTO_TEST_CASE(contenttype_default) +{ + ContentType v; + BOOST_CHECK( !v ); + BOOST_CHECK( v.empty() ); + BOOST_CHECK( v.emptyType() ); + BOOST_CHECK( v.emptySubtype() ); + + ContentType w( "/" ); + BOOST_CHECK_EQUAL( v == w, true ); + BOOST_CHECK_EQUAL( v != w, false ); + BOOST_CHECK_EQUAL( v < w, false ); + BOOST_CHECK_EQUAL( v <= w, true ); + BOOST_CHECK_EQUAL( v > w, false ); + BOOST_CHECK_EQUAL( v >= w, true ); + + BOOST_CHECK_EQUAL( v.asString(), "" ); +} + +BOOST_AUTO_TEST_CASE(contenttype_val) +{ + BOOST_CHECK_THROW( ContentType( " " ), std::invalid_argument ); + + BOOST_CHECK_THROW( ContentType( "//" ), std::invalid_argument ); + BOOST_CHECK_THROW( ContentType( "/ " ), std::invalid_argument ); + + BOOST_CHECK_THROW( ContentType( "/", "a" ), std::invalid_argument ); + BOOST_CHECK_THROW( ContentType( "a", "/" ), std::invalid_argument ); + + BOOST_CHECK_THROW( ContentType( " ", "a" ), std::invalid_argument ); + BOOST_CHECK_THROW( ContentType( "a", " " ), std::invalid_argument ); +} + +BOOST_AUTO_TEST_CASE(contenttype_cmp) +{ + std::set c( { + ContentType( "" ), + ContentType( "/" ), // == "" + ContentType( "a" ), + ContentType( "a/" ), // == "a" + ContentType( "/a" ), + ContentType( "" , "a" ), // == "/a" + ContentType( "a/b" ), + ContentType( "b/b" ), + ContentType( "b/c" ) + }); + + std::set::const_iterator i = c.begin(); + BOOST_CHECK_EQUAL( *(i++), ContentType() ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "", "a" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "a", "" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "a", "b" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "b", "b" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "b", "c" ) ); + BOOST_CHECK( i == c.end() ); +} \ No newline at end of file diff --git a/zypp/CMakeLists.txt b/zypp/CMakeLists.txt index c8474fd..853bedf 100644 --- a/zypp/CMakeLists.txt +++ b/zypp/CMakeLists.txt @@ -103,6 +103,7 @@ SET( zypp_HEADERS CapMatch.h Changelog.h CheckSum.h + ContentType.h CountryCode.h CpeId.h Date.h diff --git a/zypp/ContentType.h b/zypp/ContentType.h new file mode 100644 index 0000000..41a6b74 --- /dev/null +++ b/zypp/ContentType.h @@ -0,0 +1,144 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ContentType.h + */ +#ifndef ZYPP_CONTENTTYPE_H +#define ZYPP_CONTENTTYPE_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class ContentType + /// \brief Mime type like \c 'type/subtype' classification of content + /// + /// Used e.g. in \ref callback::UserData to describe the kind of + /// user data passed as \c void* to a callback. Neither type nor + /// subtype may contain a '/'. + /////////////////////////////////////////////////////////////////// + class ContentType + { + public: + /** Default ctor: empty */ + ContentType() + {} + + /** Ctor taking "type[/subtype]" + * \throws std::invalid_argument if string is malformed + */ + explicit ContentType( const std::string & type_r ) + { + std::string::size_type pos = type_r.find( "/" ); + if ( pos == std::string::npos ) + { + testAndSet( _type, type_r ); + } + else + { + testAndSet( _type, type_r.substr( 0, pos ) ); + testAndSet( _subtype, type_r.substr( pos+1 ) ); + } + } + + /** Ctor taking type and subtype + * \throws std::invalid_argument if string is malformed + */ + ContentType( const std::string & type_r, const std::string & subtype_r ) + { + testAndSet( _type, type_r ); + testAndSet( _subtype, subtype_r ); + } + + public: + /** Get type */ + const std::string & type() const + { return _type; } + + /** Set type + * \throws std::invalid_argument if string is malformed + */ + void type( const std::string & type_r ) + { _type = type_r; } + + /** Get subtype */ + const std::string & subtype() const + { return _subtype; } + + /** Set subtype + * \throws std::invalid_argument if string is malformed + */ + void subtype( const std::string & subtype_r ) + { _subtype = subtype_r; } + + public: + /** Whether type and subtype are empty */ + bool empty() const + { return emptyType() && emptySubtype(); } + /** Whether type is empty */ + bool emptyType() const + { return _type.empty(); } + /** Whether subtype is empty */ + bool emptySubtype() const + { return _subtype.empty(); } + + /** Validate object in a boolean context: !empty */ + explicit operator bool () const + { return !empty(); } + + /** String representation "type[/subtype]" */ + std::string asString() const + { std::string ret( type() ); if ( ! emptySubtype() ) { ret += "/"; ret += subtype(); } return ret; } + + private: + void testAndSet( std::string & var_r, const std::string & val_r ) + { + if ( val_r.find_first_of( "/ \t\r\n" ) != std::string::npos ) + throw std::invalid_argument( "ContentType: illegal char in '" + val_r + "'" ); + var_r = val_r; + } + private: + std::string _type; + std::string _subtype; + }; + + /** \relates ContentType Stream output */ + inline std::ostream & operator<<( std::ostream & str, const ContentType & obj ) + { return str << obj.asString(); } + + /** \relates ContentType */ + inline bool operator==( const ContentType & lhs, const ContentType & rhs ) + { return lhs.type() == rhs.type() && lhs.subtype() == rhs.subtype(); } + + /** \relates ContentType */ + inline bool operator!=( const ContentType & lhs, const ContentType & rhs ) + { return !( lhs == rhs ); } + + /** \relates ContentType */ + inline bool operator<( const ContentType & lhs, const ContentType & rhs ) + { int cmp = lhs.type().compare( rhs.type() ); return cmp < 0 || ( cmp == 0 && lhs.subtype() < rhs.subtype() ); } + + /** \relates ContentType */ + inline bool operator<=( const ContentType & lhs, const ContentType & rhs ) + { return lhs < rhs || lhs == rhs; } + + /** \relates ContentType */ + inline bool operator>( const ContentType & lhs, const ContentType & rhs ) + { return !( lhs <= rhs ); } + + /** \relates ContentType */ + inline bool operator>=( const ContentType & lhs, const ContentType & rhs ) + { return !( lhs < rhs ); } + + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CONTENTTYPE_H -- 2.7.4