Completed PackageInfo-parser and fleshed out BPackageVersion, BPackageProvision and BPackageRequirement.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40313 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe
2011-01-28 23:36:08 +00:00
parent 28e96d8542
commit 30222ff141
2 changed files with 558 additions and 199 deletions
+66 -21
View File
@@ -18,12 +18,12 @@ namespace BPackageKit {
enum BPackageInfoIndex { enum BPackageInfoIndex {
B_PACKAGE_INFO_NAME = 0, B_PACKAGE_INFO_NAME = 0,
B_PACKAGE_INFO_SUMMARY, // single line, 72 chars max B_PACKAGE_INFO_SUMMARY, // single line, 70 chars max
B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible
B_PACKAGE_INFO_VENDOR, // e.g. "Haiku Project" B_PACKAGE_INFO_VENDOR, // e.g. "Haiku Project"
B_PACKAGE_INFO_PACKAGER, // e-mail address preferred B_PACKAGE_INFO_PACKAGER, // e-mail address preferred
B_PACKAGE_INFO_ARCHITECTURE, B_PACKAGE_INFO_ARCHITECTURE,
B_PACKAGE_INFO_VERSION, B_PACKAGE_INFO_VERSION, // <major>[.<minor>[.<micro>]]
B_PACKAGE_INFO_COPYRIGHTS, // list B_PACKAGE_INFO_COPYRIGHTS, // list
B_PACKAGE_INFO_LICENSES, // list B_PACKAGE_INFO_LICENSES, // list
B_PACKAGE_INFO_PROVIDES, // list B_PACKAGE_INFO_PROVIDES, // list
@@ -34,7 +34,7 @@ enum BPackageInfoIndex {
enum BPackageArchitecture { enum BPackageArchitecture {
B_PACKAGE_ARCHITECTURE_NONE = 0, B_PACKAGE_ARCHITECTURE_ANY = 0,
B_PACKAGE_ARCHITECTURE_X86, B_PACKAGE_ARCHITECTURE_X86,
B_PACKAGE_ARCHITECTURE_X86_GCC2, B_PACKAGE_ARCHITECTURE_X86_GCC2,
// //
@@ -44,29 +44,76 @@ enum BPackageArchitecture {
class BPackageVersion { class BPackageVersion {
public: public:
void MakeEmpty() {} BPackageVersion();
BPackageVersion(const BString& major,
const BString& minor, const BString& micro,
uint8 release);
status_t InitCheck() const;
void GetVersionString(BString& string) const;
void SetTo(const BString& major,
const BString& minor, const BString& micro,
uint8 release);
void Clear();
int Compare(const BPackageVersion& other) const;
// does a natural compare over major, minor
// and micro, finally comparing release
private:
BString fMajor;
BString fMinor;
BString fMicro;
uint8 fRelease;
}; };
class BPackageProvision { class BPackageProvision {
public: public:
int Compare(const BPackageProvision& other) const BPackageProvision();
{ BPackageProvision(const BString& name,
return fX.Compare(other.fX); const BPackageVersion& version
} = BPackageVersion());
status_t InitCheck() const;
void GetProvisionString(BString& string) const;
void SetTo(const BString& name,
const BPackageVersion& version
= BPackageVersion());
void Clear();
private: private:
BString fX; BString fName;
BPackageVersion fVersion;
}; };
class BPackageRequirement { class BPackageRequirement {
public: public:
int Compare(const BPackageRequirement& other) const BPackageRequirement();
{ BPackageRequirement(const BString& name,
return fX.Compare(other.fX); const BString& _operator = "",
} const BPackageVersion& version
= BPackageVersion());
status_t InitCheck() const;
void GetRequirementString(BString& string) const;
void SetTo(const BString& name,
const BString& _operator = "",
const BPackageVersion& version
= BPackageVersion());
void Clear();
private: private:
BString fX; BString fName;
BString fOperator;
BPackageVersion fVersion;
}; };
@@ -126,31 +173,29 @@ public:
void ClearCopyrights(); void ClearCopyrights();
status_t AddCopyright(const BString& copyright); status_t AddCopyright(const BString& copyright);
status_t RemoveCopyright(const BString& copyright);
void ClearLicenses(); void ClearLicenses();
status_t AddLicense(const BString& license); status_t AddLicense(const BString& license);
status_t RemoveLicense(const BString& license);
void ClearProvisions(); void ClearProvisions();
status_t AddProvision( status_t AddProvision(
const BPackageProvision& provision); const BPackageProvision& provision);
status_t RemoveProvision(
const BPackageProvision& provision);
void ClearRequirements(); void ClearRequirements();
status_t AddRequirement( status_t AddRequirement(
const BPackageRequirement& requirement); const BPackageRequirement& requirement);
status_t RemoveRequirement(
const BPackageRequirement& requirement);
void MakeEmpty(); void Clear();
public: public:
static status_t GetElementName( static status_t GetElementName(
BPackageInfoIndex index, BPackageInfoIndex index,
const char** name); const char** name);
static status_t GetArchitectureName(
BPackageArchitecture arch,
const char** name);
private: private:
class Parser; class Parser;
friend class Parser; friend class Parser;
+492 -178
View File
@@ -1,4 +1,3 @@
#include <stdio.h>
/* /*
* Copyright 2011, Oliver Tappe <[email protected]> * Copyright 2011, Oliver Tappe <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
@@ -17,6 +16,11 @@
#include <Entry.h> #include <Entry.h>
#include <String.h> #include <String.h>
#include <NaturalCompare.h>
using BPrivate::NaturalCompare;
namespace BPackageKit { namespace BPackageKit {
@@ -37,7 +41,6 @@ enum TokenType {
TOKEN_OPEN_BRACKET, TOKEN_OPEN_BRACKET,
TOKEN_CLOSE_BRACKET, TOKEN_CLOSE_BRACKET,
TOKEN_COMMA, TOKEN_COMMA,
TOKEN_SEMICOLON,
TOKEN_COLON, TOKEN_COLON,
// //
TOKEN_EOF, TOKEN_EOF,
@@ -73,16 +76,24 @@ private:
struct Token; struct Token;
Token _NextToken(); Token _NextToken();
void _RewindTo(const Token& token);
void _ParseStringValue(BString* value); void _ParseStringValue(BString* value);
void _ParseArchitectureValue( void _ParseArchitectureValue(
BPackageArchitecture* value); BPackageArchitecture* value);
void _ParseVersionValue(BPackageVersion* value,
bool releaseIsOptional);
void _ParseStringList(BObjectList<BString>* value);
void _ParseProvisionList(
BObjectList<BPackageProvision>* value);
void _ParseRequirementList(
BObjectList<BPackageRequirement>* value);
void _Parse(BPackageInfo* packageInfo); void _Parse(BPackageInfo* packageInfo);
private: private:
ParseErrorListener* fListener; ParseErrorListener* fListener;
const char* fPos; const char* fPos;
int fCurrentLine;
}; };
@@ -140,8 +151,7 @@ BPackageInfo::ParseErrorListener::~ParseErrorListener()
BPackageInfo::Parser::Parser(ParseErrorListener* listener) BPackageInfo::Parser::Parser(ParseErrorListener* listener)
: :
fListener(listener), fListener(listener),
fPos(NULL), fPos(NULL)
fCurrentLine(0)
{ {
} }
@@ -154,7 +164,6 @@ BPackageInfo::Parser::Parse(const BString& packageInfoString,
return B_BAD_VALUE; return B_BAD_VALUE;
fPos = packageInfoString.String(); fPos = packageInfoString.String();
fCurrentLine = 1;
try { try {
_Parse(packageInfo); _Parse(packageInfo);
@@ -164,7 +173,7 @@ BPackageInfo::Parser::Parse(const BString& packageInfoString,
int line = 1; int line = 1;
int column; int column;
int32 offset = error.pos - packageInfoString.String(); int32 offset = error.pos - packageInfoString.String();
int32 newlinePos = packageInfoString.FindLast('\n', offset); int32 newlinePos = packageInfoString.FindLast('\n', offset - 1);
if (newlinePos < 0) if (newlinePos < 0)
column = offset; column = offset;
else { else {
@@ -178,6 +187,10 @@ BPackageInfo::Parser::Parse(const BString& packageInfoString,
fListener->OnError(error.message, line, column); fListener->OnError(error.message, line, column);
} }
return B_BAD_DATA; 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; return B_OK;
@@ -188,20 +201,15 @@ BPackageInfo::Parser::Token
BPackageInfo::Parser::_NextToken() BPackageInfo::Parser::_NextToken()
{ {
// eat any whitespace or comments // eat any whitespace or comments
printf("1: %p\n", fPos);
bool inComment = false; bool inComment = false;
while ((inComment && *fPos != '\0') || isspace(*fPos) || *fPos == '#') { while ((inComment && *fPos != '\0') || isspace(*fPos) || *fPos == '#') {
printf("1b: %p\n", fPos);
if (*fPos == '#') if (*fPos == '#')
inComment = true; inComment = true;
else if (*fPos == '\n') { else if (*fPos == '\n')
inComment = false; inComment = false;
fCurrentLine++;
}
fPos++; fPos++;
} }
printf("2: %p\n", fPos);
const char* tokenPos = fPos; const char* tokenPos = fPos;
switch (*fPos) { switch (*fPos) {
case '\0': case '\0':
@@ -215,10 +223,6 @@ printf("2: %p\n", fPos);
fPos++; fPos++;
return Token(TOKEN_COMMA, tokenPos); return Token(TOKEN_COMMA, tokenPos);
case ';':
fPos++;
return Token(TOKEN_SEMICOLON, tokenPos);
case '[': case '[':
fPos++; fPos++;
return Token(TOKEN_OPEN_BRACKET, tokenPos); return Token(TOKEN_OPEN_BRACKET, tokenPos);
@@ -231,22 +235,22 @@ printf("2: %p\n", fPos);
fPos++; fPos++;
if (*fPos == '=') { if (*fPos == '=') {
fPos++; fPos++;
return Token(TOKEN_OPERATOR_LESS_EQUAL, tokenPos); return Token(TOKEN_OPERATOR_LESS_EQUAL, tokenPos, 2);
} }
return Token(TOKEN_OPERATOR_LESS, tokenPos); return Token(TOKEN_OPERATOR_LESS, tokenPos, 1);
case '=': case '=':
fPos++; fPos++;
if (*fPos == '=') { if (*fPos == '=') {
fPos++; fPos++;
return Token(TOKEN_OPERATOR_EQUAL, tokenPos); return Token(TOKEN_OPERATOR_EQUAL, tokenPos, 2);
} }
return Token(TOKEN_OPERATOR_ASSIGN, tokenPos); return Token(TOKEN_OPERATOR_ASSIGN, tokenPos, 1);
case '!': case '!':
if (fPos[1] == '=') { if (fPos[1] == '=') {
fPos += 2; fPos += 2;
return Token(TOKEN_OPERATOR_NOT_EQUAL, tokenPos); return Token(TOKEN_OPERATOR_NOT_EQUAL, tokenPos, 2);
} }
break; break;
@@ -254,9 +258,9 @@ printf("2: %p\n", fPos);
fPos++; fPos++;
if (*fPos == '=') { if (*fPos == '=') {
fPos++; fPos++;
return Token(TOKEN_OPERATOR_GREATER_EQUAL, tokenPos); return Token(TOKEN_OPERATOR_GREATER_EQUAL, tokenPos, 2);
} }
return Token(TOKEN_OPERATOR_GREATER, tokenPos); return Token(TOKEN_OPERATOR_GREATER, tokenPos, 1);
case '"': case '"':
{ {
@@ -269,8 +273,6 @@ printf("2: %p\n", fPos);
lastWasEscape = false; lastWasEscape = false;
else if (*fPos == '\\') else if (*fPos == '\\')
lastWasEscape = true; lastWasEscape = true;
else if (*fPos == '\n')
fCurrentLine++;
fPos++; fPos++;
} }
if (*fPos != '"') if (*fPos != '"')
@@ -297,6 +299,13 @@ printf("2: %p\n", fPos);
} }
void
BPackageInfo::Parser::_RewindTo(const Token& token)
{
fPos = token.pos;
}
void void
BPackageInfo::Parser::_ParseStringValue(BString* value) BPackageInfo::Parser::_ParseStringValue(BString* value)
{ {
@@ -332,6 +341,165 @@ BPackageInfo::Parser::_ParseArchitectureValue(BPackageArchitecture* value)
} }
void
BPackageInfo::Parser::_ParseVersionValue(BPackageVersion* value,
bool releaseIsOptional)
{
Token word = _NextToken();
if (word.type != TOKEN_WORD)
throw ParseError("expected word (a version)", word.pos);
uint8 release = 0;
int32 lastDashPos = word.text.FindLast('-');
if (lastDashPos < 0) {
if (!releaseIsOptional) {
throw ParseError("expected release number (-<number> suffix)",
word.pos + word.text.Length());
}
} else {
int number = atoi(word.text.String() + lastDashPos + 1);
if (number <= 0 || number > 99) {
throw ParseError("release number must be from 1-99",
word.pos + word.text.Length());
}
release = number;
word.text.Truncate(lastDashPos);
}
BString major;
BString minor;
BString micro;
int32 firstDotPos = word.text.FindFirst('.');
if (firstDotPos < 0)
major = word.text;
else {
word.text.CopyInto(major, 0, firstDotPos);
int32 secondDotPos = word.text.FindFirst('.', firstDotPos + 1);
if (secondDotPos == firstDotPos + 1)
throw ParseError("expected minor version", word.pos + secondDotPos);
if (secondDotPos < 0)
word.text.CopyInto(minor, firstDotPos + 1, word.text.Length());
else {
word.text.CopyInto(minor, firstDotPos + 1,
secondDotPos - firstDotPos + 1);
word.text.CopyInto(micro, secondDotPos + 1, word.text.Length());
}
}
value->SetTo(major, minor, micro, release);
}
void
BPackageInfo::Parser::_ParseStringList(BObjectList<BString>* value)
{
Token openBracket = _NextToken();
if (openBracket.type != TOKEN_OPEN_BRACKET)
throw ParseError("expected start of list ('[')", openBracket.pos);
bool needComma = false;
while (true) {
Token token = _NextToken();
if (token.type == TOKEN_CLOSE_BRACKET)
return;
if (needComma) {
if (token.type != TOKEN_COMMA)
throw ParseError("expected comma", token.pos);
token = _NextToken();
} else
needComma = true;
if (token.type != TOKEN_QUOTED_STRING && token.type != TOKEN_WORD)
throw ParseError("expected quoted-string or word", token.pos);
value->AddItem(new BString(token.text));
}
}
void
BPackageInfo::Parser::_ParseProvisionList(BObjectList<BPackageProvision>* value)
{
Token openBracket = _NextToken();
if (openBracket.type != TOKEN_OPEN_BRACKET)
throw ParseError("expected start of list ('[')", openBracket.pos);
bool needComma = false;
while (true) {
Token name = _NextToken();
if (name.type == TOKEN_CLOSE_BRACKET)
return;
if (needComma) {
if (name.type != TOKEN_COMMA)
throw ParseError("expected comma", name.pos);
name = _NextToken();
} else
needComma = true;
if (name.type != TOKEN_WORD)
throw ParseError("expected word (a provision name)", name.pos);
BPackageVersion version;
Token op = _NextToken();
if (op.type == TOKEN_OPERATOR_ASSIGN)
_ParseVersionValue(&version, true);
else if (op.type == TOKEN_COMMA || op.type == TOKEN_CLOSE_BRACKET)
_RewindTo(op);
else
throw ParseError("expected '=', comma or ']'", op.pos);
value->AddItem(new BPackageProvision(name.text, version));
}
}
void
BPackageInfo::Parser::_ParseRequirementList(
BObjectList<BPackageRequirement>* value)
{
Token openBracket = _NextToken();
if (openBracket.type != TOKEN_OPEN_BRACKET)
throw ParseError("expected start of list ('[')", openBracket.pos);
bool needComma = false;
while (true) {
Token name = _NextToken();
if (name.type == TOKEN_CLOSE_BRACKET)
return;
if (needComma) {
if (name.type != TOKEN_COMMA)
throw ParseError("expected comma", name.pos);
name = _NextToken();
} else
needComma = true;
if (name.type != TOKEN_WORD)
throw ParseError("expected word (a requirement name)", name.pos);
BPackageVersion version;
Token op = _NextToken();
if (op.type == TOKEN_OPERATOR_LESS
|| op.type == TOKEN_OPERATOR_LESS_EQUAL
|| op.type == TOKEN_OPERATOR_EQUAL
|| op.type == TOKEN_OPERATOR_GREATER_EQUAL
|| op.type == TOKEN_OPERATOR_GREATER)
_ParseVersionValue(&version, true);
else if (op.type == TOKEN_COMMA || op.type == TOKEN_CLOSE_BRACKET)
_RewindTo(op);
else {
throw ParseError(
"expected '<', '<=', '==', '>=', '>', comma or ']'", op.pos);
}
value->AddItem(new BPackageRequirement(name.text, op.text, version));
}
}
void void
BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo) BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
{ {
@@ -343,11 +511,11 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
while (Token t = _NextToken()) { while (Token t = _NextToken()) {
if (t.type != TOKEN_WORD) if (t.type != TOKEN_WORD)
throw ParseError("expected word [a variable name]", t.pos); throw ParseError("expected word (a variable name)", t.pos);
Token opAssign = _NextToken(); Token opAssign = _NextToken();
if (opAssign.type != TOKEN_OPERATOR_ASSIGN) { if (opAssign.type != TOKEN_OPERATOR_ASSIGN) {
throw ParseError("expected assignment operator ['=']", throw ParseError("expected assignment operator ('=')",
opAssign.pos); opAssign.pos);
} }
@@ -417,75 +585,70 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
_ParseArchitectureValue(&architecture); _ParseArchitectureValue(&architecture);
packageInfo->SetArchitecture(architecture); packageInfo->SetArchitecture(architecture);
seen[B_PACKAGE_INFO_ARCHITECTURE] = true; seen[B_PACKAGE_INFO_ARCHITECTURE] = true;
} } else if (t.text.ICompare(names[B_PACKAGE_INFO_VERSION]) == 0) {
// } else if (t.text.ICompare(names[B_PACKAGE_INFO_VERSION]) == 0) { if (seen[B_PACKAGE_INFO_VERSION]) {
// if (seen[B_PACKAGE_INFO_VERSION]) { BString error = BString(names[B_PACKAGE_INFO_VERSION])
// BString error = BString(names[B_PACKAGE_INFO_VERSION]) << " already seen!";
// << " already seen!"; throw ParseError(error, t.pos);
// throw ParseError(error, t.pos); }
// }
//
// BPackageVersion version;
// _ParseVersionValue(&version);
// packageInfo->SetVersion(version);
// seen[B_PACKAGE_INFO_VERSION] = true;
// } else if (t.text.ICompare(names[B_PACKAGE_INFO_COPYRIGHTS]) == 0) {
// if (seen[B_PACKAGE_INFO_COPYRIGHTS]) {
// BString error = BString(names[B_PACKAGE_INFO_COPYRIGHTS])
// << " already seen!";
// throw ParseError(error, t.pos);
// }
//
// BObjectList<BString> copyrights;
// _ParseStringList(&copyrights);
// int count = copyrights.CountItems();
// for (int i = 0; i < count; ++i)
// packageInfo->AddCopyright(*(copyrights.ItemAt(i)));
// seen[B_PACKAGE_INFO_COPYRIGHTS] = true;
// } else if (t.text.ICompare(names[B_PACKAGE_INFO_LICENSES]) == 0) {
// if (seen[B_PACKAGE_INFO_LICENSES]) {
// BString error = BString(names[B_PACKAGE_INFO_LICENSES])
// << " already seen!";
// throw ParseError(error, t.pos);
// }
//
// BObjectList<BString> licenses;
// _ParseStringList(&licenses);
// int count = licenses.CountItems();
// for (int i = 0; i < count; ++i)
// packageInfo->AddLicense(*(licenses.ItemAt(i)));
// seen[B_PACKAGE_INFO_LICENSES] = true;
// } else if (t.text.ICompare(names[B_PACKAGE_INFO_PROVIDES]) == 0) {
// if (seen[B_PACKAGE_INFO_PROVIDES]) {
// BString error = BString(names[B_PACKAGE_INFO_PROVIDES])
// << " already seen!";
// throw ParseError(error, t.pos);
// }
//
// BObjectList<BPackageProvision> provisions;
// _ParseProvisionList(&provisions);
// int count = provisions.CountItems();
// for (int i = 0; i < count; ++i)
// packageInfo->AddProvision(*(provisions.ItemAt(i)));
// seen[B_PACKAGE_INFO_PROVIDES] = true;
// } else if (t.text.ICompare(names[B_PACKAGE_INFO_REQUIRES]) == 0) {
// if (seen[B_PACKAGE_INFO_REQUIRES]) {
// BString error = BString(names[B_PACKAGE_INFO_REQUIRES])
// << " already seen!";
// throw ParseError(error, t.pos);
// }
//
// BObjectList<BPackageRequirement> requirements;
// _ParseRequirementList(&requirements);
// int count = requirements.CountItems();
// for (int i = 0; i < count; ++i)
// packageInfo->AddRequirement(*(requirements.ItemAt(i)));
// seen[B_PACKAGE_INFO_REQUIRES] = true;
// }
Token semicolon = _NextToken(); BPackageVersion version;
if (semicolon.type != TOKEN_SEMICOLON) _ParseVersionValue(&version, false);
throw ParseError("expected semicolon [';']", semicolon.pos); packageInfo->SetVersion(version);
seen[B_PACKAGE_INFO_VERSION] = true;
} else if (t.text.ICompare(names[B_PACKAGE_INFO_COPYRIGHTS]) == 0) {
if (seen[B_PACKAGE_INFO_COPYRIGHTS]) {
BString error = BString(names[B_PACKAGE_INFO_COPYRIGHTS])
<< " already seen!";
throw ParseError(error, t.pos);
}
BObjectList<BString> copyrights;
_ParseStringList(&copyrights);
int count = copyrights.CountItems();
for (int i = 0; i < count; ++i)
packageInfo->AddCopyright(*(copyrights.ItemAt(i)));
seen[B_PACKAGE_INFO_COPYRIGHTS] = true;
} else if (t.text.ICompare(names[B_PACKAGE_INFO_LICENSES]) == 0) {
if (seen[B_PACKAGE_INFO_LICENSES]) {
BString error = BString(names[B_PACKAGE_INFO_LICENSES])
<< " already seen!";
throw ParseError(error, t.pos);
}
BObjectList<BString> licenses;
_ParseStringList(&licenses);
int count = licenses.CountItems();
for (int i = 0; i < count; ++i)
packageInfo->AddLicense(*(licenses.ItemAt(i)));
seen[B_PACKAGE_INFO_LICENSES] = true;
} else if (t.text.ICompare(names[B_PACKAGE_INFO_PROVIDES]) == 0) {
if (seen[B_PACKAGE_INFO_PROVIDES]) {
BString error = BString(names[B_PACKAGE_INFO_PROVIDES])
<< " already seen!";
throw ParseError(error, t.pos);
}
BObjectList<BPackageProvision> provisions;
_ParseProvisionList(&provisions);
int count = provisions.CountItems();
for (int i = 0; i < count; ++i)
packageInfo->AddProvision(*(provisions.ItemAt(i)));
seen[B_PACKAGE_INFO_PROVIDES] = true;
} else if (t.text.ICompare(names[B_PACKAGE_INFO_REQUIRES]) == 0) {
if (seen[B_PACKAGE_INFO_REQUIRES]) {
BString error = BString(names[B_PACKAGE_INFO_REQUIRES])
<< " already seen!";
throw ParseError(error, t.pos);
}
BObjectList<BPackageRequirement> requirements;
_ParseRequirementList(&requirements);
int count = requirements.CountItems();
for (int i = 0; i < count; ++i)
packageInfo->AddRequirement(*(requirements.ItemAt(i)));
seen[B_PACKAGE_INFO_REQUIRES] = true;
}
} }
for (int i = 0; i < B_PACKAGE_INFO_ENUM_COUNT; ++i) { for (int i = 0; i < B_PACKAGE_INFO_ENUM_COUNT; ++i) {
@@ -497,6 +660,197 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
} }
BPackageVersion::BPackageVersion()
{
}
BPackageVersion::BPackageVersion(const BString& major, const BString& minor,
const BString& micro, uint8 release)
:
fMajor(major),
fMinor(minor),
fMicro(micro),
fRelease(release)
{
}
status_t
BPackageVersion::InitCheck() const
{
return fMajor.Length() > 0 ? B_OK : B_NO_INIT;
}
int
BPackageVersion::Compare(const BPackageVersion& other) const
{
int majorDiff = NaturalCompare(fMajor.String(), other.fMajor.String());
if (majorDiff != 0)
return majorDiff;
int minorDiff = NaturalCompare(fMinor.String(), other.fMinor.String());
if (minorDiff != 0)
return minorDiff;
int microDiff = NaturalCompare(fMicro.String(), other.fMicro.String());
if (microDiff != 0)
return microDiff;
return (int)fRelease - (int)other.fRelease;
}
void
BPackageVersion::GetVersionString(BString& string) const
{
string = fMajor;
if (fMinor.Length() > 0) {
string << '.' << fMinor;
if (fMicro.Length() > 0)
string << '.' << fMicro;
}
if (fRelease > 0)
string << '-' << fRelease;
}
void
BPackageVersion::SetTo(const BString& major, const BString& minor,
const BString& micro, uint8 release)
{
fMajor = major;
fMinor = minor;
fMicro = micro;
fRelease = release;
}
void
BPackageVersion::Clear()
{
fMajor.Truncate(0);
fMinor.Truncate(0);
fMicro.Truncate(0);
fRelease = 0;
}
BPackageProvision::BPackageProvision()
{
}
BPackageProvision::BPackageProvision(const BString& name,
const BPackageVersion& version)
:
fName(name),
fVersion(version)
{
}
status_t
BPackageProvision::InitCheck() const
{
return fName.Length() > 0 ? B_OK : B_NO_INIT;
}
void
BPackageProvision::GetProvisionString(BString& string) const
{
string = fName;
if (fVersion.InitCheck() == B_OK) {
string << '=';
fVersion.GetVersionString(string);
}
}
void
BPackageProvision::SetTo(const BString& name, const BPackageVersion& version)
{
fName = name;
fVersion = version;
}
void
BPackageProvision::Clear()
{
fName.Truncate(0);
fVersion.Clear();
}
BPackageRequirement::BPackageRequirement()
{
}
BPackageRequirement::BPackageRequirement(const BString& name,
const BString& _operator, const BPackageVersion& version)
:
fName(name),
fOperator(_operator),
fVersion(version)
{
}
status_t
BPackageRequirement::InitCheck() const
{
if (fName.Length() == 0)
return B_NO_INIT;
// either both or none of operator and version must be set
if (fOperator.Length() == 0 && fVersion.InitCheck() == B_OK)
return B_NO_INIT;
if (fOperator.Length() > 0 && fVersion.InitCheck() != B_OK)
return B_NO_INIT;
return B_OK;
}
void
BPackageRequirement::GetRequirementString(BString& string) const
{
string = fName;
if (fVersion.InitCheck() == B_OK) {
string << fOperator;
fVersion.GetVersionString(string);
}
}
void
BPackageRequirement::SetTo(const BString& name, const BString& _operator,
const BPackageVersion& version)
{
fName = name;
fOperator = _operator;
fVersion = version;
}
void
BPackageRequirement::Clear()
{
fName.Truncate(0);
fOperator.Truncate(0);
fVersion.Clear();
}
const char* BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = { const char* BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = {
"name", "name",
"summary", "summary",
@@ -514,7 +868,7 @@ const char* BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = {
const char* const char*
BPackageInfo::kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = { BPackageInfo::kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = {
"no_arch", "any",
"x86", "x86",
"x86_gcc2", "x86_gcc2",
}; };
@@ -522,7 +876,7 @@ BPackageInfo::kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = {
BPackageInfo::BPackageInfo() BPackageInfo::BPackageInfo()
: :
fArchitecture(B_PACKAGE_ARCHITECTURE_NONE), fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
fCopyrights(5, true), fCopyrights(5, true),
fLicenses(5, true), fLicenses(5, true),
fProvisions(20, true), fProvisions(20, true),
@@ -573,7 +927,7 @@ status_t
BPackageInfo::ReadFromConfigString(const BString& packageInfoString, BPackageInfo::ReadFromConfigString(const BString& packageInfoString,
ParseErrorListener* listener) ParseErrorListener* listener)
{ {
MakeEmpty(); Clear();
Parser parser(listener); Parser parser(listener);
return parser.Parse(packageInfoString, this); return parser.Parse(packageInfoString, this);
@@ -583,7 +937,15 @@ BPackageInfo::ReadFromConfigString(const BString& packageInfoString,
status_t status_t
BPackageInfo::InitCheck() const BPackageInfo::InitCheck() const
{ {
// TODO if (fName.Length() == 0 || fSummary.Length() == 0
|| fDescription.Length() == 0 || fVendor.Length() == 0
|| fPackager.Length() == 0
|| fArchitecture == B_PACKAGE_ARCHITECTURE_ENUM_COUNT
|| fVersion.InitCheck() != B_OK
|| fCopyrights.IsEmpty() || fLicenses.IsEmpty()
|| fProvisions.IsEmpty() || fRequirements.IsEmpty())
return B_NO_INIT;
return B_OK; return B_OK;
} }
@@ -732,21 +1094,6 @@ BPackageInfo::AddCopyright(const BString& copyright)
} }
status_t
BPackageInfo::RemoveCopyright(const BString& copyright)
{
int32 count = fCopyrights.CountItems();
for (int i = 0; i < count; ++i) {
if (fCopyrights.ItemAt(i)->Compare(copyright) == 0) {
delete fCopyrights.RemoveItemAt(i);
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
void void
BPackageInfo::ClearLicenses() BPackageInfo::ClearLicenses()
{ {
@@ -765,55 +1112,6 @@ BPackageInfo::AddLicense(const BString& license)
} }
status_t
BPackageInfo::RemoveLicense(const BString& license)
{
int32 count = fLicenses.CountItems();
for (int i = 0; i < count; ++i) {
if (fLicenses.ItemAt(i)->Compare(license) == 0) {
delete fLicenses.RemoveItemAt(i);
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
void
BPackageInfo::ClearRequirements()
{
fRequirements.MakeEmpty();
}
status_t
BPackageInfo::AddRequirement(const BPackageRequirement& requirement)
{
BPackageRequirement* newRequirement
= new (std::nothrow) BPackageRequirement(requirement);
if (newRequirement == NULL)
return B_NO_MEMORY;
return fRequirements.AddItem(newRequirement) ? B_OK : B_ERROR;
}
status_t
BPackageInfo::RemoveRequirement(const BPackageRequirement& requirement)
{
int32 count = fRequirements.CountItems();
for (int i = 0; i < count; ++i) {
if (fRequirements.ItemAt(i)->Compare(requirement)) {
delete fRequirements.RemoveItemAt(i);
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
void void
BPackageInfo::ClearProvisions() BPackageInfo::ClearProvisions()
{ {
@@ -833,31 +1131,35 @@ BPackageInfo::AddProvision(const BPackageProvision& provision)
} }
status_t void
BPackageInfo::RemoveProvision(const BPackageProvision& provision) BPackageInfo::ClearRequirements()
{ {
int32 count = fProvisions.CountItems(); fRequirements.MakeEmpty();
for (int i = 0; i < count; ++i) { }
if (fProvisions.ItemAt(i)->Compare(provision) == 0) {
delete fProvisions.RemoveItemAt(i);
return B_OK;
}
}
return B_NAME_NOT_FOUND;
status_t
BPackageInfo::AddRequirement(const BPackageRequirement& requirement)
{
BPackageRequirement* newRequirement
= new (std::nothrow) BPackageRequirement(requirement);
if (newRequirement == NULL)
return B_NO_MEMORY;
return fRequirements.AddItem(newRequirement) ? B_OK : B_ERROR;
} }
void void
BPackageInfo::MakeEmpty() BPackageInfo::Clear()
{ {
fName.Truncate(0); fName.Truncate(0);
fSummary.Truncate(0); fSummary.Truncate(0);
fDescription.Truncate(0); fDescription.Truncate(0);
fVendor.Truncate(0); fVendor.Truncate(0);
fPackager.Truncate(0); fPackager.Truncate(0);
fVersion.MakeEmpty(); fVersion.Clear();
fArchitecture = B_PACKAGE_ARCHITECTURE_NONE; fArchitecture = B_PACKAGE_ARCHITECTURE_ENUM_COUNT;
fCopyrights.MakeEmpty(); fCopyrights.MakeEmpty();
fLicenses.MakeEmpty(); fLicenses.MakeEmpty();
fRequirements.MakeEmpty(); fRequirements.MakeEmpty();
@@ -877,4 +1179,16 @@ BPackageInfo::GetElementName(BPackageInfoIndex index, const char** name)
} }
/*static*/ status_t
BPackageInfo::GetArchitectureName(BPackageArchitecture arch, const char** name)
{
if (arch < 0 || arch >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT || name == NULL)
return B_BAD_VALUE;
*name = kArchitectureNames[arch];
return B_OK;
}
} // namespace BPackageKit } // namespace BPackageKit