diff options
Diffstat (limited to 'src/Xpl2Protocol.cpp')
| -rw-r--r-- | src/Xpl2Protocol.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/Xpl2Protocol.cpp b/src/Xpl2Protocol.cpp new file mode 100644 index 0000000..9ee7f4f --- /dev/null +++ b/src/Xpl2Protocol.cpp @@ -0,0 +1,128 @@ +/** + * @file Xpl2Protocol.cpp + * @brief Wire framing for the XPL2 printhead protocol. + */ +#include "Xpl2Protocol.h" + +#include <QMetaType> + +namespace Xpl2Protocol +{ + +QByteArray +buildMessage (const QByteArray &command, const QVariantList ¶ms) +{ + QByteArray msg = command; + + for (const QVariant &p : params) + { + msg += ','; + + switch (p.typeId ()) + { + case QMetaType::Bool: + msg += p.toBool () ? '1' : '0'; + break; + case QMetaType::Int: + case QMetaType::LongLong: + msg += QByteArray::number (p.toLongLong ()); + break; + case QMetaType::UInt: + case QMetaType::ULongLong: + msg += QByteArray::number (p.toULongLong ()); + break; + case QMetaType::Float: + case QMetaType::Double: + msg += QByteArray::number (p.toDouble (), 'g', 10); + break; + default: + msg += '"'; + msg += p.toString ().toUtf8 (); + msg += '"'; + break; + } + } + + msg += Terminator; + return msg; +} + +static QList<QByteArray> +splitFields (const QByteArray &data) +{ + QList<QByteArray> fields; + QByteArray current; + bool inQuotes = false; + + for (int i = 0; i < data.size (); ++i) + { + char c = data.at (i); + + if (c == '"') + { + inQuotes = !inQuotes; + current += c; + } + else if (c == ',' && !inQuotes) + { + fields.append (current); + current.clear (); + } + else + { + current += c; + } + } + + if (!current.isEmpty ()) + fields.append (current); + + return fields; +} + +static QVariant +parseField (const QByteArray &field) +{ + if (field.size () >= 2 && field.front () == '"' && field.back () == '"') + return QString::fromUtf8 (field.mid (1, field.size () - 2)); + + bool ok = false; + + int intVal = field.toInt (&ok); + if (ok) + return intVal; + + double dblVal = field.toDouble (&ok); + if (ok) + return dblVal; + + return QString::fromUtf8 (field); +} + +ParsedMessage +parseMessage (const QByteArray &raw) +{ + QByteArray data = raw; + + /* Strip terminator. */ + while (!data.isEmpty () && data.back () == Terminator) + data.chop (1); + + if (data.isEmpty ()) + return {}; + + QList<QByteArray> fields = splitFields (data); + if (fields.isEmpty ()) + return {}; + + ParsedMessage msg; + msg.command = fields.takeFirst (); + msg.valid = true; + + for (const QByteArray &f : fields) + msg.params.append (parseField (f)); + + return msg; +} + +} // namespace Xpl2Protocol |
