summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/cl-extra.el35
-rw-r--r--lisp/emacs-lisp/cl-lib.el19
2 files changed, 54 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index 3761d04c2c2..c8404e0bc2d 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -383,6 +383,41 @@ With two arguments, return rounding and remainder of their quotient."
"Return 1 if X is positive, -1 if negative, 0 if zero."
(cond ((> x 0) 1) ((< x 0) -1) (t 0)))
+;;;###autoload
+(cl-defun cl-parse-integer (string &key start end radix junk-allowed)
+ "Parse integer from the substring of STRING from START to END.
+STRING may be surrounded by whitespace chars (chars with syntax ` ').
+Other non-digit chars are considered junk.
+RADIX is an integer between 2 and 36, the default is 10. Signal
+an error if the substring between START and END cannot be parsed
+as an integer unless JUNK-ALLOWED is non-nil."
+ (cl-check-type string string)
+ (let* ((start (or start 0))
+ (len (length string))
+ (end (or end len))
+ (radix (or radix 10)))
+ (or (<= start end len)
+ (error "Bad interval: [%d, %d)" start end))
+ (cl-flet ((skip-whitespace ()
+ (while (and (< start end)
+ (= 32 (char-syntax (aref string start))))
+ (setq start (1+ start)))))
+ (skip-whitespace)
+ (let ((sign (cl-case (and (< start end) (aref string start))
+ (?+ (cl-incf start) +1)
+ (?- (cl-incf start) -1)
+ (t +1)))
+ digit sum)
+ (while (and (< start end)
+ (setq digit (cl-digit-char-p (aref string start) radix)))
+ (setq sum (+ (* (or sum 0) radix) digit)
+ start (1+ start)))
+ (skip-whitespace)
+ (cond ((and junk-allowed (null sum)) sum)
+ (junk-allowed (* sign sum))
+ ((/= start end) (error "Not an integer string: %s" string))
+ (t (* sign sum)))))))
+
;; Random numbers.
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index c4b9673aa2a..09cc3eee985 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -279,6 +279,25 @@ so that they are registered at compile-time as well as run-time."
"Return t if INTEGER is even."
(eq (logand integer 1) 0))
+(defconst cl-digit-char-table
+ (let* ((digits (make-vector 256 nil))
+ (populate (lambda (start end base)
+ (mapc (lambda (i)
+ (aset digits i (+ base (- i start))))
+ (number-sequence start end)))))
+ (funcall populate ?0 ?9 0)
+ (funcall populate ?A ?Z 10)
+ (funcall populate ?a ?z 10)
+ digits))
+
+(defun cl-digit-char-p (char &optional radix)
+ "Test if CHAR is a digit in the specified RADIX (default 10).
+If true return the decimal value of digit CHAR in RADIX."
+ (or (<= 2 (or radix 10) 36)
+ (signal 'args-out-of-range (list 'radix radix '(2 36))))
+ (let ((n (aref cl-digit-char-table char)))
+ (and n (< n (or radix 10)) n)))
+
(defvar cl--random-state
(vector 'cl--random-state-tag -1 30 (cl--random-time)))