1 /* 2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <package/PackageResolvableExpression.h> 8 9 #include <package/hpkg/PackageInfoAttributeValue.h> 10 #include <package/PackageInfo.h> 11 #include <package/PackageResolvable.h> 12 13 14 namespace BPackageKit { 15 16 17 const char* 18 BPackageResolvableExpression 19 ::kOperatorNames[B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT] = { 20 "<", 21 "<=", 22 "==", 23 "!=", 24 ">=", 25 ">", 26 }; 27 28 29 BPackageResolvableExpression::BPackageResolvableExpression() 30 : 31 fOperator(B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) 32 { 33 } 34 35 36 BPackageResolvableExpression::BPackageResolvableExpression( 37 const BPackageResolvableExpressionData& data) 38 : 39 fName(data.name), 40 fOperator(data.op), 41 fVersion(data.version) 42 { 43 fName.ToLower(); 44 } 45 46 47 BPackageResolvableExpression::BPackageResolvableExpression(const BString& name, 48 BPackageResolvableOperator _operator, const BPackageVersion& version) 49 : 50 fName(name), 51 fOperator(_operator), 52 fVersion(version) 53 { 54 fName.ToLower(); 55 } 56 57 58 BPackageResolvableExpression::BPackageResolvableExpression( 59 const BString& expressionString) 60 : 61 fName(), 62 fOperator(B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT), 63 fVersion() 64 { 65 SetTo(expressionString); 66 } 67 68 69 status_t 70 BPackageResolvableExpression::InitCheck() const 71 { 72 if (fName.Length() == 0) 73 return B_NO_INIT; 74 75 // either both or none of operator and version must be set 76 if ((fOperator >= 0 && fOperator < B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) 77 != (fVersion.InitCheck() == B_OK)) 78 return B_NO_INIT; 79 80 return B_OK; 81 } 82 83 84 const BString& 85 BPackageResolvableExpression::Name() const 86 { 87 return fName; 88 } 89 90 91 BPackageResolvableOperator 92 BPackageResolvableExpression::Operator() const 93 { 94 return fOperator; 95 } 96 97 98 const BPackageVersion& 99 BPackageResolvableExpression::Version() const 100 { 101 return fVersion; 102 } 103 104 105 BString 106 BPackageResolvableExpression::ToString() const 107 { 108 BString string = fName; 109 110 if (fVersion.InitCheck() == B_OK) 111 string << kOperatorNames[fOperator] << fVersion.ToString(); 112 113 return string; 114 } 115 116 117 status_t 118 BPackageResolvableExpression::SetTo(const BString& expressionString) 119 { 120 fName.Truncate(0); 121 fOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT; 122 fVersion.Clear(); 123 124 return BPackageInfo::ParseResolvableExpressionString(expressionString, 125 *this); 126 } 127 128 129 void 130 BPackageResolvableExpression::SetTo(const BString& name, 131 BPackageResolvableOperator _operator, const BPackageVersion& version) 132 { 133 fName = name; 134 fOperator = _operator; 135 fVersion = version; 136 137 fName.ToLower(); 138 } 139 140 141 void 142 BPackageResolvableExpression::Clear() 143 { 144 fName.Truncate(0); 145 fOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT; 146 fVersion.Clear(); 147 } 148 149 150 bool 151 BPackageResolvableExpression::Matches(const BPackageVersion& version, 152 const BPackageVersion& compatibleVersion) const 153 { 154 // If no particular version is required, we always match. 155 if (fVersion.InitCheck() != B_OK) 156 return true; 157 158 if (version.InitCheck() != B_OK) 159 return false; 160 161 int compare = version.Compare(fVersion); 162 bool matches = false; 163 switch (fOperator) { 164 case B_PACKAGE_RESOLVABLE_OP_LESS: 165 matches = compare < 0; 166 break; 167 case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL: 168 matches = compare <= 0; 169 break; 170 case B_PACKAGE_RESOLVABLE_OP_EQUAL: 171 matches = compare == 0; 172 break; 173 case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL: 174 matches = compare != 0; 175 break; 176 case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL: 177 matches = compare >= 0; 178 break; 179 case B_PACKAGE_RESOLVABLE_OP_GREATER: 180 matches = compare > 0; 181 break; 182 default: 183 break; 184 } 185 if (!matches) 186 return false; 187 188 // Check compatible version. If not specified, the match must be exact. 189 // Otherwise fVersion must be >= compatibleVersion. 190 if (compatibleVersion.InitCheck() != B_OK) 191 return compare == 0; 192 193 // Since compatibleVersion <= version, we can save the comparison, if 194 // version <= fVersion. 195 return compare <= 0 || compatibleVersion.Compare(fVersion) <= 0; 196 } 197 198 199 bool 200 BPackageResolvableExpression::Matches(const BPackageResolvable& provides) const 201 { 202 if (provides.Name() != fName) 203 return false; 204 205 return Matches(provides.Version(), provides.CompatibleVersion()); 206 } 207 208 209 } // namespace BPackageKit 210