---------------------------------------------------------------------- CUnescapeInternal() Unescapes C escape sequences and is the reverse of CEscape(). If 'source' is valid, stores the unescaped string and its size in 'dest' and 'dest_len' respectively, and returns true. Otherwise returns false and optionally stores the error description in 'error' and the error offset in 'error_offset'. If 'err
| 108 | // - Should not contain any other unescaped occurrence of <closing_str>. |
| 109 | // ---------------------------------------------------------------------- |
| 110 | bool UnescapeInternal(absl::string_view source, absl::string_view closing_str, |
| 111 | bool is_raw_literal, bool is_bytes_literal, |
| 112 | std::string* dest, std::string* error) { |
| 113 | if (!CheckForClosingString(source, closing_str, error)) { |
| 114 | return false; |
| 115 | } |
| 116 | |
| 117 | if (ABSL_PREDICT_FALSE(source.empty())) { |
| 118 | *dest = std::string(); |
| 119 | return true; |
| 120 | } |
| 121 | |
| 122 | // Strip off the closing_str from the end before unescaping. |
| 123 | source = source.substr(0, source.size() - closing_str.size()); |
| 124 | if (!is_bytes_literal) { |
| 125 | if (!Utf8IsValid(source)) { |
| 126 | if (error) { |
| 127 | *error = absl::StrCat("Structurally invalid UTF8 string: ", |
| 128 | EscapeBytes(source)); |
| 129 | } |
| 130 | return false; |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | dest->reserve(source.size()); |
| 135 | |
| 136 | const char* p = source.data(); |
| 137 | const char* end = p + source.size(); |
| 138 | const char* last_byte = end - 1; |
| 139 | |
| 140 | while (p < end) { |
| 141 | if (*p != '\\') { |
| 142 | if (*p != '\r') { |
| 143 | dest->push_back(*p++); |
| 144 | } else { |
| 145 | // All types of newlines in different platforms i.e. '\r', '\n', '\r\n' |
| 146 | // are replaced with '\n'. |
| 147 | dest->push_back('\n'); |
| 148 | p++; |
| 149 | if (p < end && *p == '\n') { |
| 150 | p++; |
| 151 | } |
| 152 | } |
| 153 | } else { |
| 154 | if ((p + 1) > last_byte) { |
| 155 | if (error) { |
| 156 | *error = is_raw_literal |
| 157 | ? "Raw literals cannot end with odd number of \\" |
| 158 | : is_bytes_literal ? "Bytes literal cannot end with \\" |
| 159 | : "String literal cannot end with \\"; |
| 160 | } |
| 161 | return false; |
| 162 | } |
| 163 | if (is_raw_literal) { |
| 164 | // For raw literals, all escapes are valid and those characters ('\\' |
| 165 | // and the escaped character) come through literally in the string. |
| 166 | dest->push_back(*p++); |
| 167 | dest->push_back(*p++); |
no test coverage detected