| 155 | } |
| 156 | |
| 157 | DBRecord parseDBRecord(std::istream &is, const DBRecord &defaultRecordValue) |
| 158 | { |
| 159 | DBRecord record = defaultRecordValue; |
| 160 | std::vector<std::string> recordParts; |
| 161 | std::string s; |
| 162 | while (is.peek() != '\n' && is >> std::quoted(s)) { |
| 163 | recordParts.push_back(s); |
| 164 | while (is.peek() == ' ' || is.peek() == '\t') |
| 165 | is.ignore(1); |
| 166 | } |
| 167 | |
| 168 | if (recordParts.size() % 2 != 0) |
| 169 | throw std::invalid_argument("incomplete key-value pair of key " + recordParts.back()); |
| 170 | |
| 171 | for (size_t i = 0; i < recordParts.size(); i += 2) { |
| 172 | auto &recordPartKey = recordParts[i]; |
| 173 | auto &recordPartValue = recordParts[i + 1]; |
| 174 | |
| 175 | if (recordPartKey == "label") { |
| 176 | if (recordPartValue.length() == 1) |
| 177 | record.label = static_cast<DBLabel>(recordPartValue[0]); |
| 178 | else if (recordPartValue.length() > 1 && recordPartValue[0] == '(') { |
| 179 | size_t rightPar = recordPartValue.find_first_of(')', 1); |
| 180 | if (rightPar != std::string::npos) { |
| 181 | recordPartValue = recordPartValue.substr(1, rightPar - 1); |
| 182 | if (recordPartValue == "null") |
| 183 | record.label = DBLabel(0); |
| 184 | else |
| 185 | record.label = DBLabel(std::atoi(recordPartValue.c_str())); |
| 186 | } |
| 187 | else |
| 188 | throw std::invalid_argument("unclosed label"); |
| 189 | } |
| 190 | else |
| 191 | throw std::invalid_argument("invalid label"); |
| 192 | } |
| 193 | else if (recordPartKey == "value") |
| 194 | record.value = std::atoi(recordPartValue.data()); |
| 195 | else if (recordPartKey == "depth") |
| 196 | record.setDepthBound(std::atoi(recordPartValue.data()), record.bound()); |
| 197 | else if (recordPartKey == "bound") { |
| 198 | Bound bound; |
| 199 | if (recordPartValue == "lower") |
| 200 | bound = BOUND_LOWER; |
| 201 | else if (recordPartValue == "upper") |
| 202 | bound = BOUND_UPPER; |
| 203 | else if (recordPartValue == "exact") |
| 204 | bound = BOUND_EXACT; |
| 205 | else if (recordPartValue == "none") |
| 206 | bound = BOUND_NONE; |
| 207 | else |
| 208 | throw std::invalid_argument("invalid bound"); |
| 209 | |
| 210 | record.setDepthBound(record.depth(), bound); |
| 211 | } |
| 212 | else if (recordPartKey == "text") |
| 213 | record.text = ConsoleCPToUTF8(recordPartValue); |
| 214 | else |
no test coverage detected