emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r117953: Add cl-parse-integer based on parse-integer


From: Leo Liu
Subject: [Emacs-diffs] trunk r117953: Add cl-parse-integer based on parse-integer
Date: Fri, 26 Sep 2014 00:21:25 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 117953
revision-id: address@hidden
parent: address@hidden
fixes bug: http://debbugs.gnu.org/18557
committer: Leo Liu <address@hidden>
branch nick: trunk
timestamp: Fri 2014-09-26 08:15:21 +0800
message:
  Add cl-parse-integer based on parse-integer
  
  * doc/misc/cl.texi (Predicates on Numbers): Document cl-digit-char-p.
  (Numerical Functions): Document cl-parse-integer. 
  
  * lisp/calendar/parse-time.el (parse-time-digits): Remove.
  (digit-char-p, parse-integer) Moved to cl-lib.el.
  (parse-time-tokenize, parse-time-rules, parse-time-string): Use
  cl-parse-integer.
  
  * lisp/emacs-lisp/cl-extra.el (cl-parse-integer): New function.
  
  * lisp/emacs-lisp/cl-lib.el (cl-digit-char-table): New var.
  (cl-digit-char-p): New function.
  
  * test/automated/cl-lib.el (cl-digit-char-p, cl-parse-integer): New
  tests.
modified:
  doc/misc/ChangeLog             changelog-20091113204419-o5vbwnq5f7feedwu-6331
  doc/misc/cl.texi               cl.texi-20091113204419-o5vbwnq5f7feedwu-6292
  lisp/ChangeLog                 changelog-20091113204419-o5vbwnq5f7feedwu-1432
  lisp/calendar/parse-time.el    
parsetime.el-20091113204419-o5vbwnq5f7feedwu-2379
  lisp/emacs-lisp/cl-extra.el    clextra.el-20091113204419-o5vbwnq5f7feedwu-611
  lisp/emacs-lisp/cl-lib.el      cl.el-20091113204419-o5vbwnq5f7feedwu-614
  test/ChangeLog                 changelog-20091113204419-o5vbwnq5f7feedwu-8588
  test/automated/cl-lib.el       cllib.el-20130711160611-o23w1tyz0y13jq8e-1
=== modified file 'doc/misc/ChangeLog'
--- a/doc/misc/ChangeLog        2014-09-24 17:33:54 +0000
+++ b/doc/misc/ChangeLog        2014-09-26 00:15:21 +0000
@@ -1,3 +1,8 @@
+2014-09-26  Leo Liu  <address@hidden>
+
+       * cl.texi (Predicates on Numbers): Document cl-digit-char-p.
+       (Numerical Functions): Document cl-parse-integer.  (Bug#18557)
+
 2014-09-24  Ulf Jasper  <address@hidden>
 
        * newsticker.texi: Reworked.  Document new treeview group

=== modified file 'doc/misc/cl.texi'
--- a/doc/misc/cl.texi  2014-06-10 02:20:31 +0000
+++ b/doc/misc/cl.texi  2014-09-26 00:15:21 +0000
@@ -2929,6 +2929,12 @@
 error if the argument is not an integer.
 @end defun
 
address@hidden cl-digit-char-p char radix
+Test if @var{char} is a digit in the specified @var{radix} (default is
+10).  If true return the decimal value of digit @var{char} in
address@hidden
address@hidden defun
+
 @node Numerical Functions
 @section Numerical Functions
 
@@ -3011,6 +3017,15 @@
 of @code{cl-truncate}.
 @end defun
 
address@hidden cl-parse-integer string &key start end radix junk-allowed
+This function implements the Common Lisp @code{parse-integer}
+function.  It parses an integer in the specified @var{radix} from the
+substring of @var{string} between @var{start} and @var{end}.  Any
+leading and trailing whitespace chars are ignored. It signals an error
+if the substring between @var{start} and @var{end} cannot be parsed as
+an integer unless @var{junk-allowed} is non-nil.
address@hidden defun
+
 @node Random Numbers
 @section Random Numbers
 

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2014-09-25 20:55:58 +0000
+++ b/lisp/ChangeLog    2014-09-26 00:15:21 +0000
@@ -1,3 +1,16 @@
+2014-09-26  Leo Liu  <address@hidden>
+
+       Add cl-parse-integer based on parse-integer (Bug#18557)
+       * calendar/parse-time.el (parse-time-digits): Remove.
+       (digit-char-p, parse-integer) Moved to cl-lib.el.
+       (parse-time-tokenize, parse-time-rules, parse-time-string): Use
+       cl-parse-integer.
+
+       * emacs-lisp/cl-extra.el (cl-parse-integer): New function.
+
+       * emacs-lisp/cl-lib.el (cl-digit-char-table): New var.
+       (cl-digit-char-p): New function.
+
 2014-09-25  Juri Linkov  <address@hidden>
 
        * vc/add-log.el (change-log-next-buffer): Don't create an empty

=== modified file 'lisp/calendar/parse-time.el'
--- a/lisp/calendar/parse-time.el       2014-08-03 15:38:52 +0000
+++ b/lisp/calendar/parse-time.el       2014-09-26 00:15:21 +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)
@@ -59,30 +50,6 @@
            ((string-match "[[:lower:]]" str) ?a)
            ((string-match "[[:digit:]]" str) ?0)))))
 
-(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 +67,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 +114,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 +177,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'
--- a/lisp/emacs-lisp/cl-extra.el       2014-03-20 18:16:47 +0000
+++ b/lisp/emacs-lisp/cl-extra.el       2014-09-26 00:15:21 +0000
@@ -383,6 +383,41 @@
   "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.
 

=== modified file 'lisp/emacs-lisp/cl-lib.el'
--- a/lisp/emacs-lisp/cl-lib.el 2014-05-21 00:41:21 +0000
+++ b/lisp/emacs-lisp/cl-lib.el 2014-09-26 00:15:21 +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/ChangeLog'
--- a/test/ChangeLog    2014-09-24 17:33:54 +0000
+++ b/test/ChangeLog    2014-09-26 00:15:21 +0000
@@ -1,3 +1,8 @@
+2014-09-26  Leo Liu  <address@hidden>
+
+       * automated/cl-lib.el (cl-digit-char-p, cl-parse-integer): New
+       tests.  (Bug#18557)
+
 2014-09-24  Ulf Jasper  <address@hidden>
 
        * automated/newsticker-tests.el

=== modified file 'test/automated/cl-lib.el'
--- a/test/automated/cl-lib.el  2014-04-22 21:32:51 +0000
+++ b/test/automated/cl-lib.el  2014-09-26 00:15:21 +0000
@@ -223,6 +223,25 @@
     (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 (null (cl-parse-integer "" :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)))
+  (should (= -123 (cl-parse-integer "  -123  "))))
+
 (ert-deftest cl-loop-destructuring-with ()
   (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]