File indexing completed on 2024-04-21 04:36:03

0001 /*
0002  * XDebug Debugger Support
0003  *
0004  * Copyright (C) 2004-2006 by Thiago Silva <thiago.silva@kdemail.net>
0005  * Copyright 2009 Niko Sams <niko.sams@gmail.com>
0006  *
0007  * This program is free software; you can redistribute it and/or modify
0008  * it under the terms of the GNU General Public License as
0009  * published by the Free Software Foundation; either version 2 of the
0010  * License, or (at your option) any later version.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU General Public
0018  * License along with this program; if not, write to the
0019  * Free Software Foundation, Inc.,
0020  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0021  */
0022 
0023 #ifndef CONNECTION_H
0024 #define CONNECTION_H
0025 
0026 #include <QObject>
0027 #include <QAbstractSocket>
0028 #include <QStringList>
0029 
0030 #include "debugsession.h"
0031 
0032 class QUrl;
0033 class QDomDocument;
0034 class QTcpSocket;
0035 
0036 namespace XDebug {
0037 class StackModel;
0038 
0039 class CallbackBase
0040 {
0041 public:
0042     virtual void execute(const QDomDocument&) = 0;
0043     virtual ~CallbackBase() {};
0044 
0045     /**
0046      * @return true if the callback handles errors himself. Else the callback won't be executed if an error is returned
0047      */
0048     virtual bool allowError() const = 0;
0049 };
0050 
0051 template <class Handler, class Cookie>
0052 class CallbackWithCookie
0053     : public CallbackBase
0054 {
0055 public:
0056     CallbackWithCookie(Handler* scope, void(Handler::* method)(Cookie*, const QDomDocument&), Cookie* cookie = 0, bool allowError = false)
0057         : m_cookie(cookie)
0058         , m_scope(scope)
0059         , m_method(method)
0060         , m_allowError(allowError)
0061     {}
0062 
0063     void execute(const QDomDocument& xml) override
0064     {
0065         return (m_scope->*m_method)(m_cookie, xml);
0066     }
0067 
0068     bool allowError() const override { return m_allowError; }
0069 
0070 private:
0071     Cookie* m_cookie;
0072     Handler* m_scope;
0073     void (Handler::* m_method)(Cookie*, const QDomDocument&);
0074     bool m_allowError;
0075 };
0076 
0077 template <class Handler>
0078 class Callback
0079     : public CallbackBase
0080 {
0081 public:
0082     Callback(Handler* scope, void(Handler::* method)(const QDomDocument&), bool allowError = false)
0083         : m_scope(scope)
0084         , m_method(method)
0085         , m_allowError(allowError)
0086     {}
0087 
0088     void execute(const QDomDocument& xml) override
0089     {
0090         return (m_scope->*m_method)(xml);
0091     }
0092 
0093     bool allowError() const override { return m_allowError; }
0094 
0095 private:
0096     Handler* m_scope;
0097     void (Handler::* m_method)(const QDomDocument&);
0098     bool m_allowError;
0099 };
0100 
0101 class Connection
0102     : public QObject
0103 {
0104     Q_OBJECT
0105 
0106 public:
0107     Connection(QTcpSocket* socket, QObject* parent = nullptr);
0108     ~Connection() override;
0109 
0110     void close();
0111 
0112     void sendCommand(const QString& cmd, QStringList arguments = QStringList(),
0113                      const QByteArray& data = QByteArray(), CallbackBase* callback = nullptr);
0114     void setState(DebugSession::DebuggerState state);
0115     DebugSession::DebuggerState currentState();
0116 
0117     QTcpSocket* socket();
0118 
0119 public Q_SLOTS:
0120     void processFinished(int exitCode);
0121 
0122 Q_SIGNALS:
0123     void stateChanged(KDevelop::IDebugSession::DebuggerState status);
0124     void currentPositionChanged(const QUrl& fileName, int lineNum);
0125     void output(QString content);
0126     void outputLine(QString content);
0127     void closed();
0128 
0129 private Q_SLOTS:
0130     void readyRead();
0131     void error(QAbstractSocket::SocketError error);
0132 
0133 private:
0134     void processInit(const QDomDocument& xml);
0135     void processResponse(const QDomDocument& xml);
0136     void processStream(const QDomDocument& xml);
0137 
0138     QTcpSocket* m_socket;
0139 
0140     QString m_outputLine;
0141     DebugSession::DebuggerState m_currentState;
0142     QTextCodec* m_codec;
0143     StackModel* m_stackModel;
0144 
0145     int m_lastTransactionId;
0146     QMap<int, CallbackBase*> m_callbacks;
0147 };
0148 }
0149 #endif