| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/files/file_path.h" | 5 #include "base/files/file_path.h" | 
| 6 | 6 | 
| 7 #include <string.h> | 7 #include <string.h> | 
| 8 #include <algorithm> | 8 #include <algorithm> | 
| 9 | 9 | 
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 24 #endif | 24 #endif | 
| 25 | 25 | 
| 26 #if defined(OS_WIN) | 26 #if defined(OS_WIN) | 
| 27 #include <windows.h> | 27 #include <windows.h> | 
| 28 #elif defined(OS_MACOSX) | 28 #elif defined(OS_MACOSX) | 
| 29 #include <CoreFoundation/CoreFoundation.h> | 29 #include <CoreFoundation/CoreFoundation.h> | 
| 30 #endif | 30 #endif | 
| 31 | 31 | 
| 32 namespace base { | 32 namespace base { | 
| 33 | 33 | 
| 34 typedef FilePath::StringType StringType; | 34 using StringType = FilePath::StringType; | 
|  | 35 using StringPieceType = FilePath::StringPieceType; | 
| 35 | 36 | 
| 36 namespace { | 37 namespace { | 
| 37 | 38 | 
| 38 const char* const kCommonDoubleExtensionSuffixes[] = { "gz", "z", "bz2", "bz" }; | 39 const char* const kCommonDoubleExtensionSuffixes[] = { "gz", "z", "bz2", "bz" }; | 
| 39 const char* const kCommonDoubleExtensions[] = { "user.js" }; | 40 const char* const kCommonDoubleExtensions[] = { "user.js" }; | 
| 40 | 41 | 
| 41 const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0'); | 42 const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0'); | 
| 42 | 43 | 
| 43 // If this FilePath contains a drive letter specification, returns the | 44 // If this FilePath contains a drive letter specification, returns the | 
| 44 // position of the last character of the drive letter specification, | 45 // position of the last character of the drive letter specification, | 
| 45 // otherwise returns npos.  This can only be true on Windows, when a pathname | 46 // otherwise returns npos.  This can only be true on Windows, when a pathname | 
| 46 // begins with a letter followed by a colon.  On other platforms, this always | 47 // begins with a letter followed by a colon.  On other platforms, this always | 
| 47 // returns npos. | 48 // returns npos. | 
| 48 StringType::size_type FindDriveLetter(const StringType& path) { | 49 StringPieceType::size_type FindDriveLetter(StringPieceType path) { | 
| 49 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 50 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 
| 50   // This is dependent on an ASCII-based character set, but that's a | 51   // This is dependent on an ASCII-based character set, but that's a | 
| 51   // reasonable assumption.  iswalpha can be too inclusive here. | 52   // reasonable assumption.  iswalpha can be too inclusive here. | 
| 52   if (path.length() >= 2 && path[1] == L':' && | 53   if (path.length() >= 2 && path[1] == L':' && | 
| 53       ((path[0] >= L'A' && path[0] <= L'Z') || | 54       ((path[0] >= L'A' && path[0] <= L'Z') || | 
| 54        (path[0] >= L'a' && path[0] <= L'z'))) { | 55        (path[0] >= L'a' && path[0] <= L'z'))) { | 
| 55     return 1; | 56     return 1; | 
| 56   } | 57   } | 
| 57 #endif  // FILE_PATH_USES_DRIVE_LETTERS | 58 #endif  // FILE_PATH_USES_DRIVE_LETTERS | 
| 58   return StringType::npos; | 59   return StringType::npos; | 
| 59 } | 60 } | 
| 60 | 61 | 
| 61 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 62 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 
| 62 bool EqualDriveLetterCaseInsensitive(const StringType& a, | 63 bool EqualDriveLetterCaseInsensitive(StringPieceType a, StringPieceType b) { | 
| 63                                      const StringType& b) { |  | 
| 64   size_t a_letter_pos = FindDriveLetter(a); | 64   size_t a_letter_pos = FindDriveLetter(a); | 
| 65   size_t b_letter_pos = FindDriveLetter(b); | 65   size_t b_letter_pos = FindDriveLetter(b); | 
| 66 | 66 | 
| 67   if (a_letter_pos == StringType::npos || b_letter_pos == StringType::npos) | 67   if (a_letter_pos == StringType::npos || b_letter_pos == StringType::npos) | 
| 68     return a == b; | 68     return a == b; | 
| 69 | 69 | 
| 70   StringType a_letter(a.substr(0, a_letter_pos + 1)); | 70   StringPieceType a_letter(a.substr(0, a_letter_pos + 1)); | 
| 71   StringType b_letter(b.substr(0, b_letter_pos + 1)); | 71   StringPieceType b_letter(b.substr(0, b_letter_pos + 1)); | 
| 72   if (!StartsWith(a_letter, b_letter, false)) | 72   if (!StartsWith(a_letter, b_letter, CompareCase::INSENSITIVE_ASCII)) | 
| 73     return false; | 73     return false; | 
| 74 | 74 | 
| 75   StringType a_rest(a.substr(a_letter_pos + 1)); | 75   StringPieceType a_rest(a.substr(a_letter_pos + 1)); | 
| 76   StringType b_rest(b.substr(b_letter_pos + 1)); | 76   StringPieceType b_rest(b.substr(b_letter_pos + 1)); | 
| 77   return a_rest == b_rest; | 77   return a_rest == b_rest; | 
| 78 } | 78 } | 
| 79 #endif  // defined(FILE_PATH_USES_DRIVE_LETTERS) | 79 #endif  // defined(FILE_PATH_USES_DRIVE_LETTERS) | 
| 80 | 80 | 
| 81 bool IsPathAbsolute(const StringType& path) { | 81 bool IsPathAbsolute(StringPieceType path) { | 
| 82 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 82 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 
| 83   StringType::size_type letter = FindDriveLetter(path); | 83   StringType::size_type letter = FindDriveLetter(path); | 
| 84   if (letter != StringType::npos) { | 84   if (letter != StringType::npos) { | 
| 85     // Look for a separator right after the drive specification. | 85     // Look for a separator right after the drive specification. | 
| 86     return path.length() > letter + 1 && | 86     return path.length() > letter + 1 && | 
| 87         FilePath::IsSeparator(path[letter + 1]); | 87         FilePath::IsSeparator(path[letter + 1]); | 
| 88   } | 88   } | 
| 89   // Look for a pair of leading separators. | 89   // Look for a pair of leading separators. | 
| 90   return path.length() > 1 && | 90   return path.length() > 1 && | 
| 91       FilePath::IsSeparator(path[0]) && FilePath::IsSeparator(path[1]); | 91       FilePath::IsSeparator(path[0]) && FilePath::IsSeparator(path[1]); | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 170 } | 170 } | 
| 171 | 171 | 
| 172 }  // namespace | 172 }  // namespace | 
| 173 | 173 | 
| 174 FilePath::FilePath() { | 174 FilePath::FilePath() { | 
| 175 } | 175 } | 
| 176 | 176 | 
| 177 FilePath::FilePath(const FilePath& that) : path_(that.path_) { | 177 FilePath::FilePath(const FilePath& that) : path_(that.path_) { | 
| 178 } | 178 } | 
| 179 | 179 | 
| 180 FilePath::FilePath(const StringType& path) : path_(path) { | 180 FilePath::FilePath(StringPieceType path) { | 
|  | 181   path.CopyToString(&path_); | 
| 181   StringType::size_type nul_pos = path_.find(kStringTerminator); | 182   StringType::size_type nul_pos = path_.find(kStringTerminator); | 
| 182   if (nul_pos != StringType::npos) | 183   if (nul_pos != StringType::npos) | 
| 183     path_.erase(nul_pos, StringType::npos); | 184     path_.erase(nul_pos, StringType::npos); | 
| 184 } | 185 } | 
| 185 | 186 | 
| 186 FilePath::~FilePath() { | 187 FilePath::~FilePath() { | 
| 187 } | 188 } | 
| 188 | 189 | 
| 189 FilePath& FilePath::operator=(const FilePath& that) { | 190 FilePath& FilePath::operator=(const FilePath& that) { | 
| 190   path_ = that.path_; | 191   path_ = that.path_; | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 272       parent_components.begin(); | 273       parent_components.begin(); | 
| 273   std::vector<StringType>::const_iterator child_comp = | 274   std::vector<StringType>::const_iterator child_comp = | 
| 274       child_components.begin(); | 275       child_components.begin(); | 
| 275 | 276 | 
| 276 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 277 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 
| 277   // Windows can access case sensitive filesystems, so component | 278   // Windows can access case sensitive filesystems, so component | 
| 278   // comparisions must be case sensitive, but drive letters are | 279   // comparisions must be case sensitive, but drive letters are | 
| 279   // never case sensitive. | 280   // never case sensitive. | 
| 280   if ((FindDriveLetter(*parent_comp) != StringType::npos) && | 281   if ((FindDriveLetter(*parent_comp) != StringType::npos) && | 
| 281       (FindDriveLetter(*child_comp) != StringType::npos)) { | 282       (FindDriveLetter(*child_comp) != StringType::npos)) { | 
| 282     if (!StartsWith(*parent_comp, *child_comp, false)) | 283     if (!StartsWith(*parent_comp, *child_comp, CompareCase::INSENSITIVE_ASCII)) | 
| 283       return false; | 284       return false; | 
| 284     ++parent_comp; | 285     ++parent_comp; | 
| 285     ++child_comp; | 286     ++child_comp; | 
| 286   } | 287   } | 
| 287 #endif  // defined(FILE_PATH_USES_DRIVE_LETTERS) | 288 #endif  // defined(FILE_PATH_USES_DRIVE_LETTERS) | 
| 288 | 289 | 
| 289   while (parent_comp != parent_components.end()) { | 290   while (parent_comp != parent_components.end()) { | 
| 290     if (*parent_comp != *child_comp) | 291     if (*parent_comp != *child_comp) | 
| 291       return false; | 292       return false; | 
| 292     ++parent_comp; | 293     ++parent_comp; | 
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 397   if (FinalExtension().empty()) | 398   if (FinalExtension().empty()) | 
| 398     return *this; | 399     return *this; | 
| 399 | 400 | 
| 400   const StringType::size_type dot = FinalExtensionSeparatorPosition(path_); | 401   const StringType::size_type dot = FinalExtensionSeparatorPosition(path_); | 
| 401   if (dot == StringType::npos) | 402   if (dot == StringType::npos) | 
| 402     return *this; | 403     return *this; | 
| 403 | 404 | 
| 404   return FilePath(path_.substr(0, dot)); | 405   return FilePath(path_.substr(0, dot)); | 
| 405 } | 406 } | 
| 406 | 407 | 
| 407 FilePath FilePath::InsertBeforeExtension(const StringType& suffix) const { | 408 FilePath FilePath::InsertBeforeExtension(StringPieceType suffix) const { | 
| 408   if (suffix.empty()) | 409   if (suffix.empty()) | 
| 409     return FilePath(path_); | 410     return FilePath(path_); | 
| 410 | 411 | 
| 411   if (IsEmptyOrSpecialCase(BaseName().value())) | 412   if (IsEmptyOrSpecialCase(BaseName().value())) | 
| 412     return FilePath(); | 413     return FilePath(); | 
| 413 | 414 | 
| 414   StringType ext = Extension(); | 415   StringType ext = Extension(); | 
| 415   StringType ret = RemoveExtension().value(); | 416   StringType ret = RemoveExtension().value(); | 
| 416   ret.append(suffix); | 417   suffix.AppendToString(&ret); | 
| 417   ret.append(ext); | 418   ret.append(ext); | 
| 418   return FilePath(ret); | 419   return FilePath(ret); | 
| 419 } | 420 } | 
| 420 | 421 | 
| 421 FilePath FilePath::InsertBeforeExtensionASCII(const StringPiece& suffix) | 422 FilePath FilePath::InsertBeforeExtensionASCII(StringPiece suffix) | 
| 422     const { | 423     const { | 
| 423   DCHECK(IsStringASCII(suffix)); | 424   DCHECK(IsStringASCII(suffix)); | 
| 424 #if defined(OS_WIN) | 425 #if defined(OS_WIN) | 
| 425   return InsertBeforeExtension(ASCIIToUTF16(suffix.as_string())); | 426   return InsertBeforeExtension(ASCIIToUTF16(suffix)); | 
| 426 #elif defined(OS_POSIX) | 427 #elif defined(OS_POSIX) | 
| 427   return InsertBeforeExtension(suffix.as_string()); | 428   return InsertBeforeExtension(suffix); | 
| 428 #endif | 429 #endif | 
| 429 } | 430 } | 
| 430 | 431 | 
| 431 FilePath FilePath::AddExtension(const StringType& extension) const { | 432 FilePath FilePath::AddExtension(StringPieceType extension) const { | 
| 432   if (IsEmptyOrSpecialCase(BaseName().value())) | 433   if (IsEmptyOrSpecialCase(BaseName().value())) | 
| 433     return FilePath(); | 434     return FilePath(); | 
| 434 | 435 | 
| 435   // If the new extension is "" or ".", then just return the current FilePath. | 436   // If the new extension is "" or ".", then just return the current FilePath. | 
| 436   if (extension.empty() || extension == StringType(1, kExtensionSeparator)) | 437   if (extension.empty() || | 
|  | 438       (extension.size() == 1 && extension[0] == kExtensionSeparator)) | 
| 437     return *this; | 439     return *this; | 
| 438 | 440 | 
| 439   StringType str = path_; | 441   StringType str = path_; | 
| 440   if (extension[0] != kExtensionSeparator && | 442   if (extension[0] != kExtensionSeparator && | 
| 441       *(str.end() - 1) != kExtensionSeparator) { | 443       *(str.end() - 1) != kExtensionSeparator) { | 
| 442     str.append(1, kExtensionSeparator); | 444     str.append(1, kExtensionSeparator); | 
| 443   } | 445   } | 
| 444   str.append(extension); | 446   extension.AppendToString(&str); | 
| 445   return FilePath(str); | 447   return FilePath(str); | 
| 446 } | 448 } | 
| 447 | 449 | 
| 448 FilePath FilePath::ReplaceExtension(const StringType& extension) const { | 450 FilePath FilePath::ReplaceExtension(StringPieceType extension) const { | 
| 449   if (IsEmptyOrSpecialCase(BaseName().value())) | 451   if (IsEmptyOrSpecialCase(BaseName().value())) | 
| 450     return FilePath(); | 452     return FilePath(); | 
| 451 | 453 | 
| 452   FilePath no_ext = RemoveExtension(); | 454   FilePath no_ext = RemoveExtension(); | 
| 453   // If the new extension is "" or ".", then just remove the current extension. | 455   // If the new extension is "" or ".", then just remove the current extension. | 
| 454   if (extension.empty() || extension == StringType(1, kExtensionSeparator)) | 456   if (extension.empty() || | 
|  | 457       (extension.size() == 1 && extension[0] == kExtensionSeparator)) | 
| 455     return no_ext; | 458     return no_ext; | 
| 456 | 459 | 
| 457   StringType str = no_ext.value(); | 460   StringType str = no_ext.value(); | 
| 458   if (extension[0] != kExtensionSeparator) | 461   if (extension[0] != kExtensionSeparator) | 
| 459     str.append(1, kExtensionSeparator); | 462     str.append(1, kExtensionSeparator); | 
| 460   str.append(extension); | 463   extension.AppendToString(&str); | 
| 461   return FilePath(str); | 464   return FilePath(str); | 
| 462 } | 465 } | 
| 463 | 466 | 
| 464 bool FilePath::MatchesExtension(const StringType& extension) const { | 467 bool FilePath::MatchesExtension(StringPieceType extension) const { | 
| 465   DCHECK(extension.empty() || extension[0] == kExtensionSeparator); | 468   DCHECK(extension.empty() || extension[0] == kExtensionSeparator); | 
| 466 | 469 | 
| 467   StringType current_extension = Extension(); | 470   StringType current_extension = Extension(); | 
| 468 | 471 | 
| 469   if (current_extension.length() != extension.length()) | 472   if (current_extension.length() != extension.length()) | 
| 470     return false; | 473     return false; | 
| 471 | 474 | 
| 472   return FilePath::CompareEqualIgnoreCase(extension, current_extension); | 475   return FilePath::CompareEqualIgnoreCase(extension, current_extension); | 
| 473 } | 476 } | 
| 474 | 477 | 
| 475 FilePath FilePath::Append(const StringType& component) const { | 478 FilePath FilePath::Append(StringPieceType component) const { | 
| 476   const StringType* appended = &component; | 479   StringPieceType appended = component; | 
| 477   StringType without_nuls; | 480   StringType without_nuls; | 
| 478 | 481 | 
| 479   StringType::size_type nul_pos = component.find(kStringTerminator); | 482   StringType::size_type nul_pos = component.find(kStringTerminator); | 
| 480   if (nul_pos != StringType::npos) { | 483   if (nul_pos != StringPieceType::npos) { | 
| 481     without_nuls = component.substr(0, nul_pos); | 484     component.substr(0, nul_pos).CopyToString(&without_nuls); | 
| 482     appended = &without_nuls; | 485     appended = StringPieceType(without_nuls); | 
| 483   } | 486   } | 
| 484 | 487 | 
| 485   DCHECK(!IsPathAbsolute(*appended)); | 488   DCHECK(!IsPathAbsolute(appended)); | 
| 486 | 489 | 
| 487   if (path_.compare(kCurrentDirectory) == 0) { | 490   if (path_.compare(kCurrentDirectory) == 0) { | 
| 488     // Append normally doesn't do any normalization, but as a special case, | 491     // Append normally doesn't do any normalization, but as a special case, | 
| 489     // when appending to kCurrentDirectory, just return a new path for the | 492     // when appending to kCurrentDirectory, just return a new path for the | 
| 490     // component argument.  Appending component to kCurrentDirectory would | 493     // component argument.  Appending component to kCurrentDirectory would | 
| 491     // serve no purpose other than needlessly lengthening the path, and | 494     // serve no purpose other than needlessly lengthening the path, and | 
| 492     // it's likely in practice to wind up with FilePath objects containing | 495     // it's likely in practice to wind up with FilePath objects containing | 
| 493     // only kCurrentDirectory when calling DirName on a single relative path | 496     // only kCurrentDirectory when calling DirName on a single relative path | 
| 494     // component. | 497     // component. | 
| 495     return FilePath(*appended); | 498     return FilePath(appended); | 
| 496   } | 499   } | 
| 497 | 500 | 
| 498   FilePath new_path(path_); | 501   FilePath new_path(path_); | 
| 499   new_path.StripTrailingSeparatorsInternal(); | 502   new_path.StripTrailingSeparatorsInternal(); | 
| 500 | 503 | 
| 501   // Don't append a separator if the path is empty (indicating the current | 504   // Don't append a separator if the path is empty (indicating the current | 
| 502   // directory) or if the path component is empty (indicating nothing to | 505   // directory) or if the path component is empty (indicating nothing to | 
| 503   // append). | 506   // append). | 
| 504   if (appended->length() > 0 && new_path.path_.length() > 0) { | 507   if (appended.length() > 0 && new_path.path_.length() > 0) { | 
| 505     // Don't append a separator if the path still ends with a trailing | 508     // Don't append a separator if the path still ends with a trailing | 
| 506     // separator after stripping (indicating the root directory). | 509     // separator after stripping (indicating the root directory). | 
| 507     if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { | 510     if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { | 
| 508       // Don't append a separator if the path is just a drive letter. | 511       // Don't append a separator if the path is just a drive letter. | 
| 509       if (FindDriveLetter(new_path.path_) + 1 != new_path.path_.length()) { | 512       if (FindDriveLetter(new_path.path_) + 1 != new_path.path_.length()) { | 
| 510         new_path.path_.append(1, kSeparators[0]); | 513         new_path.path_.append(1, kSeparators[0]); | 
| 511       } | 514       } | 
| 512     } | 515     } | 
| 513   } | 516   } | 
| 514 | 517 | 
| 515   new_path.path_.append(*appended); | 518   appended.AppendToString(&new_path.path_); | 
| 516   return new_path; | 519   return new_path; | 
| 517 } | 520 } | 
| 518 | 521 | 
| 519 FilePath FilePath::Append(const FilePath& component) const { | 522 FilePath FilePath::Append(const FilePath& component) const { | 
| 520   return Append(component.value()); | 523   return Append(component.value()); | 
| 521 } | 524 } | 
| 522 | 525 | 
| 523 FilePath FilePath::AppendASCII(const StringPiece& component) const { | 526 FilePath FilePath::AppendASCII(StringPiece component) const { | 
| 524   DCHECK(base::IsStringASCII(component)); | 527   DCHECK(base::IsStringASCII(component)); | 
| 525 #if defined(OS_WIN) | 528 #if defined(OS_WIN) | 
| 526   return Append(ASCIIToUTF16(component.as_string())); | 529   return Append(ASCIIToUTF16(component)); | 
| 527 #elif defined(OS_POSIX) | 530 #elif defined(OS_POSIX) | 
| 528   return Append(component.as_string()); | 531   return Append(component); | 
| 529 #endif | 532 #endif | 
| 530 } | 533 } | 
| 531 | 534 | 
| 532 bool FilePath::IsAbsolute() const { | 535 bool FilePath::IsAbsolute() const { | 
| 533   return IsPathAbsolute(path_); | 536   return IsPathAbsolute(path_); | 
| 534 } | 537 } | 
| 535 | 538 | 
| 536 bool FilePath::EndsWithSeparator() const { | 539 bool FilePath::EndsWithSeparator() const { | 
| 537   if (empty()) | 540   if (empty()) | 
| 538     return false; | 541     return false; | 
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 673     return false; | 676     return false; | 
| 674 #endif | 677 #endif | 
| 675 | 678 | 
| 676   if (path_.find(kStringTerminator) != StringType::npos) | 679   if (path_.find(kStringTerminator) != StringType::npos) | 
| 677     return false; | 680     return false; | 
| 678 | 681 | 
| 679   return true; | 682   return true; | 
| 680 } | 683 } | 
| 681 | 684 | 
| 682 #if defined(OS_WIN) | 685 #if defined(OS_WIN) | 
| 683 // Windows specific implementation of file string comparisons | 686 // Windows specific implementation of file string comparisons. | 
| 684 | 687 | 
| 685 int FilePath::CompareIgnoreCase(const StringType& string1, | 688 int FilePath::CompareIgnoreCase(StringPieceType string1, | 
| 686                                 const StringType& string2) { | 689                                 StringPieceType string2) { | 
| 687   // Perform character-wise upper case comparison rather than using the | 690   // Perform character-wise upper case comparison rather than using the | 
| 688   // fully Unicode-aware CompareString(). For details see: | 691   // fully Unicode-aware CompareString(). For details see: | 
| 689   // http://blogs.msdn.com/michkap/archive/2005/10/17/481600.aspx | 692   // http://blogs.msdn.com/michkap/archive/2005/10/17/481600.aspx | 
| 690   StringType::const_iterator i1 = string1.begin(); | 693   StringPieceType::const_iterator i1 = string1.begin(); | 
| 691   StringType::const_iterator i2 = string2.begin(); | 694   StringPieceType::const_iterator i2 = string2.begin(); | 
| 692   StringType::const_iterator string1end = string1.end(); | 695   StringPieceType::const_iterator string1end = string1.end(); | 
| 693   StringType::const_iterator string2end = string2.end(); | 696   StringPieceType::const_iterator string2end = string2.end(); | 
| 694   for ( ; i1 != string1end && i2 != string2end; ++i1, ++i2) { | 697   for ( ; i1 != string1end && i2 != string2end; ++i1, ++i2) { | 
| 695     wchar_t c1 = | 698     wchar_t c1 = | 
| 696         (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i1, 0))); | 699         (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i1, 0))); | 
| 697     wchar_t c2 = | 700     wchar_t c2 = | 
| 698         (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i2, 0))); | 701         (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i2, 0))); | 
| 699     if (c1 < c2) | 702     if (c1 < c2) | 
| 700       return -1; | 703       return -1; | 
| 701     if (c1 > c2) | 704     if (c1 > c2) | 
| 702       return 1; | 705       return 1; | 
| 703   } | 706   } | 
| 704   if (i1 != string1end) | 707   if (i1 != string1end) | 
| 705     return 1; | 708     return 1; | 
| 706   if (i2 != string2end) | 709   if (i2 != string2end) | 
| 707     return -1; | 710     return -1; | 
| 708   return 0; | 711   return 0; | 
| 709 } | 712 } | 
| 710 | 713 | 
| 711 #elif defined(OS_MACOSX) | 714 #elif defined(OS_MACOSX) | 
| 712 // Mac OS X specific implementation of file string comparisons | 715 // Mac OS X specific implementation of file string comparisons. | 
| 713 | 716 | 
| 714 // cf. http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSu
      btleties | 717 // cf. http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSu
      btleties | 
