source: ogBrowser-Git/qtermwidget/lib/kptydevice.h @ c0cec9d

jenkinsmain
Last change on this file since c0cec9d was fedf2a2, checked in by Vadim Troshchinskiy Shmelev <vtroshchinskiy@…>, 18 months ago

Update Qtermwidget to Qt6 version
Remove build files

  • Property mode set to 100644
File size: 8.8 KB
RevLine 
[64efc22]1/*
2 * This file is a part of QTerminal - http://gitorious.org/qterminal
3 *
4 * This file was un-linked from KDE and modified
5 * by Maxim Bourmistrov <maxim@unixconn.com>
6 *
7 */
8
9/* This file is part of the KDE libraries
10
11    Copyright (C) 2007 Oswald Buddenhagen <ossi@kde.org>
12
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Library General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Library General Public License for more details.
22
23    You should have received a copy of the GNU Library General Public License
24    along with this library; see the file COPYING.LIB.  If not, write to
25    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26    Boston, MA 02110-1301, USA.
27*/
28
29#ifndef kptydev_h
30#define kptydev_h
31
32#include "kpty_p.h"
33
34#include <QIODevice>
35
36#define KMAXINT ((int)(~0U >> 1))
37
[fedf2a2]38class KPtyDevicePrivate;
[64efc22]39class QSocketNotifier;
40
41/**
42 * Encapsulates KPty into a QIODevice, so it can be used with Q*Stream, etc.
43 */
44class KPtyDevice : public QIODevice, public KPty {
45    Q_OBJECT
[fedf2a2]46    Q_DECLARE_PRIVATE_D(KPty::d_ptr, KPtyDevice)
[64efc22]47
48public:
49
50    /**
51     * Constructor
52     */
53    KPtyDevice(QObject *parent = nullptr);
54
55    /**
56     * Destructor:
57     *
58     *  If the pty is still open, it will be closed. Note, however, that
59     *  an utmp registration is @em not undone.
60     */
61    ~KPtyDevice() override;
62
63    /**
64     * Create a pty master/slave pair.
65     *
66     * @return true if a pty pair was successfully opened
67     */
68    bool open(OpenMode mode = ReadWrite | Unbuffered) override;
69
70    /**
71     * Open using an existing pty master. The ownership of the fd
72     * remains with the caller, i.e., close() will not close the fd.
73     *
74     * This is useful if you wish to attach a secondary "controller" to an
75     * existing pty device such as a terminal widget.
76     * Note that you will need to use setSuspended() on both devices to
77     * control which one gets the incoming data from the pty.
78     *
79     * @param fd an open pty master file descriptor.
80     * @param mode the device mode to open the pty with.
81     * @return true if a pty pair was successfully opened
82     */
83    bool open(int fd, OpenMode mode = ReadWrite | Unbuffered);
84
85    /**
86     * Close the pty master/slave pair.
87     */
88    void close() override;
89
90    /**
91     * Sets whether the KPtyDevice monitors the pty for incoming data.
92     *
93     * When the KPtyDevice is suspended, it will no longer attempt to buffer
94     * data that becomes available from the pty and it will not emit any
95     * signals.
96     *
97     * Do not use on closed ptys.
98     * After a call to open(), the pty is not suspended. If you need to
99     * ensure that no data is read, call this function before the main loop
100     * is entered again (i.e., immediately after opening the pty).
101     */
102    void setSuspended(bool suspended);
103
104    /**
105     * Returns true if the KPtyDevice is not monitoring the pty for incoming
106     * data.
107     *
108     * Do not use on closed ptys.
109     *
110     * See setSuspended()
111     */
112    bool isSuspended() const;
113
114    /**
115     * @return always true
116     */
117    bool isSequential() const override;
118
119    /**
120     * @reimp
121     */
122    bool canReadLine() const override;
123
124    /**
125     * @reimp
126     */
127    bool atEnd() const override;
128
129    /**
130     * @reimp
131     */
132    qint64 bytesAvailable() const override;
133
134    /**
135     * @reimp
136     */
137    qint64 bytesToWrite() const override;
138
139    bool waitForBytesWritten(int msecs = -1) override;
140    bool waitForReadyRead(int msecs = -1) override;
141
142
143Q_SIGNALS:
144    /**
145     * Emitted when EOF is read from the PTY.
146     *
147     * Data may still remain in the buffers.
148     */
149    void readEof();
150
151protected:
152    qint64 readData(char *data, qint64 maxSize) override;
153    qint64 readLineData(char *data, qint64 maxSize) override;
154    qint64 writeData(const char *data, qint64 maxSize) override;
155
156private:
157    Q_PRIVATE_SLOT(d_func(), bool _k_canRead())
158    Q_PRIVATE_SLOT(d_func(), bool _k_canWrite())
159};
160
161/////////////////////////////////////////////////////
162// Helper. Remove when QRingBuffer becomes public. //
163/////////////////////////////////////////////////////
164
165#include <QByteArray>
166#include <list>
167
168#define CHUNKSIZE 4096
169
170class KRingBuffer
171{
172public:
173    KRingBuffer()
174    {
175        clear();
176    }
177
178    void clear()
179    {
180        buffers.clear();
181        QByteArray tmp;
182        tmp.resize(CHUNKSIZE);
183        buffers.push_back(tmp);
184        head = tail = 0;
185        totalSize = 0;
186    }
187
188    inline bool isEmpty() const
189    {
190        return buffers.size() == 1 && !tail;
191    }
192
193    inline int size() const
194    {
195        return totalSize;
196    }
197
198    inline int readSize() const
199    {
200        return (buffers.size() == 1 ? tail : buffers.front().size()) - head;
201    }
202
203    inline const char *readPointer() const
204    {
205        Q_ASSERT(totalSize > 0);
206        return buffers.front().constData() + head;
207    }
208
209    void free(int bytes)
210    {
211        totalSize -= bytes;
212        Q_ASSERT(totalSize >= 0);
213
214        forever {
215            int nbs = readSize();
216
217            if (bytes < nbs) {
218                head += bytes;
219                if (head == tail && buffers.size() == 1) {
220                    buffers.front().resize(CHUNKSIZE);
221                    head = tail = 0;
222                }
223                break;
224            }
225
226            bytes -= nbs;
227            if (buffers.size() == 1) {
228                buffers.front().resize(CHUNKSIZE);
229                head = tail = 0;
230                break;
231            }
232
233            buffers.pop_front();
234            head = 0;
235        }
236    }
237
238    char *reserve(int bytes)
239    {
240        totalSize += bytes;
241
242        char *ptr;
243        if (tail + bytes <= buffers.back().size()) {
244            ptr = buffers.back().data() + tail;
245            tail += bytes;
246        } else {
247            buffers.back().resize(tail);
248            QByteArray tmp;
249            tmp.resize(qMax(CHUNKSIZE, bytes));
250            ptr = tmp.data();
251            buffers.push_back(tmp);
252            tail = bytes;
253        }
254        return ptr;
255    }
256
257    // release a trailing part of the last reservation
258    inline void unreserve(int bytes)
259    {
260        totalSize -= bytes;
261        tail -= bytes;
262    }
263
264    inline void write(const char *data, int len)
265    {
266        memcpy(reserve(len), data, len);
267    }
268
269    // Find the first occurrence of c and return the index after it.
270    // If c is not found until maxLength, maxLength is returned, provided
271    // it is smaller than the buffer size. Otherwise -1 is returned.
272    int indexAfter(char c, int maxLength = KMAXINT) const
273    {
274        int index = 0;
275        int start = head;
276        std::list<QByteArray>::const_iterator it = buffers.cbegin();
277        forever {
278            if (!maxLength)
279                return index;
280            if (index == size())
281                return -1;
282            const QByteArray &buf = *it;
283            ++it;
284            int len = qMin((it == buffers.cend() ? tail : buf.size()) - start,
285                           maxLength);
286            const char *ptr = buf.data() + start;
287            if (const char *rptr = (const char *)memchr(ptr, c, len))
288                return index + (rptr - ptr) + 1;
289            index += len;
290            maxLength -= len;
291            start = 0;
292        }
293    }
294
295    inline int lineSize(int maxLength = KMAXINT) const
296    {
297        return indexAfter('\n', maxLength);
298    }
299
300    inline bool canReadLine() const
301    {
302        return lineSize() != -1;
303    }
304
305    int read(char *data, int maxLength)
306    {
307        int bytesToRead = qMin(size(), maxLength);
308        int readSoFar = 0;
309        while (readSoFar < bytesToRead) {
310            const char *ptr = readPointer();
311            int bs = qMin(bytesToRead - readSoFar, readSize());
312            memcpy(data + readSoFar, ptr, bs);
313            readSoFar += bs;
314            free(bs);
315        }
316        return readSoFar;
317    }
318
319    int readLine(char *data, int maxLength)
320    {
321        return read(data, lineSize(qMin(maxLength, size())));
322    }
323
324private:
325    std::list<QByteArray> buffers;
326    int head, tail;
327    int totalSize;
328};
329
[fedf2a2]330class KPtyDevicePrivate : public KPtyPrivate {
[64efc22]331
332    Q_DECLARE_PUBLIC(KPtyDevice)
333
[fedf2a2]334public:
[64efc22]335    KPtyDevicePrivate(KPty* parent) :
336        KPtyPrivate(parent),
337        emittedReadyRead(false), emittedBytesWritten(false),
338        readNotifier(nullptr), writeNotifier(nullptr)
339    {
340    }
341
342    bool _k_canRead();
343    bool _k_canWrite();
344
345    bool doWait(int msecs, bool reading);
346    void finishOpen(QIODevice::OpenMode mode);
347
348    bool emittedReadyRead;
349    bool emittedBytesWritten;
350    QSocketNotifier *readNotifier;
351    QSocketNotifier *writeNotifier;
352    KRingBuffer readBuffer;
353    KRingBuffer writeBuffer;
354};
355
356#endif
357
Note: See TracBrowser for help on using the repository browser.