Commit 3fc7c99d02f9ba3045a7f085bf8f74132c174b59

Authored by James R. Barlow
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;