|
14 | 14 | #include <string> |
15 | 15 | #include <vector> |
16 | 16 | #include <stdexcept> |
| 17 | +#include <memory> |
17 | 18 | #include <sstream> |
18 | 19 | #include <cctype> |
19 | 20 | #include <cstdlib> |
|
25 | 26 | # include <ShlObj.h> |
26 | 27 | #else |
27 | 28 | # include <unistd.h> |
| 29 | +# include <dirent.h> |
| 30 | +# include <sys/types.h> |
28 | 31 | #endif |
29 | 32 | #include <sys/stat.h> |
30 | 33 |
|
@@ -407,6 +410,107 @@ class path { |
407 | 410 | bool m_smb; // Unused, except for on Windows |
408 | 411 | }; |
409 | 412 |
|
| 413 | +class directory_entry { |
| 414 | +public: |
| 415 | + directory_entry() = default; |
| 416 | + explicit directory_entry(const path& p) : p(p) {} |
| 417 | + filesystem::path path() const { |
| 418 | + return p; |
| 419 | + } |
| 420 | + |
| 421 | +private: |
| 422 | + filesystem::path p; |
| 423 | +}; |
| 424 | + |
| 425 | +class directory_iterator { |
| 426 | +public: |
| 427 | + directory_iterator() = default; |
| 428 | + directory_iterator(const path& p) : p(p) {} |
| 429 | + directory_iterator(const directory_iterator& rhs) = default; |
| 430 | + directory_iterator(directory_iterator&& rhs) = default; |
| 431 | + ~directory_iterator() = default; |
| 432 | + |
| 433 | + directory_iterator begin() { |
| 434 | +#if defined(_WIN32) |
| 435 | + hFind = FindFirstFile((p / path("*")).str().c_str(), &findData); |
| 436 | +#else |
| 437 | + dir = std::shared_ptr<DIR>(opendir(p.str().c_str()), closedir); |
| 438 | +#endif |
| 439 | + return increment(); |
| 440 | + } |
| 441 | + |
| 442 | + directory_iterator end() const { |
| 443 | + return directory_iterator(); |
| 444 | + } |
| 445 | + |
| 446 | + bool operator==(const directory_iterator& rhs) const { |
| 447 | + return entry.path() == rhs.entry.path(); |
| 448 | + } |
| 449 | + |
| 450 | + bool operator!=(const directory_iterator& rhs) const { |
| 451 | + return entry.path() != rhs.entry.path(); |
| 452 | + } |
| 453 | + |
| 454 | + directory_entry operator*() const { |
| 455 | + return entry; |
| 456 | + } |
| 457 | + |
| 458 | + directory_entry* operator->() { |
| 459 | + return &entry; |
| 460 | + } |
| 461 | + |
| 462 | + directory_iterator& increment() { |
| 463 | +#if defined(_WIN32) |
| 464 | + if (hFind != NULL && hFind != INVALID_HANDLE_VALUE) { |
| 465 | + do { |
| 466 | + if (findData.cFileName[0] != '.') break; |
| 467 | + } while (FindNextFile(hFind, &findData)); |
| 468 | + } |
| 469 | + |
| 470 | + if (hFind != NULL && hFind != INVALID_HANDLE_VALUE) { |
| 471 | + entry = directory_entry(p / path(findData.cFileName)); |
| 472 | + if (!FindNextFile(hFind, &findData)) { |
| 473 | + FindClose(hFind); |
| 474 | + hFind = NULL; |
| 475 | + } |
| 476 | + } else { |
| 477 | + entry = directory_entry(); |
| 478 | + } |
| 479 | +#else |
| 480 | + dirent *ent = NULL; |
| 481 | + while ((ent = readdir(dir.get())) != NULL) { |
| 482 | + if (ent->d_name[0] != '.') break; |
| 483 | + } |
| 484 | + |
| 485 | + if (ent) |
| 486 | + entry = directory_entry(p / path(ent->d_name)); |
| 487 | + else |
| 488 | + entry = directory_entry(); |
| 489 | +#endif |
| 490 | + return *this; |
| 491 | + } |
| 492 | + |
| 493 | + directory_iterator& operator++() { |
| 494 | + return increment(); |
| 495 | + } |
| 496 | + |
| 497 | + directory_iterator operator++(int) { |
| 498 | + directory_iterator prev = *this; |
| 499 | + increment(); |
| 500 | + return prev; |
| 501 | + } |
| 502 | + |
| 503 | +private: |
| 504 | + path p; |
| 505 | + directory_entry entry; |
| 506 | +#if defined(_WIN32) |
| 507 | + HANDLE hFind = NULL; |
| 508 | + WIN32_FIND_DATA findData; |
| 509 | +#else |
| 510 | + std::shared_ptr<DIR> dir = nullptr; |
| 511 | +#endif |
| 512 | +}; |
| 513 | + |
410 | 514 | inline bool create_directory(const path& p) { |
411 | 515 | #if defined(_WIN32) |
412 | 516 | return CreateDirectoryW(p.wstr().c_str(), NULL) != 0; |
|
0 commit comments