Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for ANSI color sequences(#338) #655

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/logdata/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_library(
${CMAKE_CURRENT_SOURCE_DIR}/include/fileholder.h
${CMAKE_CURRENT_SOURCE_DIR}/include/filedigest.h
${CMAKE_CURRENT_SOURCE_DIR}/include/readablesize.h
${CMAKE_CURRENT_SOURCE_DIR}/include/onelinelog.h
${CMAKE_CURRENT_SOURCE_DIR}/src/abstractlogdata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/blockpool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/compressedlinestorage.cpp
Expand All @@ -27,6 +28,7 @@ add_library(
${CMAKE_CURRENT_SOURCE_DIR}/src/fileholder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/filedigest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/readablesize.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/onelinelog.cpp
src/filedigest.cpp
)

Expand Down
16 changes: 14 additions & 2 deletions src/logdata/include/abstractlogdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,18 @@
#include <QTextCodec>

#include "linetypes.h"
#include "onelinelog.h"

// Base class representing a set of data.
// It can be either a full set or a filtered set.
class AbstractLogData : public QObject {
Q_OBJECT

public:
public:
// Returns then line as OneLineLog structure, You can do anything with it.
OneLineLog getOneLineLog( LineNumber line ) const;
// Returns a set of lines as a set of OneLineLog structure, You can do anything with it.
klogg::vector<OneLineLog> getOneLineLogs( LineNumber firstLine, LinesCount number ) const;
// Returns the line passed as a QString
QString getLineString( LineNumber line ) const;
// Returns the line passed as a QString, with tabs expanded
Expand Down Expand Up @@ -92,6 +97,12 @@ class AbstractLogData : public QObject {
Q_DECLARE_FLAGS( LineType, LineTypeFlags )

protected:
// Returns then line as OneLineLog structure, You can do anything with it.
virtual OneLineLog doGetOneLineLog( LineNumber line ) const = 0;
// Returns a set of lines as a set of OneLineLog structure, You can do anything with it.
virtual klogg::vector<OneLineLog> doGetOneLineLogs( LineNumber firstLine,
LinesCount number ) const
= 0;
// Internal function called to get a given line
virtual QString doGetLineString( LineNumber line ) const = 0;
// Internal function called to get a given line
Expand All @@ -100,7 +111,8 @@ class AbstractLogData : public QObject {
virtual klogg::vector<QString> doGetLines( LineNumber first_line, LinesCount number ) const = 0;
// Internal function called to get a set of expanded lines
virtual klogg::vector<QString> doGetExpandedLines( LineNumber first_line,
LinesCount number ) const = 0;
LinesCount number ) const
= 0;

// Internal function called to get the index of given line
virtual LineNumber doGetLineNumber( LineNumber index ) const = 0;
Expand Down
12 changes: 8 additions & 4 deletions src/logdata/include/logdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@
class LogFilteredData;

// Thrown when trying to attach an already attached LogData
class CantReattachErr {
};
class CantReattachErr {};

// Represents a complete set of data to be displayed (ie. a log file content)
// This class is thread-safe.
Expand Down Expand Up @@ -102,7 +101,7 @@ class LogData : public AbstractLogData {
// Get the auto-detected encoding for the indexed text.
QTextCodec* getDetectedEncoding() const;

void setPrefilter(const QString& prefilterPattern);
void setPrefilter( const QString& prefilterPattern );

struct RawLines {
LineNumber startLine;
Expand All @@ -116,6 +115,8 @@ class LogData : public AbstractLogData {

public:
klogg::vector<QString> decodeLines() const;
using OneLineLogConstructor = std::function<OneLineLog( const char*, OneLineLog::Length )>;
klogg::vector<OneLineLog> splitLines( OneLineLogConstructor makeOneLineLog ) const;
klogg::vector<std::string_view> buildUtf8View() const;

private:
Expand Down Expand Up @@ -144,6 +145,9 @@ class LogData : public AbstractLogData {

private:
// Implementation of virtual functions
OneLineLog doGetOneLineLog( LineNumber line ) const override;
klogg::vector<OneLineLog> doGetOneLineLogs( LineNumber firstLine,
LinesCount number ) const override;
QString doGetLineString( LineNumber line ) const override;
QString doGetExpandedLineString( LineNumber line ) const override;
klogg::vector<QString> doGetLines( LineNumber first, LinesCount number ) const override;
Expand All @@ -160,7 +164,7 @@ class LogData : public AbstractLogData {
void reOpenFile() const;

klogg::vector<QString> getLinesFromFile( LineNumber first, LinesCount number,
QString ( *processLine )( QString&& ) ) const;
QString ( *processLine )( QString&& ) ) const;

private:
mutable std::unique_ptr<FileHolder> attached_file_;
Expand Down
2 changes: 2 additions & 0 deletions src/logdata/include/logfiltereddata.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ class LogFilteredData : public AbstractLogData {

private:
// Implementation of virtual functions
OneLineLog doGetOneLineLog( LineNumber line ) const override;
klogg::vector<OneLineLog> doGetOneLineLogs( LineNumber firstLine, LinesCount number ) const override;
QString doGetLineString( LineNumber line ) const override;
QString doGetExpandedLineString( LineNumber line ) const override;
klogg::vector<QString> doGetLines( LineNumber first, LinesCount number ) const override;
Expand Down
47 changes: 47 additions & 0 deletions src/logdata/include/onelinelog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Created by marvin on 23-7-26.
//
#pragma once

#include <memory>

#include <QByteArray>
#include <QRegularExpression>
#include <QString>

#include "encodingdetector.h"

class OneLineLog {
public:
using Length = QByteArray::size_type;

public:
OneLineLog() = default;
OneLineLog( const char* data, Length len, std::shared_ptr<TextDecoder> dec,
std::shared_ptr<QRegularExpression> reg );

~OneLineLog() = default;

// no copying allowed
OneLineLog( const OneLineLog& ) = delete;
OneLineLog& operator=( const OneLineLog& ) = delete;

OneLineLog& operator=( OneLineLog&& ) = default;
OneLineLog( OneLineLog&& ) = default;

QString string() const;

QString expandedString() const;

QString process( std::function<void( QString& )> fn ) const;

inline bool empty() const
{
return buffer_.isEmpty() || !decoder_ || !reg_;
}

private:
QByteArray buffer_;
std::shared_ptr<TextDecoder> decoder_;
std::shared_ptr<QRegularExpression> reg_;
};
13 changes: 12 additions & 1 deletion src/logdata/src/abstractlogdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@

#include "abstractlogdata.h"

OneLineLog AbstractLogData::getOneLineLog( LineNumber line ) const
{
return doGetOneLineLog( line );
}

klogg::vector<OneLineLog> AbstractLogData::getOneLineLogs( LineNumber firstLine,
LinesCount number ) const
{
return doGetOneLineLogs( firstLine, number );
}

// Simple wrapper in order to use a clean Template Method
QString AbstractLogData::getLineString( LineNumber line ) const
{
Expand All @@ -64,7 +75,7 @@ klogg::vector<QString> AbstractLogData::getLines( LineNumber first_line, LinesCo

// Simple wrapper in order to use a clean Template Method
klogg::vector<QString> AbstractLogData::getExpandedLines( LineNumber first_line,
LinesCount number ) const
LinesCount number ) const
{
return doGetExpandedLines( first_line, number );
}
Expand Down
97 changes: 97 additions & 0 deletions src/logdata/src/logdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,49 @@ QTextCodec* LogData::doGetDisplayEncoding() const
return codec_.codec();
}

OneLineLog LogData::doGetOneLineLog( LineNumber line ) const
{
auto lines = doGetOneLineLogs( line, 1_lcount );
return lines.empty() ? OneLineLog{} : std::move( lines.front() );
}

klogg::vector<OneLineLog> LogData::doGetOneLineLogs( LineNumber firstLine, LinesCount number ) const
{
LOG_DEBUG << "firstLine:" << firstLine << " nb:" << number;

if ( number.get() == 0 ) {
return {};
}

klogg::vector<OneLineLog> processedLines;
std::shared_ptr<TextDecoder> dec{ std::make_shared<TextDecoder>( codec_.makeDecoder() ) };
std::shared_ptr<QRegularExpression> reg{ std::make_shared<QRegularExpression>(
prefilterPattern_, QRegularExpression::CaseInsensitiveOption ) };
try {
const auto rawLines = getLinesRaw( firstLine, number );
processedLines = rawLines.splitLines(
[ &dec, &reg ]( const char* log, OneLineLog::Length len ) -> OneLineLog {
return { log, len, dec, reg };
} );

} catch ( const std::bad_alloc& e ) {
LOG_ERROR << "not enough memory " << e.what();
const char* replaceLog = "KLOGG WARNING: not enough memory";
processedLines.emplace_back(
replaceLog, type_safe::narrow_cast<OneLineLog::Length>( ::strlen( replaceLog ) ), dec,
reg );
}

while ( processedLines.size() < number.get() ) {
const char* replaceLog = "KLOGG WARNING: failed to read some lines before this one";
processedLines.emplace_back(
replaceLog, type_safe::narrow_cast<OneLineLog::Length>( ::strlen( replaceLog ) ), dec,
reg );
}

return processedLines;
}

QString LogData::doGetLineString( LineNumber line ) const
{
const auto lines = doGetLines( line, 1_lcount );
Expand Down Expand Up @@ -506,6 +549,60 @@ klogg::vector<QString> LogData::RawLines::decodeLines() const
return decodedLines;
}

klogg::vector<OneLineLog>
LogData::RawLines::splitLines( OneLineLogConstructor makeOneLineLog ) const
{
if ( this->endOfLines.empty() ) {
return {};
}

klogg::vector<OneLineLog> decodedLines;
decodedLines.reserve( this->endOfLines.size() );

try {
qint64 lineStart = 0;
// size_t currentLineIndex = 0;
const auto lineFeedWidth = textDecoder.encodingParams.lineFeedWidth;
for ( const auto& lineEnd : this->endOfLines ) {
const auto length = lineEnd - lineStart - lineFeedWidth;

constexpr auto maxlength = std::numeric_limits<int>::max() / 2;
if ( length >= maxlength ) {
const char* log = "KLOGG WARNING: this line is too long";
decodedLines.emplace_back( makeOneLineLog(
log, type_safe::narrow_cast<OneLineLog::Length>( ::strlen( log ) ) ) );
break;
}

if ( lineStart + length > klogg::ssize( buffer ) ) {
const char* log = "KLOGG WARNING: file read failed";
decodedLines.emplace_back( makeOneLineLog(
log, type_safe::narrow_cast<OneLineLog::Length>( ::strlen( log ) ) ) );
LOG_WARNING << "not enough data in buffer";
break;
}

decodedLines.emplace_back( makeOneLineLog(
buffer.data() + lineStart, type_safe::narrow_cast<OneLineLog::Length>( length ) ) );

lineStart = lineEnd;
}
} catch ( const std::bad_alloc& ) {
LOG_ERROR << "not enough memory";
const char* log = "KLOGG WARNING: not enough memory";
decodedLines.emplace_back(
makeOneLineLog( log, type_safe::narrow_cast<OneLineLog::Length>( ::strlen( log ) ) ) );
}

while ( decodedLines.size() < this->endOfLines.size() ) {
const char* log = "KLOGG WARNING: failed to decode some lines before this one";
decodedLines.emplace_back(
makeOneLineLog( log, type_safe::narrow_cast<OneLineLog::Length>( ::strlen( log ) ) ) );
}

return decodedLines;
}

klogg::vector<std::string_view> LogData::RawLines::buildUtf8View() const
{
klogg::vector<std::string_view> lines;
Expand Down
28 changes: 25 additions & 3 deletions src/logdata/src/logfiltereddata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,28 @@ LineNumber LogFilteredData::findFilteredLine( LineNumber lineNum ) const
return LineNumber( index );
}

// Implementation of the virtual function.
klogg::vector<OneLineLog> LogFilteredData::doGetOneLineLogs( LineNumber firstLine,
LinesCount number ) const
{
klogg::vector<LineNumber::UnderlyingType> lineNumbers( number.get() );
std::iota( lineNumbers.begin(), lineNumbers.end(), firstLine.get() );

klogg::vector<OneLineLog> logs( number.get() );
std::transform(
lineNumbers.cbegin(), lineNumbers.cend(), logs.begin(),
[ this ]( const auto& idx ) -> auto { return doGetOneLineLog( LineNumber{ idx } ); } );

return logs;
}

// Implementation of the virtual function.
OneLineLog LogFilteredData::doGetOneLineLog( LineNumber index ) const
{
const auto line = findLogDataLine( index );
return sourceLogData_->getOneLineLog( line );
}

// Implementation of the virtual function.
QString LogFilteredData::doGetLineString( LineNumber index ) const
{
Expand All @@ -504,7 +526,7 @@ klogg::vector<QString> LogFilteredData::doGetLines( LineNumber first_line, Lines

// Implementation of the virtual function.
klogg::vector<QString> LogFilteredData::doGetExpandedLines( LineNumber first_line,
LinesCount number ) const
LinesCount number ) const
{
return doGetLines( first_line, number,
[ this ]( const auto& line ) { return doGetExpandedLineString( line ); } );
Expand All @@ -525,9 +547,9 @@ LogFilteredData::doGetLines( LineNumber first_line, LinesCount number,
return lines;
}

LineNumber LogFilteredData::doGetLineNumber(LineNumber index) const
LineNumber LogFilteredData::doGetLineNumber( LineNumber index ) const
{
return getMatchingLineNumber(index);
return getMatchingLineNumber( index );
}

// Implementation of the virtual function.
Expand Down
Loading