<?php

/**
 * This file is part of phpMorphy library
 *
 * Copyright c 2007-2008 Kamaev Vladimir <heromantor@users.sourceforge.net>
 *
 * 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 2 of the License, or (at your option) 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/**
 * This file is autogenerated at Wed, 14 Oct 2009 01:34:00 +0400, don`t change it!
 */
class phpMorphy_Graminfo_File extends phpMorphy_Graminfo {

    function getGramInfoHeaderSize() {
        return 20;
    }

    function readGramInfoHeader($offset) {
        $__fh = $this->resource;
        fseek($__fh, $offset);

        $result = unpack(
                        'vid/vfreq/vforms_count/vpacked_forms_count/vancodes_count/vancodes_offset/vancodes_map_offset/vaffixes_offset/vaffixes_size/vbase_size',
                        fread($__fh, 20)
        );

        $result['offset'] = $offset;

        return $result;
    }

    protected function readAncodesMap($info) {
        $__fh = $this->resource;

        // TODO: this can be wrong due to aligning ancodes map section
        $offset = $info['offset'] + 20 + $info['forms_count'] * 2;

        fseek($__fh, $offset);

        $forms_count = $info['packed_forms_count'];
        return unpack("v$forms_count", fread($__fh, $forms_count * 2));
    }

    protected function splitAncodes($ancodes, $map) {
        $result = array();
        for ($i = 1, $c = count($map), $j = 1; $i <= $c; $i++) {
            $res = array();

            for ($k = 0, $kc = $map[$i]; $k < $kc; $k++, $j++) {
                $res[] = $ancodes[$j];
            }

            $result[] = $res;
        }

        return $result;
    }

    function readAncodes($info) {
        $__fh = $this->resource;

        // TODO: this can be wrong due to aligning ancodes section
        $offset = $info['offset'] + 20;

        fseek($__fh, $offset);

        $forms_count = $info['forms_count'];
        $ancodes = unpack("v$forms_count", fread($__fh, $forms_count * 2));

        /*
          if(!$expand) {
          return $ancodes;
          }
         */

        $map = $this->readAncodesMap($info);

        return $this->splitAncodes($ancodes, $map);
    }

    function readFlexiaData($info) {
        $__fh = $this->resource;

        $offset = $info['offset'] + 20;

        if (isset($info['affixes_offset'])) {
            $offset += $info['affixes_offset'];
        } else {
            $offset += $info['forms_count'] * 2 + $info['packed_forms_count'] * 2;
        }

        fseek($__fh, $offset);
        return explode($this->ends, fread($__fh, $info['affixes_size'] - $this->ends_size));
    }

    function readAllGramInfoOffsets() {
        return $this->readSectionIndex($this->header['flex_index_offset'], $this->header['flex_count']);
    }

    protected function readSectionIndex($offset, $count) {
        $__fh = $this->resource;

        fseek($__fh, $offset);

        return array_values(unpack("V$count", fread($__fh, $count * 4)));
    }

    function readAllFlexia() {
        $__fh = $this->resource;

        $result = array();

        $offset = $this->header['flex_offset'];

        foreach ($this->readSectionIndexAsSize($this->header['flex_index_offset'], $this->header['flex_count'], $this->header['flex_size']) as $size) {
            $header = $this->readGramInfoHeader($offset);
            $affixes = $this->readFlexiaData($header);
            $ancodes = $this->readAncodes($header, true);

            $result[$header['id']] = array(
                    'header' => $header,
                    'affixes' => $affixes,
                    'ancodes' => $ancodes
            );

            $offset += $size;
        }

        return $result;
    }

    function readAllPartOfSpeech() {
        $__fh = $this->resource;

        $result = array();

        $offset = $this->header['poses_offset'];

        foreach ($this->readSectionIndexAsSize($this->header['poses_index_offset'], $this->header['poses_count'], $this->header['poses_size']) as $size) {
            fseek($__fh, $offset);

            $res = unpack(
                            'vid/Cis_predict',
                            fread($__fh, 3)
            );

            $result[$res['id']] = array(
                    'is_predict' => (bool) $res['is_predict'],
                    'name' => $this->cleanupCString(fread($__fh, $size - 3))
            );

            $offset += $size;
        }

        return $result;
    }

    function readAllGrammems() {
        $__fh = $this->resource;

        $result = array();

        $offset = $this->header['grammems_offset'];

        foreach ($this->readSectionIndexAsSize($this->header['grammems_index_offset'], $this->header['grammems_count'], $this->header['grammems_size']) as $size) {
            fseek($__fh, $offset);

            $res = unpack(
                            'vid/Cshift',
                            fread($__fh, 3)
            );

            $result[$res['id']] = array(
                    'shift' => $res['shift'],
                    'name' => $this->cleanupCString(fread($__fh, $size - 3))
            );

            $offset += $size;
        }

        return $result;
    }

    function readAllAncodes() {
        $__fh = $this->resource;

        $result = array();

        $offset = $this->header['ancodes_offset'];
        fseek($__fh, $offset);

        for ($i = 0; $i < $this->header['ancodes_count']; $i++) {
            $res = unpack('vid/vpos_id', fread($__fh, 4));
            $offset += 4;

            list(, $grammems_count) = unpack('v', fread($__fh, 2));
            $offset += 2;

            $result[$res['id']] = array(
                    'pos_id' => $res['pos_id'],
                    'grammem_ids' => $grammems_count ?
                            array_values(unpack("v$grammems_count", fread($__fh, $grammems_count * 2))) :
                            array(),
                    'offset' => $offset,
            );

            $offset += $grammems_count * 2;
        }

        return $result;
    }

}
