Filtering...

strpos

books/std/strings/strpos
other
(in-package "STR")
other
(include-book "misc/definline" :dir :system)
other
(include-book "strprefixp")
other
(include-book "std/lists/sublistp" :dir :system)
other
(include-book "std/basic/defs" :dir :system)
other
(local (include-book "arithmetic"))
other
(defsection strpos-fast
  :parents (strpos)
  :short "Fast implementation of @(see strpos)."
  (defund strpos-fast
    (x y n xl yl)
    (declare (type string x)
      (type string y)
      (type integer n)
      (type integer xl)
      (type integer yl)
      (xargs :guard (and (stringp x)
          (stringp y)
          (natp xl)
          (natp yl)
          (natp n)
          (<= n (length y))
          (= xl (length x))
          (= yl (length y)))
        :measure (nfix (- (nfix yl) (nfix n)))))
    (cond ((mbe :logic (prefixp (explode x)
           (nthcdr n (explode y)))
         :exec (strprefixp-impl (the string x)
           (the string y)
           (the integer 0)
           (the integer n)
           (the integer xl)
           (the integer yl))) (lnfix n))
      ((mbe :logic (zp (- (nfix yl) (nfix n)))
         :exec (int= n yl)) nil)
      (t (strpos-fast (the string x)
          (the string y)
          (+ 1 (lnfix n))
          (the integer xl)
          (the integer yl)))))
  (local (in-theory (enable strpos-fast)))
  (local (defthm l0
      (implies (sublistp x (cdr y))
        (sublistp x y))
      :hints (("Goal" :in-theory (enable sublistp)))))
  (defthm strpos-fast-removal
    (implies (and (force (stringp x))
        (force (stringp y))
        (force (natp n))
        (force (equal xl (length x)))
        (force (equal yl (length y))))
      (equal (strpos-fast x y n xl yl)
        (let ((idx (listpos (explode x)
               (nthcdr n (explode y)))))
          (and idx (+ n idx)))))
    :hints (("Goal" :induct (strpos-fast x y n xl yl)
       :do-not '(generalize fertilize eliminate-destructors)
       :do-not-induct t
       :in-theory (enable strpos-fast listpos)))))
other
(defsection strpos
  :parents (substrings)
  :short "Locate the first occurrence of a substring."
  :long "<p>@(call strpos) searches through the string @('y') for the first
occurrence of the substring @('x').  If @('x') occurs somewhere in @('y'), it
returns the starting index of the first occurrence.  Otherwise, it returns
@('nil') to indicate that @('x') never occurs in @('y').</p>

<p>The function is "efficient" in the sense that it does not coerce its
arguments into lists, but rather traverses both strings with @(see char).  On
the other hand, it is a naive string search which operates by repeatedly
calling @(see strprefixp), rather than some better algorithm.</p>

<p>Corner case: we say that the empty string <b>is</b> a prefix of any other
string.  That is, @('(strpos "" x)') is 0 for all @('x').</p>"
  (definline strpos
    (x y)
    (declare (type string x y))
    (mbe :logic (listpos (explode x) (explode y))
      :exec (strpos-fast (the string x)
        (the string y)
        (the integer 0)
        (the integer (length (the string x)))
        (the integer (length (the string y))))))
  (defcong streqv
    equal
    (strpos x y)
    1)
  (defcong streqv
    equal
    (strpos x y)
    2))