bool parser::parse_string(context& ctx, string_type& value, IteratorType& ch, IteratorType end) { ctx.clear(); if (!check_char(ctx, '"', ch, end)) { return false; } while (ch != end) { if (std::iscntrl(*ch)) { return false; } switch (*ch) { case '"': { // The string ends. ++ch; value = ctx.str(); return true; } case '\\': { // An escape character was provided. ++ch; if (ch == end) { return false; } switch (*ch) { case '"': ctx.push_char('"'); ++ch; break; case '\\': ctx.push_char('\\'); ++ch; break; case '/': ctx.push_char('/'); ++ch; break; case 'b': ctx.push_char('\b'); ++ch; break; case 'n': ctx.push_char('\n'); ++ch; break; case 'f': ctx.push_char('\f'); ++ch; break; case 'r': ctx.push_char('\r'); ++ch; break; case 't': ctx.push_char('\t'); ++ch; break; case 'u': { ++ch; uint16_t codepoint = 0x0000; for (size_t i = 0; i < 4; ++i) { if (ch == end) { return false; } if (!std::isxdigit(*ch)) { return false; } codepoint *= 16; codepoint += xdigit_to_int(*ch); ++ch; } ctx.push_codepoint(codepoint); break; } default: return false; } break; } default: { ctx.push_char(*ch); ++ch; } } } return false; }