add zypp-cpeid tool
authorMichael Andres <ma@suse.de>
Tue, 8 Apr 2014 11:25:48 +0000 (13:25 +0200)
committerMichael Andres <ma@suse.de>
Tue, 8 Apr 2014 11:25:48 +0000 (13:25 +0200)
tools/zypp-cpeid.cc [new file with mode: 0644]
zypp/CpeId.cc

diff --git a/tools/zypp-cpeid.cc b/tools/zypp-cpeid.cc
new file mode 100644 (file)
index 0000000..f653b2d
--- /dev/null
@@ -0,0 +1,66 @@
+#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;
+}
index 9be3d88..d2c89dd 100644 (file)
@@ -228,7 +228,7 @@ namespace zypp
                    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;
              }
            }
@@ -251,7 +251,7 @@ namespace zypp
                }
              }
              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;
 
@@ -303,10 +303,10 @@ namespace zypp
        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;
   }
 
@@ -314,11 +314,12 @@ namespace zypp
   {
     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 )
     {
@@ -329,7 +330,7 @@ namespace zypp
        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] );
@@ -350,7 +351,9 @@ namespace zypp
     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 )
@@ -459,14 +462,14 @@ namespace zypp
            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
@@ -485,9 +488,9 @@ namespace zypp
            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;
        }
@@ -521,7 +524,7 @@ namespace zypp
              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;
@@ -550,14 +553,14 @@ namespace zypp
              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 ) );
       }
     }
@@ -620,12 +623,12 @@ namespace zypp
                }
                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;