diff --git a/src/kits/package/PackageInfo.cpp b/src/kits/package/PackageInfo.cpp index fdcef99678..269ea5e44a 100644 --- a/src/kits/package/PackageInfo.cpp +++ b/src/kits/package/PackageInfo.cpp @@ -6,7 +6,6 @@ #include -#include #include #include #include @@ -23,6 +22,7 @@ #include #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 - 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 - void _WriteValue(const BObjectList& 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 - 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 - 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 diff --git a/src/kits/package/PackageInfoStringBuilder.h b/src/kits/package/PackageInfoStringBuilder.h new file mode 100644 index 0000000000..7bd29cb396 --- /dev/null +++ b/src/kits/package/PackageInfoStringBuilder.h @@ -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 + +#include +#include + + +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 + 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 + void _WriteValue(const BObjectList& 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 + 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 + 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