OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <fnmatch.h> | 10 #include <fnmatch.h> |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "base/eintr_wrapper.h" | 28 #include "base/eintr_wrapper.h" |
29 #include "base/file_path.h" | 29 #include "base/file_path.h" |
30 #include "base/lock.h" | 30 #include "base/lock.h" |
31 #include "base/logging.h" | 31 #include "base/logging.h" |
32 #include "base/scoped_ptr.h" | 32 #include "base/scoped_ptr.h" |
33 #include "base/singleton.h" | 33 #include "base/singleton.h" |
34 #include "base/string_util.h" | 34 #include "base/string_util.h" |
35 #include "base/sys_string_conversions.h" | 35 #include "base/sys_string_conversions.h" |
36 #include "base/time.h" | 36 #include "base/time.h" |
37 #include "base/utf_string_conversions.h" | 37 #include "base/utf_string_conversions.h" |
38 #include "unicode/coll.h" | |
39 | |
40 | |
41 namespace { | |
42 | |
43 class LocaleAwareComparator { | |
44 public: | |
45 LocaleAwareComparator() { | |
46 UErrorCode error_code = U_ZERO_ERROR; | |
47 // Use the default collator. The default locale should have been properly | |
48 // set by the time this constructor is called. | |
49 collator_.reset(icu::Collator::createInstance(error_code)); | |
50 DCHECK(U_SUCCESS(error_code)); | |
51 // Make it case-sensitive. | |
52 collator_->setStrength(icu::Collator::TERTIARY); | |
53 // Note: We do not set UCOL_NORMALIZATION_MODE attribute. In other words, we | |
54 // do not pay performance penalty to guarantee sort order correctness for | |
55 // non-FCD (http://unicode.org/notes/tn5/#FCD) file names. This should be a | |
56 // reasonable tradeoff because such file names should be rare and the sort | |
57 // order doesn't change much anyway. | |
58 } | |
59 | |
60 // Note: A similar function is available in l10n_util. | |
61 // We cannot use it because base should not depend on l10n_util. | |
62 // TODO(yuzo): Move some of l10n_util to base. | |
63 int Compare(const string16& a, const string16& b) { | |
64 // We are not sure if Collator::compare is thread-safe. | |
65 // Use an AutoLock just in case. | |
66 AutoLock auto_lock(lock_); | |
67 | |
68 UErrorCode error_code = U_ZERO_ERROR; | |
69 UCollationResult result = collator_->compare( | |
70 static_cast<const UChar*>(a.c_str()), | |
71 static_cast<int>(a.length()), | |
72 static_cast<const UChar*>(b.c_str()), | |
73 static_cast<int>(b.length()), | |
74 error_code); | |
75 DCHECK(U_SUCCESS(error_code)); | |
76 return result; | |
77 } | |
78 | |
79 private: | |
80 scoped_ptr<icu::Collator> collator_; | |
81 Lock lock_; | |
82 friend struct DefaultSingletonTraits<LocaleAwareComparator>; | |
83 | |
84 DISALLOW_COPY_AND_ASSIGN(LocaleAwareComparator); | |
85 }; | |
86 | |
87 } // namespace | |
88 | 38 |
89 namespace file_util { | 39 namespace file_util { |
90 | 40 |
91 #if defined(OS_FREEBSD) || \ | 41 #if defined(OS_FREEBSD) || \ |
92 (defined(OS_MACOSX) && \ | 42 (defined(OS_MACOSX) && \ |
93 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) | 43 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) |
94 typedef struct stat stat_wrapper_t; | 44 typedef struct stat stat_wrapper_t; |
95 static int CallStat(const char *path, stat_wrapper_t *sb) { | 45 static int CallStat(const char *path, stat_wrapper_t *sb) { |
96 return stat(path, sb); | 46 return stat(path, sb); |
97 } | 47 } |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 return FilePath(); | 566 return FilePath(); |
617 | 567 |
618 root_path_ = pending_paths_.top(); | 568 root_path_ = pending_paths_.top(); |
619 root_path_ = root_path_.StripTrailingSeparators(); | 569 root_path_ = root_path_.StripTrailingSeparators(); |
620 pending_paths_.pop(); | 570 pending_paths_.pop(); |
621 | 571 |
622 std::vector<DirectoryEntryInfo> entries; | 572 std::vector<DirectoryEntryInfo> entries; |
623 if (!ReadDirectory(&entries, root_path_, file_type_ & SHOW_SYM_LINKS)) | 573 if (!ReadDirectory(&entries, root_path_, file_type_ & SHOW_SYM_LINKS)) |
624 continue; | 574 continue; |
625 | 575 |
626 // The API says that order is not guaranteed, but order affects UX | |
627 std::sort(entries.begin(), entries.end(), CompareFiles); | |
628 | |
629 directory_entries_.clear(); | 576 directory_entries_.clear(); |
630 current_directory_entry_ = 0; | 577 current_directory_entry_ = 0; |
631 for (std::vector<DirectoryEntryInfo>::const_iterator | 578 for (std::vector<DirectoryEntryInfo>::const_iterator |
632 i = entries.begin(); i != entries.end(); ++i) { | 579 i = entries.begin(); i != entries.end(); ++i) { |
633 FilePath full_path = root_path_.Append(i->filename); | 580 FilePath full_path = root_path_.Append(i->filename); |
634 if (ShouldSkip(full_path)) | 581 if (ShouldSkip(full_path)) |
635 continue; | 582 continue; |
636 | 583 |
637 if (pattern_.value().size() && | 584 if (pattern_.value().size() && |
638 fnmatch(pattern_.value().c_str(), full_path.value().c_str(), | 585 fnmatch(pattern_.value().c_str(), full_path.value().c_str(), |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 } | 631 } |
685 memset(&info.stat, 0, sizeof(info.stat)); | 632 memset(&info.stat, 0, sizeof(info.stat)); |
686 } | 633 } |
687 entries->push_back(info); | 634 entries->push_back(info); |
688 } | 635 } |
689 | 636 |
690 closedir(dir); | 637 closedir(dir); |
691 return true; | 638 return true; |
692 } | 639 } |
693 | 640 |
694 bool FileEnumerator::CompareFiles(const DirectoryEntryInfo& a, | |
695 const DirectoryEntryInfo& b) { | |
696 // Order lexicographically with directories before other files. | |
697 if (S_ISDIR(a.stat.st_mode) != S_ISDIR(b.stat.st_mode)) | |
698 return S_ISDIR(a.stat.st_mode); | |
699 | |
700 // On linux, the file system encoding is not defined. We assume | |
701 // SysNativeMBToWide takes care of it. | |
702 // | |
703 // ICU's collator can take strings in OS native encoding. But we convert the | |
704 // strings to UTF-16 ourselves to ensure conversion consistency. | |
705 // TODO(yuzo): Perhaps we should define SysNativeMBToUTF16? | |
706 return Singleton<LocaleAwareComparator>()->Compare( | |
707 WideToUTF16(base::SysNativeMBToWide(a.filename.value().c_str())), | |
708 WideToUTF16(base::SysNativeMBToWide(b.filename.value().c_str()))) < 0; | |
709 } | |
710 | |
711 /////////////////////////////////////////////// | 641 /////////////////////////////////////////////// |
712 // MemoryMappedFile | 642 // MemoryMappedFile |
713 | 643 |
714 MemoryMappedFile::MemoryMappedFile() | 644 MemoryMappedFile::MemoryMappedFile() |
715 : file_(-1), | 645 : file_(-1), |
716 data_(NULL), | 646 data_(NULL), |
717 length_(0) { | 647 length_(0) { |
718 } | 648 } |
719 | 649 |
720 bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) { | 650 bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) { |
(...skipping 24 matching lines...) Expand all Loading... |
745 munmap(data_, length_); | 675 munmap(data_, length_); |
746 if (file_ != -1) | 676 if (file_ != -1) |
747 close(file_); | 677 close(file_); |
748 | 678 |
749 data_ = NULL; | 679 data_ = NULL; |
750 length_ = 0; | 680 length_ = 0; |
751 file_ = -1; | 681 file_ = -1; |
752 } | 682 } |
753 | 683 |
754 } // namespace file_util | 684 } // namespace file_util |
OLD | NEW |