Xcode: Fix string quoting to match ASCII plist format

The logic for quoting and unescaping strings was a bit random.
We now leave the strings alone, until writing them out as values,
where we quote and escape the characters that need escaping.

See:

  http://www.gnustep.org/resources/documentation/Developer/Base/Reference/NSPropertyList.html
  https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html
  https://code.google.com/p/plist/source/browse/trunk/src/main/java/com/dd/plist/NSString.java?r=107#230

Change-Id: I2096df531947abdce4f6b57428136f544d22c466
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
Tor Arne Vestbø 2013-06-27 15:21:37 +02:00 committed by The Qt Project
parent 29570d8442
commit 0233e9ec8b

View File

@ -1520,12 +1520,8 @@ ProjectBuilderMakefileGenerator::fixForOutput(const QString &values)
project->values("QMAKE_PBX_VARS").append(reg_var.cap(1)); project->values("QMAKE_PBX_VARS").append(reg_var.cap(1));
rep += reg_var.matchedLength(); rep += reg_var.matchedLength();
} }
QString ret = values;
ret = ret.replace(QRegExp("\\\\ "), " "); //unescape spaces return values;
ret = ret.replace(QRegExp("('|\\\\|\")"), "\\\\1"); //fix quotes
ret = ret.replace("\t", " "); //fix tabs
ret = ret.replace(QRegExp(" "), "\\ "); //escape spaces
return ret;
} }
ProStringList ProStringList
@ -1749,37 +1745,81 @@ ProjectBuilderMakefileGenerator::escapeFilePath(const QString &path) const
#endif #endif
} }
static QString quotedStringLiteral(const QString &value)
{
QString result;
const int len = value.length();
result.reserve(int(len * 1.1) + 2);
result += QLatin1Char('"');
// Escape
for (int i = 0; i < len; ++i) {
QChar character = value.at(i);;
ushort code = character.unicode();
switch (code) {
case '\\':
result += QLatin1String("\\\\");
break;
case '"':
result += QLatin1String("\\\"");
break;
case '\b':
result += QLatin1String("\\b");
break;
case '\n':
result += QLatin1String("\\n");
break;
case '\r':
result += QLatin1String("\\r");
break;
case '\t':
result += QLatin1String("\\t");
break;
default:
if (code >= 32 && code <= 127)
result += character;
else
result += QLatin1String("\\u") + QString::number(code, 16).rightJustified(4, '0');
}
}
result += QLatin1Char('"');
result.squeeze();
return result;
}
QString QString
ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStringList &vals, int flags, int indent_level) ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStringList &vals, int flags, int indent_level)
{ {
QString ret; QString ret;
const QString quote = (flags & SettingsNoQuote) ? "" : "\""; bool shouldQuote = !((flags & SettingsNoQuote));
const QString escape_quote = quote.isEmpty() ? "" : QString("\\" + quote);
QString newline = "\n"; QString newline = "\n";
for(int i = 0; i < indent_level; ++i) for(int i = 0; i < indent_level; ++i)
newline += "\t"; newline += "\t";
ret += var + " = ";
if(flags & SettingsAsList) { if(flags & SettingsAsList) {
ret += var + " = (" + newline; ret += "(" + newline;
for(int i = 0, count = 0; i < vals.size(); ++i) { for(int i = 0, count = 0; i < vals.size(); ++i) {
QString val = vals.at(i).toQString(); QString val = vals.at(i).toQString();
if(!val.isEmpty()) { if(!val.isEmpty()) {
if(count++ > 0) if(count++ > 0)
ret += "," + newline; ret += "," + newline;
ret += quote + val.replace(quote, escape_quote) + quote; if (shouldQuote)
val = quotedStringLiteral(val);
ret += val;
} }
} }
ret += ")"; ret += ")";
} else { } else {
ret += var + " = " + quote; QString val = vals.join(QLatin1Char(' '));
for(int i = 0; i < vals.size(); ++i) { if (shouldQuote)
QString val = vals.at(i).toQString(); val = quotedStringLiteral(val);
// if(val.isEmpty()) ret += val;
// val = quote + quote;
if(i)
ret += " ";
ret += val;
}
ret += quote;
} }
return ret; return ret;
} }