Move package info string builder to its own header
This commit is contained in:
parent
6da0ce6ff2
commit
daa10fc3a5
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <package/PackageInfo.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -23,6 +22,7 @@
|
|||
#include <package/PackageInfoContentHandler.h>
|
||||
|
||||
#include "PackageInfoParser.h"
|
||||
#include "PackageInfoStringBuilder.h"
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
@ -72,277 +72,6 @@ const char* const BPackageInfo::kSettingsFileUpdateTypes[
|
|||
};
|
||||
|
||||
|
||||
// #pragma mark - StringBuilder
|
||||
|
||||
|
||||
struct BPackageInfo::StringBuilder {
|
||||
StringBuilder()
|
||||
:
|
||||
fData(),
|
||||
fError(B_OK),
|
||||
fBasePackage()
|
||||
{
|
||||
}
|
||||
|
||||
status_t Error() const
|
||||
{
|
||||
return fError;
|
||||
}
|
||||
|
||||
status_t GetString(BString& _string) const
|
||||
{
|
||||
if (fError != B_OK) {
|
||||
_string = BString();
|
||||
return fError;
|
||||
}
|
||||
|
||||
_string.SetTo((const char*)fData.Buffer(), fData.BufferLength());
|
||||
return (size_t)_string.Length() == fData.BufferLength()
|
||||
? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
StringBuilder& Write(const char* attribute, Value value)
|
||||
{
|
||||
if (_IsValueEmpty(value))
|
||||
return *this;
|
||||
|
||||
_Write(attribute);
|
||||
_Write('\t');
|
||||
_WriteValue(value);
|
||||
_Write('\n');
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuilder& WriteFlags(const char* attribute, uint32 flags)
|
||||
{
|
||||
if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) == 0
|
||||
&& (flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) == 0) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Write(attribute);
|
||||
_Write('\t');
|
||||
|
||||
if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) == 0)
|
||||
_Write(" approve_license");
|
||||
if ((flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) == 0)
|
||||
_Write(" system_package");
|
||||
|
||||
_Write('\n');
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuilder& BeginRequires(const BString& basePackage)
|
||||
{
|
||||
fBasePackage = basePackage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuilder& EndRequires()
|
||||
{
|
||||
fBasePackage.Truncate(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void _WriteValue(const char* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value);
|
||||
}
|
||||
|
||||
void _WriteValue(const BPackageVersion& value)
|
||||
{
|
||||
if (fError != B_OK)
|
||||
return;
|
||||
|
||||
if (value.InitCheck() != B_OK) {
|
||||
fError = B_BAD_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
_Write(value.ToString());
|
||||
}
|
||||
|
||||
void _WriteValue(const BStringList& value)
|
||||
{
|
||||
int32 count = value.CountStrings();
|
||||
if (count == 1) {
|
||||
_WriteMaybeQuoted(value.StringAt(0));
|
||||
} else {
|
||||
_Write("{\n", 2);
|
||||
|
||||
int32 count = value.CountStrings();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
_Write('\t');
|
||||
_WriteMaybeQuoted(value.StringAt(i));
|
||||
_Write('\n');
|
||||
}
|
||||
|
||||
_Write('}');
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
void _WriteValue(const BObjectList<Value>& value)
|
||||
{
|
||||
// Note: The fBasePackage solution is disgusting, but any attempt of
|
||||
// encapsulating the stringification via templates seems to result in
|
||||
// an Internal Compiler Error with gcc 2.
|
||||
|
||||
int32 count = value.CountItems();
|
||||
if (count == 1) {
|
||||
_WriteListElement(value.ItemAt(0));
|
||||
} else {
|
||||
_Write("{\n", 2);
|
||||
|
||||
int32 count = value.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
_Write('\t');
|
||||
_WriteListElement(value.ItemAt(i));
|
||||
_Write('\n');
|
||||
}
|
||||
|
||||
_Write('}');
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
void _WriteListElement(const Value* value)
|
||||
{
|
||||
_Write(value->ToString());
|
||||
if (!fBasePackage.IsEmpty()
|
||||
&& value->Name() == fBasePackage) {
|
||||
_Write(" base");
|
||||
}
|
||||
}
|
||||
|
||||
void _WriteListElement(const BGlobalSettingsFileInfo* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value->Path());
|
||||
if (value->IsIncluded()) {
|
||||
_Write(' ');
|
||||
_Write(kSettingsFileUpdateTypes[value->UpdateType()]);
|
||||
}
|
||||
}
|
||||
|
||||
void _WriteListElement(const BUserSettingsFileInfo* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value->Path());
|
||||
if (!value->TemplatePath().IsEmpty()) {
|
||||
_Write(" template ");
|
||||
_WriteMaybeQuoted(value->TemplatePath());
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool _IsValueEmpty(const char* value)
|
||||
{
|
||||
return value[0] == '\0';
|
||||
}
|
||||
|
||||
static inline bool _IsValueEmpty(const BPackageVersion& value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename List>
|
||||
static inline bool _IsValueEmpty(const List& value)
|
||||
{
|
||||
return value.IsEmpty();
|
||||
}
|
||||
|
||||
void _WriteMaybeQuoted(const char* data)
|
||||
{
|
||||
// check whether quoting is needed
|
||||
bool needsQuoting = false;
|
||||
bool needsEscaping = false;
|
||||
for (const char* it = data; *it != '\0'; it++) {
|
||||
if (isalnum(*it) || *it == '.' || *it == '-' || *it == '_'
|
||||
|| *it == ':' || *it == '+') {
|
||||
continue;
|
||||
}
|
||||
|
||||
needsQuoting = true;
|
||||
|
||||
if (*it == '\t' || *it == '\n' || *it == '"' || *it == '\\') {
|
||||
needsEscaping = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsQuoting) {
|
||||
_Write(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// we need quoting
|
||||
_Write('"');
|
||||
|
||||
// escape the string, if necessary
|
||||
if (needsEscaping) {
|
||||
const char* start = data;
|
||||
const char* end = data;
|
||||
while (*end != '\0') {
|
||||
char replacement[2];
|
||||
switch (*end) {
|
||||
case '\t':
|
||||
replacement[1] = 't';
|
||||
break;
|
||||
case '\n':
|
||||
replacement[1] = 'n';
|
||||
break;
|
||||
case '"':
|
||||
case '\\':
|
||||
replacement[1] = *end;
|
||||
break;
|
||||
default:
|
||||
end++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start < end)
|
||||
_Write(start, end - start);
|
||||
|
||||
replacement[0] = '\\';
|
||||
_Write(replacement, 2);
|
||||
}
|
||||
} else
|
||||
_Write(data);
|
||||
|
||||
_Write('"');
|
||||
}
|
||||
|
||||
inline void _Write(char data)
|
||||
{
|
||||
_Write(&data, 1);
|
||||
}
|
||||
|
||||
inline void _Write(const char* data)
|
||||
{
|
||||
_Write(data, strlen(data));
|
||||
}
|
||||
|
||||
inline void _Write(const BString& data)
|
||||
{
|
||||
_Write(data, data.Length());
|
||||
}
|
||||
|
||||
void _Write(const void* data, size_t size)
|
||||
{
|
||||
if (fError == B_OK) {
|
||||
ssize_t bytesWritten = fData.Write(data, size);
|
||||
if (bytesWritten < 0)
|
||||
fError = bytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BMallocIO fData;
|
||||
status_t fError;
|
||||
BString fBasePackage;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - FieldName
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PACKAGE_INFO_STRING_BUILDER_H
|
||||
#define PACKAGE_INFO_STRING_BUILDER_H
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <package/PackageInfo.h>
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
struct BPackageInfo::StringBuilder {
|
||||
StringBuilder()
|
||||
:
|
||||
fData(),
|
||||
fError(B_OK),
|
||||
fBasePackage()
|
||||
{
|
||||
}
|
||||
|
||||
status_t Error() const
|
||||
{
|
||||
return fError;
|
||||
}
|
||||
|
||||
status_t GetString(BString& _string) const
|
||||
{
|
||||
if (fError != B_OK) {
|
||||
_string = BString();
|
||||
return fError;
|
||||
}
|
||||
|
||||
_string.SetTo((const char*)fData.Buffer(), fData.BufferLength());
|
||||
return (size_t)_string.Length() == fData.BufferLength()
|
||||
? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
StringBuilder& Write(const char* attribute, Value value)
|
||||
{
|
||||
if (_IsValueEmpty(value))
|
||||
return *this;
|
||||
|
||||
_Write(attribute);
|
||||
_Write('\t');
|
||||
_WriteValue(value);
|
||||
_Write('\n');
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuilder& WriteFlags(const char* attribute, uint32 flags)
|
||||
{
|
||||
if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) == 0
|
||||
&& (flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) == 0) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Write(attribute);
|
||||
_Write('\t');
|
||||
|
||||
if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) == 0)
|
||||
_Write(" approve_license");
|
||||
if ((flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) == 0)
|
||||
_Write(" system_package");
|
||||
|
||||
_Write('\n');
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuilder& BeginRequires(const BString& basePackage)
|
||||
{
|
||||
fBasePackage = basePackage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuilder& EndRequires()
|
||||
{
|
||||
fBasePackage.Truncate(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void _WriteValue(const char* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value);
|
||||
}
|
||||
|
||||
void _WriteValue(const BPackageVersion& value)
|
||||
{
|
||||
if (fError != B_OK)
|
||||
return;
|
||||
|
||||
if (value.InitCheck() != B_OK) {
|
||||
fError = B_BAD_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
_Write(value.ToString());
|
||||
}
|
||||
|
||||
void _WriteValue(const BStringList& value)
|
||||
{
|
||||
int32 count = value.CountStrings();
|
||||
if (count == 1) {
|
||||
_WriteMaybeQuoted(value.StringAt(0));
|
||||
} else {
|
||||
_Write("{\n", 2);
|
||||
|
||||
int32 count = value.CountStrings();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
_Write('\t');
|
||||
_WriteMaybeQuoted(value.StringAt(i));
|
||||
_Write('\n');
|
||||
}
|
||||
|
||||
_Write('}');
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
void _WriteValue(const BObjectList<Value>& value)
|
||||
{
|
||||
// Note: The fBasePackage solution is disgusting, but any attempt of
|
||||
// encapsulating the stringification via templates seems to result in
|
||||
// an Internal Compiler Error with gcc 2.
|
||||
|
||||
int32 count = value.CountItems();
|
||||
if (count == 1) {
|
||||
_WriteListElement(value.ItemAt(0));
|
||||
} else {
|
||||
_Write("{\n", 2);
|
||||
|
||||
int32 count = value.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
_Write('\t');
|
||||
_WriteListElement(value.ItemAt(i));
|
||||
_Write('\n');
|
||||
}
|
||||
|
||||
_Write('}');
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
void _WriteListElement(const Value* value)
|
||||
{
|
||||
_Write(value->ToString());
|
||||
if (!fBasePackage.IsEmpty()
|
||||
&& value->Name() == fBasePackage) {
|
||||
_Write(" base");
|
||||
}
|
||||
}
|
||||
|
||||
void _WriteListElement(const BGlobalSettingsFileInfo* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value->Path());
|
||||
if (value->IsIncluded()) {
|
||||
_Write(' ');
|
||||
_Write(kSettingsFileUpdateTypes[value->UpdateType()]);
|
||||
}
|
||||
}
|
||||
|
||||
void _WriteListElement(const BUserSettingsFileInfo* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value->Path());
|
||||
if (!value->TemplatePath().IsEmpty()) {
|
||||
_Write(" template ");
|
||||
_WriteMaybeQuoted(value->TemplatePath());
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool _IsValueEmpty(const char* value)
|
||||
{
|
||||
return value[0] == '\0';
|
||||
}
|
||||
|
||||
static inline bool _IsValueEmpty(const BPackageVersion& value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename List>
|
||||
static inline bool _IsValueEmpty(const List& value)
|
||||
{
|
||||
return value.IsEmpty();
|
||||
}
|
||||
|
||||
void _WriteMaybeQuoted(const char* data)
|
||||
{
|
||||
// check whether quoting is needed
|
||||
bool needsQuoting = false;
|
||||
bool needsEscaping = false;
|
||||
for (const char* it = data; *it != '\0'; it++) {
|
||||
if (isalnum(*it) || *it == '.' || *it == '-' || *it == '_'
|
||||
|| *it == ':' || *it == '+') {
|
||||
continue;
|
||||
}
|
||||
|
||||
needsQuoting = true;
|
||||
|
||||
if (*it == '\t' || *it == '\n' || *it == '"' || *it == '\\') {
|
||||
needsEscaping = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsQuoting) {
|
||||
_Write(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// we need quoting
|
||||
_Write('"');
|
||||
|
||||
// escape the string, if necessary
|
||||
if (needsEscaping) {
|
||||
const char* start = data;
|
||||
const char* end = data;
|
||||
while (*end != '\0') {
|
||||
char replacement[2];
|
||||
switch (*end) {
|
||||
case '\t':
|
||||
replacement[1] = 't';
|
||||
break;
|
||||
case '\n':
|
||||
replacement[1] = 'n';
|
||||
break;
|
||||
case '"':
|
||||
case '\\':
|
||||
replacement[1] = *end;
|
||||
break;
|
||||
default:
|
||||
end++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start < end)
|
||||
_Write(start, end - start);
|
||||
|
||||
replacement[0] = '\\';
|
||||
_Write(replacement, 2);
|
||||
}
|
||||
} else
|
||||
_Write(data);
|
||||
|
||||
_Write('"');
|
||||
}
|
||||
|
||||
inline void _Write(char data)
|
||||
{
|
||||
_Write(&data, 1);
|
||||
}
|
||||
|
||||
inline void _Write(const char* data)
|
||||
{
|
||||
_Write(data, strlen(data));
|
||||
}
|
||||
|
||||
inline void _Write(const BString& data)
|
||||
{
|
||||
_Write(data, data.Length());
|
||||
}
|
||||
|
||||
void _Write(const void* data, size_t size)
|
||||
{
|
||||
if (fError == B_OK) {
|
||||
ssize_t bytesWritten = fData.Write(data, size);
|
||||
if (bytesWritten < 0)
|
||||
fError = bytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BMallocIO fData;
|
||||
status_t fError;
|
||||
BString fBasePackage;
|
||||
};
|
||||
|
||||
|
||||
} // namespace BPackageKit
|
||||
|
||||
|
||||
#endif // PACKAGE_INFO_STRING_BUILDER_H
|
Loading…
Reference in New Issue