Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: base/files/file_path.cc

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

Powered by Google App Engine
This is Rietveld 408576698