21 #include "qjson_debug.h"
22 #include "json_scanner.h"
23 #include "json_parser.hh"
27 #include <QtCore/QDebug>
28 #include <QtCore/QRegExp>
32 bool ishexnstring(
const QString&
string) {
33 for (
int i = 0; i <
string.length(); i++) {
34 if (isxdigit(
string[i] == 0))
40 JSonScanner::JSonScanner(QIODevice* io)
43 m_quotmarkClosed =
true;
47 static QString unescape(
const QByteArray& ba,
bool* ok ) {
53 for (
int i = 0, size = ba.size(); i < size; ++i ) {
54 const char ch = ba[i];
80 res += QString::fromUtf8( seg );
88 const QString hex_digit1 = QString::fromUtf8( ba.mid( i + 1, 2 ) );
89 const QString hex_digit2 = QString::fromUtf8( ba.mid( i + 3, 2 ) );
92 if ( !ishexnstring( hex_digit1 ) || !ishexnstring( hex_digit2 ) ) {
93 qCritical() <<
"Not an hex string:" << hex_digit1 << hex_digit2;
97 const ushort hex_code1 = hex_digit1.toShort( &hexOk, 16 );
99 qCritical() <<
"error converting hex value to short:" << hex_digit1;
102 const ushort hex_code2 = hex_digit2.toShort( &hexOk, 16 );
104 qCritical() <<
"error converting hex value to short:" << hex_digit2;
108 res += QChar(hex_code2, hex_code1);
120 res += QString::fromUtf8( seg );
125 int JSonScanner::yylex(YYSTYPE* yylval,
yy::location *yylloc)
129 if (!m_io->isOpen()) {
130 qCritical() <<
"JSonScanner::yylex - io device is not open";
139 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::END";
140 return yy::json_parser::token::END;
143 ret = m_io->getChar(&ch);
146 qCritical() <<
"JSonScanner::yylex - error reading from io device";
150 qjsonDebug() <<
"JSonScanner::yylex - got |" << ch <<
"|";
154 if (ch ==
'\n' || ch ==
'\r')
157 }
while (m_quotmarkClosed && (isspace(ch) != 0));
159 if (m_quotmarkClosed && ((ch ==
't') || (ch ==
'T')
160 || (ch ==
'n') || (ch ==
'N'))) {
162 const QByteArray buf = m_io->peek(3).toLower();
164 if (buf.length() == 3) {
168 qjsonDebug() <<
"JSonScanner::yylex - TRUE_VAL";
169 return yy::json_parser::token::TRUE_VAL;
171 else if (buf ==
"ull") {
174 qjsonDebug() <<
"JSonScanner::yylex - NULL_VAL";
175 return yy::json_parser::token::NULL_VAL;
179 else if (m_quotmarkClosed && ((ch ==
'f') || (ch ==
'F'))) {
181 const QByteArray buf = m_io->peek(4).toLower();
182 if (buf.length() == 4) {
186 qjsonDebug() <<
"JSonScanner::yylex - FALSE_VAL";
187 return yy::json_parser::token::FALSE_VAL;
191 else if (m_quotmarkClosed && ((ch ==
'e') || (ch ==
'E'))) {
192 QByteArray ret(1, ch);
193 const QByteArray buf = m_io->peek(1);
194 if (!buf.isEmpty()) {
195 if ((buf[0] ==
'+' ) || (buf[0] ==
'-' )) {
196 ret += m_io->read (1);
200 *yylval = QVariant(QString::fromUtf8(ret));
201 return yy::json_parser::token::E;
204 if (ch !=
'"' && !m_quotmarkClosed) {
209 bool escape_on = (ch ==
'\\') ?
true :
false;
213 qint64 ret = m_io->peek(&nextCh, 1);
216 return yy::json_parser::token::END;
219 }
else if ( !escape_on && nextCh ==
'\"' ) {
221 const QString str = unescape( raw, &ok );
222 *yylval = ok ? str : QString();
223 return ok ? yy::json_parser::token::STRING : -1;
226 if ( prevCh ==
'\\' && nextCh !=
'"' && nextCh !=
'\\' && nextCh !=
'/' &&
227 nextCh !=
'b' && nextCh !=
'f' && nextCh !=
'n' &&
228 nextCh !=
'r' && nextCh !=
't' && nextCh !=
'u') {
229 qjsonDebug() <<
"Just read" << nextCh;
230 qjsonDebug() <<
"JSonScanner::yylex - error decoding escaped sequence";
240 escape_on = (prevCh ==
'\\') ?
true :
false;
242 if (nextCh ==
'\\') {
244 if (m_io->getChar (&buf)) {
246 if (((buf !=
'"') && (buf !=
'\\') && (buf !=
'/') &&
247 (buf !=
'b') && (buf !=
'f') && (buf !=
'n') &&
248 (buf !=
'r') && (buf !=
't') && (buf !=
'u'))) {
249 qjsonDebug() <<
"Just read" << buf;
250 qjsonDebug() <<
"JSonScanner::yylex - error decoding escaped sequence";
254 qCritical() <<
"JSonScanner::yylex - error decoding escaped sequence : io error";
261 else if (isdigit(ch) != 0 && m_quotmarkClosed) {
262 *yylval = QVariant(QString::fromLatin1(QByteArray(&ch,1)));
263 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::DIGIT";
264 return yy::json_parser::token::DIGIT;
266 else if (isalnum(ch) != 0) {
267 *yylval = QVariant(QString(QChar::fromLatin1(ch)));
268 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::WORD ("
270 return yy::json_parser::token::STRING;
272 else if (ch ==
':') {
274 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::COLON";
275 return yy::json_parser::token::COLON;
277 else if (ch ==
'"') {
282 if (m_quotmarkCount %2 == 0) {
283 m_quotmarkClosed =
true;
285 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::QUOTMARKCLOSE";
286 return yy::json_parser::token::QUOTMARKCLOSE;
289 m_quotmarkClosed =
false;
290 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::QUOTMARKOPEN";
291 return yy::json_parser::token::QUOTMARKOPEN;
294 else if (ch ==
',') {
295 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::COMMA";
296 return yy::json_parser::token::COMMA;
298 else if (ch ==
'.') {
299 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::DOT";
300 return yy::json_parser::token::DOT;
302 else if (ch ==
'-') {
303 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::MINUS";
304 return yy::json_parser::token::MINUS;
306 else if (ch ==
'[') {
307 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_OPEN";
308 return yy::json_parser::token::SQUARE_BRACKET_OPEN;
310 else if (ch ==
']') {
311 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_CLOSE";
312 return yy::json_parser::token::SQUARE_BRACKET_CLOSE;
314 else if (ch ==
'{') {
315 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_OPEN";
316 return yy::json_parser::token::CURLY_BRACKET_OPEN;
318 else if (ch ==
'}') {
319 qjsonDebug() <<
"JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_CLOSE";
320 return yy::json_parser::token::CURLY_BRACKET_CLOSE;
325 qCritical() <<
"JSonScanner::yylex - unknown char, returning -1";