2 * © 2008 by David Roden <droden@gmail.com>
8 #include "CollectionReader.h"
9 #include "GlobalSettings.h"
11 CollectionReader::CollectionReader(ReaderInput* readerInput) {
12 this->readerInput = readerInput;
16 CollectionReader::~CollectionReader() {
19 bool CollectionReader::isLineBreakPresent() {
20 size_t indexOfLineBreak = growingBuffer.indexOf('\n');
21 GlobalSettings::isVerbose() && (indexOfLineBreak != (size_t) -1) && fprintf(stderr, "[%s:%d] found line break at %d.\n", __FILE__, __LINE__, indexOfLineBreak);
22 GlobalSettings::isVerbose() && (indexOfLineBreak == (size_t) -1) && fprintf(stderr, "[%s:%d] could not find line break.\n", __FILE__, __LINE__);
23 return indexOfLineBreak != (size_t) -1;
26 StringTag* CollectionReader::readStringTag(bool header) {
29 if (!ensureBufferCapacity(2)) {
32 growingBuffer.read(&unknown, 2);
35 if (!ensureBufferCapacity(1)) {
38 growingBuffer.read(&tagName, 1);
39 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag name %d.\n", __FILE__, __LINE__, tagName);
40 uint16_t tagLength = 0;
41 if (!ensureBufferCapacity(2)) {
44 growingBuffer.read(&tagLength, 2);
45 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag length %d.\n", __FILE__, __LINE__, tagLength);
46 char* tagValue = (char*) malloc(tagLength + 1);
47 if (!ensureBufferCapacity(tagLength)) {
50 growingBuffer.read(tagValue, tagLength);
51 tagValue[tagLength] = '\0';
52 StringTag* stringTag = new StringTag(tagName, tagValue);
57 BlobTag* CollectionReader::readBlobTag(bool header) {
60 if (!ensureBufferCapacity(2)) {
63 growingBuffer.read(&unknown, 2);
66 if (!ensureBufferCapacity(1)) {
69 growingBuffer.read(&tagName, 1);
70 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag name %d.\n", __FILE__, __LINE__, tagName);
71 uint32_t tagLength = 0;
72 if (!ensureBufferCapacity(4)) {
75 growingBuffer.read(&tagLength, 4);
76 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag length %d.\n", __FILE__, __LINE__, tagLength);
77 void* tagValue = (char*) malloc(tagLength);
78 if (!ensureBufferCapacity(tagLength)) {
81 growingBuffer.read(tagValue, tagLength);
82 BlobTag* blobTag = new BlobTag(tagName, tagValue, tagLength);
87 ED2KLink* CollectionReader::getNextLink() {
88 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
89 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
93 identifyCollectionType();
94 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
95 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
100 if (isTextCollection) {
101 while (!readerInput->isEOF() && !isLineBreakPresent()) {
104 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
105 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
108 size_t indexOfLineBreak = growingBuffer.indexOf('\n');
110 if (indexOfLineBreak == (size_t) -1) {
111 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not find line break, using remainder of file.\n", __FILE__, __LINE__);
112 indexOfLineBreak = growingBuffer.getRemaining();
113 line = (char*) malloc(indexOfLineBreak + 1);
114 growingBuffer.read(line, indexOfLineBreak);
115 line[indexOfLineBreak] = '\0';
117 line = (char*) malloc(indexOfLineBreak + 1);
118 growingBuffer.read(line, indexOfLineBreak + 1);
119 if (line[indexOfLineBreak] == '\n') {
120 line[indexOfLineBreak] = '\0';
122 if (line[indexOfLineBreak - 1] == '\r') {
123 line[indexOfLineBreak - 1] = '\0';
127 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] got line: %s\n", __FILE__, __LINE__, line);
128 ED2KLink* ed2kLink = ED2KLink::parseED2KLink(line);
133 if (!ensureBufferCapacity(4)) {
136 uint32_t headerTagCount = 0;
137 growingBuffer.read(&headerTagCount, 4);
138 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d header tags.\n", __FILE__, __LINE__, headerTagCount);
139 for (uint32_t headerTagIndex = 0; headerTagIndex < headerTagCount; headerTagIndex++) {
141 if (!ensureBufferCapacity(1)) {
144 growingBuffer.read(&tagType, 1);
145 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag type %d.\n", __FILE__, __LINE__, tagType);
146 if (tagType == 0x02) {
147 StringTag* stringTag = readStringTag(true);
148 if (stringTag->getId() == 0x01) {
149 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_FILENAME: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
150 } else if (stringTag->getId() == 0x31) {
151 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_COLLECTIONAUTHOR: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
153 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown string in header: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
155 } else if (tagType == 0x07) {
156 BlobTag* blobTag = readBlobTag(true);
157 if (blobTag->getId() == 0x32) {
158 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_COLLECTIONAUTHORKEY: %d bytes.\n", __FILE__, __LINE__, blobTag->getSize());
160 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown block in header: %d bytes.\n", __FILE__, __LINE__, blobTag->getSize());
163 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown tag type: %02x.\n", __FILE__, __LINE__, tagType);
170 bool CollectionReader::ensureBufferCapacity(size_t byteCount) {
171 while (!readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
172 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] only %d bytes remaning, need at least %d, reading more bytes.\n", __FILE__, __LINE__, growingBuffer.getRemaining(), byteCount);
175 if (readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
176 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] need %d more bytes, but file is EOF.\n", __FILE__, __LINE__, (byteCount - growingBuffer.getRemaining()));
182 void CollectionReader::readMoreBytes() {
186 readBytes = readerInput->read(buffer, 1024);
187 growingBuffer.write(buffer, readBytes);
190 void CollectionReader::identifyCollectionType() {
194 readBytes = readerInput->read(&version, 4);
195 if ((readBytes < 4) || readerInput->isEOF()) {
198 if (version == 0x01) {
199 isTextCollection = false;
201 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified binary collection, version 1\n", __FILE__, __LINE__);
202 } else if (version == 0x02) {
203 isTextCollection = false;
205 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified binary collection, version 2\n", __FILE__, __LINE__);
206 } else if (!strncmp("ed2k", (char*) &version, 4)) {
207 isTextCollection = true;
208 growingBuffer.write(&version, 4);
209 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified text collection\n", __FILE__, __LINE__);
211 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not identify collection!\n", __FILE__, __LINE__);