Skip to content

Commit

Permalink
Improve Base85 interface
Browse files Browse the repository at this point in the history
  • Loading branch information
oblivioncth committed Jul 22, 2023
1 parent 328d46f commit cb20498
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 43 deletions.
12 changes: 6 additions & 6 deletions lib/core/include/qx/core/qx-base85.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,15 @@ class QX_CORE_EXPORT Base85

// External parse
template<typename D>
requires any_of<D, QString, QByteArrayView>
requires any_of<D, QLatin1StringView, QUtf8StringView, QStringView>
static Base85 fromExternal(D base85, const Base85Encoding* enc, Base85ParseError* error);

template<typename D, typename C = typename std::iterator_traits<typename D::const_iterator>::value_type>
requires any_of<D, QString, QByteArrayView>
template<typename D>
requires any_of<D, QLatin1StringView, QUtf8StringView, QStringView>
static Base85ParseError parseExternal(D base85, Base85& externallyEncoded);

public:
static Base85 fromString(const QString& base85, const Base85Encoding* enc, Base85ParseError* error = nullptr);
static Base85 fromData(QByteArrayView base85, const Base85Encoding* enc, Base85ParseError* error = nullptr);
static Base85 fromEncoded(QAnyStringView base85, const Base85Encoding* enc, Base85ParseError* error = nullptr);
static Base85 encode(const QByteArray& data, const Base85Encoding* enc);

//-Instance Functions---------------------------------------------------------------------------------------------------------
Expand All @@ -238,7 +237,8 @@ class QX_CORE_EXPORT Base85

QByteArray decode();
QString toString();
const QByteArray& encodedData() const;
QByteArrayView data() const;
qsizetype size() const;

