How do I convert a string of hex into ASCII using elisp?

Viewed 3733

Today I received a reply to one of my emails in the form of a string of hex bytes:

"686170707920333974682068617665206120676f6f64206f6e6521"

And I was thinking of the most efficient clean way to convert the string into it's ASCII equivalent. I'll add my answer to the question but I didn't feel it was as elegant as it could have been.

7 Answers

Building the answers provided by Inaimathi and Shrein, I also added an encode function. Here is an implementation of both encode and decode, for both string and region arguments:

;; ASCII-HEX converion
(defun my/hex-decode-string (hex-string)
  (let ((res nil))
    (dotimes (i (/ (length hex-string) 2) (apply #'concat (reverse res)))
      (let ((hex-byte (substring hex-string (* 2 i) (* 2 (+ i 1)))))
        (push (format "%c" (string-to-number hex-byte 16)) res)))))

(defun my/hex-encode-string (ascii-string)
  (let ((res nil))
    (dotimes (i (length ascii-string) (apply #'concat (reverse res)))
      (let ((ascii-char (substring ascii-string i  (+ i 1))))
        (push (format "%x" (string-to-char ascii-char)) res)))))

(defun my/hex-decode-region (start end) 
  "Decode a hex string in the selected region."
  (interactive "r")
  (save-excursion
    (let* ((decoded-text 
            (my/hex-decode-string
             (buffer-substring start end))))
      (delete-region start end)
      (insert decoded-text))))

(defun my/hex-encode-region (start end) 
  "Encode a hex string in the selected region."
  (interactive "r")
  (save-excursion
    (let* ((encoded-text 
            (my/hex-encode-string
             (buffer-substring start end))))
      (delete-region start end)
      (insert encoded-text))))
Related