| 114 | } |
| 115 | |
| 116 | static bool ConvertLine(StringPiece line, |
| 117 | const std::vector<string>& multi_line_fields, |
| 118 | string* ml) { |
| 119 | // Is this a field we should convert? |
| 120 | if (!StartsWithFieldName(line, multi_line_fields)) { |
| 121 | return false; |
| 122 | } |
| 123 | // Has a matching field name, so look for "..." after the colon. |
| 124 | StringPiece up_to_colon; |
| 125 | StringPiece after_colon = line; |
| 126 | SplitAt(':', &after_colon, &up_to_colon); |
| 127 | while (absl::ConsumePrefix(&after_colon, " ")) |
| 128 | ; // Remove leading spaces. |
| 129 | if (!absl::ConsumePrefix(&after_colon, "\"")) { |
| 130 | // We only convert string fields, so don't convert this line. |
| 131 | return false; |
| 132 | } |
| 133 | auto last_quote = after_colon.rfind('\"'); |
| 134 | if (last_quote == StringPiece::npos) { |
| 135 | // Error: we don't see the expected matching quote, abort the conversion. |
| 136 | return false; |
| 137 | } |
| 138 | StringPiece escaped = after_colon.substr(0, last_quote); |
| 139 | StringPiece suffix = after_colon.substr(last_quote + 1); |
| 140 | // We've now parsed line into '<up_to_colon>: "<escaped>"<suffix>' |
| 141 | |
| 142 | string unescaped; |
| 143 | if (!absl::CUnescape(escaped, &unescaped, nullptr)) { |
| 144 | // Error unescaping, abort the conversion. |
| 145 | return false; |
| 146 | } |
| 147 | // No more errors possible at this point. |
| 148 | |
| 149 | // Find a string to mark the end that isn't in unescaped. |
| 150 | string end = "END"; |
| 151 | for (int s = 0; unescaped.find(end) != string::npos; ++s) { |
| 152 | end = strings::StrCat("END", s); |
| 153 | } |
| 154 | |
| 155 | // Actually start writing the converted output. |
| 156 | strings::StrAppend(ml, up_to_colon, ": <<", end, "\n", unescaped, "\n", end); |
| 157 | if (!suffix.empty()) { |
| 158 | // Output suffix, in case there was a trailing comment in the source. |
| 159 | strings::StrAppend(ml, suffix); |
| 160 | } |
| 161 | strings::StrAppend(ml, "\n"); |
| 162 | return true; |
| 163 | } |
| 164 | |
| 165 | string PBTxtToMultiline(StringPiece pbtxt, |
| 166 | const std::vector<string>& multi_line_fields) { |
no test coverage detected