// ----------------------------------------------------------------------------
// advance_array.js
// Advance Array
// Version 2.9
// 擬似双方向連結リスト実装
// Copyright (C) 2003-2005 Taku Watabe
// Time-stamp: <2007-09-09T00:10:07+09:00>
// ----------------------------------------------------------------------------
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// ----------------------------------------------------------------------------
// GNU 一般公衆利用許諾契約書の複製物は http://eof.my-sv.net/data/gpl に存在し
// ます。
// ----------------------------------------------------------------------------
// 意見・バグ報告は taku.eof@gmail.com まで。
// Subject に必ず「Advance Array」という文字列を含めてください。
// 存在しない場合は単にメールを無視します。
// ----------------------------------------------------------------------------
// Property
//   before : <n-static> look の一つ前にある要素の配列番号
//   look   : <n-static> 現在注目している要素の配列番号
//   after  : <n-static> look の一つ後にある要素の配列番号
// ----------------------------------------------------------------------------
// Method
//   back()    : look を一つ前に持ってきた場合の状態を再計算
//   past()    : look を一つ後に持ってきた場合の状態を再計算
//   here(num) : 現在注目している要素を再計算
//               ないし、num 番目の要素を現在地点としてセット
//               （配列長を変更した場合等に使用）
// ----------------------------------------------------------------------------

Array.prototype.addDoublyLinkedList = function()
{
  this.before = 0;
  this.look   = 0;
  this.after  = 0;
};

Array.prototype.addDoublyLinkedList();
delete Array.prototype.addDoublyLinkedList;


// 現在地点セット
Array.prototype.setLook = function(num)
{
  var length = this.length;

  if (length <= 0) {
    this.before = this.look = this.after = 0;
    return false;
  }

  // 引数があればそれを現在地点とする
  // 配列引数と同じ扱い
  if (num !== undefined) {
    this.look = num;
  }

  // 既に存在しない場所 -> 最後尾
  // この仕様は要検討 : 剰余をとってみるという手もある
  if (this.look > length-1) {
    this.look = length-1;
  }

  // look 前に要素無 -> look の位置は先頭 -> before は最後尾を参照
  // look 前に要素有 ----------------------> before は look の前を参照
  this.before = (this.look <= 0) ? length-1 : this.look-1;
  // look 後に要素無 -> look の位置は末尾 -> after は最前列を参照
  // look 後に要素有 ----------------------> after は look の次を参照
  this.after = (this.look >= length-1) ? 0 : this.look+1;

  return true;
};

// 次へ進む
Array.prototype.past = function()
{
  if (this.setLook() == false) { return; }

  this.before = this.look;
  this.look   = this.after;
  // after 後に要素無 -> after の位置は末尾 -> after は最前列を参照
  // after 後に要素有 -----------------------> after は after の次を参照
  this.after = (this.after >= this.length-1) ? 0 : this.after+1;
};

// 前へ戻る
Array.prototype.back = function()
{
  if (this.setLook() == false) { return; }

  this.after = this.look;
  this.look  = this.before;
  // before 前に要素無 -> before の位置は先頭 -> before は最後尾を参照
  // before 前に要素有 ->                     -> before は before 前を参照
  this.before = (this.before <= 0) ? this.length-1 : this.before-1;
};

