PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
dirent_msvc.h
Go to the documentation of this file.
1 //
2 // dirent.h - dirent API for Microsoft Visual Studio
3 //
4 // Copyright (C) 2006 Toni Ronkko
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // ``Software''), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 // IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
24 //
25 //
26 // Jan 18, 2008, Toni Ronkko
27 // Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
28 // between multi-byte and unicode representations. This makes the
29 // code simpler and also allows the code to be compiled under MingW. Thanks
30 // to Azriel Fasten for the suggestion.
31 //
32 // Mar 4, 2007, Toni Ronkko
33 // Bug fix: due to the strncpy_s() function this file only compiled in
34 // Visual Studio 2005. Using the new string functions only when the
35 // compiler version allows.
36 //
37 // Nov 2, 2006, Toni Ronkko
38 // Major update: removed support for Watcom C, MS-DOS and Turbo C to
39 // simplify the file, updated the code to compile cleanly on Visual
40 // Studio 2005 with both unicode and multi-byte character strings,
41 // removed rewinddir() as it had a bug.
42 //
43 // Aug 20, 2006, Toni Ronkko
44 // Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
45 // comments by removing SGML tags.
46 //
47 // May 14 2002, Toni Ronkko
48 // Embedded the function definitions directly to the header so that no
49 // source modules need to be included in the Visual Studio project. Removed
50 // all the dependencies to other projects so that this very header can be
51 // used independently.
52 //
53 // May 28 1998, Toni Ronkko
54 // First version.
55 //
56 #ifndef DIRENT_H
57 #define DIRENT_H
58 
59 #include <windows.h>
60 #include <string.h>
61 #include <assert.h>
62 
63 
64 typedef struct dirent
65 {
66  // name of current directory entry (a multi-byte character string)
67  char d_name[MAX_PATH + 1];
68 
69  // file attributes
70  WIN32_FIND_DATAA data;
71 } dirent;
72 
73 
74 typedef struct DIR
75 {
76  // current directory entry
78 
79  // is there an un-processed entry in current?
80  int cached;
81 
82  // file search handle
83  HANDLE search_handle;
84 
85  // search pattern (3 = zero terminator + pattern "\\*")
86  char patt[MAX_PATH + 3];
87 } DIR;
88 
89 
90 static DIR *opendir( const char *dirname );
91 static struct dirent *readdir( DIR *dirp );
92 static int closedir( DIR *dirp );
93 
94 
95 // use the new safe string functions introduced in Visual Studio 2005
96 #if defined ( _MSC_VER ) && _MSC_VER >= 1400
97 # define STRNCPY( dest, src, size ) strncpy_s( ( dest ), ( size ), ( src ), _TRUNCATE )
98 #else
99 # define STRNCPY( dest, src, size ) strncpy( ( dest ), ( src ), ( size ) )
100 #endif
101 
102 
103 //
104 // Open directory stream DIRNAME for read and return a pointer to the
105 // internal working area that is used to retrieve individual directory
106 // entries.
107 //
108 static DIR*
110  const char *dirname )
111 {
112  DIR *dirp;
113  assert( dirname != NULL );
114  assert( strlen( dirname ) < MAX_PATH );
115 
116  // construct new DIR structure
117  dirp = (DIR *) malloc( sizeof ( struct DIR ) );
118  if ( dirp != NULL )
119  {
120  char *p;
121 
122  // take directory name...
123  STRNCPY( dirp->patt, dirname, sizeof ( dirp->patt ) );
124  dirp->patt[MAX_PATH] = '\0';
125 
126  // ... and append search pattern to it
127  p = strchr( dirp->patt, '\0' );
128  if ( dirp->patt < p && *( p - 1 ) != '\\' && *( p - 1 ) != ':' )
129  {
130  *p++ = '\\';
131  }
132  *p++ = '*';
133  *p = '\0';
134 
135  // open stream and retrieve first file
136  dirp->search_handle = FindFirstFileA( dirp->patt, &dirp->current.data );
137  if ( dirp->search_handle == INVALID_HANDLE_VALUE )
138  {
139  // invalid search pattern?
140  free( dirp );
141  return NULL;
142  }
143 
144  // there is an un-processed directory entry in memory now
145  dirp->cached = 1;
146  }
147  return dirp;
148 }
149 
150 
151 //
152 // Read a directory entry, and return a pointer to a dirent structure
153 // containing the name of the entry in d_name field. Individual directory
154 // entries returned by this very function include regular files,
155 // sub-directories, pseudo-directories "." and "..", but also volume labels,
156 // hidden files and system files may be returned.
157 //
158 static struct dirent *
160  DIR *dirp )
161 {
162  assert( dirp != NULL );
163 
164  if ( dirp->search_handle == INVALID_HANDLE_VALUE )
165  {
166  // directory stream was opened/rewound incorrectly or it ended normally
167  return NULL;
168  }
169 
170  // get next directory entry
171  if ( dirp->cached != 0 )
172  {
173  // a valid directory entry already in memory
174  dirp->cached = 0;
175  }
176  else
177  {
178  // read next directory entry from disk
179  if ( FindNextFileA( dirp->search_handle, &dirp->current.data ) == FALSE )
180  {
181  // the very last file has been processed or an error occured
182  FindClose( dirp->search_handle );
183  dirp->search_handle = INVALID_HANDLE_VALUE;
184  return NULL;
185  }
186  }
187 
188  // copy as a multibyte character string
189  STRNCPY( dirp->current.d_name, dirp->current.data.cFileName, sizeof ( dirp->current.d_name ) );
190  dirp->current.d_name[MAX_PATH] = '\0';
191 
192  return &dirp->current;
193 }
194 
195 
196 //
197 // Close directory stream opened by opendir() function. Close of the
198 // directory stream invalidates the DIR structure as well as any previously
199 // read directory entry.
200 //
201 static int
203  DIR *dirp )
204 {
205  assert( dirp != NULL );
206 
207  // release search handle
208  if ( dirp->search_handle != INVALID_HANDLE_VALUE )
209  {
210  FindClose( dirp->search_handle );
211  dirp->search_handle = INVALID_HANDLE_VALUE;
212  }
213 
214  // release directory handle
215  free( dirp );
216  return 0;
217 }
218 
219 
220 #endif //DIRENT_H