diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-12 20:12:38 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-12 20:12:38 +0000 |
commit | 45cbfb0444d2ae27d9dbc9880c547c0d42978782 (patch) | |
tree | 3f5a3477831c68b73f87365c8222b3033758358a | |
parent | f33651e32ab77d1413e01f5fed1e90f5b36f7534 (diff) | |
download | chromium_src-45cbfb0444d2ae27d9dbc9880c547c0d42978782.zip chromium_src-45cbfb0444d2ae27d9dbc9880c547c0d42978782.tar.gz chromium_src-45cbfb0444d2ae27d9dbc9880c547c0d42978782.tar.bz2 |
Add a MemoryMappedFile class to file_util.
Factor out windowisms from the spell checker.
Review URL: http://codereview.chromium.org/14041
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6919 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/file_util.h | 39 | ||||
-rw-r--r-- | base/file_util_win.cc | 66 | ||||
-rw-r--r-- | chrome/browser/spellchecker.cc | 56 | ||||
-rw-r--r-- | chrome/browser/spellchecker.h | 12 |
4 files changed, 115 insertions, 58 deletions
diff --git a/base/file_util.h b/base/file_util.h index 7bc7e820..854703f 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -305,7 +305,6 @@ bool GetFileInfo(const FilePath& file_path, FileInfo* info); // Deprecated temporary compatibility function. bool GetFileInfo(const std::wstring& file_path, FileInfo* info); - // Wrapper for fopen-like calls. Returns non-NULL FILE* on success. FILE* OpenFile(const FilePath& filename, const char* mode); // Deprecated temporary compatibility functions. @@ -415,6 +414,44 @@ class FileEnumerator { DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator); }; +// TODO(port): port this class to posix. +#if defined(OS_WIN) +class MemoryMappedFile { + public: + // The default constructor sets all members to invalid/null values. + MemoryMappedFile(); + ~MemoryMappedFile(); + + // Opens an existing file and maps it into memory. Access is restricted to + // read only. If this object already points to a valid memory mapped file + // then this method will fail and return false. If it cannot open the file, + // the file does not exist, or the memory mapping fails, it will return false. + // Later we may want to allow the user to specify access. + bool Initialize(const FilePath& file_name); + + const uint8* Data() const { return data_; } + size_t Length() const { return length_; } + + // Is file_ a valid file handle that points to an open, memory mapped file? + bool IsValid(); + + private: + // Map the file to memory, set data_ to that memory address. Return true on + // success, false on any kind of failure. This is a helper for Initialize(). + bool MapFileToMemory(const FilePath& file_name); + + // Closes all open handles. Later we may want to make this public. + void CloseHandles(); + + HANDLE file_; + HANDLE file_mapping_; + const uint8* data_; + size_t length_; + + DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile); +}; +#endif // defined(OS_WIN) + // Renames a file using the SHFileOperation API to ensure that the target file // gets the correct default security descriptor in the new path. bool RenameFileAndResetSecurityDescriptor( diff --git a/base/file_util_win.cc b/base/file_util_win.cc index db22fa3..c287129 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -595,7 +595,7 @@ bool SetCurrentDirectory(const FilePath& directory) { } /////////////////////////////////////////////// - +// FileEnumerator FileEnumerator::FileEnumerator(const FilePath& root_path, bool recursive, @@ -694,6 +694,70 @@ FilePath FileEnumerator::Next() { return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); } +/////////////////////////////////////////////// +// MemoryMappedFile + +MemoryMappedFile::MemoryMappedFile() + : file_(INVALID_HANDLE_VALUE), + file_mapping_(INVALID_HANDLE_VALUE), + data_(NULL), + length_(INVALID_FILE_SIZE) { +} + +MemoryMappedFile::~MemoryMappedFile() { + CloseHandles(); +} + +bool MemoryMappedFile::Initialize(const FilePath& file_name) { + if (IsValid()) + return false; + + if (!MapFileToMemory(file_name)) { + CloseHandles(); + return false; + } + + return true; +} + +bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) { + file_ = ::CreateFile(file_name.value().c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (file_ == INVALID_HANDLE_VALUE) + return false; + + length_ = ::GetFileSize(file_, NULL); + if (length_ == INVALID_FILE_SIZE) + return false; + + file_mapping_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY, + 0, length_, NULL); + if (file_mapping_ == INVALID_HANDLE_VALUE) + return false; + + data_ = reinterpret_cast<const uint8*>( + ::MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, length_)); + return data_ != NULL; +} + +bool MemoryMappedFile::IsValid() { + return data_ != NULL; +} + +void MemoryMappedFile::CloseHandles() { + if (data_) + ::UnmapViewOfFile(data_); + if (file_mapping_ != INVALID_HANDLE_VALUE) + ::CloseHandle(file_mapping_); + if (file_ != INVALID_HANDLE_VALUE) + ::CloseHandle(file_); + + data_ = NULL; + file_mapping_ = file_ = INVALID_HANDLE_VALUE; + length_ = INVALID_FILE_SIZE; +} + // Deprecated functions ---------------------------------------------------- void InsertBeforeExtension(std::wstring* path_str, diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc index 2598ad3..004c39b 100644 --- a/chrome/browser/spellchecker.cc +++ b/chrome/browser/spellchecker.cc @@ -346,10 +346,6 @@ SpellChecker::SpellChecker(const std::wstring& dict_dir, URLRequestContext* request_context, const std::wstring& custom_dictionary_file_name) : custom_dictionary_file_name_(custom_dictionary_file_name), - bdict_file_(NULL), - bdict_mapping_(NULL), - bdict_mapped_data_(NULL), - hunspell_(NULL), tried_to_init_(false), #ifndef NDEBUG worker_loop_(NULL), @@ -393,15 +389,6 @@ SpellChecker::~SpellChecker() { if (worker_loop_) DCHECK(MessageLoop::current() == worker_loop_); #endif - - delete hunspell_; - - if (bdict_mapped_data_) - UnmapViewOfFile(bdict_mapped_data_); - if (bdict_mapping_) - CloseHandle(bdict_mapping_); - if (bdict_file_) - CloseHandle(bdict_file_); } // Initialize SpellChecker. In this method, if the dicitonary is not present @@ -417,7 +404,7 @@ bool SpellChecker::Initialize() { // Return false if tried to init and failed - don't try multiple times in // this session. if (tried_to_init_) - return hunspell_ != NULL; + return hunspell_.get() != NULL; StatsScope<StatsCounterTimer> timer(chrome::Counters::spellcheck_init()); @@ -441,10 +428,9 @@ bool SpellChecker::Initialize() { // Control has come so far - both files probably exist. TimeTicks begin_time = TimeTicks::Now(); - const unsigned char* bdict_data; - size_t bdict_length; - if (MapBdictFile(&bdict_data, &bdict_length)) { - hunspell_ = new Hunspell(bdict_data, bdict_length); + bdict_file_.reset(new file_util::MemoryMappedFile()); + if (bdict_file_->Initialize(FilePath::FromWStringHack(bdict_file_name_))) { + hunspell_.reset(new Hunspell(bdict_file_->Data(), bdict_file_->Length())); AddCustomWordsToHunspell(); } DHISTOGRAM_TIMES(L"Spellcheck.InitTime", TimeTicks::Now() - begin_time); @@ -462,7 +448,7 @@ void SpellChecker::AddCustomWordsToHunspell() { file_util::ReadFileToString(custom_dictionary_file_name_, &contents); std::vector<std::string> list_of_words; SplitString(contents, '\n', &list_of_words); - if (hunspell_) { + if (hunspell_.get()) { for (std::vector<std::string>::iterator it = list_of_words.begin(); it != list_of_words.end(); ++it) { hunspell_->put_word(it->c_str()); @@ -470,36 +456,6 @@ void SpellChecker::AddCustomWordsToHunspell() { } } -bool SpellChecker::MapBdictFile(const unsigned char** data, size_t* length) { - bdict_file_ = CreateFile(bdict_file_name_.c_str(), GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (bdict_file_ == INVALID_HANDLE_VALUE) - return false; - - DWORD size = GetFileSize(bdict_file_, NULL); - bdict_mapping_ = - CreateFileMapping(bdict_file_, NULL, PAGE_READONLY, 0, size, NULL); - if (!bdict_mapping_) { - CloseHandle(bdict_file_); - bdict_file_ = NULL; - return false; - } - - bdict_mapped_data_ = reinterpret_cast<const unsigned char*>( - MapViewOfFile(bdict_mapping_, FILE_MAP_READ, 0, 0, size)); - if (!data) { - CloseHandle(bdict_mapping_); - bdict_mapping_ = NULL; - CloseHandle(bdict_file_); - bdict_file_ = NULL; - return false; - } - - *data = bdict_mapped_data_; - *length = size; - return true; -} - // Returns whether or not the given string is a valid contraction. // This function is a fall-back when the SpellcheckWordIterator class // returns a concatenated word which is not in the selected dictionary @@ -545,7 +501,7 @@ bool SpellChecker::SpellCheckWord( if (in_word_len == 0) return true; // no input means always spelled correctly - if (!hunspell_) + if (!hunspell_.get()) return true; // unable to spellcheck, return word is OK SpellcheckWordIterator word_iterator; diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h index 45eb73d..921a08e 100644 --- a/chrome/browser/spellchecker.h +++ b/chrome/browser/spellchecker.h @@ -24,6 +24,9 @@ class Profile; class MessageLoop; class URLRequestContext; +namespace file_util { +class MemoryMappedFile; +} // The Browser's Spell Checker. It checks and suggests corrections. // @@ -119,14 +122,11 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker> { // Path to the custom dictionary file. std::wstring custom_dictionary_file_name_; - // We memory-map the BDict file for spellchecking. These are the handles - // necessary for that. - HANDLE bdict_file_; - HANDLE bdict_mapping_; - const unsigned char* bdict_mapped_data_; + // We memory-map the BDict file. + scoped_ptr<file_util::MemoryMappedFile> bdict_file_; // The hunspell dictionary in use. - Hunspell* hunspell_; + scoped_ptr<Hunspell> hunspell_; // Represents character attributes used for filtering out characters which // are not supported by this SpellChecker object. |