23#define WFN_ATTRIBUTES {\
30 Attribute::language, \
31 Attribute::sw_edition,\
32 Attribute::target_sw, \
33 Attribute::target_hw, \
44 inline int heDecodeCh(
char ch )
46 if (
'0' <= ch && ch <=
'9' )
48 if (
'A' <= ch && ch <=
'F' )
49 return( ch -
'A' + 10 );
50 if (
'a' <= ch && ch <=
'f' )
51 return( ch -
'a' + 10 );
56 inline bool chIsValidRange(
char ch )
57 {
return(
'!' <= ch && ch <=
'~' ); }
60 inline bool chIsAlpha(
char ch )
61 {
return( (
'a' <= ch && ch <=
'z' ) || (
'A' <= ch && ch <=
'Z' ) ); }
64 inline bool chIsNum(
char ch )
65 {
return(
'0' <= ch && ch <=
'9' ); }
68 inline bool chIsAlNum(
char ch )
69 {
return( chIsAlpha( ch ) || chIsNum( ch ) ); }
72 inline bool chIsWfnUnescaped(
char ch )
73 {
return( chIsAlNum( ch ) || ch ==
'_' ); }
86 using Wfn = std::array<Value, Attribute::numAttributes>;
96 explicit operator bool()
const
97 {
for (
const auto & val :
_wfn )
if ( ! val.isANY() )
return true;
return false; }
117 std::string val =
_wfn[
ai].asUri();
119 if (
ai == Attribute::edition )
121 if ( ! (
_wfn[Attribute::sw_edition].isANY()
122 &&
_wfn[Attribute::target_sw].isANY()
123 &&
_wfn[Attribute::target_hw].isANY()
124 &&
_wfn[Attribute::other].isANY() ) )
129 <<
'~' <<
_wfn[Attribute::sw_edition].asUri()
130 <<
'~' <<
_wfn[Attribute::target_sw].asUri()
131 <<
'~' <<
_wfn[Attribute::target_hw].asUri()
132 <<
'~' <<
_wfn[Attribute::other].asUri();
146 if (
ai == Attribute::language )
161 if (
ai )
ret <<
',';
162 ret << Attribute::asString(
ai ) <<
'=';
164 ret <<
'"' << val <<
'"';
175 SetCompare
ret = SetCompare::equal;
180 case SetCompare::uncomparable:
181 ret = SetCompare::uncomparable;
184 case SetCompare::equal:
187 case SetCompare::properSubset:
188 if (
ret == SetCompare::equal )
189 ret = SetCompare::properSubset;
190 else if (
ret != SetCompare::properSubset )
191 ret = SetCompare::uncomparable;
194 case SetCompare::properSuperset:
195 if (
ret == SetCompare::equal )
196 ret = SetCompare::properSuperset;
197 else if (
ret != SetCompare::properSuperset )
198 ret = SetCompare::uncomparable;
201 case SetCompare::disjoint:
202 ret = SetCompare::disjoint;
205 if (
ret == SetCompare::uncomparable ||
ret == SetCompare::disjoint )
217 if (
val_r.isString() )
219 switch (
attr_r.asEnum() )
221 case Attribute::part:
223 const std::string &
wfn(
val_r.asWfn() );
229 if (
wfn[1] ==
'\0' )
233 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn:part: '" <<
wfn <<
"' illegal value; expected: 'h' | 'o' | 'a'" );
239 case Attribute::language:
241 const std::string &
wfn(
val_r.asWfn() );
242 std::string::size_type len = 0;
247 if (
wfn[len] ==
'-' )
255 if (
wfn.size() != len )
256 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn:language: '" <<
wfn <<
"' illegal value; expected RFC5646 conform: language ['-' region]" );
296 if (
cpe_r[4] ==
'/' )
300 else if (
cpe_r[4] ==
'2'
308 throw std::invalid_argument(
"CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" );
310 else if (
cpe_r[0] !=
'\0' )
311 throw std::invalid_argument(
"CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" );
320 std::vector<std::string>
field;
321 field.reserve( Attribute::numAttributes );
323 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri: too many fields (" <<
field.size() <<
"); expected " <<
numUriAttr );
324 field.resize( Attribute::numAttributes );
328 if (
ai == Attribute::edition &&
field[
ai][0] ==
'~' )
331 static constexpr unsigned numPacks = 6u;
332 std::vector<std::string>
pack;
335 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri:edition: too many packs (" <<
pack.size() <<
"); expected " <<
numPacks );
353 std::vector<std::string>
field;
354 field.reserve( Attribute::numAttributes );
356 throw std::invalid_argument(
str::Str() <<
"CpeId:Fs: too many fields (" <<
field.size() <<
"); expected 11" );
359 field.resize( Attribute::numAttributes,
"*" );
401 {
return bool(*_pimpl); }
404 {
return _pimpl->asFs(); }
407 {
return _pimpl->asUri(); }
410 {
return _pimpl->asWfn(); }
421 static std::map<Enum,std::string> _table = {
422#define OUTS(N) { N, #N }
436 return _table[
val_r];
454 _value.reset(
new std::string );
470 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: illegal quoted character '\\" <<
reinterpret_cast<void*
>(*
chp) <<
"'" );
472 throw std::invalid_argument(
"CpeId:Wfn: Backslash escapes nothing" );
475 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: unnecessarily quoted character '\\" << *
chp <<
"'" );
477 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: '\\-' is illegal value" );
481 while ( *(
chp+1) ==
'?' )
484 throw std::invalid_argument(
"CpeId:Wfn: embedded ?" );
489 throw std::invalid_argument(
"CpeId:Wfn: embedded *" );
496 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: missing quote before '" << *
chp <<
"'" );
498 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: illegal character '" <<
reinterpret_cast<void*
>(*
chp) <<
"'" );
530 result <<
'\\' << *
chp;
532 throw std::invalid_argument(
str::Str() <<
"CpeId:Fs: illegal quoted character '\\" << *
chp <<
"'" );
534 throw std::invalid_argument(
"CpeId:Fs: Backslash escapes nothing" );
539 while ( *(
chp+1) ==
'?' )
545 throw std::invalid_argument(
"CpeId:Fs: embedded ?" );
552 throw std::invalid_argument(
"CpeId:Fs: embedded *" );
559 result <<
'\\' << *
chp;
561 throw std::invalid_argument(
str::Str() <<
"CpeId:Fs: illegal character '" <<
reinterpret_cast<void*
>(*
chp) <<
"'" );
568 throw std::invalid_argument(
"CpeId:Fs: '' value is illegal" );
569 _value.reset(
new std::string( result ) );
604 while ( *(
chp+1) ==
'%' && *(
chp+2) ==
'0' && *(
chp+3) ==
'1' )
615 throw std::invalid_argument(
"CpeId:Uri: embedded %01" );
626 throw std::invalid_argument(
"CpeId:Uri: embedded %02" );
631 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri: illegal % encoded character '" <<
reinterpret_cast<void*
>(
ch) <<
"'" );
636 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri: illegal character '" <<
reinterpret_cast<void*
>(
ch) <<
"'" );
641 result <<
'\\' <<
ch;
646 _value.reset(
new std::string( result ) );
656 static const std::string any(
"*" );
669 static const std::string
asterisk(
"*" );
674 static const std::string
dash(
"-" );
696 throw std::invalid_argument(
"CpeId:Wfn: Backslash escapes nothing" );
700 result <<
'\\' << *
chp;
717 static const std::string
dash(
"-" );
731 static const char *
const hdig =
"0123456789abcdef";
744 throw std::invalid_argument(
"CpeId:Wfn: Backslash escapes nothing" );
748 result <<
'%' <<
hdig[(
unsigned char)(*
chp)/16] <<
hdig[(
unsigned char)(*
chp)%16];
762 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: illegal char '" << *
chp <<
"' in WFN" );
778 {
return(
ch_r ==
'*' ||
ch_r ==
'?' ); }
793 return !(backslashes & 1U);
797 inline unsigned trueCharsIn(
const std::string & str_r, std::string::size_type begin_r, std::string::size_type end_r )
800 for_( it, begin_r, end_r )
803 if ( str_r[it] ==
'\\' )
813 inline bool matchWildcardfreeString(
const std::string & lhs,
const std::string & rhs )
842 inline bool matchWildcardedString( std::string src, std::string trg )
846 std::string::size_type prefx = 0;
847 switch ( *src.begin() )
850 if ( src.size() == 1 )
853 prefx = std::string::npos;
858 for_( it, ++src.begin(), src.end() )
859 {
if ( *it ==
'?' ) ++prefx;
else break; }
860 if ( src.size() == prefx )
861 return( trg.size() <= prefx );
863 src.erase( 0, prefx );
869 std::string::size_type suffx = 0;
872 switch ( *src.rbegin() )
875 if ( evenNumberOfBackslashes( ++src.rbegin(), src.rend() ) )
877 suffx = std::string::npos;
878 src.erase( src.size()-1 );
883 for_( it, ++src.rbegin(), src.rend() )
884 {
if ( *it ==
'?' ) ++suffx;
else break; }
885 if ( ! evenNumberOfBackslashes( src.rbegin()+suffx, src.rend() ) )
887 src.erase( src.size()-suffx );
896 for ( std::string::size_type match = trg.find( src, 0 );
897 match != std::string::npos;
898 match = trg.find( src, match+1 ) )
900 if ( prefx != std::string::npos && trueCharsIn( trg, 0, match ) > prefx )
902 std::string::size_type frontSize = match + src.size();
903 if ( suffx != std::string::npos && trueCharsIn( trg, frontSize, trg.size() ) > suffx )
914 const std::string & value( *
_value );
933#define WFN_STRICT_SPEC 0
937 static const SetCompare kNeedsCloserLook( SetCompare::Enum(-1) );
938 static const SetCompare matchTabel[4][4] = {{
940 SetCompare::properSuperset,
941 SetCompare::properSuperset,
942 SetCompare::uncomparable,
944 SetCompare::properSubset,
946 SetCompare::disjoint,
947 SetCompare::uncomparable,
949 SetCompare::properSubset,
950 SetCompare::disjoint,
952 SetCompare::uncomparable,
954 SetCompare::properSubset,
955 SetCompare::disjoint,
957 SetCompare::uncomparable,
960 Type srcType = type();
961 Type trgType = trg.type();
962 SetCompare ret = matchTabel[srcType.asIntegral()][trgType.asIntegral()];
963 if ( ret == kNeedsCloserLook )
965 if ( srcType == Type::wildcardfree )
968 ret = matchWildcardfreeString( *
_value, *trg._value ) ? SetCompare::equal : SetCompare::disjoint;
970 else if ( srcType == Type::wildcarded )
973 ret = matchWildcardedString( *
_value, *trg._value ) ? SetCompare::properSuperset : SetCompare::disjoint;
1003 SetCompare
ret = SetCompare::disjoint;
1007 ret =
trg.isANY() ? SetCompare::equal : SetCompare::properSuperset;
1009 else if (
trg.isANY() )
1011 ret = SetCompare::properSubset;
1015 if (
trg.isNA() )
ret = SetCompare::equal;
1017 else if ( !
trg.isNA() )
1020 if ( isWildcarded() )
1022 if (
trg.isWildcarded() )
1035 if (
trg.isWildcarded() )
1052 {
return str <<
obj.asString(); }
#define WFN_ATTRIBUTES
Initializer list with all wfn attributes.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
void swap(AutoDispose &rhs) noexcept
Exchange the contents of two AutoDispose objects.
void reset()
Reset to default Ctor values.
shared_ptr< Impl > _pimpl
std::string asUri() const
Impl(const std::string &cpe_r)
SetCompare setRelationMixinCompare(const Impl &trg) const
static void assignAttr(Wfn &wfn_r, Attribute attr_r, const Value &val_r)
Assign val_r if it meets attr_r specific contraints.
static Wfn unbindUri(const std::string &cpe_r)
Parse Uri and unbind.
static Wfn unbind(const std::string &cpe_r)
Parse magic and unbind accordingly.
std::array< Value, Attribute::numAttributes > Wfn
static Wfn unbindFs(const std::string &cpe_r)
Parse Fs and unbind.
std::string asWfn() const
static const Value ANY
Logical value matching ANY value.
static const Value NA
Logical value indicating “not applicable/not used".
bool isANY() const
Whether value is ANY.
static constexpr UriFormatType uriFormat
Indicator argument for ctor arg in URI format.
static constexpr FsFormatType fsFormat
Indicator argument for ctor arg in FS format.
bool isString() const
Whether it's an attribute value string (not logical value).
std::string asFs() const
String representation as in Formated-String (ANY:"*", NA:"-")
SetCompare setRelationMixinCompare(const Value &trg) const
CPE name matching hook for SetRelationMixin.
Value()
Default ctor: ANY.
bool containsWildcard() const
HAs unquoted [*?] at begin and/or end of value.
std::string asUri() const
String representation as in URI (ANY:"", NA:"-")
std::string asWfn() const
String representation as in Well-Formed-Name (ANY:"*", NA:"").
Common Platform Enumearation (2.3) See http://cpe.mitre.org/ for more information on the Common Platf...
std::string asUri() const
String representation as URI (in/out).
std::ostream & operator<<(std::ostream &str, const CpeId &obj)
Stream output.
static constexpr NoThrowType noThrow
Indicator argument for non-trowing ctor.
base::EnumClass< EAttributeDef > Attribute
'enum class Attribute'
std::string asWfn() const
String representation as Well-Formed-Name (internal format, out only).
std::string asFs() const
String representation as Formated-String (in/out).
SetCompare setRelationMixinCompare(const CpeId &trg) const
CPE name matching hook for SetRelationMixin.
CpeId()
Default ctor: ANY-Cpeid, all attribute values are ANY.
RWCOW_pointer< Impl > _pimpl
Implementation class.
SetCompare compare(const CpeId &trg) const
Compare sets.
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
unsigned splitFields(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=":")
Split line_r into fields.
std::string toLower(const std::string &s)
Return lowercase version of s.
int compareCI(const C_Str &lhs, const C_Str &rhs)
Easy-to use interface to the ZYPP dependency resolver.
static const std::string & asString(Enum val_r)
string representantion
Indicator type for non-trowing ctor.
static std::string lastMalformed
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
#define for_(IT, BEG, END)
Convenient for-loops using iterator.