Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Zend Framework
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to version 1.0 of the Zend Framework
8
 * license, that is bundled with this package in the file LICENSE, and
9
 * is available through the world-wide-web at the following URL:
10
 * http://www.zend.com/license/framework/1_0.txt. If you did not receive
11
 * a copy of the Zend Framework license and are unable to obtain it
12
 * through the world-wide-web, please send a note to license@zend.com
13
 * so we can mail you a copy immediately.
14
 *
15
 * @package    Zend_Search_Lucene
16
 * @subpackage Storage
17
 * @copyright  Copyright (c) 2005-2006 Zend Technologies USA Inc. (http://www.zend.com)
18
 * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0
19
 */
20
 
21
 
22
/**
23
 * @package    Zend_Search_Lucene
24
 * @subpackage Storage
25
 * @copyright  Copyright (c) 2005-2006 Zend Technologies USA Inc. (http://www.zend.com)
26
 * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0
27
 */
28
abstract class Zend_Search_Lucene_Storage_File
29
{
30
 
31
    /**
32
     * Class constructor.  Open the file.
33
     */
34
    abstract public function __construct($filename, $mode='r');
35
 
36
 
37
    /**
38
     * Reads $length number of bytes at the current position in the
39
     * file and advances the file pointer.
40
     *
41
     * @param integer $length
42
     * @return string
43
     */
44
    abstract protected function _fread($length=1);
45
 
46
 
47
    /**
48
     * Sets the file position indicator and advances the file pointer.
49
     * The new position, measured in bytes from the beginning of the file,
50
     * is obtained by adding offset to the position specified by whence,
51
     * whose values are defined as follows:
52
     * SEEK_SET - Set position equal to offset bytes.
53
     * SEEK_CUR - Set position to current location plus offset.
54
     * SEEK_END - Set position to end-of-file plus offset. (To move to
55
     * a position before the end-of-file, you need to pass a negative value
56
     * in offset.)
57
     * Upon success, returns 0; otherwise, returns -1
58
     *
59
     * @param integer $offset
60
     * @param integer $whence
61
     * @return integer
62
     */
63
    abstract public function seek($offset, $whence=SEEK_SET);
64
 
65
    /**
66
     * Get file position.
67
     *
68
     * @return integer
69
     */
70
    abstract public function tell();
71
 
72
    /**
73
     * Writes $length number of bytes (all, if $length===null) to the end
74
     * of the file.
75
     *
76
     * @param string $data
77
     * @param integer $length
78
     */
79
    abstract protected function _fwrite($data, $length=null);
80
 
81
 
82
    /**
83
     * Reads a byte from the current position in the file
84
     * and advances the file pointer.
85
     *
86
     * @return integer
87
     */
88
    public function readByte()
89
    {
90
        return ord($this->_fread(1));
91
    }
92
 
93
    /**
94
     * Writes a byte to the end of the file.
95
     *
96
     * @param integer $byte
97
     */
98
    public function writeByte($byte)
99
    {
100
        return $this->_fwrite(chr($byte), 1);
101
    }
102
 
103
    /**
104
     * Read num bytes from the current position in the file
105
     * and advances the file pointer.
106
     *
107
     * @param integer $num
108
     * @return string
109
     */
110
    public function readBytes($num)
111
    {
112
        return $this->_fread($num);
113
    }
114
 
115
    /**
116
     * Writes num bytes of data (all, if $num===null) to the end
117
     * of the file.
118
     *
119
     * @param string $data
120
     * @param integer $num
121
     */
122
    public function writeBytes($data, $num=null)
123
    {
124
        $this->_fwrite($data, $num);
125
    }
126
 
127
 
128
    /**
129
     * Reads an integer from the current position in the file
130
     * and advances the file pointer.
131
     *
132
     * @return integer
133
     */
134
    public function readInt()
135
    {
136
        $str = $this->_fread(4);
137
 
138
        return  ord($str{0}) << 24 |
139
                ord($str{1}) << 16 |
140
                ord($str{2}) << 8  |
141
                ord($str{3});
142
    }
143
 
144
 
145
    /**
146
     * Writes an integer to the end of file.
147
     *
148
     * @param integer $value
149
     */
150
    public function writeInt($value)
151
    {
152
        settype($value, 'integer');
153
        $this->_fwrite( chr($value>>24 & 0xFF) .
154
                        chr($value>>16 & 0xFF) .
155
                        chr($value>>8  & 0xFF) .
156
                        chr($value     & 0xFF),   4  );
157
    }
158
 
159
 
160
    /**
161
     * Returns a long integer from the current position in the file
162
     * and advances the file pointer.
163
     *
164
     * @return integer
165
     */
166
    public function readLong()
167
    {
168
        $str = $this->_fread(8);
169
 
170
        /**
171
         * PHP uses long as largest integer. fseek() uses long for offset.
172
         * long has 4 bytes in a lot of systems. 4 bytes are discarded to prevent
173
         * conversion to float.
174
         * So, largest index segment file is 2Gb
175
         */
176
        return  /* ord($str{0}) << 56  | */
177
                /* ord($str{1}) << 48  | */
178
                /* ord($str{2}) << 40  | */
179
                /* ord($str{3}) << 32  | */
180
                ord($str{4}) << 24  |
181
                ord($str{5}) << 16  |
182
                ord($str{6}) << 8   |
183
                ord($str{7});
184
    }
185
 
186
    /**
187
     * Writes long integer to the end of file
188
     *
189
     * @param integer $value
190
     */
191
    public function writeLong($value)
192
    {
193
        /**
194
         * PHP uses long as largest integer. fseek() uses long for offset.
195
         * long has 4 bytes in a lot of systems. 4 bytes are discarded to prevent
196
         * conversion to float.
197
         * So, largest index segment file is 2Gb
198
         */
199
        settype($value, 'integer');
200
        $this->_fwrite( "\x00\x00\x00\x00"     .
201
                        chr($value>>24 & 0xFF) .
202
                        chr($value>>16 & 0xFF) .
203
                        chr($value>>8  & 0xFF) .
204
                        chr($value     & 0xFF),   8  );
205
    }
206
 
207
 
208
 
209
    /**
210
     * Returns a variable-length integer from the current
211
     * position in the file and advances the file pointer.
212
     *
213
     * @return integer
214
     */
215
    public function readVInt()
216
    {
217
        $nextByte = ord($this->_fread(1));
218
        $val = $nextByte & 0x7F;
219
 
220
        for ($shift=7; ($nextByte & 0x80) != 0; $shift += 7) {
221
            $nextByte = ord($this->_fread(1));
222
            $val |= ($nextByte & 0x7F) << $shift;
223
        }
224
        return $val;
225
    }
226
 
227
    /**
228
     * Writes a variable-length integer to the end of file.
229
     *
230
     * @param integer $value
231
     */
232
    public function writeVInt($value)
233
    {
234
        settype($value, 'integer');
235
        while ($value > 0x7F) {
236
            $this->_fwrite(chr( ($value & 0x7F)|0x80 ));
237
            $value >>= 7;
238
        }
239
        $this->_fwrite(chr($value));
240
    }
241
 
242
 
243
    /**
244
     * Reads a string from the current position in the file
245
     * and advances the file pointer.
246
     *
247
     * @return string
248
     */
249
    public function readString()
250
    {
251
        $strlen = $this->readVInt();
252
        if ($strlen == 0) {
253
            return '';
254
        } else {
255
            /**
256
             * This implementation supports only Basic Multilingual Plane
257
             * (BMP) characters (from 0x0000 to 0xFFFF) and doesn't support
258
             * "supplementary characters" (characters whose code points are
259
             * greater than 0xFFFF)
260
             * Java 2 represents these characters as a pair of char (16-bit)
261
             * values, the first from the high-surrogates range (0xD800-0xDBFF),
262
             * the second from the low-surrogates range (0xDC00-0xDFFF). Then
263
             * they are encoded as usual UTF-8 characters in six bytes.
264
             * Standard UTF-8 representation uses four bytes for supplementary
265
             * characters.
266
             */
267
 
268
            $str_val = $this->_fread($strlen);
269
 
270
            for ($count = 0; $count < $strlen; $count++ ) {
271
                if (( ord($str_val{$count}) & 0xC0 ) == 0xC0) {
272
                    $addBytes = 1;
273
                    if (ord($str_val{$count}) & 0x20 ) {
274
                        $addBytes++;
275
 
276
                        // Never used. Java2 doesn't encode strings in four bytes
277
                        if (ord($str_val{$count}) & 0x10 ) {
278
                            $addBytes++;
279
                        }
280
                    }
281
                    $str_val .= $this->_fread($addBytes);
282
                    $strlen += $addBytes;
283
 
284
                    // Check for null character. Java2 encodes null character
285
                    // in two bytes.
286
                    if (ord($str_val{$count})   == 0xC0 &&
287
                        ord($str_val{$count+1}) == 0x80   ) {
288
                        $str_val{$count} = 0;
289
                        $str_val = substr($str_val,0,$count+1)
290
                                 . substr($str_val,$count+2);
291
                    }
292
                    $count += $addBytes;
293
                }
294
            }
295
 
296
            return $str_val;
297
        }
298
    }
299
 
300
    /**
301
     * Writes a string to the end of file.
302
     *
303
     * @param string $str
304
     * @throws Zend_Search_Lucene_Exception
305
     */
306
    public function writeString($str)
307
    {
308
        /**
309
         * This implementation supports only Basic Multilingual Plane
310
         * (BMP) characters (from 0x0000 to 0xFFFF) and doesn't support
311
         * "supplementary characters" (characters whose code points are
312
         * greater than 0xFFFF)
313
         * Java 2 represents these characters as a pair of char (16-bit)
314
         * values, the first from the high-surrogates range (0xD800-0xDBFF),
315
         * the second from the low-surrogates range (0xDC00-0xDFFF). Then
316
         * they are encoded as usual UTF-8 characters in six bytes.
317
         * Standard UTF-8 representation uses four bytes for supplementary
318
         * characters.
319
         */
320
 
321
        // convert input to a string before iterating string characters
322
        settype($str, 'string');
323
 
324
        $chars = $strlen = strlen($str);
325
        $containNullChars = false;
326
 
327
        for ($count = 0; $count < $strlen; $count++ ) {
328
            /**
329
             * String is already in Java 2 representation.
330
             * We should only calculate actual string length and replace
331
             * \x00 by \xC0\x80
332
             */
333
            if ((ord($str{$count}) & 0xC0) == 0xC0) {
334
                $addBytes = 1;
335
                if (ord($str{$count}) & 0x20 ) {
336
                    $addBytes++;
337
 
338
                    // Never used. Java2 doesn't encode strings in four bytes
339
                    // and we dont't support non-BMP characters
340
                    if (ord($str{$count}) & 0x10 ) {
341
                        $addBytes++;
342
                    }
343
                }
344
                $chars -= $addBytes;
345
 
346
                if (ord($str{$count}) == 0 ) {
347
                    $containNullChars = true;
348
                }
349
                $count += $addBytes;
350
            }
351
        }
352
 
353
        if ($chars < 0) {
354
            throw new Zend_Search_Lucene_Exception('Invalid UTF-8 string');
355
        }
356
 
357
        $this->writeVInt($chars);
358
        if ($containNullChars) {
359
            $this->_fwrite(str_replace($str, "\x00", "\xC0\x80"));
360
        } else {
361
            $this->_fwrite($str);
362
        }
363
    }
364
 
365
 
366
    /**
367
     * Reads binary data from the current position in the file
368
     * and advances the file pointer.
369
     *
370
     * @return string
371
     */
372
    public function readBinary()
373
    {
374
        return $this->_fread($this->readVInt());
375
    }
376
}