Commit 3fc7c99d02f9ba3045a7f085bf8f74132c174b59
Committed by
Jay Berkenbilt
1 parent
3221022f
Replace memchr with manual memory search
On large files with predominantly \n line endings, memchr(..'\r'..) seems to waste a considerable amount of time searching for a line ending candidate that we don't need. On the Adobe PDF Reference Manual 1.7, this commit is 8x faster at QPDF::processMemoryFile().
Showing
1 changed file
with
7 additions
and
6 deletions
libqpdf/BufferInputSource.cc
| @@ -61,14 +61,15 @@ BufferInputSource::findAndSkipNextEOL() | @@ -61,14 +61,15 @@ BufferInputSource::findAndSkipNextEOL() | ||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | qpdf_offset_t result = 0; | 63 | qpdf_offset_t result = 0; |
| 64 | - size_t len = QIntC::to_size(end_pos - this->m->cur_offset); | ||
| 65 | unsigned char const* buffer = this->m->buf->getBuffer(); | 64 | unsigned char const* buffer = this->m->buf->getBuffer(); |
| 65 | + unsigned char const* end = buffer + end_pos; | ||
| 66 | + unsigned char const* p = buffer + this->m->cur_offset; | ||
| 66 | 67 | ||
| 67 | - void* start = const_cast<unsigned char*>(buffer) + this->m->cur_offset; | ||
| 68 | - unsigned char* p1 = static_cast<unsigned char*>(memchr(start, '\r', len)); | ||
| 69 | - unsigned char* p2 = static_cast<unsigned char*>(memchr(start, '\n', len)); | ||
| 70 | - unsigned char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; | ||
| 71 | - if (p) | 68 | + while ((p < end) && !((*p == '\r') || (*p == '\n'))) |
| 69 | + { | ||
| 70 | + ++p; | ||
| 71 | + } | ||
| 72 | + if (p < end) | ||
| 72 | { | 73 | { |
| 73 | result = p - buffer; | 74 | result = p - buffer; |
| 74 | this->m->cur_offset = result + 1; | 75 | this->m->cur_offset = result + 1; |