//========================================================================== // VALUEITERATOR.H - part of // OMNeT++/OMNEST // Discrete System Simulation in C++ // // Author: Andras Varga // //========================================================================== /*--------------------------------------------------------------* Copyright (C) 1992-2017 Andras Varga Copyright (C) 2006-2017 OpenSim Ltd. This file is distributed WITHOUT ANY WARRANTY. See the file `license' for details on this and other legal matters. *--------------------------------------------------------------*/ #ifndef __OMNETPP_ENVIR_VALUEITERATOR_H #define __OMNETPP_ENVIR_VALUEITERATOR_H #include #include #include #include "common/expression.h" #include "envirdefs.h" namespace omnetpp { namespace envir { /** * Support class for parsing simulation scenarios. Given a sequence of * values in string form, this class can enumerate those values. * Generating numeric sequences with a simple from-to-step syntax * is also supported. * * Syntax: items separated by comma. Quotation marks are respected * (that is, commas are ignored within string constants). * If an item has the format expr..expr or * expr..expr step expr, it generates * a numeric sequence. * * Items may contain variable references, in the $var or ${var} syntax. * For single items, variables will be textually substituted; for numeric * sequences (from/to/step), variables will be textually substituted, then * the from/to/step expressions will be evaluated using the Expression class * in src/common. * * Usage: the string should be passed to the constructor or the parse() method. * Before iteration, the restart() method MUST be called, with a map of variables * to be substituted as argument. Then iteration may begin, using get() and * operator++. Iteration may be restarted any number of times. */ class ENVIR_API ValueIterator { public: typedef omnetpp::common::Expression Expression; typedef std::map VariableMap; // maps variable names to their iterators /** * Represents an element in the iteration string (a single item, or one of * the from/to/step expressions); stores both the original ("raw") string, * and the result after variable substitution and optional evaluation. * Currently also used for the constraint= expression. */ class Expr { private: std::string raw; // original text of item; may contain variable references Expression::Value value; // value after variable substitution and optional evalutation; filled in by substituteVariables() and evaluate() void checkType(char expected) const; public: Expr() {} Expr(const char *text) : raw(text) {} void collectVariablesInto(std::set& vars) const; void substituteVariables(const VariableMap& map); // raw -> value void evaluate(); // value -> value double dblValue() const { checkType('D'); return value.dbl; } bool boolValue() const { checkType('B'); return value.bl; } std::string strValue() const { checkType('S'); return value.s; } }; private: /** * The parsed iteration spec; it can be * - constant text * - '..' where and are either contants or numeric expressions * - '.. step ' where , and are either constants or numeric expressions */ struct Item { enum Type { TEXT, FROM_TO_STEP}; Type type; Expr text; Expr from, to, step; Item() : type(TEXT) {} void parse(const char *s); void collectVariablesInto(std::set& result) const; void restart(const VariableMap& map); int getNumValues() const; std::string getValueAsString(int k) const; }; std::vector items; // iteration state int itemIndex; // index into items[] int k; // index within the item // counts how many times op++() was invoked on the iterator int pos; // names of variables referenced in this value iterator std::set referredVariables; public: /** * Default constructor. */ ValueIterator(); /** * Constructor; the iteration is parsed from the string argument. */ ValueIterator(const char *s); /** * Destructor. */ ~ValueIterator(); /** * Parses the given string. */ void parse(const char *s); /** * Returns the variable names referenced in the iteration string, e.g. "x", "a", "b" * in "${1,5,$x+2,$a..$b}". Used by Scenario to calculate iteration variable ordering. * (Referenced variables should become outer loops to this one.) */ std::set getReferencedVariableNames() const { return referredVariables; } /** * Stateless access: returns the length of the sequence, with numeric * ranges expanded. Does not change the state of the iterator. * * Note: restart() MUST BE CALLED before iteration! */ int length() const; /** * Stateless access: returns the ith value in the sequence. * If i<0 or i>=length(), an error is thrown. * Does not change the state of the iterator. * * Note: restart() MUST BE CALLED before iteration! */ std::string get(int k) const; /** * Restarts the iteration. It substitutes variables in the expression * defining this iterator and re-evaluates the , , expressions. */ void restart(const VariableMap& vars); /** * Moves the iterator to the next element. * * Note: restart() MUST BE CALLED before iteration! */ void operator++(int); /** * Returns the current element. Result is undefined when the iteration is * over (end() returns true). * * Note: restart() MUST BE CALLED before iteration! */ std::string get() const; /** * Same as get(). */ std::string operator()() const {return get();} /** * Returns how many times operator++ was invoked on the iterator * since construction or the last restart() call. */ int getPosition() const {return pos;} /** * Restart the iteration, and go to the ith position in the sequence. * Returns false if there is no ith element. The vars argument will * be passed to restart(). */ bool gotoPosition(int pos, const VariableMap& vars); /** * Returns true when the iteration is over, that is, after invoking * operator++() after the last element. */ bool end() const; /** * For debugging purposes */ void dump() const; }; } // namespace envir } // namespace omnetpp #endif