emacs-diffs
[Top][All Lists]
Advanced

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

master aa9cba6: Allow empty elements in directory-append


From: Lars Ingebrigtsen
Subject: master aa9cba6: Allow empty elements in directory-append
Date: Sun, 25 Jul 2021 02:00:59 -0400 (EDT)

branch: master
commit aa9cba658768aba4da1b74ffb33d9962ffff5756
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Allow empty elements in directory-append
    
    * doc/lispref/files.texi (Directory Names): Document it.
    * src/fileio.c (Fdirectory_append): Allow empty elements.
---
 doc/lispref/files.texi   |  4 +++-
 src/fileio.c             | 46 +++++++++++++++++++++++++++++++++-------------
 test/src/fileio-tests.el |  9 ++++++---
 3 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 804cef2..e7a0ad2 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -2355,7 +2355,9 @@ didn't end with a slash.
 @end group
 @end example
 
-A zero-length directory or component is not allowed.
+A @var{directory} or components that are @code{nil} or the empty
+string are ignored---they are filtered out first and do not affect the
+results in any way.
 
 This is almost the same as using @code{concat}, but @var{dirname} (and
 the non-final components) may or may not end with slash characters,
diff --git a/src/fileio.c b/src/fileio.c
index d6b3e7b..3d8b082 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -751,14 +751,14 @@ For that reason, you should normally use `make-temp-file' 
instead.  */)
 
 DEFUN ("directory-append", Fdirectory_append, Sdirectory_append, 1, MANY, 0,
        doc: /* Append COMPONENTS to DIRECTORY and return the resulting string.
-COMPONENTS must be strings.
+Elements in COMPONENTS must be a string or nil.
 DIRECTORY or the non-final elements in COMPONENTS may or may not end
 with a slash -- if they don't end with a slash, a slash will be
 inserted before contatenating.
 usage: (record DIRECTORY &rest COMPONENTS) */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  ptrdiff_t chars = 0, bytes = 0, multibytes = 0;
+  ptrdiff_t chars = 0, bytes = 0, multibytes = 0, eargs = 0;
   Lisp_Object *elements = args;
   Lisp_Object result;
   ptrdiff_t i;
@@ -768,9 +768,13 @@ usage: (record DIRECTORY &rest COMPONENTS) */)
   for (i = 0; i < nargs; i++)
     {
       Lisp_Object arg = args[i];
+      /* Skip empty and nil elements. */
+      if (NILP (arg))
+       continue;
       CHECK_STRING (arg);
       if (SCHARS (arg) == 0)
-       xsignal1 (Qfile_error, build_string ("Empty file name"));
+       continue;
+      eargs++;
       /* Multibyte and non-ASCII. */
       if (STRING_MULTIBYTE (arg) && SCHARS (arg) != SBYTES (arg))
        multibytes++;
@@ -789,25 +793,41 @@ usage: (record DIRECTORY &rest COMPONENTS) */)
     }
 
   /* Convert if needed. */
-  if (multibytes != 0 && multibytes != nargs)
+  if ((multibytes != 0 && multibytes != nargs)
+      || eargs != nargs)
     {
-      elements = xmalloc (nargs * sizeof *elements);
+      int j = 0;
+      elements = xmalloc (eargs * sizeof *elements);
       bytes = 0;
+      chars = 0;
+
+      /* Filter out nil/"". */
       for (i = 0; i < nargs; i++)
        {
          Lisp_Object arg = args[i];
+         if (!NILP (arg) && SCHARS (arg) != 0)
+           elements[j++] = arg;
+       }
+
+      for (i = 0; i < eargs; i++)
+       {
+         Lisp_Object arg = elements[i];
          /* Use multibyte or all-ASCII strings as is. */
-         if (STRING_MULTIBYTE (arg) || string_ascii_p (arg))
-           elements[i] = arg;
-         else
+         if (!STRING_MULTIBYTE (arg) && !string_ascii_p (arg))
            elements[i] = Fstring_to_multibyte (arg);
          arg = elements[i];
          /* We have to recompute the number of bytes. */
-         if (i == nargs - 1
+         if (i == eargs - 1
              || IS_DIRECTORY_SEP (*(SSDATA (arg) + SBYTES (arg) - 1)))
-           bytes += SBYTES (arg);
+           {
+             bytes += SBYTES (arg);
+             chars += SCHARS (arg);
+           }
          else
-           bytes += SBYTES (arg) + 1;
+           {
+             bytes += SBYTES (arg) + 1;
+             chars += SCHARS (arg) + 1;
+           }
        }
     }
 
@@ -821,13 +841,13 @@ usage: (record DIRECTORY &rest COMPONENTS) */)
 
   /* Copy over the data. */
   char *p = SSDATA (result);
-  for (i = 0; i < nargs; i++)
+  for (i = 0; i < eargs; i++)
     {
       Lisp_Object arg = elements[i];
       memcpy (p, SSDATA (arg), SBYTES (arg));
       p += SBYTES (arg);
       /* The last element shouldn't have a slash added at the end. */
-      if (i < nargs - 1 && !IS_DIRECTORY_SEP (*(p - 1)))
+      if (i < eargs - 1 && !IS_DIRECTORY_SEP (*(p - 1)))
        *p++ = DIRECTORY_SEP;
     }
 
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 73a7775..b1288f9 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -175,8 +175,11 @@ Also check that an encoding error can appear in a symlink."
     (aset string 2 255)
     (should (not (multibyte-string-p string)))
     (should (equal (directory-append "fóo" string) "fóo/aa\377aa")))
-  (should-error (directory-append "foo" ""))
-  (should-error (directory-append "" "bar"))
-  (should-error (directory-append "" "")))
+  (should (equal (directory-append "foo") "foo"))
+  (should (equal (directory-append "foo/") "foo/"))
+  (should (equal (directory-append "foo" "") "foo"))
+  (should (equal (directory-append "foo" "" "" "" nil) "foo"))
+  (should (equal (directory-append "" "bar") "bar"))
+  (should (equal (directory-append "" "") "")))
 
 ;;; fileio-tests.el ends here



reply via email to

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