| 205 | } |
| 206 | |
| 207 | std::string json_string(const std::string& json, const std::string& key) { |
| 208 | std::string pattern = "\"" + key + "\":"; |
| 209 | size_t pos = json.find(pattern); |
| 210 | if (pos == std::string::npos) return {}; |
| 211 | size_t start = pos + pattern.size(); |
| 212 | |
| 213 | while (start < json.size() && (json[start] == ' ' || json[start] == '\t')) ++start; |
| 214 | if (start >= json.size() || json[start] != '"') return {}; |
| 215 | ++start; |
| 216 | |
| 217 | std::string out; |
| 218 | out.reserve(128); |
| 219 | bool escaped = false; |
| 220 | for (size_t i = start; i < json.size(); ++i) { |
| 221 | char c = json[i]; |
| 222 | if (escaped) { |
| 223 | switch (c) { |
| 224 | case '"': out.push_back('"'); break; |
| 225 | case '\\': out.push_back('\\'); break; |
| 226 | case '/': out.push_back('/'); break; |
| 227 | case 'b': out.push_back('\b'); break; |
| 228 | case 'f': out.push_back('\f'); break; |
| 229 | case 'n': out.push_back('\n'); break; |
| 230 | case 'r': out.push_back('\r'); break; |
| 231 | case 't': out.push_back('\t'); break; |
| 232 | default: out.push_back(c); break; |
| 233 | } |
| 234 | escaped = false; |
| 235 | continue; |
| 236 | } |
| 237 | |
| 238 | if (c == '\\') { |
| 239 | escaped = true; |
| 240 | continue; |
| 241 | } |
| 242 | |
| 243 | if (c == '"') { |
| 244 | return out; |
| 245 | } |
| 246 | |
| 247 | out.push_back(c); |
| 248 | } |
| 249 | return {}; |
| 250 | } |
| 251 | |
| 252 | std::string escape_json(const std::string& s) { |
| 253 | std::ostringstream o; |
no test coverage detected