File indexing completed on 2024-05-19 16:47:16

0001 // clang-format off
0002 /*
0003  * KDiff3 - Text Diff And Merge Tool
0004 
0005  * SPDX-FileCopyrightText: 2002-2011 Joachim Eibl, joachim.eibl at gmx.de
0006  * SPDX-FileCopyrightText: 2018-2020 Michael Reeves reeves.87@gmail.com
0007  * SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 // clang-format on
0010 
0011 #include "common.h"
0012 #include "TypeUtils.h"
0013 
0014 #include <map>
0015 #include <utility> // for pair
0016 
0017 #include <QColor>
0018 #include <QFont>
0019 #include <QLatin1String>
0020 #include <QPoint>
0021 #include <QSize>
0022 #include <QStringList>
0023 #include <QStringLiteral>
0024 #include <QTextStream>
0025 
0026 ValueMap::ValueMap() = default;
0027 
0028 ValueMap::~ValueMap() = default;
0029 
0030 void ValueMap::save(QTextStream& ts)
0031 {
0032     for(const auto &entry: m_map)
0033     {
0034         const QString key = entry.first;
0035         const QString val = entry.second;
0036         ts << key << "=" << val << "\n";
0037     }
0038 }
0039 
0040 QString ValueMap::getAsString()
0041 {
0042     QString result;
0043 
0044     for(const auto &entry: m_map)
0045     {
0046         const QString key = entry.first;
0047         const QString val = entry.second;
0048         result += key + '=' + val + '\n';
0049     }
0050     return result;
0051 }
0052 
0053 void ValueMap::load(QTextStream& ts)
0054 {
0055     while(!ts.atEnd())
0056     {                              // until end of file...
0057         QString s = ts.readLine(); // line of text excluding '\n'
0058         QtSizeType pos = s.indexOf('=');
0059         if(pos > 0) // seems not to have a tag
0060         {
0061             QString key = s.left(pos);
0062             QString val = s.mid(pos + 1);
0063             m_map[key] = val;
0064         }
0065     }
0066 }
0067 
0068 // safeStringJoin and safeStringSplit allow to convert a stringlist into a string and back
0069 // safely, even if the individual strings in the list contain the separator character.
0070 QString safeStringJoin(const QStringList& sl, char sepChar, char metaChar)
0071 {
0072     // Join the strings in the list, using the separator ','
0073     // If a string contains the separator character, it will be replaced with "\,".
0074     // Any occurrences of "\" (one backslash) will be replaced with "\\" (2 backslashes)
0075 
0076     assert(sepChar != metaChar);
0077 
0078     QString sep;
0079     sep += sepChar;
0080     QString meta;
0081     meta += metaChar;
0082 
0083     QString safeString;
0084 
0085     QStringList::const_iterator i;
0086     for(i = sl.begin(); i != sl.end(); ++i)
0087     {
0088         QString s = *i;
0089         s.replace(meta, meta + meta); //  "\" -> "\\"
0090         s.replace(sep, meta + sep);   //  "," -> "\,"
0091         if(i == sl.begin())
0092             safeString = s;
0093         else
0094             safeString += sep + s;
0095     }
0096     return safeString;
0097 }
0098 
0099 // Split a string that was joined with safeStringJoin
0100 QStringList safeStringSplit(const QString& s, char sepChar, char metaChar)
0101 {
0102     assert(sepChar != metaChar);
0103     QStringList sl;
0104     // Miniparser
0105     QtSizeType i = 0;
0106     QtSizeType len = s.length();
0107     QString b;
0108     for(i = 0; i < len; ++i)
0109     {
0110         if(i + 1 < len && s[i] == metaChar && s[i + 1] == metaChar)
0111         {
0112             b += metaChar;
0113             ++i;
0114         }
0115         else if(i + 1 < len && s[i] == metaChar && s[i + 1] == sepChar)
0116         {
0117             b += sepChar;
0118             ++i;
0119         }
0120         else if(s[i] == sepChar) // real separator
0121         {
0122             sl.push_back(b);
0123             b = "";
0124         }
0125         else
0126         {
0127             b += s[i];
0128         }
0129     }
0130     if(!b.isEmpty())
0131         sl.push_back(b);
0132 
0133     return sl;
0134 }
0135 
0136 void ValueMap::writeEntry(const QString& k, const QFont& v)
0137 {
0138     m_map[k] = v.family() + u8"," + QString::number(v.pointSize()) + u8"," + (v.bold() ? QStringLiteral("bold") : QStringLiteral("normal"));
0139 }
0140 
0141 void ValueMap::writeEntry(const QString& k, const QColor& v)
0142 {
0143     m_map[k].setNum(v.red()) + u8"," + QString().setNum(v.green()) + u8"," + QString().setNum(v.blue());
0144 }
0145 
0146 void ValueMap::writeEntry(const QString& k, const QSize& v)
0147 {
0148     m_map[k].setNum(v.width()) + u8"," + QString().setNum(v.height());
0149 }
0150 
0151 void ValueMap::writeEntry(const QString& k, const QPoint& v)
0152 {
0153     m_map[k].setNum(v.x()) + u8"," + QString().setNum(v.y());
0154 }
0155 
0156 void ValueMap::writeEntry(const QString& k, qint32 v)
0157 {
0158     m_map[k].setNum(v);
0159 }
0160 
0161 void ValueMap::writeEntry(const QString& k, bool v)
0162 {
0163     m_map[k].setNum(v);
0164 }
0165 
0166 void ValueMap::writeEntry(const QString& k, const QString& v)
0167 {
0168     m_map[k] = v;
0169 }
0170 
0171 void ValueMap::writeEntry(const QString& k, const char* v)
0172 {
0173     m_map[k] = QLatin1String(v);
0174 }
0175 
0176 void ValueMap::writeEntry(const QString& k, const QStringList& v)
0177 {
0178     m_map[k] = safeStringJoin(v);
0179 }
0180 
0181 QFont ValueMap::readFontEntry(const QString& k, const QFont* defaultVal)
0182 {
0183     QFont f = *defaultVal;
0184     std::map<QString, QString>::iterator i = m_map.find(k);
0185     if(i != m_map.end())
0186     {
0187         f.setFamily(i->second.split(',')[0]);
0188         f.setPointSize(i->second.split(',')[1].toInt());
0189         f.setBold(i->second.split(',')[2] == "bold");
0190     }
0191     return f;
0192 }
0193 
0194 QColor ValueMap::readColorEntry(const QString& k, const QColor* defaultVal)
0195 {
0196     QColor c = *defaultVal;
0197     std::map<QString, QString>::iterator i = m_map.find(k);
0198     if(i != m_map.end())
0199     {
0200         QString s = i->second;
0201         c = QColor(s.split(',')[0].toInt(), s.split(',')[1].toInt(), s.split(',')[2].toInt());
0202     }
0203 
0204     return c;
0205 }
0206 
0207 QSize ValueMap::readSizeEntry(const QString& k, const QSize* defaultVal)
0208 {
0209     QSize size = defaultVal ? *defaultVal : QSize(600, 400);
0210     std::map<QString, QString>::iterator i = m_map.find(k);
0211     if(i != m_map.end())
0212     {
0213 
0214         QString s = i->second;
0215         size = QSize(s.split(',')[0].toInt(), s.split(',')[1].toInt());
0216     }
0217 
0218     return size;
0219 }
0220 
0221 QPoint ValueMap::readPointEntry(const QString& k, const QPoint* defaultVal)
0222 {
0223     QPoint point = defaultVal ? *defaultVal : QPoint(0, 0);
0224     std::map<QString, QString>::iterator i = m_map.find(k);
0225     if(i != m_map.end())
0226     {
0227         QString s = i->second;
0228         point = QPoint(s.split(',')[0].toInt(), s.split(',')[1].toInt());
0229     }
0230 
0231     return point;
0232 }
0233 
0234 bool ValueMap::readBoolEntry(const QString& k, bool bDefault)
0235 {
0236     bool b = bDefault;
0237     std::map<QString, QString>::iterator i = m_map.find(k);
0238     if(i != m_map.end())
0239     {
0240         QString s = i->second;
0241         b = (s.split(',')[0].toInt() == 1);
0242     }
0243 
0244     return b;
0245 }
0246 
0247 qint32 ValueMap::readNumEntry(const QString& k, qint32 iDefault)
0248 {
0249     qint32 ival = iDefault;
0250     std::map<QString, QString>::iterator i = m_map.find(k);
0251     if(i != m_map.end())
0252     {
0253         QString s = i->second;
0254         ival = s.split(',')[0].toInt();
0255     }
0256 
0257     return ival;
0258 }
0259 
0260 QString ValueMap::readStringEntry(const QString& k, const QString& sDefault)
0261 {
0262     QString sval = sDefault;
0263     std::map<QString, QString>::iterator i = m_map.find(k);
0264     if(i != m_map.end())
0265     {
0266         sval = i->second;
0267     }
0268 
0269     return sval;
0270 }
0271 
0272 QStringList ValueMap::readListEntry(const QString& k, const QStringList& defaultVal)
0273 {
0274     QStringList strList;
0275 
0276     std::map<QString, QString>::iterator i = m_map.find(k);
0277     if(i != m_map.end())
0278     {
0279         strList = safeStringSplit(i->second);
0280         return strList;
0281     }
0282     else
0283         return defaultVal;
0284 }
0285 
0286 QString ValueMap::readEntry(const QString& s, const QString& defaultVal)
0287 {
0288     return readStringEntry(s, defaultVal);
0289 }
0290 
0291 QString ValueMap::readEntry(const QString& s, const char* defaultVal)
0292 {
0293     return readStringEntry(s, QString::fromLatin1(defaultVal));
0294 }
0295 
0296 QFont ValueMap::readEntry(const QString& s, const QFont& defaultVal)
0297 {
0298     return readFontEntry(s, &defaultVal);
0299 }
0300 
0301 QColor ValueMap::readEntry(const QString& s, const QColor defaultVal)
0302 {
0303     return readColorEntry(s, &defaultVal);
0304 }
0305 
0306 QSize ValueMap::readEntry(const QString& s, const QSize defaultVal)
0307 {
0308     return readSizeEntry(s, &defaultVal);
0309 }
0310 
0311 QPoint ValueMap::readEntry(const QString& s, const QPoint defaultVal)
0312 {
0313     return readPointEntry(s, &defaultVal);
0314 }
0315 
0316 bool ValueMap::readEntry(const QString& s, bool bDefault)
0317 {
0318     return readBoolEntry(s, bDefault);
0319 }
0320 
0321 qint32 ValueMap::readEntry(const QString& s, qint32 iDefault)
0322 {
0323     return readNumEntry(s, iDefault);
0324 }
0325 
0326 QStringList ValueMap::readEntry(const QString& s, const QStringList& defaultVal)
0327 {
0328     return readListEntry(s, defaultVal);
0329 }