/* * VsqBPList.cs * Copyright (c) 2008-2009 kbinani * * This file is part of Boare.Lib.Vsq. * * Boare.Lib.Vsq is free software; you can redistribute it and/or * modify it under the terms of the BSD License. * * Boare.Lib.Vsq 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. */ #if JAVA package org.kbinani.vsq; import java.util.*; import java.io.*; import org.kbinani.*; #else using System; using bocoree; using bocoree.java.io; using bocoree.java.util; namespace Boare.Lib.Vsq { using boolean = System.Boolean; using Integer = System.Int32; #endif #if JAVA public class VsqBPList implements Cloneable, Serializable{ #else [Serializable] public class VsqBPList : ICloneable { #endif private Vector m_clock = new Vector(); private Vector m_items = new Vector(); private int m_default = 0; private int m_maximum = 127; private int m_minimum = 0; private long m_max_id = 0; class KeyClockIterator : Iterator { private VsqBPList m_list; private int m_pos; public KeyClockIterator( VsqBPList list ) { m_list = list; m_pos = -1; } public boolean hasNext() { if ( m_pos + 1 < m_list.m_clock.size() ) { return true; } else { return false; } } public Object next() { m_pos++; return m_list.m_clock.get( m_pos ); } public void remove() { if ( 0 <= m_pos && m_pos < m_list.m_clock.size() ) { int key = m_list.m_clock.get( m_pos ); m_list.m_clock.removeElementAt( m_pos ); m_list.m_items.removeElementAt( m_pos ); } } } /// /// コンストラクタ。デフォルト値はココで指定する。 /// /// public VsqBPList( int default_value, int minimum, int maximum ) { m_default = default_value; m_maximum = maximum; m_minimum = minimum; m_max_id = 0; } #if JAVA public VsqBPList(){ this( 0, 0, 64 ); #else public VsqBPList() : this( 0, 0, 64 ) { #endif } #if !JAVA public int Default { get { return getDefault(); } set { setDefault( value ); } } #endif public long getMaxID() { return m_max_id; } /// /// このBPListのデフォルト値を取得します /// public int getDefault() { return m_default; } public void setDefault( int value ) { m_default = value; } /// /// データ点のIDを一度クリアし,新たに番号付けを行います. /// IDは,Redo,Undo用コマンドが使用するため,このメソッドを呼ぶとRedo,Undo操作が破綻する.XMLからのデシリアライズ直後のみ使用するべき. /// public void renumberIDs() { m_max_id = 0; int count = m_items.size(); for ( int i = 0; i < count; i++ ) { m_max_id++; VsqBPPair v = m_items.get( i ); v.id = m_max_id; m_items.set( i, v ); } } #if !JAVA /// /// XMLシリアライズ用 /// public String Data { get { return getData(); } set { setData( value ); } } #endif public String getData() { String ret = ""; int count = -1; int size = m_clock.size(); for ( int i = 0; i < size; i++ ) { count++; ret += (count == 0 ? "" : ",") + m_clock.get( i ) + "=" + m_items.get( i ).value; } return ret; } public void setData( String value ) { m_clock.clear(); m_items.clear(); m_max_id = 0; String[] spl = PortUtil.splitString( value, ',' ); for ( int i = 0; i < spl.Length; i++ ) { String[] spl2 = PortUtil.splitString( spl[i], '=' ); if ( spl2.Length < 2 ) { continue; } try { int clock = PortUtil.parseInt( spl2[0] ); m_clock.add( clock ); m_items.add( new VsqBPPair( PortUtil.parseInt( spl2[1] ), m_max_id + 1 ) ); m_max_id++; } catch ( Exception ex ) { #if DEBUG PortUtil.println( " ex=" + ex ); PortUtil.println( " i=" + i + "; spl2[0]=" + spl2[0] + "; spl2[1]=" + spl2[1] ); #endif } } } /// /// このVsqBPListの同一コピーを作成します /// /// public Object clone() { VsqBPList res = new VsqBPList( m_default, m_minimum, m_maximum ); int count = m_clock.size(); for ( int i = 0; i < count; i++ ) { res.m_clock.add( m_clock.get( i ) ); #if JAVA res.m_items.add( (VsqBPPair)m_items.get( i ).clone() ); #else res.m_items.add( m_items.get( i ) ); #endif } res.m_max_id = m_max_id; return res; } #if !JAVA public object Clone() { return clone(); } #endif #if !JAVA public int Maximum { get { return getMaximum(); } set { setMaximum( value ); } } #endif /// /// このリストに設定された最大値を取得します。 /// public int getMaximum() { return m_maximum; } public void setMaximum( int value ) { m_maximum = value; } #if !JAVA public int Minimum { get { return getMinimum(); } set { setMinimum( value ); } } #endif /// /// このリストに設定された最小値を取得します /// public int getMinimum() { return m_minimum; } public void setMinimum( int value ) { m_minimum = value; } public void remove( int clock ) { int index = m_clock.indexOf( clock ); removeElementAt( index ); } public void removeElementAt( int index ) { if ( index >= 0 ) { m_clock.removeElementAt( index ); m_items.removeElementAt( index ); } } public boolean isContainsKey( int clock ) { return m_clock.contains( clock ); } /* public int[] getKeys() { Vector t = new Vector(); foreach( int key in m_list.Keys ){ t.add( key ); } return t.toArray( new Integer[]{} ); }*/ /// /// 時刻clockのデータを時刻new_clockに移動します。 /// 時刻clockにデータがなければ何もしない。 /// 時刻new_clockに既にデータがある場合、既存のデータは削除される。 /// /// /// public void move( int clock, int new_clock, int new_value ) { int index = m_clock.indexOf( clock ); if ( index < 0 ) { return; } VsqBPPair item = m_items.get( index ); m_clock.removeElementAt( index ); m_items.removeElementAt( index ); int index_new = m_clock.indexOf( new_clock ); if ( index_new >= 0 ) { item.value = new_value; m_items.set( index_new, item ); return; } else { m_clock.add( new_clock ); Collections.sort( m_clock ); index_new = m_clock.indexOf( new_clock ); item.value = new_value; m_items.insertElementAt( item, index_new ); } } public void clear() { m_clock.clear(); m_items.clear(); } public int getElement( int index ) { return getElementA( index ); } public int getElementA( int index ) { return m_items.get( index ).value; } public VsqBPPair getElementB( int index ) { return m_items.get( index ); } public int getKeyClock( int index ) { return m_clock.get( index ); } public int findValueFromID( long id ) { int c = m_items.size(); for ( int i = 0; i < c; i++ ) { VsqBPPair item = m_items.get( i ); if ( item.id == id ) { return item.value; } } return m_default; } /// /// 指定したid値を持つVsqBPPairを検索し、その結果を返します。 /// /// /// public VsqBPPairSearchContext findElement( long id ) { VsqBPPairSearchContext context = new VsqBPPairSearchContext(); int c = m_items.size(); for ( int i = 0; i < c; i++ ) { VsqBPPair item = m_items.get( i ); if ( item.id == id ) { context.clock = m_clock.get( i ); context.index = i; context.point = item; return context; } } context.clock = -1; context.index = -1; context.point = new VsqBPPair( m_default, -1 ); return context; } public void setValueForID( long id, int value ) { int c = m_items.size(); for ( int i = 0; i < c; i++ ) { VsqBPPair item = m_items.get( i ); if ( item.id == id ) { item.value = value; m_items.set( i, item ); break; } } } public int getValue( int clock, ByRef index ) { int count = m_clock.size(); if ( count == 0 ) { return m_default; } else { if ( index.value < 0 ) { index.value = 0; } for ( int i = index.value; i < count; i++ ) { int keyclock = m_clock.get( i ); if ( clock < keyclock ) { if ( i > 0 ) { index.value = i; return m_items.get( i - 1 ).value; } else { index.value = i; return m_default; } } } index.value = count - 1; return m_items.get( count - 1 ).value; } } private void printCor( ITextWriter writer, int start_clock, String header ) #if JAVA throws IOException #endif { writer.writeLine( header ); int c = m_clock.size(); for ( int i = 0; i < c; i++ ) { int key = m_clock.get( i ); if ( start_clock <= key ) { int val = m_items.get( i ).value; writer.writeLine( key + "=" + val ); } } } /// /// このBPListの内容をテキストファイルに書き出します /// /// public void print( BufferedWriter writer, int start, String header ) #if JAVA throws IOException #endif { printCor( new WrappedStreamWriter( writer ), start, header ); } /// /// このBPListの内容をテキストファイルに書き出します /// /// public void print( TextMemoryStream writer, int start, String header ) #if JAVA throws IOException #endif { printCor( writer, start, header ); } /// /// テキストファイルからデータ点を読込み、現在のリストに追加します /// /// /// public String appendFromText( TextMemoryStream reader ) { String last_line = reader.readLine(); while ( !last_line.StartsWith( "[" ) ) { String[] spl = PortUtil.splitString( last_line, new char[] { '=' } ); int clock = PortUtil.parseInt( spl[0] ); int value = PortUtil.parseInt( spl[1] ); this.add( clock, value ); if ( reader.peek() < 0 ) { break; } else { last_line = reader.readLine(); } } return last_line; } public int size() { return m_clock.size(); } public Iterator keyClockIterator() { return new KeyClockIterator( this ); } public long add( int clock, int value ) { int index = m_clock.indexOf( clock ); if ( index >= 0 ) { VsqBPPair v = m_items.get( index ); v.value = value; m_items.set( index, v ); return v.id; } else { m_clock.add( clock ); Collections.sort( m_clock ); index = m_clock.indexOf( clock ); m_max_id++; m_items.insertElementAt( new VsqBPPair( value, m_max_id ), index ); return m_max_id; } } public void addWithID( int clock, int value, long id ) { int index = m_clock.indexOf( clock ); if ( index >= 0 ) { VsqBPPair v = m_items.get( index ); v.value = value; v.id = id; m_items.set( index, v ); } else { m_clock.add( clock ); Collections.sort( m_clock ); index = m_clock.indexOf( clock ); m_items.insertElementAt( new VsqBPPair( value, id ), index ); m_max_id = Math.Max( m_max_id, id ); } } public void removeWithID( long id ) { int c = m_items.size(); for ( int i = 0; i < c; i++ ) { if ( m_items.get( i ).id == id ) { m_items.removeElementAt( i ); m_clock.removeElementAt( i ); break; } } } public int getValue( int clock ) { int index = m_clock.indexOf( clock ); if ( index >= 0 ) { return m_items.get( index ).value; } else { int count = m_clock.size(); if ( count <= 0 ) { return m_default; } else { int draft = -1; for ( int i = 0; i < count; i++ ) { int c = m_clock.get( i ); if ( clock < c ) { break; } draft = i; } if ( draft < 0 ) { return m_default; } else { return m_items.get( draft ).value; } } } } } #if !JAVA } #endif