diff options
author | Matt Vogt <matthew.vogt@jollamobile.com> | 2014-12-23 08:06:04 +1000 |
---|---|---|
committer | Matthew Vogt <matthew.vogt@qinetic.com.au> | 2015-01-05 04:56:51 +0100 |
commit | 6aa227bcf2d34acff67cebf656df40e308221da8 (patch) | |
tree | 7a9b3b74b5921ed76777d0f6c08df86474dc1157 /src/organizer/qorganizermanager_p.cpp | |
parent | f922e68d080136eafb51f760633d84cd5aedf71d (diff) |
PIM ID local components do not need to be human-readable
The PIM ID objects compose two elements: the URI of the manager that
owns them, and a local component meaningful only to that manager. The
URI is composed from human-readable elements and benefits from a
string representation, but the local element has no requirement on
readability, and can consume less storage by using a binary
representation.
Change-Id: I56d553f6d9debf0486310688006b0be8728c1c90
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Christopher Adams <chris.adams@jollamobile.com>
Diffstat (limited to 'src/organizer/qorganizermanager_p.cpp')
-rw-r--r-- | src/organizer/qorganizermanager_p.cpp | 141 |
1 files changed, 98 insertions, 43 deletions
diff --git a/src/organizer/qorganizermanager_p.cpp b/src/organizer/qorganizermanager_p.cpp index d4cd966ca..5fd9af31d 100644 --- a/src/organizer/qorganizermanager_p.cpp +++ b/src/organizer/qorganizermanager_p.cpp @@ -261,6 +261,24 @@ static inline QString escapeParam(const QString ¶m) return ret; } +static inline QByteArray escapeColon(const QByteArray ¶m) +{ + QByteArray ret; + const int len = param.length(); + ret.reserve(len + (len >> 3)); + for (QByteArray::const_iterator it = param.begin(), end = param.end(); it != end; ++it) { + switch (*it) { + case ':': + ret += ":"; + break; + default: + ret += *it; + break; + } + } + return ret; +} + static inline QString unescapeParam(const QString ¶m) { QString ret(param); @@ -272,19 +290,32 @@ static inline QString unescapeParam(const QString ¶m) return ret; } +static inline QByteArray unescapeColon(const QByteArray ¶m) +{ + QByteArray ret(param); + int index = 0; + while ((index = ret.indexOf('&', index)) != -1) { + const QByteArray partial(ret.mid(index, 5)); + if (partial == ":") + ret.replace(index, 5, ":"); + ++index; + } + return ret; +} + /*! - Parses the individual components of the given \a idString and fills the - \a managerName, \a params, \a managerUri and \a engineIdString. + Parses the individual components of the given \a uriString and fills the + \a managerName, \a params and \a managerUri and \a localId. Returns true if the parts could be parsed successfully, false otherwise. */ -bool QOrganizerManagerData::parseIdString(const QString &idString, QString *managerName, QMap<QString, QString> *params, QString *managerUri, QString *engineIdString) +bool QOrganizerManagerData::parseUri(const QString &uriString, QString *managerName, QMap<QString, QString> *params, bool strict) { - // Format: qtorganizer:<managerid>:<key>=<value>&<key>=<value>:<engineIdString> - // we assume that the prefix, managerid, params, and engineIdString cannot contain `:', `=', or `&' - // similarly, that neither param keys nor param values can contain these characters + // Format: qtorganizer:<managerid>:<key>=<value>&<key>=<value> + // we assume that the prefix, managerid, and params cannot contain `:', `=', or `&' + // similarly, that neither param keys nor param values can contain these characters. - const QStringList colonSplit = idString.split(QLatin1Char(':'), QString::KeepEmptyParts); - if (colonSplit.size() < 2 || (engineIdString && colonSplit.size() != 4)) + const QStringList colonSplit = uriString.split(QLatin1Char(':'), QString::KeepEmptyParts); + if ((colonSplit.size() != 3) && (strict || colonSplit.size() != 2)) return false; const QString prefix = colonSplit.at(0); @@ -323,59 +354,83 @@ bool QOrganizerManagerData::parseIdString(const QString &idString, QString *mana if (managerName) *managerName = unescapeParam(mgrName); - if (managerUri) - *managerUri = cachedUri(prefix + QLatin1Char(':') + mgrName + QLatin1Char(':') + paramString); - - // and unescape the engine id string - if (engineIdString) - *engineIdString = unescapeParam(colonSplit.at(3)); - return true; } /*! Returns an ID string that describes a manager name and parameters with which to instantiate - a manager object, from the given \a managerUri. - If \a engineIdString is non-null, the generated ID string is suitable for + a manager object, from the given \a managerName and \a params. + If \a localId is non-null, the generated ID string is suitable for passing to QOrganizerCollectionId::fromString() or QOrganizerItemId::fromString(). */ -QString QOrganizerManagerData::buildIdString(const QString &managerUri, const QString &engineIdString) +QString QOrganizerManagerData::buildUri(const QString &managerName, const QMap<QString, QString> ¶ms) { - if (!engineIdString.isNull()) - return managerUri + QLatin1Char(':') + escapeParam(engineIdString); + // Format: qtorganizer:<managerid>:<key>=<value>&<key>=<value> + // if the prefix, managerid, param keys, or param values contain `:', `=', or `&', + // we escape them to `:', `&equ;', and `&', respectively. - return managerUri; + QString paramString; + QMap<QString, QString>::const_iterator it = params.constBegin(); + for ( ; it != params.constEnd(); ++it) { + if (it.key().isEmpty()) + continue; + if (!paramString.isEmpty()) + paramString += QLatin1Char('&'); + paramString += escapeParam(it.key()) + QLatin1Char('=') + escapeParam(it.value()); + } + + return QStringLiteral("qtorganizer:") + escapeParam(managerName) + QLatin1Char(':') + paramString; } /*! - Returns a ID string that describes a manager name and parameters with which to instantiate - a manager object, from the given \a managerName and \a params. - If \a engineIdString is non-null, the generated ID string is suitable for - passing to QOrganizerCollectionId::fromString() or QOrganizerItemId::fromString(). + Parses the individual components of the given \a idData and fills the + \a managerName, \a params, \a managerUri and \a localId. + Returns true if the parts could be parsed successfully, false otherwise. */ -QString QOrganizerManagerData::buildIdString(const QString &managerName, const QMap<QString, QString> ¶ms, const QString &engineIdString) +bool QOrganizerManagerData::parseIdData(const QByteArray &idData, QString *managerName, QMap<QString, QString> *params, QString *managerUri, QByteArray *localId) { - // Format: qtorganizer:<managerid>:<key>=<value>&<key>=<value>:<engineIdString> - // if the prefix, managerid, param keys, param values, or engineIdString contain `:', `=', or `&', - // we escape them to `:', `&equ;', and `&', respectively + // Format: <managerUri>:<localId> + int splitIndex = idData.lastIndexOf(':'); + if (splitIndex == -1) + return false; - QString idString; + const QString uriString(QString::fromUtf8(idData.mid(0, splitIndex))); + if (!parseUri(uriString, managerName, params)) + return false; - // we have to escape each param - QMap<QString, QString>::const_iterator it = params.constBegin(); - for ( ; it != params.constEnd(); ++it) { - if (it.key().isEmpty()) - continue; - if (!idString.isEmpty()) - idString += QLatin1Char('&'); - idString += escapeParam(it.key()) + QLatin1Char('=') + escapeParam(it.value()); - } + if (managerUri) + *managerUri = uriString; + if (localId) + *localId = unescapeColon(idData.mid(splitIndex + 1)); - idString = QStringLiteral("qtorganizer:") + escapeParam(managerName) + QLatin1Char(':') + idString; - if (!engineIdString.isNull()) - idString += QLatin1Char(':') + escapeParam(engineIdString); + return true; +} - return idString; +/*! + Returns an ID string that describes a manager name and parameters with which to instantiate + a manager object, from the given \a managerUri. + If \a localId is non-null, the generated ID string is suitable for + passing to QOrganizerCollectionId::fromString() or QOrganizerItemId::fromString(). +*/ +QByteArray QOrganizerManagerData::buildIdData(const QString &managerUri, const QByteArray &localId) +{ + // Format: <managerUri>:<localId> + // localId cannot contain ':' so it must be escaped + QByteArray rv = managerUri.toUtf8(); + if (!localId.isEmpty()) + rv.append(':').append(escapeColon(localId)); + return rv; +} + +/*! + Returns an ID string that describes a manager name and parameters with which to instantiate + a manager object, from the given \a managerName and \a params. + If \a localId is non-null, the generated ID string is suitable for + passing to QOrganizerCollectionId::fromString() or QOrganizerItemId::fromString(). +*/ +QByteArray QOrganizerManagerData::buildIdData(const QString &managerName, const QMap<QString, QString> ¶ms, const QByteArray &localId) +{ + return buildIdData(buildUri(managerName, params), localId); } /*! |