]> vaikene.ee Git - evaf/commitdiff
Changed the Common::IniFile class to work with 7-bit character INI files only.
authorEnar Väikene <enar@vaikene.net>
Wed, 30 Nov 2011 12:26:14 +0000 (14:26 +0200)
committerEnar Väikene <enar@vaikene.net>
Wed, 30 Nov 2011 12:26:14 +0000 (14:26 +0200)
* Strings and byte arrays are now escaped;
* Strings and byte arrays can now be in single or double quotes; makes it possible to
  have leading and trailing spaces.
* When saving string or byte array values with leading or trailing spaces, automatically adds
  double quotes.

src/libs/Common/config.cpp
src/libs/Common/inifile.cpp
src/libs/Common/inifile.h
src/libs/Common/inifile_p.h
src/libs/Common/version.h

index 610dd74d98b445ba766efad28cc0badf0df0e557..c4f09970ff13e5ccf47a7a5ae2afb63f5612c5ce 100644 (file)
@@ -123,7 +123,7 @@ QVariant Config::getValue(QString const & paramName, QVariant const & defaultVal
     }
 
     // Read the value
-    return ini->getValue(name, defaultValue);
+    return ini->getValue(name.toLocal8Bit(), defaultValue);
 }
 
 bool Config::setValue(QString const & paramName, QVariant const & value, bool commit)
@@ -198,7 +198,7 @@ bool Config::writeValue(QString const & paramName, QVariant const & value)
     }
 
     // Write the value
-    if (!ini->setValue(name, value))
+    if (!ini->setValue(name.toLocal8Bit(), value))
         return false;
 
     return true;
index 14a47ee5fda19cb3c82b2bdbab383f13cfe3d9a6..838ff723630f057cb4a7e750a2f229877df1c83b 100644 (file)
@@ -56,12 +56,12 @@ QString IniFile::errorString() const
     return d->errorString();
 }
 
-QVariant IniFile::getValue(QString const & paramName, QVariant const & defaultValue)
+QVariant IniFile::getValue(QByteArray const & paramName, QVariant const & defaultValue)
 {
     return d->getValue(paramName, defaultValue);
 }
 
-bool IniFile::setValue(QString const & paramName, QVariant const & value)
+bool IniFile::setValue(QByteArray const & paramName, QVariant const & value)
 {
     return d->setValue(paramName, value);
 }
