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 14namespace BPackageKit { 15 16 17const char* 18BPackageResolvableExpression 19::kOperatorNames[B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT] = { 20 "<", 21 "<=", 22 "==", 23 "!=", 24 ">=", 25 ">", 26}; 27 28 29BPackageResolvableExpression::BPackageResolvableExpression() 30 : 31 fOperator(B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) 32{ 33} 34 35 36BPackageResolvableExpression::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 47BPackageResolvableExpression::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 58BPackageResolvableExpression::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 69status_t 70BPackageResolvableExpression::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 84const BString& 85BPackageResolvableExpression::Name() const 86{ 87 return fName; 88} 89 90 91BPackageResolvableOperator 92BPackageResolvableExpression::Operator() const 93{ 94 return fOperator; 95} 96 97 98const BPackageVersion& 99BPackageResolvableExpression::Version() const 100{ 101 return fVersion; 102} 103 104 105BString 106BPackageResolvableExpression::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 117status_t 118BPackageResolvableExpression::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 129void 130BPackageResolvableExpression::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 141void 142BPackageResolvableExpression::Clear() 143{ 144 fName.Truncate(0); 145 fOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT; 146 fVersion.Clear(); 147} 148 149 150bool 151BPackageResolvableExpression::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 199bool 200BPackageResolvableExpression::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