<?php

// Bit Indexer (c) yoya@awm.jp

require_once dirname(__FILE__).'/ByteBit.php';

class 
BitIndexer {
    var 
$_data null;
    var 
$_indices = array();
    var 
$_parser;
    function 
BitIndexer($parser) {
        
$this->_parser $parser;
    }
    function 
parse($data$length) {
        
$this->_data $data;
        if (! 
$length instanceof ByteBit) {
            
$length = new ByteBit($length0);
        }
        
$offset = new ByteBit(00);
        while (
$length->cmp($offset) > 0) {
            
$ret $this->_parser->getChunk($data$offset$length->diff($offset));
            if (
is_null($ret)) {
                break;
            }
            
$ret['offset'] = $offset;
            
$this->_indices[] = $ret;
            
$offset $offset->add($ret['length']);
        }
        return 
true;
    }
    function 
build() {
        
$offset = new ByteBit(00);
        
$data '';
        foreach (
$this->_indices as $index) {
            if (isset(
$index['offset'])) {
                if (
$offset->bit == && $index['offset']->bit == && $index['length']->bit == 0) {
                    
$data .= substr($this->_data$index['offset']->byte$index['length']->byte);
                } else {
                    die(
'bit builder not implemented yet. ');
                }
                
$offset $offset.add($index['length']);
            } else{
                
$data .= $index['data'];
            }
        }
        return 
$data;
    }
    function 
getIndices() {
        return 
$this->_indices;
    }
    function 
dump() {
        foreach(
$this->_indices as $index) {
            echo 
"* ".$index['name']." \n";
            
$this->dumpChunk($index['offset'], $index['length']);
        }
    }
    function 
dumpChunk($offset$length) {
        
$byte_offset $offset->byte;
        
$next_chunk $offset->add($length);
        
$byte_length $next_chunk->byte $byte_offset;
        if (
$next_chunk->bit != 0) {
            
$byte_length += 1;
        }
        
printf("            0  1  2  3  4  5  6  7   8  9  a  b  c  d  e  f  0123456789abcdef\n");

        
$dump_str '';
        if (
$byte_offset 8) {
            
printf("0x%08x "$byte_offset - ($byte_offset 8));
            
$dump_str str_pad(' '$byte_offset 8);
        }
        for (
$i 0$i $byte_offset 8$i++) {
            if (
$i == 8) {
                echo(
' ');
            }
            echo(
'   ');
        }
        for (
$i $byte_offset $i $byte_offset $byte_length$i++) {
            if ((
$i 8) == 0) {
                
printf("0x%08x "$byte_offset - ($byte_offset 8));
            }
            if (isset(
$this->_data[$i])) {
                
$dump_str .= $this->_data[$i];
                
$value ord($this->_data[$i]);
                
printf("%02x "$value);
            } else {
                
$dump_str .= ' ';
                echo 
'   ';
            }
            if ((
$i 8) == 7) {
                echo 
" ";
                echo 
$dump_str;
                echo 
"\n";
                
$dump_str '';
            }
        }
        if ((
$i 8) != 7) {
            echo 
str_pad(' '* (0x10 - ($i 8)));
            if (
$i 8) {
                echo 
' ';
            }
            echo 
" ";
            echo 
$dump_str;
            echo 
"\n";
            
$dump_str '';
            echo 
"\n";
        }
    }
}