xref: /haiku/src/kits/package/PackageResolvableExpression.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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