| 1073 | |
| 1074 | template <typename Vector, typename ReturnType> |
| 1075 | ReturnType readJSONObjectPossiblyInvalid(Vector & s, ReadBuffer & buf) |
| 1076 | { |
| 1077 | static constexpr bool throw_exception = std::is_same_v<ReturnType, void>; |
| 1078 | |
| 1079 | auto error = [](const char * message [[maybe_unused]], int code [[maybe_unused]]) |
| 1080 | { |
| 1081 | if constexpr (throw_exception) |
| 1082 | throw ParsingException(code, std::move(message)); |
| 1083 | return ReturnType(false); |
| 1084 | }; |
| 1085 | |
| 1086 | if (buf.eof() || *buf.position() != '{') |
| 1087 | return error("JSON should start from opening curly bracket", ErrorCodes::INCORRECT_DATA); |
| 1088 | |
| 1089 | s.push_back(*buf.position()); |
| 1090 | ++buf.position(); |
| 1091 | |
| 1092 | Int64 balance = 1; |
| 1093 | bool quotes = false; |
| 1094 | |
| 1095 | while (!buf.eof()) |
| 1096 | { |
| 1097 | char * next_pos = find_first_symbols<'\\', '{', '}', '"'>(buf.position(), buf.buffer().end()); |
| 1098 | appendToStringOrVector(s, buf, next_pos); |
| 1099 | buf.position() = next_pos; |
| 1100 | |
| 1101 | if (!buf.hasPendingData()) |
| 1102 | continue; |
| 1103 | |
| 1104 | s.push_back(*buf.position()); |
| 1105 | |
| 1106 | if (*buf.position() == '\\') |
| 1107 | { |
| 1108 | ++buf.position(); |
| 1109 | if (!buf.eof()) |
| 1110 | { |
| 1111 | s.push_back(*buf.position()); |
| 1112 | ++buf.position(); |
| 1113 | } |
| 1114 | |
| 1115 | continue; |
| 1116 | } |
| 1117 | |
| 1118 | if (*buf.position() == '"') |
| 1119 | quotes = !quotes; |
| 1120 | else if (!quotes) // can be only '{' or '}' |
| 1121 | balance += *buf.position() == '{' ? 1 : -1; |
| 1122 | |
| 1123 | ++buf.position(); |
| 1124 | |
| 1125 | if (balance == 0) |
| 1126 | return ReturnType(true); |
| 1127 | |
| 1128 | if (balance < 0) |
| 1129 | break; |
| 1130 | } |
| 1131 | |
| 1132 | return error("JSON should have equal number of opening and closing brackets", ErrorCodes::INCORRECT_DATA); |
no test coverage detected