bool operator==(const Base85& other) const;
bool operator!=(const Base85& other) const;
Expand Down
62 changes: 25 additions & 37 deletions lib/core/src/qx-base85.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ char Base85::charToLatin1(QChar ch) { return ch.toLatin1(); }
* definitions are obviously available here, the above holds true.
*/
template<typename D>
requires any_of<D, QString, QByteArrayView>
requires any_of<D, QLatin1StringView, QUtf8StringView, QStringView>
Base85 Base85::fromExternal(D base85, const Base85Encoding* enc, Base85ParseError* error)
{
// Ensure encoding is valid
Expand Down Expand Up @@ -876,22 +876,24 @@ Base85 Base85::fromExternal(D base85, const Base85Encoding* enc, Base85ParseErro
return externallyEncoded;
}

template<typename D, typename C>
requires any_of<D, QString, QByteArrayView>
template<typename D>
requires any_of<D, QLatin1StringView, QUtf8StringView, QStringView>
Base85ParseError Base85::parseExternal(D base85, Base85& externallyEncoded)
{
using CharType = typename D::value_type;

const Base85Encoding* encooding = externallyEncoded.encoding();

//-Check for Padding---------------------------------------------------------------
// Determine shortcut characters vs regular characters (assume encoding is correct at this point)
QSet<C> shortcutChars;
QSet<CharType> shortcutChars;
if(encooding->usesZeroGroupShortcut())
shortcutChars.insert(encooding->zeroGroupCharacter().value());
if(encooding->usesSpaceGroupShortcut())
shortcutChars.insert(encooding->spaceGroupCharacter().value());

int shortcutCount = shortcutChars.isEmpty() ? 0 :
std::count_if(base85.cbegin(), base85.cend(), [&shortcutChars](const C& c){ return shortcutChars.contains(c); });
std::count_if(base85.cbegin(), base85.cend(), [&shortcutChars](const auto& c){ return shortcutChars.contains(c); });
int nonShortcutCount = base85.size() - shortcutCount;

// Determine if string relies on padding
Expand All @@ -908,31 +910,31 @@ Base85ParseError Base85::parseExternal(D base85, Base85& externallyEncoded)

// Validate each character one-by-one and append to internal data
int frameIdx = 0;
for(qsizetype i = 0; i < base85.size(); i++)
for(qsizetype chIdx = -1; const auto& ch : base85)
{
const C& ch = base85[i];
++chIdx;

// White space is to be ignored, if char is whitespace, skip it
if(Char::isSpace(ch))
continue;

// Only matters for input type that contains QChar
if constexpr(std::is_same_v<C, QChar>)
if constexpr(std::is_same_v<CharType, QStringView>)
{
// Ensure character can fit in one byte (ASCII/extended-ASCII)
if(ch.unicode() > 255)
return Base85ParseError(Base85ParseError::NonANSI, i);
if(ch > 255)
return Base85ParseError(Base85ParseError::NonANSI, chIdx);
}

// Ensure character belongs to encoding
char asciiChar = charToLatin1(ch); // Ensures char is Latin1, covers QChar
if(!encooding->containsCharacter(asciiChar))
return Base85ParseError(Base85ParseError::CharacterSetMismatch, i);
return Base85ParseError(Base85ParseError::CharacterSetMismatch, chIdx);

// Check if character is a shortcut char, and if so is appropriately used
bool isShortcut = shortcutChars.contains(ch);
if(isShortcut && frameIdx != 0) // Can only be used at start of frame
return Base85ParseError(Base85ParseError::ShortcutMidFrame, i);
return Base85ParseError(Base85ParseError::ShortcutMidFrame, chIdx);

// Add validated character
encodedData->append(asciiChar);
Expand All @@ -950,27 +952,8 @@ Base85ParseError Base85::parseExternal(D base85, Base85& externallyEncoded)

//Public:
/*!
* Parses @a base85 as a Base85 string that was encoded with @a enc and creates a Base85
* object from it. Any whitespace within the original string will not be present in the
* resultant object.
*
* Returns a valid (non-null) Base85 string if the parsing succeeds. If it fails, the
* returned string will be null, and the optional @a error variable will contain further
* details about the error.
*
* @warning The caller must be able to guarantee that @a enc will not be deleted as long as
* the Base85 exists and may have its methods used.
*
* @sa toString(), fromData(), Base85ParseError, and isNull().
*/
Base85 Base85::fromString(const QString& base85, const Base85Encoding* enc, Base85ParseError* error)
{
return fromExternal(base85, enc, error);
}

/*!
* Parses the binary data @a base85 as a Base85 string that was encoded with @a enc and creates
* a Base85 object from it. Any whitespace within the original string will not be present in the
* Parses @a base85 as a Base85 string that was encoded with @a enc and creates
* a Base85 object from it. Any whitespace within the original data will not be present in the
* resultant object.
*
* Returns a valid (non-null) Base85 string if the parsing succeeds. If it fails, the
Expand All @@ -982,9 +965,9 @@ Base85 Base85::fromString(const QString& base85, const Base85Encoding* enc, Base
*
* @sa fromString(), Base85ParseError, isNull(), and @a encodedData().
*/
Base85 Base85::fromData(QByteArrayView base85, const Base85Encoding* enc, Base85ParseError* error)
Base85 Base85::fromEncoded(QAnyStringView base85, const Base85Encoding* enc, Base85ParseError* error)
{
return fromExternal(base85, enc, error);
return base85.visit([&](auto str){ return fromExternal(str, enc, error); });
}

/*!
Expand Down Expand Up @@ -1065,11 +1048,16 @@ QByteArray Base85::decode()
QString Base85::toString() { return QString::fromLatin1(mEncoded); }

/*!
* Returns a reference to the encoded data.
* Returns a view of the encoded data.
*
* @sa toString().
*/
const QByteArray& Base85::encodedData() const { return mEncoded; }
QByteArrayView Base85::data() const { return mEncoded; }

/*!
* Returns the size of the encoded data.
*/
qsizetype Base85::size() const { return mEncoded.size(); }


/*!
Expand Down

0 comments on commit cb20498

Please sign in to comment.