msgpackiodevice.h
1 #ifndef NEOVIM_QT_MSGPACKIODEVICE 2 #define NEOVIM_QT_MSGPACKIODEVICE 3 4 #include <msgpack.h> 5 #include <QHash> 6 #include <QIODevice> 7 #include <QVariant> 8 9 namespace NeovimQt { 10 11 class MsgpackRequest; 12 class MsgpackRequestHandler; 13 class MsgpackIODevice: public QObject 14 { 15 Q_OBJECT 16 Q_PROPERTY(MsgpackError error READ errorCause NOTIFY error) 17 public: 18 enum MsgpackError 19 { 20 NoError = 0, 21 InvalidDevice, 22 InvalidMsgpack, 23 }; 24 Q_ENUM(MsgpackError) 25 26 MsgpackIODevice(QIODevice *, QObject *parent=0); 27 ~MsgpackIODevice(); 28 static MsgpackIODevice* fromStdinOut(QObject *parent=0); 29 30 bool isOpen(); 31 QString errorString() const; 32 MsgpackError errorCause() const {return m_error;}; 33 34 QByteArray encoding() const; 35 36 quint32 msgId(); 37 MsgpackRequest* startRequestUnchecked(const QString& method, quint32 argcount); 38 39 void send(int64_t); 40 void send(double); 41 void send(const QVariant&); 42 void send(const QByteArray&); 43 void send(bool); 44 void send(const QList<QByteArray>& list); 45 template <class T> 46 void sendArrayOf(const QList<T>& list) { 47 msgpack_pack_array(&m_pk, list.size()); 48 foreach(const T& elem, list) { 49 send(elem); 50 } 51 } 52 53 // Convert string to the proper encoding to send to neovim (utf8) 54 inline QByteArray encode(const QString& str) { return str.toUtf8(); } 55 // Decode byte array as string, from Neovim's encoding 56 QString decode(const QByteArray& data) { return QString::fromUtf8(data); } 57 bool checkVariant(const QVariant&); 58 59 bool sendResponse(uint64_t msgid, const QVariant& err, const QVariant& res); 60 bool sendNotification(const QByteArray& method, const QVariantList& params); 61 62 void setRequestHandler(MsgpackRequestHandler *); 63 64 /** Typedef for msgpack-to-Qvariant decoder @see registerExtType */ 65 typedef QVariant (*msgpackExtDecoder)(MsgpackIODevice*, const char* data, quint32 size); 66 void registerExtType(int8_t type, msgpackExtDecoder); 67 68 QList<quint32> pendingRequests() const; 69 signals: 70 void error(NeovimQt::MsgpackIODevice::MsgpackError); 71 /** A notification with the given name and arguments was received */ 72 void notification(const QByteArray &name, const QVariantList& args); 73 void encodingChanged(const QByteArray& encoding); 74 void aboutToClose(); 75 76 protected: 77 void sendError(const msgpack_object& req, const QString& msg); 78 void sendError(uint64_t msgid, const QString& msg); 79 void dispatch(msgpack_object& obj); 80 void dispatchRequest(msgpack_object& obj); 81 void dispatchResponse(msgpack_object& obj); 82 void dispatchNotification(msgpack_object& obj); 83 84 bool decodeMsgpack(const msgpack_object& in, int64_t& out); 85 bool decodeMsgpack(const msgpack_object& in, double& out); 86 bool decodeMsgpack(const msgpack_object& in, QVariant& out); 87 bool decodeMsgpack(const msgpack_object& in, QByteArray& out); 88 bool decodeMsgpack(const msgpack_object& in, bool& out); 89 bool decodeMsgpack(const msgpack_object& in, QList<QByteArray>& out); 90 bool decodeMsgpack(const msgpack_object& in, QList<int64_t>& out); 91 bool decodeMsgpack(const msgpack_object& in, QList<double>& out); 92 bool decodeMsgpack(const msgpack_object& in, QPoint& out); 93 94 protected slots: 95 void setError(NeovimQt::MsgpackIODevice::MsgpackError err, const QString& msg); 96 97 void dataAvailable(); 98 void dataAvailableStdin(const QByteArray&); 99 void dataAvailableFd(int fd); 100 101 void requestTimeout(quint32 id); 102 103 private: 104 static int msgpack_write_to_stdout(void* data, const char* buf, unsigned long int len); 105 static int msgpack_write_to_dev(void* data, const char* buf, unsigned long int len); 106 107 quint32 m_reqid; 108 QIODevice* m_dev; 109 msgpack_packer m_pk; 110 msgpack_unpacker m_uk; 111 QHash<quint32, MsgpackRequest*> m_requests; 112 MsgpackRequestHandler *m_reqHandler; 113 QHash<int8_t, msgpackExtDecoder> m_extTypes; 114 115 QString m_errorString; 116 MsgpackError m_error; 117 }; 118 119 class MsgpackRequestHandler { 120 public: 121 virtual void handleRequest(MsgpackIODevice*, quint32 msgid, const QByteArray&, const QVariantList&)=0; 122 }; 123 124 } // Namespace NeovimQt 125 Q_DECLARE_METATYPE(NeovimQt::MsgpackIODevice::MsgpackError) 126 #endif