diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/parser/ParserStack.cpp | 46 | ||||
| -rw-r--r-- | src/core/parser/ParserStack.hpp | 57 | 
2 files changed, 61 insertions, 42 deletions
diff --git a/src/core/parser/ParserStack.cpp b/src/core/parser/ParserStack.cpp index 7bc7af3..dca7f35 100644 --- a/src/core/parser/ParserStack.cpp +++ b/src/core/parser/ParserStack.cpp @@ -20,44 +20,38 @@  #include "ParserStack.hpp" +#include <core/Utils.hpp>  #include <core/Exceptions.hpp>  namespace ousia {  namespace parser { +/* Class Handler */ + +void Handler::data(const std::string &data, int field) +{ +	for (auto &c : data) { +		if (!Utils::isWhitespace(c)) { +			throw LoggableException{"No data allowed here."}; +		} +	} +} +  /* Class HandlerDescriptor */  HandlerInstance HandlerDescriptor::create(const ParserContext &ctx,                                            std::string name, State parentState, -                                          bool isChild, char **attrs) const +                                          bool isChild, +                                          const Variant &args) const  {  	Handler *h = ctor(ctx, name, targetState, parentState, isChild); -	h->start(attrs); +	h->start(args);  	return HandlerInstance(h, this);  }  /* Class ParserStack */  /** - * Function used internally to turn the elements of a collection into a string - * separated by the given delimiter. - */ -template <class T> -static std::string join(T es, const std::string &delim) -{ -	std::stringstream res; -	bool first = true; -	for (auto &e : es) { -		if (!first) { -			res << delim; -		} -		res << e; -		first = false; -	} -	return res.str(); -} - -/**   * Returns an Exception that should be thrown when a currently invalid command   * is thrown.   */ @@ -73,7 +67,7 @@ static LoggableException invalidCommand(const std::string &name,  		    std::string{"Expected "} +  		    (expected.size() == 1 ? std::string{"\""}  		                          : std::string{"one of \""}) + -		    join(expected, "\", \"") + std::string{"\", but got \""} + name + +		    Utils::join(expected, "\", \"") + std::string{"\", but got \""} + name +  		    std::string{"\""}};  	}  } @@ -89,7 +83,7 @@ std::set<std::string> ParserStack::expectedCommands(State state)  	return res;  } -void ParserStack::start(std::string name, char **attrs) +void ParserStack::start(std::string name, const Variant &args)  {  	// Fetch the current handler and the current state  	const HandlerInstance *h = stack.empty() ? nullptr : &stack.top(); @@ -117,7 +111,7 @@ void ParserStack::start(std::string name, char **attrs)  	}  	// Instantiate the handler and call its start function -	stack.emplace(descr->create(ctx, name, curState, isChild, attrs)); +	stack.emplace(descr->create(ctx, name, curState, isChild, args));  }  void ParserStack::end() @@ -141,7 +135,7 @@ void ParserStack::end()  	}  } -void ParserStack::data(const char *data, int len) +void ParserStack::data(const std::string &data, int field)  {  	// Check whether there is any command the data can be sent to  	if (stack.empty()) { @@ -149,7 +143,7 @@ void ParserStack::data(const char *data, int len)  	}  	// Pass the data to the current Handler instance -	stack.top().handler->data(data, len); +	stack.top().handler->data(data, field);  }  }  } diff --git a/src/core/parser/ParserStack.hpp b/src/core/parser/ParserStack.hpp index 18fc8d9..c5ed4e4 100644 --- a/src/core/parser/ParserStack.hpp +++ b/src/core/parser/ParserStack.hpp @@ -37,6 +37,8 @@  #include <stack>  #include <vector> +#include <core/variant/Variant.hpp> +  #include "Parser.hpp"  namespace ousia { @@ -125,10 +127,9 @@ public:  	 * Called when the command that was specified in the constructor is  	 * instanciated.  	 * -	 * @param attrs contains the attributes that were specified for the command. -	 * TODO: Replace with StructInstance! +	 * @param args is a map from strings to variants (argument name and value).  	 */ -	virtual void start(char **attrs) = 0; +	virtual void start(const Variant &args) = 0;  	/**  	 * Called whenever the command for which this handler @@ -137,15 +138,15 @@ public:  	/**  	 * Called whenever raw data (int the form of a string) is available for the -	 * Handler instance. -	 * -	 * TODO: Replace with std::string? -	 * TODO: Per default: Allow no data except for whitespace characters! +	 * Handler instance. In the default handler an exception is raised if the +	 * received data contains non-whitespace characters.  	 *  	 * @param data is a pointer at the character data that is available for the  	 * Handler instance. +	 * @param field is the field number (the interpretation of this value +	 * depends on the format that is being parsed).  	 */ -	virtual void data(const char *data, int len){}; +	virtual void data(const std::string &data, int field);  	/**  	 * Called whenever a direct child element was created and has ended. @@ -225,7 +226,8 @@ struct HandlerDescriptor {  	 * HandlerDescriptor and calls its start function.  	 */  	HandlerInstance create(const ParserContext &ctx, std::string name, -	                       State parentState, bool isChild, char **attrs) const; +	                       State parentState, bool isChild, +	                       const Variant &args) const;  };  /** @@ -240,6 +242,11 @@ private:  	const ParserContext &ctx;  	/** +	 * User specified data that will be passed to all handlers. +	 */ +	void *userData; + +	/**  	 * Map containing all registered command names and the corresponding  	 * handler  	 * descriptor. @@ -278,7 +285,8 @@ public:  	 * @return the state of the currently active Handler instance or STATE_NONE  	 * if no handler is on the stack.  	 */ -	State currentState() { +	State currentState() +	{  		return stack.empty() ? STATE_NONE : stack.top().handler->state;  	} @@ -288,7 +296,8 @@ public:  	 * @return the name of the command currently being handled by the active  	 * Handler instance or an empty string if no handler is currently active.  	 */ -	std::string currentName() { +	std::string currentName() +	{  		return stack.empty() ? std::string{} : stack.top().handler->name;  	} @@ -297,17 +306,33 @@ public:  	 *  	 * @return true if the handler allows arbitrary children, false otherwise.  	 */ -	bool currentArbitraryChildren() { +	bool currentArbitraryChildren() +	{  		return stack.empty() ? false : stack.top().descr->arbitraryChildren;  	} -	// TODO: Change signature -	void start(std::string name, char **attrs); +	/** +	 * Function that should be called whenever a new command starts. +	 * +	 * @param name is the name of the command. +	 * @param args is a map from strings to variants (argument name and value). +	 */ +	void start(std::string name, const Variant &args); +	/** +	 * Function called whenever a command ends. +	 */  	void end(); -	// TODO: Change signature -	void data(const char *data, int len); +	/** +	 * Function that should be called whenever data is available for the +	 * command. +	 * +	 * @param data is the data that should be passed to the handler. +	 * @param field is the field number (the interpretation of this value +	 * depends on the format that is being parsed). +	 */ +	void data(const std::string &data, int field = 0);  };  }  }  | 
