]> git.cworth.org Git - apitrace/blobdiff - thirdparty/qjson/json_scanner.cpp
Update bundled QJson
[apitrace] / thirdparty / qjson / json_scanner.cpp
index 7f7b88fa0a74fe75c41a3af29d5cfb221e2517f1..de0ddc23c53c94cfd1122c8f7248b5a30b0dedb3 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ * 
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * You should have received a copy of the GNU Lesser General Public License
  * along with this library; see the file COPYING.LIB.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
@@ -38,12 +38,17 @@ bool ishexnstring(const QString& string) {
 }
 
 JSonScanner::JSonScanner(QIODevice* io)
-  : m_io (io)
+  : m_allowSpecialNumbers(false),
+    m_io (io)
 {
   m_quotmarkClosed = true;
   m_quotmarkCount = 0;
 }
 
+void JSonScanner::allowSpecialNumbers(bool allow) {
+  m_allowSpecialNumbers = allow;
+}
+
 static QString unescape( const QByteArray& ba, bool* ok ) {
   assert( ok );
   *ok = false;
@@ -125,7 +130,7 @@ static QString unescape( const QByteArray& ba, bool* ok ) {
 int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
 {
   char ch;
-  
+
   if (!m_io->isOpen()) {
     qCritical() << "JSonScanner::yylex - io device is not open";
     return -1;
@@ -148,32 +153,34 @@ int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
     }
 
     qjsonDebug() << "JSonScanner::yylex - got |" << ch << "|";
-    
     yylloc->columns();
-    
+
     if (ch == '\n' || ch == '\r')
       yylloc->lines();
-      
   } while (m_quotmarkClosed && (isspace(ch) != 0));
 
-  if (m_quotmarkClosed && ((ch == 't') || (ch == 'T')
-      || (ch == 'n') || (ch == 'N'))) {
-    // check true & null value
+  if (m_quotmarkClosed && ((ch == 't') || (ch == 'T'))) {
     const QByteArray buf = m_io->peek(3).toLower();
+    if (buf == "rue") {
+      m_io->read (3);
+      yylloc->columns(3);
+      qjsonDebug() << "JSonScanner::yylex - TRUE_VAL";
+      return yy::json_parser::token::TRUE_VAL;
+    }
+  }
+  else if (m_quotmarkClosed && ((ch == 'n') || (ch == 'N'))) {
+    const QByteArray buf = m_io->peek(3).toLower();
+    if (buf == "ull") {
+      m_io->read (3);
+      yylloc->columns(3);
+      qjsonDebug() << "JSonScanner::yylex - NULL_VAL";
+      return yy::json_parser::token::NULL_VAL;
+    } else if (buf.startsWith("an") && m_allowSpecialNumbers) {
+      m_io->read(2);
+      yylloc->columns(2);
+      qjsonDebug() << "JSonScanner::yylex - NAN_VAL";
+      return yy::json_parser::token::NAN_VAL;
 
-    if (buf.length() == 3) {
-      if (buf == "rue") {
-        m_io->read (3);
-        yylloc->columns(3);
-        qjsonDebug() << "JSonScanner::yylex - TRUE_VAL";
-        return yy::json_parser::token::TRUE_VAL;
-      }
-      else if (buf == "ull") {
-        m_io->read (3);
-        yylloc->columns(3);
-        qjsonDebug() << "JSonScanner::yylex - NULL_VAL";
-        return yy::json_parser::token::NULL_VAL;
-      }
     }
   }
   else if (m_quotmarkClosed && ((ch == 'f') || (ch == 'F'))) {
@@ -193,14 +200,24 @@ int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
     const QByteArray buf = m_io->peek(1);
     if (!buf.isEmpty()) {
       if ((buf[0] == '+' ) || (buf[0] == '-' )) {
-        ret += m_io->read (1);  
+        ret += m_io->read (1);
         yylloc->columns();
       }
     }
     *yylval = QVariant(QString::fromUtf8(ret));
     return yy::json_parser::token::E;
   }
-  
+  else if (m_allowSpecialNumbers && m_quotmarkClosed && ((ch == 'I') || (ch == 'i'))) {
+    QByteArray ret(1, ch);
+    const QByteArray buf = m_io->peek(7);
+    if (buf == "nfinity") {
+      m_io->read(7);
+      yylloc->columns(7);
+      qjsonDebug() << "JSonScanner::yylex - INFINITY_VAL";
+      return yy::json_parser::token::INFINITY_VAL;
+    }
+  }
+
   if (ch != '"' && !m_quotmarkClosed) {
     // we're inside a " " block
     QByteArray raw;
@@ -259,7 +276,38 @@ int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
     }
   }
   else if (isdigit(ch) != 0 && m_quotmarkClosed) {
-    *yylval = QVariant(QString::fromLatin1(QByteArray(&ch,1)));
+    bool ok;
+    QByteArray numArray = QByteArray::fromRawData( &ch, 1 * sizeof(char) );
+    qulonglong number = numArray.toULongLong(&ok);
+    if (!ok) {
+      //This shouldn't happen
+      qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1";
+      return -1;
+    }
+    if (number == 0) {
+      // we have to return immediately otherwise numbers like
+      // 2.04 will be converted to 2.4
+      *yylval = QVariant(number);
+      qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT";
+      return yy::json_parser::token::DIGIT;
+    }
+
+    char nextCh;
+    qint64 ret = m_io->peek(&nextCh, 1);
+    while (ret == 1 && isdigit(nextCh)) {
+      m_io->read(1); //consume
+      yylloc->columns(1);
+      numArray = QByteArray::fromRawData( &nextCh, 1 * sizeof(char) );
+      number = number * 10 + numArray.toULongLong(&ok);
+      if (!ok) {
+        //This shouldn't happen
+        qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1";
+        return -1;
+      }
+      ret = m_io->peek(&nextCh, 1);
+    }
+
+    *yylval = QVariant(number);
     qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT";
     return yy::json_parser::token::DIGIT;
   }