--- /dev/null
+#include <iostream>
+#include <zypp/CpeId.h>
+#include <zypp/Pathname.h>
+
+using std::cout;
+using std::endl;
+using zypp::CpeId;
+using zypp::Pathname;
+
+int main( int argc, const char * argv[] )
+{
+ if ( argc == 1 || argv[1] == std::string( "--help" ) || argv[1] == std::string( "-h" ) )
+ {
+ cout <<
+ "Usage: " << Pathname::basename( argv[0] ) << " [CPEID]...\n"
+ "Check and print all supplied CPEIDs as FS, URI and WFN.\n"
+ "Afterwards compare them pairwise. \n"
+ "\n"
+ " (wfn:[part=\"a\",vendor=\"openSUSE\",product=\"libzypp\",version=\"14\\.17\\.3\"])\n"
+ " URI: cpe:/a:openSUSE:libzypp:14.17.3\n"
+ " FS: cpe:2.3:a:openSUSE:libzypp:14.17.3:*:*:*:*:*:*:*\n"
+ "\n";
+
+ return 0;
+ }
+ --argc, ++argv;
+
+
+ std::vector<CpeId> args;
+ args.reserve( argc );
+
+ for ( ; argc; --argc, ++argv )
+ {
+ try {
+ CpeId cpe( argv[0] );
+ cout << '[' << args.size() << "]-----------------------------------------------------------------------------" << endl;
+ cout << "arg: " << argv[0] << endl;
+ cout << " (" << cpe.asWfn() << ')' << endl;
+ cout << "URI: " << cpe.asUri() << endl;
+ cout << "FS: " << cpe<< endl;
+ args.push_back( cpe );
+ }
+ catch ( const std::invalid_argument & exp )
+ {
+ cout << "--------------------------------------------------------------------------------" << endl;
+ cout << "arg: " << argv[0] << endl;
+ cout << "ERR: " << exp.what() << endl;
+ }
+ }
+
+ cout << "--------------------------------------------------------------------------------" << endl;
+ unsigned lhsidx = 0;
+ for ( const auto & lhs : args )
+ {
+ unsigned rhsidx = 0;
+ for ( const auto & rhs : args )
+ {
+ cout << "[" << lhsidx << "] " << lhs << endl;
+ cout << "[" << rhsidx << "] " << rhs << endl;
+ cout << " ==> " << compare( lhs, rhs ) << endl;
+ ++rhsidx;
+ }
+ ++lhsidx;
+ }
+ return 0;
+}
break;
// else: fallthrough
default:
- throw std::invalid_argument( "CpeId:Wfn:part: illegal value" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn:part: '" << wfn << "' illegal value; expected: 'h' | 'o' | 'a'" );
break;
}
}
}
}
if ( wfn.size() != len )
- throw std::invalid_argument( "CpeId:Wfn:language: illegal value" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn:language: '" << wfn << "' illegal value; expected RFC5646 conform: language ['-' region]" );
}
break;
ret = unbindFs( cpe_r );
}
else
- throw std::invalid_argument( "CpeId: bad magic" );
+ throw std::invalid_argument( "CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" );
}
else if ( cpe_r[0] != '\0' )
- throw std::invalid_argument( "CpeId: bad magic" );
+ throw std::invalid_argument( "CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" );
return ret;
}
{
Wfn ret;
+ static constexpr unsigned numUriAttr = 7u; // basic URI attibutes
std::vector<std::string> field;
- field.reserve( Attribute::numAttributes );
- if ( str::splitFields( cpe_r.c_str()+5/* skip magic 'cpe:/' */, std::back_inserter(field), ":" ) > Attribute::numAttributes )
- throw std::invalid_argument( "CpeId:Uri: too many fields" );
- field.resize( Attribute::numAttributes ); // fillup with ANY("")
+ field.reserve( Attribute::numAttributes ); // reserve 7 + 4 for packed extened attrs in edition
+ if ( str::splitFields( cpe_r.c_str()+5/* skip magic 'cpe:/' */, std::back_inserter(field), ":" ) > numUriAttr )
+ throw std::invalid_argument( str::Str() << "CpeId:Uri: too many fields (" << field.size() << "); expected " << numUriAttr );
+ field.resize( Attribute::numAttributes ); // fillup with ANY(""),
for ( auto ai : WFN_ATTRIBUTES )
{
std::vector<std::string> pack;
pack.reserve( numPacks );
if ( str::splitFields( field[ai], std::back_inserter(pack), "~" ) > numPacks )
- throw std::invalid_argument( "CpeId:Uri: too many packs" );
+ throw std::invalid_argument( str::Str() << "CpeId:Uri:edition: too many packs (" << pack.size() << "); expected " << numPacks );
pack.resize( numPacks ); // fillup with ANY(""), should be noOP
pack[1].swap( field[Attribute::edition] );
std::vector<std::string> field;
field.reserve( Attribute::numAttributes );
if ( str::splitFields( cpe_r.c_str()+8/* skip magic 'cpe:2.3:' */, std::back_inserter(field), ":" ) > Attribute::numAttributes )
- throw std::invalid_argument( "CpeId:Fs: too many fields" );
+ throw std::invalid_argument( str::Str() << "CpeId:Fs: too many fields (" << field.size() << "); expected 11" /*<< Attribute::numAttributes but g++ currently can't resoolve this as constexpr*/ );
+ if ( field.back().empty() ) // A trailing ':' leads to an empty (illegal) field, but we fillup missing fields with ANY|"*"
+ field.back() = "*";
field.resize( Attribute::numAttributes, "*" ); // fillup with ANY|"*"
for ( auto ai : WFN_ATTRIBUTES )
if ( ! chIsValidRange( *chp ) )
{
if ( *chp )
- throw std::invalid_argument( "CpeId:Wfn: illegal quoted character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn: illegal quoted character '\\" << reinterpret_cast<void*>(*chp) << "'" );
else
throw std::invalid_argument( "CpeId:Wfn: Backslash escapes nothing" );
}
else if ( chIsWfnUnescaped( *chp ) )
- throw std::invalid_argument( "CpeId:Wfn: unnecessarily quoted character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn: unnecessarily quoted character '\\" << *chp << "'" );
else if ( starting && *chp == '-' && chp+1 == value_r.end() )
- throw std::invalid_argument( "CpeId:Wfn: '\\-' is illegal value" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn: '\\-' is illegal value" );
break;
case '?': // sequence at beginning or end of string
if ( ! chIsWfnUnescaped( *chp ) )
{
if ( chIsValidRange( *chp ) )
- throw std::invalid_argument( "CpeId:Wfn: missing quote" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn: missing quote before '" << *chp << "'" );
else
- throw std::invalid_argument( "CpeId:Wfn: illegal character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Wfn: illegal character '" << reinterpret_cast<void*>(*chp) << "'" );
}
break;
}
else if ( chIsValidRange( *chp ) )
result << '\\' << *chp;
else if ( *chp )
- throw std::invalid_argument( "CpeId:Fs: illegal quoted character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Fs: illegal quoted character '\\" << *chp << "'" );
else
throw std::invalid_argument( "CpeId:Fs: Backslash escapes nothing" );
break;
else if ( chIsValidRange( *chp ) )
result << '\\' << *chp;
else
- throw std::invalid_argument( "CpeId:Fs: illegal character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Fs: illegal character '" << reinterpret_cast<void*>(*chp) << "'" );
break;
}
if ( starting )
starting = false;
}
if ( starting )
- throw std::invalid_argument( "CpeId:Fs: '' is illegal" );
+ throw std::invalid_argument( "CpeId:Fs: '' value is illegal" );
_value.reset( new std::string( result ) );
}
}
}
ch = (d1<<4)|d2;
if ( ! chIsValidRange( ch ) )
- throw std::invalid_argument( "CpeId:Uri: illegal % encoded character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Uri: illegal % encoded character '" << reinterpret_cast<void*>(ch) << "'" );
}
}
}
else if ( ! chIsValidRange( ch ) )
- throw std::invalid_argument( "CpeId:Uri: illegal character" );
+ throw std::invalid_argument( str::Str() << "CpeId:Uri: illegal character '" << reinterpret_cast<void*>(ch) << "'" );
if ( chIsWfnUnescaped( ch ) )
result << ch;