diff --git a/headers/os/package/PackageInfo.h b/headers/os/package/PackageInfo.h index a3fec62bdc..bc4819f589 100644 --- a/headers/os/package/PackageInfo.h +++ b/headers/os/package/PackageInfo.h @@ -202,6 +202,10 @@ public: bool revisionIsOptional, BPackageVersion& _version, ParseErrorListener* listener = NULL); + static status_t ParseResolvableString( + const BString& string, + BPackageResolvable& _expression, + ParseErrorListener* listener = NULL); static status_t ParseResolvableExpressionString( const BString& string, BPackageResolvableExpression& _expression, diff --git a/headers/os/package/PackageResolvable.h b/headers/os/package/PackageResolvable.h index fe4eca0856..13467f4022 100644 --- a/headers/os/package/PackageResolvable.h +++ b/headers/os/package/PackageResolvable.h @@ -61,6 +61,7 @@ public: BString ToString() const; + status_t SetToString(const BString& expressionString); void SetTo(const BString& name, const BPackageVersion& version = BPackageVersion(), diff --git a/src/kits/package/PackageInfo.cpp b/src/kits/package/PackageInfo.cpp index 9fe1ce5b43..2982662338 100644 --- a/src/kits/package/PackageInfo.cpp +++ b/src/kits/package/PackageInfo.cpp @@ -1156,6 +1156,14 @@ BPackageInfo::ParseVersionString(const BString& string, bool revisionIsOptional, } +/*static*/ status_t +BPackageInfo::ParseResolvableString(const BString& string, + BPackageResolvable& _expression, ParseErrorListener* listener) +{ + return Parser(listener).ParseResolvable(string, _expression); +} + + /*static*/ status_t BPackageInfo::ParseResolvableExpressionString(const BString& string, BPackageResolvableExpression& _expression, ParseErrorListener* listener) diff --git a/src/kits/package/PackageInfoParser.cpp b/src/kits/package/PackageInfoParser.cpp index 7035bc9b0c..26feb1f4eb 100644 --- a/src/kits/package/PackageInfoParser.cpp +++ b/src/kits/package/PackageInfoParser.cpp @@ -106,6 +106,31 @@ BPackageInfo::Parser::ParseVersion(const BString& versionString, } +status_t +BPackageInfo::Parser::ParseResolvable(const BString& expressionString, + BPackageResolvable& _expression) +{ + fPos = expressionString.String(); + + try { + Token token(TOKEN_STRING, fPos, expressionString.Length()); + _ParseResolvable(_NextToken(), _expression); + } 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; +} + + status_t BPackageInfo::Parser::ParseResolvableExpression(const BString& expressionString, BPackageResolvableExpression& _expression) @@ -427,6 +452,50 @@ BPackageInfo::Parser::_ParseVersionValue(Token& word, BPackageVersion* value, } +void +BPackageInfo::Parser::_ParseResolvable(const Token& token, + BPackageResolvable& _value) +{ + 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); + } + + // parse version + BPackageVersion version; + Token op = _NextToken(); + if (op.type == TOKEN_OPERATOR_ASSIGN) { + _ParseVersionValue(&version, true); + } else if (op.type == TOKEN_ITEM_SEPARATOR + || op.type == TOKEN_CLOSE_BRACE || op.type == TOKEN_EOF) { + _RewindTo(op); + } else + throw ParseError("expected '=', comma or '}'", op.pos); + + // parse compatible version + BPackageVersion compatibleVersion; + Token compatible = _NextToken(); + if (compatible.type == TOKEN_STRING + && (compatible.text == "compat" + || compatible.text == "compatible")) { + op = _NextToken(); + if (op.type == TOKEN_OPERATOR_GREATER_EQUAL) { + _ParseVersionValue(&compatibleVersion, true); + } else + _RewindTo(compatible); + } else + _RewindTo(compatible); + + _value.SetTo(token.text, version, compatibleVersion); +} + + void BPackageInfo::Parser::_ParseResolvableExpression(const Token& token, BPackageResolvableExpression& _value, BString* _basePackage) @@ -611,44 +680,9 @@ BPackageInfo::Parser::_ParseResolvableList( virtual void operator()(const Token& token) { - 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); - } - - // parse version - BPackageVersion version; - Token op = parser._NextToken(); - if (op.type == TOKEN_OPERATOR_ASSIGN) { - parser._ParseVersionValue(&version, true); - } else if (op.type == TOKEN_ITEM_SEPARATOR - || op.type == TOKEN_CLOSE_BRACE) { - parser._RewindTo(op); - } else - throw ParseError("expected '=', comma or '}'", op.pos); - - // parse compatible version - BPackageVersion compatibleVersion; - Token compatible = parser._NextToken(); - if (compatible.type == TOKEN_STRING - && (compatible.text == "compat" - || compatible.text == "compatible")) { - op = parser._NextToken(); - if (op.type == TOKEN_OPERATOR_GREATER_EQUAL) { - parser._ParseVersionValue(&compatibleVersion, true); - } else - parser._RewindTo(compatible); - } else - parser._RewindTo(compatible); - - value->AddItem(new BPackageResolvable(token.text, version, - compatibleVersion)); + BPackageResolvable expression; + parser._ParseResolvable(token, expression); + value->AddItem(new BPackageResolvable(expression)); } } resolvableParser(*this, value); diff --git a/src/kits/package/PackageInfoParser.h b/src/kits/package/PackageInfoParser.h index 53195587c7..1ea542a955 100644 --- a/src/kits/package/PackageInfoParser.h +++ b/src/kits/package/PackageInfoParser.h @@ -27,6 +27,9 @@ public: status_t ParseVersion(const BString& versionString, bool revisionIsOptional, BPackageVersion& _version); + status_t ParseResolvable( + const BString& expressionString, + BPackageResolvable& _expression); status_t ParseResolvableExpression( const BString& expressionString, BPackageResolvableExpression& _expression); @@ -69,6 +72,9 @@ private: static void _ParseVersionValue(Token& word, BPackageVersion* value, bool revisionIsOptional); + void _ParseResolvable( + const Token& token, + BPackageResolvable& _value); void _ParseResolvableExpression( const Token& token, BPackageResolvableExpression& _value, diff --git a/src/kits/package/PackageResolvable.cpp b/src/kits/package/PackageResolvable.cpp index b604303b5f..cebb6b5e88 100644 --- a/src/kits/package/PackageResolvable.cpp +++ b/src/kits/package/PackageResolvable.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace BPackageKit { @@ -81,6 +82,18 @@ BPackageResolvable::ToString() const } +status_t +BPackageResolvable::SetToString(const BString& expressionString) +{ + fName.Truncate(0); + fVersion.Clear(); + fCompatibleVersion.Clear(); + + return BPackageInfo::ParseResolvableString(expressionString, + *this); +} + + void BPackageResolvable::SetTo(const BString& name, const BPackageVersion& version, const BPackageVersion& compatibleVersion)