Common lisp integer to hex conversion - decimal

Is there a similar function to (parse-integer "ff" :radix 16) that will take me back the other way? If I have the int 255 how do I convert it to the string ff?

(write-to-string 255 :base 16)

You can also use format with the ~X radix designator:
CL-USER> (format t "~X" 255)
FF
NIL
To get the leading 0x and a minimum width of, say, four padded with zeros, use
CL-USER> (format t "0x~4,'0X" 255)
0x00FF
NIL
To force the digits from 10 to 15 to be lowercase, use the case conversion directive ~( as follows:
CL-USER> (format t "0x~(~4,'0x~)" 255)
0x00ff
NIL

Related

How to distinguish escaped characters from non-escaped e.g. "\x27" from "x27" in a string in Common Lisp?

Solving Advent of Code 2015 task 8 part2 I encountered the problem to have to distinguish in a string the occurrence of "\x27" from plain "x27".
But I don't see a way how I can do it. Because
(length "\x27") ;; is 3
(length "x27") ;; is also 3
(subseq "\x27" 0 1) ;; is "x"
(subseq "x27" 0 1) ;; is "x"
Neither print, prin1, princ made a difference.
# nor does `coerce`
(coerce "\x27" 'list)
;; (#\x #\2 #\7)
So how then to distinguish in a string when "\x27" or any of such
hexadecimal representation occurs?
It turned out, one doesn't need to solve this to solve the task. However, now I still would like to know whether there is a way to distinguish "\x" from "x" in common lisp.
The string literal "\x27" is read as the same as "x27", because \ is an escape character in string literals. If you want a string with the contents \x27, you need to write the literal as "\\x27" (i. e. escape the escape character). This has nothing to do with the strings themselves. If you read a string from a file containing \x27 (e. g. with read-line), then the four-character string \x27 results.
By the time that the Lisp reader gets to work, \x is the same as x. There may be some way to turn this off - I wouldn't be surprised - but the original text talks about Santa's file.
So, I created my own file, like this:
x27
\x27
And I read the data into special variables like this:
(defun read-line-crlf (stream)
(string-right-trim '(#\Return) (read-line stream nil)))
(defun read-lines (filename)
(with-open-file (stream filename)
(setf x (read-line-crlf stream))
(setf x-esc (read-line-crlf stream))
))
The length of x is then 3, and the length of x-esc is 4. The returned string must be trimmed on Windows, or an external format declared, because otherwise SBCL will leave half of the CR-LF on the end of the read strings.

Decode a single character from octets in lisp

How can I decode a single character from a vector of octets in common lisp?
I want something like:
(decode-character vector :start i :encoding :utf-8)
or more specifically:
(decode-character #(195 164 195 173 99 195 176) :start 0)
=> #\LATIN_SMALL_LETTER_A_WITH_DIAERESIS
which would return the UTF-8 encoded character that starts at position i in vector.
I can't figure out how to do that using either babel or flexi-streams.
(defun decode-character (vector &rest args)
(char (apply #'babel:octets-to-string
(coerce vector '(vector (unsigned-byte 8))) args)
0))
This is maybe not what you are looking for (I'd gladly update if I can).
I did not look at Babel, but you could generalize the approach for other encodings I guess. I'll stick with trivial-utf-8 here. I would do this:
(defun decode-utf-8-char (octet-vector &key (start 0))
(char (trivial-utf-8:utf-8-bytes-to-string
octet-vector
:start start
:end (+ start 4)) 0))
Gives the result you want with your example vector.
The reason it works is because utf-8 characters are at most 4 bytes long. The call to char is here to grab the first character in case more than one were actually read.

Appending character to string in Common Lisp

I have a character ch that I want to append to a string str. I realize you can concatenate strings like such:
(setf str (concatenate 'string str (list ch)))
But that seems rather inefficient. Is there a faster way to just append a single character?
If the string has a fill-pointer and maybe is also adjustable.
Adjustable = can change its size.
fill-pointer = the content size, the length, can be less than the string size.
VECTOR-PUSH = add an element at the end and increment the fill-pointer.
VECTOR-PUSH-EXTEND = as VECTOR-PUSH, additionally resizes the array, if it is too small.
We can make an adjustable string from a normal one:
CL-USER 32 > (defun make-adjustable-string (s)
(make-array (length s)
:fill-pointer (length s)
:adjustable t
:initial-contents s
:element-type (array-element-type s)))
MAKE-ADJUSTABLE-STRING
CL-USER 33 > (let ((s (make-adjustable-string "Lisp")))
(vector-push-extend #\! s)
s)
"Lisp!"
If you want to extend a single string multiple times, it is often
quite performant to use with-output-to-string, writing to the stream
it provides. Be sure to use write or princ etc. (instead of format)
for performance.

convert two chars at a time from a string to hex

I have the following piece of code which converts 1 char to a hex at a time. I want to convert two chars to a hex. ie 99ab should be treated as '99', 'ab' to be converted to its equivalent hex.
Current implementation is as follows
$final =~ s/(.)/sprintf("0x%X ",ord($1))/eg;
chop($final);
TIA
Your question doesn't make much sense. Hex is a string representation of a number. You can't convert a string to hex.
You can convert individual characters of a string to hex since characters are merely numbers, but that's clearly not what you want. (That's what your code does.)
I think you are trying to convert from from hex to chars.
6 chars "6a6b0a" ⇒ 3 chars "\x6a\x6b\x0a"
If so, you can use your choice of
$final =~ s/(..)/ chr(hex($1)) /seg;
or
$final = pack 'H*', $final;
The other possibility I can think of is that you want to unpack 16-bit integers.
6 chars "6a6b" ⇒ 13 chars "0x6136 0x6236" (LE byte order)
-or-
6 chars "6a6b" ⇒ 13 chars "0x3661 0x3662" (BE byte order)
If so, you can use
my #nums = unpack 'S<*', $packed; # For 16-bit ints, LE byte order
-or-
my #nums = unpack 'S>*', $packed; # For 16-bit ints, BE byte order
my $final = join ' ', map sprintf('0x%04X', $_), #nums;

How to center a string in elisp?

I would like to center justify a given input string to a given size so that what is produced is a string with padded spaces either side (left and right) of the input string.
The code I have to do this:
(defun center-string (string size)
(let* ((padding (/ (- size (length string)) 2))
(lpad (+ (length string) padding))
(lformat (format "%%%ds" lpad))
(rformat (format "%%%ds" (- size))))
(format rformat (format lformat string))))
And some test cases:
(center-string "KJF" 10)
=> " KJF "
(center-string "KF" 10)
=> " KF "
(center-string "0123456789" 10)
=> "0123456789"
(center-string "0123456789" 5)
=> "0123456789" ; Notice justifcation is ignored as input string too large.
Is there an existing elisp function to do this or a better method?
There's a center-line, which works in a buffer (and uses the buffer's value of fill-column as the line length), so if your goal is to produce a nicely formatted file, you could do something like
(defun insert-centered (x)
(insert "\n" x)
(center-line)
(insert "\n"))
No, there is not an existing emacs lisp routine that does what you want. (the standard search through emacs lisp info and emacs info supports this).

Resources