PathTokenizer.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <?php
  2. /*
  3. * $Id: PathTokenizer.php 905 2010-10-05 16:28:03Z mrook $
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information please see
  19. * <http://phing.info>.
  20. */
  21. include_once 'phing/util/StringHelper.php';
  22. /**
  23. * A Path tokenizer takes a path and returns the components that make up
  24. * that path.
  25. *
  26. * The path can use path separators of either ':' or ';' and file separators
  27. * of either '/' or '\'.
  28. *
  29. * @author Hans Lellelid <hans@xmpl.org> (Phing)
  30. * @author Conor MacNeill (Ant)
  31. * @author Jeff Tulley <jtulley@novell.com> (Ant)
  32. * @package phing.util
  33. */
  34. class PathTokenizer {
  35. /**
  36. * A array of tokens, created by preg_split().
  37. */
  38. private $tokens = array();
  39. /**
  40. * A string which stores any path components which have been read ahead
  41. * due to DOS filesystem compensation.
  42. * @var string
  43. */
  44. private $lookahead;
  45. /**
  46. * Flag to indicate whether or not we are running on a platform with a
  47. * DOS style filesystem
  48. * @var boolean
  49. */
  50. private $dosStyleFilesystem;
  51. /**
  52. * Constructs a path tokenizer for the specified path.
  53. *
  54. * @param path The path to tokenize. Must not be <code>null</code>.
  55. */
  56. public function __construct($path) {
  57. // on Windows and Unix, we can ignore delimiters and still have
  58. // enough information to tokenize correctly.
  59. $this->tokens = preg_split("/[;:]/", $path, -1, PREG_SPLIT_NO_EMPTY);
  60. $this->dosStyleFilesystem = ( PATH_SEPARATOR == ';');
  61. }
  62. /**
  63. * Tests if there are more path elements available from this tokenizer's
  64. * path. If this method returns <code>true</code>, then a subsequent call
  65. * to nextToken will successfully return a token.
  66. *
  67. * @return <code>true</code> if and only if there is at least one token
  68. * in the string after the current position; <code>false</code> otherwise.
  69. */
  70. public function hasMoreTokens() {
  71. if ($this->lookahead !== null) {
  72. return true;
  73. }
  74. return !empty($this->tokens);
  75. }
  76. /**
  77. * Returns the next path element from this tokenizer.
  78. *
  79. * @return the next path element from this tokenizer.
  80. *
  81. * @throws Exception if there are no more elements in this tokenizer's path.
  82. */
  83. public function nextToken() {
  84. if ($this->lookahead !== null) {
  85. $token = $this->lookahead;
  86. $this->lookahead = null;
  87. } else {
  88. $token = trim(array_shift($this->tokens));
  89. }
  90. if (strlen($token) === 1 && Character::isLetter($token{0})
  91. && $this->dosStyleFilesystem
  92. && !empty($this->tokens)) {
  93. // we are on a dos style system so this path could be a drive
  94. // spec. We look at the next token
  95. $nextToken = trim(array_shift($this->tokens));
  96. if (StringHelper::startsWith('\\', $nextToken) || StringHelper::startsWith('/', $nextToken)) {
  97. // we know we are on a DOS style platform and the next path
  98. // starts with a slash or backslash, so we know this is a
  99. // drive spec
  100. $token .= ':' . $nextToken;
  101. } else {
  102. // store the token just read for next time
  103. $this->lookahead = $nextToken;
  104. }
  105. }
  106. return $token;
  107. }
  108. /**
  109. * Non StringTokenizer function, that indicates whether the specified path is contained in loaded tokens.
  110. * We can do this easily because in PHP implimentation we're using arrays.
  111. * @param string $path path to search for.
  112. * @return boolean
  113. */
  114. public function contains($path) {
  115. return in_array($path, $this->tokens, true);
  116. }
  117. }