/**
  * Reads whole (including chunk type) string block from stream.
  * Stream must be at the chunk type.
  */
 public static function read(IntReader $reader)
 {
     ReadUtil::readCheckType($reader, self::CHUNK_TYPE);
     $chunkSize = $reader->readInt();
     $stringCount = $reader->readInt();
     $styleOffsetCount = $reader->readInt();
     $reader->readInt();
     $stringsOffset = $reader->readInt();
     $stylesOffset = $reader->readInt();
     $block = new StringBlock();
     $block->m_stringOffsets = $reader->readIntArray($stringCount);
     if ($styleOffsetCount != 0) {
         $block->m_styleOffsets = $reader->readIntArray($styleOffsetCount);
     }
     $size = ($stylesOffset == 0 ? $chunkSize : $stylesOffset) - $stringsOffset;
     if ($size % 4 != 0) {
         throw new IOException("String data size is not multiple of 4 (" + size + ").");
     }
     $block->m_strings = $reader->readIntArray($size / 4);
     if ($stylesOffset != 0) {
         $size = $chunkSize - $stylesOffset;
         if ($size % 4 != 0) {
             throw new IOException("Style data size is not multiple of 4 (" + size + ").");
         }
         $block->m_styles = $reader->readIntArray($size / 4);
     }
     $block->s = array();
     for ($i = 0; $i != $block->getCount(); ++$i) {
         $block->s[$i] = $block->getRaw($i);
     }
     return block;
 }
 private function doNext()
 {
     if ($this->m_tagType == self::END_DOCUMENT) {
         return self::END_DOCUMENT;
     }
     $this->m_tagType = ReadUtil::readInt($this->m_stream) & 0xff;
     /*other 3 bytes?*/
     /*some source length*/
     ReadUtil::readInt($this->m_stream);
     $this->m_tagSourceLine = ReadUtil::readInt($this->m_stream);
     /*0xFFFFFFFF*/
     ReadUtil::readInt($this->m_stream);
     $this->m_tagName = -1;
     $this->m_tagAttributes = null;
     switch ($this->m_tagType) {
         case self::START_DOCUMENT:
             /*namespace?*/
             ReadUtil::readInt($this->m_stream);
             /*name?*/
             ReadUtil::readInt($this->m_stream);
             break;
         case self::START_TAG:
             /*0xFFFFFFFF*/
             ReadUtil::readInt($this->m_stream);
             $this->m_tagName = ReadUtil::readInt($this->m_stream);
             /*flags?*/
             ReadUtil::readInt($this->m_stream);
             $attributeCount = ReadUtil::readInt($this->m_stream);
             /*?*/
             ReadUtil::readInt($this->m_stream);
             $this->m_tagAttributes = array();
             for ($i = 0; $i != $attributeCount; ++$i) {
                 $attribute = new TagAttribute();
                 $attribute->namespace = ReadUtil::readInt($this->m_stream);
                 $attribute->name = ReadUtil::readInt($this->m_stream);
                 $attribute->valueString = ReadUtil::readInt($this->m_stream);
                 $attribute->valueType = ReadUtil::readInt($this->m_stream) >> 24;
                 /*other 3 bytes?*/
                 $attribute->value = ReadUtil::readInt($this->m_stream);
                 $this->m_tagAttributes[$i] = $attribute;
             }
             break;
         case self::END_TAG:
             /*0xFFFFFFFF*/
             ReadUtil::readInt($this->m_stream);
             $this->m_tagName = ReadUtil::readInt($this->m_stream);
             break;
         case self::TEXT:
             $this->m_tagName = ReadUtil::readInt($this->m_stream);
             /*?*/
             ReadUtil::readInt($this->m_stream);
             /*?*/
             ReadUtil::readInt($this->m_stream);
             break;
         case self::END_DOCUMENT:
             /*namespace?*/
             ReadUtil::readInt($this->m_stream);
             /*name?*/
             ReadUtil::readInt($this->m_stream);
             break;
         default:
             throw new Exception("Invalid tag type (" . $this->m_tagType . ").");
     }
     return $this->m_tagType;
 }