diff options
| -rw-r--r-- | xmpp/element_buffer.go | 58 | ||||
| -rw-r--r-- | xmpp/stream_pair.go | 20 | 
2 files changed, 76 insertions, 2 deletions
diff --git a/xmpp/element_buffer.go b/xmpp/element_buffer.go new file mode 100644 index 0000000..c55279b --- /dev/null +++ b/xmpp/element_buffer.go @@ -0,0 +1,58 @@ +package xmpp + +import ( +	"encoding/xml" +) + +// elementBuffer is a struct to store multiple values of type xml.Token until +// they form a complete XML element with opening and closing tag which is +// suitable to be passed to an appropriate handler function. +type elementBuffer struct { +	tokens []xml.Token +	end    xml.EndElement +	level  int +} + +// newElementBuffer returns a new initialized elementBuffer struct. +func newElementBuffer() elementBuffer { +	buf := elementBuffer{} +	buf.reset() +	return buf +} + +// FIXME this function needs essential error handling for corner cases! +// +// add is able to add a new xml.Token to the buffer. There are some rules +// checked to ensure a correct and consistent elementBuffer which are checked. +// If one of these checks fail the token is not added and a corresponding error +// is returned. +func (e *elementBuffer) add(t xml.Token) error { +	switch t.(type) { +	case xml.StartElement: +		e.level += 1 +	case xml.EndElement: +		e.level -= 1 +	} +	e.tokens = append(e.tokens, t) +	return nil +} + +// isComplete returns true if the buffer contains a slice of XML tokens which +// form a complete XML element starting with an xml.StartElement and closing +// with the corresponding xml.EndElement. +func (e *elementBuffer) isComplete() bool { +	return (len(e.tokens) > 0 && e.level == 0) +} + +// reset returns the content of the buffer as a slice of XML tokens and resets +// the buffer to the initial state. This function can be used to initialize the +// elementBuffer struct. In that case the return value can be ignored. +func (e *elementBuffer) reset() (buf []xml.Token) { +	retval := e.tokens + +	e.tokens = make([]xml.Token, 0) +	e.end = xml.EndElement{} +	e.level = 0 + +	return retval +} diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index e02cca6..b13d8a3 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -9,6 +9,8 @@ func runStreamPair(s *session) {  	openStream(s)  	defer closeStream(s) +	buf := newElementBuffer() +  	for {  		select {  		case data := <-s.in: @@ -18,8 +20,22 @@ func runStreamPair(s *session) {  			default:  				log.Printf("Unknown data '%d'!\n", data)  			} -		case _ = <-s.rx: -			// TODO route received XML token here +		case t := <-s.rx: +			err := buf.add(t) +			if err != nil { +				log.Printf("Could not add XML token to buffer: %v\n", err) +				return +			} +			if buf.isComplete() { +				element := buf.reset() +				// TODO handle XML element here - this is just a dummy: +				switch start := element[0].(type) { +				case xml.StartElement: +					log.Printf("Got XML element `%s`\n", start.Name.Local) +				default: +					log.Println("No xml.StartElement at start of element buffer!") +				} +			}  		}  	}  }  | 
