File indexing completed on 2024-04-28 05:36:59

0001 /***************************************************************************
0002  * Copyright (C) 2014 by Renaud Guezennec                                   *
0003  * https://rolisteam.org/contact                      *
0004  *                                                                          *
0005  *  This file is part of DiceParser                                         *
0006  *                                                                          *
0007  * DiceParser is free software; you can redistribute it and/or modify       *
0008  * it under the terms of the GNU General Public License as published by     *
0009  * the Free Software Foundation; either version 2 of the License, or        *
0010  * (at your option) any later version.                                      *
0011  *                                                                          *
0012  * This program is distributed in the hope that it will be useful,          *
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of           *
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             *
0015  * GNU General Public License for more details.                             *
0016  *                                                                          *
0017  * You should have received a copy of the GNU General Public License        *
0018  * along with this program; if not, write to the                            *
0019  * Free Software Foundation, Inc.,                                          *
0020  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.                 *
0021  ***************************************************************************/
0022 #include <QRegularExpression>
0023 #include <diceparser/dicealias.h>
0024 
0025 #include <QDebug>
0026 
0027 QString makeReplament(const QString& pattern, const QString& command, QString cmd)
0028 {
0029     auto hasPattern= cmd.contains(pattern);
0030     if(hasPattern)
0031     {
0032         auto idxPattern= cmd.indexOf(pattern);
0033         std::vector<std::pair<int, int>> quotes;
0034 
0035         int pos= 0;
0036         bool open= true;
0037         while(pos != -1 && pos < cmd.size())
0038         {
0039             auto oldPos= pos;
0040             pos= cmd.indexOf("\"", pos);
0041             if(open && pos != -1)
0042                 open= false;
0043             else if(pos != -1)
0044             {
0045                 quotes.push_back({oldPos, pos});
0046             }
0047 
0048             if(pos != -1)
0049                 pos+= 1;
0050         }
0051         auto hasQuote= false;
0052         for(auto range : quotes)
0053         {
0054             if(idxPattern < range.second && idxPattern >= range.first)
0055                 hasQuote= true;
0056         }
0057 
0058         auto hasVariable= cmd.contains("${");
0059         auto commentPos= cmd.lastIndexOf("#");
0060 
0061         if(!hasQuote && !hasVariable)
0062         {
0063             cmd.replace(pattern, command);
0064         }
0065         else
0066         {
0067             std::vector<int> patternPosList;
0068             std::vector<std::pair<int, int>> variablePos;
0069 
0070             int pos= 0;
0071             QRegularExpressionMatch match;
0072             while(pos != -1)
0073             {
0074                 auto start= cmd.indexOf(QRegularExpression("\\${\\N+}"), pos, &match);
0075                 if(start >= 0)
0076                 {
0077                     auto end= start + match.captured().length();
0078                     variablePos.push_back(std::make_pair(start, end));
0079                     pos= end + 1;
0080                 }
0081                 else
0082                 {
0083                     pos= start;
0084                 }
0085             }
0086 
0087             pos= 0;
0088             while(pos != -1)
0089             {
0090                 auto start= cmd.indexOf("\"", pos);
0091                 if(start >= 0)
0092                 {
0093                     auto end= cmd.indexOf("\"", start + 1);
0094                     variablePos.push_back(std::make_pair(start, end));
0095                     pos= end + 1;
0096                 }
0097                 else
0098                 {
0099                     pos= start;
0100                 }
0101             }
0102             pos= 0;
0103             while((pos= cmd.indexOf(pattern, pos)) && pos != -1)
0104             {
0105                 bool isInsidePair= false;
0106                 for(auto pair : variablePos)
0107                 {
0108                     if(!isInsidePair)
0109                         isInsidePair= (pos > pair.first && pos < pair.second);
0110 
0111                     if(commentPos >= 0 && pos > commentPos)
0112                         isInsidePair= true;
0113                 }
0114                 if(!isInsidePair)
0115                     patternPosList.push_back(pos);
0116 
0117                 pos+= 1;
0118             }
0119 
0120             // TODO to be replace by C++14 when it is ready
0121             for(auto i= patternPosList.rbegin(); i != patternPosList.rend(); ++i)
0122             {
0123                 cmd.replace(*i, 1, command);
0124             }
0125         }
0126     }
0127     return cmd;
0128 }
0129 
0130 DiceAlias::DiceAlias(QString pattern, QString command, QString comment, bool isReplace, bool isEnable)
0131     : m_pattern(pattern)
0132     , m_command(command)
0133     , m_comment(comment)
0134     , m_type(isReplace ? REPLACE : REGEXP)
0135     , m_isEnable(isEnable)
0136 {
0137 }
0138 
0139 DiceAlias::~DiceAlias()
0140 {
0141     // qDebug() << "destructeur of alias!" << this;
0142 }
0143 
0144 DiceAlias::DiceAlias(const DiceAlias& alias)
0145 {
0146     m_command= alias.command();
0147     m_comment= alias.comment();
0148     m_pattern= alias.pattern();
0149     m_isEnable= alias.isEnable();
0150     m_type= alias.isReplace() ? REPLACE : REGEXP;
0151 }
0152 
0153 bool DiceAlias::resolved(QString& str)
0154 {
0155     if(!m_isEnable)
0156         return false;
0157 
0158     if((m_type == REPLACE) && (str.contains(m_pattern)))
0159     {
0160         str= makeReplament(m_pattern, m_command, str);
0161         return true;
0162     }
0163     else if(m_type == REGEXP)
0164     {
0165         QRegularExpression exp(m_pattern);
0166         str.replace(exp, m_command);
0167         return true;
0168     }
0169     return false;
0170 }
0171 
0172 void DiceAlias::setCommand(QString command)
0173 {
0174     m_command= command;
0175 }
0176 
0177 void DiceAlias::setPattern(const QString& pattern)
0178 {
0179     m_pattern= pattern;
0180 }
0181 
0182 void DiceAlias::setType(RESOLUTION_TYPE type)
0183 {
0184     m_type= type;
0185 }
0186 QString DiceAlias::command() const
0187 {
0188     return m_command;
0189 }
0190 
0191 QString DiceAlias::pattern() const
0192 {
0193     return m_pattern;
0194 }
0195 
0196 bool DiceAlias::isReplace() const
0197 {
0198     return (m_type == REPLACE) ? true : false;
0199 }
0200 
0201 void DiceAlias::setReplace(bool b)
0202 {
0203     if(b)
0204     {
0205         m_type= REPLACE;
0206     }
0207     else
0208     {
0209         m_type= REGEXP;
0210     }
0211 }
0212 
0213 bool DiceAlias::isEnable() const
0214 {
0215     return m_isEnable;
0216 }
0217 
0218 void DiceAlias::setEnable(bool b)
0219 {
0220     m_isEnable= b;
0221 }
0222 
0223 QString DiceAlias::comment() const
0224 {
0225     return m_comment;
0226 }
0227 
0228 void DiceAlias::setComment(const QString& comment)
0229 {
0230     m_comment= comment;
0231 }