YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
FileSystem.cpp
浏览该文件的文档.
1 /*
2  Copyright by FrankHB 2012 - 2013.
3 
4  This file is part of the YSLib project, and may only be used,
5  modified, and distributed under the terms of the YSLib project
6  license, LICENSE.TXT. By continuing to use, modify, or distribute
7  this file you indicate that you have read the license and
8  understand and accept it fully.
9 */
10 
28 #include "YCLib/FileSystem.h"
29 #include "YCLib/NativeAPI.h"
30 #include "CHRLib/chrproc.h"
31 #include <cstring> // for std::strcpy, std::strchr;
32 #if YCL_DS
33 # include <fcntl.h>
34 
36 extern "C" int _EXFUN(fileno, (FILE *));
37 #elif YCL_MINGW32
38 # include <Shlwapi.h> // for ::PathIsRelativeW;
39 
41 
42 extern "C"
43 {
44 
45 struct _WDIR;
46 struct _wdirent;
47 
48 struct _WDIR* __cdecl __MINGW_NOTHROW
49 _wopendir(const wchar_t*);
50 struct _wdirent* __cdecl __MINGW_NOTHROW
51 _wreaddir(_WDIR*);
52 int __cdecl __MINGW_NOTHROW
53 _wclosedir(_WDIR*);
54 
55 } // extern "C";
57 #endif
58 
59 namespace platform
60 {
61 
62 static_assert(std::is_same<CHRLib::ucs2_t, char16_t>::value,
63  "Wrong character type!");
64 static_assert(std::is_same<CHRLib::ucs4_t, char32_t>::value,
65  "Wrong character type!");
66 #if YCL_MINGW32
67 static_assert(sizeof(wchar_t) == sizeof(CHRLib::ucs2_t),
68  "Wrong character type!");
69 static_assert(yalignof(wchar_t) == yalignof(CHRLib::ucs2_t),
70  "Inconsist alignment between character types!");
71 #endif
72 
73 namespace
74 {
75 
76 #if YCL_DS
78 u16_to_u(const char16_t* u16str)
79 {
80  yconstraint(u16str);
81 
82  static char* tstr;
83  std::string str;
84 
85  str = std::string(tstr = CHRLib::strdup(u16str));
86  std::free(tstr);
87  return std::move(str);
88 }
89 #elif YCL_MINGW32
90 std::wstring
91 u_to_w(const char* str)
92 {
93  yconstraint(str);
94 
95  static CHRLib::ucs2_t* tstr;
96  std::wstring wstr;
97 
98  wstr = std::wstring(reinterpret_cast<const wchar_t*>(
99  tstr = CHRLib::ucsdup(str)));
100  std::free(tstr);
101  return std::move(wstr);
102 }
103 #else
104 # error Unsupported platform found!
105 #endif
106 
107 } // unnamed namespace;
108 
109 
110 int
111 uopen(const char* filename, int oflag) ynothrow
112 {
113  yconstraint(filename);
114 
115 #if YCL_DS
116  return ::open(filename, oflag);
117 #elif YCL_MINGW32
118  try
119  {
120  return ::_wopen(u_to_w(filename).c_str(), oflag);
121  }
122  catch(...)
123  {}
124  return -1;
125 #else
126 # error Unsupported platform found!
127 #endif
128 }
129 int
130 uopen(const char* filename, int oflag, int pmode) ynothrow
131 {
132  yconstraint(filename);
133 
134 #if YCL_DS
135  return ::open(filename, oflag, pmode);
136 #elif YCL_MINGW32
137  try
138  {
139  return ::_wopen(u_to_w(filename).c_str(), oflag, pmode);
140  }
141  catch(...)
142  {}
143  return -1;
144 #else
145 # error Unsupported platform found!
146 #endif
147 }
148 int
149 uopen(const char16_t* filename, int oflag) ynothrow
150 {
151  yconstraint(filename);
152 
153 #if YCL_DS
154  try
155  {
156  return ::open(u16_to_u(filename).c_str(), oflag);
157  }
158  catch(...)
159  {}
160  return -1;
161 #elif YCL_MINGW32
162  return ::_wopen(reinterpret_cast<const wchar_t*>(filename), oflag);
163 #else
164 # error Unsupported platform found!
165 #endif
166 }
167 int
168 uopen(const char16_t* filename, int oflag, int pmode) ynothrow
169 {
170  yconstraint(filename);
171 
172 #if YCL_DS
173  try
174  {
175  return ::open(u16_to_u(filename).c_str(), oflag, pmode);
176  }
177  catch(...)
178  {}
179  return -1;
180 #elif YCL_MINGW32
181  return ::_wopen(reinterpret_cast<const wchar_t*>(filename), oflag, pmode);
182 #else
183 # error Unsupported platform found!
184 #endif
185 }
186 
187 std::FILE*
188 ufopen(const char* filename, const char* mode) ynothrow
189 {
190  yconstraint(filename),
191  yconstraint(mode);
192  yconstraint(*mode != char());
193 
194 #if YCL_DS
195  return std::fopen(filename, mode);
196 #elif YCL_MINGW32
197  try
198  {
199  return ::_wfopen(u_to_w(filename).c_str(), u_to_w(mode).c_str());
200  }
201  catch(...)
202  {}
203  return nullptr;
204 #else
205 # error Unsupported platform found!
206 #endif
207 }
208 std::FILE*
209 ufopen(const char16_t* filename, const char16_t* mode) ynothrow
210 {
211  yconstraint(filename),
212  yconstraint(mode);
213  yconstraint(*mode != char());
214 
215 #if YCL_DS
216  try
217  {
218  return std::fopen(u16_to_u(filename).c_str(), u16_to_u(mode).c_str());
219  }
220  catch(...)
221  {}
222  return nullptr;
223 #elif YCL_MINGW32
224  return ::_wfopen(reinterpret_cast<const wchar_t*>(filename),
225  reinterpret_cast<const wchar_t*>(mode));
226 #else
227 # error Unsupported platform found!
228 #endif
229 }
230 
231 bool
232 ufexists(const char* filename) ynothrow
233 {
234 #if YCL_DS
235  return ystdex::fexists(filename);
236 #elif YCL_MINGW32
237  yconstraint(filename);
238 
239  if(const auto file = ufopen(filename, "rb"))
240  {
241  std::fclose(file);
242  return true;
243  }
244  return false;
245 #else
246 # error Unsupported platform found!
247 #endif
248 }
249 bool
250 ufexists(const char16_t* filename) ynothrow
251 {
252  yconstraint(filename);
253 
254  if(const auto file = ufopen(filename, u"rb"))
255  {
256  std::fclose(file);
257  return true;
258  }
259  return false;
260 }
261 
262 bool
264 {
265  const auto dir(::opendir(path));
266 
267  ::closedir(dir);
268  return dir;
269 }
270 
271 bool
273 {
274 #if YCL_MINGW32
275  using namespace CHRLib;
276 
277  if(path)
278  try
279  {
280  const auto dir(::_wopendir(u_to_w(path).c_str()));
281 
282  ::_wclosedir(dir);
283  return dir;
284  }
285  catch(...)
286  {}
287  return false;
288 #else
289  return direxists(path);
290 #endif
291 }
292 
293 char*
294 getcwd_n(char* buf, std::size_t size) ynothrow
295 {
296  if(YB_LIKELY(buf))
297  return ::getcwd(buf, size);
298  return nullptr;
299 }
300 
301 char16_t*
302 u16getcwd_n(char16_t* buf, std::size_t size) ynothrow
303 {
304  if(size == 0)
305  // last_err = EINVAL;
306  ;
307  else
308  {
309  using namespace std;
310  using namespace CHRLib;
311 
312  if(YB_LIKELY(buf))
313 #if YCL_DS
314  {
315  const auto p(static_cast<ucs2_t*>(malloc((size + 1)
316  * sizeof(ucs2_t))));
317 
318  if(YB_LIKELY(p))
319  {
320  auto len(MBCSToUCS2(p,
321  ::getcwd(reinterpret_cast<char*>(buf), size)));
322 
323  if(size < len + 1)
324  {
325  // last_err = ERANGE;
326  return nullptr;
327  }
328  memcpy(buf, p, ++len * sizeof(ucs2_t));
329  return buf;
330  }
331  // else
332  // last_err = ENOMEM;
333  }
334 #elif YCL_MINGW32
335  return reinterpret_cast<ucs2_t*>(
336  ::_wgetcwd(reinterpret_cast<wchar_t*>(buf), size));
337 #else
338 # error Unsupported platform found!
339 #endif
340  }
341  return nullptr;
342 }
343 
344 int
346 {
347 #if YCL_DS
348  return ::chdir(path);
349 #elif YCL_MINGW32
350  try
351  {
352  return path ? ::_wchdir(u_to_w(path).c_str()) : -1;
353  }
354  catch(...)
355  {}
356  return -1;
357 #else
358 # error Unsupported platform found!
359 #endif
360 }
361 
362 bool
364 {
365  PATHSTR path;
366 
367  std::strcpy(path, cpath);
368  for(char* slash(path); (slash = strchr(slash, YCL_PATH_DELIMITER));
369  ++slash)
370  {
371  *slash = char();
372  ::mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
373  *slash = '/';
374  }
375  //新建目录成功或目标路径已存在时返回 true 。
376  return ::mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) == 0
377  || errno == EEXIST;
378 }
379 
380 bool
381 truncate(std::FILE* fp, std::size_t size) ynothrow
382 {
383 #if YCL_DS
384  return ::ftruncate(fileno(fp), ::off_t(size)) != 0;
385 #elif YCL_MINGW32
386  return ::_chsize(_fileno(fp), long(size));
387 #else
388 # error Unsupported platform found!
389 #endif
390 }
391 
392 
393 int HFileNode::LastError(0);
394 
395 HFileNode&
397 {
398  LastError = 0;
399  if(YB_LIKELY(*this))
400  {
401  if(!(p_dirent = ::readdir(dir)))
402  LastError = 2;
403  }
404  else
405  LastError = 1;
406  return *this;
407 }
408 
409 bool
411 {
412 #if YCL_DS || YCL_MINGW32
414 #else
415 # error Unsupported platform found!
416 #endif
417 }
418 
419 const char*
421 {
422  return p_dirent ? p_dirent->d_name : ".";
423 }
424 
425 void
427 {
428  dir = path ? ::opendir(path) : nullptr;
429 }
430 
431 void
433 {
434  LastError = *this ? ::closedir(dir) : 1;
435  dir = nullptr;
436 }
437 
438 void
440 {
441  ::rewinddir(dir);
442 }
443 
444 
445 bool
447 {
448 #if YCL_DS
449  if(path)
450  {
451  if(*path == '/')
452  return true;
453 
454  const auto p(std::strstr(path, ":/"));
455 
456  return p && p != path && !std::strstr(p, ":/");
457  }
458  return false;
459 #elif YCL_MINGW32
460  return !::PathIsRelativeW(u_to_w(path).c_str());
461 #else
462 # error Unsupported platform found!
463 #endif
464 }
465 
466 std::size_t
468 {
469  const char* p(std::strchr(path, ':'));
470 
471  return !p ? 0 : p - path + 1;
472 }
473 
474 }
475 
476 namespace platform_ex
477 {
478 
479 }
480