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/file_path.h" | 5 #include "base/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 29 matching lines...) Expand all Loading... |
40 | 40 |
41 const FilePath::CharType FilePath::kExtensionSeparator = FILE_PATH_LITERAL('.'); | 41 const FilePath::CharType FilePath::kExtensionSeparator = FILE_PATH_LITERAL('.'); |
42 | 42 |
43 typedef FilePath::StringType StringType; | 43 typedef FilePath::StringType StringType; |
44 | 44 |
45 namespace { | 45 namespace { |
46 | 46 |
47 const char* kCommonDoubleExtensionSuffixes[] = { "gz", "z", "bz2" }; | 47 const char* kCommonDoubleExtensionSuffixes[] = { "gz", "z", "bz2" }; |
48 const char* kCommonDoubleExtensions[] = { "user.js" }; | 48 const char* kCommonDoubleExtensions[] = { "user.js" }; |
49 | 49 |
| 50 const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0'); |
| 51 |
50 // If this FilePath contains a drive letter specification, returns the | 52 // If this FilePath contains a drive letter specification, returns the |
51 // position of the last character of the drive letter specification, | 53 // position of the last character of the drive letter specification, |
52 // otherwise returns npos. This can only be true on Windows, when a pathname | 54 // otherwise returns npos. This can only be true on Windows, when a pathname |
53 // begins with a letter followed by a colon. On other platforms, this always | 55 // begins with a letter followed by a colon. On other platforms, this always |
54 // returns npos. | 56 // returns npos. |
55 StringType::size_type FindDriveLetter(const StringType& path) { | 57 StringType::size_type FindDriveLetter(const StringType& path) { |
56 #if defined(FILE_PATH_USES_DRIVE_LETTERS) | 58 #if defined(FILE_PATH_USES_DRIVE_LETTERS) |
57 // This is dependent on an ASCII-based character set, but that's a | 59 // This is dependent on an ASCII-based character set, but that's a |
58 // reasonable assumption. iswalpha can be too inclusive here. | 60 // reasonable assumption. iswalpha can be too inclusive here. |
59 if (path.length() >= 2 && path[1] == L':' && | 61 if (path.length() >= 2 && path[1] == L':' && |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 | 177 |
176 } // namespace | 178 } // namespace |
177 | 179 |
178 FilePath::FilePath() { | 180 FilePath::FilePath() { |
179 } | 181 } |
180 | 182 |
181 FilePath::FilePath(const FilePath& that) : path_(that.path_) { | 183 FilePath::FilePath(const FilePath& that) : path_(that.path_) { |
182 } | 184 } |
183 | 185 |
184 FilePath::FilePath(const StringType& path) : path_(path) { | 186 FilePath::FilePath(const StringType& path) : path_(path) { |
| 187 StringType::size_type nul_pos = path_.find(kStringTerminator); |
| 188 if (nul_pos != StringType::npos) |
| 189 path_.erase(nul_pos, StringType::npos); |
185 } | 190 } |
186 | 191 |
187 FilePath::~FilePath() { | 192 FilePath::~FilePath() { |
188 } | 193 } |
189 | 194 |
190 FilePath& FilePath::operator=(const FilePath& that) { | 195 FilePath& FilePath::operator=(const FilePath& that) { |
191 path_ = that.path_; | 196 path_ = that.path_; |
192 return *this; | 197 return *this; |
193 } | 198 } |
194 | 199 |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 | 452 |
448 StringType current_extension = Extension(); | 453 StringType current_extension = Extension(); |
449 | 454 |
450 if (current_extension.length() != extension.length()) | 455 if (current_extension.length() != extension.length()) |
451 return false; | 456 return false; |
452 | 457 |
453 return FilePath::CompareEqualIgnoreCase(extension, current_extension); | 458 return FilePath::CompareEqualIgnoreCase(extension, current_extension); |
454 } | 459 } |
455 | 460 |
456 FilePath FilePath::Append(const StringType& component) const { | 461 FilePath FilePath::Append(const StringType& component) const { |
457 DCHECK(!IsPathAbsolute(component)); | 462 const StringType* appended = &component; |
| 463 StringType without_nuls; |
| 464 |
| 465 StringType::size_type nul_pos = component.find(kStringTerminator); |
| 466 if (nul_pos != StringType::npos) { |
| 467 without_nuls = component.substr(0, nul_pos); |
| 468 appended = &without_nuls; |
| 469 } |
| 470 |
| 471 DCHECK(!IsPathAbsolute(*appended)); |
| 472 |
458 if (path_.compare(kCurrentDirectory) == 0) { | 473 if (path_.compare(kCurrentDirectory) == 0) { |
459 // Append normally doesn't do any normalization, but as a special case, | 474 // Append normally doesn't do any normalization, but as a special case, |
460 // when appending to kCurrentDirectory, just return a new path for the | 475 // when appending to kCurrentDirectory, just return a new path for the |
461 // component argument. Appending component to kCurrentDirectory would | 476 // component argument. Appending component to kCurrentDirectory would |
462 // serve no purpose other than needlessly lengthening the path, and | 477 // serve no purpose other than needlessly lengthening the path, and |
463 // it's likely in practice to wind up with FilePath objects containing | 478 // it's likely in practice to wind up with FilePath objects containing |
464 // only kCurrentDirectory when calling DirName on a single relative path | 479 // only kCurrentDirectory when calling DirName on a single relative path |
465 // component. | 480 // component. |
466 return FilePath(component); | 481 return FilePath(*appended); |
467 } | 482 } |
468 | 483 |
469 FilePath new_path(path_); | 484 FilePath new_path(path_); |
470 new_path.StripTrailingSeparatorsInternal(); | 485 new_path.StripTrailingSeparatorsInternal(); |
471 | 486 |
472 // Don't append a separator if the path is empty (indicating the current | 487 // Don't append a separator if the path is empty (indicating the current |
473 // directory) or if the path component is empty (indicating nothing to | 488 // directory) or if the path component is empty (indicating nothing to |
474 // append). | 489 // append). |
475 if (component.length() > 0 && new_path.path_.length() > 0) { | 490 if (appended->length() > 0 && new_path.path_.length() > 0) { |
476 // Don't append a separator if the path still ends with a trailing | 491 // Don't append a separator if the path still ends with a trailing |
477 // separator after stripping (indicating the root directory). | 492 // separator after stripping (indicating the root directory). |
478 if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { | 493 if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { |
479 // Don't append a separator if the path is just a drive letter. | 494 // Don't append a separator if the path is just a drive letter. |
480 if (FindDriveLetter(new_path.path_) + 1 != new_path.path_.length()) { | 495 if (FindDriveLetter(new_path.path_) + 1 != new_path.path_.length()) { |
481 new_path.path_.append(1, kSeparators[0]); | 496 new_path.path_.append(1, kSeparators[0]); |
482 } | 497 } |
483 } | 498 } |
484 } | 499 } |
485 | 500 |
486 new_path.path_.append(component); | 501 new_path.path_.append(*appended); |
487 return new_path; | 502 return new_path; |
488 } | 503 } |
489 | 504 |
490 FilePath FilePath::Append(const FilePath& component) const { | 505 FilePath FilePath::Append(const FilePath& component) const { |
491 return Append(component.value()); | 506 return Append(component.value()); |
492 } | 507 } |
493 | 508 |
494 FilePath FilePath::AppendASCII(const base::StringPiece& component) const { | 509 FilePath FilePath::AppendASCII(const base::StringPiece& component) const { |
495 DCHECK(IsStringASCII(component)); | 510 DCHECK(IsStringASCII(component)); |
496 #if defined(OS_WIN) | 511 #if defined(OS_WIN) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 FilePath FilePath::FromWStringHack(const std::wstring& wstring) { | 597 FilePath FilePath::FromWStringHack(const std::wstring& wstring) { |
583 return FilePath(wstring); | 598 return FilePath(wstring); |
584 } | 599 } |
585 | 600 |
586 // static | 601 // static |
587 FilePath FilePath::FromUTF8Unsafe(const std::string& utf8) { | 602 FilePath FilePath::FromUTF8Unsafe(const std::string& utf8) { |
588 return FilePath(UTF8ToWide(utf8)); | 603 return FilePath(UTF8ToWide(utf8)); |
589 } | 604 } |
590 #endif | 605 #endif |
591 | 606 |
592 void FilePath::WriteToPickle(Pickle* pickle) { | 607 void FilePath::WriteToPickle(Pickle* pickle) const { |
593 #if defined(OS_WIN) | 608 #if defined(OS_WIN) |
594 pickle->WriteString16(path_); | 609 pickle->WriteString16(path_); |
595 #else | 610 #else |
596 pickle->WriteString(path_); | 611 pickle->WriteString(path_); |
597 #endif | 612 #endif |
598 } | 613 } |
599 | 614 |
600 bool FilePath::ReadFromPickle(PickleIterator* iter) { | 615 bool FilePath::ReadFromPickle(PickleIterator* iter) { |
601 #if defined(OS_WIN) | 616 #if defined(OS_WIN) |
602 if (!iter->ReadString16(&path_)) | 617 if (!iter->ReadString16(&path_)) |
603 return false; | 618 return false; |
604 #else | 619 #else |
605 if (!iter->ReadString(&path_)) | 620 if (!iter->ReadString(&path_)) |
606 return false; | 621 return false; |
607 #endif | 622 #endif |
608 | 623 |
| 624 if (path_.find(kStringTerminator) != StringType::npos) |
| 625 return false; |
| 626 |
609 return true; | 627 return true; |
610 } | 628 } |
611 | 629 |
612 #if defined(OS_WIN) | 630 #if defined(OS_WIN) |
613 // Windows specific implementation of file string comparisons | 631 // Windows specific implementation of file string comparisons |
614 | 632 |
615 int FilePath::CompareIgnoreCase(const StringType& string1, | 633 int FilePath::CompareIgnoreCase(const StringType& string1, |
616 const StringType& string2) { | 634 const StringType& string2) { |
617 // Perform character-wise upper case comparison rather than using the | 635 // Perform character-wise upper case comparison rather than using the |
618 // fully Unicode-aware CompareString(). For details see: | 636 // fully Unicode-aware CompareString(). For details see: |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 } | 1247 } |
1230 return FilePath(copy); | 1248 return FilePath(copy); |
1231 #else | 1249 #else |
1232 return *this; | 1250 return *this; |
1233 #endif | 1251 #endif |
1234 } | 1252 } |
1235 | 1253 |
1236 void PrintTo(const FilePath& path, std::ostream* out) { | 1254 void PrintTo(const FilePath& path, std::ostream* out) { |
1237 *out << path.value(); | 1255 *out << path.value(); |
1238 } | 1256 } |
OLD | NEW |