// Copyright 2015 The Weave Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef LIBWEAVE_SRC_NOTIFICATION_XMPP_STREAM_PARSER_H_ #define LIBWEAVE_SRC_NOTIFICATION_XMPP_STREAM_PARSER_H_ #include #include #include #include #include #include namespace weave { class XmlNode; // A simple XML stream parser. As the XML data is being read from a data source // (for example, a socket), XmppStreamParser::ParseData() should be called. // This method parses the provided XML data chunk and if it finds complete // XML elements, it will call internal OnOpenElement(), OnCloseElement() and // OnCharData() member functions. These will track the element nesting level. // When a top-level element starts, the parser will call Delegate::OnStreamStart // method. Once this happens, every complete XML element (including its children // if they are present) will trigger Delegate::OnStanze() callback. // Finally, when top-level element is closed, Delegate::OnStreamEnd() is called. // This class is specifically tailored to XMPP streams which look like this: // B: // S: // S: // S: // S: ... // E: // Here, "B:" will trigger OnStreamStart(), "S:" will result in OnStanza() and // "E:" will result in OnStreamEnd(). class XmppStreamParser final { public: // Delegate interface that interested parties implement to receive // notifications of stream opening/closing and on new stanzas arriving. class Delegate { public: virtual void OnStreamStart( const std::string& node_name, std::map attributes) = 0; virtual void OnStreamEnd(const std::string& node_name) = 0; virtual void OnStanza(std::unique_ptr stanza) = 0; protected: virtual ~Delegate() {} }; explicit XmppStreamParser(Delegate* delegate); ~XmppStreamParser(); // Parses additional XML data received from an input stream. void ParseData(const std::string& data); // Resets the parser to expect the top-level stream node again. void Reset(); private: // Raw expat callbacks. static void HandleElementStart(void* user_data, const XML_Char* element, const XML_Char** attr); static void HandleElementEnd(void* user_data, const XML_Char* element); static void HandleCharData(void* user_data, const char* content, int length); // Reinterpreted callbacks from expat with some data pre-processed. void OnOpenElement(const std::string& node_name, std::map attributes); void OnCloseElement(const std::string& node_name); void OnCharData(const std::string& text); Delegate* delegate_; XML_Parser parser_{nullptr}; bool started_{false}; std::stack> node_stack_; DISALLOW_COPY_AND_ASSIGN(XmppStreamParser); }; } // namespace weave #endif // LIBWEAVE_SRC_NOTIFICATION_XMPP_STREAM_PARSER_H_