lipsync/trunk/Boare.Lib.Vsq/VsqBPList.cs

449 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using bocoree;
namespace Boare.Lib.Vsq {
using boolean = System.Boolean;
/// <summary>
/// BPListのデータ部分を取り扱うためのクラス。
/// </summary>
[Serializable]
public class VsqBPList : ICloneable {
private SortedList<int, VsqBPPair> m_list = new SortedList<int, VsqBPPair>();
private int m_default = 0;
private int m_maximum = 127;
private int m_minimum = 0;
/// <summary>
/// このリストに設定されたidの最大値次にデータ点が追加されたときは個の値+1がidとして利用される削除された場合でも減らない
/// </summary>
private int m_max_id = 0;
private class KeyClockIterator : Iterator {
private SortedList<int, VsqBPPair> m_list;
private int m_pos;
public KeyClockIterator( SortedList<int, VsqBPPair> list ) {
m_list = list;
m_pos = -1;
}
public boolean hasNext() {
if ( m_pos + 1 < m_list.Keys.Count ) {
return true;
} else {
return false;
}
}
public object next() {
m_pos++;
return m_list.Keys[m_pos];
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.Keys.Count ) {
int key = m_list.Keys[m_pos];
m_list.Remove( key );
}
}
}
public VsqBPList()
: this( 0, 0, 64 ) {
}
public int Default {
get {
return getDefault();
}
set {
setDefault( value );
}
}
/// <summary>
/// このBPListのデフォルト値を取得します
/// </summary>
public int getDefault() {
return m_default;
}
public void setDefault( int value ) {
m_default = value;
}
/// <summary>
/// データ点のIDを一度クリアし新たに番号付けを行います
/// IDはRedo,Undo用コマンドが使用するためこのメソッドを呼ぶとRedo,Undo操作が破綻するXMLからのデシリアライズ直後のみ使用するべき
/// </summary>
public void renumberIDs() {
m_max_id = 0;
for ( Iterator itr = keyClockIterator(); itr.hasNext(); ) {
VsqBPPair item = (VsqBPPair)itr.next();
m_max_id++;
item.id = m_max_id;
}
}
/// <summary>
/// XMLシリアライズ用
/// </summary>
public String Data {
get {
String ret = "";
int count = -1;
foreach ( int key in m_list.Keys ) {
count++;
ret += (count == 0 ? "" : "," ) + key + "=" + m_list[key].value;
}
return ret;
}
set {
m_list.Clear();
m_max_id = 0;
String[] spl = value.Split( ',' );
for ( int i = 0; i < spl.Length; i++ ) {
String[] spl2 = spl[i].Split( '=' );
if ( spl2.Length < 2 ) {
continue;
}
try {
m_list.Add( int.Parse( spl2[0] ), new VsqBPPair( int.Parse( spl2[1] ), m_max_id + 1 ) );
m_max_id++;
} catch ( Exception ex ) {
#if DEBUG
Console.WriteLine( " ex=" + ex );
Console.WriteLine( " i=" + i + "; spl2[0]=" + spl2[0] + "; spl2[1]=" + spl2[1] );
#endif
}
}
}
}
/// <summary>
/// このVsqBPListの同一コピーを作成します
/// </summary>
/// <returns></returns>
public Object clone() {
VsqBPList res = new VsqBPList( getDefault(), getMinimum(), getMaximum() );
foreach ( int key in m_list.Keys ) {
res.m_list.Add( key, m_list[key] );
}
res.m_max_id = m_max_id;
return res;
}
public object Clone() {
return clone();
}
/// <summary>
/// コンストラクタ。デフォルト値はココで指定する。
/// </summary>
/// <param name="default_value"></param>
public VsqBPList( int default_value, int minimum, int maximum ) {
m_default = default_value;
m_maximum = maximum;
m_minimum = minimum;
m_max_id = 0;
}
public int Maximum {
get {
return getMaximum();
}
set {
setMaximum( value );
}
}
/// <summary>
/// このリストに設定された最大値を取得します。
/// </summary>
public int getMaximum() {
return m_maximum;
}
public void setMaximum( int value ){
m_maximum = value;
}
public int Minimum {
get {
return getMinimum();
}
set {
setMinimum( value );
}
}
/// <summary>
/// このリストに設定された最小値を取得します
/// </summary>
public int getMinimum() {
return m_minimum;
}
public void setMinimum( int value ) {
m_minimum = value;
}
public Iterator keyClockIterator() {
return new KeyClockIterator( m_list );
}
public void remove( int clock ) {
if ( m_list.ContainsKey( clock ) ) {
m_list.Remove( clock );
}
}
public boolean isContainsKey( int clock ) {
return m_list.ContainsKey( clock );
}
public int size() {
return m_list.Count;
}
public int[] getKeys() {
Vector<int> t = new Vector<int>();
foreach( int key in m_list.Keys ){
t.add( key );
}
return t.toArray( new Int32[]{} );
}
/// <summary>
/// 時刻clockのデータを時刻new_clockに移動します。
/// 時刻clockにデータがなければ何もしない。
/// 時刻new_clockに既にデータがある場合、既存のデータは削除される。
/// </summary>
/// <param name="clock"></param>
/// <param name="new_clock"></param>
public void move( int clock, int new_clock, int new_value ) {
if ( !m_list.ContainsKey( clock ) ) {
return;
}
VsqBPPair item = m_list[clock];
m_list.Remove( clock );
if ( m_list.ContainsKey( new_clock ) ) {
m_list.Remove( new_clock );
}
item.value = new_value;
m_list.Add( new_clock, item );
}
public void clear() {
m_list.Clear();
}
/// <summary>
/// 新しいデータ点を追加します。
/// 戻り値に、新しいデータ点のIDを返します
/// </summary>
/// <param name="clock"></param>
/// <param name="value"></param>
/// <returns></returns>
public long add( int clock, int value ) {
lock ( m_list ) {
if ( m_list.ContainsKey( clock ) ) {
VsqBPPair v = m_list[clock];
v.value = value;
m_list[clock] = v;
return v.id;
} else {
VsqBPPair v = new VsqBPPair( value, m_max_id + 1 );
m_max_id++;
#if DEBUG
//Console.WriteLine( "VsqBPList#add; m_max_id=" + m_max_id );
#endif
m_list.Add( clock, v );
return m_max_id;
}
}
}
public int getElement( int index ) {
return getElementA( index );
}
public int getElementA( int index ) {
return m_list[m_list.Keys[index]].value;
}
public VsqBPPair getElementB( int index ) {
return m_list[m_list.Keys[index]];
}
public int getKeyClock( int index ) {
return m_list.Keys[index];
}
public int findValueFromID( long id ) {
int c = m_list.Keys.Count;
foreach ( int key in m_list.Keys ) {
if ( m_list[key].id == id ) {
return m_list[key].value;
}
}
return m_default;
}
/// <summary>
/// 指定したid値を持つVsqBPPairを検索し、その結果を返します。
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public VsqBPPairSearchContext findElement( long id ) {
VsqBPPairSearchContext context = new VsqBPPairSearchContext();
int c = m_list.Keys.Count;
for ( int i = 0; i < c; i++ ) {
int clock = m_list.Keys[i];
VsqBPPair item = m_list[clock];
if ( item.id == id ) {
context.clock = clock;
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_list.Keys.Count;
foreach ( int key in m_list.Keys ) {
if ( m_list[key].id == id ) {
VsqBPPair v = m_list[key];
v.value = value;
m_list[key] = v;
break;
}
}
}
public int getValue( int clock, ref int index ) {
if ( m_list.Count == 0 ) {
return m_default;
} else {
if ( index < 0 ) {
index = 0;
}
for ( int i = index ; i < m_list.Keys.Count; i++ ) {
int keyclock = m_list.Keys[i];
if ( clock < keyclock ) {
if ( i > 0 ) {
index = i;
return m_list[m_list.Keys[i - 1]].value;
} else {
index = i;
return m_default;
}
}
}
index = m_list.Keys.Count - 1;
return m_list[m_list.Keys[m_list.Keys.Count - 1]].value;
}
}
public int getValue( int clock ) {
if ( m_list.Count == 0 ) {
return m_default;
} else {
for ( int i = 0; i < m_list.Keys.Count; i++ ) {
int keyclock = m_list.Keys[i];
if ( clock < keyclock ) {
if ( i > 0 ) {
return m_list[m_list.Keys[i - 1]].value;
} else {
return m_default;
}
}
}
return m_list[m_list.Keys[m_list.Keys.Count - 1]].value;
}
}
/// <summary>
/// このBPListの内容をテキストファイルに書き出します
/// </summary>
/// <param name="writer"></param>
public void print( StreamWriter writer ) {
boolean first = true;
foreach ( int key in m_list.Keys ) {
int val = m_list[key].value;
if ( first ) {
writer.WriteLine( key + "=" + val );
first = false;
} else {
writer.WriteLine( key + "=" + val );
}
}
}
/// <summary>
/// このBPListの内容をテキストファイルに書き出します
/// </summary>
/// <param name="writer"></param>
public void print( TextMemoryStream writer, int start, String header ) {
boolean first = true;
foreach ( int key in m_list.Keys ) {
if ( start <= key ) {
if ( first ) {
writer.writeLine( header );
first = false;
}
int val = m_list[key].value;
writer.writeLine( key + "=" + val );
}
}
}
/// <summary>
/// テキストファイルからデータ点を読込み、現在のリストに追加します
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public String appendFromText( TextMemoryStream reader ) {
String last_line = reader.readLine();
while ( !last_line.StartsWith( "[" ) ) {
String[] spl = last_line.Split( new char[] { '=' } );
int i1 = int.Parse( spl[0] );
int i2 = int.Parse( spl[1] );
VsqBPPair v = new VsqBPPair( i2, m_max_id + 1 );
m_max_id++;
m_list.Add( i1, v );
if ( reader.peek() < 0 ) {
break;
} else {
last_line = reader.readLine();
}
}
return last_line;
}
}
}