// array.js - CArray, CHash, CHashWithKeys classes

function CArray()
{
  this.Init = CArray_Init;
  this.Init();
}
function CArray_Init()
{
  this.Set = function ( objItem, nIndex)
  {
    if (nIndex < 0)
      nIndex = this.Count();
    this.m_arItems[nIndex] = objItem;
    return nIndex;
  }
  this.Add = function ( objItem)
  {
    return this.Set( objItem, -1);
  }
  this.Del = function ( nIndex)
  {
    var i;
    var nLast = this.Count() -1;
    for (i = nIndex; i < nLast; i++)
    {
      this.m_arItems[i] = this.m_arItems[i + 1];
    }
    if (nLast >= nIndex)
      this.m_arItems.pop();
      //delete this.m_arItems[ nLast];// = null;
  }
  this.DelPredicate = function( objPredicate)
  {
    var i;
    var nCount = this.Count();
    var nDelCount = 0;
    for ( i=0; i < nCount; i++)
    {
      if (objPredicate.Test( this.Item(i)))
      {
        nDelCount ++;
      }
      else
      {
        if (nDelCount > 0)
          this.m_arItems[i - nDelCount] = this.m_arItems[i];
      }
    }
    for ( i=0; i < nDelCount; i++)
      this.m_arItems.pop();
  }
  this.Item = function ( nIndex)
  {
    return this.m_arItems[nIndex];
  }
  this.Count = function ()
  {
    return this.m_arItems.length;
  }
  this.Pop = function()
  {
    return this.m_arItems.pop();
  }
  this.Push = function( objItem)
  {
    return this.Add( objItem);
  }
  this.Is = function()
  {
    return (this.Count() > 0);
  }
  this.CopyFrom = function( objOther)
  {
    var nCount = objOther.Count();
    for ( var i = 0; i < nCount; i++)
    {
      this.Add( objOther.Item(i));
    }
  }
  this.CopyNotNullFrom = function( objOther)
  {
    var nCount = objOther.Count();
    for ( var i = 0; i < nCount; i++)
    {
      var item = objOther.Item(i);
      if ( item != null)
        this.Add( item);
    }
  }
  this.CloneFrom = function( objOther)
  {
    var nCount = objOther.Count();
    for ( var i = 0; i < nCount; i++)
    {
      this.Add( objOther.Item(i).Clone());
    }
  }
  this.ArItems = function()
  {
    return this.m_arItems;
  }
  this.Clear = function()
  {
    this.m_arItems = new Array();
  }

  this.Clear();
}

function CHash_Init()
{
  this.Set = function ( nKey, objItem)
  {
    this.m_hash[nKey] = objItem;
  }
  this.Del = function ( nKey)
  {
    delete this.m_hash[nKey];
    //this.Set( nKey, null);
  }
  this.Item = function ( nKey)
  {
    var item = null;
    var e;
    try
    {
      item = this.m_hash[nKey];
    }
    catch ( e)
    {
    }
    return item;
  }
  this.Clear = function()
  {
    this.m_hash = new Array();
  }

  this.Clear();
}

function CHash()
{
  this.Init = CHash_Init;
  this.Init();
}

function CHashWithKeys()
{
  this.Set = function( key, value)
  {
    if ( this.m_hashKeyIndex.Item( key))
    {
    }
    else
    {
      this.m_arKey.Add( key);
      this.m_hashKeyIndex.Set( key, this.m_arKey.Count());
    }
    this.m_hashKeyValue.Set( key, value);
  }
  
  this.Del = function( key)
  {
    var nIncreasedNameIndex = this.m_hashKeyIndex.Item( key);
    if ( nIncreasedNameIndex)
    {
      this.m_arKey.Del( nIncreasedNameIndex -1);
      this.m_hashKeyIndex.Del( key);
      this.m_hashKeyValue.Del( key);
      var i = 0;
      for ( i = nIncreasedNameIndex -1; i < this.m_arKey.Count(); i++)
      {
        var strKey = this.m_arKey.Item( i);
        var nNewIndex = this.m_hashKeyIndex.Item( strKey) -1;
        this.m_hashKeyIndex.Set( strKey, nNewIndex);
      }
    }
  }

  this.Keys = function()
  {
    return this.m_arKey;
  }

  this.Item = function( key)
  {
    return this.m_hashKeyValue.Item( key);
  }

  this.Clear = CHashWithKeys;

  this.m_arKey = new CArray();
  this.m_hashKeyIndex = new CHash();
  this.m_hashKeyValue = new CHash();
}

