Program Listing for File list.hpp

Return to documentation for file (libtcod/list.hpp)

/* BSD 3-Clause License
 *
 * Copyright © 2008-2026, Jice and the libtcod contributors.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once
#ifndef TCOD_LIST_HPP_
#define TCOD_LIST_HPP_

#include <stdlib.h>  // NULL
#include <string.h>  // memcpy

#include <utility>

#include "list.h"

// fast & lightweight list template


template <class T>
class TCODList {
  T* array{};
  int fillSize{};
  int allocSize{};

 public:
  [[deprecated("TCODList is unsuitable as a C++ container.")]] TCODList() = default;

  TCODList(const TCOD_list_t l) {
    for (void** it = TCOD_list_begin(l); it != TCOD_list_end(l); ++it) {
      push(*static_cast<T*>(static_cast<void*>(it)));
    }
  }
  TCODList(const TCODList<T>& rhs) { *this = rhs; }
  TCODList<T>& operator=(const TCODList<T>& rhs) {
    while (allocSize < rhs.allocSize) allocate();
    fillSize = rhs.fillSize;
    int i = 0;
    for (T* t = rhs.begin(); t != rhs.end(); ++t) {
      array[i++] = *t;
    }
    return *this;
  }
  TCODList(TCODList&& rhs) noexcept { swap(*this, rhs); };
  TCODList& operator=(TCODList&& rhs) noexcept {
    swap(*this, rhs);
    return *this;
  }

  virtual ~TCODList() {
    if (array) delete[] array;
  }

  friend void swap(TCODList& lhs, TCODList& rhs) noexcept {
    using std::swap;
    swap(lhs.array, rhs.array);
    swap(lhs.fillSize, rhs.fillSize);
    swap(lhs.allocSize, rhs.allocSize);
  }

  [[deprecated("TCODList is unsuitable as a C++ container.")]] TCODList(int nbElements) {
    fillSize = 0;
    allocSize = nbElements;
    array = new T[nbElements];
  }
  // clang-format off

  void set(const T elt, int idx) {
    if ( idx < 0 ) return;
    while ( allocSize < idx+1 ) allocate();
    array[idx] = elt;
    if ( idx+1 > fillSize ) fillSize = idx+1;
  }

  T get(int idx) const {
    return array[idx];
  }

  bool isEmpty() const {
    return ( fillSize == 0 );
  }

  int size() const {
    return fillSize;
  }

  bool contains(const T elt) const
  {
    for (T* curElt = begin(); curElt != end(); ++curElt) {
      if (*curElt == elt) { return true; }
    }
    return false;
  }

  T * insertBefore(const T elt,int before) {
    if ( fillSize+1 >= allocSize ) allocate();
    for (int idx=fillSize; idx > before; idx--) {
      array[idx]=array[idx-1];
    }
    array[before]=elt;
    fillSize++;
    return &array[before];
  }

  void remove(const T elt) {
    for ( T* curElt = begin(); curElt != end(); curElt ++) {
      if ( *curElt == elt ) {
        remove(curElt);
        return;
      }
    }
  }
  void removeFast(const T elt) {
    for ( T* curElt = begin(); curElt != end(); curElt ++) {
      if ( *curElt == elt ) {
        removeFast(curElt);
        return;
      }
    }
  }

  void addAll(const TCODList<T> &l2) {
    for (T *t=l2.begin(); t!= l2.end(); t++) {
      push(*t);
    }
  }

  void clear() {
    fillSize=0;
  }
  void clearAndDelete() {
    for ( T* curElt = begin(); curElt != end(); curElt ++ ) {
      delete (*curElt);
    }
    fillSize=0;
  }

  void reverse() {
    T* head = begin();
    T* tail = end() - 1;
    while (head < tail) {
      std::swap(*head, *tail);
      ++head;
      --tail;
    }
  }

  void push(const T elt) {
    if ( fillSize+1 >= allocSize ) allocate();
    array[fillSize++] = elt;
  }

  T pop() {
    if ( fillSize == 0 ) return T{};
    return array[--fillSize];
  }

  T peek() const {
    if ( fillSize == 0 ) return T{};
    return array[fillSize-1];
  }

  T * begin() const {
    if ( fillSize == 0 ) return (T *)NULL;
    return &array[0];
  }
  T * end() const {
    if ( fillSize == 0 ) return (T *)NULL;
    return &array[fillSize];
  }

  T *remove(T *elt) {
    for ( T* curElt = elt; curElt < end()-1; curElt ++) {
      *curElt = *(curElt+1);
    }
    fillSize--;
    if ( fillSize == 0 ) return ((T *)NULL)-1;
    else return elt-1;
  }
  T *removeFast(T *elt) {
    *elt = array[fillSize-1];
    fillSize--;
    if ( fillSize == 0 ) return ((T *)NULL)-1;
    else return elt-1;
  }

protected :
  void allocate() {
    int newSize = allocSize * 2;
    if ( newSize == 0 ) newSize = 16;
    T *newArray = new T[ newSize ];
    if ( array ) {
      if ( fillSize > 0 ) memcpy(newArray, array, sizeof(T)*fillSize);
      delete [] array;
    }
    array=newArray;
    allocSize=newSize;
  }
};
#endif // TCOD_LIST_HPP_