YSTest: FileIO.cpp 源文件

YSTest PreAlpha_b700_20160611 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

FileIO.cpp
浏览该文件的文档.
1 /*
2 © 2011-2016 FrankHB.
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 #undef __STRICT_ANSI__ // for fileno, ::pclose, ::popen for POSIX platforms;
29 // _fileno, _wfopen for MinGW.org;
30 #include "YCLib/YModules.h"
31 #include YFM_YCLib_FileIO
32 #include YFM_YCLib_Debug // for Nonnull, ystdex::throw_error,
33 // ystdex::temporary_buffer;
34 #include YFM_YCLib_Reference // for unique_ptr;
35 #include YFM_YCLib_NativeAPI // for std::is_same, ystdex::underlying_type_t,
36 // Mode, ::HANDLE, struct ::stat, ::fstat, ::stat, ::lstat, ::close, ::fcntl,
37 // F_GETFL, _O_*, O_*, ::fchmod, ::_chsize, ::ftruncate, ::setmode, ::_wgetcwd,
38 // ::getcwd, !defined(__STRICT_ANSI__) API, platform_ex::futimens;
39 #include <ystdex/functional.hpp> // for ystdex::compose, ystdex::addrof;
40 #include <ystdex/streambuf.hpp> // for ystdex::streambuf_equal;
41 #if YCL_DS
42 # include "CHRLib/YModules.h"
43 # include YFM_CHRLib_CharacterProcessing // for CHRLib::MakeMBCS;
44
46 using namespace CHRLib;
47 #elif YCL_Win32
48 # if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
49 // At least one headers of <stdlib.h>, <stdio.h>, <Windows.h>, <Windef.h>
50 // (and probably more) should have been included to make the MinGW-W64 macro
51 // available if it is really being used.
52 # undef _fileno
53 # endif
54 # include YFM_Win32_YCLib_MinGW32 // for platform_ex::FileAttributes,
55 // platform_ex::GetErrnoFromWin32, platform_ex::QueryFileLinks,
56 // platform_ex::QueryFileNodeID, platform_ex::QueryFileTime,
57 // platform_ex::WCSToUTF8, platform_ex::UTF8ToWCS, platform_ex::ConvertTime,
58 // platform_ex::SetFileTime;
59
61 using platform_ex::FileAttributes;
62 using platform_ex::GetErrnoFromWin32;
64 using platform_ex::QueryFileLinks;
66
67 using platform_ex::QueryFileNodeID;
68 using platform_ex::QueryFileTime;
70 using platform_ex::UTF8ToWCS;
72 using platform_ex::WCSToUTF8;
73 using platform_ex::ConvertTime;
75 #elif YCL_API_POSIXFileSystem
76 # include "CHRLib/YModules.h"
77 # include YFM_CHRLib_CharacterProcessing // for MakeMBCS;
78 # include <dirent.h>
79
81 using namespace CHRLib;
82 #else
83 # error "Unsupported platform found."
84 #endif
85
86 namespace platform
87 {
88
90 static_assert(std::is_same<::mode_t, ystdex::underlying_type_t<Mode>>(),
91 "Mismatched mode types found.");
92
93 // XXX: Catch %std::bad_alloc?
94 #define YCL_Impl_RetTryCatchAll(...) \
95 TryRet(__VA_ARGS__) \
96 CatchExpr(std::bad_alloc&, errno = ENOMEM) \
97 CatchIgnore(...)
98
99 namespace
100 {
101
103
104 template<typename _func>
105 auto
106 RetryOnInterrupted(_func f) -> decltype(RetryOnError(f, errno, EINTR))
107 {
108 return RetryOnError(f, errno, EINTR);
109 }
110
111 template<typename _func, typename _tBuf>
112 size_t
113 #if YCL_Win64
114 SafeReadWrite(_func f, int fd, _tBuf buf, unsigned nbyte) ynothrowv
115 #else
116 SafeReadWrite(_func f, int fd, _tBuf buf, size_t nbyte) ynothrowv
117 #endif
118 {
119 return size_t(RetryOnInterrupted([&]{
120 return f(fd, buf, nbyte);
121 }));
122 }
123
124 template<int _vErr, typename _func, typename _tByteBuf>
125 _tByteBuf
126 FullReadWrite(_func f, _tByteBuf ptr, size_t nbyte)
127 {
128 while(nbyte > 0)
129 {
130 const auto n(f(ptr, nbyte));
131
132 if(n == size_t(-1))
133 break;
134 if(n == 0)
135 {
136 errno = _vErr;
137 break;
138 }
139 yunseq(ptr += n, nbyte -= n);
140 }
141 return ptr;
142 }
144
145 #if YCL_Win32
146 inline PDefH(::HANDLE, ToHandle, int fd) ynothrow
148 ImplRet(::HANDLE(::_get_osfhandle(fd)))
149
150 void
152 QueryFileTime(const char* path, ::FILETIME* p_ctime, ::FILETIME* p_atime,
153 ::FILETIME* p_mtime, bool follow_reparse_point)
154 {
155 QueryFileTime(UTF8ToWCS(path).c_str(), p_ctime, p_atime, p_mtime,
156 follow_reparse_point);
157 }
159
160 void
161 QueryFileTime(int fd, ::FILETIME* p_ctime, ::FILETIME* p_atime,
162 ::FILETIME* p_mtime)
163 {
164 QueryFileTime(ToHandle(fd), p_ctime, p_atime, p_mtime);
165 }
166
167 // TODO: Blocked. Use C++14 generic lambda expressions.
168 yconstexpr const struct
169 {
170 template<typename _tParam, typename... _tParams>
171 FileTime
172 operator()(_tParam arg, _tParams... args) const
173 {
174 ::FILETIME atime{};
175
176 QueryFileTime(arg, {}, &atime, {}, args...);
177 return ConvertTime(atime);
178 }
179 } get_st_atime{};
180 yconstexpr const struct
181 {
182 template<typename _tParam, typename... _tParams>
183 FileTime
184 operator()(_tParam arg, _tParams... args) const
185 {
186 ::FILETIME mtime{};
187
188 QueryFileTime(arg, {}, {}, &mtime, args...);
189 return ConvertTime(mtime);
190 }
191 } get_st_mtime{};
192 yconstexpr const struct
193 {
194 template<typename _tParam, typename... _tParams>
195 array<FileTime, 2>
196 operator()(_tParam arg, _tParams... args) const
197 {
198 ::FILETIME mtime{}, atime{};
199
200 QueryFileTime(arg, {}, &atime, &mtime, args...);
201 return array<FileTime, 2>{ConvertTime(mtime), ConvertTime(atime)};
202 }
203 } get_st_matime{};
205
207
208 YB_NONNULL(1) bool
209 UnlinkWithAttr(const wchar_t* path, FileAttributes attr) ynothrow
210 {
211 return !(attr & FileAttributes::ReadOnly) || ::SetFileAttributesW(path,
212 attr & ~FileAttributes::ReadOnly) ? ::_wunlink(path) == 0
213 : (errno = GetErrnoFromWin32(), false);
214 }
215
216 template<typename _func>
217 YB_NONNULL(2) bool
218 CallFuncWithAttr(_func f, const char* path)
219 {
220 const auto& wpath(UTF8ToWCS(path));
221 const auto& wstr(wpath.c_str());
222 const auto attr(FileAttributes(::GetFileAttributesW(wstr)));
223
224 return attr != platform_ex::Invalid ? f(wstr, attr)
225 : (errno = GetErrnoFromWin32(), false);
226 }
228 #else
229 inline PDefH(::timespec, ToTimeSpec, FileTime ft) ynothrow
231 ImplRet({std::time_t(ft.count() / 1000000000LL),
232 long(ft.count() % 1000000000LL)})
233
234 YB_NONNULL(2) void
236 TrySetFileTime(int fd, const ::timespec* times)
237 {
238 #if YCL_DS
239 // XXX: Hack.
240 #ifndef UTIME_OMIT
241 # define UTIME_OMIT (-1L)
242 #endif
243 yunused(fd), yunused(times);
244 ystdex::throw_error(std::errc::function_not_supported);
245 #else
246 if(::futimens(fd, times) != 0)
247 ThrowFileOperationFailure("Failed setting file time.");
248 #endif
249 }
250
252
253 const auto get_st_atime([](struct ::stat& st){
254 return FileTime(st.st_atime);
255 });
256 const auto get_st_mtime([](struct ::stat& st){
257 return FileTime(st.st_mtime);
258 });
259 const auto get_st_matime([](struct ::stat& st){
260 return array<FileTime, 2>{FileTime(st.st_mtime), FileTime(st.st_atime)};
261 });
263
265
266 static_assert(std::is_integral<::dev_t>(),
267 "Nonconforming '::dev_t' type found.");
268 static_assert(std::is_unsigned<::ino_t>(),
269 "Nonconforming '::ino_t' type found.");
270
271 inline PDefH(FileNodeID, get_file_node_id, struct ::stat& st) ynothrow
272 ImplRet({std::uint64_t(st.st_dev), std::uint64_t(st.st_ino)})
274
276
277 YB_NONNULL(2) int
278 estat(struct ::stat& st, const char* path, bool follow_link)
279 {
280 # if YCL_DS
281 yunused(follow_link);
282 return ::stat(Nonnull(path), &st);
283 # else
284 return (follow_link ? ::stat : ::lstat)(Nonnull(path), &st);
285 # endif
286 }
287 YB_NONNULL(2) int
288 estat(struct ::stat& st, const char16_t* path, bool follow_link)
289 {
290 return estat(st, MakeMBCS(path).c_str(), follow_link);
291 }
292 #endif
293 int
294 estat(struct ::stat& st, int fd)
295 {
296 return ::fstat(fd, &st);
297 }
299
301 template<typename _func, typename... _tParams>
302 auto
303 FetchFileTime(_func f, _tParams... args)
304 #if YCL_Win32
305 -> ystdex::result_of_t<_func(_tParams&...)>
306 #else
307 -> ystdex::result_of_t<_func(struct ::stat&)>
308 #endif
309 {
310 #if YCL_Win32
311 // NOTE: The %::FILETIME has resolution of 100 nanoseconds.
312 // XXX: Error handling for indirect calls.
313 TryRet(f(args...))
314 CatchThrow(std::system_error& e, FileOperationFailure(e.code(),
315 std::string("Failed querying file time: ") + e.what()))
316 #else
317 // TODO: Get more precise time count.
318 struct ::stat st;
319
320 if(estat(st, args...) == 0)
321 return f(st);
322 ThrowFileOperationFailure("Failed querying file time.");
323 #endif
324 }
325
327 bool
328 IsNodeShared_Impl(const char* a, const char* b, bool follow_link) ynothrow
329 {
330 #if YCL_Win32
331 YCL_Impl_RetTryCatchAll(QueryFileNodeID(UTF8ToWCS(a).c_str(), follow_link)
332 == QueryFileNodeID(UTF8ToWCS(b).c_str(), follow_link))
333 return {};
334 #else
335 struct ::stat st;
336
337 if(estat(st, a, follow_link) != 0)
338 return {};
339
340 const auto id(get_file_node_id(st));
341
342 if(estat(st, b, follow_link) != 0)
343 return {};
344
345 return IsNodeShared(id, get_file_node_id(st));
346 #endif
347 }
349 bool
350 IsNodeShared_Impl(const char16_t* a, const char16_t* b, bool follow_link) ynothrow
351 {
352 #if YCL_Win32
353 YCL_Impl_RetTryCatchAll(QueryFileNodeID(wcast(a), follow_link)
354 == QueryFileNodeID(wcast(b), follow_link))
355 return {};
356 #else
357 return IsNodeShared_Impl(MakeMBCS(a).c_str(), MakeMBCS(b).c_str(), follow_link);
358 #endif
359 }
360
361 } // unnamed namespace;
362
363
364 string
365 MakePathString(const char16_t* s)
366 {
367 #if YCL_Win32
368 return WCSToUTF8(wcast(s));
369 #else
370 return MakeMBCS(s);
371 #endif
372 }
373
374
375 NodeCategory
376 CategorizeNode(mode_t st_mode) ynothrow
377 {
378 auto res(NodeCategory::Empty);
379 const auto m(Mode(st_mode) & Mode::FileType);
380
381 if((m & Mode::Directory) == Mode::Directory)
382 res |= NodeCategory::Directory;
383 #if !YCL_Win32
384 if((m & Mode::Link) == Mode::Link)
385 res |= NodeCategory::Link;
386 #endif
387 if((m & Mode::Regular) == Mode::Regular)
388 res |= NodeCategory::Regular;
389 if(YB_UNLIKELY((m & Mode::Character) == Mode::Character))
390 res |= NodeCategory::Character;
391 #if !YCL_Win32
392 else if(YB_UNLIKELY((m & Mode::Block) == Mode::Block))
393 res |= NodeCategory::Block;
394 #endif
395 if(YB_UNLIKELY((m & Mode::FIFO) == Mode::FIFO))
396 res |= NodeCategory::FIFO;
397 #if !YCL_Win32
398 if((m & Mode::Socket) == Mode::Socket)
399 res |= NodeCategory::Socket;
400 #endif
401 return res;
402 }
403
404
405 void
406 FileDescriptor::Deleter::operator()(pointer p) const ynothrow
407 {
408 if(p)
409 // NOTE: Error is ignored.
410 // See $2016-03 @ %Documentation::Workflow::Annual2016.
411 ::close(*p);
412 }
413
414
415 FileDescriptor::FileDescriptor(std::FILE* fp) ynothrow
416 #if YCL_Win32
417 : desc(fp ? ::_fileno(fp) : -1)
418 #else
419 : desc(fp ? fileno(fp) : -1)
420 #endif
421 {}
422
423 FileTime
424 FileDescriptor::GetAccessTime() const
425 {
426 return FetchFileTime(get_st_atime, desc);
427 }
428 NodeCategory
429 FileDescriptor::GetCategory() const ynothrow
430 {
431 #if YCL_Win32
432 const auto h(ToHandle(desc));
433
434 return h ? platform_ex::CategorizeNode(h) : NodeCategory::Invalid;
435 #else
436 struct ::stat st;
437
438 return estat(st, desc) == 0 ? CategorizeNode(st.st_mode)
439 : NodeCategory::Invalid;
440 #endif
441 }
442 int
443 FileDescriptor::GetFlags() const ynothrow
444 {
445 #if YCL_API_POSIXFileSystem
446 return ::fcntl(desc, F_GETFL);
447 #else
448 errno = ENOSYS;
449 return -1;
450 #endif
451 }
452 mode_t
453 FileDescriptor::GetMode() const ynothrow
454 {
455 struct ::stat st;
456
457 return estat(st, desc) == 0 ? st.st_mode : 0;
458 }
459 FileTime
460 FileDescriptor::GetModificationTime() const
461 {
462 return FetchFileTime(get_st_mtime, desc);
463 }
464 array<FileTime, 2>
465 FileDescriptor::GetModificationAndAccessTime() const
466 {
467 return FetchFileTime(get_st_matime, desc);
468 }
469 FileNodeID
470 FileDescriptor::GetNodeID() const ynothrow
471 {
472 #if YCL_Win32
473 YCL_Impl_RetTryCatchAll(QueryFileNodeID(ToHandle(desc)))
474 #else
475 struct ::stat st;
476
477 if(estat(st, desc) == 0)
478 return get_file_node_id(st);
479 #endif
480 return FileNodeID();
481 }
482 size_t
483 FileDescriptor::GetNumberOfLinks() const ynothrow
484 {
485 #if YCL_Win32
486 YCL_Impl_RetTryCatchAll(QueryFileLinks(ToHandle(desc)))
487 #else
488 struct ::stat st;
489 static_assert(std::is_unsigned<decltype(st.st_nlink)>(),
490 "Unsupported '::nlink_t' type found.");
491
492 if(estat(st, desc) == 0)
493 return size_t(st.st_nlink);
494 #endif
495 return size_t();
496 }
497 std::uint64_t
498 FileDescriptor::GetSize() const
499 {
500 #if YCL_Win32
501 ::LARGE_INTEGER sz;
502
503 // XXX: Error handling for indirect calls.
504 if(::GetFileSizeEx(ToHandle(desc), &sz) != 0 && YB_LIKELY(sz.QuadPart >= 0))
505 return std::uint64_t(sz.QuadPart);
506 ystdex::throw_error<FileOperationFailure>(GetErrnoFromWin32(),
507 "Failed getting file size.");
508 #else
509 struct ::stat st;
510
511 if(estat(st, desc) == 0)
512 // TODO: Use YSLib::CheckNonnegativeScalar<std::uint64_t>?
513 // XXX: No negative file size should be found. See also:
514 // http://stackoverflow.com/questions/12275831/why-is-the-st-size-field-in-struct-stat-signed.
515 return std::uint64_t(st.st_size);
516 ThrowFileOperationFailure("Failed getting file size.");
517 #endif
518 }
519
520 void
521 FileDescriptor::SetAccessTime(FileTime ft) const
522 {
523 #if YCL_Win32
524 auto atime(ConvertTime(ft));
525
526 platform_ex::SetFileTime(ToHandle(desc), {}, &atime, {});
527 #else
528 const ::timespec times[]{ToTimeSpec(ft), {yimpl(0), UTIME_OMIT}};
529
530 TrySetFileTime(desc, times);
531 #endif
532 }
533 bool
534 FileDescriptor::SetBlocking() const ynothrow
535 {
536 #if YCL_API_POSIXFileSystem
537 // NOTE: Read-modify-write operation is need for compatibility.
538 // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html.
539 const int flags(GetFlags());
540
541 if(flags != -1 && flags & O_NONBLOCK)
542 return SetFlags(flags & ~O_NONBLOCK);
543 #else
544 errno = ENOSYS;
545 #endif
546 return {};
547 }
548 bool
549 FileDescriptor::SetFlags(int flags) const ynothrow
550 {
551 #if YCL_API_POSIXFileSystem
552 return ::fcntl(desc, F_SETFL, flags) != -1;
553 #else
554 // TODO: Try using NT6 %::SetFileInformationByHandle for Win32.
555 yunused(flags);
556 errno = ENOSYS;
557 return {};
558 #endif
559 }
560 bool
561 FileDescriptor::SetMode(mode_t mode) const ynothrow
562 {
563 #if YCL_API_POSIXFileSystem
564 return ::fchmod(desc, mode) != -1;
565 #else
566 yunused(mode);
567 errno = ENOSYS;
568 return {};
569 #endif
570 }
571 void
572 FileDescriptor::SetModificationTime(FileTime ft) const
573 {
574 #if YCL_Win32
575 auto mtime(ConvertTime(ft));
576
577 platform_ex::SetFileTime(ToHandle(desc), {}, {}, &mtime);
578 #else
579 const ::timespec times[]{{yimpl(0), UTIME_OMIT}, ToTimeSpec(ft)};
580
581 TrySetFileTime(desc, times);
582 #endif
583 }
584 void
585 FileDescriptor::SetModificationAndAccessTime(array<FileTime, 2> fts) const
586 {
587 #if YCL_Win32
588 auto atime(ConvertTime(fts[0])), mtime(ConvertTime(fts[1]));
589
590 platform_ex::SetFileTime(ToHandle(desc), {}, &atime, &mtime);
591 #else
592 const ::timespec times[]{ToTimeSpec(fts[0]), ToTimeSpec(fts[1])};
593
594 TrySetFileTime(desc, times);
595 #endif
596 }
597 bool
598 FileDescriptor::SetNonblocking() const ynothrow
599 {
600 #if YCL_API_POSIXFileSystem
601 // NOTE: Read-modify-write operation is need for compatibility.
602 // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html.
603 const int flags(GetFlags());
604
605 if(flags != -1 && !(flags & O_NONBLOCK))
606 return SetFlags(flags | O_NONBLOCK);
607 #else
608 errno = ENOSYS;
609 #endif
610 return {};
611 }
612 bool
613 FileDescriptor::SetSize(size_t size) ynothrow
614 {
615 #if YCL_Win32
616 return ::_chsize(desc, long(size)) == 0;
617 #else
618 // FIXME: It seems that on Android 32-bit size is always used even if
619 // '_FILE_OFFSET_BITS == 1'. Thus it is not safe and would better to be
620 // ignored slightly.
621 return ::ftruncate(desc, ::off_t(size)) == 0;
622 #endif
623 }
624 int
625 FileDescriptor::SetTranslationMode(int mode) const ynothrow
626 {
627 #if YCL_Win32
628 return ::_setmode(desc, mode);
629 #elif defined(_NEWLIB_VERSION) && defined(__SCLE)
630 // TODO: Other platforms.
631 return ::setmode(desc, mode);
632 #else
633 // NOTE: No effect.
634 yunused(mode);
635 return 0;
636 #endif
637 }
638
639 size_t
640 FileDescriptor::FullRead(void* buf, size_t nbyte) ynothrowv
641 {
642 using namespace std::placeholders;
643 const auto p_buf(static_cast<char*>(buf));
644
645 return size_t(FullReadWrite<0>(
646 std::bind(&FileDescriptor::Read, this, _1, _2), p_buf, nbyte) - p_buf);
647 }
648
649 size_t
650 FileDescriptor::FullWrite(const void* buf, size_t nbyte) ynothrowv
651 {
652 using namespace std::placeholders;
653 const auto p_buf(static_cast<const char*>(buf));
654
655 return size_t(FullReadWrite<ENOSPC>(std::bind(&FileDescriptor::Write, this,
656 _1, _2), p_buf, nbyte) - p_buf);
657 }
658
659 size_t
660 FileDescriptor::Read(void* buf, size_t nbyte) ynothrowv
661 {
662 #if YCL_Win64
663 return SafeReadWrite(::read, desc, buf, unsigned(nbyte));
664 #else
665 return SafeReadWrite(::read, desc, buf, nbyte);
666 #endif
667 }
668
669 size_t
670 FileDescriptor::Write(const void* buf, size_t nbyte) ynothrowv
671 {
672 #if YCL_Win64
673 return SafeReadWrite(::write, desc, buf, unsigned(nbyte));
674 #else
675 return SafeReadWrite(::write, desc, buf, nbyte);
676 #endif
677 }
678
679 void
680 FileDescriptor::WriteContent(FileDescriptor ofd, FileDescriptor ifd,
681 byte* buf, size_t size)
682 {
683 YAssertNonnull(ifd),
684 YAssertNonnull(ofd),
685 YAssertNonnull(buf),
686 YAssert(size != 0, "Invalid size found.");
687
688 ystdex::retry_on_cond([&](size_t len){
689 if(len == size_t(-1))
690 ThrowFileOperationFailure(
691 "Failed reading source file '" + to_string(*ifd) + "'.");
692 if(ofd.FullWrite(buf, len) == size_t(-1))
693 ThrowFileOperationFailure(
694 "Failed writing destination file '" + to_string(*ofd) + "'.");
695 return len != 0;
696 #if YB_IMPL_GNUCPP < 50000 && !defined(NDEBUG)
697 // TODO: Use newer G++ to get away with the workaround.
698 }, [&]{
699 return ifd.Read(buf, size);
700 });
701 #else
702 }, &FileDescriptor::Read, &ifd, buf, size);
703 #endif
704 }
705 void
706 FileDescriptor::WriteContent(FileDescriptor ofd, FileDescriptor ifd,
707 size_t size)
708 {
709 ystdex::temporary_buffer<byte> buf(size);
710
711 WriteContent(ofd, ifd, buf.get().get(), buf.size());
712 }
713
714
715 mode_t
716 DefaultPMode() ynothrow
717 {
718 #if YCL_Win32
719 // XXX: For compatibility with newer version of MSVCRT, no %_umask call
720 // would be considered. See https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx.
721 return mode_t(Mode::UserReadWrite);
722 #else
723 return mode_t(Mode::UserReadWrite | Mode::GroupReadWrite | Mode::OtherRead);
724 #endif
725 }
726
727 void
728 SetBinaryIO(std::FILE* stream) ynothrowv
729 {
730 #if YCL_Win32
731 FileDescriptor(Nonnull(stream)).SetTranslationMode(_O_BINARY);
732 #else
733 // NOTE: No effect.
734 Nonnull(stream);
735 #endif
736 }
737
738
739 int
740 omode_conv(std::ios_base::openmode mode) ynothrow
741 {
742 using namespace std;
743
744 switch(unsigned((mode &= ~ios_base::ate) & ~ios_base::binary))
745 {
746 case ios_base::out:
747 return O_CREAT | O_WRONLY;
748 case ios_base::out | ios_base::trunc:
749 return O_CREAT | O_WRONLY | O_TRUNC;
750 case ios_base::out | ios_base::app:
751 case ios_base::app:
752 return O_CREAT | O_WRONLY | O_APPEND;
753 case ios_base::in:
754 return O_RDONLY;
755 case ios_base::in | ios_base::out:
756 return O_RDWR;
757 case ios_base::in | ios_base::out | ios_base::trunc:
758 return O_CREAT | O_RDWR | O_TRUNC;
759 case ios_base::in | ios_base::out | ios_base::app:
760 case ios_base::in | ios_base::app:
761 return O_CREAT | O_RDWR | O_APPEND;
762 default:
763 return 0;
764 }
765 }
766
767 int
768 omode_convb(std::ios_base::openmode mode) ynothrow
769 {
770 #if YCL_Win32
771 const int res(omode_conv(mode));
772
773 return res | (mode & std::ios_base::binary ? _O_BINARY : _O_TEXT);
774 #else
775 return omode_conv(mode);
776 #endif
777 }
778
779
780 int
781 uaccess(const char* path, int amode) ynothrowv
782 {
783 YAssertNonnull(path);
784 #if YCL_Win32
785 YCL_Impl_RetTryCatchAll(::_waccess(UTF8ToWCS(path).c_str(), amode))
786 return -1;
787 #else
788 return ::access(path, amode);
789 #endif
790 }
791 int
792 uaccess(const char16_t* path, int amode) ynothrowv
793 {
794 YAssertNonnull(path);
795 #if YCL_Win32
796 return ::_waccess(wcast(path), amode);
797 #else
798 YCL_Impl_RetTryCatchAll(::access(MakeMBCS(path).c_str(), amode))
799 return -1;
800 #endif
801 }
802
803 int
804 uopen(const char* filename, int oflag, mode_t pmode) ynothrowv
805 {
806 YAssertNonnull(filename);
807 #if YCL_Win32
808 YCL_Impl_RetTryCatchAll(::_wopen(UTF8ToWCS(filename).c_str(), oflag,
809 int(pmode)))
810 return -1;
811 #else
812 return ::open(filename, oflag, pmode);
813 #endif
814 }
815 int
816 uopen(const char16_t* filename, int oflag, mode_t pmode) ynothrowv
817 {
818 YAssertNonnull(filename);
819 #if YCL_Win32
820 return ::_wopen(wcast(filename), oflag, int(pmode));
821 #else
822 YCL_Impl_RetTryCatchAll(::open(MakeMBCS(filename).c_str(), oflag, pmode))
823 return -1;
824 #endif
825 }
826
827 std::FILE*
828 ufopen(const char* filename, const char* mode) ynothrowv
829 {
830 YAssertNonnull(filename);
831 YAssert(Deref(mode) != char(), "Invalid argument found.");
832 #if YCL_Win32
833 YCL_Impl_RetTryCatchAll(::_wfopen(UTF8ToWCS(filename).c_str(),
834 UTF8ToWCS(mode).c_str()))
835 return {};
836 #else
837 return std::fopen(filename, mode);
838 #endif
839 }
840 std::FILE*
841 ufopen(const char16_t* filename, const char16_t* mode) ynothrowv
842 {
843 YAssertNonnull(filename);
844 YAssert(Deref(mode) != char(), "Invalid argument found.");
845 #if YCL_Win32
846 return ::_wfopen(wcast(filename), wcast(mode));
847 #else
848 YCL_Impl_RetTryCatchAll(std::fopen(MakeMBCS(filename).c_str(),
849 MakeMBCS(mode).c_str()))
850 return {};
851 #endif
852 }
853 std::FILE*
854 ufopen(const char* filename, std::ios_base::openmode mode) ynothrowv
855 {
856 if(const auto c_mode = ystdex::openmode_conv(mode))
857 return ufopen(filename, c_mode);
858 return {};
859 }
860 std::FILE*
861 ufopen(const char16_t* filename, std::ios_base::openmode mode) ynothrowv
862 {
863 YAssertNonnull(filename);
864 if(const auto c_mode = ystdex::openmode_conv(mode))
865 #if YCL_Win32
866 YCL_Impl_RetTryCatchAll(
867 ::_wfopen(wcast(filename), UTF8ToWCS(c_mode).c_str()))
868 #else
869 YCL_Impl_RetTryCatchAll(std::fopen(MakeMBCS(filename).c_str(), c_mode))
870 #endif
871 return {};
872 }
873
874 bool
875 ufexists(const char* filename) ynothrowv
876 {
877 #if YCL_Win32
878 return ystdex::call_value_or(ystdex::compose(std::fclose, ystdex::addrof<>()),
879 ufopen(filename, "rb"), yimpl(1)) == 0;
880 #else
881 return ystdex::fexists(filename);
882 #endif
883 }
884 bool
885 ufexists(const char16_t* filename) ynothrowv
886 {
887 return ystdex::call_value_or(ystdex::compose(std::fclose, ystdex::addrof<>()),
888 ufopen(filename, u"rb"), yimpl(1)) == 0;
889 }
890
891 int
892 upclose(std::FILE* fp) ynothrowv
893 {
894 YAssertNonnull(fp);
895 #if YCL_DS
896 errno = ENOSYS;
897 return -1;
898 #elif YCL_Win32
899 return ::_pclose(fp);
900 #else
901 return ::pclose(fp);
902 #endif
903 }
904
905 std::FILE*
906 upopen(const char* filename, const char* mode) ynothrowv
907 {
908 YAssertNonnull(filename);
909 YAssert(Deref(mode) != char(), "Invalid argument found.");
910 #if YCL_DS
911 errno = ENOSYS;
912 return {};
913 #elif YCL_Win32
914 YCL_Impl_RetTryCatchAll(::_wpopen(UTF8ToWCS(filename).c_str(),
915 UTF8ToWCS(mode).c_str()))
916 return {};
917 #else
918 return ::popen(filename, mode);
919 #endif
920 }
921 std::FILE*
922 upopen(const char16_t* filename, const char16_t* mode) ynothrowv
923 {
924 YAssertNonnull(filename);
925 YAssert(Deref(mode) != char(), "Invalid argument found.");
926 #if YCL_DS
927 errno = ENOSYS;
928 return {};
929 #elif YCL_Win32
930 return ::_wpopen(wcast(filename), wcast(mode));
931 #else
932 YCL_Impl_RetTryCatchAll(::popen(MakeMBCS(filename).c_str(),
933 MakeMBCS(mode).c_str()))
934 return {};
935 #endif
936 }
937
938 char*
939 ugetcwd(char* buf, size_t size) ynothrowv
940 {
941 YAssertNonnull(buf);
942 if(size != 0)
943 {
944 using namespace std;
945
946 #if YCL_Win32
947 try
948 {
949 const auto p(make_unique<wchar_t[]>(size));
950
951 if(const auto cwd = ::_wgetcwd(p.get(), int(size)))
952 {
953 const auto res(WCSToUTF8(cwd));
954 const auto len(res.length());
955
956 if(size < len + 1)
957 errno = ERANGE;
958 else
959 return ystdex::ntctscpy(buf, res.data(), len);
960 }
961 }
962 CatchExpr(std::bad_alloc&, errno = ENOMEM);
963 #else
964 return ucast(::getcwd(wcast(buf), size));
965 #endif
966 }
967 else
968 errno = EINVAL;
969 return {};
970 }
971 char16_t*
972 ugetcwd(char16_t* buf, size_t size) ynothrowv
973 {
974 YAssertNonnull(buf);
975 if(size != 0)
976 {
977 using namespace std;
978
979 #if YCL_Win32
980 return ucast(::_wgetcwd(wcast(buf), int(size)));
981 #else
982 if(const auto cwd
983 = ::getcwd(ystdex::aligned_store_cast<char*>(buf), size))
984 try
985 {
986 const auto res(MakeUCS2LE(cwd));
987 const auto len(res.length());
988
989 if(size < len + 1)
990 errno = ERANGE;
991 else
992 return ystdex::ntctscpy(buf, res.data(), len);
993 }
994 CatchExpr(std::bad_alloc&, errno = ENOMEM)
995 #endif
996 }
997 else
998 errno = EINVAL;
999 return {};
1000 }
1001
1002 #define YCL_Impl_FileSystem_ufunc_1(_n) \
1003 bool \
1004 _n(const char* path) ynothrowv \
1005 { \
1006 YAssertNonnull(path); \
1007
1008 #if YCL_Win32
1009 # define YCL_Impl_FileSystem_ufunc_2(_fn, _wfn) \
1010 YCL_Impl_RetTryCatchAll(_wfn(UTF8ToWCS(path).c_str()) == 0) \
1011 return {}; \
1012 }
1013 #else
1014 # define YCL_Impl_FileSystem_ufunc_2(_fn, _wfn) \
1015 return _fn(path) == 0; \
1016 }
1017 #endif
1018
1019 #define YCL_Impl_FileSystem_ufunc(_n, _fn, _wfn) \
1020 YCL_Impl_FileSystem_ufunc_1(_n) \
1021 YCL_Impl_FileSystem_ufunc_2(_fn, _wfn)
1022
1023 YCL_Impl_FileSystem_ufunc(uchdir, ::chdir, ::_wchdir)
1024
1025 YCL_Impl_FileSystem_ufunc_1(umkdir)
1026 #if YCL_Win32
1027 YCL_Impl_FileSystem_ufunc_2(_unused_, ::_wmkdir)
1028 #else
1029 return ::mkdir(path, mode_t(Mode::Access)) == 0;
1030 }
1031 #endif
1032
1033 YCL_Impl_FileSystem_ufunc(urmdir, ::rmdir, ::_wrmdir)
1034
1035 YCL_Impl_FileSystem_ufunc_1(uunlink)
1036 #if YCL_Win32
1037 YCL_Impl_RetTryCatchAll(CallFuncWithAttr(UnlinkWithAttr, path))
1038 return {};
1039 }
1040 #else
1041 YCL_Impl_FileSystem_ufunc_2(::unlink, )
1042 #endif
1043
1044 YCL_Impl_FileSystem_ufunc_1(uremove)
1045 #if YCL_Win32
1046 YCL_Impl_RetTryCatchAll(CallFuncWithAttr(
1047 [](const wchar_t* wstr, FileAttributes attr) YB_NONNULL(1) ynothrow{
1048 return attr & FileAttributes::Directory ? _wrmdir(wstr) == 0
1049 : UnlinkWithAttr(wstr, attr);
1050 }, path))
1051 return {};
1052 }
1053 #else
1054 YCL_Impl_FileSystem_ufunc_2(std::remove, )
1055 #endif
1056
1057 #undef YCL_Impl_FileSystem_ufunc_1
1058 #undef YCL_Impl_FileSystem_ufunc_2
1059 #undef YCL_Impl_FileSystem_ufunc
1060
1061
1062 ImplDeDtor(FileOperationFailure)
1063
1064
1065 FileTime
1066 GetFileAccessTimeOf(const char* filename, bool follow_link)
1067 {
1068 return FetchFileTime(get_st_atime, filename, follow_link);
1069 }
1070 FileTime
1071 GetFileAccessTimeOf(const char16_t* filename, bool follow_link)
1072 {
1073 return FetchFileTime(get_st_atime, wcast(filename), follow_link);
1074 }
1075
1076 FileTime
1077 GetFileModificationTimeOf(const char* filename, bool follow_link)
1078 {
1079 return FetchFileTime(get_st_mtime, filename, follow_link);
1080 }
1081 FileTime
1082 GetFileModificationTimeOf(const char16_t* filename, bool follow_link)
1083 {
1084 return FetchFileTime(get_st_mtime, wcast(filename), follow_link);
1085 }
1086
1087 array<FileTime, 2>
1088 GetFileModificationAndAccessTimeOf(const char* filename, bool follow_link)
1089 {
1090 return FetchFileTime(get_st_matime, filename, follow_link);
1091 }
1092 array<FileTime, 2>
1093 GetFileModificationAndAccessTimeOf(const char16_t* filename, bool follow_link)
1094 {
1095 return FetchFileTime(get_st_matime, wcast(filename), follow_link);
1096 }
1097
1098 YB_NONNULL(1) size_t
1099 FetchNumberOfLinks(const char* path, bool follow_link) ynothrowv
1100 {
1101 #if YCL_Win32
1102 return QueryFileLinks(UTF8ToWCS(path).c_str(), follow_link);
1103 #else
1104 struct ::stat st;
1105
1106 estat(st, path, follow_link);
1107 return size_t(st.st_nlink > 0 ? st.st_nlink : 0);
1108 #endif
1109 }
1110 YB_NONNULL(1) size_t
1111 FetchNumberOfLinks(const char16_t* path, bool follow_link) ynothrowv
1112 {
1113 #if YCL_Win32
1114 return QueryFileLinks(wcast(path), follow_link);
1115 #else
1116 return FetchNumberOfLinks(MakeMBCS(path).c_str(), follow_link);
1117 #endif
1118 }
1119
1120
1121 UniqueFile
1122 EnsureUniqueFile(const char* dst, mode_t mode, size_t allowed_links,
1123 bool share)
1124 {
1125 static yconstexpr const int de_oflag
1126 #if YCL_Win32
1127 (_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY);
1128 #else
1129 (O_WRONLY | O_CREAT | O_TRUNC);
1130 #endif
1131
1132 mode &= mode_t(Mode::User);
1133 if(UniqueFile p_file{uopen(dst,
1134 #if YCL_Win32
1135 de_oflag | _O_EXCL
1136 #else
1137 de_oflag | O_EXCL
1138 #endif
1139 , mode)})
1140 return p_file;
1141 if(allowed_links != 0 && errno == EEXIST)
1142 {
1143 const auto n_links(FetchNumberOfLinks(dst));
1144
1145 // FIXME: Blocked. TOCTTOU access.
1146 if(!(allowed_links < n_links)
1147 && (n_links == 1 || share || uunlink(dst) || errno == ENOENT))
1148 if(UniqueFile p_file{uopen(dst, de_oflag, mode)})
1149 return p_file;
1150 }
1151 ThrowFileOperationFailure("Failed creating file '" + string(dst) + "'.");
1152 }
1153
1154 bool
1155 HaveSameContents(const char* path_a, const char* path_b, mode_t mode)
1156 {
1157 if(UniqueFile p_a{uopen(path_a,
1158 #if YCL_Win32
1159 _O_RDONLY | _O_BINARY
1160 #else
1161 O_RDONLY
1162 #endif
1163 , mode)})
1164 if(UniqueFile p_b{uopen(path_b,
1165 #if YCL_Win32
1166 _O_RDONLY | _O_BINARY
1167 #else
1168 O_RDONLY
1169 #endif
1170 , mode)})
1171 return HaveSameContents(std::move(p_a), std::move(p_b), path_a,
1172 path_b);
1173 return {};
1174 }
1175 bool
1176 HaveSameContents(UniqueFile p_a, UniqueFile p_b, const char* name_a,
1177 const char* name_b)
1178 {
1179 if(Nonnull(p_a)->GetCategory() != NodeCategory::Directory
1180 && Nonnull(p_b)->GetCategory() != NodeCategory::Directory)
1181 {
1182 if(IsNodeShared(p_a.get(), p_b.get()))
1183 return true;
1184
1185 filebuf fb_a, fb_b;
1186
1187 errno = 0;
1188 // FIXME: Implement for streams without open-by-raw-file extension.
1189 // TODO: Throw a nested error with errno if errno != 0.
1190 if(!fb_a.open(std::move(p_a),
1191 std::ios_base::in | std::ios_base::binary))
1192 ThrowFileOperationFailure(name_a ? ("Failed opening first file '"
1193 + string(name_a) + "'.").c_str()
1194 : "Failed opening first file.");
1195 // TODO: Throw a nested error with errno if errno != 0.
1196 if(!fb_b.open(std::move(p_b),
1197 std::ios_base::in | std::ios_base::binary))
1198 ThrowFileOperationFailure(name_b ? ("Failed opening second file '"
1199 + string(name_b) + "'.").c_str()
1200 : "Failed opening second file.");
1201 return ystdex::streambuf_equal(fb_a, fb_b);
1202 }
1203 return {};
1204 }
1205
1206 bool
1207 IsNodeShared(const char* a, const char* b, bool follow_link) ynothrowv
1208 {
1209 return a == b || ystdex::ntctscmp(Nonnull(a), Nonnull(b)) == 0
1210 || IsNodeShared_Impl(a, b, follow_link);
1211 }
1212 bool
1213 IsNodeShared(const char16_t* a, const char16_t* b, bool follow_link) ynothrowv
1214 {
1215 return a == b || ystdex::ntctscmp(Nonnull(a), Nonnull(b)) == 0
1216 || IsNodeShared_Impl(a, b, follow_link);
1217 }
1218 bool
1219 IsNodeShared(FileDescriptor x, FileDescriptor y) ynothrow
1220 {
1221 const auto id(x.GetNodeID());
1222
1223 return id != FileNodeID() && id == y.GetNodeID();
1224 }
1225
1226 } // namespace platform;
1227
platform::DefaultPMode
YF_API YB_STATELESS mode_t DefaultPMode() ynothrow
取默认权限。
Definition: FileIO.cpp:716
platform::SetBinaryIO
YF_API void SetBinaryIO(std::FILE *) ynothrowv
设置标准库流二进制输入/输出模式。
Definition: FileIO.cpp:728
YSLib::Drawing::x
The boundary is out of the const Rect SDst SPos x
Definition: YDraw.h:127
CHRLib::YB_NONNULL
YB_NONNULL(1) PDefH(ConversionResult
转换指定编码的多字节字符串为指定类型的 UCS-2 字符串。
platform_ex::Windows::SetFileTime
YF_API void SetFileTime(UniqueHandle::pointer,::FILETIME *={},::FILETIME *={},::FILETIME *={})
设置文件的创建、访问和/或修改时间。
platform::mode_t
::mode_t mode_t
文件模式类型。
Definition: FileIO.h:108
ystdex::to_string
std::string to_string(const std::thread::id &)
转换 thread::id 为字符串表示。
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:653
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:740
platform::containers::string
basic_string< char > string
Definition: Container.h:101
platform::Nonnull
_type && Nonnull(_type &&p) ynothrow
断言并返回非空指针。
Definition: Debug.h:411
platform::ugetcwd
char16_t * ugetcwd(char16_t *buf, size_t size) ynothrowv
Definition: FileIO.cpp:972
YSLib::Text::buf
const char * buf
Definition: TextFile.h:77
ImplDeDtor
#define ImplDeDtor(_t)
Definition: YBaseMacro.h:182
CHRLib::MakeUCS2LE
_tDst MakeUCS2LE(basic_string_view< char > sv, _tParams &&...args)
Definition: CharacterProcessing.h:538
platform::KeyCategory::Character
表示产生字符的键。
Definition: Keys.h:111
ystdex::streambuf_equal
bool streambuf_equal(std::basic_streambuf< _tChar, _tTraits > &a, std::basic_streambuf< _tChar, _tTraits > &b)
比较指定流缓冲区的内容相等。
Definition: streambuf.hpp:45
platform_ex::Windows::QueryFileTime
YF_API void QueryFileTime(UniqueHandle::pointer,::FILETIME *={},::FILETIME *={},::FILETIME *={})
查询文件的创建、访问和/或修改时间。
YSLib::IO::FileDescriptor
YF_API const char *YF_API FileDescriptor
Definition: YSLib/Service/FileSystem.h:575
ystdex::ntctscpy
enable_if_irreplaceable_char_t< _tChar, _tChar * > ntctscpy(_tChar *s1, const _tChar *s2)
复制 NTCTS 。
Definition: cstring.h:250
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
ystdex::write
std::basic_ostream< _tChar, typename _tString::traits_type > & write(std::basic_ostream< _tChar, typename _tString::traits_type > &os, const _tString &str, typename _tString::size_type pos=0, typename _tString::size_type n=_tString::npos)
非格式输出。
Definition: string.hpp:921
platform::NodeCategory
NodeCategory
文件节点类别。
Definition: FileIO.h:117
platform::CategorizeNode
NodeCategory CategorizeNode(mode_t st_mode) ynothrow
Definition: FileIO.cpp:376
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:760
platform::GetFileAccessTimeOf
FileTime GetFileAccessTimeOf(const char16_t *filename, bool follow_link)
Definition: FileIO.cpp:1071
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YAssert
#define YAssert(_expr, _msg)
Definition: cassert.h:105
platform::upopen
std::FILE * upopen(const char16_t *filename, const char16_t *mode) ynothrowv
Definition: FileIO.cpp:922
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:942
platform_ex::Windows::Directory
Definition: MinGW32.h:442
CHRLib::size_t
return size_t(d-p)
platform::uchdir
bool uchdir(const char *path) ynothrowv
Definition: FileIO.cpp:1023
platform::IsNodeShared
bool IsNodeShared(const char16_t *a, const char16_t *b, bool follow_link) ynothrowv
Definition: FileIO.cpp:1213
platform_ex::Windows::Invalid
Definition: MinGW32.h:461
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:256
CHRLib::char16_t
char16_t((*c_ptr<< CHAR_BIT)|c_ptr[1])) inline PDefH(char16_t
取 c_ptr 指向的小端序双字节字符。
ystdex::ntctscmp
int ntctscmp(const _tChar *s1, const _tChar *s2)
按字典序比较简单 NTCTS 。
Definition: cstring.h:154
ystdex::fexists
bool fexists(const char *)
判断指定路径的文件是否存在。
Definition: cstdio.cpp:59
CHRLib::p
const auto p(d)
platform::UniqueFile
unique_ptr_from< FileDescriptor::Deleter > UniqueFile
Definition: FileIO.h:427
platform_ex::Windows::QueryFileNodeID
YF_API pair< VolumeID, FileID > QueryFileNodeID(UniqueHandle::pointer)
查询文件标识。
platform::upclose
int upclose(std::FILE *fp) ynothrowv
Definition: FileIO.cpp:892
YCL_Impl_FileSystem_ufunc
#define YCL_Impl_FileSystem_ufunc(_n, _fn, _wfn)
Definition: FileIO.cpp:1019
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:438
YCL_Impl_RetTryCatchAll
#define YCL_Impl_RetTryCatchAll(...)
Definition: FileIO.cpp:94
platform::GetFileModificationTimeOf
FileTime GetFileModificationTimeOf(const char16_t *filename, bool follow_link)
Definition: FileIO.cpp:1082
NPL::dst
YF_API const char src const string const char * dst
Definition: Dependency.h:93
ystdex::throw_error
void throw_error(std::error_code ec, _tParams &&...args)
抛出错误： std::system_error 或允许相同构造函数参数的异常。
Definition: ystdex/exception.h:162
FileAttributes
FileAttributes
文件共享模式。
Definition: MinGW32.h:437
functional.hpp
函数和可调用对象。
platform::umkdir
bool umkdir(const char *path) ynothrowv
Definition: FileIO.cpp:1025
platform
默认平台命名空间。
Definition: Container.h:47
platform::ufexists
bool ufexists(const char16_t *filename) ynothrowv
Definition: FileIO.cpp:885
platform_ex::Windows::ConvertTime
YF_API std::chrono::nanoseconds ConvertTime(const ::FILETIME &)
转换文件时间为以 POSIX 历元起始度量的时间间隔。
std
Definition: memory.hpp:1100
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:440
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:114
platform::ufopen
std::FILE * ufopen(const char16_t *filename, std::ios_base::openmode mode) ynothrowv
Definition: FileIO.cpp:861
platform::HaveSameContents
bool HaveSameContents(UniqueFile p_a, UniqueFile p_b, const char *name_a, const char *name_b)
Definition: FileIO.cpp:1176
ystdex::cpp2014::make_unique
enable_if_t<!is_array< _type >::value, std::unique_ptr< _type > > make_unique(_tParams &&...args)
使用 new 和指定参数构造指定类型的 std::unique_ptr 对象。
Definition: memory.hpp:729
CHRLib::PDefH
PDefH(char16_t, FetchBiCharBE, const char *c_ptr) ImplRet(yconstraint(c_ptr)
取 c_ptr 指向的大端序双字节字符。
platform::KeyCodes::Win32::Empty
Definition: Keys.h:279
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
platform::uunlink
bool uunlink(const char *path) ynothrowv
Definition: FileIO.cpp:1035
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:996
YSLib::path
YF_API const char * path
Definition: Initialization.h:74
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
platform::uremove
bool uremove(const char *path) ynothrowv
Definition: FileIO.cpp:1044
YModules.h
CHRLib::f
f(d, s)
YModules.h
YSLib::IO::int
YF_API int
Definition: File.h:49
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
platform::pmode
YF_API int mode_t pmode
Definition: FileIO.h:504
CHRLib
Definition: CharacterDefinition.h:38
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:808
ystdex::temporary_buffer
临时缓冲区。
Definition: memory.hpp:401
ystdex::openmode_conv
const char * openmode_conv(std::ios_base::openmode)
ISO C/C++ 标准输入输出接口打开模式转换。
Definition: cstdio.cpp:68
platform::MakePathString
string MakePathString(const char16_t *s)
Definition: FileIO.cpp:365
ystdex::call_value_or
auto call_value_or(_func f, _type p, _tOther &&other={}) -> decltype(p?f(*p):other)
调用非空值或取默认值。
Definition: deref_op.hpp:100
YB_LIKELY
#define YB_LIKELY(_expr)
Definition: ydef.h:437
platform::omode_convb
std::ios_base::sync_with_stdio(sync)) YF_API YB_STATELESS int omode_conv(std YF_API YB_STATELESS int omode_convb(std::ios_base::openmode) ynothrow
ISO C++ 标准输入输出接口打开模式转换为 POSIX 文件打开模式。
Definition: FileIO.cpp:768
YSLib::a
YB_PURE const _type * a
Definition: YCoreUtilities.h:167
platform::urmdir
bool urmdir(const char *path) ynothrowv
Definition: FileIO.cpp:1033
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
ystdex::addrof
一元 & 操作。
Definition: functor.hpp:416
YCL_Impl_FileSystem_ufunc_1
#define YCL_Impl_FileSystem_ufunc_1(_n)
Definition: FileIO.cpp:1002
platform_ex::Windows::QueryFileLinks
YF_API size_t QueryFileLinks(UniqueHandle::pointer)
查询文件链接数。
CHRLib::MakeMBCS
_tDst MakeMBCS(string_view sv, Encoding enc)
Definition: CharacterProcessing.h:603
platform::estat
estat(st, path, follow_link)
ystdex::compose
auto compose(_func1 f, _func2 g, _funcs...args) -> decltype(ystdex::compose(ystdex::compose(f, g), args...))
Definition: functional.hpp:646
platform_ex::Windows::WCSToUTF8
const char *str string_view sv WCSToUTF8
Definition: MinGW32.h:657
streambuf.hpp
ISO C++ 标准库标准流缓冲扩展。
ystdex::retry_on_cond
result_of_t< _fCallable &&(_tParams &&...)> retry_on_cond(_fCond cond, _fCallable &&f, _tParams &&...args)
循环重复调用：代替直接使用 do-while 语句以避免过多引入作用域外的变量。
Definition: functional.hpp:1019
CHRLib::args
_tParams && args
Definition: CharacterProcessing.h:538
platform::uopen
int uopen(const char16_t *filename, int oflag, mode_t pmode) ynothrowv
Definition: FileIO.cpp:816
platform::uaccess
int uaccess(const char16_t *path, int amode) ynothrowv
Definition: FileIO.cpp:792
platform::follow_link
bool follow_link
Definition: FileIO.cpp:1067
platform::GetFileModificationAndAccessTimeOf
GetFileModificationAndAccessTimeOf
Definition: FileIO.h:1221
ystdex::cpp2014::result_of_t
typename result_of< _type >::type result_of_t
Definition: type_traits.hpp:362
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
platform::oflag
YF_API int oflag
Definition: FileIO.h:504
platform_ex::Windows::UTF8ToWCS
UTF8ToWCS
Definition: MinGW32.h:650
CHRLib::fp
std::FILE ConversionState fp
Definition: CharacterProcessing.h:92
platform::EnsureUniqueFile
UniqueFile EnsureUniqueFile(const char *dst, mode_t mode, size_t allowed_links, bool share)
Definition: FileIO.cpp:1122
YCL_Impl_FileSystem_ufunc_2
#define YCL_Impl_FileSystem_ufunc_2(_fn, _wfn)
Definition: FileIO.cpp:1014
CHRLib::ImplRet
const char *c_ptr ImplRet(yconstraint(c_ptr), char16_t((c_ptr[1]<< CHAR_BIT)|*c_ptr)) enum class ConversionResult
编码转换结果。
Definition: CharacterMapping.h:84
platform::omode_conv
int omode_conv(std::ios_base::openmode mode) ynothrow
Definition: FileIO.cpp:740
platform::FileDescriptor
文件描述符包装类。
Definition: FileIO.h:171
platform_ex::Windows::ReadOnly
Definition: MinGW32.h:439
platform::n
size_t n
Definition: YCLib/FileSystem.cpp:321
CatchThrow
#define CatchThrow(_ex,...)
指定抛出指定异常作为异常处理器。
Definition: YBaseMacro.h:141