1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4/**
5 * A reader that concatene the data of the files of a source
6 *
7 * PHP versions 4 and 5
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA
22 *
23 * @category   File Formats
24 * @package    File_Archive
25 * @author     Vincent Lascaux <vincentlascaux@php.net>
26 * @copyright  1997-2005 The PHP Group
27 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL
28 * @version    CVS: $Id: Concat.php,v 1.17 2005/07/07 15:48:28 vincentlascaux Exp $
29 * @link       http://pear.php.net/package/File_Archive
30 */
31
32require_once "File/Archive/Reader/Relay.php";
33
34/**
35 * This reader provides one single file that is the concatenation of the data of
36 * all the files of another reader
37 */
38class File_Archive_Reader_Concat extends File_Archive_Reader
39{
40    var $source;
41    var $filename;
42    var $stat;
43    var $mime;
44    var $opened = false;
45    var $filePos = 0;
46
47    function File_Archive_Reader_Concat(&$source, $filename,
48                                        $stat=array(), $mime=null)
49    {
50        $this->source =& $source;
51        $this->filename = $filename;
52        $this->stat = $stat;
53        $this->mime = $mime;
54
55        //Compute the total length
56        $this->stat[7] = 0;
57        while (($error = $source->next()) === true) {
58            $sourceStat = $source->getStat();
59            if (isset($sourceStat[7])) {
60                $this->stat[7] += $sourceStat[7];
61            } else {
62                unset($this->stat[7]);
63                break;
64            }
65        }
66        if (isset($this->stat[7])) {
67            $this->stat['size'] = $this->stat[7];
68        }
69        if (PEAR::isError($error) || PEAR::isError($source->close())) {
70            die("Error in File_Archive_Reader_Concat constructor ".
71                '('.$error->getMessage().'), cannot continue');
72        }
73    }
74
75    /**
76     * @see File_Archive_Reader::next()
77     */
78    function next()
79    {
80        if (!$this->opened) {
81            return $this->opened = $this->source->next();
82        } else {
83            return false;
84        }
85    }
86    /**
87     * @see File_Archive_Reader::getFilename()
88     */
89    function getFilename() { return $this->filename; }
90    /**
91     * @see File_Archive_Reader::getStat()
92     */
93    function getStat() { return $this->stat; }
94    /**
95     * @see File_Archive_Reader::getMime()
96     */
97    function getMime()
98    {
99        return $this->mime==null ? parent::getMime() : $this->mime;
100    }
101    /**
102     * @see File_Archive_Reader::getData()
103     */
104    function getData($length = -1)
105    {
106        if ($length == 0) {
107            return '';
108        }
109
110        $result = '';
111        while ($length == -1 || strlen($result)<$length) {
112            $sourceData = $this->source->getData(
113                $length==-1 ? -1 : $length - strlen($result)
114            );
115
116            if (PEAR::isError($sourceData)) {
117                return $sourceData;
118            }
119
120            if ($sourceData === null) {
121                $error = $this->source->next();
122                if (PEAR::isError($error)) {
123                    return $error;
124                }
125                if (!$error) {
126                    break;
127                }
128            } else {
129                $result .= $sourceData;
130            }
131        }
132        $this->filePos += strlen($result);
133        return $result == '' ? null : $result;
134    }
135    /**
136     * @see File_Archive_Reader::skip()
137     */
138    function skip($length = -1)
139    {
140        $skipped = 0;
141        while ($skipped < $length) {
142            $sourceSkipped = $this->source->skip($length);
143            if (PEAR::isError($sourceSkipped)) {
144                return $skipped;
145            }
146            $skipped += $sourceSkipped;
147            $filePos += $sourceSkipped;
148        }
149        return $skipped;
150    }
151    /**
152     * @see File_Archive_Reader::rewind()
153     */
154    function rewind($length = -1)
155    {
156        //TODO: implement rewind
157        return parent::rewind($length);
158    }
159
160    /**
161     * @see File_Archive_Reader::tell()
162     */
163    function tell()
164    {
165        return $this->filePos;
166    }
167
168    /**
169     * @see File_Archive_Reader::close()
170     */
171    function close()
172    {
173        $this->opened = false;
174        $this->filePos = 0;
175        return $this->source->close();
176    }
177
178    /**
179     * @see File_Archive_Reader::makeWriter
180     */
181    function makeWriter($fileModif = true, $seek = 0)
182    {
183        return $this->source->makeWriter($fileModif, $seek);
184    }
185}
186
187?>