<?php
/**
* 配列クラス
*
* PHP version 5
*
* @package    base
* @author     stk2k <stk2k@sazysoft.com>
* @copyright  2008 stk2k, sazysoft
*/

class Vector extends Object implements Iterator, ArrayAccess
{
	private $_value;

	/*
	 *	コンストラクタ
	 */
	public function __construct( $value = array() )
	{
		parent::__construct();

		if ( $value ){
			if ( is_array($value) ){
				$this->_value = array_diff( $value, array() );	// deep copy
			}
			else{
				_throw( new NonArrayException($value) );
			}
		}
		else{
			$this->_value = array();
		}
	}

	/*
	 *	Iteratorインタフェース:rewidの実装
	 */
	public function rewind() {
		reset($this->_value);
	}

	/*
	 *	Iteratorインタフェース:currentの実装
	 */
	public function current() {
		$var = current($this->_value);
		return $var;
	}

	/*
	 *	Iteratorインタフェース:keyの実装
	 */
	public function key() {
		$var = key($this->_value);
		return $var;
	}

	/*
	 *	Iteratorインタフェース:nextの実装
	 */
	public function next() {
		$var = next($this->_value);
		return $var;
	}

	/*
	 *	Iteratorインタフェース:validの実装
	 */
	public function valid() {
		$var = $this->current() !== false;
		return $var;
	}

	/*
	 *	先頭を取得
	 */
	public function getHead()
	{
		$cnt = count( $this->_value );
		if ( $cnt > 0 ){
			return $this->_value[ 0 ];
		}
		return NULL;
	}

	/*
	 *	最後尾を取得
	 */
	public function getTail()
	{
		$cnt = count( $this->_value );
		if ( $cnt > 0 ){
			return $this->_value[ $cnt - 1 ];
		}
		return NULL;
	}


	/*
	 *	最後尾を削除
	 */
	public function removeTail()
	{
		return array_pop( $this->_value );
	}

	/*
	 *	空か
	 */
	public function isEmpty()
	{
		return count( $this->_value ) === 0;
	}

	/*
	 *	最後尾に追加
	 */
	public function add( $item )
	{
		array_push( $this->_value, $item );
	}

	/*
	 *	値を取得
	 */
	public function getValue()
	{
		return $this->_value;
	}

	/*
	 *	要素値を取得
	 */
	public function get( String $key )
	{
		return isset($this->_value["$key"]) ? $this->_value["$key"] : NULL;
	}

	/*
	 *	要素値を更新
	 */
	public function set( String $key, $value )
	{
		$this->_value["$key"] = $value;
	}

	/*
	 * プロパティの取得
	 */
	public function __get( $name )
	{
if ( !is_string($name) ){
	_throw( new NonStringException( $offset ) );
}
		$data =  isset($this->_value[ $name ]) ? $this->_value[ $name ] : NULL;
		return $data;
	}

	/*
	 * プロパティの設定
	 */
	public function __set( $name, $value )
	{
		$this->_value[ $name ] = $value;
	}

	/*
	 *	ArrayAccessインタフェース:offsetGetの実装
	 */
	public function offsetGet($offset)
	{
		if ( $offset instanceof String ){
			return isset($this->_value[ "$offset" ]) ? $this->_value[ "$offset" ] : NULL;
		}
		else{
			return isset($this->_value[ $offset ]) ? $this->_value[ $offset ] : NULL;
		}
	}

	/*
	 *	ArrayAccessインタフェース:offsetSetの実装
	 */
	public function offsetSet($offset, $value)
	{
		if ( $offset instanceof String ){
			$this->_value[ "$offset" ] = $value;
		}
		else{
			$this->_value[ $offset ] = $value;
		}
	}

	/*
	 *	ArrayAccessインタフェース:offsetExistsの実装
	 */
	public function offsetExists($offset)
	{
		if ( $offset instanceof String ){
			return isset($this->_value["$offset"]);
		}
		return isset($this->_value[$offset]);
	}

	/*
	 *	ArrayAccessインタフェース:offsetUnsetの実装
	 */
	public function offsetUnset($offset)
	{
		unset($this->_value[$offset]);
	}

	/*
	 *	エントリの総数を取得
	 */
	public function count()
	{
		return count( $this->_value );
	}

	/*
	 *	キー一覧を取得
	 */
	public function keys()
	{
		return new Vector( array_keys( $this->_value ) );
	}

	/*
	 *	配列の先頭を取り出す
	 */
	public function shift()
	{
		return array_shift( $this->_value );
	}

	/*
	 *	配列の最後尾に追加する
	 */
	public function push()
	{
		return array_shift( $this->_value );
	}


	/*
	 *	配列化
	 */
	public function toArray()
	{
		return array_diff( $this->_value, array() );
	}

	/*
	 *	逆順にする
	 */
	public function reverse()
	{
		return new Vector( array_reverse( $this->_value ) );
	}

	/*
	 *	連想配列を区切り文字でつなげた文字列にして返す
	 */
	public function implodeAssoc( $glue = ',' )
	{
		$array = $this->_value;
		$str = '[';
		foreach( $array as $key => $value ){
			if ( strlen($str) > 1 ){
				$str .= $glue;
			}
			$str .= "$key=$value";
		}
		$str .= "]";

		return $str;
	}

	/*
	 *	文字列化
	 */
	public function toString()
	{
		return $this->implodeAssoc();
	}

}
return __FILE__;
