Skip to content

Commit

Permalink
feat: add OneLineLog type logdata
Browse files Browse the repository at this point in the history
  • Loading branch information
nowhszh committed Jul 31, 2023
1 parent 88abcec commit ab20712
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 14 deletions.
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();

QString expandedString();

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

inline bool empty()
{
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

0 comments on commit ab20712

Please sign in to comment.