package kit: Add API for parsing resolvable expression strings
* Add BPackageInfo::ParseResolvableExpressionString(). * Add BPackageResolvableExpression constructor and SetTo() taking an expression string.
This commit is contained in:
@@ -196,6 +196,10 @@ public:
|
|||||||
bool revisionIsOptional,
|
bool revisionIsOptional,
|
||||||
BPackageVersion& _version,
|
BPackageVersion& _version,
|
||||||
ParseErrorListener* listener = NULL);
|
ParseErrorListener* listener = NULL);
|
||||||
|
static status_t ParseResolvableExpressionString(
|
||||||
|
const BString& string,
|
||||||
|
BPackageResolvableExpression& _expression,
|
||||||
|
ParseErrorListener* listener = NULL);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const char* const kElementNames[];
|
static const char* const kElementNames[];
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ public:
|
|||||||
BPackageResolvableExpression(
|
BPackageResolvableExpression(
|
||||||
const BPackageResolvableExpressionData& data
|
const BPackageResolvableExpressionData& data
|
||||||
);
|
);
|
||||||
|
explicit BPackageResolvableExpression(
|
||||||
|
const BString& expressionString);
|
||||||
BPackageResolvableExpression(
|
BPackageResolvableExpression(
|
||||||
const BString& name,
|
const BString& name,
|
||||||
BPackageResolvableOperator _op
|
BPackageResolvableOperator _operator,
|
||||||
= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT,
|
const BPackageVersion& version);
|
||||||
const BPackageVersion& version
|
|
||||||
= BPackageVersion());
|
|
||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
@@ -60,11 +60,10 @@ public:
|
|||||||
|
|
||||||
BString ToString() const;
|
BString ToString() const;
|
||||||
|
|
||||||
|
status_t SetTo(const BString& expressionString);
|
||||||
void SetTo(const BString& name,
|
void SetTo(const BString& name,
|
||||||
BPackageResolvableOperator _op
|
BPackageResolvableOperator _operator,
|
||||||
= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT,
|
const BPackageVersion& version);
|
||||||
const BPackageVersion& version
|
|
||||||
= BPackageVersion());
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
bool Matches(const BPackageVersion& version,
|
bool Matches(const BPackageVersion& version,
|
||||||
|
|||||||
@@ -1112,6 +1112,14 @@ BPackageInfo::ParseVersionString(const BString& string, bool revisionIsOptional,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
BPackageInfo::ParseResolvableExpressionString(const BString& string,
|
||||||
|
BPackageResolvableExpression& _expression, ParseErrorListener* listener)
|
||||||
|
{
|
||||||
|
return Parser(listener).ParseResolvableExpression(string, _expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPackageInfo::_ReadFromPackageFile(const PackageFileLocation& fileLocation)
|
BPackageInfo::_ReadFromPackageFile(const PackageFileLocation& fileLocation)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -103,6 +103,31 @@ BPackageInfo::Parser::ParseVersion(const BString& versionString,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BPackageInfo::Parser::ParseResolvableExpression(const BString& expressionString,
|
||||||
|
BPackageResolvableExpression& _expression)
|
||||||
|
{
|
||||||
|
fPos = expressionString.String();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Token token(TOKEN_STRING, fPos, expressionString.Length());
|
||||||
|
_ParseResolvableExpression(_NextToken(), _expression, NULL);
|
||||||
|
} catch (const ParseError& error) {
|
||||||
|
if (fListener != NULL) {
|
||||||
|
int32 offset = error.pos - expressionString.String();
|
||||||
|
fListener->OnError(error.message, 1, offset);
|
||||||
|
}
|
||||||
|
return B_BAD_DATA;
|
||||||
|
} catch (const std::bad_alloc& e) {
|
||||||
|
if (fListener != NULL)
|
||||||
|
fListener->OnError("out of memory", 0, 0);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BPackageInfo::Parser::Token
|
BPackageInfo::Parser::Token
|
||||||
BPackageInfo::Parser::_NextToken()
|
BPackageInfo::Parser::_NextToken()
|
||||||
{
|
{
|
||||||
@@ -399,6 +424,61 @@ BPackageInfo::Parser::_ParseVersionValue(Token& word, BPackageVersion* value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPackageInfo::Parser::_ParseResolvableExpression(const Token& token,
|
||||||
|
BPackageResolvableExpression& _value, BString* _basePackage)
|
||||||
|
{
|
||||||
|
if (token.type != TOKEN_STRING) {
|
||||||
|
throw ParseError("expected word (a resolvable name)",
|
||||||
|
token.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 errorPos;
|
||||||
|
if (!_IsValidResolvableName(token.text, &errorPos)) {
|
||||||
|
throw ParseError("invalid character in resolvable name",
|
||||||
|
token.pos + errorPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
BPackageVersion version;
|
||||||
|
Token op = _NextToken();
|
||||||
|
BPackageResolvableOperator resolvableOperator;
|
||||||
|
if (op.type == TOKEN_OPERATOR_LESS
|
||||||
|
|| op.type == TOKEN_OPERATOR_LESS_EQUAL
|
||||||
|
|| op.type == TOKEN_OPERATOR_EQUAL
|
||||||
|
|| op.type == TOKEN_OPERATOR_NOT_EQUAL
|
||||||
|
|| op.type == TOKEN_OPERATOR_GREATER_EQUAL
|
||||||
|
|| op.type == TOKEN_OPERATOR_GREATER) {
|
||||||
|
_ParseVersionValue(&version, true);
|
||||||
|
|
||||||
|
if (_basePackage != NULL) {
|
||||||
|
Token base = _NextToken();
|
||||||
|
if (base.type == TOKEN_STRING && base.text == "base") {
|
||||||
|
if (!_basePackage->IsEmpty()) {
|
||||||
|
throw ParseError("multiple packages marked as base package",
|
||||||
|
token.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
*_basePackage = token.text;
|
||||||
|
} else
|
||||||
|
_RewindTo(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvableOperator = (BPackageResolvableOperator)
|
||||||
|
(op.type - TOKEN_OPERATOR_LESS);
|
||||||
|
} else if (op.type == TOKEN_ITEM_SEPARATOR
|
||||||
|
|| op.type == TOKEN_CLOSE_BRACE || op.type == TOKEN_EOF) {
|
||||||
|
_RewindTo(op);
|
||||||
|
resolvableOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT;
|
||||||
|
} else {
|
||||||
|
throw ParseError(
|
||||||
|
"expected '<', '<=', '==', '!=', '>=', '>', comma or '}'",
|
||||||
|
op.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
_value.SetTo(token.text, resolvableOperator, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BPackageInfo::Parser::_ParseList(ListElementParser& elementParser,
|
BPackageInfo::Parser::_ParseList(ListElementParser& elementParser,
|
||||||
bool allowSingleNonListElement)
|
bool allowSingleNonListElement)
|
||||||
@@ -587,56 +667,9 @@ BPackageInfo::Parser::_ParseResolvableExprList(
|
|||||||
|
|
||||||
virtual void operator()(const Token& token)
|
virtual void operator()(const Token& token)
|
||||||
{
|
{
|
||||||
if (token.type != TOKEN_STRING) {
|
BPackageResolvableExpression expression;
|
||||||
throw ParseError("expected word (a resolvable name)",
|
parser._ParseResolvableExpression(token, expression, basePackage);
|
||||||
token.pos);
|
value->AddItem(new BPackageResolvableExpression(expression));
|
||||||
}
|
|
||||||
|
|
||||||
int32 errorPos;
|
|
||||||
if (!_IsValidResolvableName(token.text, &errorPos)) {
|
|
||||||
throw ParseError("invalid character in resolvable name",
|
|
||||||
token.pos + errorPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
BPackageVersion version;
|
|
||||||
Token op = parser._NextToken();
|
|
||||||
BPackageResolvableOperator resolvableOperator;
|
|
||||||
if (op.type == TOKEN_OPERATOR_LESS
|
|
||||||
|| op.type == TOKEN_OPERATOR_LESS_EQUAL
|
|
||||||
|| op.type == TOKEN_OPERATOR_EQUAL
|
|
||||||
|| op.type == TOKEN_OPERATOR_NOT_EQUAL
|
|
||||||
|| op.type == TOKEN_OPERATOR_GREATER_EQUAL
|
|
||||||
|| op.type == TOKEN_OPERATOR_GREATER) {
|
|
||||||
parser._ParseVersionValue(&version, true);
|
|
||||||
|
|
||||||
if (basePackage != NULL) {
|
|
||||||
Token base = parser._NextToken();
|
|
||||||
if (base.type == TOKEN_STRING && base.text == "base") {
|
|
||||||
if (!basePackage->IsEmpty()) {
|
|
||||||
throw ParseError(
|
|
||||||
"multiple packages marked as base package",
|
|
||||||
token.pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
*basePackage = token.text;
|
|
||||||
} else
|
|
||||||
parser._RewindTo(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvableOperator = (BPackageResolvableOperator)
|
|
||||||
(op.type - TOKEN_OPERATOR_LESS);
|
|
||||||
} else if (op.type == TOKEN_ITEM_SEPARATOR
|
|
||||||
|| op.type == TOKEN_CLOSE_BRACE) {
|
|
||||||
parser._RewindTo(op);
|
|
||||||
resolvableOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT;
|
|
||||||
} else {
|
|
||||||
throw ParseError(
|
|
||||||
"expected '<', '<=', '==', '!=', '>=', '>', comma or '}'",
|
|
||||||
op.pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
value->AddItem(new BPackageResolvableExpression(token.text,
|
|
||||||
resolvableOperator, version));
|
|
||||||
}
|
}
|
||||||
} resolvableExpressionParser(*this, value, _basePackage);
|
} resolvableExpressionParser(*this, value, _basePackage);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ public:
|
|||||||
status_t ParseVersion(const BString& versionString,
|
status_t ParseVersion(const BString& versionString,
|
||||||
bool revisionIsOptional,
|
bool revisionIsOptional,
|
||||||
BPackageVersion& _version);
|
BPackageVersion& _version);
|
||||||
|
status_t ParseResolvableExpression(
|
||||||
|
const BString& expressionString,
|
||||||
|
BPackageResolvableExpression& _expression);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ParseError;
|
struct ParseError;
|
||||||
@@ -63,6 +66,10 @@ private:
|
|||||||
static void _ParseVersionValue(Token& word,
|
static void _ParseVersionValue(Token& word,
|
||||||
BPackageVersion* value,
|
BPackageVersion* value,
|
||||||
bool revisionIsOptional);
|
bool revisionIsOptional);
|
||||||
|
void _ParseResolvableExpression(
|
||||||
|
const Token& token,
|
||||||
|
BPackageResolvableExpression& _value,
|
||||||
|
BString* _basePackage);
|
||||||
void _ParseList(ListElementParser& elementParser,
|
void _ParseList(ListElementParser& elementParser,
|
||||||
bool allowSingleNonListElement);
|
bool allowSingleNonListElement);
|
||||||
void _ParseStringList(BStringList* value,
|
void _ParseStringList(BStringList* value,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <package/PackageResolvableExpression.h>
|
#include <package/PackageResolvableExpression.h>
|
||||||
|
|
||||||
#include <package/hpkg/PackageInfoAttributeValue.h>
|
#include <package/hpkg/PackageInfoAttributeValue.h>
|
||||||
|
#include <package/PackageInfo.h>
|
||||||
#include <package/PackageResolvable.h>
|
#include <package/PackageResolvable.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -54,6 +55,17 @@ BPackageResolvableExpression::BPackageResolvableExpression(const BString& name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BPackageResolvableExpression::BPackageResolvableExpression(
|
||||||
|
const BString& expressionString)
|
||||||
|
:
|
||||||
|
fName(),
|
||||||
|
fOperator(B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT),
|
||||||
|
fVersion()
|
||||||
|
{
|
||||||
|
SetTo(expressionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPackageResolvableExpression::InitCheck() const
|
BPackageResolvableExpression::InitCheck() const
|
||||||
{
|
{
|
||||||
@@ -102,6 +114,18 @@ BPackageResolvableExpression::ToString() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BPackageResolvableExpression::SetTo(const BString& expressionString)
|
||||||
|
{
|
||||||
|
fName.Truncate(0);
|
||||||
|
fOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT;
|
||||||
|
fVersion.Clear();
|
||||||
|
|
||||||
|
return BPackageInfo::ParseResolvableExpressionString(expressionString,
|
||||||
|
*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BPackageResolvableExpression::SetTo(const BString& name,
|
BPackageResolvableExpression::SetTo(const BString& name,
|
||||||
BPackageResolvableOperator _operator, const BPackageVersion& version)
|
BPackageResolvableOperator _operator, const BPackageVersion& version)
|
||||||
|
|||||||
Reference in New Issue
Block a user