/** * Creates a new text token from a stream * * @param Jstewmc\Stream\Stream $stream a stream of characters * @return Jstewmc\Rtf\Token\Text|false * @since 0.1.0 * @since 0.2.0 renamed from createFromSource() to createFromStream(); * replaced argument $characters, an array of characters, with $stream, an * instance of Jstewmc\Stream */ public static function createFromStream(\Jstewmc\Stream\Stream $stream) { $token = false; // loop through the characters until a group-open, group-close, control word, // or control symbol occurs and append the plain-text // $text = ''; while (false !== ($character = $stream->current())) { // if the current characer isn't ignored if (!in_array($character, ["\n", "\r", "\f", ""])) { // if the current character is a backslash if ($character == '\\') { // if the next character exists if (false !== ($next = $stream->next())) { // if the next character is a control character if (in_array($next, ['\\', '{', '}'])) { // it's a literal control character // ignore the backslash and append the character // $text .= $next; } else { // otherwise, the backslash is the start of a control word // rollback two characters (i.e., put the pointer on the character before // the control word's backslash) // $stream->previous(); $stream->previous(); break; } } else { // hmmm, do nothing? } } elseif ($character == '{' || $character == '}') { // otherwise, the current group is closing or a sub-group is opening // rollback to the previous character (so it isn't consumed) // $stream->previous(); break; } else { // otherwise, it's text! $text .= $character; } } // advance to the next character $stream->next(); } // if $text is not empty, create a new token // keep in mind, empty() will consider '0'to be empty, and it's a valid value // if (!empty($text) || $text === '0') { $token = new Text($text); } return $token; }
/** * Lexes the tab character ("\t") * * Tab characters should be converted to "\tab" control words. * * @param Jstewmc\Stream\Stream $stream the character stream * @return Jstewmc\Rtf\Token\Control\Word * @throws InvalidArgumentException if the current character in $stream is not * the tab character * @since 0.2.0 */ protected function lexTab(\Jstewmc\Stream\Stream $stream) { if ($stream->current() !== "\t") { throw new \InvalidArgumentException(__METHOD__ . "() expects the current character in the stream to be a tab character"); } return new Token\Control\Word('tab'); }
/** * Creates a control symbol token from stream * * @param Jstewmc\Stream $stream a stream of characters (the current character * must be the backslash character, and the next character should be non- * alphanumeric) * @return Jstewmc\Rtf\Token\Control\Symbol|false * @throws InvalidArgumentException if the current character in $stream is * not a backslash * @throws InvalidArgumentException if the next character in $stream is not * a non-alphanumeric character * @since 0.1.0 * @since 0.2.0 renamed from createFromSource() to createFromStream; replaced * argument $characters, an array of characters, with $stream, an instance * of Jstewmc\STream */ public static function createFromStream(\Jstewmc\Stream\Stream $stream) { $symbol = false; // if a current character exists if ($stream->current()) { // if the current character is a backslash if ($stream->current() === '\\') { // if the next character exists if ($stream->next() !== false) { // if the now current character is not alphanumeric if (!ctype_alnum($stream->current())) { // create a new control symbol $symbol = new Symbol($stream->current()); // if the current character is an apostrophe, get the symbol's parameter if ($stream->current() === '\'') { $parameter = $stream->next() . $stream->next(); $symbol->setParameter($parameter); } // if the next character is a space, the control symbol is space-delimited, // and we should set the flag; otherwise, it's not, and we should rollback // to leave the pointer on the last character in the token (i.e., the // symbol) // if ($stream->next() === ' ') { $symbol->setIsSpaceDelimited(true); } else { $symbol->setIsSpaceDelimited(false); $stream->previous(); } } else { throw new \InvalidArgumentException(__METHOD__ . "() expects the next element in parameter one, characters, to " . "be a non-alphanumeric character"); } } else { // hmm, do nothing? } } else { throw new \InvalidArgumentException(__METHOD__ . "() expects the current element in parameter one, characters, to " . "be the backslash character"); } } return $symbol; }
/** * Reads a control word's parameter from the characters stream * * @param Jstewmc\Stream $stream a stream of characters (the current character * must be a digit or hyphen) * @return int * @throws InvalidArgumentException if the current character in $stream is * not a digit or hyphen * @since 0.1.0 * @since 0.2.0 replace argument $characters, an array of characters, with $stream * an instance of Jstewmc\Stream */ protected static function readParameter(\Jstewmc\Stream\Stream $stream) { $parameter = ''; // if the current character is a digit or hyphen ("-") if (ctype_digit($stream->current()) || $stream->current() == '-') { // determine if the parameter is negative $isNegative = $stream->current() == '-'; // if the number is negative, consume the hyphen if ($isNegative) { $stream->next(); } // loop through the digits and append them to the parameter while (ctype_digit($stream->current())) { $parameter .= $stream->current(); $stream->next(); } // evaluate the parameter's numeric value $parameter = +$parameter; // if the parameter is negative, negate it if ($isNegative) { $parameter = -$parameter; } } else { throw new \InvalidArgumentException(__METHOD__ . "() expects the current element in parameter one, characters, " . "to be a digit or hyphen"); } return $parameter; }
/** * reset() should reset the internal chunk pointer */ public function testReset() { $chunker = new Chunker\Text('foo'); $stream = new Stream($chunker); $stream->next(); // returns "o" $stream->next(); // returns "o" $this->assertEquals('o', $stream->current()); $stream->reset(); $this->assertEquals('f', $stream->current()); return; }