7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
16 * @package Zend_Search_Lucene
18 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Memory.php 16971 2009-07-22 18:05:45Z mikaelkael $
23 /** Zend_Search_Lucene_Storage_File */
24 require_once 'Zend/Search/Lucene/Storage/File.php';
28 * @package Zend_Search_Lucene
30 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
31 * @license http://framework.zend.com/license/new-bsd New BSD License
33 class Zend_Search_Lucene_Storage_File_Memory extends Zend_Search_Lucene_Storage_File
47 private $_position = 0;
55 public function __construct($data)
61 * Reads $length number of bytes at the current position in the
62 * file and advances the file pointer.
64 * @param integer $length
67 protected function _fread($length = 1)
69 $returnValue = substr($this->_data, $this->_position, $length);
70 $this->_position += $length;
76 * Sets the file position indicator and advances the file pointer.
77 * The new position, measured in bytes from the beginning of the file,
78 * is obtained by adding offset to the position specified by whence,
79 * whose values are defined as follows:
80 * SEEK_SET - Set position equal to offset bytes.
81 * SEEK_CUR - Set position to current location plus offset.
82 * SEEK_END - Set position to end-of-file plus offset. (To move to
83 * a position before the end-of-file, you need to pass a negative value
85 * Upon success, returns 0; otherwise, returns -1
87 * @param integer $offset
88 * @param integer $whence
91 public function seek($offset, $whence=SEEK_SET)
95 $this->_position = $offset;
99 $this->_position += $offset;
103 $this->_position = strlen($this->_data);
104 $this->_position += $offset;
117 public function tell()
119 return $this->_position;
125 * Returns true on success or false on failure.
129 public function flush()
137 * Writes $length number of bytes (all, if $length===null) to the end
140 * @param string $data
141 * @param integer $length
143 protected function _fwrite($data, $length=null)
145 // We do not need to check if file position points to the end of "file".
146 // Only append operation is supported now
148 if ($length !== null) {
149 $this->_data .= substr($data, 0, $length);
151 $this->_data .= $data;
154 $this->_position = strlen($this->_data);
160 * Lock type may be a LOCK_SH (shared lock) or a LOCK_EX (exclusive lock)
162 * @param integer $lockType
165 public function lock($lockType, $nonBlockinLock = false)
167 // Memory files can't be shared
176 public function unlock()
178 // Memory files can't be shared
183 * Reads a byte from the current position in the file
184 * and advances the file pointer.
188 public function readByte()
190 return ord($this->_data[$this->_position++]);
194 * Writes a byte to the end of the file.
196 * @param integer $byte
198 public function writeByte($byte)
200 // We do not need to check if file position points to the end of "file".
201 // Only append operation is supported now
203 $this->_data .= chr($byte);
204 $this->_position = strlen($this->_data);
210 * Read num bytes from the current position in the file
211 * and advances the file pointer.
213 * @param integer $num
216 public function readBytes($num)
218 $returnValue = substr($this->_data, $this->_position, $num);
219 $this->_position += $num;
225 * Writes num bytes of data (all, if $num===null) to the end
228 * @param string $data
229 * @param integer $num
231 public function writeBytes($data, $num=null)
233 // We do not need to check if file position points to the end of "file".
234 // Only append operation is supported now
237 $this->_data .= substr($data, 0, $num);
239 $this->_data .= $data;
242 $this->_position = strlen($this->_data);
247 * Reads an integer from the current position in the file
248 * and advances the file pointer.
252 public function readInt()
254 $str = substr($this->_data, $this->_position, 4);
255 $this->_position += 4;
257 return ord($str[0]) << 24 |
265 * Writes an integer to the end of file.
267 * @param integer $value
269 public function writeInt($value)
271 // We do not need to check if file position points to the end of "file".
272 // Only append operation is supported now
274 settype($value, 'integer');
275 $this->_data .= chr($value>>24 & 0xFF) .
276 chr($value>>16 & 0xFF) .
277 chr($value>>8 & 0xFF) .
280 $this->_position = strlen($this->_data);
285 * Returns a long integer from the current position in the file
286 * and advances the file pointer.
289 * @throws Zend_Search_Lucene_Exception
291 public function readLong()
294 * Check, that we work in 64-bit mode.
295 * fseek() uses long for offset. Thus, largest index segment file size in 32bit mode is 2Gb
297 if (PHP_INT_SIZE > 4) {
298 $str = substr($this->_data, $this->_position, 8);
299 $this->_position += 8;
301 return ord($str[0]) << 56 |
310 return $this->readLong32Bit();
315 * Writes long integer to the end of file
317 * @param integer $value
318 * @throws Zend_Search_Lucene_Exception
320 public function writeLong($value)
322 // We do not need to check if file position points to the end of "file".
323 // Only append operation is supported now
326 * Check, that we work in 64-bit mode.
327 * fseek() and ftell() use long for offset. Thus, largest index segment file size in 32bit mode is 2Gb
329 if (PHP_INT_SIZE > 4) {
330 settype($value, 'integer');
331 $this->_data .= chr($value>>56 & 0xFF) .
332 chr($value>>48 & 0xFF) .
333 chr($value>>40 & 0xFF) .
334 chr($value>>32 & 0xFF) .
335 chr($value>>24 & 0xFF) .
336 chr($value>>16 & 0xFF) .
337 chr($value>>8 & 0xFF) .
340 $this->writeLong32Bit($value);
343 $this->_position = strlen($this->_data);
348 * Returns a long integer from the current position in the file,
349 * advances the file pointer and return it as float (for 32-bit platforms).
351 * @return integer|float
352 * @throws Zend_Search_Lucene_Exception
354 public function readLong32Bit()
356 $wordHigh = $this->readInt();
357 $wordLow = $this->readInt();
359 if ($wordHigh & (int)0x80000000) {
360 // It's a negative value since the highest bit is set
361 if ($wordHigh == (int)0xFFFFFFFF && ($wordLow & (int)0x80000000)) {
364 require_once 'Zend/Search/Lucene/Exception.php';
365 throw new Zend_Search_Lucene_Exception('Long integers lower than -2147483648 (0x80000000) are not supported on 32-bit platforms.');
371 // Value is large than 0x7FFF FFFF. Represent low word as float.
372 $wordLow &= 0x7FFFFFFF;
373 $wordLow += (float)0x80000000;
376 if ($wordHigh == 0) {
377 // Return value as integer if possible
381 return $wordHigh*(float)0x100000000/* 0x00000001 00000000 */ + $wordLow;
386 * Writes long integer to the end of file (32-bit platforms implementation)
388 * @param integer|float $value
389 * @throws Zend_Search_Lucene_Exception
391 public function writeLong32Bit($value)
393 if ($value < (int)0x80000000) {
394 require_once 'Zend/Search/Lucene/Exception.php';
395 throw new Zend_Search_Lucene_Exception('Long integers lower than -2147483648 (0x80000000) are not supported on 32-bit platforms.');
399 $wordHigh = (int)0xFFFFFFFF;
400 $wordLow = (int)$value;
402 $wordHigh = (int)($value/(float)0x100000000/* 0x00000001 00000000 */);
403 $wordLow = $value - $wordHigh*(float)0x100000000/* 0x00000001 00000000 */;
405 if ($wordLow > 0x7FFFFFFF) {
406 // Highest bit of low word is set. Translate it to the corresponding negative integer value
407 $wordLow -= 0x80000000;
408 $wordLow |= 0x80000000;
412 $this->writeInt($wordHigh);
413 $this->writeInt($wordLow);
417 * Returns a variable-length integer from the current
418 * position in the file and advances the file pointer.
422 public function readVInt()
424 $nextByte = ord($this->_data[$this->_position++]);
425 $val = $nextByte & 0x7F;
427 for ($shift=7; ($nextByte & 0x80) != 0; $shift += 7) {
428 $nextByte = ord($this->_data[$this->_position++]);
429 $val |= ($nextByte & 0x7F) << $shift;
435 * Writes a variable-length integer to the end of file.
437 * @param integer $value
439 public function writeVInt($value)
441 // We do not need to check if file position points to the end of "file".
442 // Only append operation is supported now
444 settype($value, 'integer');
445 while ($value > 0x7F) {
446 $this->_data .= chr( ($value & 0x7F)|0x80 );
449 $this->_data .= chr($value);
451 $this->_position = strlen($this->_data);
456 * Reads a string from the current position in the file
457 * and advances the file pointer.
461 public function readString()
463 $strlen = $this->readVInt();
468 * This implementation supports only Basic Multilingual Plane
469 * (BMP) characters (from 0x0000 to 0xFFFF) and doesn't support
470 * "supplementary characters" (characters whose code points are
471 * greater than 0xFFFF)
472 * Java 2 represents these characters as a pair of char (16-bit)
473 * values, the first from the high-surrogates range (0xD800-0xDBFF),
474 * the second from the low-surrogates range (0xDC00-0xDFFF). Then
475 * they are encoded as usual UTF-8 characters in six bytes.
476 * Standard UTF-8 representation uses four bytes for supplementary
480 $str_val = substr($this->_data, $this->_position, $strlen);
481 $this->_position += $strlen;
483 for ($count = 0; $count < $strlen; $count++ ) {
484 if (( ord($str_val[$count]) & 0xC0 ) == 0xC0) {
486 if (ord($str_val[$count]) & 0x20 ) {
489 // Never used. Java2 doesn't encode strings in four bytes
490 if (ord($str_val[$count]) & 0x10 ) {
494 $str_val .= substr($this->_data, $this->_position, $addBytes);
495 $this->_position += $addBytes;
496 $strlen += $addBytes;
498 // Check for null character. Java2 encodes null character
500 if (ord($str_val[$count]) == 0xC0 &&
501 ord($str_val[$count+1]) == 0x80 ) {
502 $str_val[$count] = 0;
503 $str_val = substr($str_val,0,$count+1)
504 . substr($str_val,$count+2);
515 * Writes a string to the end of file.
518 * @throws Zend_Search_Lucene_Exception
520 public function writeString($str)
523 * This implementation supports only Basic Multilingual Plane
524 * (BMP) characters (from 0x0000 to 0xFFFF) and doesn't support
525 * "supplementary characters" (characters whose code points are
526 * greater than 0xFFFF)
527 * Java 2 represents these characters as a pair of char (16-bit)
528 * values, the first from the high-surrogates range (0xD800-0xDBFF),
529 * the second from the low-surrogates range (0xDC00-0xDFFF). Then
530 * they are encoded as usual UTF-8 characters in six bytes.
531 * Standard UTF-8 representation uses four bytes for supplementary
535 // We do not need to check if file position points to the end of "file".
536 // Only append operation is supported now
538 // convert input to a string before iterating string characters
539 settype($str, 'string');
541 $chars = $strlen = strlen($str);
542 $containNullChars = false;
544 for ($count = 0; $count < $strlen; $count++ ) {
546 * String is already in Java 2 representation.
547 * We should only calculate actual string length and replace
550 if ((ord($str[$count]) & 0xC0) == 0xC0) {
552 if (ord($str[$count]) & 0x20 ) {
555 // Never used. Java2 doesn't encode strings in four bytes
556 // and we dont't support non-BMP characters
557 if (ord($str[$count]) & 0x10 ) {
563 if (ord($str[$count]) == 0 ) {
564 $containNullChars = true;
571 require_once 'Zend/Search/Lucene/Exception.php';
572 throw new Zend_Search_Lucene_Exception('Invalid UTF-8 string');
575 $this->writeVInt($chars);
576 if ($containNullChars) {
577 $this->_data .= str_replace($str, "\x00", "\xC0\x80");
580 $this->_data .= $str;
583 $this->_position = strlen($this->_data);
588 * Reads binary data from the current position in the file
589 * and advances the file pointer.
593 public function readBinary()
595 $length = $this->readVInt();
596 $returnValue = substr($this->_data, $this->_position, $length);
597 $this->_position += $length;