]> gitweb.hamatoma.de Git - reqt/commitdiff
refind: TextFinder
authorhama <hama@siduction.net>
Mon, 13 Apr 2015 22:29:19 +0000 (00:29 +0200)
committerhama <hama@siduction.net>
Mon, 13 Apr 2015 22:29:19 +0000 (00:29 +0200)
appl/refind/filefinder.cpp
appl/refind/mainwindow.cpp
appl/refind/mainwindow.hpp
appl/refind/refind.pro
appl/refind/textfinder.cpp [new file with mode: 0644]
appl/refind/textfinder.hpp [new file with mode: 0644]

index c4262210a73a6bad501673e4615ee6807c7bcd05..b934212bc0ab77286df4a6c1cacb2b36d028b95c 100644 (file)
@@ -11,6 +11,9 @@
 #include "mainwindow.hpp"
 #include "filefinder.hpp"
 
+/**
+ * Constructor.
+ */
 FileFinder::FileFinder() :
             m_lines(0),
             m_patterns(),
@@ -26,8 +29,7 @@ FileFinder::FileFinder() :
             m_countFiles(0),
             m_countDirs(0),
             m_bytes(0),
-            m_excludedDirs()
-{
+            m_excludedDirs(){
    m_youngerThan.setMSecsSinceEpoch(0);
    m_olderThan.setMSecsSinceEpoch(0);
 }
@@ -96,11 +98,11 @@ QString fileSize(int64_t size){
 QString typeOf(QFileInfo& info){
    QString rc;
    if (info.isSymLink()){
-       if (info.isDir())
-           rc = QObject::tr("link (dir)");
-       else
-           rc = QObject::tr("link (file)");
-   } else if (info.isDir())
+      if (info.isDir())
+         rc = QObject::tr("link (dir)");
+      else
+         rc = QObject::tr("link (file)");
+   }else if (info.isDir())
       rc = QObject::tr("dir");
    else
       rc = QObject::tr("file");
@@ -119,9 +121,9 @@ void FileFinder::fillTable(const QString& path, int depth, QTableWidget* table){
    QDir dir(path);
    QDir::Filters filters = m_fileTypes | QDir::NoDotAndDotDot;
    if (m_patterns.count() == 0)
-         entries = dir.entryInfoList(filters, QDir::NoSort);
-      else
-         entries = dir.entryInfoList(m_patterns, filters, QDir::NoSort);
+      entries = dir.entryInfoList(filters, QDir::NoSort);
+   else
+      entries = dir.entryInfoList(m_patterns, filters, QDir::NoSort);
    QList <QFileInfo>::iterator it;
    QString relativePath = path.mid(1 + m_baseDir.length());
    QString node, ext;
@@ -162,8 +164,8 @@ void FileFinder::fillTable(const QString& path, int depth, QTableWidget* table){
       bool filtered = m_excludedDirs.length() > 0;
       for (it = entries.begin(); it != entries.end(); ++it){
          QString node = it->fileName();
-         if (! filtered || !isExcludedDir(node))
-             fillTable(path + QDir::separator() + node, depth + 1, table);
+         if (!filtered || !isExcludedDir(node))
+            fillTable(path + QDir::separator() + node, depth + 1, table);
       }
    }
    table->setRowCount(m_lines);
@@ -176,15 +178,15 @@ void FileFinder::fillTable(const QString& path, int depth, QTableWidget* table){
  * @return      <code>true</code>: the node is part of the excluded dirs
  */
 bool FileFinder::isExcludedDir(const QString& node){
-    bool rc = false;
-    QList <QString>::iterator it;
-    for (it = m_excludedDirs.begin(); it != m_excludedDirs.end(); ++it){
-        if (QString::compare(node, *it, Qt::CaseInsensitive) == 0){
-            rc = true;
-            break;
-        }
-    }
-    return rc;
+   bool rc = false;
+   QList <QString>::iterator it;
+   for (it = m_excludedDirs.begin(); it != m_excludedDirs.end(); ++it){
+      if (QString::compare(node, *it, Qt::CaseInsensitive) == 0){
+         rc = true;
+         break;
+      }
+   }
+   return rc;
 }
 
 /**
@@ -214,16 +216,15 @@ bool FileFinder::isValid(const QFileInfo& file){
  * @param baseDir   the directory where the search starts
  */
 void FileFinder::setBaseDir(const QString& baseDir){
-    m_baseDir = baseDir;
+   m_baseDir = baseDir;
 }
 
 /**
  * Sets the list of excluded directories.
  * @param excludedDirs  each entry of this list will not be entered for search
  */
-void FileFinder::setExcludedDirs(const QStringList& excludedDirs)
-{
-    m_excludedDirs = excludedDirs;
+void FileFinder::setExcludedDirs(const QStringList& excludedDirs){
+   m_excludedDirs = excludedDirs;
 }
 
 /**
index e2f4529c91f703a18a5d8ac0caeb778d1c0a5c63..6ee4f2ba87a617c87f9bcbdedf185ce9581a84eb 100644 (file)
@@ -29,12 +29,14 @@ MainWindow::MainWindow(const QString& startDir, QWidget *parent) :
             m_errors(0){
    ui->setupUi(this);
    m_statusMessage = new QLabel(tr("Willkommen bei refind"));
-   ui->comboBoxDirectory->setCurrentText(startDir.isEmpty() ? QDir::currentPath() : startDir);
+   ui->comboBoxDirectory->setCurrentText(
+      startDir.isEmpty() ? QDir::currentPath() : startDir);
    statusBar()->addWidget(m_statusMessage);
    connect(ui->pushButtonSearch, SIGNAL(clicked()), this, SLOT(search()));
    connect(ui->pushButtonSearch2, SIGNAL(clicked()), this, SLOT(search()));
    connect(ui->pushButtonUp, SIGNAL(clicked()), this, SLOT(up()));
-   connect(ui->pushButtonDirectory, SIGNAL(clicked()), this, SLOT(selectDirectory()));
+   connect(ui->pushButtonDirectory, SIGNAL(clicked()), this,
+      SLOT(selectDirectory()));
    ui->tableWidget->setColumnWidth(TC_NODE, 200);
    ui->tableWidget->setColumnWidth(TC_EXT, 40);
    ui->tableWidget->setColumnWidth(TC_SIZE, 125);
@@ -143,28 +145,28 @@ QString MainWindow::comboText(QComboBox* combo){
  * @return the filetypes selected by the checkboxes
  */
 QDir::Filters MainWindow::buildFileTypes(){
-    QDir::Filters rc = 0;
-    if (ui->checkBoxDirs->isChecked())
-        rc |= QDir::Dirs;
-    if (ui->checkBoxFiles->isChecked())
-        rc |= QDir::Files;
-    if (rc == 0)
-        rc |= QDir::Dirs | QDir::Files;
-    if (! ui->checkBoxLinks->isChecked())
-        rc |= QDir::NoSymLinks;
-    if (ui->checkBoxHidden)
-        rc |= QDir::Hidden | QDir::System;
-    QDir::Filters mask = 0;
-    if (ui->checkBoxWritable->isChecked())
-        mask |= QDir::Writable;
-    if (ui->checkBoxReadable->isChecked())
-        mask |= QDir::Readable;
-    if (ui->checkBoxExecutable->isChecked())
-        mask |= QDir::Executable;
-    if (mask == 0)
-        mask |= QDir::PermissionMask;
-    rc |= mask;
-    return rc;
+   QDir::Filters rc = 0;
+   if (ui->checkBoxDirs->isChecked())
+      rc |= QDir::Dirs;
+   if (ui->checkBoxFiles->isChecked())
+      rc |= QDir::Files;
+   if (rc == 0)
+      rc |= QDir::Dirs | QDir::Files;
+   if (!ui->checkBoxLinks->isChecked())
+      rc |= QDir::NoSymLinks;
+   if (ui->checkBoxHidden)
+      rc |= QDir::Hidden | QDir::System;
+   QDir::Filters mask = 0;
+   if (ui->checkBoxWritable->isChecked())
+      mask |= QDir::Writable;
+   if (ui->checkBoxReadable->isChecked())
+      mask |= QDir::Readable;
+   if (ui->checkBoxExecutable->isChecked())
+      mask |= QDir::Executable;
+   if (mask == 0)
+      mask |= QDir::PermissionMask;
+   rc |= mask;
+   return rc;
 }
 
 /**
@@ -188,12 +190,13 @@ void MainWindow::search(){
       patterns = value.split(",");
    finder.setPatterns(patterns);
    value = ui->comboBoxExcludedDirs->currentText();
-   if (value.indexOf('/')>= 0 || value.indexOf('\\') >= 0)
-       guiError(ui->comboBoxExcludedDirs, tr("no path delimiter allowed"));
-   else if (value.indexOf('*')>= 0)
-       guiError(ui->comboBoxExcludedDirs, tr("no patterns allowed. Do not use '*"));
+   if (value.indexOf('/') >= 0 || value.indexOf('\\') >= 0)
+      guiError(ui->comboBoxExcludedDirs, tr("no path delimiter allowed"));
+   else if (value.indexOf('*') >= 0)
+      guiError(ui->comboBoxExcludedDirs,
+         tr("no patterns allowed. Do not use '*"));
    else if (!value.isEmpty())
-       patterns = value.split(",");
+      patterns = value.split(",");
    finder.setExcludedDirs(patterns);
    if (m_errors == 0){
       clock_t start = clock();
@@ -211,11 +214,10 @@ void MainWindow::search(){
  * Handles the push of the button "select directory".
  */
 void MainWindow::selectDirectory(){
-    QString dir = QFileDialog::getExistingDirectory(this,
-      tr("Select Directory"), ui->comboBoxDirectory->currentText(),
-      QFileDialog::ShowDirsOnly);
-    if (! dir.isEmpty())
-        ui->comboBoxDirectory->setCurrentText(dir);
+   QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"),
+      ui->comboBoxDirectory->currentText(), QFileDialog::ShowDirsOnly);
+   if (!dir.isEmpty())
+      ui->comboBoxDirectory->setCurrentText(dir);
 }
 
 /**
@@ -265,14 +267,14 @@ void MainWindow::setStatusMessage(bool error, const QString& message){
  * @brief Handles the "up" button: go to the parent directory.
  */
 void MainWindow::up(){
-    QString path = ui->comboBoxDirectory->currentText();
+   QString path = ui->comboBoxDirectory->currentText();
    QDir dir(path);
    if (dir.exists()){
-        dir.cdUp();
-        if (dir.exists()){
-            path = dir.absolutePath();
-            ui->comboBoxDirectory->setEditText(path);
-            setInHistory(ui->comboBoxDirectory, path);
-        }
+      dir.cdUp();
+      if (dir.exists()){
+         path = dir.absolutePath();
+         ui->comboBoxDirectory->setEditText(path);
+         setInHistory(ui->comboBoxDirectory, path);
+      }
    }
 }
index 04b0c7b9cdeb4eb3d1ca844a69b8b7f2c42c555c..373ed7b88775a1133442bfcb2fae0d31fd9dce54 100644 (file)
@@ -34,11 +34,10 @@ public:
    explicit MainWindow(const QString& startDir, QWidget *parent = 0);
    ~MainWindow();
 
-
 private slots:
-    void search();
-    void up();
-    void selectDirectory();
+   void search();
+   void up();
+   void selectDirectory();
 
 private:
    QDir::Filters buildFileTypes();
index e4ca5205b6c8ffe0da8d8a37bee8ebffed974672..f0d0ab51bf72c43e6544621b23fe7db32f503055 100644 (file)
@@ -1,30 +1,32 @@
-#-------------------------------------------------\r
-#\r
-# Project created by QtCreator 2015-04-02T23:48:19\r
-#\r
-#-------------------------------------------------\r
-\r
-QT       += core gui\r
-\r
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets\r
-\r
-TARGET = refind\r
-TEMPLATE = app\r
-\r
-INCLUDEPATH = ../.. /usr/include/c++/4.9\r
-\r
-SOURCES += main.cpp\\r
-        mainwindow.cpp \\r
-    ../../base/ReException.cpp \\r
-    ../../base/ReQStringUtil.cpp \\r
-    ../../base/ReLogger.cpp \\r
-    filefinder.cpp\r
-\r
-\r
-HEADERS  += mainwindow.hpp \\r
-    ../../base/rebase.hpp \\r
-    filefinder.hpp \\r
-    ../../base/ReQStringUtil.hpp\r
-\r
-\r
-FORMS    += mainwindow.ui\r
+#-------------------------------------------------
+#
+# Project created by QtCreator 2015-04-02T23:48:19
+#
+#-------------------------------------------------
+
+QT       += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = refind
+TEMPLATE = app
+
+INCLUDEPATH = ../.. /usr/include/c++/4.9
+
+SOURCES += main.cpp\
+        mainwindow.cpp \
+    ../../base/ReException.cpp \
+    ../../base/ReQStringUtil.cpp \
+    ../../base/ReLogger.cpp \
+    filefinder.cpp \
+    textfinder.cpp
+
+
+HEADERS  += mainwindow.hpp \
+    ../../base/rebase.hpp \
+    filefinder.hpp \
+    ../../base/ReQStringUtil.hpp \
+    textfinder.hpp
+
+
+FORMS    += mainwindow.ui
diff --git a/appl/refind/textfinder.cpp b/appl/refind/textfinder.cpp
new file mode 100644 (file)
index 0000000..abaf7da
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+ */
+
+#include "base/rebase.hpp"
+#include "textfinder.hpp"
+
+/**
+ * Constructor.
+ *
+ * @param fullName  path and name of the file
+ * @param length        length of the file
+ * @param ignoreBinary  <code>true</code>: binary files will be ignored
+ */
+TextFinder::TextFinder(const QString& fullName, int64_t length,
+   bool ignoreBinary) :
+            m_ignoreBinary(ignoreBinary),
+            m_filename(fullName),
+            m_length(length),
+            m_file(fullName),
+            m_valid(false){
+   m_valid = m_file.open(QIODevice::ReadOnly);
+}
+
+/**
+ * Destructor.
+ */
+TextFinder::~TextFinder(){
+}
+
+/**
+ * Search a text pattern in the given file.
+ *
+ * @param pattern       a text pattern to search
+ * @param ignoreCase    <code>true</code>: the search must be case insensitive
+ * @param isRegular     <code>true</code>: the pattern is a regular expression
+ * @return              <code>true</code>: the patter was found
+ */
+bool TextFinder::contains(const QString& pattern, bool ignoreCase,
+   bool isRegular){
+   bool rc = false;
+   if (!m_ignoreBinary || !isBinary()){
+      m_file.seek(0);
+      QTextStream stream(&m_file);
+      QString line;
+      if (isRegular){
+         QRegularExpression::PatternOption option =
+                  ignoreCase ?
+                     QRegularExpression::CaseInsensitiveOption :
+                     QRegularExpression::NoPatternOption;
+         QRegularExpression expr(pattern, option);
+         QRegularExpressionMatch match;
+         while (!stream.atEnd()){
+            line = stream.readLine();
+            match = expr.match(line);
+            if (match.hasMatch()){
+               rc = true;
+               break;
+            }
+         }
+      }else{
+         Qt::CaseSensitivity mode =
+                  ignoreCase ? Qt::CaseInsensitive : Qt::CaseSensitive;
+         while (!stream.atEnd()){
+            line = stream.readLine();
+            if (line.indexOf(pattern, 0, mode) >= 0){
+               rc = true;
+               break;
+            }
+         }
+      }
+   }
+   return rc;
+}
+
+/**
+ * Tests whether the file is a binary file.
+ *
+ * @return  <code>true</code>: the file is a binary file
+ */
+bool TextFinder::isBinary(){
+   QByteArray data = m_file.read(64 * 1024);
+   int length = data.length();
+   const char* ptr = reinterpret_cast <const char*>(memchr(data.constData(),
+      '\0', length));
+   bool rc = int(ptr - data.constData()) != length;
+
+   if (!rc)
+      rc = !isText(data);
+
+   return rc;
+}
+
+/**
+ * Tests whether a string contains only text characters.
+ *
+ * @param data      data to inspect
+ * @param trueAscii OUT: <code>true</code>: only 7-bit ASCII character are present
+ * @return          <code>true</code>: the file is a text file
+ */
+bool TextFinder::isText(const QByteArray& data, bool* trueAscii){
+   const uint8_t* ptr = reinterpret_cast <const uint8_t*>(data.constData());
+   bool isAscii = true;
+   uint8_t byte1;
+   bool rc = true;
+   while ((byte1 = *ptr++) != '\0'){
+      // ASCII with control chars:
+      if (byte1 < ' ' && byte1 != '\t' && byte1 != '\n' && byte1 != '\r'){
+         rc = false;
+         break;
+      }
+      if (rc > 0x7f)
+         isAscii = false;
+   }
+   if (trueAscii != NULL)
+      *trueAscii = rc && isAscii;
+   return rc;
+}
+
+/**
+ * Tests whether the file is a binary file.
+ *
+ * @param data      data to inspect
+ * @param trueAscii OUT: <code>true</code>: only 7-bit ASCII character are present
+ * @return          <code>true</code>: the file is an UTF-8 file
+ */
+bool TextFinder::isUTF8(const QByteArray& data, bool* trueAscii) const{
+   const uint8_t* ptr = reinterpret_cast <const uint8_t*>(data.constData());
+   bool isAscii = true;
+   uint8_t byte1;
+   bool rc = true;
+   while ((byte1 = *ptr++) != '\0'){
+      // ASCII with control chars:
+      if ((0x20 <= byte1 && byte1 <= 0x7E) || byte1 == '\t' || byte1 == '\n'
+         || byte1 == '\r'){
+         continue;
+      }
+      isAscii = false;
+      uint8_t byte2 = *ptr++;
+      // non-overlong 2-byte
+      if (0xC2 <= byte1 && byte1 <= 0xDF && 0x80 <= byte2 && byte2 <= 0xBF){
+         continue;
+      }
+      uint8_t byte3 = *ptr++;
+      // excluding overlongs
+      if ((byte1 == 0xE0 && 0xA0 <= byte2 && byte2 <= 0xBF && 0x80 <= byte3
+         && byte3 <= 0xBF)
+      // straight 3-byte
+         || (((0xE1 <= byte1 && byte1 <= 0xEC) || byte1 == 0xEE || byte1 == 0xEF)
+            && 0x80 <= byte2 && byte2 <= 0xBF && 0x80 <= byte3 && byte3 <= 0xBF)
+         // excluding surrogates
+         || (byte1 == 0xED && (0x80 <= byte2 && byte2 <= 0x9F)
+            && (0x80 <= byte3 && byte3 <= 0xBF))){
+         continue;
+      }
+      uint8_t byte4 = *ptr++;
+      if ( // planes 1-3
+      (byte1 == 0xF0 && 0x90 <= byte2 && byte2 <= 0xBF && 0x80 <= byte3
+         && byte3 <= 0xBF && 0x80 <= byte4 && byte4 <= 0xBF)
+      // planes 4-15
+         || (0xF1 <= byte1 && byte1 <= 0xF3 && 0x80 <= byte2 && byte2 <= 0xBF
+            && 0x80 <= byte3 && byte3 <= 0xBF && 0x80 <= byte4 && byte4 <= 0xBF)
+         // plane 16
+         || (byte1 == 0xF4 && 0x80 <= byte2 && byte2 <= 0x8F && 0x80 <= byte3
+            && byte3 <= 0xBF && 0x80 <= byte4 && byte4 <= 0xBF)){
+         continue;
+      }
+
+      rc = false;
+      break;
+   }
+   if (trueAscii != NULL)
+      *trueAscii = rc && isAscii;
+   return rc;
+}
+/**
+ * Tests wether the file was opened correctly
+ * @return      <code>true</code>: the file can be read
+ */
+bool TextFinder::isValid() const{
+   return m_valid;
+}
+
diff --git a/appl/refind/textfinder.hpp b/appl/refind/textfinder.hpp
new file mode 100644 (file)
index 0000000..42748de
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+ */
+
+#ifndef TEXTFINDER_HPP
+#define TEXTFINDER_HPP
+
+class TextFinder {
+public:
+   TextFinder(const QString& fullName, int64_t length, bool ignoreBinary);
+   ~TextFinder();
+public:
+   bool contains(const QString& pattern, bool ignoreCase, bool isRegular);
+   bool isBinary();
+   bool isText(const QByteArray& data, bool* trueAscii = NULL);
+   bool isUTF8(const QByteArray& data, bool* trueAscii) const;
+   bool isValid() const;
+
+private:
+   bool m_ignoreBinary;
+   QString m_filename;
+   int64_t m_length;
+   QFile m_file;
+   bool m_valid;
+};
+
+#endif // TEXTFINDER_HPP