diff --git a/common/config-file.cpp b/common/config-file.cpp index 42d67109fad..b01f7597822 100644 --- a/common/config-file.cpp +++ b/common/config-file.cpp @@ -88,7 +88,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { while (!stream.eos()) { lineno++; - if (!stream.readLine(buf, MAXLINELEN)) + if (!stream.readLine_OLD(buf, MAXLINELEN)) break; if (buf[0] == '#') { diff --git a/common/stream.cpp b/common/stream.cpp index e06cc284158..1ca741483e7 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -86,7 +86,7 @@ void MemoryReadStream::seek(int32 offs, int whence) { #define LF 0x0A #define CR 0x0D -char *SeekableReadStream::readLine(char *buf, size_t bufSize) { +char *SeekableReadStream::readLine_OLD(char *buf, size_t bufSize) { assert(buf && bufSize > 0); char *p = buf; size_t len = 0; @@ -202,6 +202,20 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) { return buf; } +String SeekableReadStream::readLine() { + // Read a line + String line; + while (line.lastChar() != '\n') { + char buf[256]; + if (!readLine_NEW(buf, 256)) + break; + line += buf; + } + + return line; +} + + uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) { dataSize = MIN(dataSize, _end - _pos); diff --git a/common/stream.h b/common/stream.h index 01a946e6856..81bb3dc91a4 100644 --- a/common/stream.h +++ b/common/stream.h @@ -320,9 +320,10 @@ public: * Read one line of text from a CR or CR/LF terminated plain text file. * This method is a rough analog of the (f)gets function. * - * @bug A main difference (and flaw) in this function is that there is no - * way to detect that a line exceeeds the length of the buffer. - * Code which needs this should use the new readLine_NEW() method instead. + * @deprecated This method has a major flaw: There is no way to detect + * whether a line exceeeds the length of the buffer, resulting in breakage + * when overlong lines are encountered. + * Use readLine_NEW() or readline() instead. * * @param buf the buffer to store into * @param bufSize the size of the buffer @@ -331,16 +332,16 @@ public: * @note The line terminator (CR or CR/LF) is stripped and not inserted * into the buffer. */ - virtual char *readLine(char *buf, size_t bufSize); + virtual char *readLine_OLD(char *buf, size_t bufSize); /** * Reads at most one less than the number of characters specified * by bufSize from the and stores them in the string buf. Reading - * stops when the end of a line is reached (CR, CR/LF or LF), at - * end-of-file or error. The newline, if any, is retained (CR and - * CR/LF are translated to LF = 0xA = '\n'). If any characters are - * read and there is no error, a `\0' character is appended to end - * the string. + * stops when the end of a line is reached (CR, CR/LF or LF), and + * at end-of-file or error. The newline, if any, is retained (CR + * and CR/LF are translated to LF = 0xA = '\n'). If any characters + * are read and there is no error, a `\0' character is appended + * to end the string. * * Upon successful completion, return a pointer to the string. If * end-of-file occurs before any characters are read, returns NULL @@ -354,6 +355,19 @@ public: * @return a pointer to the read string, or NULL if an error occurred */ virtual char *readLine_NEW(char *s, size_t bufSize); + + + /** + * Reads a full line and returns it as a Common::String. Reading + * stops when the end of a line is reached (CR, CR/LF or LF), and + * at end-of-file or error. + * + * Upon successful completion, return a string with the content + * of the line, *without* the end of a line marker. This method + * does not indicate whether an error occured. Callers muse use + * ioFailed() or eos() to determine whether an exception occurred. + */ + virtual String readLine(); }; /** diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp index d3e4d0dd312..5e3885b7027 100644 --- a/engines/drascula/saveload.cpp +++ b/engines/drascula/saveload.cpp @@ -50,7 +50,7 @@ bool DrasculaEngine::saveLoadScreen() { } } for (n = 0; n < NUM_SAVES; n++) - sav->readLine(names[n], 23); + sav->readLine_OLD(names[n], 23); delete sav; loadPic("savescr.alg", bgSurface, HALF_PAL); diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index c51daa84c48..e028f5e0f1b 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -251,7 +251,7 @@ void TextviewView::processLines() { error("Attempted to read past end of response file"); while (!_script->eos()) { - _script->readLine(_currentLine, 79); + _script->readLine_OLD(_currentLine, 79); // Commented out line, so go loop for another if (_currentLine[0] == '#') @@ -601,7 +601,7 @@ void AnimviewView::processLines() { } while (!_script->eos()) { - _script->readLine(_currentLine, 79); + _script->readLine_OLD(_currentLine, 79); // Process the line char *cStart = strchr(_currentLine, '-'); diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index bde4f7f6d6a..7611adcddd9 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -293,7 +293,7 @@ SaveStateList ParallactionMetaEngine::listSaves(const char *target) const { if (slotNum >= 0 && slotNum <= 99) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { - in->readLine(saveDesc, 199); + in->readLine_OLD(saveDesc, 199); saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file)); delete in; } diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp index b59863947ea..9c6173775d4 100644 --- a/engines/parallaction/saveload.cpp +++ b/engines/parallaction/saveload.cpp @@ -114,25 +114,25 @@ void SaveLoad_ns::doLoadGame(uint16 slot) { char n[16]; char l[16]; - f->readLine(s, 199); + f->readLine_OLD(s, 199); - f->readLine(n, 15); + f->readLine_OLD(n, 15); - f->readLine(l, 15); + f->readLine_OLD(l, 15); - f->readLine(s, 15); + f->readLine_OLD(s, 15); _vm->_location._startPosition.x = atoi(s); - f->readLine(s, 15); + f->readLine_OLD(s, 15); _vm->_location._startPosition.y = atoi(s); - f->readLine(s, 15); + f->readLine_OLD(s, 15); _score = atoi(s); - f->readLine(s, 15); + f->readLine_OLD(s, 15); _globalFlags = atoi(s); - f->readLine(s, 15); + f->readLine_OLD(s, 15); // TODO (LIST): unify (and parametrize) calls to freeZones. // We aren't calling freeAnimations because it is not needed, since @@ -147,12 +147,12 @@ void SaveLoad_ns::doLoadGame(uint16 slot) { uint16 _si; for (_si = 0; _si < _vm->_numLocations; _si++) { - f->readLine(s, 20); + f->readLine_OLD(s, 20); s[strlen(s)] = '\0'; strcpy(_vm->_locationNames[_si], s); - f->readLine(s, 15); + f->readLine_OLD(s, 15); _vm->_localFlags[_si] = atoi(s); } @@ -161,10 +161,10 @@ void SaveLoad_ns::doLoadGame(uint16 slot) { uint32 value; for (_si = 0; _si < 30; _si++) { - f->readLine(s, 15); + f->readLine_OLD(s, 15); value = atoi(s); - f->readLine(s, 15); + f->readLine_OLD(s, 15); name = atoi(s); _vm->addInventoryItem(name, value); @@ -351,7 +351,7 @@ int SaveLoad_ns::buildSaveFileList(Common::StringList& l) { Common::InSaveFile *f = getInSaveFile(i); if (f) { - f->readLine(buf, 199); + f->readLine_OLD(buf, 199); delete f; count++; @@ -431,7 +431,7 @@ void SaveLoad_ns::setPartComplete(const char *part) { Common::InSaveFile *inFile = getInSaveFile(SPECIAL_SAVESLOT); if (inFile) { - inFile->readLine(buf, 29); + inFile->readLine_OLD(buf, 29); delete inFile; if (strstr(buf, part)) { @@ -455,7 +455,7 @@ void SaveLoad_ns::getGamePartProgress(bool *complete, int size) { char buf[30]; Common::InSaveFile *inFile = getInSaveFile(SPECIAL_SAVESLOT); - inFile->readLine(buf, 29); + inFile->readLine_OLD(buf, 29); delete inFile; complete[0] = strstr(buf, "dino"); diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp index b3bd663baf3..38d841e96aa 100644 --- a/engines/queen/resource.cpp +++ b/engines/queen/resource.cpp @@ -132,7 +132,7 @@ void Resource::loadTextFile(const char *filename, Common::StringList &stringList seekResourceFile(re->bundle, re->offset); char buf[512]; Common::SeekableSubReadStream stream(&_resourceFile, re->offset, re->offset + re->size); - while (stream.readLine(buf, 512)) { + while (stream.readLine_OLD(buf, 512)) { stringList.push_back(buf); } } diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index caf766ed9fc..3e15429e44d 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -189,7 +189,7 @@ bool MoviePlayer::load(uint32 id) { int lastEnd = -1; _movieTexts.clear(); - while (f.readLine(line, sizeof(line))) { + while (f.readLine_OLD(line, sizeof(line))) { lineNo++; if (line[0] == '#' || line[0] == 0) { continue; diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp index 880234aab00..326f90cd826 100644 --- a/engines/sword2/resman.cpp +++ b/engines/sword2/resman.cpp @@ -113,7 +113,7 @@ bool ResourceManager::init() { // The resource.inf file is a simple text file containing the names of // all the resource files. - while (file.readLine(_resFiles[_totalClusters].fileName, sizeof(_resFiles[_totalClusters].fileName))) { + while (file.readLine_OLD(_resFiles[_totalClusters].fileName, sizeof(_resFiles[_totalClusters].fileName))) { _resFiles[_totalClusters].numEntries = -1; _resFiles[_totalClusters].entryTab = NULL; if (++_totalClusters >= MAX_res_files) { diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp index b2fcc45c9c9..1faef01939a 100644 --- a/engines/sword2/screen.cpp +++ b/engines/sword2/screen.cpp @@ -919,7 +919,7 @@ void Screen::rollCredits() { while (1) { char buffer[80]; - char *line = f.readLine(buffer, sizeof(buffer)); + char *line = f.readLine_OLD(buffer, sizeof(buffer)); if (!line || *line == 0) { if (!hasCenterMark) { diff --git a/engines/sword2/startup.cpp b/engines/sword2/startup.cpp index 18413848972..2d19ed6bf95 100644 --- a/engines/sword2/startup.cpp +++ b/engines/sword2/startup.cpp @@ -68,7 +68,7 @@ bool Sword2Engine::initStartMenu() { int lineno = 0; - while (fp.readLine(buf, sizeof(buf))) { + while (fp.readLine_OLD(buf, sizeof(buf))) { char *errptr; int id;