#ifndef VMETAWORDMANAGER_H #define VMETAWORDMANAGER_H #include #include #include #include #include #include #include enum class MetaWordType { // Definition is plain text. Simple = 0, // Definition is a function call to get the value. FunctionBased, // Like FunctionBased, but should re-evaluate the value for each occurence. Dynamic, // Consists of other meta words. Compound, Invalid }; // We call meta word "magic word" in user interaction. struct VMagicWord { QString m_name; QString m_definition; }; class VMetaWordManager; class VMetaWord; typedef std::function MetaWordFunc; // A Meta Word is surrounded by %. // - Use %% for an escaped %; // - Built-in or user-defined; // - A meta word could contain other meta words as definition. class VMetaWord { public: VMetaWord(const VMetaWordManager *p_manager, MetaWordType p_type, const QString &p_word, const QString &p_definition, MetaWordFunc p_function = nullptr, bool p_allowAllSpaces = false); bool isValid() const; QString evaluate() const; MetaWordType getType() const; const QString &getWord() const; const QString &getDefinition() const; const VMetaWordManager *getManager() const; QString toString() const; enum class TokenType { Raw = 0, MetaWord }; struct Token { Token() : m_type(TokenType::Raw) { } Token(VMetaWord::TokenType p_type, const QString &p_value) : m_type(p_type), m_value(p_value) { } QString toString() const { return QString("token %1[%2]").arg(m_type == TokenType::Raw ? "Raw" : "MetaWord") .arg(m_value); } bool isRaw() const { return m_type == TokenType::Raw; } bool isMetaWord() const { return m_type == TokenType::MetaWord; } TokenType m_type; // For Raw type, m_value is the raw string of this token; // For MetaWord type, m_value is the word of the meta word pointed to by // this token. QString m_value; }; private: // Check if m_type is @p_type. bool checkType(MetaWordType p_type); // Parse children word from definition. // Children word MUST be defined in m_manager already. // @p_allowAllSpaces: if true then we allow all spaces including \n and \t // to appear in the definition. void checkAndParseDefinition(bool p_allowAllSpaces); // Parse @p_text to a list of tokens. static QVector parseToTokens(const QString &p_text); // Used for Compound meta word with cache @p_cache. // @p_cache: value cache for FunctionBased Token. // For a meta word occuring more than once, we should evaluate it once for // FunctionBased meta word. QString evaluateTokens(const QVector &p_tokens, QHash &p_cache) const; const VMetaWordManager *m_manager; MetaWordType m_type; // Word could contains spaces but no %. QString m_word; // For Simple/Compound meta word, this contains the definition; // For FunctionBased/Dynamic meta word, this makes no sense and is used // for description. QString m_definition; // For FunctionBased and Dynamic meta word. MetaWordFunc m_function; bool m_valid; // Tokens used for Compound meta word. QVector m_tokens; }; // Manager of meta word. class VMetaWordManager : public QObject { Q_OBJECT public: explicit VMetaWordManager(QObject *p_parent = nullptr); // Expand meta words in @p_text and return the expanded text. // @p_overriddenWords: a table containing overridden meta words. QString evaluate(const QString &p_text, const QHash &p_overriddenWords = QHash()) const; const VMetaWord *findMetaWord(const QString &p_word) const; bool contains(const QString &p_word) const; const QDateTime &getDateTime() const; const QHash &getAllMetaWords() const; // Find @p_word in the overridden table. // Return true if found and set @p_value to the overridden value. bool findOverriddenValue(const QString &p_word, QString &p_value) const; // % by default. static const QChar c_delimiter; private: void init(); void addMetaWord(MetaWordType p_type, const QString &p_word, const QString &p_definition, MetaWordFunc p_function = nullptr); void initCustomMetaWords(); bool m_initialized; // Map using word as key. QHash m_metaWords; // Used for data/time related evaluate. // Will be updated before each evaluation. QDateTime m_dateTime; // Overridden table containing meta words with their designated value. // Will be updated before each evaluation and clear after the evaluation. QHash m_overriddenWords; }; inline const QDateTime &VMetaWordManager::getDateTime() const { return m_dateTime; } inline const QHash &VMetaWordManager::getAllMetaWords() const { const_cast(this)->init(); return m_metaWords; } #endif // VMETAWORDMANAGER_H