| 544 | } |
| 545 | |
| 546 | class SQFile { |
| 547 | private: |
| 548 | FileHandle file; |
| 549 | size_t size; |
| 550 | size_t pos; |
| 551 | std::string buffer; |
| 552 | StringConsumer consumer; |
| 553 | |
| 554 | size_t ReadInternal(std::span<char> buf) |
| 555 | { |
| 556 | size_t count = buf.size(); |
| 557 | if (this->pos + count > this->size) { |
| 558 | count = this->size - this->pos; |
| 559 | } |
| 560 | if (count > 0) count = fread(buf.data(), 1, count, this->file); |
| 561 | this->pos += count; |
| 562 | return count; |
| 563 | } |
| 564 | |
| 565 | public: |
| 566 | SQFile(FileHandle file, size_t size) : file(std::move(file)), size(size), pos(0), consumer(buffer) {} |
| 567 | |
| 568 | StringConsumer &GetConsumer(size_t min_size = 64) |
| 569 | { |
| 570 | if (this->consumer.GetBytesLeft() < min_size && this->pos < this->size) { |
| 571 | this->buffer.erase(0, this->consumer.GetBytesRead()); |
| 572 | |
| 573 | size_t buffer_size = this->buffer.size(); |
| 574 | size_t read_size = Align(min_size - buffer_size, 4096); // read pages of 4096 bytes |
| 575 | /* TODO C++23: use std::string::resize_and_overwrite() */ |
| 576 | this->buffer.resize(buffer_size + read_size); |
| 577 | auto dest = std::span(this->buffer.data(), this->buffer.size()).subspan(buffer_size); |
| 578 | buffer_size += this->ReadInternal(dest); |
| 579 | this->buffer.resize(buffer_size); |
| 580 | |
| 581 | this->consumer = StringConsumer(this->buffer); |
| 582 | } |
| 583 | return this->consumer; |
| 584 | } |
| 585 | |
| 586 | size_t Read(void *buf, size_t max_size) |
| 587 | { |
| 588 | std::span<char> dest(reinterpret_cast<char *>(buf), max_size); |
| 589 | |
| 590 | auto view = this->consumer.Read(max_size); |
| 591 | std::copy(view.data(), view.data() + view.size(), dest.data()); |
| 592 | size_t result_size = view.size(); |
| 593 | |
| 594 | if (result_size < max_size) { |
| 595 | assert(!this->consumer.AnyBytesLeft()); |
| 596 | result_size += this->ReadInternal(dest.subspan(result_size)); |
| 597 | } |
| 598 | |
| 599 | return result_size; |
| 600 | } |
| 601 | }; |
| 602 | |
| 603 | static char32_t _io_file_lexfeed_ASCII(SQUserPointer file) |
nothing calls this directly
no test coverage detected