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