isWhitespace() public static method

Checks if the given character is a whitespace.
public static isWhitespace ( string $str ) : boolean
$str string String to be checked.
return boolean
Example #1
0
 public function testIsWhitespace()
 {
     $this->assertTrue(Context::isWhitespace(" "));
     $this->assertTrue(Context::isWhitespace("\r"));
     $this->assertTrue(Context::isWhitespace("\n"));
     $this->assertTrue(Context::isWhitespace("\t"));
     $this->assertFalse(Context::isWhitespace("a"));
     $this->assertFalse(Context::isWhitespace("\\b"));
     $this->assertFalse(Context::isWhitespace("\\u1000"));
 }
Example #2
0
 /**
  * Extracts a statement from the buffer.
  *
  * @param bool $end Whether the end of the buffer was reached.
  *
  * @return string
  */
 public function extract($end = false)
 {
     /**
      * The last parsed position.
      *
      * This is statically defined because it is not used outside anywhere
      * outside this method and there is probably a (minor) performance
      * improvement to it.
      *
      * @var int
      */
     static $i = 0;
     if (empty($this->query)) {
         return false;
     }
     /**
      * The length of the buffer.
      * @var int $len
      */
     $len = strlen($this->query);
     /**
      * The last index of the string that is going to be parsed.
      *
      * There must be a few characters left in the buffer so the parser can
      * avoid confusing some symbols that may have multiple meanings.
      *
      * For example, if the buffer ends in `-` that may be an operator or the
      * beginning of a comment.
      *
      * Another example if the buffer ends in `DELIMITE`. The parser is going
      * to require a few more characters because that may be a part of the
      * `DELIMITER` keyword or just a column named `DELIMITE`.
      *
      * Those extra characters are required only if there is more data
      * expected (the end of the buffer was not reached).
      *
      * @var int $loopLen
      */
     $loopLen = $end ? $len : $len - 16;
     for (; $i < $loopLen; ++$i) {
         /*
          * Handling special parses statuses.
          */
         if ($this->status === static::STATUS_STRING_SINGLE_QUOTES) {
             // Single-quoted strings like 'foo'.
             if ($this->query[$i - 1] != '\\' && $this->query[$i] === '\'') {
                 $this->status = 0;
             }
             $this->current .= $this->query[$i];
             continue;
         } elseif ($this->status === static::STATUS_STRING_DOUBLE_QUOTES) {
             // Double-quoted strings like "bar".
             if ($this->query[$i - 1] != '\\' && $this->query[$i] === '"') {
                 $this->status = 0;
             }
             $this->current .= $this->query[$i];
             continue;
         } elseif ($this->status === static::STATUS_STRING_BACKTICK) {
             if ($this->query[$i] === '`') {
                 $this->status = 0;
             }
             $this->current .= $this->query[$i];
             continue;
         } elseif ($this->status === static::STATUS_COMMENT_BASH || $this->status === static::STATUS_COMMENT_SQL) {
             // Bash-like (#) or SQL-like (-- ) comments end in new line.
             if ($this->query[$i] === "\n") {
                 $this->status = 0;
             }
             continue;
         } elseif ($this->status === static::STATUS_COMMENT_C) {
             // C-like comments end in */.
             if ($this->query[$i - 1] === '*' && $this->query[$i] === '/') {
                 $this->status = 0;
             }
             continue;
         }
         /*
          * Checking if a string started.
          */
         if ($this->query[$i] === '\'') {
             $this->status = static::STATUS_STRING_SINGLE_QUOTES;
             $this->current .= $this->query[$i];
             continue;
         } elseif ($this->query[$i] === '"') {
             $this->status = static::STATUS_STRING_DOUBLE_QUOTES;
             $this->current .= $this->query[$i];
             continue;
         } elseif ($this->query[$i] === '`') {
             $this->status = static::STATUS_STRING_BACKTICK;
             $this->current .= $this->query[$i];
             continue;
         }
         /*
          * Checking if a comment started.
          */
         if ($this->query[$i] === '#') {
             $this->status = static::STATUS_COMMENT_BASH;
             continue;
         } elseif ($i + 2 < $len && $this->query[$i] === '-' && $this->query[$i + 1] === '-' && Context::isWhitespace($this->query[$i + 2])) {
             $this->status = static::STATUS_COMMENT_SQL;
             continue;
         } elseif ($i + 2 < $len && $this->query[$i] === '/' && $this->query[$i + 1] === '*' && $this->query[$i + 2] !== '!') {
             $this->status = static::STATUS_COMMENT_C;
             continue;
         }
         /*
          * Handling `DELIMITER` statement.
          *
          * The code below basically checks for
          *     `strtoupper(substr($this->query, $i, 9)) === 'DELIMITER'`
          *
          * This optimization makes the code about 3 times faster.
          */
         if ($i + 9 < $len && ($this->query[$i] === 'D' || $this->query[$i] === 'd') && ($this->query[$i + 1] === 'E' || $this->query[$i + 1] === 'e') && ($this->query[$i + 2] === 'L' || $this->query[$i + 2] === 'l') && ($this->query[$i + 3] === 'I' || $this->query[$i + 3] === 'i') && ($this->query[$i + 4] === 'M' || $this->query[$i + 4] === 'm') && ($this->query[$i + 5] === 'I' || $this->query[$i + 5] === 'i') && ($this->query[$i + 6] === 'T' || $this->query[$i + 6] === 't') && ($this->query[$i + 7] === 'E' || $this->query[$i + 7] === 'e') && ($this->query[$i + 8] === 'R' || $this->query[$i + 8] === 'r') && Context::isWhitespace($this->query[$i + 9])) {
             // Saving the current index to be able to revert any parsing
             // done in this block.
             $iBak = $i;
             $i += 9;
             // Skipping `DELIMITER`.
             // Skipping whitespaces.
             while ($i < $len && Context::isWhitespace($this->query[$i])) {
                 ++$i;
             }
             // Parsing the delimiter.
             $delimiter = '';
             while ($i < $len && !Context::isWhitespace($this->query[$i])) {
                 $delimiter .= $this->query[$i++];
             }
             // Checking if the delimiter definition ended.
             if ($delimiter != '' && ($i < $len && Context::isWhitespace($this->query[$i]) || $i === $len && $end)) {
                 // Saving the delimiter.
                 $this->setDelimiter($delimiter);
                 // Whether this statement should be returned or not.
                 $ret = '';
                 if (!empty($this->options['parse_delimiter'])) {
                     // Appending the `DELIMITER` statement that was just
                     // found to the current statement.
                     $ret = trim($this->current . ' ' . substr($this->query, $iBak, $i - $iBak));
                 }
                 // Removing the statement that was just extracted from the
                 // query.
                 $this->query = substr($this->query, $i);
                 $i = 0;
                 // Resetting the current statement.
                 $this->current = '';
                 return $ret;
             }
             // Incomplete statement. Reverting
             $i = $iBak;
             return false;
         }
         /*
          * Checking if the current statement finished.
          *
          * The first letter of the delimiter is being checked as an
          * optimization. This code is almost as fast as the one above.
          *
          * There is no point in checking if two strings match if not even
          * the first letter matches.
          */
         if ($this->query[$i] === $this->delimiter[0] && ($this->delimiterLen === 1 || substr($this->query, $i, $this->delimiterLen) === $this->delimiter)) {
             // Saving the statement that just ended.
             $ret = $this->current;
             // If needed, adds a delimiter at the end of the statement.
             if (!empty($this->options['add_delimiter'])) {
                 $ret .= $this->delimiter;
             }
             // Removing the statement that was just extracted from the
             // query.
             $this->query = substr($this->query, $i + $this->delimiterLen);
             $i = 0;
             // Resetting the current statement.
             $this->current = '';
             // Returning the statement.
             return trim($ret);
         }
         /*
          * Appending current character to current statement.
          */
         $this->current .= $this->query[$i];
     }
     if ($end && $i === $len) {
         // If the end of the buffer was reached, the buffer is emptied and
         // the current statement that was extracted is returned.
         $ret = $this->current;
         // Emptying the buffer.
         $this->query = '';
         $i = 0;
         // Resetting the current statement.
         $this->current = '';
         // Returning the statement.
         return trim($ret);
     }
     return '';
 }
Example #3
0
 /**
  * Parses a whitespace.
  *
  * @return Token
  */
 public function parseWhitespace()
 {
     $token = $this->str[$this->last];
     if (!Context::isWhitespace($token)) {
         return null;
     }
     while (++$this->last < $this->len && Context::isWhitespace($this->str[$this->last])) {
         $token .= $this->str[$this->last];
     }
     --$this->last;
     return new Token($token, Token::TYPE_WHITESPACE);
 }