Read and process a chunk of the file. On entry, fileOverlapLength is the offset into the start of the buffer that we should read into, and if it is nonzero then there was an incomplete comment line already at the start of the buffer. The file position is correct for reading the next chunk of the file. If successful set reachedEnd true if we ran out of data in the file; otherwise set reachedEnd fal
| 303 | // If successful set reachedEnd true if we ran out of data in the file; otherwise set reachedEnd false and leave the buffer, fileOverlaplength and the file seek position ready for the next call to this function. |
| 304 | // Return true if success, false if there was a file read error. |
| 305 | bool FileInfoParser::ReadAndProcessFileChunk(bool isParsingHeader, bool& reachedEnd) noexcept |
| 306 | { |
| 307 | // Read a chunk of the file into the buffer after the data we have already. |
| 308 | // For efficiency, read complete 512byte sectors on 512byte sector boundaries, and read them into 32-bit aligned memory - that allows the SD card driver to DMA directly into the buffer. |
| 309 | bufferStartFilePosition = fileBeingParsed->Position() - GCodeOverlapSize; // we need to keep this up to date so that we can record the file offsets of thumbnails |
| 310 | const FilePosition sizeLeft = fileBeingParsed->Length() - fileBeingParsed->Position(); |
| 311 | const size_t sizeToRead = (size_t)min<FilePosition>(sizeLeft, GCodeReadSize); |
| 312 | |
| 313 | const uint32_t now1 = millis(); |
| 314 | const int nbytes = fileBeingParsed->Read(buf + GCodeOverlapSize, sizeToRead); |
| 315 | accumulatedReadTime += millis() - now1; |
| 316 | |
| 317 | if (nbytes != (int)sizeToRead) |
| 318 | { |
| 319 | return false; |
| 320 | } |
| 321 | |
| 322 | if (!isParsingHeader) |
| 323 | { |
| 324 | trailerBytesProcessed += (unsigned int)nbytes; |
| 325 | } |
| 326 | |
| 327 | const char *_ecv_array bufp = buf + scanStartOffset; |
| 328 | char *_ecv_array bufLim = buf + GCodeOverlapSize + (unsigned int)nbytes; |
| 329 | reachedEnd = (sizeLeft <= GCodeReadSize); |
| 330 | if (reachedEnd) |
| 331 | { |
| 332 | // This is the last read of the file, so append a '\n' terminator so that ScanBuffer can process the last line |
| 333 | *bufLim = '\n'; |
| 334 | ++bufLim; |
| 335 | } |
| 336 | |
| 337 | if (!atLineStart) |
| 338 | { |
| 339 | // The last scan encountered a very long line. Skip the rest of it before resuming parsing. |
| 340 | while (bufp < bufLim) |
| 341 | { |
| 342 | const char c = *bufp++; |
| 343 | if (c == '\n' || c == '\r') |
| 344 | { |
| 345 | atLineStart = true; |
| 346 | break; |
| 347 | } |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | const uint32_t now2 = millis(); |
| 352 | const char *_ecv_array const pEnd = (bufp == bufLim) ? bufp : ScanBuffer(bufp, bufLim, isParsingHeader, reachedEnd); |
| 353 | accumulatedParseTime += millis() - now2; |
| 354 | |
| 355 | if (!reachedEnd && pEnd < bufLim) |
| 356 | { |
| 357 | scanStartOffset = GCodeOverlapSize - (size_t)(bufLim - pEnd); |
| 358 | memcpy(buf + scanStartOffset, pEnd, bufLim - pEnd); |
| 359 | } |
| 360 | else |
| 361 | { |
| 362 | scanStartOffset = GCodeOverlapSize; |