From: Lars Ingebrigtsen Date: Thu, 24 Sep 2020 23:52:10 +0000 (+0200) Subject: Add a new function 'string-search' X-Git-Tag: emacs-28.0.90~5902 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=e51a98b0c2d35648c2d054486f7ba5869e24e4cf;p=emacs.git Add a new function 'string-search' * doc/lispref/strings.texi (Text Comparison): Document it. * src/fns.c (Fstring_search): New function. --- diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 8de6255478b..6eb3d6f3100 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -656,6 +656,14 @@ optional argument @var{ignore-case} is non-@code{nil}, the comparison ignores case differences. @end defun +@defun string-search needle haystack &optional start-pos +Return the position of the first instance of @var{needle} in +@var{haystack}, both of which are strings. If @var{start-pos} is +non-@code{nil}, start searching from that position in @var{needle}. +This function only considers the characters in the strings when doing +the comparison; text properties are ignored. +@end defun + @defun compare-strings string1 start1 end1 string2 start2 end2 &optional ignore-case This function compares a specified part of @var{string1} with a specified part of @var{string2}. The specified part of @var{string1} diff --git a/etc/NEWS b/etc/NEWS index 13a022d1422..6bedd0347ee 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1415,6 +1415,11 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el. * Lisp Changes in Emacs 28.1 ++++ +*** New function 'string-search'. +This function takes two string parameters and returns the position of +the first instance of the first string in the latter. + +++ *** New function 'process-lines-ignore-status'. This is like 'process-lines', but does not signal an error if the diff --git a/src/fns.c b/src/fns.c index a3b8d6ef57d..3927e4306e6 100644 --- a/src/fns.c +++ b/src/fns.c @@ -5454,6 +5454,51 @@ It should not be used for anything security-related. See return make_digest_string (digest, SHA1_DIGEST_SIZE); } +DEFUN ("string-search", Fstring_search, Sstring_search, 2, 3, 0, + doc: /* Search for the string NEEDLE in the string HAYSTACK. +The return value is the position of the first instance of NEEDLE in +HAYSTACK. + +The optional START-POS argument says where to start searching in +HAYSTACK. If not given, start at the beginning. */) + (register Lisp_Object needle, Lisp_Object haystack, Lisp_Object start_pos) +{ + ptrdiff_t start_byte = 0, haybytes; + char *res = NULL, *haystart; + + CHECK_STRING (needle); + CHECK_STRING (haystack); + + if (!NILP (start_pos)) + { + CHECK_FIXNUM (start_pos); + start_byte = string_char_to_byte (haystack, XFIXNUM (start_pos)); + } + + haystart = SSDATA (haystack) + start_byte; + haybytes = SBYTES (haystack) - start_byte; + + if (STRING_MULTIBYTE (haystack) == STRING_MULTIBYTE (needle)) + res = memmem (haystart, haybytes, + SSDATA (needle), SBYTES (needle)); + else if (STRING_MULTIBYTE (haystack) && !STRING_MULTIBYTE (needle)) + { + Lisp_Object multi_needle = string_to_multibyte (needle); + res = memmem (haystart, haybytes, + SSDATA (multi_needle), SBYTES (multi_needle)); + } + else if (!STRING_MULTIBYTE (haystack) && STRING_MULTIBYTE (needle)) + { + Lisp_Object uni_needle = Fstring_as_unibyte (needle); + res = memmem (haystart, haybytes, + SSDATA (uni_needle), SBYTES (uni_needle)); + } + + if (! res) + return Qnil; + + return make_int (string_byte_to_char (haystack, res - SSDATA (haystack))); +} void @@ -5494,6 +5539,7 @@ syms_of_fns (void) defsubr (&Sremhash); defsubr (&Smaphash); defsubr (&Sdefine_hash_table_test); + defsubr (&Sstring_search); /* Crypto and hashing stuff. */ DEFSYM (Qiv_auto, "iv-auto"); diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index b9a7d29895a..8c2b1300dce 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -901,3 +901,26 @@ (should (equal (delete t [nil t]) [nil])) (should (equal (delete 1 v1) (vector))) (should (equal (delete 2 v1) v1)))) + +(ert-deftest string-search () + (should (equal (string-search "zot" "foobarzot") 6)) + (should (equal (string-search "foo" "foobarzot") 0)) + (should (not (string-search "fooz" "foobarzot"))) + (should (not (string-search "zot" "foobarzo"))) + + (should (equal + (string-search (make-string 2 130) + (concat "helló" (make-string 5 130 t) "bár")) + 5)) + (should (equal + (string-search (make-string 2 127) + (concat "helló" (make-string 5 127 t) "bár")) + 5)) + + (should (equal (string-search "\377" "a\377ø") 1)) + (should (equal (string-search "\377" "a\377a") 1)) + + (should (not (string-search (make-string 1 255) "a\377ø"))) + (should (not (string-search (make-string 1 255) "a\377a"))) + + (should (equal (string-search "fóo" "zotfóo") 3)))