| 293 | } |
| 294 | |
| 295 | bool PresentMonCsv::ReadRow() |
| 296 | { |
| 297 | row_[0] = '\0'; |
| 298 | cols_.clear(); |
| 299 | |
| 300 | // Read a line |
| 301 | if (fgets(row_, _countof(row_), fp_) == nullptr) { |
| 302 | if (ferror(fp_) != 0) { |
| 303 | AddTestFailure(Convert(path_).c_str(), (int) line_, "File read error"); |
| 304 | } |
| 305 | return false; |
| 306 | } |
| 307 | |
| 308 | line_ += 1; |
| 309 | |
| 310 | // Split line into columns, skipping leading/trailing whitespace |
| 311 | auto p0 = row_; |
| 312 | for (; *p0 == ' ' || *p0 == '\t'; ++p0) *p0 = '\0'; |
| 313 | for (auto p = p0; ; ++p) { |
| 314 | auto ch = *p; |
| 315 | if (ch == ',' || ch == '\0') { |
| 316 | *p = '\0'; |
| 317 | cols_.push_back(p0); |
| 318 | for (p0 = p + 1; *p0 == ' ' || *p0 == '\t'; ++p0) *p0 = '\0'; |
| 319 | for (auto q = p - 1; *q == ' ' || *q == '\t' || *q == '\n' || *q == '\r'; --q) *q = '\0'; |
| 320 | if (ch == '\0') break; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | // Hard-code some per-row validation |
| 325 | |
| 326 | auto idxFrameTime = headerColumnIndex_[Header_FrameTime]; |
| 327 | auto idxCPUBusy = headerColumnIndex_[Header_CPUBusy]; |
| 328 | auto idxCPUWait = headerColumnIndex_[Header_CPUWait]; |
| 329 | if (idxFrameTime != SIZE_MAX && idxCPUBusy != SIZE_MAX && idxCPUWait != SIZE_MAX) { |
| 330 | auto delta = strtod(cols_[idxFrameTime], nullptr) - |
| 331 | strtod(cols_[idxCPUBusy], nullptr) - |
| 332 | strtod(cols_[idxCPUWait], nullptr); |
| 333 | if (delta <= -0.0001 || delta >= 0.0001) { |
| 334 | AddTestFailure(__FILE__, __LINE__, "Invalid FrameTime: %s != %s + %s (%lf)", cols_[idxFrameTime], |
| 335 | cols_[idxCPUBusy], |
| 336 | cols_[idxCPUWait], |
| 337 | delta); |
| 338 | return false; |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | auto idxGPUTime = headerColumnIndex_[Header_GPUTime]; |
| 343 | auto idxGPUBusy = headerColumnIndex_[Header_GPUBusy]; |
| 344 | auto idxGPUWait = headerColumnIndex_[Header_GPUWait]; |
| 345 | if (idxGPUTime != SIZE_MAX && idxGPUBusy != SIZE_MAX && idxGPUWait != SIZE_MAX) { |
| 346 | auto delta = strtod(cols_[idxGPUTime], nullptr) - |
| 347 | strtod(cols_[idxGPUBusy], nullptr) - |
| 348 | strtod(cols_[idxGPUWait], nullptr); |
| 349 | auto idxVideoBusy = headerColumnIndex_[Header_VideoBusy]; |
| 350 | if (idxVideoBusy != SIZE_MAX) { |
| 351 | delta -= strtod(cols_[idxVideoBusy], nullptr); |
| 352 | } |