| 262 | |
| 263 | |
| 264 | static std::map<std::string,std::string> ParseLuxReplyMapping(const std::string &s) |
| 265 | { |
| 266 | std::map<std::string,std::string> mapping; |
| 267 | size_t ptr=0; |
| 268 | while (ptr < s.size()) { |
| 269 | std::string key, value; |
| 270 | while (ptr < s.size() && s[ptr] != '=' && s[ptr] != ' ') { |
| 271 | key.push_back(s[ptr]); |
| 272 | ++ptr; |
| 273 | } |
| 274 | if (ptr == s.size()) // unexpected end of line |
| 275 | return std::map<std::string,std::string>(); |
| 276 | if (s[ptr] == ' ') // The remaining string is an OptArguments |
| 277 | break; |
| 278 | ++ptr; // skip '=' |
| 279 | if (ptr < s.size() && s[ptr] == '"') { // Quoted string |
| 280 | ++ptr; // skip opening '"' |
| 281 | bool escape_next = false; |
| 282 | while (ptr < s.size() && (escape_next || s[ptr] != '"')) { |
| 283 | // Repeated backslashes must be interpreted as pairs |
| 284 | escape_next = (s[ptr] == '\\' && !escape_next); |
| 285 | value.push_back(s[ptr]); |
| 286 | ++ptr; |
| 287 | } |
| 288 | if (ptr == s.size()) // unexpected end of line |
| 289 | return std::map<std::string,std::string>(); |
| 290 | ++ptr; // skip closing '"' |
| 291 | |
| 292 | std::string escaped_value; |
| 293 | for (size_t i = 0; i < value.size(); ++i) { |
| 294 | if (value[i] == '\\') { |
| 295 | // This will always be valid, because if the QuotedString |
| 296 | // ended in an odd number of backslashes, then the parser |
| 297 | // would already have returned above, due to a missing |
| 298 | // terminating double-quote. |
| 299 | ++i; |
| 300 | if (value[i] == 'n') { |
| 301 | escaped_value.push_back('\n'); |
| 302 | } else if (value[i] == 't') { |
| 303 | escaped_value.push_back('\t'); |
| 304 | } else if (value[i] == 'r') { |
| 305 | escaped_value.push_back('\r'); |
| 306 | } else if ('0' <= value[i] && value[i] <= '7') { |
| 307 | size_t j; |
| 308 | // Octal escape sequences have a limit of three octal digits, |
| 309 | // but terminate at the first character that is not a valid |
| 310 | // octal digit if encountered sooner. |
| 311 | for (j = 1; j < 3 && (i+j) < value.size() && '0' <= value[i+j] && value[i+j] <= '7'; ++j) {} |
| 312 | // Lux restricts first digit to 0-3 for three-digit octals. |
| 313 | // A leading digit of 4-7 would therefore be interpreted as |
| 314 | // a two-digit octal. |
| 315 | if (j == 3 && value[i] > '3') { |
| 316 | j--; |
| 317 | } |
| 318 | escaped_value.push_back(strtol(value.substr(i, j).c_str(), NULL, 8)); |
| 319 | // Account for automatic incrementing at loop end |
| 320 | i += j - 1; |
| 321 | } else { |
no test coverage detected