diff --git a/headers/os/package/PackageInfo.h b/headers/os/package/PackageInfo.h index 5fdb2c9b36..d54a5d2c5e 100644 --- a/headers/os/package/PackageInfo.h +++ b/headers/os/package/PackageInfo.h @@ -196,6 +196,10 @@ public: bool revisionIsOptional, BPackageVersion& _version, ParseErrorListener* listener = NULL); + static status_t ParseResolvableExpressionString( + const BString& string, + BPackageResolvableExpression& _expression, + ParseErrorListener* listener = NULL); public: static const char* const kElementNames[]; diff --git a/headers/os/package/PackageResolvableExpression.h b/headers/os/package/PackageResolvableExpression.h index ea48808e43..5236a1f1a6 100644 --- a/headers/os/package/PackageResolvableExpression.h +++ b/headers/os/package/PackageResolvableExpression.h @@ -45,12 +45,12 @@ public: BPackageResolvableExpression( const BPackageResolvableExpressionData& data ); + explicit BPackageResolvableExpression( + const BString& expressionString); BPackageResolvableExpression( const BString& name, - BPackageResolvableOperator _op - = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT, - const BPackageVersion& version - = BPackageVersion()); + BPackageResolvableOperator _operator, + const BPackageVersion& version); status_t InitCheck() const; @@ -60,11 +60,10 @@ public: BString ToString() const; + status_t SetTo(const BString& expressionString); void SetTo(const BString& name, - BPackageResolvableOperator _op - = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT, - const BPackageVersion& version - = BPackageVersion()); + BPackageResolvableOperator _operator, + const BPackageVersion& version); void Clear(); bool Matches(const BPackageVersion& version, diff --git a/src/kits/package/PackageInfo.cpp b/src/kits/package/PackageInfo.cpp index 562943b965..57bbfd9199 100644 --- a/src/kits/package/PackageInfo.cpp +++ b/src/kits/package/PackageInfo.cpp @@ -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 BPackageInfo::_ReadFromPackageFile(const PackageFileLocation& fileLocation) { diff --git a/src/kits/package/PackageInfoParser.cpp b/src/kits/package/PackageInfoParser.cpp index 1bdc87084a..15076e0125 100644 --- a/src/kits/package/PackageInfoParser.cpp +++ b/src/kits/package/PackageInfoParser.cpp @@ -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::_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 BPackageInfo::Parser::_ParseList(ListElementParser& elementParser, bool allowSingleNonListElement) @@ -587,56 +667,9 @@ BPackageInfo::Parser::_ParseResolvableExprList( 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); - } - - 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)); + BPackageResolvableExpression expression; + parser._ParseResolvableExpression(token, expression, basePackage); + value->AddItem(new BPackageResolvableExpression(expression)); } } resolvableExpressionParser(*this, value, _basePackage); diff --git a/src/kits/package/PackageInfoParser.h b/src/kits/package/PackageInfoParser.h index 613ec686c8..6824b9e349 100644 --- a/src/kits/package/PackageInfoParser.h +++ b/src/kits/package/PackageInfoParser.h @@ -26,6 +26,9 @@ public: status_t ParseVersion(const BString& versionString, bool revisionIsOptional, BPackageVersion& _version); + status_t ParseResolvableExpression( + const BString& expressionString, + BPackageResolvableExpression& _expression); private: struct ParseError; @@ -63,6 +66,10 @@ private: static void _ParseVersionValue(Token& word, BPackageVersion* value, bool revisionIsOptional); + void _ParseResolvableExpression( + const Token& token, + BPackageResolvableExpression& _value, + BString* _basePackage); void _ParseList(ListElementParser& elementParser, bool allowSingleNonListElement); void _ParseStringList(BStringList* value, diff --git a/src/kits/package/PackageResolvableExpression.cpp b/src/kits/package/PackageResolvableExpression.cpp index ee2202317c..086479d1d6 100644 --- a/src/kits/package/PackageResolvableExpression.cpp +++ b/src/kits/package/PackageResolvableExpression.cpp @@ -7,6 +7,7 @@ #include #include +#include #include @@ -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 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 BPackageResolvableExpression::SetTo(const BString& name, BPackageResolvableOperator _operator, const BPackageVersion& version)