| 715 // | 718 // | 
| 716 // "When using CreateTextEncoding to create a text encoding, you should set | 719 // "When using CreateTextEncoding to create a text encoding, you should set | 
| 717 // the TextEncodingBase to kTextEncodingUnicodeV2_0, set the | 720 // the TextEncodingBase to kTextEncodingUnicodeV2_0, set the | 
| 718 // TextEncodingVariant to kUnicodeCanonicalDecompVariant, and set the | 721 // TextEncodingVariant to kUnicodeCanonicalDecompVariant, and set the | 
| 719 // TextEncodingFormat to kUnicode16BitFormat. Using these values ensures that | 722 // TextEncodingFormat to kUnicode16BitFormat. Using these values ensures that | 
| 720 // the Unicode will be in the same form as on an HFS Plus volume, even as the | 723 // the Unicode will be in the same form as on an HFS Plus volume, even as the | 
| 721 // Unicode standard evolves." | 724 // Unicode standard evolves." | 
| 722 // | 725 // | 
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1146       int lookup_offset = lower_case_table[codepoint >> 8]; | 1149       int lookup_offset = lower_case_table[codepoint >> 8]; | 
| 1147       if (lookup_offset != 0) | 1150       if (lookup_offset != 0) | 
| 1148         codepoint = lower_case_table[lookup_offset + (codepoint & 0x00FF)]; | 1151         codepoint = lower_case_table[lookup_offset + (codepoint & 0x00FF)]; | 
| 1149       // Note: codepoint1 may be again 0 at this point if the character was | 1152       // Note: codepoint1 may be again 0 at this point if the character was | 
| 1150       // an ignorable. | 1153       // an ignorable. | 
| 1151     } | 1154     } | 
| 1152   } | 1155   } | 
| 1153   return codepoint; | 1156   return codepoint; | 
| 1154 } | 1157 } | 
| 1155 | 1158 | 
| 1156 }  // anonymous namespace | 1159 }  // namespace | 
| 1157 | 1160 | 
| 1158 // Special UTF-8 version of FastUnicodeCompare. Cf: | 1161 // Special UTF-8 version of FastUnicodeCompare. Cf: | 
| 1159 // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringCompari
      sonAlgorithm | 1162 // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringCompari
      sonAlgorithm | 
