You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.6 KiB
136 lines
3.6 KiB
2 years ago
|
<?php
|
||
|
/*
|
||
|
* Copyright 2018 MongoDB, Inc.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
namespace MongoDB\Model;
|
||
|
|
||
|
use MongoDB\Exception\UnexpectedValueException;
|
||
|
use MongoDB\Model\BSONDocument;
|
||
|
use Iterator;
|
||
|
|
||
|
/**
|
||
|
* Iterator for BSON documents.
|
||
|
*/
|
||
|
class BSONIterator implements Iterator
|
||
|
{
|
||
|
private static $bsonSize = 4;
|
||
|
|
||
|
private $buffer;
|
||
|
private $bufferLength;
|
||
|
private $current;
|
||
|
private $key = 0;
|
||
|
private $position = 0;
|
||
|
private $options;
|
||
|
|
||
|
/**
|
||
|
* Constructs a BSON Iterator.
|
||
|
*
|
||
|
* Supported options:
|
||
|
*
|
||
|
* * typeMap (array): Type map for BSON deserialization.
|
||
|
*
|
||
|
* @internal
|
||
|
* @see http://php.net/manual/en/function.mongodb.bson-tophp.php
|
||
|
* @param string $data Concatenated, valid, BSON-encoded documents
|
||
|
* @param array $options Iterator options
|
||
|
* @throws InvalidArgumentException for parameter/option parsing errors
|
||
|
*/
|
||
|
public function __construct($data, array $options = [])
|
||
|
{
|
||
|
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
|
||
|
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
|
||
|
}
|
||
|
|
||
|
if ( ! isset($options['typeMap'])) {
|
||
|
$options['typeMap'] = [];
|
||
|
}
|
||
|
|
||
|
$this->buffer = $data;
|
||
|
$this->bufferLength = strlen($data);
|
||
|
$this->options = $options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see http://php.net/iterator.current
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function current()
|
||
|
{
|
||
|
return $this->current;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see http://php.net/iterator.key
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function key()
|
||
|
{
|
||
|
return $this->key;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see http://php.net/iterator.next
|
||
|
* @return void
|
||
|
*/
|
||
|
public function next()
|
||
|
{
|
||
|
$this->key++;
|
||
|
$this->current = null;
|
||
|
$this->advance();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see http://php.net/iterator.rewind
|
||
|
* @return void
|
||
|
*/
|
||
|
public function rewind()
|
||
|
{
|
||
|
$this->key = 0;
|
||
|
$this->position = 0;
|
||
|
$this->current = null;
|
||
|
$this->advance();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see http://php.net/iterator.valid
|
||
|
* @return boolean
|
||
|
*/
|
||
|
public function valid()
|
||
|
{
|
||
|
return $this->current !== null;
|
||
|
}
|
||
|
|
||
|
private function advance()
|
||
|
{
|
||
|
if ($this->position === $this->bufferLength) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (($this->bufferLength - $this->position) < self::$bsonSize) {
|
||
|
throw new UnexpectedValueException(sprintf('Expected at least %d bytes; %d remaining', self::$bsonSize, $this->bufferLength - $this->position));
|
||
|
}
|
||
|
|
||
|
list(,$documentLength) = unpack('V', substr($this->buffer, $this->position, self::$bsonSize));
|
||
|
|
||
|
if (($this->bufferLength - $this->position) < $documentLength) {
|
||
|
throw new UnexpectedValueException(sprintf('Expected %d bytes; %d remaining', $documentLength, $this->bufferLength - $this->position));
|
||
|
}
|
||
|
|
||
|
$this->current = \MongoDB\BSON\toPHP(substr($this->buffer, $this->position, $documentLength), $this->options['typeMap']);
|
||
|
$this->position += $documentLength;
|
||
|
}
|
||
|
}
|