OSDN Git Service

Avoid snprintf() overhead in directory stream functions.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Thu, 26 Jan 2017 18:56:27 +0000 (18:56 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Thu, 26 Jan 2017 18:56:27 +0000 (18:56 +0000)
mingwrt/ChangeLog
mingwrt/mingwex/dirent.c

index b90c04e..67091e8 100644 (file)
@@ -1,5 +1,16 @@
 2017-01-26  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
+       Avoid snprintf() overhead in directory stream functions.
+
+       * mingwex/dirent.c (dirent_update): Do not use either snprintf() or
+       snwprintf() functions when updating dd->d_name and dd->d_namlen data;
+       emulate them instead, using a lightweight inline char-by-char counted
+       copy loop, operating on char or wchar_t data as appropriate.
+       (DIRENT_ASSIGN_NAME): Macro no longer required; delete it.
+       (NUL): New manifest constant; define it.
+
+2017-01-26  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
        Avoid #include_next misbehaviour; cf. MinGW-Bug [#2330]
 
        * include/ctype.h (wctype.h): Use "..." form of #include, rather than
index e6813c1..10a2ac7 100644 (file)
@@ -1,24 +1,46 @@
 /*
  * dirent.c
  *
- * This file has no copyright assigned and is placed in the Public Domain.
+ * $Id$
+ *
+ * Provides emulation of POSIX "directory stream" manipulation functions,
+ * in terms of the MS-Windows FindFile API.
  *
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
  *
  * Derived from DIRLIB.C by Matt J. Weinstein
- * This note appears in the DIRLIB.H
+ * This note appears in the associated DIRLIB.H header file:
  * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
  *
  * Updated by Jeremy Bettis <jeremy@hksys.com>
  * Significantly revised and rewinddir, seekdir and telldir added
  * by Colin Peters <colin@fu.is.saga-u.ac.jp>
+ *
  * Further significantly revised for improved memory utilisation,
  * efficiency in operation, and better POSIX standards compliance
  * by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 1997, 2001-2006, 2014, 2017, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
  */
-#include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <windows.h>
 #include <tchar.h>
 
-#ifdef _UNICODE
-  /* In a Unicode build, the path name within the _wdirent struct is
-   * represented by a wchar_t string; we use the snwprintf() function
-   * to simultaneously assign the d_name and d_namlen fields, copying
-   * from a temporary WIN32_FIND_DATA struct on the stack...
-   */
-# include <wchar.h>
-# define DIRENT_ASSIGN_NAME  snwprintf
-
-#else
-  /* ...while for a non-Unicode build, the corresponding data within
-   * the dirent structure is represented by a normal char string, and
-   * the assignments are made by the snprintf() function.
-   */
-# define DIRENT_ASSIGN_NAME  snprintf
-#endif
-
 /* This implementation applies a "__mingw_" pseudo-namespace prefix to
  * the standard POSIX function names, for each each function it defines;
  * the following pair of macros facilitates this.
@@ -150,16 +155,33 @@ struct __wdirstream_t
  */
 #define DT_VALID_BITS  ~(DT_IGNORED | 0x0080)
 
+/* For convenience, we identify the NUL "character" which terminates any
+ * file or directory name, appropriately typed, using this macro:
+ */
+#define NUL            ((_TCHAR)(0))
+
 static
 void dirent_update( struct _tdirent *dd, WIN32_FIND_DATA *fd )
 {
   /* Helper function, used by dirent_findfirst() and dirent_findnext(),
    * to transfer all relevant data from their respective WIN32_FIND_DATA
-   * buffers to the specified dirent structure.
+   * buffers to the specified dirent structure; in the case of the d_name
+   * field, we want the effect of a snprintf() string transfer, but to
+   * avoid the (perceptually significant) overhead of format parsing,
+   * we simulate it with an inline character-by-character counted
+   * string copy loop...
+   */
+  _TCHAR *d_name = dd->d_name;
+  for( dd->d_namlen = 0; (*d_name = fd->cFileName[dd->d_namlen]) != NUL; )
+    /*
+     * ...continuing to count input characters, until the terminal NUL,
+     * but declining to store any character beyond the physical end of
+     * the d_name field buffer.
+     */
+    if( ++dd->d_namlen < FILENAME_MAX ) ++d_name;
+
+  /* Store only those file attribute bits which are valid for d_type.
    */
-  dd->d_namlen = DIRENT_ASSIGN_NAME( dd->d_name, FILENAME_MAX,
-      _T("%s"), fd->cFileName
-    );
   if( (dd->d_type = fd->dwFileAttributes & DT_VALID_BITS) > DT_DIR )
     dd->d_type = DT_UNKNOWN;
 }