File indexing completed on 2024-12-08 05:07:39

0001 // clang-format off
0002 /*
0003  *  This file is part of KDiff3.
0004  *
0005  * SPDX-FileCopyrightText: 2002-2011 Joachim Eibl, joachim.eibl at gmx.de
0006  * SPDX-FileCopyrightText: 2018-2020 Michael Reeves reeves.87@gmail.com
0007  * SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 // clang-format on
0010 
0011 #ifndef SOURCEDATA_H
0012 #define SOURCEDATA_H
0013 
0014 #include "diff.h"
0015 #include "fileaccess.h"
0016 #include "LineRef.h"
0017 #include "options.h"
0018 
0019 #include <memory>
0020 #include <optional>
0021 
0022 #include <QTemporaryFile>
0023 #include <QSharedPointer>
0024 #include <QString>
0025 #include <QStringList>
0026 
0027 class SourceData
0028 {
0029   public:
0030     [[nodiscard]] LineType getSizeLines() const;
0031     [[nodiscard]] qint64 getSizeBytes() const;
0032     [[nodiscard]] const char* getBuf() const;
0033     [[nodiscard]] const QString& getText() const;
0034     [[nodiscard]] const std::shared_ptr<LineDataVector>& getLineDataForDisplay() const;
0035     [[nodiscard]] const std::shared_ptr<LineDataVector>& getLineDataForDiff() const;
0036 
0037     void setFilename(const QString& filename);
0038     void setFileAccess(const FileAccess& fileAccess);
0039     [[nodiscard]] QString getFilename() const;
0040     void setAliasName(const QString& name);
0041     [[nodiscard]] QString getAliasName() const;
0042     [[nodiscard]] bool isEmpty() const;                // File was set
0043     [[nodiscard]] bool hasData() const;                // Data was readable
0044     [[nodiscard]] bool isText() const;                 // is it pure text (vs. binary data)
0045     [[nodiscard]] bool isIncompleteConversion() const; // true if some replacement characters were found
0046     [[nodiscard]] bool isFromBuffer() const;           // was it set via setData() (vs. setFileAccess() or setFilename())
0047     void setData(const QString& data);
0048     [[nodiscard]] bool isValid() const; // Either no file is specified or reading was successful
0049 
0050     // Returns a list of error messages if anything went wrong
0051     void readAndPreprocess(const char* encoding, bool bAutoDetectUnicode);
0052     bool saveNormalDataAs(const QString& fileName);
0053 
0054     [[nodiscard]] bool isBinaryEqualWith(const QSharedPointer<SourceData>& other) const;
0055 
0056     void reset();
0057 
0058     [[nodiscard]] bool isDir() const { return m_fileAccess.isDir(); }
0059 
0060     [[nodiscard]] const char* getEncoding() const { return mEncoding; }
0061     [[nodiscard]] e_LineEndStyle getLineEndStyle() const { return m_normalData.m_eLineEndStyle; }
0062     [[nodiscard]] inline bool hasEOLTermiantion() { return m_normalData.hasEOLTermiantion(); }
0063     [[nodiscard]] inline bool hasBOM() const { return m_normalData.hasBOM(); }
0064     [[nodiscard]] const QStringList& getErrors() const { return mErrors; }
0065 
0066     void setEncoding(const char* encoding);
0067 
0068   protected:
0069     bool convertFileEncoding(const QString& fileNameIn, const QByteArray& pCodecIn,
0070                              const QString& fileNameOut, const QByteArray& pCodecOut);
0071 
0072     [[nodiscard]] static std::optional<const char*> detectUTF8(const QByteArray& data);
0073     [[nodiscard]] static std::optional<const char*> detectEncoding(const char* buf, qint64 size, FileOffset& skipBytes);
0074     [[nodiscard]] static std::optional<const char*> getEncodingFromTag(const QByteArray& s, const QByteArray& encodingTag);
0075 
0076     std::optional<const char*> detectEncoding(const QString& fileName);
0077     QString m_aliasName;
0078     FileAccess m_fileAccess;
0079     QString m_tempInputFileName;
0080     QTemporaryFile m_tempFile; //Created from clipboard content.
0081 
0082     QStringList mErrors;
0083 
0084     bool mFromClipBoard = false;
0085 
0086     class FileData
0087     {
0088       private:
0089         friend SourceData;
0090         bool mHasBOM = false;
0091 
0092         std::unique_ptr<char[]> m_pBuf; //TODO: Phase out needlessly wastes memory and time by keeping second copy of file data.
0093         quint64 mDataSize = 0;
0094         qint64 mLineCount = 0; // Number of lines in m_pBuf1 and size of m_v1, m_dv12 and m_dv13
0095         QSharedPointer<QString> m_unicodeBuf=QSharedPointer<QString>::create();
0096         std::shared_ptr<LineDataVector> m_v=std::make_shared<LineDataVector>();
0097         bool m_bIsText = false;
0098         bool m_bIncompleteConversion = false;
0099         e_LineEndStyle m_eLineEndStyle = eLineEndStyleUndefined;
0100         bool mHasEOLTermination = false;
0101 
0102       public:
0103         bool readFile(FileAccess& file);
0104         bool readFile(const QString& filename);
0105         bool writeFile(const QString& filename);
0106 
0107         bool preprocess(const QByteArray& encoding, bool removeComments);
0108         void reset();
0109         void copyBufFrom(const FileData& src);
0110 
0111         [[nodiscard]] bool isEmpty() const { return mDataSize == 0; }
0112 
0113         [[nodiscard]] bool isText() const { return m_bIsText || isEmpty(); }
0114         [[nodiscard]] inline bool hasEOLTermiantion() const { return m_bIsText && mHasEOLTermination; }
0115         [[nodiscard]] inline bool hasBOM() const { return mHasBOM; }
0116 
0117         [[nodiscard]] inline qint64 lineCount() const { return mLineCount; }
0118         [[nodiscard]] inline qint64 byteCount() const { return mDataSize; }
0119     };
0120     FileData m_normalData;
0121     FileData m_lmppData;
0122     const char* mEncoding = u8"UTF-8";
0123 };
0124 
0125 #endif // !SOURCEDATA_H