;; stomp.el, interpret STOMP messages. (defun stomp-connect (host port) "Connect to a server supporting the STOMP protocol" (message "Not implemented yet")) (defun stomp-shift-message (buffer) "Read a message from a buffer. After reading a message, it will be deleted from the buffer." (let ((message (stomp-read-message buffer))) (cond (message (stomp-delete-message buffer) message) (t nil)))) (defun stomp-delete-message (buffer) "Delete the top-most messsage in a buffer" (with-current-buffer buffer (goto-char (point-min)) (while (not (string-equal (thing-at-point 'line) "\u0000\n")) (forward-line)) (delete-region (point-min) (+ (line-end-position) 1)))) ;; TODO: make this delete the message after reading it (defun stomp-read-message (buffer) "Attempt to read a single message from a buffer. The buffer may contain multiple messages, but only the first message (from top to bottom) will be read. If there are no messages in the buffer, nil will be returned." (with-current-buffer buffer (goto-char (point-min)) (let ((message ()) (headers ()) (content)) (map-put message 'command (current-word)) (setq headers (stomp-read-headers buffer)) (setq content (stomp-read-content buffer (+ (length headers) 3))) (cond (content (map-put message 'headers headers) (map-put message 'content content)) (t nil))))) (defun stomp-read-headers (buffer &optional headers) "Attempt to read the headers of a stomp message in *buffer*" (with-current-buffer buffer (unless headers (goto-char (point-min))) (forward-line) (let ((header (split-string (thing-at-point 'line) ":"))) (cond ((> (length header) 2) (throw 'invalid-header nil)) ((= (length header) 1) headers) (t (stomp-read-headers buffer (push headers header))))))) (defun stomp-read-content (buffer start-line &optional content) "Read the message contents from a buffer" (with-current-buffer buffer (unless content (goto-char (point-min)) (forward-line (- start-line 3)) (setq content "")) (forward-line) (cond ((string-equal (thing-at-point 'line) "\u0000\n") content) ((= (line-end-position) (point-max)) nil) (t (stomp-read-content buffer start-line (concat content (thing-at-point 'line))))))) (eval-when-compile (require 'cl) (defun test-stomp-read-message () (with-temp-buffer (insert "MESSAGE content-type:text/plain bla:bloe vla bla ahweiuawhefuhawleghawe \n") (let ((result (stomp-read-message (current-buffer)))) (assert (string-equal (alist-get 'command result) "MESSAGE") t)))) (test-stomp-read-message))