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,6 +21,7 @@ | ||
| 21 | #include <qpdf/QPDFObjectHandle.hh> | 21 | #include <qpdf/QPDFObjectHandle.hh> |
| 22 | #include <qpdf/QPDFTokenizer.hh> | 22 | #include <qpdf/QPDFTokenizer.hh> |
| 23 | #include <qpdf/Buffer.hh> | 23 | #include <qpdf/Buffer.hh> |
| 24 | +#include <qpdf/InputSource.hh> | ||
| 24 | 25 | ||
| 25 | class QPDF_Stream; | 26 | class QPDF_Stream; |
| 26 | class BitStream; | 27 | class BitStream; |
| @@ -474,80 +475,6 @@ class QPDF | @@ -474,80 +475,6 @@ class QPDF | ||
| 474 | private: | 475 | private: |
| 475 | static std::string qpdf_version; | 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 | class ObjGen | 478 | class ObjGen |
| 552 | { | 479 | { |
| 553 | public: | 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,6 +11,8 @@ | ||
| 11 | #include <qpdf/PCRE.hh> | 11 | #include <qpdf/PCRE.hh> |
| 12 | #include <qpdf/Pipeline.hh> | 12 | #include <qpdf/Pipeline.hh> |
| 13 | #include <qpdf/Pl_Discard.hh> | 13 | #include <qpdf/Pl_Discard.hh> |
| 14 | +#include <qpdf/FileInputSource.hh> | ||
| 15 | +#include <qpdf/BufferInputSource.hh> | ||
| 14 | 16 | ||
| 15 | #include <qpdf/QPDFExc.hh> | 17 | #include <qpdf/QPDFExc.hh> |
| 16 | #include <qpdf/QPDF_Null.hh> | 18 | #include <qpdf/QPDF_Null.hh> |
| @@ -36,318 +38,6 @@ static char const* EMPTY_PDF = | @@ -36,318 +38,6 @@ static char const* EMPTY_PDF = | ||
| 36 | "110\n" | 38 | "110\n" |
| 37 | "%%EOF\n"; | 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 | QPDF::ObjGen::ObjGen(int o = 0, int g = 0) : | 42 | QPDF::ObjGen::ObjGen(int o = 0, int g = 0) : |
| 353 | obj(o), | 43 | obj(o), |
libqpdf/build.mk
| @@ -8,6 +8,9 @@ SRCS_libqpdf = \ | @@ -8,6 +8,9 @@ SRCS_libqpdf = \ | ||
| 8 | libqpdf/BitStream.cc \ | 8 | libqpdf/BitStream.cc \ |
| 9 | libqpdf/BitWriter.cc \ | 9 | libqpdf/BitWriter.cc \ |
| 10 | libqpdf/Buffer.cc \ | 10 | libqpdf/Buffer.cc \ |
| 11 | + libqpdf/BufferInputSource.cc \ | ||
| 12 | + libqpdf/FileInputSource.cc \ | ||
| 13 | + libqpdf/InputSource.cc \ | ||
| 11 | libqpdf/MD5.cc \ | 14 | libqpdf/MD5.cc \ |
| 12 | libqpdf/PCRE.cc \ | 15 | libqpdf/PCRE.cc \ |
| 13 | libqpdf/Pipeline.cc \ | 16 | libqpdf/Pipeline.cc \ |