//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>

#include <WSClistData.h>

WSClistData::WSClistData(){
  _seg_size = 16;
  _num = 0;
  _data = (void**)NULL;
}
WSClistData::WSClistData(long seg){
  _seg_size = seg;
  if (seg > 255){
    _seg_size = 0;
  } 
  _num = 0;
  _data = (void**)NULL;
}

WSClistData::~WSClistData(){
  if (_data != NULL){
    delete _data;
    _data = NULL;;
  }
  _num = 0;
}

long WSClistData::getNum(){
  return _num;
}
long WSClistData::add(void* item,long pos){
  void**   newList = NULL;
  long num = _num;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }
  if (pos == -1 || pos >= num){

    if (num % segment_size == 0){
	  if (num != 0){
        newList = new void*[ (num /segment_size +1) * segment_size ];
        memcpy(newList,_data,sizeof(void*) * num);
        delete _data;
	  }else{
        newList = new void*[ segment_size ];
	  }
      _data = newList;
    }
    _data[num] = item;
    num++;
    _num = num;
    return 0;
  }

  if (pos < 0 ){
    pos = 0;
  }

  if (num != 0){
    if (num % segment_size == 0){
       long newlen = (num /segment_size +1) * segment_size;
       newList = new void*[newlen];
       memcpy(newList,_data,sizeof(void*) * pos);
       memcpy(&newList[pos+1],&_data[pos],sizeof(void*) * (num -pos));
       delete _data;
       _data = newList;
    }else{
       memmove(&_data[pos+1],&_data[pos],sizeof(void*) * (num - pos));
    }
  }else{
    newList = new void*[segment_size];
    _data = newList;
  }

  _data[pos] = item;
  num++;
  _num = num;
  return 0;
}

long WSClistData::del(void* item){
  long i,fl;
  fl = -1;
  long num = _num;
  for(i =0; i < num; i++){
    if (_data[i] == item){
      if (num != 1){
        memcpy(&(_data[i]),&(_data[i+1]),sizeof(void*) * (num - i -1));
      }else{
        delete _data;
        _data = NULL;
      }
      num--;
      _num = num;
      return 0;
    }
  }
  return -1;
}

long WSClistData::delPos(long fl){
  if (fl  < 0){
    return -1;
  }
  long num = _num;
  if (num == 0){
    return -1;
  }
  // over flow deleting pos  
  if (fl > num-1){
    return -1;
  }

  if (num != 1){
    memcpy(&(_data[fl]),&(_data[fl+1]),sizeof(void*) * (num - fl -1));
  }else{
    delete _data;
    _data = NULL;
  }
  num--;
  _num = num;
  return 0;
}

void WSClistData::clear(){
  if (_data != NULL){
    delete _data;
    _data = NULL;;
  }
  _num = 0;
}

void WSClistData::setData(long i,void* d){
  long num = _num;
  if (i < num && i > -1){
    _data[i] = d;
    return;
  }else{
    return ;
  }
}

void* WSClistData::getData(long i){
  long num = _num;
  if (i < num && i > -1){
    return _data[i];
  }else if (i == -1 && num > 0){
    return _data[num-1];
  }else{
    return 0;
  }
}

void* WSClistData::getBottomData(){
  long num = _num;
  if(num == 0){
    return 0;
  }
  return _data[num - 1];
}

void* WSClistData::getTopData(){
  long num = _num;
  if(num == 0){
    return 0;
  }
  return _data[0];
}

void** WSClistData::getBuf(){
  return _data;
}

WSClistData::WSClistData(WSClistData& src){
  _data = NULL;
  _num = src._num;
  _seg_size = src._seg_size;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }
  if (_num != 0){
    _data = new void*[ (_num /segment_size +1) * segment_size ];
    memcpy(_data,src._data,sizeof(void*)*_num);
  }
}

WSClistData::WSClistData(const WSClistData& src){
  _data = NULL;
  _num = src._num;
  _seg_size = src._seg_size;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }
  if (_num != 0){
    _data = new void*[ (_num /segment_size +1) * segment_size ];
    memcpy(_data,src._data,sizeof(void*)*_num);
  }
}


void*& WSClistData::operator [] (long i){
  if (i < (long)_num && i > -1){
    return _data[i];
  }else if (i < 0 && _num > 0){
    return _data[_num-1];
  }
static void* dummy;
  dummy = 0;
  return dummy;
}
#if 0
const void*& WSClistData::operator [] (long i) const{
  if (i < (long)_num && i > -1){
    return _data[i];
  }else if (i < 0 && _num > 0){
    return _data[_num-1];
  }
static void* dummy;
  dummy = 0;
  return dummy;
}
#endif
WSClistData& WSClistData::operator = (WSClistData& src){
  if (&src != this){
    if (_data){
      delete _data;
      _data = NULL;
    }
    _num = src._num;
    _seg_size = src._seg_size;
    long segment_size = _seg_size;
    if (segment_size == 0){
      segment_size = 0x100;
    }
    if (_num != 0){
      _data = new void*[ (_num /segment_size +1) * segment_size ];
      memcpy(_data,src._data,sizeof(void*)*_num);
    }
  }
  return *this;
}