@@ -99,7 +99,7 @@ IniFileImpl::~IniFileImpl()
 void IniFileImpl::updateCache(quint64 pos, qint64 diff)
 {
     // Walk through all the sections in the cache
-    QHash<QString, QExplicitlySharedDataPointer<IniFileSection> >::const_iterator it;
+    QHash<QByteArray, QExplicitlySharedDataPointer<IniFileSection> >::const_iterator it;
     for (it = mCache.constBegin(); it != mCache.constEnd(); ++it) {
         QExplicitlySharedDataPointer<IniFileSection> sectionObject = *it;
 
@@ -108,7 +108,7 @@ void IniFileImpl::updateCache(quint64 pos, qint64 diff)
             sectionObject->filePos += diff;
 
         // Update individual values in the section that come after the current file offset
-        QHash<QString, QExplicitlySharedDataPointer<IniFileValue> >::const_iterator it1;
+        QHash<QByteArray, QExplicitlySharedDataPointer<IniFileValue> >::const_iterator it1;
         for (it1 = sectionObject->values.constBegin(); it1 != sectionObject->values.constEnd(); ++it1) {
             QExplicitlySharedDataPointer<IniFileValue> valueObject = *it1;
             if (valueObject->filePos > pos)
@@ -117,7 +117,7 @@ void IniFileImpl::updateCache(quint64 pos, qint64 diff)
     }
 }
 
-QExplicitlySharedDataPointer<IniFileSection> IniFileImpl::getSection(QFile & file, QString const & sectionName)
+QExplicitlySharedDataPointer<IniFileSection> IniFileImpl::getSection(QFile & file, QByteArray const & sectionName)
 {
     // Check for external modifications
     QFileInfo fi(file);
@@ -128,7 +128,7 @@ QExplicitlySharedDataPointer<IniFileSection> IniFileImpl::getSection(QFile & fil
     }
 
     // Look for the section in the cache first
-    QHash<QString, QExplicitlySharedDataPointer<IniFileSection> >::const_iterator it = mCache.constFind(sectionName.toLower());
+    QHash<QByteArray, QExplicitlySharedDataPointer<IniFileSection> >::const_iterator it = mCache.constFind(sectionName.toLower());
     if (it != mCache.constEnd()) {
         // Found in the cache
         if (mValid)
@@ -138,7 +138,7 @@ QExplicitlySharedDataPointer<IniFileSection> IniFileImpl::getSection(QFile & fil
 
     // Read the INI file and look for the section
     while (mValid && !file.atEnd()) {
-        QString line = file.readLine().trimmed();
+        QByteArray line = file.readLine().trimmed();
 
         // Ignore the line if it is empty, a comment or not a section name
         if (line.isEmpty() || line.startsWith(';') || line.startsWith('#') || !line.startsWith('['))
@@ -150,7 +150,7 @@ QExplicitlySharedDataPointer<IniFileSection> IniFileImpl::getSection(QFile & fil
             continue;
 
         // Is this the section that we are looking for?
-        if (line.mid(1, idx - 1).compare(sectionName, Qt::CaseInsensitive) == 0) {
+        if (qstricmp(line.mid(1, idx - 1).constData(), sectionName.constData()) == 0) {
             // Create the section object and add to the cache
             QExplicitlySharedDataPointer<IniFileSection> sectionObject(new IniFileSection(file.pos()));
             sectionObject->name = sectionName.toLower();
@@ -166,10 +166,10 @@ QExplicitlySharedDataPointer<IniFileSection> IniFileImpl::getSection(QFile & fil
     return QExplicitlySharedDataPointer<IniFileSection>();
 }
 
-QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & file, IniFileSection & section, QString const & paramName)
+QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & file, IniFileSection & section, QByteArray const & paramName)
 {
     // Look for the parameter in the cache first
-    QHash<QString, QExplicitlySharedDataPointer<IniFileValue> >::const_iterator it = section.values.constFind(paramName.toLower());
+    QHash<QByteArray, QExplicitlySharedDataPointer<IniFileValue> >::const_iterator it = section.values.constFind(paramName.toLower());
     if (it != section.values.constEnd()) {
         // Found it in the cache
         if (mValid)
@@ -183,7 +183,7 @@ QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & fil
         // Current file position
         quint64 currentPos = file.pos();
 
-        QString line = file.readLine().trimmed();
+        QByteArray line = file.readLine().trimmed();
 
         // Ignore the line if it is empty or a comment
         if (line.isEmpty() || line.startsWith(';') || line.startsWith('#'))
@@ -202,8 +202,8 @@ QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & fil
         if (idx == -1)
             continue;
 
-        QString name = line.mid(0, idx).trimmed().toLower();
-        QString value = line.mid(idx + 1).trimmed();
+        QByteArray name = line.mid(0, idx).trimmed().toLower();
+        QByteArray value = line.mid(idx + 1).trimmed();
 
         // Check for the 'windows:' or 'linux:' prefix in the parameter name
         bool thisOsOnly = false;
@@ -226,7 +226,7 @@ QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & fil
 
         // If the parameter value is not in the cache, add it to the cache
         QExplicitlySharedDataPointer<IniFileValue> valueObject;
-        QHash<QString, QExplicitlySharedDataPointer<IniFileValue> >::const_iterator it = section.values.constFind(name);
+        QHash<QByteArray, QExplicitlySharedDataPointer<IniFileValue> >::const_iterator it = section.values.constFind(name);
         if (it == section.values.constEnd()) {
             valueObject = new IniFileValue(currentPos);
             valueObject->name = name;
@@ -243,7 +243,7 @@ QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & fil
         }
 
         // Is this the parameter vwe are looking for?
-        if (name.compare(paramName, Qt::CaseInsensitive) == 0) {
+        if (qstricmp(name.constData(), paramName.constData()) == 0) {
             // Rewind to the beginning of the line
             file.seek(currentPos);
 
@@ -256,7 +256,7 @@ QExplicitlySharedDataPointer<IniFileValue> IniFileImpl::getParameter(QFile & fil
     return QExplicitlySharedDataPointer<IniFileValue>();
 }
 
-QVariant IniFileImpl::getValue(QString const & paramName, QVariant const & defaultValue)
+QVariant IniFileImpl::getValue(QByteArray const & paramName, QVariant const & defaultValue)
 {
     // Locate the '/' character that separates section names from key names
     int idx = paramName.lastIndexOf('/');
@@ -264,8 +264,8 @@ QVariant IniFileImpl::getValue(QString const & paramName, QVariant const & defau
         return defaultValue;
 
     // Separate section and key names
-    QString section = paramName.left(idx);
-    QString key = paramName.mid(idx + 1);
+    QByteArray section = paramName.left(idx);
+    QByteArray key = paramName.mid(idx + 1);
 
     // Open the file
     QFile f(mFileName);
@@ -289,10 +289,38 @@ QVariant IniFileImpl::getValue(QString const & paramName, QVariant const & defau
     if (f.isOpen())
         f.close();
 
-    return toVariant(valueObject->paramValue, defaultValue);
+    // Return the cached value if it is already set and the type is the same than the default value type
+    if (valueObject->value.isValid() && (!defaultValue.isValid() || valueObject->value.type() == defaultValue.type()))
+        return valueObject->value;
+
+    // Convert to the proper type
+    if (defaultValue.type() == QVariant::ByteArray || defaultValue.type() == QVariant::String) {
+        // Remove single and double quotes
+        QByteArray v = valueObject->paramValue;
+        if (v.startsWith('\"')) {
+            v.remove(0, 1);
+            if (v.endsWith('\"'))
+                v.remove(v.size() - 1, 1);
+        }
+        else if (v.startsWith('\'')) {
+            v.remove(0, 1);
+            if (v.endsWith('\''))
+                v.remove(v.size() - 1, 1);
+        }
+
+        // Convert from the escaped character array
+        if (defaultValue.type() == QVariant::String)
+            valueObject->value = QVariant(strFromEscapedCharArray(v));
+        else
+            valueObject->value = QVariant(binFromEscapedCharArray(v));
+    }
+    else
+        valueObject->value = toVariant(valueObject->paramValue, defaultValue);
+
+    return valueObject->value;
 }
 
-bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
+bool IniFileImpl::setValue(QByteArray const & paramName, QVariant const & value)
 {
     // Locate the '/' character that separates section names from key names
     int idx = paramName.lastIndexOf('/', -1);
@@ -300,29 +328,49 @@ bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
         return false;
 
     // Separate section and key names
-    QString section = paramName.left(idx).toLower();
-    QString key = paramName.mid(idx + 1).toLower();
+    QByteArray section = paramName.left(idx).toLower();
+    QByteArray key = paramName.mid(idx + 1).toLower();
 
     // Format the value depending on the type
-    QString valueString;
+    QByteArray valueString;
     switch (value.type()) {
         case QVariant::UInt:
-            valueString = "0x" + QString::number(value.toUInt(), 16);
+            valueString = QByteArray("0x").append(QByteArray::number(value.toUInt(), 16));
             break;
         case QVariant::Int:
-            valueString = QString::number(value.toInt());
+            valueString = QByteArray::number(value.toInt());
             break;
         case QVariant::Double:
-            valueString = QString::number(value.toDouble(), 'f');
+            valueString = QByteArray::number(value.toDouble(), 'f');
             break;
         case QVariant::Bool:
             valueString = value.toBool() ? "true" : "false";
             break;
-        case QVariant::Char:
-            valueString = value.toChar();
+        case QVariant::Char: {
+            QChar c = value.toChar();
+            printf("c.unicode() = %u\n", c.unicode());
+            if (c.unicode() < 32 || c.unicode() >= 127)
+                valueString = QByteArray("\\0x").append(QByteArray::number(c.unicode(), 16));
+            else
+                valueString = QByteArray(1, (char const)c.unicode());
+            break;
+        }
+        case QVariant::ByteArray:
+            valueString = binToEscapedCharArray(value.toByteArray());
+            if (valueString.startsWith(' ') || valueString.endsWith(' ')) {
+                valueString.insert(0, '\"');
+                valueString.append('\"');
+            }
+            break;
+        case QVariant::String:
+            valueString = strToEscapedCharArray(value.toString());
+            if (valueString.startsWith(' ') || valueString.endsWith(' ')) {
+                valueString.insert(0, '\"');
+                valueString.append('\"');
+            }
             break;
         default:
-            valueString = value.toString();
+            valueString = value.toString().toLatin1();
     }
 
     // Open the file
@@ -343,7 +391,7 @@ bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
     if (!sectionObject) {
 
         // Write the new section to the INI file (the file is already positioned at the end)
-        if (f.write(QString("[%1]" EOL).arg(section).toLocal8Bit()) == -1) {
+        if (f.write(QString("[%1]" EOL).arg(section.constData()).toLatin1()) == -1) {
             mErrorString = f.errorString();
             mValid = false;
             EVAF_ERROR("Failed to write to the INI file %s : %s", qPrintable(mFileName), qPrintable(mErrorString));
@@ -358,7 +406,7 @@ bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
         mCache.insert(section.toLower(), sectionObject);
 
         // Write the parameter value to the INI file
-        if (f.write(QString("%1 = %2" EOL).arg(key).arg(valueString).toLocal8Bit()) == -1) {
+        if (f.write(QString("%1 = %2" EOL).arg(key.constData()).arg(valueString.constData()).toLatin1()) == -1) {
             mErrorString = f.errorString();
             mValid = false;
             EVAF_ERROR("Failed to write to the INI file %s : %s", qPrintable(mFileName), qPrintable(mErrorString));
@@ -369,6 +417,7 @@ bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
         QExplicitlySharedDataPointer<IniFileValue> valueObject(new IniFileValue(currentPos));
         valueObject->name = key;
         valueObject->paramValue = valueString;
+        valueObject->value = value;
         sectionObject->values.insert(key, valueObject);
     }
 
@@ -423,7 +472,7 @@ bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
 
         // Rewind to the original position and write the new parameter value
         f.seek(currentPos);
-        if (f.write(QString("%1%2 = %3" EOL).arg(prefix).arg(key).arg(valueString).toLocal8Bit()) == -1) {
+        if (f.write(QString("%1%2 = %3" EOL).arg(prefix).arg(key.constData()).arg(valueString.constData()).toLatin1()) == -1) {
             mErrorString = f.errorString();
             mValid = false;
             EVAF_ERROR("Failed to write to the INI file %s : %s", qPrintable(mFileName), qPrintable(mErrorString));
@@ -459,6 +508,7 @@ bool IniFileImpl::setValue(QString const & paramName, QVariant const & value)
 
         // Update the parameter value in the internal cache
         valueObject->paramValue = valueString;
+        valueObject->value = value;
 
     }
 
index 21a1bc4346ac293b8d96b03992242210efce013a..2ebe1c1c863c4ec340443e9d271900cb9f844453 100644 (file)
@@ -59,7 +59,7 @@ namespace Internal {
  * of different data types:
  *
  * @li Bool - '0', 'false', 'off', 'no' are equal to false and '1', 'true', 'on', 'yes' are equal to true;
- * @li Char - a single character or an ASCII code as '\0NNN' (oct) or '\0xNN' (hex);
+ * @li Char - a single character or an UTF-16 code as '\0NNNNNN' (oct) or '\0xNNNN' (hex);
  * @li Date - date string in the ISO 8601 format YYYY-MM-DD;
  * @li DateTime - date and time string in the ISO 8601 format YYY-MM-DDTHH:MM:SSTZD;
  * @li Double - the decimal point is always '.' regardless of the locale;
@@ -119,7 +119,7 @@ public:
      *
      * @sa eVaf::Common::toVariant()
      */
-    QVariant getValue(QString const & paramName, QVariant const & defaultValue = QVariant::Invalid);
+    QVariant getValue(QByteArray const & paramName, QVariant const & defaultValue = QVariant::Invalid);
 
     /**
      * Writes a value to the INI file.
@@ -134,7 +134,7 @@ public:
      * The method returns true if the parameter value was written into the INI file and false if not. Use the errorString() method
      * to get a human-readable error string if writing to the INI file fails.
      */
-    bool setValue(QString const & paramName, QVariant const & value);
+    bool setValue(QByteArray const & paramName, QVariant const & value);
 
 
 private:
index b7826270f25239bc64c0013f0949d7c031ee54cc..ffb7a1e2647d7031421ecf004c904639533de456 100644 (file)
@@ -57,12 +57,17 @@ public:
     /**
      * Key name of the parameter
      */
-    QString name;
+    QByteArray name;
 
     /**
      * Value from the INI file
      */
-    QString paramValue;
+    QByteArray paramValue;
+
+    /**
+     * Value converted to the final type (defaults to QVariant::Invalid
+     */
+    QVariant value;
 
     /**
      * Flag indicating that this value is valid on this OS only
@@ -93,14 +98,14 @@ public:
     /**
      * Name of the section
      */
-    QString name;
+    QByteArray name;
 
     /**
      * List of all the known parameter values in this section
      *
      * The key to the hash table is the name of the key for the parameters value.
      */
-    QHash<QString, QExplicitlySharedDataPointer<IniFileValue> > values;
+    QHash<QByteArray, QExplicitlySharedDataPointer<IniFileValue> > values;
 
 };
 
@@ -115,9 +120,9 @@ public:
 
     ~IniFileImpl();
 
-    QVariant getValue(QString const & paramName, QVariant const & defaultValue);
+    QVariant getValue(QByteArray const & paramName, QVariant const & defaultValue);
 
-    bool setValue(QString const & paramName, QVariant const & value);
+    bool setValue(QByteArray const & paramName, QVariant const & value);
 
     inline bool isValid() const { return mValid; }
 
@@ -145,7 +150,7 @@ private: // Members
      *
      * The key to the hash table is the name of the section.
      */
-    QHash<QString, QExplicitlySharedDataPointer<IniFileSection> > mCache;
+    QHash<QByteArray, QExplicitlySharedDataPointer<IniFileSection> > mCache;
 
     /// When was the INI file modified.
     QDateTime mLastModified;
@@ -178,7 +183,7 @@ private: /// Methods
      * The file object is expected to be opened if the mValid flag is true. If the mValid flag is false, looks
      * only in the cache.
      */
-    QExplicitlySharedDataPointer<IniFileSection> getSection(QFile & file, QString const & sectionName);
+    QExplicitlySharedDataPointer<IniFileSection> getSection(QFile & file, QByteArray const & sectionName);
 
     /**
      * Looks for a parameter in the INI file
@@ -195,7 +200,7 @@ private: /// Methods
      * The file object is expected to be opened if the mValid flag is true. If the mValid flag is false, looks
      * only in the cache.
      */
-    QExplicitlySharedDataPointer<IniFileValue> getParameter(QFile & file, IniFileSection & section, QString const & paramName);
+    QExplicitlySharedDataPointer<IniFileValue> getParameter(QFile & file, IniFileSection & section, QByteArray const & paramName);
 
 };
 
index e6068b955cedbf6c9155671938890eeaa4290c46..fb1c67f724ffe9ca4a48bf8991f5002c337f499d 100644 (file)
 /**
  * Module/library version number in the form major,minor,release,build
  */
-#define VER_FILE_VERSION                0,2,2,9
+#define VER_FILE_VERSION                0,2,2,10
 
 /**
  * Module/library version number in the string format (shall end with \0)
  */
-#define VER_FILE_VERSION_STR            "0.2.2.9\0"
+#define VER_FILE_VERSION_STR            "0.2.2.10\0"
 
 /**
  * Module/library name (shall end with \0)