| 1160 // The input strings must be in the special HFS decomposed form. | 1163 // The input strings must be in the special HFS decomposed form. | 
| 1161 int FilePath::HFSFastUnicodeCompare(const StringType& string1, | 1164 int FilePath::HFSFastUnicodeCompare(StringPieceType string1, | 
| 1162                                     const StringType& string2) { | 1165                                     StringPieceType string2) { | 
| 1163   int length1 = string1.length(); | 1166   int length1 = string1.length(); | 
| 1164   int length2 = string2.length(); | 1167   int length2 = string2.length(); | 
| 1165   int index1 = 0; | 1168   int index1 = 0; | 
| 1166   int index2 = 0; | 1169   int index2 = 0; | 
| 1167 | 1170 | 
| 1168   for (;;) { | 1171   for (;;) { | 
| 1169     int codepoint1 = HFSReadNextNonIgnorableCodepoint(string1.c_str(), | 1172     int codepoint1 = HFSReadNextNonIgnorableCodepoint(string1.data(), | 
| 1170                                                       length1, | 1173                                                       length1, | 
| 1171                                                       &index1); | 1174                                                       &index1); | 
| 1172     int codepoint2 = HFSReadNextNonIgnorableCodepoint(string2.c_str(), | 1175     int codepoint2 = HFSReadNextNonIgnorableCodepoint(string2.data(), | 
| 1173                                                       length2, | 1176                                                       length2, | 
| 1174                                                       &index2); | 1177                                                       &index2); | 
| 1175     if (codepoint1 != codepoint2) | 1178     if (codepoint1 != codepoint2) | 
| 1176       return (codepoint1 < codepoint2) ? -1 : 1; | 1179       return (codepoint1 < codepoint2) ? -1 : 1; | 
| 1177     if (codepoint1 == 0) { | 1180     if (codepoint1 == 0) { | 
| 1178       DCHECK_EQ(index1, length1); | 1181       DCHECK_EQ(index1, length1); | 
| 1179       DCHECK_EQ(index2, length2); | 1182       DCHECK_EQ(index2, length2); | 
| 1180       return 0; | 1183       return 0; | 
| 1181     } | 1184     } | 
| 1182   } | 1185   } | 
| 1183 } | 1186 } | 
| 1184 | 1187 | 
| 1185 StringType FilePath::GetHFSDecomposedForm(const StringType& string) { | 1188 StringType FilePath::GetHFSDecomposedForm(StringPieceType string) { | 
| 1186   ScopedCFTypeRef<CFStringRef> cfstring( | 1189   ScopedCFTypeRef<CFStringRef> cfstring( | 
| 1187       CFStringCreateWithBytesNoCopy( | 1190       CFStringCreateWithBytesNoCopy( | 
| 1188           NULL, | 1191           NULL, | 
| 1189           reinterpret_cast<const UInt8*>(string.c_str()), | 1192           reinterpret_cast<const UInt8*>(string.data()), | 
| 1190           string.length(), | 1193           string.length(), | 
| 1191           kCFStringEncodingUTF8, | 1194           kCFStringEncodingUTF8, | 
| 1192           false, | 1195           false, | 
| 1193           kCFAllocatorNull)); | 1196           kCFAllocatorNull)); | 
| 1194   // Query the maximum length needed to store the result. In most cases this | 1197   // Query the maximum length needed to store the result. In most cases this | 
| 1195   // will overestimate the required space. The return value also already | 1198   // will overestimate the required space. The return value also already | 
| 1196   // includes the space needed for a terminating 0. | 1199   // includes the space needed for a terminating 0. | 
| 1197   CFIndex length = CFStringGetMaximumSizeOfFileSystemRepresentation(cfstring); | 1200   CFIndex length = CFStringGetMaximumSizeOfFileSystemRepresentation(cfstring); | 
| 1198   DCHECK_GT(length, 0);  // should be at least 1 for the 0-terminator. | 1201   DCHECK_GT(length, 0);  // should be at least 1 for the 0-terminator. | 
| 1199   // Reserve enough space for CFStringGetFileSystemRepresentation to write into. | 1202   // Reserve enough space for CFStringGetFileSystemRepresentation to write into. | 
| 1200   // Also set the length to the maximum so that we can shrink it later. | 1203   // Also set the length to the maximum so that we can shrink it later. | 
| 1201   // (Increasing rather than decreasing it would clobber the string contents!) | 1204   // (Increasing rather than decreasing it would clobber the string contents!) | 
| 1202   StringType result; | 1205   StringType result; | 
| 1203   result.reserve(length); | 1206   result.reserve(length); | 
| 1204   result.resize(length - 1); | 1207   result.resize(length - 1); | 
| 1205   Boolean success = CFStringGetFileSystemRepresentation(cfstring, | 1208   Boolean success = CFStringGetFileSystemRepresentation(cfstring, | 
| 1206                                                         &result[0], | 1209                                                         &result[0], | 
| 1207                                                         length); | 1210                                                         length); | 
| 1208   if (success) { | 1211   if (success) { | 
| 1209     // Reduce result.length() to actual string length. | 1212     // Reduce result.length() to actual string length. | 
| 1210     result.resize(strlen(result.c_str())); | 1213     result.resize(strlen(result.c_str())); | 
| 1211   } else { | 1214   } else { | 
| 1212     // An error occurred -> clear result. | 1215     // An error occurred -> clear result. | 
| 1213     result.clear(); | 1216     result.clear(); | 
| 1214   } | 1217   } | 
| 1215   return result; | 1218   return result; | 
| 1216 } | 1219 } | 
| 1217 | 1220 | 
| 1218 int FilePath::CompareIgnoreCase(const StringType& string1, | 1221 int FilePath::CompareIgnoreCase(StringPieceType string1, | 
| 1219                                 const StringType& string2) { | 1222                                 StringPieceType string2) { | 
| 1220   // Quick checks for empty strings - these speed things up a bit and make the | 1223   // Quick checks for empty strings - these speed things up a bit and make the | 
| 1221   // following code cleaner. | 1224   // following code cleaner. | 
| 1222   if (string1.empty()) | 1225   if (string1.empty()) | 
| 1223     return string2.empty() ? 0 : -1; | 1226     return string2.empty() ? 0 : -1; | 
| 1224   if (string2.empty()) | 1227   if (string2.empty()) | 
| 1225     return 1; | 1228     return 1; | 
| 1226 | 1229 | 
| 1227   StringType hfs1 = GetHFSDecomposedForm(string1); | 1230   StringType hfs1 = GetHFSDecomposedForm(string1); | 
| 1228   StringType hfs2 = GetHFSDecomposedForm(string2); | 1231   StringType hfs2 = GetHFSDecomposedForm(string2); | 
| 1229 | 1232 | 
| 1230   // GetHFSDecomposedForm() returns an empty string in an error case. | 1233   // GetHFSDecomposedForm() returns an empty string in an error case. | 
| 1231   if (hfs1.empty() || hfs2.empty()) { | 1234   if (hfs1.empty() || hfs2.empty()) { | 
| 1232     NOTREACHED(); | 1235     NOTREACHED(); | 
| 1233     ScopedCFTypeRef<CFStringRef> cfstring1( | 1236     ScopedCFTypeRef<CFStringRef> cfstring1( | 
| 1234         CFStringCreateWithBytesNoCopy( | 1237         CFStringCreateWithBytesNoCopy( | 
| 1235             NULL, | 1238             NULL, | 
| 1236             reinterpret_cast<const UInt8*>(string1.c_str()), | 1239             reinterpret_cast<const UInt8*>(string1.data()), | 
| 1237             string1.length(), | 1240             string1.length(), | 
| 1238             kCFStringEncodingUTF8, | 1241             kCFStringEncodingUTF8, | 
| 1239             false, | 1242             false, | 
| 1240             kCFAllocatorNull)); | 1243             kCFAllocatorNull)); | 
| 1241     ScopedCFTypeRef<CFStringRef> cfstring2( | 1244     ScopedCFTypeRef<CFStringRef> cfstring2( | 
| 1242         CFStringCreateWithBytesNoCopy( | 1245         CFStringCreateWithBytesNoCopy( | 
| 1243             NULL, | 1246             NULL, | 
| 1244             reinterpret_cast<const UInt8*>(string2.c_str()), | 1247             reinterpret_cast<const UInt8*>(string2.data()), | 
| 1245             string2.length(), | 1248             string2.length(), | 
| 1246             kCFStringEncodingUTF8, | 1249             kCFStringEncodingUTF8, | 
| 1247             false, | 1250             false, | 
| 1248             kCFAllocatorNull)); | 1251             kCFAllocatorNull)); | 
| 1249     return CFStringCompare(cfstring1, | 1252     return CFStringCompare(cfstring1, | 
| 1250                            cfstring2, | 1253                            cfstring2, | 
| 1251                            kCFCompareCaseInsensitive); | 1254                            kCFCompareCaseInsensitive); | 
| 1252   } | 1255   } | 
| 1253 | 1256 | 
| 1254   return HFSFastUnicodeCompare(hfs1, hfs2); | 1257   return HFSFastUnicodeCompare(hfs1, hfs2); | 
| 1255 } | 1258 } | 
| 1256 | 1259 | 
| 1257 #else  // << WIN. MACOSX | other (POSIX) >> | 1260 #else  // << WIN. MACOSX | other (POSIX) >> | 
| 1258 | 1261 | 
| 1259 // Generic (POSIX) implementation of file string comparison. | 1262 // Generic (POSIX) implementation of file string comparison. | 
| 1260 // TODO(rolandsteiner) check if this is sufficient/correct. | 1263 // TODO(rolandsteiner) check if this is sufficient/correct. | 
| 1261 int FilePath::CompareIgnoreCase(const StringType& string1, | 1264 int FilePath::CompareIgnoreCase(StringPieceType string1, | 
| 1262                                 const StringType& string2) { | 1265                                 StringPieceType string2) { | 
| 1263   int comparison = strcasecmp(string1.c_str(), string2.c_str()); | 1266   int comparison = strcasecmp(string1.data(), string2.data()); | 
| 1264   if (comparison < 0) | 1267   if (comparison < 0) | 
| 1265     return -1; | 1268     return -1; | 
| 1266   if (comparison > 0) | 1269   if (comparison > 0) | 
| 1267     return 1; | 1270     return 1; | 
| 1268   return 0; | 1271   return 0; | 
| 1269 } | 1272 } | 
| 1270 | 1273 | 
| 1271 #endif  // OS versions of CompareIgnoreCase() | 1274 #endif  // OS versions of CompareIgnoreCase() | 
| 1272 | 1275 | 
| 1273 | 1276 | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1311 #endif | 1314 #endif | 
| 1312 } | 1315 } | 
| 1313 | 1316 | 
| 1314 #if defined(OS_ANDROID) | 1317 #if defined(OS_ANDROID) | 
| 1315 bool FilePath::IsContentUri() const { | 1318 bool FilePath::IsContentUri() const { | 
| 1316   return StartsWithASCII(path_, "content://", false /*case_sensitive*/); | 1319   return StartsWithASCII(path_, "content://", false /*case_sensitive*/); | 
| 1317 } | 1320 } | 
| 1318 #endif | 1321 #endif | 
| 1319 | 1322 | 
| 1320 }  // namespace base | 1323 }  // namespace base | 
| OLD | NEW | 
|---|