Merge branch 'master' of git://github.com/AlericInglewood/SingularityViewer

This commit is contained in:
Latif Khalifa
2013-09-17 21:41:58 +02:00

View File

@@ -127,73 +127,79 @@ void LLLogChat::saveHistory(std::string const& filename, std::string line)
} }
} }
const std::streamoff BUFFER_SIZE(4096); static long const LOG_RECALL_BUFSIZ = 2048;
// Read a chunk of size from pos in ifstr and prepend it to data void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogLineType, std::string, void*), void* userdata)
// return that chunk's newline count
U32 read_chunk(llifstream& ifstr, const std::streamoff& pos, U32 size, std::string& data)
{ {
char buffer[BUFFER_SIZE]; bool filename_empty = filename.empty();
ifstr.seekg(pos); if (filename_empty)
ifstr.read(buffer, size);
data.insert(0, buffer, size);
return std::count(buffer, buffer + size, '\n');
}
void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogLineType,std::string,void*), void* userdata)
{
if(!filename.size())
{ {
llwarns << "Filename is Empty!" << llendl; llwarns << "filename is empty!" << llendl;
return ;
} }
else while(1) // So we can use break.
llifstream ifstr(makeLogFileName(filename));
if (!ifstr.is_open())
{
callback(LOG_EMPTY,LLStringUtil::null,userdata);
}
else
{ {
// The number of lines to return.
static const LLCachedControl<U32> lines("LogShowHistoryLines", 32); static const LLCachedControl<U32> lines("LogShowHistoryLines", 32);
ifstr.seekg(-1, std::ios_base::end); if (lines == 0) break;
if (!lines || !ifstr)
{
callback(LOG_EMPTY,LLStringUtil::null,userdata);
return;
}
std::string data; // Open the log file.
U32 nlines = 0; LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "rb");
if (ifstr.get() != '\n') // in case file doesn't end with a newline if (!fptr) break;
{
data.push_back('\n');
++nlines;
}
// Read BUFFER_SIZE byte chunks until we have enough endlines accumulated // Set pos to point to the last character of the file, if any.
for(std::streamoff pos = ifstr.tellg() - BUFFER_SIZE; nlines < lines+1; pos -= BUFFER_SIZE) if (fseek(fptr, 0, SEEK_END)) break;
long pos = ftell(fptr) - 1;
if (pos < 0) break;
char buffer[LOG_RECALL_BUFSIZ];
bool error = false;
int nlines = 0;
while (pos > 0 && nlines < lines)
{ {
if (pos > 0) // Read the LOG_RECALL_BUFSIZ characters before pos.
size_t size = llmin(LOG_RECALL_BUFSIZ, pos);
pos -= size;
fseek(fptr, pos, SEEK_SET);
size_t len = fread(buffer, 1, size, fptr);
error = len != size;
if (error) break;
// Count the number of newlines in it and set pos to the beginning of the first line to return when we found enough.
for (char const* p = buffer + size - 1; p >= buffer; --p)
{ {
nlines += read_chunk(ifstr, pos, BUFFER_SIZE, data); if (*p == '\n')
} {
else // Ran out of file read the remaining from the start if (++nlines == lines)
{ {
nlines += read_chunk(ifstr, 0, pos + BUFFER_SIZE, data); pos += p - buffer + 1;
break; break;
}
}
} }
} }
if (error)
// Break data into lines
std::istringstream sstr(data);
for (std::string line; nlines > 0 && getline(sstr, line); --nlines)
{ {
if (nlines <= lines) fclose(fptr);
{ break;
callback(LOG_LINE, line, userdata);
}
} }
callback(LOG_END,LLStringUtil::null,userdata);
// Set the file pointer at the first line to return.
fseek(fptr, pos, SEEK_SET);
// Read lines from the file one by one until we reach the end of the file.
while (fgets(buffer, LOG_RECALL_BUFSIZ, fptr))
{
size_t len = strlen(buffer);
if (buffer[len - 1] == '\n') // In case the log file doesn't end on a new-line (is that even possible?)
{
buffer[len - 1] = '\0';
}
callback(LOG_LINE, buffer, userdata);
}
fclose(fptr);
callback(LOG_END, LLStringUtil::null, userdata);
return;
} }
callback(LOG_EMPTY, LLStringUtil::null, userdata);
} }