1<?php
2/*
3 * PHP QR Code encoder
4 *
5 * Bitstream class
6 *
7 * Based on libqrencode C library distributed under LGPL 2.1
8 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
9 *
10 * PHP QR Code is distributed under LGPL 3
11 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 3 of the License, or any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28namespace PHPQRCode;
29
30class QRbitstream {
31
32    public $data = array();
33
34    //----------------------------------------------------------------------
35    public function size()
36    {
37        return count($this->data);
38    }
39
40    //----------------------------------------------------------------------
41    public function allocate($setLength)
42    {
43        $this->data = array_fill(0, $setLength, 0);
44        return 0;
45    }
46
47    //----------------------------------------------------------------------
48    public static function newFromNum($bits, $num)
49    {
50        $bstream = new QRbitstream();
51        $bstream->allocate($bits);
52
53        $mask = 1 << ($bits - 1);
54        for($i=0; $i<$bits; $i++) {
55            if($num & $mask) {
56                $bstream->data[$i] = 1;
57            } else {
58                $bstream->data[$i] = 0;
59            }
60            $mask = $mask >> 1;
61        }
62
63        return $bstream;
64    }
65
66    //----------------------------------------------------------------------
67    public static function newFromBytes($size, $data)
68    {
69        $bstream = new QRbitstream();
70        $bstream->allocate($size * 8);
71        $p=0;
72
73        for($i=0; $i<$size; $i++) {
74            $mask = 0x80;
75            for($j=0; $j<8; $j++) {
76                if($data[$i] & $mask) {
77                    $bstream->data[$p] = 1;
78                } else {
79                    $bstream->data[$p] = 0;
80                }
81                $p++;
82                $mask = $mask >> 1;
83            }
84        }
85
86        return $bstream;
87    }
88
89    //----------------------------------------------------------------------
90    public function append(QRbitstream $arg)
91    {
92        if (is_null($arg)) {
93            return -1;
94        }
95
96        if($arg->size() == 0) {
97            return 0;
98        }
99
100        if($this->size() == 0) {
101            $this->data = $arg->data;
102            return 0;
103        }
104
105        $this->data = array_values(array_merge($this->data, $arg->data));
106
107        return 0;
108    }
109
110    //----------------------------------------------------------------------
111    public function appendNum($bits, $num)
112    {
113        if ($bits == 0)
114            return 0;
115
116        $b = QRbitstream::newFromNum($bits, $num);
117
118        if(is_null($b))
119            return -1;
120
121        $ret = $this->append($b);
122        unset($b);
123
124        return $ret;
125    }
126
127    //----------------------------------------------------------------------
128    public function appendBytes($size, $data)
129    {
130        if ($size == 0)
131            return 0;
132
133        $b = QRbitstream::newFromBytes($size, $data);
134
135        if(is_null($b))
136            return -1;
137
138        $ret = $this->append($b);
139        unset($b);
140
141        return $ret;
142    }
143
144    //----------------------------------------------------------------------
145    public function toByte()
146    {
147
148        $size = $this->size();
149
150        if($size == 0) {
151            return array();
152        }
153
154        $data = array_fill(0, (int)(($size + 7) / 8), 0);
155        $bytes = (int)($size / 8);
156
157        $p = 0;
158
159        for($i=0; $i<$bytes; $i++) {
160            $v = 0;
161            for($j=0; $j<8; $j++) {
162                $v = $v << 1;
163                $v |= $this->data[$p];
164                $p++;
165            }
166            $data[$i] = $v;
167        }
168
169        if($size & 7) {
170            $v = 0;
171            for($j=0; $j<($size & 7); $j++) {
172                $v = $v << 1;
173                $v |= $this->data[$p];
174                $p++;
175            }
176            $data[$bytes] = $v;
177        }
178
179        return $data;
180    }
181
182}