diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-15 00:27:11 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-15 00:27:11 +0100 |
commit | 253492406f04657fe71e6c0c6603496241280478 (patch) | |
tree | 5a9c1b785a5559025ff7d26bf9ed880ce98ff0ce /src/core/common | |
parent | 551b7be64f207845cb05b8ec593f9bf2d7f0c940 (diff) | |
parent | b708dd4cce828c1089a18fefcc22804f7cdad908 (diff) |
Merge branch 'master' into astoecke_parser_stack_new
Conflicts:
application/CMakeLists.txt
application/src/core/parser/stack/DocumentHandler.hpp
application/src/core/parser/stack/DomainHandler.hpp
application/src/core/parser/stack/ImportIncludeHandler.hpp
Diffstat (limited to 'src/core/common')
-rw-r--r-- | src/core/common/CharReader.cpp | 23 | ||||
-rw-r--r-- | src/core/common/CharReader.hpp | 9 | ||||
-rw-r--r-- | src/core/common/Exceptions.hpp | 2 | ||||
-rw-r--r-- | src/core/common/Logger.hpp | 14 | ||||
-rw-r--r-- | src/core/common/VariantReader.cpp | 132 | ||||
-rw-r--r-- | src/core/common/VariantReader.hpp | 49 |
6 files changed, 200 insertions, 29 deletions
diff --git a/src/core/common/CharReader.cpp b/src/core/common/CharReader.cpp index 3e95280..2a4383f 100644 --- a/src/core/common/CharReader.cpp +++ b/src/core/common/CharReader.cpp @@ -336,7 +336,7 @@ size_t Buffer::seekCursor(CursorId cursor, size_t offs) const ssize_t relativeOffs = offs - currentOffs; // Perform the actual seeking, move the peek cursor to the read cursor - const ssize_t reachedOffs = currentOffs + moveCursor(cursor, relativeOffs); + const ssize_t reachedOffs = currentOffs + moveCursor(cursor, relativeOffs); // Clamp to values larger or equal to zero return reachedOffs < 0 ? 0 : reachedOffs; @@ -402,6 +402,18 @@ CharReader::CharReader(std::shared_ptr<Buffer> buffer, SourceId sourceId, { } +CharReader::CharReader(CharReader &&other) noexcept + : buffer(std::move(other.buffer)), + readCursor(other.readCursor), + peekCursor(other.peekCursor), + coherent(other.coherent), + sourceId(other.sourceId), + offs(other.offs) +{ + other.readCursor = 0; + other.peekCursor = 0; +} + CharReader::CharReader(const std::string &str, SourceId sourceId, size_t offs) : CharReader(std::shared_ptr<Buffer>{new Buffer{str}}, sourceId, offs) { @@ -468,10 +480,7 @@ bool CharReader::read(char &c) return res; } -bool CharReader::fetch(char &c) -{ - return buffer->fetch(readCursor, c); -} +bool CharReader::fetch(char &c) { return buffer->fetch(readCursor, c); } bool CharReader::fetchPeek(char &c) { @@ -541,7 +550,7 @@ size_t CharReader::readRaw(char *buf, size_t size) size_t CharReader::seek(size_t requestedOffset) { - const size_t res = buffer->seekCursor(readCursor, requestedOffset); + const size_t res = buffer->seekCursor(readCursor, requestedOffset); buffer->copyCursor(readCursor, peekCursor); coherent = true; return res; @@ -549,7 +558,7 @@ size_t CharReader::seek(size_t requestedOffset) size_t CharReader::seekPeekCursor(size_t requestedOffset) { - const size_t res = buffer->seekCursor(peekCursor, requestedOffset); + const size_t res = buffer->seekCursor(peekCursor, requestedOffset); coherent = (res == getOffset()); return res; } diff --git a/src/core/common/CharReader.hpp b/src/core/common/CharReader.hpp index a90d337..0a220ee 100644 --- a/src/core/common/CharReader.hpp +++ b/src/core/common/CharReader.hpp @@ -462,10 +462,15 @@ public: ~CharReader(); // No copy - CharReader(const Buffer &) = delete; + CharReader(const CharReader &) = delete; // No assign - CharReader &operator=(const Buffer &) = delete; + CharReader &operator=(const CharReader &) = delete; + + /** + * Move constructor. + */ + CharReader(CharReader &&) noexcept; /** * Peeks a single character. If called multiple times, returns the diff --git a/src/core/common/Exceptions.hpp b/src/core/common/Exceptions.hpp index b63c32a..337480a 100644 --- a/src/core/common/Exceptions.hpp +++ b/src/core/common/Exceptions.hpp @@ -109,7 +109,7 @@ public: * @param loc is a reference to a variable with location data. */ template <class LocationType> - LoggableException(std::string msg, LocationType loc) + LoggableException(std::string msg, const LocationType &loc) : LoggableException(std::move(msg), SourceLocation::location(loc)) { } diff --git a/src/core/common/Logger.hpp b/src/core/common/Logger.hpp index c8b324c..d2d8e80 100644 --- a/src/core/common/Logger.hpp +++ b/src/core/common/Logger.hpp @@ -280,7 +280,7 @@ public: * @param mode specifies how the message should be displayed. */ template <class LocationType> - void log(const LoggableException &ex, LocationType loc, + void log(const LoggableException &ex, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { log(ex, SourceLocation::location(loc), mode); @@ -297,7 +297,7 @@ public: * @param mode specifies how the message should be displayed. */ template <class LocationType> - void log(Severity severity, const std::string &msg, LocationType loc, + void log(Severity severity, const std::string &msg, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { log(severity, msg, SourceLocation::location(loc), mode); @@ -328,7 +328,7 @@ public: * information. */ template <class LocationType> - void debug(const std::string &msg, LocationType loc, + void debug(const std::string &msg, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { #ifndef NDEBUG @@ -357,7 +357,7 @@ public: * information. */ template <class LocationType> - void note(const std::string &msg, LocationType loc, + void note(const std::string &msg, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { log(Severity::NOTE, msg, loc, mode); @@ -384,7 +384,7 @@ public: * information. */ template <class LocationType> - void warning(const std::string &msg, LocationType loc, + void warning(const std::string &msg, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { log(Severity::WARNING, msg, SourceLocation::location(loc), mode); @@ -411,7 +411,7 @@ public: * information. */ template <class LocationType> - void error(const std::string &msg, LocationType loc, + void error(const std::string &msg, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { log(Severity::ERROR, msg, SourceLocation::location(loc), mode); @@ -438,7 +438,7 @@ public: * information. */ template <class LocationType> - void fatalError(const std::string &msg, LocationType loc, + void fatalError(const std::string &msg, const LocationType &loc, MessageMode mode = MessageMode::DEFAULT) { log(Severity::FATAL_ERROR, msg, SourceLocation::location(loc), mode); diff --git a/src/core/common/VariantReader.cpp b/src/core/common/VariantReader.cpp index ef71740..3f02226 100644 --- a/src/core/common/VariantReader.cpp +++ b/src/core/common/VariantReader.cpp @@ -16,9 +16,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <iostream> - #include <cmath> +#include <limits> #include <sstream> #include <utf8.h> @@ -485,6 +484,36 @@ std::pair<bool, std::string> VariantReader::parseUnescapedString( return std::make_pair(true, res.str()); } +std::pair<bool, Variant::boolType> VariantReader::parseBool(CharReader &reader, + Logger &logger) +{ + // first we consume all whitespaces. + reader.consumePeek(); + reader.consumeWhitespace(); + // then we try to find the words "true" or "false". + + bool val = false; + CharReaderFork readerFork = reader.fork(); + LoggerFork loggerFork = logger.fork(); + auto res = parseToken(readerFork, loggerFork, {}); + if (res.first) { + bool valid = false; + if (res.second == "true") { + val = true; + valid = true; + } else if (res.second == "false") { + val = false; + valid = true; + } + if (valid) { + readerFork.commit(); + loggerFork.commit(); + return std::make_pair(true, val); + } + } + return std::make_pair(false, val); +} + std::pair<bool, int64_t> VariantReader::parseInteger( CharReader &reader, Logger &logger, const std::unordered_set<char> &delims) { @@ -715,10 +744,9 @@ std::pair<bool, Variant> VariantReader::parseGenericToken( // Skip all whitespace characters, read a character and abort if at the end reader.consumePeek(); reader.consumeWhitespace(); - if (!reader.peek(c) || delims.count(c)) { + if (!reader.fetch(c) || delims.count(c)) { return error(reader, logger, ERR_UNEXPECTED_END, nullptr); } - reader.resetPeek(); // Fetch the start offset const SourceOffset start = reader.getOffset(); @@ -738,26 +766,31 @@ std::pair<bool, Variant> VariantReader::parseGenericToken( CharReaderFork readerFork = reader.fork(); LoggerFork loggerFork = logger.fork(); if (n.parse(readerFork, loggerFork, delims)) { - readerFork.commit(); - loggerFork.commit(); - Variant v; if (n.isInt()) { + if (n.intValue() < + std::numeric_limits<Variant::intType>::min() || + n.intValue() > + std::numeric_limits<Variant::intType>::max()) { + logger.error("Number exceeds type limits.", reader); + return std::make_pair(false, v); + } v = Variant{static_cast<Variant::intType>(n.intValue())}; } else { v = Variant{n.doubleValue()}; } + readerFork.commit(); + loggerFork.commit(); v.setLocation({reader.getSourceId(), start, reader.getOffset()}); return std::make_pair(true, v); } - reader.resetPeek(); } // Try to parse a cardinality if (c == '{') { CharReaderFork readerFork = reader.fork(); LoggerFork loggerFork = logger.fork(); - auto res = parseCardinality(readerFork, logger); + auto res = parseCardinality(readerFork, loggerFork); if (res.first) { readerFork.commit(); loggerFork.commit(); @@ -765,7 +798,6 @@ std::pair<bool, Variant> VariantReader::parseGenericToken( v.setLocation({reader.getSourceId(), start, reader.getOffset()}); return std::make_pair(true, v); } - reader.resetPeek(); } // Try to parse an object @@ -835,5 +867,85 @@ std::pair<bool, Variant> VariantReader::parseGenericString( v.setLocation({sourceId, offs, offs + str.size()}); return std::make_pair(true, v); } + +std::pair<bool, Variant> VariantReader::parseTyped( + VariantType type, CharReader &reader, Logger &logger, + const std::unordered_set<char> &delims) +{ + switch (type) { + case VariantType::BOOL: { + auto res = parseBool(reader, logger); + return std::make_pair(res.first, Variant{res.second}); + } + case VariantType::INT: { + auto res = parseInteger(reader, logger, delims); + if (res.second < std::numeric_limits<Variant::intType>::min() || + res.second > std::numeric_limits<Variant::intType>::max()) { + logger.error("Number exceeds type limits.", reader); + return std::make_pair(false, Variant{}); + } + return std::make_pair( + res.first, Variant{static_cast<Variant::intType>(res.second)}); + } + case VariantType::DOUBLE: { + auto res = parseDouble(reader, logger, delims); + return std::make_pair(res.first, Variant{res.second}); + } + case VariantType::STRING: { + auto res = parseString(reader, logger, delims); + return std::make_pair(res.first, Variant::fromString(res.second)); + } + case VariantType::ARRAY: { + char delim = 0; + if (delims.size() == 1) { + delim = *delims.begin(); + } + auto res = parseArray(reader, logger, delim); + return std::make_pair(res.first, Variant{res.second}); + } + + case VariantType::MAP: + case VariantType::OBJECT: { + char delim = 0; + if (delims.size() == 1) { + delim = *delims.begin(); + } + auto res = parseObject(reader, logger, delim); + return std::make_pair(res.first, Variant{res.second}); + } + case VariantType::CARDINALITY: { + auto res = parseCardinality(reader, logger); + return std::make_pair(res.first, Variant{res.second}); + } + default: + break; + } + + return std::make_pair(false, Variant{}); +} + +std::pair<bool, Variant> VariantReader::parseTyped(VariantType type, + const std::string &str, + Logger &logger, + SourceId sourceId, + size_t offs) +{ + // create a char reader and forward the method. + CharReader reader{str, sourceId, offs}; + LoggerFork loggerFork = logger.fork(); + std::pair<bool, Variant> res = + parseTyped(type, reader, loggerFork, std::unordered_set<char>{}); + + // If all content could be parsed, commit the result. + if (reader.atEnd()) { + loggerFork.commit(); + return res; + } + + // otherwise do not. + logger.error("Not all input could be processed", + {sourceId, offs, offs + str.size()}); + return std::make_pair(false, Variant{}); +} } diff --git a/src/core/common/VariantReader.hpp b/src/core/common/VariantReader.hpp index 6b157d8..1232f6e 100644 --- a/src/core/common/VariantReader.hpp +++ b/src/core/common/VariantReader.hpp @@ -133,6 +133,19 @@ public: const std::unordered_set<char> &delims); /** + * Parses a bool from the given CharReader instance (the strings "true" or + * "false"). + * + * @param reader is a reference to the CharReader instance which is + * the source for the character data. The reader will be positioned after + * the bool. + * @param logger is the logger instance that should be used to log error + * messages and warnings. + */ + static std::pair<bool, Variant::boolType> parseBool(CharReader &reader, + Logger &logger); + + /** * Parses an integer from the given CharReader instance until one of the * given delimiter characters is reached. * @@ -169,7 +182,7 @@ public: * * @param reader is a reference to the CharReader instance which is * the source for the character data. The reader will be positioned after - * the number or at the terminating delimiting character. + * the array or at the terminating delimiting character. * @param logger is the logger instance that should be used to log error * messages and warnings. * @param delim is the terminating character. If nonzero, the parse function @@ -185,7 +198,7 @@ public: * * @param reader is a reference to the CharReader instance which is * the source for the character data. The reader will be positioned after - * the number or at the terminating delimiting character. + * the object or at the terminating delimiting character. * @param logger is the logger instance that should be used to log error * messages and warnings. * @param delim is the terminating character. If nonzero, the parse function @@ -293,6 +306,38 @@ public: static std::pair<bool, Variant> parseGenericString( const std::string &str, Logger &logger, SourceId sourceId = InvalidSourceId, size_t offs = 0); + + /** + * Tries to parse an instance of the given type from the given stream. The + * called method is one of the parse methods defined here and adheres to the + * specifications defined there. + * + * @param type is the VariantType for which an instance shall be parsed. + * @param reader is a reference to the CharReader instance which is + * the source for the character data. The reader will be positioned + * at the end of the type instance (or the delimiting character). + * @param delims is a set of characters which will terminate the typed + * instance if the according parser uses delimiting characters. + * These characters are not included in the result. May not be nullptr. + */ + static std::pair<bool, Variant> parseTyped( + VariantType type, CharReader &reader, Logger &logger, + const std::unordered_set<char> &delims = {}); + /** + * Tries to parse an instance of the given type from the given string. The + * called method is one of the parse methods defined here and adheres to the + * specifications defined there. + * + * @param type is the VariantType for which an instance shall be parsed. + * @param str is the string from which the value should be read. + * @param sourceId is an optional descriptor of the source file from which + * the element is being read. + * @param offs is the by offset in the source file at which the string + * starts. + */ + static std::pair<bool, Variant> parseTyped( + VariantType type, const std::string &str, Logger &logger, + SourceId sourceId = InvalidSourceId, size_t offs = 0); }; } |