blob: 9ee7f4f9087527ff1ccb21f2902acfa5dbace488 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
|