File indexing completed on 2024-12-08 13:30:51

0001 /**
0002  * KDiff3 - Text Diff And Merge Tool
0003  *
0004  * SPDX-FileCopyrightText: 2023 Michael Reeves <reeves.87@gmail.com>
0005  * SPDX-License-Identifier: GPL-2.0-or-later
0006  *
0007  */
0008 
0009 #ifndef ENCODEDDATASTREAM_H
0010 #define ENCODEDDATASTREAM_H
0011 
0012 #include "TypeUtils.h"
0013 
0014 #include <QByteArray>
0015 #include <QDataStream>
0016 #include <QString>
0017 #include <QTextCodec>
0018 #include <QTextDecoder>
0019 
0020 class EncodedDataStream: public QDataStream
0021 {
0022   private:
0023     QByteArray mEncoding = "UTF-8";
0024     bool mGenerateBOM = false;
0025     bool mError = false;
0026 
0027   public:
0028     using QDataStream::QDataStream;
0029 
0030     void setGenerateByteOrderMark(bool generate) { mGenerateBOM = generate; }
0031 
0032     //Let the compiler choose the optimal solution based on c++ rules.
0033     inline void setEncoding(const QByteArray &inEncoding) noexcept
0034     {
0035         assert(!inEncoding.isEmpty());
0036         if(inEncoding == "UTF-8-BOM")
0037         {
0038             mGenerateBOM = true;
0039             mEncoding = "UTF-8";
0040         }
0041         else
0042             mEncoding = inEncoding;
0043     };
0044 
0045     inline void setEncoding(const QByteArray &&inEncoding) noexcept
0046     {
0047         assert(!inEncoding.isEmpty());
0048         if(inEncoding == "UTF-8-BOM")
0049         {
0050             mGenerateBOM = true;
0051             mEncoding = "UTF-8";
0052         }
0053         else
0054             mEncoding = inEncoding;
0055     };
0056 
0057     inline qint32 readChar(QChar& c)
0058     {
0059         char curByte;
0060         qint32 len = 0;
0061         QString s;
0062 
0063 #if(QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
0064         QTextDecoder decoder = QTextDecoder(QTextCodec::codecForName(mEncoding), mGenerateBOM ? QTextCodec::ConversionFlag::DefaultConversion : QTextCodec::ConversionFlag::IgnoreHeader);
0065 #else
0066         QTextDecoder decoder = QTextDecoder(QTextCodec::codecForName(mEncoding), mGenerateBOM ? QStringConverter::Flag::WriteBom : QStringConverter::Flag::ConvertInitialBom);
0067 #endif
0068 
0069         do
0070         {
0071             len += readRawData(&curByte, 1);
0072             s = decoder.toUnicode(&curByte, 1);
0073         } while(!decoder.hasFailure() && decoder.needsMoreData() && !atEnd());
0074 
0075         mError = decoder.hasFailure();
0076         if(!mError)
0077             c = s[0];
0078         else
0079             c = QChar::ReplacementCharacter;
0080 
0081         return len;
0082     }
0083 
0084     EncodedDataStream &operator<<(const QString &s)
0085     {
0086 #if(QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
0087         QTextEncoder encoder(QTextCodec::codecForName(mEncoding), mGenerateBOM ? QTextCodec::ConversionFlag::DefaultConversion : QTextCodec::ConversionFlag::IgnoreHeader);
0088 #else
0089         QTextEncoder encoder(QTextCodec::codecForName(mEncoding), mGenerateBOM ? QStringConverter::Flag::WriteBom : QStringConverter::Flag::ConvertInitialBom);
0090 #endif
0091         QByteArray data = encoder.fromUnicode(s);
0092         mError = encoder.hasFailure();
0093 
0094         return *this << data;
0095     };
0096 
0097     inline bool hasError() noexcept { return mError; }
0098 
0099     //Not implemented but may be inherieted from QDataStream
0100     EncodedDataStream &operator<<(const QChar &) = delete;
0101     EncodedDataStream &operator<<(const char *&) = delete;
0102     EncodedDataStream &operator<<(const char &) = delete;
0103 
0104     EncodedDataStream &operator<<(const QByteArray &bytes)
0105     {
0106         writeRawData(bytes.constData(), bytes.length());
0107         return *this;
0108     };
0109 
0110     EncodedDataStream &operator>>(QByteArray &) = delete;
0111     EncodedDataStream &operator>>(QString &) = delete;
0112     EncodedDataStream &operator>>(QChar &) = delete;
0113     EncodedDataStream &operator>>(char *&) = delete;
0114     EncodedDataStream &operator>>(char &) = delete;
0115 };
0116 
0117 #endif /* ENCODEDDATASTREAM_H */