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; }
120 if (
ai == Attribute::edition )
122 if ( ! (
_wfn[Attribute::sw_edition].isANY()
123 &&
_wfn[Attribute::target_sw].isANY()
124 &&
_wfn[Attribute::target_hw].isANY()
125 &&
_wfn[Attribute::other].isANY() ) )
130 <<
'~' <<
_wfn[Attribute::sw_edition].asUri()
131 <<
'~' <<
_wfn[Attribute::target_sw].asUri()
132 <<
'~' <<
_wfn[Attribute::target_hw].asUri()
133 <<
'~' <<
_wfn[Attribute::other].asUri();
147 if (
ai == Attribute::language )
162 if (
ai )
ret <<
',';
163 ret << Attribute::asString(
ai ) <<
'=';
165 ret <<
'"' << val <<
'"';
176 SetCompare
ret = SetCompare::equal;
181 case SetCompare::uncomparable:
182 ret = SetCompare::uncomparable;
185 case SetCompare::equal:
188 case SetCompare::properSubset:
189 if (
ret == SetCompare::equal )
190 ret = SetCompare::properSubset;
191 else if (
ret != SetCompare::properSubset )
192 ret = SetCompare::uncomparable;
195 case SetCompare::properSuperset:
196 if (
ret == SetCompare::equal )
197 ret = SetCompare::properSuperset;
198 else if (
ret != SetCompare::properSuperset )
199 ret = SetCompare::uncomparable;
202 case SetCompare::disjoint:
203 ret = SetCompare::disjoint;
206 if (
ret == SetCompare::uncomparable ||
ret == SetCompare::disjoint )
218 if (
val_r.isString() )
220 switch (
attr_r.asEnum() )
222 case Attribute::part:
224 const std::string &
wfn(
val_r.asWfn() );
230 if (
wfn[1] ==
'\0' )
234 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn:part: '" <<
wfn <<
"' illegal value; expected: 'h' | 'o' | 'a'" );
240 case Attribute::language:
242 const std::string &
wfn(
val_r.asWfn() );
243 std::string::size_type len = 0;
248 if (
wfn[len] ==
'-' )
256 if (
wfn.size() != len )
257 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn:language: '" <<
wfn <<
"' illegal value; expected RFC5646 conform: language ['-' region]" );
297 if (
cpe_r[4] ==
'/' )
301 else if (
cpe_r[4] ==
'2'
309 throw std::invalid_argument(
"CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" );
311 else if (
cpe_r[0] !=
'\0' )
312 throw std::invalid_argument(
"CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" );
321 std::vector<std::string>
field;
322 field.reserve( Attribute::numAttributes );
324 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri: too many fields (" <<
field.size() <<
"); expected " <<
numUriAttr );
325 field.resize( Attribute::numAttributes );
329 if (
ai == Attribute::edition &&
field[
ai][0] ==
'~' )
332 static constexpr unsigned numPacks = 6u;
333 std::vector<std::string>
pack;
336 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri:edition: too many packs (" <<
pack.size() <<
"); expected " <<
numPacks );
354 std::vector<std::string>
field;
355 field.reserve( Attribute::numAttributes );
357 throw std::invalid_argument(
str::Str() <<
"CpeId:Fs: too many fields (" <<
field.size() <<
"); expected 11" );
360 field.resize( Attribute::numAttributes,
"*" );
402 {
return bool(*_pimpl); }
405 {
return _pimpl->asFs(); }
408 {
return _pimpl->asUri(); }
411 {
return _pimpl->asWfn(); }
422 static std::map<Enum,std::string> _table = {
423#define OUTS(N) { N, #N }
437 return _table[
val_r];
455 _value.reset(
new std::string );
471 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: illegal quoted character '\\" <<
reinterpret_cast<void*
>(*
chp) <<
"'" );
473 throw std::invalid_argument(
"CpeId:Wfn: Backslash escapes nothing" );
476 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: unnecessarily quoted character '\\" << *
chp <<
"'" );
478 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: '\\-' is illegal value" );
482 while ( *(
chp+1) ==
'?' )
485 throw std::invalid_argument(
"CpeId:Wfn: embedded ?" );
490 throw std::invalid_argument(
"CpeId:Wfn: embedded *" );
497 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: missing quote before '" << *
chp <<
"'" );
499 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: illegal character '" <<
reinterpret_cast<void*
>(*
chp) <<
"'" );
531 result <<
'\\' << *
chp;
533 throw std::invalid_argument(
str::Str() <<
"CpeId:Fs: illegal quoted character '\\" << *
chp <<
"'" );
535 throw std::invalid_argument(
"CpeId:Fs: Backslash escapes nothing" );
540 while ( *(
chp+1) ==
'?' )
546 throw std::invalid_argument(
"CpeId:Fs: embedded ?" );
553 throw std::invalid_argument(
"CpeId:Fs: embedded *" );
560 result <<
'\\' << *
chp;
562 throw std::invalid_argument(
str::Str() <<
"CpeId:Fs: illegal character '" <<
reinterpret_cast<void*
>(*
chp) <<
"'" );
569 throw std::invalid_argument(
"CpeId:Fs: '' value is illegal" );
570 _value.reset(
new std::string( result ) );
605 while ( *(
chp+1) ==
'%' && *(
chp+2) ==
'0' && *(
chp+3) ==
'1' )
616 throw std::invalid_argument(
"CpeId:Uri: embedded %01" );
627 throw std::invalid_argument(
"CpeId:Uri: embedded %02" );
632 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri: illegal % encoded character '" <<
reinterpret_cast<void*
>(
ch) <<
"'" );
637 throw std::invalid_argument(
str::Str() <<
"CpeId:Uri: illegal character '" <<
reinterpret_cast<void*
>(
ch) <<
"'" );
642 result <<
'\\' <<
ch;
647 _value.reset(
new std::string( result ) );
657 static const std::string any(
"*" );
670 static const std::string
asterisk(
"*" );
675 static const std::string
dash(
"-" );
697 throw std::invalid_argument(
"CpeId:Wfn: Backslash escapes nothing" );
701 result <<
'\\' << *
chp;
718 static const std::string
dash(
"-" );
732 static const char *
const hdig =
"0123456789abcdef";
745 throw std::invalid_argument(
"CpeId:Wfn: Backslash escapes nothing" );
749 result <<
'%' <<
hdig[(
unsigned char)(*
chp)/16] <<
hdig[(
unsigned char)(*
chp)%16];
763 throw std::invalid_argument(
str::Str() <<
"CpeId:Wfn: illegal char '" << *
chp <<
"' in WFN" );
779 {
return(
ch_r ==
'*' ||
ch_r ==
'?' ); }
794 return !(backslashes & 1U);
798 inline unsigned trueCharsIn(
const std::string & str_r, std::string::size_type begin_r, std::string::size_type end_r )
801 for_( it, begin_r, end_r )
804 if ( str_r[it] ==
'\\' )
814 inline bool matchWildcardfreeString(
const std::string & lhs,
const std::string & rhs )
843 inline bool matchWildcardedString( std::string src, std::string trg )
847 std::string::size_type prefx = 0;
848 switch ( *src.begin() )
851 if ( src.size() == 1 )
854 prefx = std::string::npos;
859 for_( it, ++src.begin(), src.end() )
860 {
if ( *it ==
'?' ) ++prefx;
else break; }
861 if ( src.size() == prefx )
862 return( trg.size() <= prefx );
864 src.erase( 0, prefx );
870 std::string::size_type suffx = 0;
873 switch ( *src.rbegin() )
876 if ( evenNumberOfBackslashes( ++src.rbegin(), src.rend() ) )
878 suffx = std::string::npos;
879 src.erase( src.size()-1 );
884 for_( it, ++src.rbegin(), src.rend() )
885 {
if ( *it ==
'?' ) ++suffx;
else break; }
886 if ( ! evenNumberOfBackslashes( src.rbegin()+suffx, src.rend() ) )
888 src.erase( src.size()-suffx );
897 for ( std::string::size_type match = trg.find( src, 0 );
898 match != std::string::npos;
899 match = trg.find( src, match+1 ) )
901 if ( prefx != std::string::npos && trueCharsIn( trg, 0, match ) > prefx )
903 std::string::size_type frontSize = match + src.size();
904 if ( suffx != std::string::npos && trueCharsIn( trg, frontSize, trg.size() ) > suffx )
915 const std::string & value( *
_value );
934#define WFN_STRICT_SPEC 0
938 static const SetCompare kNeedsCloserLook( SetCompare::Enum(-1) );
939 static const SetCompare matchTabel[4][4] = {{
941 SetCompare::properSuperset,
942 SetCompare::properSuperset,
943 SetCompare::uncomparable,
945 SetCompare::properSubset,
947 SetCompare::disjoint,
948 SetCompare::uncomparable,
950 SetCompare::properSubset,
951 SetCompare::disjoint,
953 SetCompare::uncomparable,
955 SetCompare::properSubset,
956 SetCompare::disjoint,
958 SetCompare::uncomparable,
961 Type srcType = type();
962 Type trgType = trg.type();
963 SetCompare ret = matchTabel[srcType.asIntegral()][trgType.asIntegral()];
964 if ( ret == kNeedsCloserLook )
966 if ( srcType == Type::wildcardfree )
969 ret = matchWildcardfreeString( *
_value, *trg._value ) ? SetCompare::equal : SetCompare::disjoint;
971 else if ( srcType == Type::wildcarded )
974 ret = matchWildcardedString( *
_value, *trg._value ) ? SetCompare::properSuperset : SetCompare::disjoint;
1004 SetCompare
ret = SetCompare::disjoint;
1008 ret =
trg.isANY() ? SetCompare::equal : SetCompare::properSuperset;
1010 else if (
trg.isANY() )
1012 ret = SetCompare::properSubset;
1016 if (
trg.isNA() )
ret = SetCompare::equal;
1018 else if ( !
trg.isNA() )
1021 if ( isWildcarded() )
1023 if (
trg.isWildcarded() )
1036 if (
trg.isWildcarded() )
1053 {
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.