| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #include <iostream>
- #include "jsonException.hh"
- #include "jsonElement.hh"
- #include "streamConsumer.hh"
- StreamConsumer::StreamConsumer(std::istream &s): stream(s)
- { }
- StreamConsumer::~StreamConsumer()
- {
- if (root)
- delete root;
- }
- StreamConsumer *StreamConsumer::read(std::istream &stream)
- {
- StreamConsumer *inst = new StreamConsumer(stream);
- inst->root = inst->readNext(nullptr);
- return inst;
- }
- JSonElement *StreamConsumer::readNext(JSonContainer *parent)
- {
- std::string buf;
- JSonElement *root = consumeToken(parent, buf);
- if (root == nullptr)
- {
- if (buf == "{")
- {
- return readObject(parent);
- }
- else if (buf == "[")
- {
- return readArray(parent);
- }
- else
- return nullptr;
- }
- return root;
- }
- JSonElement * const StreamConsumer::getRoot() const
- {
- return root;
- }
- JSonObject *StreamConsumer::readObject(JSonContainer *parent)
- {
- JSonElement *keyObj;
- JSonObject *result = nullptr;
- std::string buf;
- do
- {
- keyObj = consumeToken(result, buf);
- if (result == nullptr && keyObj == nullptr && buf == "}")
- return new JSonObject(parent);
- JSonPrimitive<std::string> *key = dynamic_cast<JSonPrimitive<std::string> *>(keyObj);
- if (key == nullptr)
- throw JsonException(stream.tellg());
- if (consumeToken(parent, buf) != nullptr || buf != ":")
- throw JsonException(stream.tellg());
- if (result == nullptr)
- result = new JSonObject(parent);
- else if (result->contains(key->getValue()))
- throw JsonException(stream.tellg()); //Double key
- key->setParent(result);
- JSonElement *child = readNext(result);
- result->push(key->getValue(), child);
- delete keyObj;
- keyObj = consumeToken(result, buf);
- } while (!keyObj && buf != "}");
- return result;
- }
- JSonArray *StreamConsumer::readArray(JSonContainer *parent)
- {
- JSonArray *result = nullptr;
- std::string buf;
- JSonElement *child = consumeToken(parent, buf);
- if (child == nullptr && buf == "]")
- return new JSonArray(parent); //Empty object
- do
- {
- if (child == nullptr)
- throw JsonException(stream.tellg());
- if (result == nullptr)
- result = new JSonArray(parent);
- child->setParent(result);
- result->push_back(child);
- child = consumeToken(result, buf);
- if (child != nullptr)
- throw JsonException(stream.tellg());
- else if (buf == "]")
- break;
- else if (buf != ",")
- throw JsonException(stream.tellg());
- child = consumeToken(result, buf);
- } while (true);
- return result;
- }
- JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &buf)
- {
- bool escaped = false;
- bool inString = false;
- bool inBool = false;
- bool inNumber = false;
- bool numberIsFloat = false;
- while (stream.good())
- {
- char c = stream.get();
- if (inString)
- {
- if (!escaped)
- {
- if (c == '"')
- return new JSonPrimitive<std::string>(parent, buf);
- else if (c == '\\')
- escaped = true;
- else
- buf += c;
- }
- else
- {
- if (c == '\\' || c == '"')
- buf += c;
- else
- throw JsonEscapedException(c, stream.tellg());
- }
- }
- else if (inBool)
- {
- if (c == 'a' || c == 'e' || c == 'l' || c == 'r' || c == 's' || c == 'u')
- buf += c;
- else if (buf == "true")
- {
- stream.unget();
- return new JSonPrimitive<bool>(parent, true);
- }
- else if (buf == "false")
- {
- stream.unget();
- return new JSonPrimitive<bool>(parent, false);
- }
- else if (ignoreChar(c))
- ;
- else
- throw JsonFormatException(c, stream.tellg());
- }
- else if (inNumber)
- {
- if (c >= '0' && c <= '9')
- buf += c;
- else if (c == '.' && !numberIsFloat)
- {
- numberIsFloat = true;
- buf += c;
- }
- else
- {
- stream.unget();
- if (numberIsFloat)
- return new JSonPrimitive<float>(parent, std::stof(buf));
- try
- {
- return new JSonPrimitive<int>(parent, std::stoi(buf));
- }
- catch(std::out_of_range e)
- {
- return new JSonPrimitive<long long>(parent, std::stol(buf));
- }
- }
- }
- else
- {
- //!InString, !inbool
- if (c == '"')
- {
- buf = "";
- inString = true;
- }
- else if (c == 't' || c == 'f')
- {
- buf = c;
- inBool = true;
- }
- else if (c == '{' || c == '[' || c == '}' || c == ']' || c == ':' || c == ',')
- {
- buf = c;
- return nullptr;
- }
- else if ((c >= '0' && c <= '9') || c == '.')
- {
- buf = c;
- inNumber = true;
- }
- else if (!ignoreChar(c))
- throw JsonFormatException(c, stream.tellg());
- }
- }
- buf = "";
- return nullptr;
- }
- bool StreamConsumer::ignoreChar(char c) const noexcept
- {
- return (c <= 32 || c >= 127);
- }
|