Ver código fonte

[add] LinearHistory keep line numbers
[add] line number in error messages
[fix #7] multi-line error messages break col indicator

isundil 9 anos atrás
pai
commit
c15bab4da6

+ 2 - 2
CMakeLists.txt

@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 2.8)
 
-add_executable(jsonstroll src/main.cpp src/jsonContainer.cpp src/params.cpp src/curseOutput.cpp src/outputFlag.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObjectEntry.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
-add_executable(json_test test/src/main.cpp src/jsonContainer.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObjectEntry.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
+add_executable(jsonstroll src/main.cpp src/jsonContainer.cpp src/params.cpp src/curseOutput.cpp src/linearHistory.cpp src/outputFlag.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObjectEntry.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
+add_executable(json_test test/src/main.cpp src/jsonContainer.cpp src/linearHistory.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObjectEntry.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
 add_executable(wrapped_test test/src/wrapped.cpp)
 
 set_property(TARGET jsonstroll PROPERTY RUNTIME_OUTPUT_DIRECTORY bin)

+ 18 - 7
include/jsonException.hh

@@ -2,7 +2,7 @@
 
 #include <exception>
 #include "config.h"
-#include "wrappedBuffer.hpp"
+#include "linearHistory.hh"
 
 class EofException: public std::exception
 { };
@@ -10,39 +10,50 @@ class EofException: public std::exception
 class JsonException: public std::exception
 {
     public:
-        JsonException(const std::string &what, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf);
+        JsonException(const std::string &what, unsigned long long offset, LinearHistory &buf);
 
         std::string getHistory() const;
         const char *what() const noexcept;
 
+        unsigned int currentLine() const;
+
     protected:
         const unsigned long long offset;
-        const WrappedBuffer<char, ERROR_HISTORY_LEN> history;
+        const LinearHistory history;
         const std::string _what;
 };
 
+class JsonHexvalueException: public JsonException
+{
+    public:
+        JsonHexvalueException(const std::string &what, unsigned long long offset, LinearHistory &hist);
+        JsonHexvalueException(const char what, unsigned long long offset, LinearHistory &hist);
+
+        static std::string msg(char c);
+};
+
 class JsonNotJsonException: public JsonException
 {
     public:
-        JsonNotJsonException(unsigned long long offet, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
+        JsonNotJsonException(unsigned long long offet, LinearHistory &h);
 };
 
 class JsonUnexpectedException: public JsonException
 {
     public:
-        JsonUnexpectedException(const char expected, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
+        JsonUnexpectedException(const char expected, unsigned long long offset, LinearHistory &h);
 };
 
 class JsonFormatException: public JsonException
 {
     public:
-        JsonFormatException(unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
+        JsonFormatException(unsigned long long offset, LinearHistory &h);
 };
 
 class JsonEscapedException: public JsonException
 {
     public:
-        JsonEscapedException(char c, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
+        JsonEscapedException(char c, unsigned long long offset, LinearHistory &h);
 
     protected:
         const char c;

+ 2 - 2
include/jsonObject.hh

@@ -25,13 +25,13 @@ class JSonObject: public JSonContainer
     class DoubleKeyException: public JsonException
     {
         public:
-            DoubleKeyException(unsigned long long offset, const std::string &key, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf);
+            DoubleKeyException(unsigned long long offset, const std::string &key, LinearHistory &buf);
     };
 
     class NotAKeyException: public JsonException
     {
         public:
-            NotAKeyException(unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf);
+            NotAKeyException(unsigned long long offset, LinearHistory &buf);
     };
 };
 

+ 21 - 0
include/linearHistory.hh

@@ -0,0 +1,21 @@
+#pragma once
+
+#include "config.h"
+#include "wrappedBuffer.hpp"
+
+class LinearHistory: public WrappedBuffer<char, ERROR_HISTORY_LEN>
+{
+    public:
+        LinearHistory();
+        ~LinearHistory();
+
+        unsigned int currentLine() const;
+
+        void put(char item);
+        void put(char item[], unsigned int count);
+
+    private:
+        bool willReset;
+        unsigned int line;
+};
+

+ 2 - 3
include/streamConsumer.hh

@@ -1,12 +1,11 @@
 #pragma once
 
 #include <istream>
-#include "config.h"
 #include "params.hh"
 #include "jsonObject.hh"
 #include "jsonArray.hh"
 #include "jsonPrimitive.hh"
-#include "wrappedBuffer.hpp"
+#include "linearHistory.hh"
 
 class StreamConsumer
 {
@@ -35,7 +34,7 @@ class StreamConsumer
         JSonElement *root;
         const AParams *params;
 
-        WrappedBuffer<char, ERROR_HISTORY_LEN> history;
+        LinearHistory history;
 
     private:
         static float _stof(const std::string &);

+ 27 - 4
include/wrappedBuffer.hpp

@@ -10,11 +10,20 @@ class WrappedBuffer
         WrappedBuffer();
         virtual ~WrappedBuffer();
 
-        void put(T item);
-        void put(T item[], unsigned int count);
+        virtual void put(T item);
+        virtual void put(T item[], unsigned int count);
         void pop_back();
+        void reset();
 
+        /**
+         * @return total size appended since instanciation or clear()
+        **/
+        unsigned int totalSize() const;
         unsigned int size() const;
+
+        /**
+         * @return Current size (cannot be greater than SIZE
+        **/
         std::basic_string<T> toString() const;
         T* toArray(T arr[SIZE]) const;
 
@@ -22,6 +31,7 @@ class WrappedBuffer
         T buffer[SIZE];
         int curR;
         int curW;
+        unsigned int written;
 };
 
 template<typename T, int SIZE>
@@ -32,9 +42,22 @@ template<typename T, int SIZE>
 WrappedBuffer<T, SIZE>::~WrappedBuffer()
 { }
 
+template<typename T, int SIZE>
+void WrappedBuffer<T, SIZE>::reset()
+{
+    curR = 0;
+    curW = -1;
+    written = 0;
+}
+
+template<typename T, int SIZE>
+unsigned int WrappedBuffer<T, SIZE>::totalSize() const
+{ return written; }
+
 template<typename T, int SIZE>
 void WrappedBuffer<T, SIZE>::put(T item)
 {
+    written++;
     if (curW +1 == SIZE)
     {
         curR = 1;
@@ -64,6 +87,7 @@ void WrappedBuffer<T, SIZE>::put(T items[], unsigned int count)
 
     if (!count)
         return;
+    written += count;
     while (count > SIZE)
     {
         count -= SIZE;
@@ -94,6 +118,7 @@ template<typename T, int SIZE>
 void WrappedBuffer<T, SIZE>::pop_back()
 {
     unsigned int oldSize = size();
+    written--;
     if (oldSize == 0)
         return;
     else if (oldSize == 1)
@@ -115,8 +140,6 @@ unsigned int WrappedBuffer<T, SIZE>::size() const
     return (curR > curW) ? (SIZE - curR + curW +1) : (curW - curR +1);
 }
 
-#include <iostream>
-
 template<typename T, int SIZE>
 std::basic_string<T> WrappedBuffer<T, SIZE>::toString() const
 {

+ 22 - 10
src/jsonException.cpp

@@ -1,31 +1,43 @@
 #include <string>
 #include "jsonException.hh"
 
-JsonException::JsonException(const std::string &wh, unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h): offset(pos), history(h), _what(wh)
+JsonException::JsonException(const std::string &wh, unsigned long long pos, LinearHistory &h): offset(pos), history(h), _what(wh)
 { }
 
-JsonFormatException::JsonFormatException(unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h):
+JsonHexvalueException::JsonHexvalueException(const std::string &what, unsigned long long o, LinearHistory &h): JsonException(what, o, h)
+{ }
+
+JsonHexvalueException::JsonHexvalueException(char c, unsigned long long o, LinearHistory &h): JsonException(JsonHexvalueException::msg(c), o, h)
+{ }
+
+JsonFormatException::JsonFormatException(unsigned long long pos, LinearHistory &h):
     JsonException("invalid value", pos, h)
 { }
 
-JsonNotJsonException::JsonNotJsonException(unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h):
+JsonNotJsonException::JsonNotJsonException(unsigned long long pos, LinearHistory &h):
     JsonException("expected json entry, got token", pos, h)
 { }
 
-JsonEscapedException::JsonEscapedException(char ch, unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h):
+JsonEscapedException::JsonEscapedException(char ch, unsigned long long pos, LinearHistory &h):
     JsonException("unexpected escaped char " +c, pos, h), c(ch)
 { }
 
-JsonUnexpectedException::JsonUnexpectedException(const char expected, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h): JsonException("expected " +expected, offset, h)
+JsonUnexpectedException::JsonUnexpectedException(const char expected, unsigned long long offset, LinearHistory &h): JsonException("expected " +expected, offset, h)
 { }
 
-std::string JsonException::getHistory() const
+std::string JsonHexvalueException::msg(char c)
 {
-    return history.toString();
+    std::string what = "invalid hex value '";
+    what += c + '\'';
+    return what;
 }
 
+unsigned int JsonException::currentLine() const
+{ return history.currentLine(); }
+
+std::string JsonException::getHistory() const
+{ return history.toString(); }
+
 const char *JsonException::what() const noexcept
-{
-    return _what.c_str();
-}
+{ return _what.c_str(); }
 

+ 2 - 2
src/jsonObject.cpp

@@ -62,12 +62,12 @@ std::string JSonObject::stringify() const
     return "{ }";
 }
 
-JSonObject::DoubleKeyException::DoubleKeyException(unsigned long long pos, const std::string &key, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf):
+JSonObject::DoubleKeyException::DoubleKeyException(unsigned long long pos, const std::string &key, LinearHistory &buf):
     JsonException("Unexpected double key " +key +" for object", pos, buf)
 {
 }
 
-JSonObject::NotAKeyException::NotAKeyException(unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf):
+JSonObject::NotAKeyException::NotAKeyException(unsigned long long pos, LinearHistory &buf):
     JsonException("expected string key for object", pos, buf)
 { }
 

+ 30 - 0
src/linearHistory.cpp

@@ -0,0 +1,30 @@
+#include "linearHistory.hh"
+
+LinearHistory::LinearHistory(): willReset(false), line(1)
+{ }
+
+LinearHistory::~LinearHistory()
+{ }
+
+unsigned int LinearHistory::currentLine() const
+{ return line; }
+
+void LinearHistory::put(char item)
+{
+    if (willReset)
+    {
+        reset();
+        line++;
+        willReset = false;
+    }
+    if (item == '\n')
+        willReset = true;
+    else
+        WrappedBuffer<char, ERROR_HISTORY_LEN>::put(item);
+}
+
+void LinearHistory::put(char items[], unsigned int count)
+{
+    WrappedBuffer<char, ERROR_HISTORY_LEN>::put(items, count);
+}
+

+ 1 - 1
src/main.cpp

@@ -29,7 +29,7 @@ void run(Params *params)
     }
     catch (JsonException &e)
     {
-        std::cerr << params->getProgName() << ": [" << typeid(e).name() << "] ("  << e.what() << ") error while reading" << std::endl;
+        std::cerr << params->getProgName() << ": [" << typeid(e).name() << "] at line " << e.currentLine() << " ("  << e.what() << ") error while reading" << std::endl;
         std::string buffer = e.getHistory();
         std::cerr << buffer << std::endl << std::string(buffer.size() -1, '~') << '^' << std::endl;
         return;

+ 8 - 2
src/streamConsumer.cpp

@@ -159,7 +159,13 @@ JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &bu
                         history.put(unicodeBuf, gcount);
                         if (gcount != 4)
                             break;
-                        appendUnicode(unicodeBuf, buf);
+                        try {
+                            appendUnicode(unicodeBuf, buf);
+                        }
+                        catch (std::invalid_argument &e)
+                        {
+                            throw JsonHexvalueException(e.what(), stream.tellg(), history);
+                        }
                         escaped = false;
                     }
                 }
@@ -259,7 +265,7 @@ static unsigned char hexbyte(const char c)
         return c - 'A' + 10;
     if (c >= 'a' && c <= 'f')
         return c - 'a' + 10;
-    return 0;
+    throw std::invalid_argument(JsonHexvalueException::msg(c));
 }
 
 static unsigned char hexbyte(const char str[2])