Commit 15eaed5c52c85dd97ce5bc829817c5535c527207
1 parent
8657c6f0
Refactor: pull *InputSource out of QPDF
InputSource, FileInputSource, and BufferInputSource are now top-level classes instead of privately nested inside QPDF.
Showing
9 changed files
with
424 additions
and
386 deletions
include/qpdf/BufferInputSource.hh
0 โ 100644
| 1 | +#ifndef __QPDF_BUFFERINPUTSOURCE_HH__ | |
| 2 | +#define __QPDF_BUFFERINPUTSOURCE_HH__ | |
| 3 | + | |
| 4 | +#include <qpdf/InputSource.hh> | |
| 5 | +#include <qpdf/Buffer.hh> | |
| 6 | + | |
| 7 | +class BufferInputSource: public InputSource | |
| 8 | +{ | |
| 9 | + public: | |
| 10 | + BufferInputSource(std::string const& description, Buffer* buf, | |
| 11 | + bool own_memory = false); | |
| 12 | + virtual ~BufferInputSource(); | |
| 13 | + virtual qpdf_offset_t findAndSkipNextEOL(); | |
| 14 | + virtual std::string const& getName() const; | |
| 15 | + virtual qpdf_offset_t tell(); | |
| 16 | + virtual void seek(qpdf_offset_t offset, int whence); | |
| 17 | + virtual void rewind(); | |
| 18 | + virtual size_t read(char* buffer, size_t length); | |
| 19 | + virtual void unreadCh(char ch); | |
| 20 | + | |
| 21 | + private: | |
| 22 | + bool own_memory; | |
| 23 | + std::string description; | |
| 24 | + Buffer* buf; | |
| 25 | + qpdf_offset_t cur_offset; | |
| 26 | +}; | |
| 27 | + | |
| 28 | +#endif // __QPDF_BUFFERINPUTSOURCE_HH__ | ... | ... |
include/qpdf/FileInputSource.hh
0 โ 100644
| 1 | +#ifndef __QPDF_FILEINPUTSOURCE_HH__ | |
| 2 | +#define __QPDF_FILEINPUTSOURCE_HH__ | |
| 3 | + | |
| 4 | +#include <qpdf/InputSource.hh> | |
| 5 | + | |
| 6 | +class FileInputSource: public InputSource | |
| 7 | +{ | |
| 8 | + public: | |
| 9 | + FileInputSource(); | |
| 10 | + void setFilename(char const* filename); | |
| 11 | + void setFile(char const* description, FILE* filep, bool close_file); | |
| 12 | + virtual ~FileInputSource(); | |
| 13 | + virtual qpdf_offset_t findAndSkipNextEOL(); | |
| 14 | + virtual std::string const& getName() const; | |
| 15 | + virtual qpdf_offset_t tell(); | |
| 16 | + virtual void seek(qpdf_offset_t offset, int whence); | |
| 17 | + virtual void rewind(); | |
| 18 | + virtual size_t read(char* buffer, size_t length); | |
| 19 | + virtual void unreadCh(char ch); | |
| 20 | + | |
| 21 | + private: | |
| 22 | + FileInputSource(FileInputSource const&); | |
| 23 | + FileInputSource& operator=(FileInputSource const&); | |
| 24 | + | |
| 25 | + void destroy(); | |
| 26 | + | |
| 27 | + bool close_file; | |
| 28 | + std::string filename; | |
| 29 | + FILE* file; | |
| 30 | +}; | |
| 31 | + | |
| 32 | +#endif // __QPDF_FILEINPUTSOURCE_HH__ | ... | ... |
include/qpdf/InputSource.hh
0 โ 100644
| 1 | +#ifndef __QPDF_INPUTSOURCE_HH__ | |
| 2 | +#define __QPDF_INPUTSOURCE_HH__ | |
| 3 | + | |
| 4 | +#include <qpdf/Types.h> | |
| 5 | +#include <stdio.h> | |
| 6 | +#include <string> | |
| 7 | + | |
| 8 | +class InputSource | |
| 9 | +{ | |
| 10 | + public: | |
| 11 | + InputSource() : | |
| 12 | + last_offset(0) | |
| 13 | + { | |
| 14 | + } | |
| 15 | + virtual ~InputSource() | |
| 16 | + { | |
| 17 | + } | |
| 18 | + | |
| 19 | + void setLastOffset(qpdf_offset_t); | |
| 20 | + qpdf_offset_t getLastOffset() const; | |
| 21 | + std::string readLine(size_t max_line_length); | |
| 22 | + | |
| 23 | + virtual qpdf_offset_t findAndSkipNextEOL() = 0; | |
| 24 | + virtual std::string const& getName() const = 0; | |
| 25 | + virtual qpdf_offset_t tell() = 0; | |
| 26 | + virtual void seek(qpdf_offset_t offset, int whence) = 0; | |
| 27 | + virtual void rewind() = 0; | |
| 28 | + virtual size_t read(char* buffer, size_t length) = 0; | |
| 29 | + virtual void unreadCh(char ch) = 0; | |
| 30 | + | |
| 31 | + protected: | |
| 32 | + qpdf_offset_t last_offset; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +#endif // __QPDF_INPUTSOURCE_HH__ | ... | ... |
include/qpdf/QPDF.hh
| ... | ... | @@ -21,6 +21,7 @@ |
| 21 | 21 | #include <qpdf/QPDFObjectHandle.hh> |
| 22 | 22 | #include <qpdf/QPDFTokenizer.hh> |
| 23 | 23 | #include <qpdf/Buffer.hh> |
| 24 | +#include <qpdf/InputSource.hh> | |
| 24 | 25 | |
| 25 | 26 | class QPDF_Stream; |
| 26 | 27 | class BitStream; |
| ... | ... | @@ -474,80 +475,6 @@ class QPDF |
| 474 | 475 | private: |
| 475 | 476 | static std::string qpdf_version; |
| 476 | 477 | |
| 477 | - class InputSource | |
| 478 | - { | |
| 479 | - public: | |
| 480 | - InputSource() : | |
| 481 | - last_offset(0) | |
| 482 | - { | |
| 483 | - } | |
| 484 | - virtual ~InputSource() | |
| 485 | - { | |
| 486 | - } | |
| 487 | - | |
| 488 | - void setLastOffset(qpdf_offset_t); | |
| 489 | - qpdf_offset_t getLastOffset() const; | |
| 490 | - std::string readLine(size_t max_line_length); | |
| 491 | - | |
| 492 | - virtual qpdf_offset_t findAndSkipNextEOL() = 0; | |
| 493 | - virtual std::string const& getName() const = 0; | |
| 494 | - virtual qpdf_offset_t tell() = 0; | |
| 495 | - virtual void seek(qpdf_offset_t offset, int whence) = 0; | |
| 496 | - virtual void rewind() = 0; | |
| 497 | - virtual size_t read(char* buffer, size_t length) = 0; | |
| 498 | - virtual void unreadCh(char ch) = 0; | |
| 499 | - | |
| 500 | - protected: | |
| 501 | - qpdf_offset_t last_offset; | |
| 502 | - }; | |
| 503 | - | |
| 504 | - class FileInputSource: public InputSource | |
| 505 | - { | |
| 506 | - public: | |
| 507 | - FileInputSource(); | |
| 508 | - void setFilename(char const* filename); | |
| 509 | - void setFile(char const* description, FILE* filep, bool close_file); | |
| 510 | - virtual ~FileInputSource(); | |
| 511 | - virtual qpdf_offset_t findAndSkipNextEOL(); | |
| 512 | - virtual std::string const& getName() const; | |
| 513 | - virtual qpdf_offset_t tell(); | |
| 514 | - virtual void seek(qpdf_offset_t offset, int whence); | |
| 515 | - virtual void rewind(); | |
| 516 | - virtual size_t read(char* buffer, size_t length); | |
| 517 | - virtual void unreadCh(char ch); | |
| 518 | - | |
| 519 | - private: | |
| 520 | - FileInputSource(FileInputSource const&); | |
| 521 | - FileInputSource& operator=(FileInputSource const&); | |
| 522 | - | |
| 523 | - void destroy(); | |
| 524 | - | |
| 525 | - bool close_file; | |
| 526 | - std::string filename; | |
| 527 | - FILE* file; | |
| 528 | - }; | |
| 529 | - | |
| 530 | - class BufferInputSource: public InputSource | |
| 531 | - { | |
| 532 | - public: | |
| 533 | - BufferInputSource(std::string const& description, Buffer* buf, | |
| 534 | - bool own_memory = false); | |
| 535 | - virtual ~BufferInputSource(); | |
| 536 | - virtual qpdf_offset_t findAndSkipNextEOL(); | |
| 537 | - virtual std::string const& getName() const; | |
| 538 | - virtual qpdf_offset_t tell(); | |
| 539 | - virtual void seek(qpdf_offset_t offset, int whence); | |
| 540 | - virtual void rewind(); | |
| 541 | - virtual size_t read(char* buffer, size_t length); | |
| 542 | - virtual void unreadCh(char ch); | |
| 543 | - | |
| 544 | - private: | |
| 545 | - bool own_memory; | |
| 546 | - std::string description; | |
| 547 | - Buffer* buf; | |
| 548 | - qpdf_offset_t cur_offset; | |
| 549 | - }; | |
| 550 | - | |
| 551 | 478 | class ObjGen |
| 552 | 479 | { |
| 553 | 480 | public: | ... | ... |
libqpdf/BufferInputSource.cc
0 โ 100644
| 1 | +#include <qpdf/BufferInputSource.hh> | |
| 2 | +#include <string.h> | |
| 3 | +#include <stdexcept> | |
| 4 | + | |
| 5 | +BufferInputSource::BufferInputSource(std::string const& description, | |
| 6 | + Buffer* buf, bool own_memory) : | |
| 7 | + own_memory(own_memory), | |
| 8 | + description(description), | |
| 9 | + buf(buf), | |
| 10 | + cur_offset(0) | |
| 11 | +{ | |
| 12 | +} | |
| 13 | + | |
| 14 | +BufferInputSource::~BufferInputSource() | |
| 15 | +{ | |
| 16 | + if (own_memory) | |
| 17 | + { | |
| 18 | + delete this->buf; | |
| 19 | + } | |
| 20 | +} | |
| 21 | + | |
| 22 | +qpdf_offset_t | |
| 23 | +BufferInputSource::findAndSkipNextEOL() | |
| 24 | +{ | |
| 25 | + if (this->cur_offset < 0) | |
| 26 | + { | |
| 27 | + throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); | |
| 28 | + } | |
| 29 | + qpdf_offset_t end_pos = (qpdf_offset_t) this->buf->getSize(); | |
| 30 | + if (this->cur_offset >= end_pos) | |
| 31 | + { | |
| 32 | + this->last_offset = end_pos; | |
| 33 | + this->cur_offset = end_pos; | |
| 34 | + return end_pos; | |
| 35 | + } | |
| 36 | + | |
| 37 | + qpdf_offset_t result = 0; | |
| 38 | + size_t len = (size_t)(end_pos - this->cur_offset); | |
| 39 | + unsigned char const* buffer = this->buf->getBuffer(); | |
| 40 | + | |
| 41 | + void* start = (void*)(buffer + this->cur_offset); | |
| 42 | + unsigned char* p1 = (unsigned char*)memchr(start, '\r', len); | |
| 43 | + unsigned char* p2 = (unsigned char*)memchr(start, '\n', len); | |
| 44 | + unsigned char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; | |
| 45 | + if (p) | |
| 46 | + { | |
| 47 | + result = p - buffer; | |
| 48 | + this->cur_offset = result + 1; | |
| 49 | + ++p; | |
| 50 | + while ((this->cur_offset < end_pos) && | |
| 51 | + ((*p == '\r') || (*p == '\n'))) | |
| 52 | + { | |
| 53 | + ++p; | |
| 54 | + ++this->cur_offset; | |
| 55 | + } | |
| 56 | + } | |
| 57 | + else | |
| 58 | + { | |
| 59 | + this->cur_offset = end_pos; | |
| 60 | + result = end_pos; | |
| 61 | + } | |
| 62 | + return result; | |
| 63 | +} | |
| 64 | + | |
| 65 | +std::string const& | |
| 66 | +BufferInputSource::getName() const | |
| 67 | +{ | |
| 68 | + return this->description; | |
| 69 | +} | |
| 70 | + | |
| 71 | +qpdf_offset_t | |
| 72 | +BufferInputSource::tell() | |
| 73 | +{ | |
| 74 | + return this->cur_offset; | |
| 75 | +} | |
| 76 | + | |
| 77 | +void | |
| 78 | +BufferInputSource::seek(qpdf_offset_t offset, int whence) | |
| 79 | +{ | |
| 80 | + switch (whence) | |
| 81 | + { | |
| 82 | + case SEEK_SET: | |
| 83 | + this->cur_offset = offset; | |
| 84 | + break; | |
| 85 | + | |
| 86 | + case SEEK_END: | |
| 87 | + this->cur_offset = (qpdf_offset_t)this->buf->getSize() + offset; | |
| 88 | + break; | |
| 89 | + | |
| 90 | + case SEEK_CUR: | |
| 91 | + this->cur_offset += offset; | |
| 92 | + break; | |
| 93 | + | |
| 94 | + default: | |
| 95 | + throw std::logic_error( | |
| 96 | + "INTERNAL ERROR: invalid argument to BufferInputSource::seek"); | |
| 97 | + break; | |
| 98 | + } | |
| 99 | + | |
| 100 | + if (this->cur_offset < 0) | |
| 101 | + { | |
| 102 | + throw std::runtime_error( | |
| 103 | + this->description + ": seek before beginning of buffer"); | |
| 104 | + } | |
| 105 | +} | |
| 106 | + | |
| 107 | +void | |
| 108 | +BufferInputSource::rewind() | |
| 109 | +{ | |
| 110 | + this->cur_offset = 0; | |
| 111 | +} | |
| 112 | + | |
| 113 | +size_t | |
| 114 | +BufferInputSource::read(char* buffer, size_t length) | |
| 115 | +{ | |
| 116 | + if (this->cur_offset < 0) | |
| 117 | + { | |
| 118 | + throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); | |
| 119 | + } | |
| 120 | + qpdf_offset_t end_pos = (qpdf_offset_t) this->buf->getSize(); | |
| 121 | + if (this->cur_offset >= end_pos) | |
| 122 | + { | |
| 123 | + this->last_offset = end_pos; | |
| 124 | + return 0; | |
| 125 | + } | |
| 126 | + | |
| 127 | + this->last_offset = this->cur_offset; | |
| 128 | + size_t len = std::min((size_t)(end_pos - this->cur_offset), length); | |
| 129 | + memcpy(buffer, buf->getBuffer() + this->cur_offset, len); | |
| 130 | + this->cur_offset += len; | |
| 131 | + return len; | |
| 132 | +} | |
| 133 | + | |
| 134 | +void | |
| 135 | +BufferInputSource::unreadCh(char ch) | |
| 136 | +{ | |
| 137 | + if (this->cur_offset > 0) | |
| 138 | + { | |
| 139 | + --this->cur_offset; | |
| 140 | + } | |
| 141 | +} | ... | ... |
libqpdf/FileInputSource.cc
0 โ 100644
| 1 | +#include <qpdf/FileInputSource.hh> | |
| 2 | +#include <string.h> | |
| 3 | +#include <qpdf/QUtil.hh> | |
| 4 | +#include <qpdf/QPDFExc.hh> | |
| 5 | + | |
| 6 | +FileInputSource::FileInputSource() : | |
| 7 | + close_file(false), | |
| 8 | + file(0) | |
| 9 | +{ | |
| 10 | +} | |
| 11 | + | |
| 12 | +void | |
| 13 | +FileInputSource::setFilename(char const* filename) | |
| 14 | +{ | |
| 15 | + destroy(); | |
| 16 | + this->filename = filename; | |
| 17 | + this->close_file = true; | |
| 18 | + this->file = QUtil::fopen_wrapper(std::string("open ") + this->filename, | |
| 19 | + fopen(this->filename.c_str(), "rb")); | |
| 20 | +} | |
| 21 | + | |
| 22 | +void | |
| 23 | +FileInputSource::setFile( | |
| 24 | + char const* description, FILE* filep, bool close_file) | |
| 25 | +{ | |
| 26 | + destroy(); | |
| 27 | + this->filename = description; | |
| 28 | + this->close_file = close_file; | |
| 29 | + this->file = filep; | |
| 30 | + this->seek(0, SEEK_SET); | |
| 31 | +} | |
| 32 | + | |
| 33 | +FileInputSource::~FileInputSource() | |
| 34 | +{ | |
| 35 | + destroy(); | |
| 36 | +} | |
| 37 | + | |
| 38 | +void | |
| 39 | +FileInputSource::destroy() | |
| 40 | +{ | |
| 41 | + if (this->file && this->close_file) | |
| 42 | + { | |
| 43 | + fclose(this->file); | |
| 44 | + this->file = 0; | |
| 45 | + } | |
| 46 | +} | |
| 47 | + | |
| 48 | +qpdf_offset_t | |
| 49 | +FileInputSource::findAndSkipNextEOL() | |
| 50 | +{ | |
| 51 | + qpdf_offset_t result = 0; | |
| 52 | + bool done = false; | |
| 53 | + char buf[10240]; | |
| 54 | + while (! done) | |
| 55 | + { | |
| 56 | + qpdf_offset_t cur_offset = QUtil::tell(this->file); | |
| 57 | + size_t len = this->read(buf, sizeof(buf)); | |
| 58 | + if (len == 0) | |
| 59 | + { | |
| 60 | + done = true; | |
| 61 | + result = this->tell(); | |
| 62 | + } | |
| 63 | + else | |
| 64 | + { | |
| 65 | + char* p1 = (char*)memchr((void*)buf, '\r', len); | |
| 66 | + char* p2 = (char*)memchr((void*)buf, '\n', len); | |
| 67 | + char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; | |
| 68 | + if (p) | |
| 69 | + { | |
| 70 | + result = cur_offset + (p - buf); | |
| 71 | + // We found \r or \n. Keep reading until we get past | |
| 72 | + // \r and \n characters. | |
| 73 | + this->seek(result + 1, SEEK_SET); | |
| 74 | + char ch; | |
| 75 | + while (! done) | |
| 76 | + { | |
| 77 | + if (this->read(&ch, 1) == 0) | |
| 78 | + { | |
| 79 | + done = true; | |
| 80 | + } | |
| 81 | + else if (! ((ch == '\r') || (ch == '\n'))) | |
| 82 | + { | |
| 83 | + this->unreadCh(ch); | |
| 84 | + done = true; | |
| 85 | + } | |
| 86 | + } | |
| 87 | + } | |
| 88 | + } | |
| 89 | + } | |
| 90 | + return result; | |
| 91 | +} | |
| 92 | + | |
| 93 | +std::string const& | |
| 94 | +FileInputSource::getName() const | |
| 95 | +{ | |
| 96 | + return this->filename; | |
| 97 | +} | |
| 98 | + | |
| 99 | +qpdf_offset_t | |
| 100 | +FileInputSource::tell() | |
| 101 | +{ | |
| 102 | + return QUtil::tell(this->file); | |
| 103 | +} | |
| 104 | + | |
| 105 | +void | |
| 106 | +FileInputSource::seek(qpdf_offset_t offset, int whence) | |
| 107 | +{ | |
| 108 | + QUtil::os_wrapper(std::string("seek to ") + this->filename + ", offset " + | |
| 109 | + QUtil::int_to_string(offset) + " (" + | |
| 110 | + QUtil::int_to_string(whence) + ")", | |
| 111 | + QUtil::seek(this->file, offset, whence)); | |
| 112 | +} | |
| 113 | + | |
| 114 | +void | |
| 115 | +FileInputSource::rewind() | |
| 116 | +{ | |
| 117 | + ::rewind(this->file); | |
| 118 | +} | |
| 119 | + | |
| 120 | +size_t | |
| 121 | +FileInputSource::read(char* buffer, size_t length) | |
| 122 | +{ | |
| 123 | + this->last_offset = QUtil::tell(this->file); | |
| 124 | + size_t len = fread(buffer, 1, length, this->file); | |
| 125 | + if ((len == 0) && ferror(this->file)) | |
| 126 | + { | |
| 127 | + throw QPDFExc(qpdf_e_system, | |
| 128 | + this->filename, "", | |
| 129 | + this->last_offset, | |
| 130 | + std::string("read ") + | |
| 131 | + QUtil::int_to_string(length) + " bytes"); | |
| 132 | + } | |
| 133 | + return len; | |
| 134 | +} | |
| 135 | + | |
| 136 | +void | |
| 137 | +FileInputSource::unreadCh(char ch) | |
| 138 | +{ | |
| 139 | + QUtil::os_wrapper(this->filename + ": unread character", | |
| 140 | + ungetc((unsigned char)ch, this->file)); | |
| 141 | +} | ... | ... |
libqpdf/InputSource.cc
0 โ 100644
| 1 | +#include <qpdf/InputSource.hh> | |
| 2 | +#include <string.h> | |
| 3 | +#include <qpdf/PointerHolder.hh> | |
| 4 | + | |
| 5 | +void | |
| 6 | +InputSource::setLastOffset(qpdf_offset_t offset) | |
| 7 | +{ | |
| 8 | + this->last_offset = offset; | |
| 9 | +} | |
| 10 | + | |
| 11 | +qpdf_offset_t | |
| 12 | +InputSource::getLastOffset() const | |
| 13 | +{ | |
| 14 | + return this->last_offset; | |
| 15 | +} | |
| 16 | + | |
| 17 | +std::string | |
| 18 | +InputSource::readLine(size_t max_line_length) | |
| 19 | +{ | |
| 20 | + // Return at most max_line_length characters from the next line. | |
| 21 | + // Lines are terminated by one or more \r or \n characters. | |
| 22 | + // Consume the trailing newline characters but don't return them. | |
| 23 | + // After this is called, the file will be positioned after a line | |
| 24 | + // terminator or at the end of the file, and last_offset will | |
| 25 | + // point to position the file had when this method was called. | |
| 26 | + | |
| 27 | + qpdf_offset_t offset = this->tell(); | |
| 28 | + char* buf = new char[max_line_length + 1]; | |
| 29 | + PointerHolder<char> bp(true, buf); | |
| 30 | + memset(buf, '\0', max_line_length + 1); | |
| 31 | + this->read(buf, max_line_length); | |
| 32 | + this->seek(offset, SEEK_SET); | |
| 33 | + qpdf_offset_t eol = this->findAndSkipNextEOL(); | |
| 34 | + this->last_offset = offset; | |
| 35 | + size_t line_length = eol - offset; | |
| 36 | + if (line_length < max_line_length) | |
| 37 | + { | |
| 38 | + buf[line_length] = '\0'; | |
| 39 | + } | |
| 40 | + return std::string(buf); | |
| 41 | +} | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -11,6 +11,8 @@ |
| 11 | 11 | #include <qpdf/PCRE.hh> |
| 12 | 12 | #include <qpdf/Pipeline.hh> |
| 13 | 13 | #include <qpdf/Pl_Discard.hh> |
| 14 | +#include <qpdf/FileInputSource.hh> | |
| 15 | +#include <qpdf/BufferInputSource.hh> | |
| 14 | 16 | |
| 15 | 17 | #include <qpdf/QPDFExc.hh> |
| 16 | 18 | #include <qpdf/QPDF_Null.hh> |
| ... | ... | @@ -36,318 +38,6 @@ static char const* EMPTY_PDF = |
| 36 | 38 | "110\n" |
| 37 | 39 | "%%EOF\n"; |
| 38 | 40 | |
| 39 | -void | |
| 40 | -QPDF::InputSource::setLastOffset(qpdf_offset_t offset) | |
| 41 | -{ | |
| 42 | - this->last_offset = offset; | |
| 43 | -} | |
| 44 | - | |
| 45 | -qpdf_offset_t | |
| 46 | -QPDF::InputSource::getLastOffset() const | |
| 47 | -{ | |
| 48 | - return this->last_offset; | |
| 49 | -} | |
| 50 | - | |
| 51 | -std::string | |
| 52 | -QPDF::InputSource::readLine(size_t max_line_length) | |
| 53 | -{ | |
| 54 | - // Return at most max_line_length characters from the next line. | |
| 55 | - // Lines are terminated by one or more \r or \n characters. | |
| 56 | - // Consume the trailing newline characters but don't return them. | |
| 57 | - // After this is called, the file will be positioned after a line | |
| 58 | - // terminator or at the end of the file, and last_offset will | |
| 59 | - // point to position the file had when this method was called. | |
| 60 | - | |
| 61 | - qpdf_offset_t offset = this->tell(); | |
| 62 | - char* buf = new char[max_line_length + 1]; | |
| 63 | - PointerHolder<char> bp(true, buf); | |
| 64 | - memset(buf, '\0', max_line_length + 1); | |
| 65 | - this->read(buf, max_line_length); | |
| 66 | - this->seek(offset, SEEK_SET); | |
| 67 | - qpdf_offset_t eol = this->findAndSkipNextEOL(); | |
| 68 | - this->last_offset = offset; | |
| 69 | - size_t line_length = eol - offset; | |
| 70 | - if (line_length < max_line_length) | |
| 71 | - { | |
| 72 | - buf[line_length] = '\0'; | |
| 73 | - } | |
| 74 | - return std::string(buf); | |
| 75 | -} | |
| 76 | - | |
| 77 | -QPDF::FileInputSource::FileInputSource() : | |
| 78 | - close_file(false), | |
| 79 | - file(0) | |
| 80 | -{ | |
| 81 | -} | |
| 82 | - | |
| 83 | -void | |
| 84 | -QPDF::FileInputSource::setFilename(char const* filename) | |
| 85 | -{ | |
| 86 | - destroy(); | |
| 87 | - this->filename = filename; | |
| 88 | - this->close_file = true; | |
| 89 | - this->file = QUtil::fopen_wrapper(std::string("open ") + this->filename, | |
| 90 | - fopen(this->filename.c_str(), "rb")); | |
| 91 | -} | |
| 92 | - | |
| 93 | -void | |
| 94 | -QPDF::FileInputSource::setFile( | |
| 95 | - char const* description, FILE* filep, bool close_file) | |
| 96 | -{ | |
| 97 | - destroy(); | |
| 98 | - this->filename = description; | |
| 99 | - this->close_file = close_file; | |
| 100 | - this->file = filep; | |
| 101 | - this->seek(0, SEEK_SET); | |
| 102 | -} | |
| 103 | - | |
| 104 | -QPDF::FileInputSource::~FileInputSource() | |
| 105 | -{ | |
| 106 | - destroy(); | |
| 107 | -} | |
| 108 | - | |
| 109 | -void | |
| 110 | -QPDF::FileInputSource::destroy() | |
| 111 | -{ | |
| 112 | - if (this->file && this->close_file) | |
| 113 | - { | |
| 114 | - fclose(this->file); | |
| 115 | - this->file = 0; | |
| 116 | - } | |
| 117 | -} | |
| 118 | - | |
| 119 | -qpdf_offset_t | |
| 120 | -QPDF::FileInputSource::findAndSkipNextEOL() | |
| 121 | -{ | |
| 122 | - qpdf_offset_t result = 0; | |
| 123 | - bool done = false; | |
| 124 | - char buf[10240]; | |
| 125 | - while (! done) | |
| 126 | - { | |
| 127 | - qpdf_offset_t cur_offset = QUtil::tell(this->file); | |
| 128 | - size_t len = this->read(buf, sizeof(buf)); | |
| 129 | - if (len == 0) | |
| 130 | - { | |
| 131 | - done = true; | |
| 132 | - result = this->tell(); | |
| 133 | - } | |
| 134 | - else | |
| 135 | - { | |
| 136 | - char* p1 = (char*)memchr((void*)buf, '\r', len); | |
| 137 | - char* p2 = (char*)memchr((void*)buf, '\n', len); | |
| 138 | - char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; | |
| 139 | - if (p) | |
| 140 | - { | |
| 141 | - result = cur_offset + (p - buf); | |
| 142 | - // We found \r or \n. Keep reading until we get past | |
| 143 | - // \r and \n characters. | |
| 144 | - this->seek(result + 1, SEEK_SET); | |
| 145 | - char ch; | |
| 146 | - while (! done) | |
| 147 | - { | |
| 148 | - if (this->read(&ch, 1) == 0) | |
| 149 | - { | |
| 150 | - done = true; | |
| 151 | - } | |
| 152 | - else if (! ((ch == '\r') || (ch == '\n'))) | |
| 153 | - { | |
| 154 | - this->unreadCh(ch); | |
| 155 | - done = true; | |
| 156 | - } | |
| 157 | - } | |
| 158 | - } | |
| 159 | - } | |
| 160 | - } | |
| 161 | - return result; | |
| 162 | -} | |
| 163 | - | |
| 164 | -std::string const& | |
| 165 | -QPDF::FileInputSource::getName() const | |
| 166 | -{ | |
| 167 | - return this->filename; | |
| 168 | -} | |
| 169 | - | |
| 170 | -qpdf_offset_t | |
| 171 | -QPDF::FileInputSource::tell() | |
| 172 | -{ | |
| 173 | - return QUtil::tell(this->file); | |
| 174 | -} | |
| 175 | - | |
| 176 | -void | |
| 177 | -QPDF::FileInputSource::seek(qpdf_offset_t offset, int whence) | |
| 178 | -{ | |
| 179 | - QUtil::os_wrapper(std::string("seek to ") + this->filename + ", offset " + | |
| 180 | - QUtil::int_to_string(offset) + " (" + | |
| 181 | - QUtil::int_to_string(whence) + ")", | |
| 182 | - QUtil::seek(this->file, offset, whence)); | |
| 183 | -} | |
| 184 | - | |
| 185 | -void | |
| 186 | -QPDF::FileInputSource::rewind() | |
| 187 | -{ | |
| 188 | - ::rewind(this->file); | |
| 189 | -} | |
| 190 | - | |
| 191 | -size_t | |
| 192 | -QPDF::FileInputSource::read(char* buffer, size_t length) | |
| 193 | -{ | |
| 194 | - this->last_offset = QUtil::tell(this->file); | |
| 195 | - size_t len = fread(buffer, 1, length, this->file); | |
| 196 | - if ((len == 0) && ferror(this->file)) | |
| 197 | - { | |
| 198 | - throw QPDFExc(qpdf_e_system, | |
| 199 | - this->filename, "", | |
| 200 | - this->last_offset, | |
| 201 | - std::string("read ") + | |
| 202 | - QUtil::int_to_string(length) + " bytes"); | |
| 203 | - } | |
| 204 | - return len; | |
| 205 | -} | |
| 206 | - | |
| 207 | -void | |
| 208 | -QPDF::FileInputSource::unreadCh(char ch) | |
| 209 | -{ | |
| 210 | - QUtil::os_wrapper(this->filename + ": unread character", | |
| 211 | - ungetc((unsigned char)ch, this->file)); | |
| 212 | -} | |
| 213 | - | |
| 214 | -QPDF::BufferInputSource::BufferInputSource(std::string const& description, | |
| 215 | - Buffer* buf, bool own_memory) : | |
| 216 | - own_memory(own_memory), | |
| 217 | - description(description), | |
| 218 | - buf(buf), | |
| 219 | - cur_offset(0) | |
| 220 | -{ | |
| 221 | -} | |
| 222 | - | |
| 223 | -QPDF::BufferInputSource::~BufferInputSource() | |
| 224 | -{ | |
| 225 | - if (own_memory) | |
| 226 | - { | |
| 227 | - delete this->buf; | |
| 228 | - } | |
| 229 | -} | |
| 230 | - | |
| 231 | -qpdf_offset_t | |
| 232 | -QPDF::BufferInputSource::findAndSkipNextEOL() | |
| 233 | -{ | |
| 234 | - if (this->cur_offset < 0) | |
| 235 | - { | |
| 236 | - throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); | |
| 237 | - } | |
| 238 | - qpdf_offset_t end_pos = (qpdf_offset_t) this->buf->getSize(); | |
| 239 | - if (this->cur_offset >= end_pos) | |
| 240 | - { | |
| 241 | - this->last_offset = end_pos; | |
| 242 | - this->cur_offset = end_pos; | |
| 243 | - return end_pos; | |
| 244 | - } | |
| 245 | - | |
| 246 | - qpdf_offset_t result = 0; | |
| 247 | - size_t len = (size_t)(end_pos - this->cur_offset); | |
| 248 | - unsigned char const* buffer = this->buf->getBuffer(); | |
| 249 | - | |
| 250 | - void* start = (void*)(buffer + this->cur_offset); | |
| 251 | - unsigned char* p1 = (unsigned char*)memchr(start, '\r', len); | |
| 252 | - unsigned char* p2 = (unsigned char*)memchr(start, '\n', len); | |
| 253 | - unsigned char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; | |
| 254 | - if (p) | |
| 255 | - { | |
| 256 | - result = p - buffer; | |
| 257 | - this->cur_offset = result + 1; | |
| 258 | - ++p; | |
| 259 | - while ((this->cur_offset < end_pos) && | |
| 260 | - ((*p == '\r') || (*p == '\n'))) | |
| 261 | - { | |
| 262 | - ++p; | |
| 263 | - ++this->cur_offset; | |
| 264 | - } | |
| 265 | - } | |
| 266 | - else | |
| 267 | - { | |
| 268 | - this->cur_offset = end_pos; | |
| 269 | - result = end_pos; | |
| 270 | - } | |
| 271 | - return result; | |
| 272 | -} | |
| 273 | - | |
| 274 | -std::string const& | |
| 275 | -QPDF::BufferInputSource::getName() const | |
| 276 | -{ | |
| 277 | - return this->description; | |
| 278 | -} | |
| 279 | - | |
| 280 | -qpdf_offset_t | |
| 281 | -QPDF::BufferInputSource::tell() | |
| 282 | -{ | |
| 283 | - return this->cur_offset; | |
| 284 | -} | |
| 285 | - | |
| 286 | -void | |
| 287 | -QPDF::BufferInputSource::seek(qpdf_offset_t offset, int whence) | |
| 288 | -{ | |
| 289 | - switch (whence) | |
| 290 | - { | |
| 291 | - case SEEK_SET: | |
| 292 | - this->cur_offset = offset; | |
| 293 | - break; | |
| 294 | - | |
| 295 | - case SEEK_END: | |
| 296 | - this->cur_offset = (qpdf_offset_t)this->buf->getSize() + offset; | |
| 297 | - break; | |
| 298 | - | |
| 299 | - case SEEK_CUR: | |
| 300 | - this->cur_offset += offset; | |
| 301 | - break; | |
| 302 | - | |
| 303 | - default: | |
| 304 | - throw std::logic_error( | |
| 305 | - "INTERNAL ERROR: invalid argument to BufferInputSource::seek"); | |
| 306 | - break; | |
| 307 | - } | |
| 308 | - | |
| 309 | - if (this->cur_offset < 0) | |
| 310 | - { | |
| 311 | - throw std::runtime_error( | |
| 312 | - this->description + ": seek before beginning of buffer"); | |
| 313 | - } | |
| 314 | -} | |
| 315 | - | |
| 316 | -void | |
| 317 | -QPDF::BufferInputSource::rewind() | |
| 318 | -{ | |
| 319 | - this->cur_offset = 0; | |
| 320 | -} | |
| 321 | - | |
| 322 | -size_t | |
| 323 | -QPDF::BufferInputSource::read(char* buffer, size_t length) | |
| 324 | -{ | |
| 325 | - if (this->cur_offset < 0) | |
| 326 | - { | |
| 327 | - throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); | |
| 328 | - } | |
| 329 | - qpdf_offset_t end_pos = (qpdf_offset_t) this->buf->getSize(); | |
| 330 | - if (this->cur_offset >= end_pos) | |
| 331 | - { | |
| 332 | - this->last_offset = end_pos; | |
| 333 | - return 0; | |
| 334 | - } | |
| 335 | - | |
| 336 | - this->last_offset = this->cur_offset; | |
| 337 | - size_t len = std::min((size_t)(end_pos - this->cur_offset), length); | |
| 338 | - memcpy(buffer, buf->getBuffer() + this->cur_offset, len); | |
| 339 | - this->cur_offset += len; | |
| 340 | - return len; | |
| 341 | -} | |
| 342 | - | |
| 343 | -void | |
| 344 | -QPDF::BufferInputSource::unreadCh(char ch) | |
| 345 | -{ | |
| 346 | - if (this->cur_offset > 0) | |
| 347 | - { | |
| 348 | - --this->cur_offset; | |
| 349 | - } | |
| 350 | -} | |
| 351 | 41 | |
| 352 | 42 | QPDF::ObjGen::ObjGen(int o = 0, int g = 0) : |
| 353 | 43 | obj(o), | ... | ... |
libqpdf/build.mk
| ... | ... | @@ -8,6 +8,9 @@ SRCS_libqpdf = \ |
| 8 | 8 | libqpdf/BitStream.cc \ |
| 9 | 9 | libqpdf/BitWriter.cc \ |
| 10 | 10 | libqpdf/Buffer.cc \ |
| 11 | + libqpdf/BufferInputSource.cc \ | |
| 12 | + libqpdf/FileInputSource.cc \ | |
| 13 | + libqpdf/InputSource.cc \ | |
| 11 | 14 | libqpdf/MD5.cc \ |
| 12 | 15 | libqpdf/PCRE.cc \ |
| 13 | 16 | libqpdf/Pipeline.cc \ | ... | ... |