data/ICalendar.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ICalendar.h" | ||
| 2 | |||
| 3 | #include <QLoggingCategory> | ||
| 4 | |||
| 5 |
4/7✓ Branch 2 → 3 taken 17 times.
✓ Branch 2 → 8 taken 3905 times.
✓ Branch 4 → 5 taken 17 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 17 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
3922 | Q_LOGGING_CATEGORY(lcICal, "mailjd.calendar.ical") |
| 6 | |||
| 7 | namespace ICal { | ||
| 8 | |||
| 9 | namespace { | ||
| 10 | |||
| 11 | // RFC 6868: a parameter value cannot hold DQUOTE or a line break; they are | ||
| 12 | // written as ^' and ^n, and ^ itself as ^^. S106-128: a DQUOTE written raw | ||
| 13 | // (e.g. in an attendee's CN) ended the quoted value early, and the rest of | ||
| 14 | // the name re-parsed as further parameters (a forged PARTSTAT). | ||
| 15 | 9722 | QString encodeParameterValue(const QString &value) { | |
| 16 | 9722 | QString out; | |
| 17 |
1/1✓ Branch 3 → 4 taken 9722 times.
|
9722 | out.reserve(value.size()); |
| 18 |
2/2✓ Branch 66 → 5 taken 53070 times.
✓ Branch 66 → 67 taken 9722 times.
|
62792 | for (int i = 0; i < value.size(); ++i) { |
| 19 | 53070 | const QChar c = value.at(i); | |
| 20 |
3/3✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 17 taken 53068 times.
✓ Branch 13 → 14 taken 2 times.
|
53072 | if (c == QLatin1Char('^')) out += QStringLiteral("^^"); |
| 21 |
3/3✓ Branch 20 → 21 taken 162 times.
✓ Branch 20 → 28 taken 52906 times.
✓ Branch 24 → 25 taken 162 times.
|
53230 | else if (c == QLatin1Char('"')) out += QStringLiteral("^'"); |
| 22 |
2/8✗ Branch 31 → 32 not taken.
✓ Branch 31 → 40 taken 52906 times.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 40 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 40 not taken.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 52906 times.
|
52906 | else if (c == QLatin1Char('\r') && i + 1 < value.size() && value.at(i + 1) == QLatin1Char('\n')) continue; |
| 23 |
6/7✓ Branch 46 → 47 taken 52905 times.
✓ Branch 46 → 51 taken 1 time.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 52905 times.
✓ Branch 53 → 54 taken 1 time.
✓ Branch 53 → 61 taken 52905 times.
✓ Branch 57 → 58 taken 1 time.
|
52907 | else if (c == QLatin1Char('\n') || c == QLatin1Char('\r')) out += QStringLiteral("^n"); |
| 24 |
1/1✓ Branch 61 → 62 taken 52905 times.
|
52905 | else out += c; |
| 25 | } | ||
| 26 | 9722 | return out; | |
| 27 | ✗ | } | |
| 28 | |||
| 29 | 205859 | QString decodeParameterValue(const QString &value) { | |
| 30 |
3/3✓ Branch 4 → 5 taken 205859 times.
✓ Branch 5 → 6 taken 205710 times.
✓ Branch 5 → 7 taken 149 times.
|
205859 | if (!value.contains(QLatin1Char('^'))) return value; |
| 31 | 149 | QString out; | |
| 32 |
1/1✓ Branch 8 → 9 taken 149 times.
|
149 | out.reserve(value.size()); |
| 33 |
2/2✓ Branch 63 → 10 taken 1787 times.
✓ Branch 63 → 64 taken 149 times.
|
1936 | for (int i = 0; i < value.size(); ++i) { |
| 34 | 1787 | const QChar c = value.at(i); | |
| 35 |
2/2✓ Branch 12 → 13 taken 1782 times.
✓ Branch 12 → 14 taken 5 times.
|
1787 | const QChar next = i + 1 < value.size() ? value.at(i + 1) : QChar(); |
| 36 |
7/7✓ Branch 18 → 19 taken 296 times.
✓ Branch 18 → 24 taken 1491 times.
✓ Branch 22 → 23 taken 2 times.
✓ Branch 22 → 24 taken 294 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 25 → 30 taken 1785 times.
✓ Branch 28 → 29 taken 2 times.
|
1787 | if (c == QLatin1Char('^') && next == QLatin1Char('^')) { out += QLatin1Char('^'); ++i; } |
| 37 |
7/7✓ Branch 33 → 34 taken 294 times.
✓ Branch 33 → 39 taken 1491 times.
✓ Branch 37 → 38 taken 292 times.
✓ Branch 37 → 39 taken 2 times.
✓ Branch 40 → 41 taken 292 times.
✓ Branch 40 → 45 taken 1493 times.
✓ Branch 43 → 44 taken 292 times.
|
1785 | else if (c == QLatin1Char('^') && next == QLatin1Char('\'')) { out += QLatin1Char('"'); ++i; } |
| 38 |
7/7✓ Branch 48 → 49 taken 2 times.
✓ Branch 48 → 54 taken 1491 times.
✓ Branch 52 → 53 taken 1 time.
✓ Branch 52 → 54 taken 1 time.
✓ Branch 55 → 56 taken 1 time.
✓ Branch 55 → 60 taken 1492 times.
✓ Branch 58 → 59 taken 1 time.
|
1493 | else if (c == QLatin1Char('^') && next == QLatin1Char('n')) { out += QLatin1Char('\n'); ++i; } |
| 39 |
1/1✓ Branch 60 → 61 taken 1492 times.
|
1492 | else out += c; // any other ^ stays literal (RFC 6868 §3) |
| 40 | } | ||
| 41 | 149 | return out; | |
| 42 | 149 | } | |
| 43 | |||
| 44 | // RFC 5545 §3.2: parameter values containing COLON, SEMICOLON or COMMA | ||
| 45 | // must be quoted. | ||
| 46 | 9722 | QString renderParameterValue(const QString &raw) { | |
| 47 |
1/1✓ Branch 2 → 3 taken 9722 times.
|
9722 | const QString value = encodeParameterValue(raw); |
| 48 |
6/6✓ Branch 5 → 6 taken 9722 times.
✓ Branch 6 → 7 taken 9607 times.
✓ Branch 6 → 15 taken 115 times.
✓ Branch 9 → 10 taken 9607 times.
✓ Branch 10 → 11 taken 9605 times.
✓ Branch 10 → 15 taken 2 times.
|
19327 | if (value.contains(QLatin1Char(':')) || value.contains(QLatin1Char(';')) || |
| 49 |
5/5✓ Branch 13 → 14 taken 9605 times.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 9604 times.
✓ Branch 17 → 18 taken 118 times.
✓ Branch 17 → 27 taken 9604 times.
|
19327 | value.contains(QLatin1Char(','))) |
| 50 |
2/2✓ Branch 22 → 23 taken 118 times.
✓ Branch 23 → 24 taken 118 times.
|
236 | return QLatin1Char('"') + value + QLatin1Char('"'); |
| 51 | 9604 | return value; | |
| 52 | 9722 | } | |
| 53 | |||
| 54 | 205859 | QString unquote(const QString &value) { | |
| 55 |
5/5✓ Branch 3 → 4 taken 191127 times.
✓ Branch 3 → 13 taken 14732 times.
✓ Branch 6 → 7 taken 191127 times.
✓ Branch 7 → 8 taken 4145 times.
✓ Branch 7 → 13 taken 186982 times.
|
210004 | if (value.size() >= 2 && value.startsWith(QLatin1Char('"')) && |
| 56 |
5/5✓ Branch 10 → 11 taken 4145 times.
✓ Branch 11 → 12 taken 3579 times.
✓ Branch 11 → 13 taken 566 times.
✓ Branch 14 → 15 taken 3579 times.
✓ Branch 14 → 17 taken 202280 times.
|
210004 | value.endsWith(QLatin1Char('"'))) |
| 57 | 3579 | return value.mid(1, value.size() - 2); | |
| 58 | 202280 | return value; | |
| 59 | } | ||
| 60 | |||
| 61 | // Splits "NAME;P1=a;P2="x:y":value" at the first colon outside quotes. | ||
| 62 | 1320727 | bool parseContentLine(const QString &line, Property *property) { | |
| 63 | 1320727 | bool inQuotes = false; | |
| 64 | 1320727 | int colon = -1; | |
| 65 |
2/2✓ Branch 20 → 3 taken 13592801 times.
✓ Branch 20 → 21 taken 1527 times.
|
13594328 | for (int i = 0; i < line.size(); ++i) { |
| 66 | 13592801 | const QChar c = line.at(i); | |
| 67 |
2/2✓ Branch 7 → 8 taken 8705 times.
✓ Branch 7 → 9 taken 13584096 times.
|
13592801 | if (c == QLatin1Char('"')) |
| 68 | 8705 | inQuotes = !inQuotes; | |
| 69 |
6/6✓ Branch 12 → 13 taken 1322882 times.
✓ Branch 12 → 15 taken 12261214 times.
✓ Branch 13 → 14 taken 1319200 times.
✓ Branch 13 → 15 taken 3682 times.
✓ Branch 16 → 17 taken 1319200 times.
✓ Branch 16 → 18 taken 12264896 times.
|
13584096 | else if (c == QLatin1Char(':') && !inQuotes) { |
| 70 | 1319200 | colon = i; | |
| 71 | 1319200 | break; | |
| 72 | } | ||
| 73 | } | ||
| 74 |
2/2✓ Branch 21 → 22 taken 1564 times.
✓ Branch 21 → 23 taken 1319163 times.
|
1320727 | if (colon <= 0) |
| 75 | 1564 | return false; | |
| 76 |
1/1✓ Branch 23 → 24 taken 1319163 times.
|
1319163 | const QString head = line.left(colon); |
| 77 |
1/1✓ Branch 24 → 25 taken 1319163 times.
|
1319163 | property->value = line.mid(colon + 1); |
| 78 | 1319163 | property->originalLine = line; | |
| 79 | 1319163 | QStringList parts; | |
| 80 | 1319163 | QString current; | |
| 81 | 1319163 | inQuotes = false; | |
| 82 |
2/2✓ Branch 47 → 30 taken 10049409 times.
✓ Branch 47 → 48 taken 1319163 times.
|
11368572 | for (const QChar c : head) { |
| 83 |
2/2✓ Branch 33 → 34 taken 8470 times.
✓ Branch 33 → 35 taken 10040939 times.
|
10049409 | if (c == QLatin1Char('"')) { |
| 84 | 8470 | inQuotes = !inQuotes; | |
| 85 |
1/1✓ Branch 34 → 46 taken 8470 times.
|
8470 | current += c; |
| 86 |
6/6✓ Branch 38 → 39 taken 208126 times.
✓ Branch 38 → 41 taken 9832813 times.
✓ Branch 39 → 40 taken 207382 times.
✓ Branch 39 → 41 taken 744 times.
✓ Branch 42 → 43 taken 207382 times.
✓ Branch 42 → 45 taken 9833557 times.
|
10040939 | } else if (c == QLatin1Char(';') && !inQuotes) { |
| 87 |
1/1✓ Branch 43 → 44 taken 207382 times.
|
207382 | parts.append(current); |
| 88 | 207382 | current.clear(); | |
| 89 | } else { | ||
| 90 |
1/1✓ Branch 45 → 46 taken 9833557 times.
|
9833557 | current += c; |
| 91 | } | ||
| 92 | } | ||
| 93 |
1/1✓ Branch 48 → 49 taken 1319163 times.
|
1319163 | parts.append(current); |
| 94 |
3/3✓ Branch 49 → 50 taken 1319163 times.
✓ Branch 50 → 51 taken 1319163 times.
✓ Branch 51 → 52 taken 1319163 times.
|
1319163 | property->name = parts.first().trimmed().toUpper(); |
| 95 |
2/2✓ Branch 56 → 57 taken 76 times.
✓ Branch 56 → 58 taken 1319087 times.
|
1319163 | if (property->name.isEmpty()) |
| 96 | 76 | return false; | |
| 97 |
2/2✓ Branch 100 → 59 taken 207234 times.
✓ Branch 100 → 101 taken 1319087 times.
|
1526321 | for (int i = 1; i < parts.size(); ++i) { |
| 98 | 207234 | const int eq = parts.at(i).indexOf(QLatin1Char('=')); | |
| 99 | 207234 | Parameter parameter; | |
| 100 |
2/2✓ Branch 63 → 64 taken 1375 times.
✓ Branch 63 → 71 taken 205859 times.
|
207234 | if (eq < 0) { |
| 101 |
2/2✓ Branch 65 → 66 taken 1375 times.
✓ Branch 66 → 67 taken 1375 times.
|
1375 | parameter.name = parts.at(i).trimmed().toUpper(); |
| 102 | } else { | ||
| 103 |
3/3✓ Branch 72 → 73 taken 205859 times.
✓ Branch 73 → 74 taken 205859 times.
✓ Branch 74 → 75 taken 205859 times.
|
205859 | parameter.name = parts.at(i).left(eq).trimmed().toUpper(); |
| 104 |
3/3✓ Branch 80 → 81 taken 205859 times.
✓ Branch 81 → 82 taken 205859 times.
✓ Branch 82 → 83 taken 205859 times.
|
205859 | parameter.value = decodeParameterValue(unquote(parts.at(i).mid(eq + 1))); |
| 105 |
1/2✗ Branch 88 → 89 not taken.
✓ Branch 88 → 96 taken 205859 times.
|
205859 | if (parameter.value.isNull()) |
| 106 | ✗ | parameter.value = QStringLiteral(""); // "NAME=" keeps its equals sign | |
| 107 | } | ||
| 108 |
1/1✓ Branch 96 → 97 taken 207234 times.
|
207234 | property->parameters.append(parameter); |
| 109 | 207234 | } | |
| 110 | 1319087 | return true; | |
| 111 | 1319163 | } | |
| 112 | |||
| 113 | // `orphans` counts continuation lines with no line to continue (S106-142): | ||
| 114 | // they are dropped like malformed lines and make the parse lossy. | ||
| 115 | 142382 | QStringList unfoldLines(const QString &text, int *orphans) { | |
| 116 | 142382 | QStringList lines; | |
| 117 | 142382 | QString normalized = text; | |
| 118 |
1/1✓ Branch 9 → 10 taken 142382 times.
|
284764 | normalized.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); |
| 119 |
1/1✓ Branch 18 → 19 taken 142382 times.
|
142382 | normalized.replace(QLatin1Char('\r'), QLatin1Char('\n')); |
| 120 |
5/5✓ Branch 22 → 23 taken 142382 times.
✓ Branch 23 → 24 taken 142382 times.
✓ Branch 24 → 25 taken 142382 times.
✓ Branch 56 → 26 taken 1586871 times.
✓ Branch 56 → 57 taken 142382 times.
|
1729253 | for (const QString &raw : normalized.split(QLatin1Char('\n'))) { |
| 121 |
7/8✓ Branch 28 → 29 taken 1444847 times.
✓ Branch 28 → 40 taken 142024 times.
✓ Branch 33 → 34 taken 1440745 times.
✓ Branch 33 → 39 taken 4102 times.
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 40 taken 1440745 times.
✓ Branch 41 → 42 taken 4102 times.
✓ Branch 41 → 51 taken 1582769 times.
|
1586871 | if (!raw.isEmpty() && (raw.at(0) == QLatin1Char(' ') || raw.at(0) == QLatin1Char('\t'))) { |
| 122 |
2/2✓ Branch 43 → 44 taken 4101 times.
✓ Branch 43 → 49 taken 1 time.
|
4102 | if (!lines.isEmpty()) |
| 123 |
3/3✓ Branch 44 → 45 taken 4101 times.
✓ Branch 45 → 46 taken 4101 times.
✓ Branch 46 → 47 taken 4101 times.
|
4101 | lines.last() += raw.mid(1); |
| 124 | else | ||
| 125 | 1 | ++*orphans; | |
| 126 | 4102 | continue; | |
| 127 | } | ||
| 128 |
2/2✓ Branch 52 → 53 taken 1440745 times.
✓ Branch 52 → 54 taken 142024 times.
|
1582769 | if (!raw.isEmpty()) |
| 129 |
1/1✓ Branch 53 → 54 taken 1440745 times.
|
1440745 | lines.append(raw); |
| 130 | 142382 | } | |
| 131 | 142382 | return lines; | |
| 132 | 142382 | } | |
| 133 | |||
| 134 | 42039 | void serializeInto(const Component &component, QString *out) { | |
| 135 |
3/3✓ Branch 5 → 6 taken 42039 times.
✓ Branch 6 → 7 taken 42039 times.
✓ Branch 7 → 8 taken 42039 times.
|
84078 | *out += foldLine(QStringLiteral("BEGIN:") + component.name); |
| 136 |
2/2✓ Branch 22 → 14 taken 314604 times.
✓ Branch 22 → 23 taken 42039 times.
|
356643 | for (const Property &property : component.properties) |
| 137 |
3/3✓ Branch 15 → 16 taken 314604 times.
✓ Branch 16 → 17 taken 314604 times.
✓ Branch 17 → 18 taken 314604 times.
|
314604 | *out += foldLine(property.contentLine()); |
| 138 |
2/2✓ Branch 29 → 25 taken 9814 times.
✓ Branch 29 → 30 taken 42039 times.
|
51853 | for (const Component &child : component.components) |
| 139 |
1/1✓ Branch 26 → 27 taken 9814 times.
|
9814 | serializeInto(child, out); |
| 140 |
3/3✓ Branch 33 → 34 taken 42039 times.
✓ Branch 34 → 35 taken 42039 times.
✓ Branch 35 → 36 taken 42039 times.
|
84078 | *out += foldLine(QStringLiteral("END:") + component.name); |
| 141 | 42039 | } | |
| 142 | |||
| 143 | } // namespace | ||
| 144 | |||
| 145 | // ─── Property ────────────────────────────────────────────── | ||
| 146 | |||
| 147 | 488626 | QString Property::parameter(const QString ¶meterName) const { | |
| 148 |
2/2✓ Branch 11 → 4 taken 436121 times.
✓ Branch 11 → 12 taken 404913 times.
|
841034 | for (const Parameter ¶meter : parameters) |
| 149 |
2/2✓ Branch 6 → 7 taken 83713 times.
✓ Branch 6 → 9 taken 352408 times.
|
436121 | if (parameter.name.compare(parameterName, Qt::CaseInsensitive) == 0) |
| 150 | 83713 | return parameter.value; | |
| 151 | 404913 | return {}; | |
| 152 | } | ||
| 153 | |||
| 154 | 269216 | bool Property::hasParameter(const QString ¶meterName) const { | |
| 155 |
2/2✓ Branch 10 → 4 taken 83870 times.
✓ Branch 10 → 11 taken 268338 times.
|
352208 | for (const Parameter ¶meter : parameters) |
| 156 |
2/2✓ Branch 6 → 7 taken 878 times.
✓ Branch 6 → 8 taken 82992 times.
|
83870 | if (parameter.name.compare(parameterName, Qt::CaseInsensitive) == 0) |
| 157 | 878 | return true; | |
| 158 | 268338 | return false; | |
| 159 | } | ||
| 160 | |||
| 161 | 791 | void Property::setParameter(const QString ¶meterName, const QString ¶meterValue) { | |
| 162 | 791 | originalLine.clear(); | |
| 163 |
1/1✓ Branch 3 → 4 taken 791 times.
|
791 | const QString upper = parameterName.toUpper(); |
| 164 |
4/4✓ Branch 4 → 5 taken 791 times.
✓ Branch 5 → 6 taken 791 times.
✓ Branch 14 → 7 taken 336 times.
✓ Branch 14 → 15 taken 747 times.
|
1083 | for (Parameter ¶meter : parameters) { |
| 165 |
2/2✓ Branch 9 → 10 taken 44 times.
✓ Branch 9 → 12 taken 292 times.
|
336 | if (parameter.name == upper) { |
| 166 | 44 | parameter.value = parameterValue; | |
| 167 | 44 | return; | |
| 168 | } | ||
| 169 | } | ||
| 170 | 747 | parameters.append({upper, parameterValue}); | |
| 171 | 1538 | } | |
| 172 | |||
| 173 | 27894 | void Property::removeParameter(const QString ¶meterName) { | |
| 174 |
1/1✓ Branch 2 → 3 taken 27894 times.
|
27894 | const QString upper = parameterName.toUpper(); |
| 175 |
1/1✓ Branch 3 → 4 taken 27894 times.
|
27894 | const auto removed = parameters.removeIf([&upper](const Parameter ¶meter) { |
| 176 | 385 | return parameter.name == upper; | |
| 177 | }); | ||
| 178 |
2/2✓ Branch 4 → 5 taken 193 times.
✓ Branch 4 → 6 taken 27701 times.
|
27894 | if (removed > 0) |
| 179 | 193 | originalLine.clear(); | |
| 180 | 27894 | } | |
| 181 | |||
| 182 | 3772 | void Property::setValue(const QString &newValue) { | |
| 183 |
6/6✓ Branch 3 → 4 taken 1160 times.
✓ Branch 3 → 7 taken 2612 times.
✓ Branch 5 → 6 taken 836 times.
✓ Branch 5 → 7 taken 324 times.
✓ Branch 8 → 9 taken 836 times.
✓ Branch 8 → 10 taken 2936 times.
|
3772 | if (newValue == value && !originalLine.isEmpty()) |
| 184 | 836 | return; | |
| 185 | 2936 | value = newValue; | |
| 186 | 2936 | originalLine.clear(); | |
| 187 | } | ||
| 188 | |||
| 189 | 513690 | QString Property::contentLine() const { | |
| 190 |
2/2✓ Branch 3 → 4 taken 394951 times.
✓ Branch 3 → 5 taken 118739 times.
|
513690 | if (!originalLine.isEmpty()) |
| 191 | 394951 | return originalLine; | |
| 192 | 118739 | QString line = name; | |
| 193 |
2/2✓ Branch 26 → 8 taken 9722 times.
✓ Branch 26 → 27 taken 118739 times.
|
128461 | for (const Parameter ¶meter : parameters) { |
| 194 |
2/2✓ Branch 11 → 12 taken 9722 times.
✓ Branch 12 → 13 taken 9722 times.
|
9722 | line += QLatin1Char(';') + parameter.name; |
| 195 |
1/2✓ Branch 15 → 16 taken 9722 times.
✗ Branch 15 → 24 not taken.
|
9722 | if (!parameter.value.isNull()) |
| 196 |
3/3✓ Branch 16 → 17 taken 9722 times.
✓ Branch 19 → 20 taken 9722 times.
✓ Branch 20 → 21 taken 9722 times.
|
9722 | line += QLatin1Char('=') + renderParameterValue(parameter.value); |
| 197 | } | ||
| 198 |
2/2✓ Branch 29 → 30 taken 118739 times.
✓ Branch 30 → 31 taken 118739 times.
|
118739 | line += QLatin1Char(':') + value; |
| 199 | 118739 | return line; | |
| 200 | 118739 | } | |
| 201 | |||
| 202 | // ─── Component ───────────────────────────────────────────── | ||
| 203 | |||
| 204 | 138286 | const Property *Component::property(const QString &propertyName) const { | |
| 205 |
2/2✓ Branch 10 → 4 taken 480983 times.
✓ Branch 10 → 11 taken 35917 times.
|
516900 | for (const Property &candidate : properties) |
| 206 |
2/2✓ Branch 6 → 7 taken 102369 times.
✓ Branch 6 → 8 taken 378614 times.
|
480983 | if (candidate.name == propertyName) |
| 207 | 102369 | return &candidate; | |
| 208 | 35917 | return nullptr; | |
| 209 | } | ||
| 210 | |||
| 211 | 5778 | Property *Component::property(const QString &propertyName) { | |
| 212 |
4/4✓ Branch 2 → 3 taken 5778 times.
✓ Branch 3 → 4 taken 5778 times.
✓ Branch 11 → 5 taken 22705 times.
✓ Branch 11 → 12 taken 3737 times.
|
26442 | for (Property &candidate : properties) |
| 213 |
2/2✓ Branch 7 → 8 taken 2041 times.
✓ Branch 7 → 9 taken 20664 times.
|
22705 | if (candidate.name == propertyName) |
| 214 | 2041 | return &candidate; | |
| 215 | 3737 | return nullptr; | |
| 216 | } | ||
| 217 | |||
| 218 | 10267 | QList<Property> Component::propertiesNamed(const QString &propertyName) const { | |
| 219 | 10267 | QList<Property> result; | |
| 220 |
2/2✓ Branch 10 → 4 taken 75078 times.
✓ Branch 10 → 11 taken 10267 times.
|
85345 | for (const Property &candidate : properties) |
| 221 |
2/2✓ Branch 6 → 7 taken 2103 times.
✓ Branch 6 → 8 taken 72975 times.
|
75078 | if (candidate.name == propertyName) |
| 222 |
1/1✓ Branch 7 → 8 taken 2103 times.
|
2103 | result.append(candidate); |
| 223 | 10267 | return result; | |
| 224 | ✗ | } | |
| 225 | |||
| 226 | 78561 | QString Component::value(const QString &propertyName) const { | |
| 227 | 78561 | const Property *found = property(propertyName); | |
| 228 |
2/2✓ Branch 3 → 4 taken 54455 times.
✓ Branch 3 → 5 taken 24106 times.
|
78561 | return found ? found->value : QString(); |
| 229 | } | ||
| 230 | |||
| 231 | 1651 | bool Component::hasProperty(const QString &propertyName) const { | |
| 232 | 1651 | return property(propertyName) != nullptr; | |
| 233 | } | ||
| 234 | |||
| 235 | 743 | void Component::setProperty(const Property &replacement) { | |
| 236 | 743 | bool replaced = false; | |
| 237 |
2/2✓ Branch 13 → 3 taken 3003 times.
✓ Branch 13 → 14 taken 743 times.
|
3746 | for (int i = 0; i < properties.size();) { |
| 238 |
2/2✓ Branch 5 → 6 taken 2873 times.
✓ Branch 5 → 7 taken 130 times.
|
3003 | if (properties.at(i).name != replacement.name) { |
| 239 | 2873 | ++i; | |
| 240 | 2873 | continue; | |
| 241 | } | ||
| 242 |
1/2✓ Branch 7 → 8 taken 130 times.
✗ Branch 7 → 11 not taken.
|
130 | if (!replaced) { |
| 243 | 130 | properties[i] = replacement; | |
| 244 | 130 | replaced = true; | |
| 245 | 130 | ++i; | |
| 246 | } else { | ||
| 247 | ✗ | properties.removeAt(i); | |
| 248 | } | ||
| 249 | } | ||
| 250 |
2/2✓ Branch 14 → 15 taken 613 times.
✓ Branch 14 → 16 taken 130 times.
|
743 | if (!replaced) |
| 251 | 613 | properties.append(replacement); | |
| 252 | 743 | } | |
| 253 | |||
| 254 | 3374 | void Component::setPropertyValue(const QString &propertyName, const QString &newValue) { | |
| 255 |
1/1✓ Branch 2 → 3 taken 3374 times.
|
3374 | Property *existing = property(propertyName); |
| 256 |
2/2✓ Branch 3 → 4 taken 1046 times.
✓ Branch 3 → 7 taken 2328 times.
|
3374 | if (existing) { |
| 257 | 1046 | existing->setValue(newValue); | |
| 258 | // Drop duplicates of a single-valued property. | ||
| 259 | 1046 | bool seen = false; | |
| 260 |
1/1✓ Branch 5 → 6 taken 1046 times.
|
1046 | properties.removeIf([&](const Property &candidate) { |
| 261 |
2/2✓ Branch 3 → 4 taken 6797 times.
✓ Branch 3 → 5 taken 1046 times.
|
7843 | if (candidate.name != propertyName) |
| 262 | 6797 | return false; | |
| 263 |
1/2✓ Branch 5 → 6 taken 1046 times.
✗ Branch 5 → 7 not taken.
|
1046 | if (!seen) { |
| 264 | 1046 | seen = true; | |
| 265 | 1046 | return false; | |
| 266 | } | ||
| 267 | ✗ | return true; | |
| 268 | }); | ||
| 269 | 1046 | return; | |
| 270 | } | ||
| 271 | 2328 | Property created; | |
| 272 | 2328 | created.name = propertyName; | |
| 273 | 2328 | created.value = newValue; | |
| 274 |
1/1✓ Branch 9 → 10 taken 2328 times.
|
2328 | properties.append(created); |
| 275 | 2328 | } | |
| 276 | |||
| 277 | 3151 | int Component::removeProperties(const QString &propertyName) { | |
| 278 | 3151 | return int(properties.removeIf([&propertyName](const Property &candidate) { | |
| 279 | 12394 | return candidate.name == propertyName; | |
| 280 | 3151 | })); | |
| 281 | } | ||
| 282 | |||
| 283 | 9143 | QList<Component> Component::componentsNamed(const QString &componentName) const { | |
| 284 | 9143 | QList<Component> result; | |
| 285 |
2/2✓ Branch 10 → 4 taken 18541 times.
✓ Branch 10 → 11 taken 9143 times.
|
27684 | for (const Component &child : components) |
| 286 |
2/2✓ Branch 6 → 7 taken 2749 times.
✓ Branch 6 → 8 taken 15792 times.
|
18541 | if (child.name == componentName) |
| 287 |
1/1✓ Branch 7 → 8 taken 2749 times.
|
2749 | result.append(child); |
| 288 | 9143 | return result; | |
| 289 | ✗ | } | |
| 290 | |||
| 291 | 1548 | int Component::removeComponents(const QString &componentName) { | |
| 292 | 1548 | return int(components.removeIf([&componentName](const Component &child) { | |
| 293 | 6575 | return child.name == componentName; | |
| 294 | 1548 | })); | |
| 295 | } | ||
| 296 | |||
| 297 | // ─── Parse / serialize ───────────────────────────────────── | ||
| 298 | |||
| 299 | 142382 | bool parse(const QString &text, QList<Component> *components, QString *error, int *skippedLines) { | |
| 300 |
2/2✓ Branch 2 → 3 taken 106112 times.
✓ Branch 2 → 4 taken 36270 times.
|
142382 | if (skippedLines) |
| 301 | 106112 | *skippedLines = 0; | |
| 302 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 14 taken 142382 times.
|
142382 | if (!components) { |
| 303 | ✗ | if (error) *error = QStringLiteral("No output component list"); | |
| 304 | ✗ | return false; | |
| 305 | } | ||
| 306 |
1/1✓ Branch 14 → 15 taken 142382 times.
|
142382 | components->clear(); |
| 307 | 142382 | QList<Component> stack; | |
| 308 | 142382 | int orphans = 0; | |
| 309 |
1/1✓ Branch 15 → 16 taken 142382 times.
|
142382 | const QStringList lines = unfoldLines(text, &orphans); |
| 310 |
2/2✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 31 taken 142381 times.
|
142382 | if (orphans > 0) { |
| 311 |
7/7✓ Branch 17 → 18 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 28 → 19 taken 1 time.
✓ Branch 28 → 29 taken 1 time.
|
2 | qCWarning(lcICal) << "Skipping" << orphans << "continuation lines before the first line"; |
| 312 |
1/2✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 31 not taken.
|
1 | if (skippedLines) |
| 313 | 1 | *skippedLines += orphans; | |
| 314 | } | ||
| 315 |
2/2✓ Branch 157 → 33 taken 1320727 times.
✓ Branch 157 → 158 taken 142164 times.
|
1462891 | for (const QString &line : lines) { |
| 316 | 1320727 | Property property; | |
| 317 |
3/3✓ Branch 34 → 35 taken 1320727 times.
✓ Branch 35 → 36 taken 1640 times.
✓ Branch 35 → 65 taken 1319087 times.
|
1320727 | if (!parseContentLine(line, &property)) { |
| 318 | // Content only at debug level: lines carry calendar and contact data. | ||
| 319 |
7/7✓ Branch 36 → 37 taken 1640 times.
✓ Branch 40 → 41 taken 1640 times.
✓ Branch 41 → 42 taken 1640 times.
✓ Branch 43 → 44 taken 1640 times.
✓ Branch 44 → 45 taken 1640 times.
✓ Branch 48 → 38 taken 1640 times.
✓ Branch 48 → 49 taken 1640 times.
|
3280 | qCWarning(lcICal) << "Skipping malformed content line of" << line.size() << "characters"; |
| 320 |
7/7✓ Branch 49 → 50 taken 1640 times.
✓ Branch 53 → 54 taken 1640 times.
✓ Branch 54 → 55 taken 1640 times.
✓ Branch 55 → 56 taken 1640 times.
✓ Branch 56 → 57 taken 1640 times.
✓ Branch 61 → 51 taken 1640 times.
✓ Branch 61 → 62 taken 1640 times.
|
3280 | qCDebug(lcICal) << "Malformed line:" << line.left(80); |
| 321 |
2/2✓ Branch 62 → 63 taken 1505 times.
✓ Branch 62 → 64 taken 135 times.
|
1640 | if (skippedLines) |
| 322 | 1505 | ++*skippedLines; | |
| 323 | 1640 | continue; | |
| 324 | 1640 | } | |
| 325 |
2/2✓ Branch 67 → 68 taken 192726 times.
✓ Branch 67 → 91 taken 1126361 times.
|
1319087 | if (property.name == QLatin1String("BEGIN")) { |
| 326 |
2/2✓ Branch 69 → 70 taken 1 time.
✓ Branch 69 → 82 taken 192725 times.
|
192726 | if (stack.size() >= kMaxComponentDepth) { |
| 327 |
1/2✓ Branch 70 → 71 taken 1 time.
✗ Branch 70 → 81 not taken.
|
1 | if (error) |
| 328 |
1/1✓ Branch 75 → 76 taken 1 time.
|
2 | *error = QStringLiteral("iCalendar components nested deeper than %1 levels").arg(kMaxComponentDepth); |
| 329 | 1 | return false; | |
| 330 | } | ||
| 331 | 192725 | Component component; | |
| 332 |
2/2✓ Branch 82 → 83 taken 192725 times.
✓ Branch 83 → 84 taken 192725 times.
|
192725 | component.name = property.value.trimmed().toUpper(); |
| 333 |
1/1✓ Branch 87 → 88 taken 192725 times.
|
192725 | stack.append(component); |
| 334 | 192725 | continue; | |
| 335 | 192725 | } | |
| 336 |
2/2✓ Branch 93 → 94 taken 191209 times.
✓ Branch 93 → 130 taken 935152 times.
|
1126361 | if (property.name == QLatin1String("END")) { |
| 337 |
2/2✓ Branch 94 → 95 taken 191209 times.
✓ Branch 95 → 96 taken 191209 times.
|
191209 | const QString name = property.value.trimmed().toUpper(); |
| 338 |
7/7✓ Branch 98 → 99 taken 191153 times.
✓ Branch 98 → 102 taken 56 times.
✓ Branch 99 → 100 taken 191153 times.
✓ Branch 101 → 102 taken 161 times.
✓ Branch 101 → 103 taken 190992 times.
✓ Branch 104 → 105 taken 217 times.
✓ Branch 104 → 117 taken 190992 times.
|
191209 | if (stack.isEmpty() || stack.last().name != name) { |
| 339 |
2/2✓ Branch 105 → 106 taken 2 times.
✓ Branch 105 → 116 taken 215 times.
|
217 | if (error) |
| 340 |
1/1✓ Branch 110 → 111 taken 2 times.
|
4 | *error = QStringLiteral("Unbalanced END:%1 in iCalendar data").arg(name); |
| 341 | 217 | return false; | |
| 342 | } | ||
| 343 |
1/1✓ Branch 117 → 118 taken 190992 times.
|
190992 | Component finished = stack.takeLast(); |
| 344 |
2/2✓ Branch 119 → 120 taken 140837 times.
✓ Branch 119 → 121 taken 50155 times.
|
190992 | if (stack.isEmpty()) |
| 345 |
1/1✓ Branch 120 → 123 taken 140837 times.
|
140837 | components->append(finished); |
| 346 | else | ||
| 347 |
2/2✓ Branch 121 → 122 taken 50155 times.
✓ Branch 122 → 123 taken 50155 times.
|
50155 | stack.last().components.append(finished); |
| 348 | 190992 | continue; | |
| 349 | 382201 | } | |
| 350 |
2/2✓ Branch 131 → 132 taken 641 times.
✓ Branch 131 → 146 taken 934511 times.
|
935152 | if (stack.isEmpty()) { |
| 351 |
6/6✓ Branch 132 → 133 taken 641 times.
✓ Branch 136 → 137 taken 641 times.
✓ Branch 137 → 138 taken 641 times.
✓ Branch 138 → 139 taken 641 times.
✓ Branch 142 → 134 taken 641 times.
✓ Branch 142 → 143 taken 641 times.
|
1282 | qCWarning(lcICal) << "Skipping iCalendar property outside a component" << property.name; |
| 352 |
1/2✓ Branch 143 → 144 taken 641 times.
✗ Branch 143 → 145 not taken.
|
641 | if (skippedLines) |
| 353 | 641 | ++*skippedLines; | |
| 354 | 641 | continue; | |
| 355 | 641 | } | |
| 356 |
2/2✓ Branch 146 → 147 taken 934511 times.
✓ Branch 147 → 148 taken 934511 times.
|
934511 | stack.last().properties.append(property); |
| 357 | 1320727 | } | |
| 358 |
2/2✓ Branch 159 → 160 taken 1146 times.
✓ Branch 159 → 173 taken 141018 times.
|
142164 | if (!stack.isEmpty()) { |
| 359 |
2/2✓ Branch 160 → 161 taken 8 times.
✓ Branch 160 → 172 taken 1138 times.
|
1146 | if (error) |
| 360 |
2/2✓ Branch 165 → 166 taken 8 times.
✓ Branch 166 → 167 taken 8 times.
|
16 | *error = QStringLiteral("Missing END:%1 in iCalendar data").arg(stack.last().name); |
| 361 | 1146 | return false; | |
| 362 | } | ||
| 363 | 141018 | return true; | |
| 364 | 142382 | } | |
| 365 | |||
| 366 | 9489 | Component parseFirst(const QString &text, const QString &name, QString *error) { | |
| 367 | 9489 | QList<Component> components; | |
| 368 |
3/3✓ Branch 2 → 3 taken 9489 times.
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 9486 times.
|
9489 | if (!parse(text, &components, error)) |
| 369 | 3 | return {}; | |
| 370 |
4/4✓ Branch 5 → 6 taken 9486 times.
✓ Branch 6 → 7 taken 9486 times.
✓ Branch 15 → 8 taken 9317 times.
✓ Branch 15 → 16 taken 171 times.
|
9488 | for (const Component &component : components) |
| 371 |
2/2✓ Branch 10 → 11 taken 9315 times.
✓ Branch 10 → 13 taken 2 times.
|
9317 | if (component.name == name) |
| 372 | 9315 | return component; | |
| 373 |
2/2✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 27 taken 168 times.
|
171 | if (error) |
| 374 |
1/1✓ Branch 21 → 22 taken 3 times.
|
6 | *error = QStringLiteral("No %1 component in iCalendar data").arg(name); |
| 375 | 171 | return {}; | |
| 376 | 9489 | } | |
| 377 | |||
| 378 | 32225 | QString serialize(const Component &component) { | |
| 379 | 32225 | QString out; | |
| 380 |
1/1✓ Branch 2 → 3 taken 32225 times.
|
32225 | serializeInto(component, &out); |
| 381 | 32225 | return out; | |
| 382 | ✗ | } | |
| 383 | |||
| 384 | 398736 | QString foldLine(const QString &line) { | |
| 385 |
1/1✓ Branch 2 → 3 taken 398736 times.
|
398736 | const QByteArray utf8 = line.toUtf8(); |
| 386 |
2/2✓ Branch 4 → 5 taken 395759 times.
✓ Branch 4 → 13 taken 2977 times.
|
398736 | if (utf8.size() <= 75) |
| 387 |
1/1✓ Branch 8 → 9 taken 395759 times.
|
395759 | return line + QStringLiteral("\r\n"); |
| 388 | 2977 | QByteArray folded; | |
| 389 | 2977 | int lineOctets = 0; | |
| 390 | 2977 | int limit = 75; | |
| 391 |
2/2✓ Branch 31 → 14 taken 37632298 times.
✓ Branch 31 → 32 taken 2977 times.
|
37635275 | for (int i = 0; i < utf8.size();) { |
| 392 | // Length of the UTF-8 sequence starting at i. | ||
| 393 | 37632298 | const auto lead = static_cast<unsigned char>(utf8.at(i)); | |
| 394 | 37632298 | int length = 1; | |
| 395 |
2/2✓ Branch 15 → 16 taken 33 times.
✓ Branch 15 → 17 taken 37632265 times.
|
37632298 | if (lead >= 0xF0) length = 4; |
| 396 |
2/2✓ Branch 17 → 18 taken 262 times.
✓ Branch 17 → 19 taken 37632003 times.
|
37632265 | else if (lead >= 0xE0) length = 3; |
| 397 |
2/2✓ Branch 19 → 20 taken 1818 times.
✓ Branch 19 → 21 taken 37630185 times.
|
37632003 | else if (lead >= 0xC0) length = 2; |
| 398 | 37632298 | length = qMin(length, int(utf8.size()) - i); | |
| 399 |
2/2✓ Branch 23 → 24 taken 507435 times.
✓ Branch 23 → 26 taken 37124863 times.
|
37632298 | if (lineOctets + length > limit) { |
| 400 |
1/1✓ Branch 24 → 25 taken 507435 times.
|
507435 | folded += "\r\n "; |
| 401 | 507435 | lineOctets = 0; | |
| 402 | 507435 | limit = 74; // the leading space counts towards the 75 octets | |
| 403 | } | ||
| 404 |
2/2✓ Branch 26 → 27 taken 37632298 times.
✓ Branch 27 → 28 taken 37632298 times.
|
37632298 | folded += utf8.mid(i, length); |
| 405 | 37632298 | lineOctets += length; | |
| 406 | 37632298 | i += length; | |
| 407 | } | ||
| 408 |
1/1✓ Branch 32 → 33 taken 2977 times.
|
2977 | folded += "\r\n"; |
| 409 |
1/1✓ Branch 33 → 34 taken 2977 times.
|
2977 | return QString::fromUtf8(folded); |
| 410 | 398736 | } | |
| 411 | |||
| 412 | 484591 | QString unescapeText(const QString &value) { | |
| 413 | 484591 | QString result; | |
| 414 |
1/1✓ Branch 3 → 4 taken 484591 times.
|
484591 | result.reserve(value.size()); |
| 415 |
2/2✓ Branch 54 → 5 taken 31031952 times.
✓ Branch 54 → 55 taken 484591 times.
|
31516543 | for (int i = 0; i < value.size(); ++i) { |
| 416 | 31031952 | const QChar c = value.at(i); | |
| 417 |
5/6✓ Branch 9 → 10 taken 74609 times.
✓ Branch 9 → 13 taken 30957343 times.
✓ Branch 11 → 12 taken 74609 times.
✗ Branch 11 → 13 not taken.
✓ Branch 14 → 15 taken 74609 times.
✓ Branch 14 → 50 taken 30957343 times.
|
31031952 | if (c == QLatin1Char('\\') && i + 1 < value.size()) { |
| 418 | 74609 | const QChar next = value.at(i + 1); | |
| 419 |
5/6✓ Branch 19 → 20 taken 13087 times.
✓ Branch 19 → 24 taken 61522 times.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 13087 times.
✓ Branch 26 → 27 taken 61522 times.
✓ Branch 26 → 31 taken 13087 times.
|
74609 | if (next == QLatin1Char('n') || next == QLatin1Char('N')) { |
| 420 |
1/1✓ Branch 29 → 30 taken 61522 times.
|
61522 | result.append(QLatin1Char('\n')); |
| 421 | 61522 | ++i; | |
| 422 | 74604 | continue; | |
| 423 | } | ||
| 424 |
8/8✓ Branch 34 → 35 taken 12950 times.
✓ Branch 34 → 43 taken 137 times.
✓ Branch 38 → 39 taken 195 times.
✓ Branch 38 → 43 taken 12755 times.
✓ Branch 42 → 43 taken 190 times.
✓ Branch 42 → 44 taken 5 times.
✓ Branch 45 → 46 taken 13082 times.
✓ Branch 45 → 48 taken 5 times.
|
13087 | if (next == QLatin1Char('\\') || next == QLatin1Char(',') || next == QLatin1Char(';')) { |
| 425 |
1/1✓ Branch 46 → 47 taken 13082 times.
|
13082 | result.append(next); |
| 426 | 13082 | ++i; | |
| 427 | 13082 | continue; | |
| 428 | } | ||
| 429 | } | ||
| 430 |
1/1✓ Branch 50 → 51 taken 30957348 times.
|
30957348 | result.append(c); |
| 431 | } | ||
| 432 | 484591 | return result; | |
| 433 | ✗ | } | |
| 434 | |||
| 435 | 228120 | QString escapeText(const QString &value) { | |
| 436 | 228120 | QString escaped; | |
| 437 |
1/1✓ Branch 3 → 4 taken 228120 times.
|
228120 | escaped.reserve(value.size() + 8); |
| 438 |
2/2✓ Branch 57 → 6 taken 1836799 times.
✓ Branch 57 → 58 taken 228120 times.
|
2064919 | for (const QChar c : value) { |
| 439 |
3/3✓ Branch 9 → 10 taken 62 times.
✓ Branch 9 → 17 taken 1836737 times.
✓ Branch 13 → 14 taken 62 times.
|
1836861 | if (c == QLatin1Char('\\')) escaped += QStringLiteral("\\\\"); |
| 440 |
3/3✓ Branch 20 → 21 taken 220 times.
✓ Branch 20 → 28 taken 1836517 times.
✓ Branch 24 → 25 taken 220 times.
|
1836957 | else if (c == QLatin1Char(';')) escaped += QStringLiteral("\\;"); |
| 441 |
3/3✓ Branch 31 → 32 taken 8189 times.
✓ Branch 31 → 39 taken 1828328 times.
✓ Branch 35 → 36 taken 8189 times.
|
1844706 | else if (c == QLatin1Char(',')) escaped += QStringLiteral("\\,"); |
| 442 |
3/3✓ Branch 42 → 43 taken 6238 times.
✓ Branch 42 → 50 taken 1822090 times.
✓ Branch 46 → 47 taken 6238 times.
|
1834566 | else if (c == QLatin1Char('\n')) escaped += QStringLiteral("\\n"); |
| 443 |
2/2✓ Branch 53 → 54 taken 28 times.
✓ Branch 53 → 55 taken 1822062 times.
|
1822090 | else if (c == QLatin1Char('\r')) continue; |
| 444 |
1/1✓ Branch 55 → 56 taken 1822062 times.
|
1822062 | else escaped += c; |
| 445 | } | ||
| 446 | 228120 | return escaped; | |
| 447 | ✗ | } | |
| 448 | |||
| 449 | 2414 | QStringList splitValues(const QString &value) { | |
| 450 | 2414 | QStringList result; | |
| 451 | 2414 | QString current; | |
| 452 |
2/2✓ Branch 31 → 3 taken 24907 times.
✓ Branch 31 → 32 taken 2414 times.
|
27321 | for (int i = 0; i < value.size(); ++i) { |
| 453 | 24907 | const QChar c = value.at(i); | |
| 454 |
5/6✓ Branch 7 → 8 taken 91 times.
✓ Branch 7 → 11 taken 24816 times.
✓ Branch 9 → 10 taken 91 times.
✗ Branch 9 → 11 not taken.
✓ Branch 12 → 13 taken 91 times.
✓ Branch 12 → 17 taken 24816 times.
|
24907 | if (c == QLatin1Char('\\') && i + 1 < value.size()) { |
| 455 |
1/1✓ Branch 13 → 14 taken 91 times.
|
91 | current += c; |
| 456 |
1/1✓ Branch 15 → 16 taken 91 times.
|
91 | current += value.at(++i); |
| 457 | 1041 | continue; | |
| 458 | } | ||
| 459 |
2/2✓ Branch 20 → 21 taken 950 times.
✓ Branch 20 → 26 taken 23866 times.
|
24816 | if (c == QLatin1Char(',')) { |
| 460 |
2/2✓ Branch 21 → 22 taken 950 times.
✓ Branch 22 → 23 taken 950 times.
|
950 | result.append(current.trimmed()); |
| 461 | 950 | current.clear(); | |
| 462 | 950 | continue; | |
| 463 | } | ||
| 464 |
1/1✓ Branch 26 → 27 taken 23866 times.
|
23866 | current += c; |
| 465 | } | ||
| 466 |
2/3✓ Branch 32 → 33 taken 2414 times.
✓ Branch 35 → 36 taken 2414 times.
✗ Branch 35 → 40 not taken.
|
2414 | if (!current.trimmed().isEmpty()) |
| 467 |
2/2✓ Branch 36 → 37 taken 2414 times.
✓ Branch 37 → 38 taken 2414 times.
|
2414 | result.append(current.trimmed()); |
| 468 | 2414 | return result; | |
| 469 | 2414 | } | |
| 470 | |||
| 471 | } // namespace ICal | ||
| 472 |