add method to ensure buffer capacity
[ecparse.git] / CollectionReader.cpp
1 /**
2  * © 2008 by David Roden <droden@gmail.com>
3  */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include "CollectionReader.h"
8 #include "GlobalSettings.h"
9
10 CollectionReader::CollectionReader(ReaderInput* readerInput) {
11         this->readerInput = readerInput;
12         firstLink = true;
13 }
14
15 CollectionReader::~CollectionReader() {
16 }
17
18 bool CollectionReader::isLineBreakPresent() {
19         size_t indexOfLineBreak = growingBuffer.indexOf('\n');
20         GlobalSettings::isVerbose() && (indexOfLineBreak != (size_t) -1) && fprintf(stderr, "[%s:%d] found line break at %d.\n", __FILE__, __LINE__, indexOfLineBreak);
21         GlobalSettings::isVerbose() && (indexOfLineBreak == (size_t) -1) && fprintf(stderr, "[%s:%d] could not find line break.\n", __FILE__, __LINE__);
22         return indexOfLineBreak != (size_t) -1;
23 }
24
25 ED2KLink* CollectionReader::getNextLink() {
26         if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
27                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
28                 return NULL;
29         }
30         if (firstLink) {
31                 identifyCollectionType();
32                 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
33                         GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
34                         return NULL;
35                 }
36                 firstLink = false;
37         }
38         if (isTextCollection) {
39                 while (!readerInput->isEOF() && !isLineBreakPresent()) {
40                         readMoreBytes();
41                 }
42                 if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
43                         GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
44                         return NULL;
45                 }
46                 size_t indexOfLineBreak = growingBuffer.indexOf('\n');
47                 char* line;
48                 if (indexOfLineBreak == (size_t) -1) {
49                         GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not find line break, using remainder of file.\n", __FILE__, __LINE__);
50                         indexOfLineBreak = growingBuffer.getRemaining();
51                         line = (char*) malloc(indexOfLineBreak + 1);
52                         growingBuffer.read(line, indexOfLineBreak);
53                         line[indexOfLineBreak] = '\0';
54                 } else {
55                         line = (char*) malloc(indexOfLineBreak + 1);
56                         growingBuffer.read(line, indexOfLineBreak + 1);
57                         if (line[indexOfLineBreak] == '\n') {
58                                 line[indexOfLineBreak] = '\0';
59                         }
60                         if (line[indexOfLineBreak - 1] == '\r') {
61                                 line[indexOfLineBreak - 1] = '\0';
62                         }
63                 }
64                 growingBuffer.cut();
65                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] got line: %s\n", __FILE__, __LINE__, line);
66                 ED2KLink* ed2kLink = ED2KLink::parseED2KLink(line);
67                 free(line);
68                 return ed2kLink;
69         } else {
70         }
71         return NULL;
72 }
73
74 bool CollectionReader::ensureBufferCapacity(size_t byteCount) {
75         while (!readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
76                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] only %d bytes remaning, need at least %d, reading more bytes.\n", __FILE__, __LINE__, growingBuffer.getRemaining(), byteCount);
77                 readMoreBytes();
78         }
79         if (readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
80                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] need %d more bytes, but file is EOF.\n", __FILE__, __LINE__, (byteCount - growingBuffer.getRemaining()));
81                 return false;
82         }
83         return true;
84 }
85
86 void CollectionReader::readMoreBytes() {
87         char buffer[1024];
88         size_t readBytes;
89
90         readBytes = readerInput->read(buffer, 1024);
91         growingBuffer.write(buffer, readBytes);
92 }
93
94 void CollectionReader::identifyCollectionType() {
95         int version;
96         size_t readBytes;
97
98         readBytes = readerInput->read(&version, 4);
99         if ((readBytes < 4) || readerInput->isEOF()) {
100                 return;
101         }
102         if (version == 0x01) {
103                 isTextCollection = false;
104                 this->version = 1;
105                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified binary collection, version 1\n", __FILE__, __LINE__);
106         } else if (version == 0x02) {
107                 isTextCollection = false;
108                 this->version = 2;
109                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified binary collection, version 2\n", __FILE__, __LINE__);
110         } else if (!strncmp("ed2k", (char*) &version, 4)) {
111                 isTextCollection = true;
112                 growingBuffer.write(&version, 4);
113                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified text collection\n", __FILE__, __LINE__);
114         } else  {
115                 GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not identify collection!\n", __FILE__, __LINE__);
116         }
117 }
118