=== modified file 'lisp/calendar/parse-time.el' --- lisp/calendar/parse-time.el 2014-08-03 15:38:52 +0000 +++ lisp/calendar/parse-time.el 2014-09-25 08:11:25 +0000 @@ -34,21 +34,12 @@ ;;; Code: -(eval-when-compile (require 'cl-lib)) - -(defvar parse-time-digits (make-vector 256 nil)) +(require 'cl-lib) ;; Byte-compiler warnings (defvar parse-time-elt) (defvar parse-time-val) -(unless (aref parse-time-digits ?0) - (cl-loop for i from ?0 to ?9 - do (aset parse-time-digits i (- i ?0)))) - -(defsubst digit-char-p (char) - (aref parse-time-digits char)) - (defsubst parse-time-string-chars (char) (save-match-data (let (case-fold-search str) @@ -62,27 +53,6 @@ (put 'parse-error 'error-conditions '(parse-error error)) (put 'parse-error 'error-message "Parsing error") -(defsubst parse-integer (string &optional start end) - "[CL] Parse and return the integer in STRING, or nil if none." - (let ((integer 0) - (digit 0) - (index (or start 0)) - (end (or end (length string)))) - (when (< index end) - (let ((sign (aref string index))) - (if (or (eq sign ?+) (eq sign ?-)) - (setq sign (parse-time-string-chars sign) - index (1+ index)) - (setq sign 1)) - (while (and (< index end) - (setq digit (digit-char-p (aref string index)))) - (setq integer (+ (* integer 10) digit) - index (1+ index))) - (if (/= index end) - (signal 'parse-error `("not an integer" - ,(substring string (or start 0) end))) - (* sign integer)))))) - (defun parse-time-tokenize (string) "Tokenize STRING into substrings." (let ((start nil) @@ -100,7 +70,7 @@ (setq c (parse-time-string-chars (aref string index)))) (setq all-digits (and all-digits (eq c ?0)))) (if (<= index end) - (push (if all-digits (parse-integer string start index) + (push (if all-digits (cl-parse-integer string :start start :end index) (substring string start index)) list))) (nreverse list))) @@ -147,8 +117,8 @@ (= 5 (length parse-time-elt)) (or (= (aref parse-time-elt 0) ?+) (= (aref parse-time-elt 0) ?-)))) - ,#'(lambda () (* 60 (+ (parse-integer parse-time-elt 3 5) - (* 60 (parse-integer parse-time-elt 1 3))) + ,#'(lambda () (* 60 (+ (cl-parse-integer parse-time-elt :start 3 :end 5) + (* 60 (cl-parse-integer parse-time-elt :start 1 :end 3))) (if (= (aref parse-time-elt 0) ?-) -1 1)))) ((5 4 3) ,#'(lambda () (and (stringp parse-time-elt) @@ -210,9 +180,10 @@ (let ((new-val (if rule (let ((this (pop rule))) (if (vectorp this) - (parse-integer + (cl-parse-integer parse-time-elt - (aref this 0) (aref this 1)) + :start (aref this 0) + :end (aref this 1)) (funcall this))) parse-time-val))) (rplaca (nthcdr (pop slots) time) new-val)))))))) === modified file 'lisp/emacs-lisp/cl-extra.el' --- lisp/emacs-lisp/cl-extra.el 2014-03-20 18:16:47 +0000 +++ lisp/emacs-lisp/cl-extra.el 2014-09-25 08:14:57 +0000 @@ -383,6 +383,28 @@ "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." + (let* ((start (or start 0)) + (end (or end (length string))) + (radix (or radix 10))) + (or (< start end (1+ (length string))) + (error "Bad interval: [%d, %d)" start end)) + (let ((sign (cl-case (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))) + (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. === modified file 'lisp/emacs-lisp/cl-lib.el' --- lisp/emacs-lisp/cl-lib.el 2014-05-21 00:41:21 +0000 +++ lisp/emacs-lisp/cl-lib.el 2014-09-25 07:55:40 +0000 @@ -279,6 +279,25 @@ "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))) === modified file 'test/automated/cl-lib.el' --- test/automated/cl-lib.el 2014-04-22 21:32:51 +0000 +++ test/automated/cl-lib.el 2014-09-25 08:16:10 +0000 @@ -223,6 +223,23 @@ (should (= (cl-the integer (cl-incf side-effect)) 1)) (should (= side-effect 1)))) +(ert-deftest cl-digit-char-p () + (should (cl-digit-char-p ?3)) + (should (cl-digit-char-p ?a 11)) + (should-not (cl-digit-char-p ?a)) + (should (cl-digit-char-p ?w 36)) + (should-error (cl-digit-char-p ?a 37)) + (should-error (cl-digit-char-p ?a 1))) + +(ert-deftest cl-parse-integer () + (should-error (cl-parse-integer "abc")) + (should (null (cl-parse-integer "abc" :junk-allowed t))) + (should (= 342391 (cl-parse-integer "0123456789" :radix 8 :junk-allowed t))) + (should-error (cl-parse-integer "0123456789" :radix 8)) + (should (= -239 (cl-parse-integer "-efz" :radix 16 :junk-allowed t))) + (should-error (cl-parse-integer "efz" :radix 16)) + (should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2)))) + (ert-deftest cl-loop-destructuring-with () (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))