Header.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "Qt.h"
00024 #include "Header.h"
00025 #include <algorithm>
00026 #include <functional>
00027
00028 using namespace Http;
00029
00030 namespace Http {
00031
00032 class HeaderPrivate
00033 {
00034 public:
00035 inline virtual ~HeaderPrivate() {}
00036
00037 struct FieldInfo
00038 {
00039 QString originalCaseFieldName;
00040 QStringList fieldValues;
00041
00042 FieldInfo() : originalCaseFieldName(), fieldValues() {}
00043 };
00044
00045 QMap <QString, FieldInfo> fields;
00046 QStringList orderedFieldList;
00047 bool valid;
00048
00049 HeaderPrivate() : fields(), orderedFieldList(), valid (false) {}
00050 };
00051
00052 }
00053
00057 Header::Header()
00058 : d(new HeaderPrivate)
00059 {
00060 d->valid = true;
00061 }
00062
00066 Header::Header (const Header &header)
00067 : d(new HeaderPrivate)
00068 {
00069 d->valid = header.d->valid;
00070 d->fields = header.d->fields;
00071 d->orderedFieldList = header.d->orderedFieldList;
00072 }
00073
00082 Header::Header (const QString &str)
00083 : d(new HeaderPrivate)
00084 {
00085 d->valid = parse(str);
00086 }
00087
00091 Header::~Header()
00092 {
00093 delete d;
00094 }
00095
00099 Header & Header::operator= (const Header &header)
00100 {
00101 d->valid = header.d->valid;
00102 d->fields = header.d->fields;
00103 d->orderedFieldList = header.d->orderedFieldList;
00104 return *this;
00105 }
00106
00111 bool Header::operator== (const Header &other) const
00112 {
00113 return toString() == other.toString();
00114 }
00115
00120 bool Header::operator!= (const Header &other) const
00121 {
00122 return !(*this == other);
00123 }
00124
00130 bool Header::isValid() const
00131 {
00132 return d->valid;
00133 }
00134
00135 struct lineAppender : public std::unary_function<QString, void>
00136 {
00137 QStringList& m_lines;
00138 lineAppender( QStringList& lines ) : m_lines( lines ) {
00139 }
00140 void operator()(QString& line) {
00141 if (!line.isEmpty()) {
00142 if (line[0].isSpace()) {
00143 if (!m_lines.isEmpty()) {
00144 m_lines.last() += " ";
00145 m_lines.last() += line.trimmed();
00146 }
00147 } else {
00148 m_lines.append(line);
00149 }
00150 }
00151 }
00152 };
00153
00154 QStringList Header::splitStringIntoLines (const QString &str)
00155 {
00156 QStringList lst;
00157 int pos = str.indexOf('\n');
00158 if (pos > 0 && str.at(pos - 1) == '\r')
00159 lst = str.trimmed().split("\r\n");
00160 else
00161 lst = str.trimmed().split("\n");
00162 lst.removeAll(QString());
00163 return lst;
00164 }
00165
00166 bool Header::parseAllLines (const QStringList& lines)
00167 {
00168 int number = 0;
00169 QStringList::const_iterator it = lines.begin();
00170 for(; it != lines.end(); ++it) {
00171 if (!parseLine(*it, number++)) {
00172 return false;
00173 }
00174 }
00175 return true;
00176 }
00177
00188 bool Header::parse (const QString &str)
00189 {
00190 d->fields.clear();
00191 d->orderedFieldList.clear();
00192 d->valid = true;
00193
00194 QStringList lst = splitStringIntoLines (str);
00195 if (lst.isEmpty())
00196 return true;
00197
00198 QStringList lines;
00199 std::for_each (lst.begin(), lst.end(), lineAppender(lines));
00200 d->valid = parseAllLines (lines);
00201 return d->valid;
00202 }
00203
00206 void Header::setValid (bool v)
00207 {
00208 d->valid = v;
00209 }
00210
00220 QString Header::fieldValue (const QString &fieldName) const
00221 {
00222 QString nameLower (fieldName.toLower());
00223 if (!d->fields.contains (nameLower))
00224 return QString();
00225 else
00226 return d->fields [nameLower].fieldValues.join (", ");
00227 }
00228
00235 QStringList Header::fields() const
00236 {
00237 return d->fields.keys();
00238 }
00239
00247 bool Header::hasField (const QString &fieldName) const
00248 {
00249 return d->fields.contains (fieldName.toLower());
00250 }
00251
00264 void Header::setFieldValue (const QString &fieldName,
00265 const QString &fieldValue)
00266 {
00267 QString nameLower (fieldName.toLower());
00268
00269 d->fields.remove (nameLower);
00270 addFieldValues(fieldName, fieldValue.split(",", QString::SkipEmptyParts));
00271 }
00272
00280 void Header::addFieldValue (const QString &fieldName,
00281 const QString &fieldValue)
00282 {
00283 QString nameLower (fieldName.toLower());
00284 d->fields [nameLower].fieldValues.push_back (fieldValue.trimmed());
00285
00286 d->fields [nameLower].originalCaseFieldName = fieldName;
00287 if (!d->orderedFieldList.contains (nameLower))
00288 d->orderedFieldList.append (nameLower);
00289 }
00290
00298 void Header::addFieldValues (const QString &fieldName,
00299 const QStringList &fieldValues)
00300 {
00301 foreach (QString value, fieldValues)
00302 addFieldValue (fieldName, value);
00303 }
00304
00312 QStringList Header::fieldValues (const QString &fieldName) const
00313 {
00314 QString nameLower (fieldName.toLower());
00315 if (!d->fields.contains (nameLower))
00316 return QStringList();
00317 else
00318 return d->fields [nameLower].fieldValues;
00319 }
00320
00326 void Header::removeField (const QString &fieldName)
00327 {
00328 QString nameLower (fieldName.toLower());
00329 if (d->fields.contains (nameLower)) {
00330 d->fields.remove (nameLower);
00331 d->orderedFieldList.removeAt (d->orderedFieldList.indexOf (nameLower));
00332 }
00333 }
00334
00343 bool Header::parseLine (const QString &line, int)
00344 {
00345 int i = line.indexOf(':');
00346 if (i == -1)
00347 return false;
00348
00349 addFieldValues (line.left (i).trimmed (),
00350 line.mid (i + 1).split (",", QString::SkipEmptyParts));
00351 return true;
00352 }
00353
00361 QString Header::toString() const
00362 {
00363 if (!isValid())
00364 return "";
00365
00366 QString ret = "";
00367
00368 foreach (QString fieldName, d->orderedFieldList) {
00369 int oldLength = ret.length();
00370 ret += d->fields [fieldName].originalCaseFieldName + ":";
00371 foreach (QString value, d->fields [fieldName].fieldValues) {
00372
00373 if (ret.length() - oldLength + value.length() + 1 > 80) {
00374
00375 oldLength = ret.length() + 2;
00376 ret += "\r\n\t" + value.trimmed() + ",";
00377 }
00378 else
00379 ret += " " + value.trimmed() + ",";
00380 }
00381 if (d->fields [fieldName].fieldValues.size() > 0)
00382 ret.chop(1);
00383 ret += "\r\n";
00384 }
00385 return ret;
00386 }