<?php

/*

 * PHP QR Code encoder

 *

 * Bitstream class

 *

 * Based on libqrencode C library distributed under LGPL 2.1

 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>

 *

 * PHP QR Code is distributed under LGPL 3

 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

 *

 * This library is free software; you can redistribute it and/or

 * modify it under the terms of the GNU Lesser General Public

 * License as published by the Free Software Foundation; either

 * version 3 of the License, or any later version.

 *

 * This library is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

 * Lesser General Public License for more details.

 *

 * You should have received a copy of the GNU Lesser General Public

 * License along with this library; if not, write to the Free Software

 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

 */

     

    class QRbitstream {

    

        public $data = array();

        

        //----------------------------------------------------------------------

        public function size()

        {

            return count($this->data);

        }

        

        //----------------------------------------------------------------------

        public function allocate($setLength)

        {

            $this->data = array_fill(0, $setLength, 0);

            return 0;

        }

    

        //----------------------------------------------------------------------

        public static function newFromNum($bits, $num)

        {

            $bstream = new QRbitstream();

            $bstream->allocate($bits);

            

            $mask = 1 << ($bits - 1);

            for($i=0; $i<$bits; $i++) {

                if($num & $mask) {

                    $bstream->data[$i] = 1;

                } else {

                    $bstream->data[$i] = 0;

                }

                $mask = $mask >> 1;

            }



            return $bstream;

        }

        

        //----------------------------------------------------------------------

        public static function newFromBytes($size, $data)

        {

            $bstream = new QRbitstream();

            $bstream->allocate($size * 8);

            $p=0;



            for($i=0; $i<$size; $i++) {

                $mask = 0x80;

                for($j=0; $j<8; $j++) {

                    if($data[$i] & $mask) {

                        $bstream->data[$p] = 1;

                    } else {

                        $bstream->data[$p] = 0;

                    }

                    $p++;

                    $mask = $mask >> 1;

                }

            }



            return $bstream;

        }

        

        //----------------------------------------------------------------------

        public function append(QRbitstream $arg)

        {

            if (is_null($arg)) {

                return -1;

            }

            

            if($arg->size() == 0) {

                return 0;

            }

            

            if($this->size() == 0) {

                $this->data = $arg->data;

                return 0;

            }

            

            $this->data = array_values(array_merge($this->data, $arg->data));



            return 0;

        }

        

        //----------------------------------------------------------------------

        public function appendNum($bits, $num)

        {

            if ($bits == 0) 

                return 0;



            $b = QRbitstream::newFromNum($bits, $num);

            

            if(is_null($b))

                return -1;



            $ret = $this->append($b);

            unset($b);



            return $ret;

        }



        //----------------------------------------------------------------------

        public function appendBytes($size, $data)

        {

            if ($size == 0) 

                return 0;



            $b = QRbitstream::newFromBytes($size, $data);

            

            if(is_null($b))

                return -1;



            $ret = $this->append($b);

            unset($b);



            return $ret;

        }

        

        //----------------------------------------------------------------------

        public function toByte()

        {

        

            $size = $this->size();



            if($size == 0) {

                return array();

            }

            

            $data = array_fill(0, (int)(($size + 7) / 8), 0);

            $bytes = (int)($size / 8);



            $p = 0;

            

            for($i=0; $i<$bytes; $i++) {

                $v = 0;

                for($j=0; $j<8; $j++) {

                    $v = $v << 1;

                    $v |= $this->data[$p];

                    $p++;

                }

                $data[$i] = $v;

            }

            

            if($size & 7) {

                $v = 0;

                for($j=0; $j<($size & 7); $j++) {

                    $v = $v << 1;

                    $v |= $this->data[$p];

                    $p++;

                }

                $data[$bytes] = $v;

            }



            return $data;

        }



    }

