gzdoom-gles/libraries/adlmidi/structures/pl_list.tcc
Wohlstand e6ce41bdde Update libADLMIDI up to 1.5.0
## 1.5.0   2020-09-28
 * Drum note length expanding is now supported in real-time mode (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Channels manager has been improved (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Nuked OPL3 1.8 emulator got some optimizations ported from 1.7 where they are was applied previously (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Reworked rhythm-mode percussions system, WOPL banks with rhythm-mode percussions
 * Added Public Domain Opal OPL3 emulator made by Reality (a team who originally made the Reality Adlib Tracker) (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Added LGPL licensed JavaOPL3 emulator made by Robson Cozendey in Java and later rewritten into C++ for GZDoom (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Fully rewritten an embedded bank database format, embedded banks now supports a wider set (more than 127:127 instruments in one bank)
 * Improved accuracy of the DMX volume model, include the buggy AM interpretation
 * Improved accuracy of Apogee volume model, include the bug of AM instruments
 * Improved accuracy of the Win9X volume model
 * Removed C++ extras. C++-bounded instruments tester is useless since a real-time MIDI API can completely replace it
 * Added AIL volume model
 * Added Generic FM variant of Win9X volume model
 * Fixed an incorrect work of CC-121 (See https://github.com/Wohlstand/libADLMIDI/issues/227 for details)
 * Added HMI volume model (Thanks to [Alexey Khokholov](https://github.com/nukeykt) for help with research!)
 * Added frequency models, assigned to every volume model: AIL, HMI, DMX, Apogee, 9X, and the Generic formula

# Conflicts:
#	libraries/adlmidi/adldata.cpp
#	libraries/adlmidi/adldata.hh
#	libraries/adlmidi/adlmidi.hpp
2020-10-04 12:50:08 +02:00

338 lines
6.6 KiB
C++

// Copyright Jean Pierre Cimalando 2018.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "pl_list.hpp"
template <class Cell>
pl_iterator<Cell>::pl_iterator(Cell *cell)
: cell_(cell)
{
}
template <class Cell>
bool pl_iterator<Cell>::is_end() const
{
return cell_->next == NULL;
}
template <class Cell>
Cell &pl_iterator<Cell>::operator*() const
{
return *cell_;
}
template <class Cell>
Cell *pl_iterator<Cell>::operator->() const
{
return cell_;
}
template <class T>
bool pl_iterator<T>::operator==(const pl_iterator &i) const
{
return cell_ == i.cell_;
}
template <class T>
bool pl_iterator<T>::operator!=(const pl_iterator &i) const
{
return cell_ != i.cell_;
}
template <class T>
pl_iterator<T> &pl_iterator<T>::operator++()
{
cell_ = cell_->next;
return *this;
}
template <class T>
pl_iterator<T> pl_iterator<T>::operator++(int)
{
pl_iterator i(cell_);
cell_ = cell_->next;
return i;
}
template <class T>
pl_iterator<T> &pl_iterator<T>::operator--()
{
cell_ = cell_->prev;
return *this;
}
template <class T>
pl_iterator<T> pl_iterator<T>::operator--(int)
{
pl_iterator i(cell_);
cell_ = cell_->prev;
return i;
}
template <class T>
pl_list<T>::pl_list(std::size_t capacity)
{
initialize(capacity);
}
template <class T>
pl_list<T>::~pl_list()
{
if (cells_allocd_)
delete[] cells_;
}
template <class T>
pl_list<T>::pl_list(pl_cell<T> *cells, std::size_t ncells, external_storage_policy)
{
initialize(ncells, cells);
}
template <class T>
pl_list<T>::pl_list(const pl_list &other)
{
initialize(other.capacity());
for(const_iterator i = other.end(), b = other.begin(); i-- != b;)
push_front(i->value);
}
template <class T>
pl_list<T> &pl_list<T>::operator=(const pl_list &other)
{
if(this != &other)
{
std::size_t size = other.size();
if(size > capacity())
{
pl_cell<T> *oldcells = cells_;
bool allocd = cells_allocd_;
initialize(other.capacity());
if (allocd)
delete[] oldcells;
}
clear();
for(const_iterator i = other.end(), b = other.begin(); i-- != b;)
push_front(i->value);
}
return *this;
}
template <class T>
std::size_t pl_list<T>::size() const
{
return size_;
}
template <class T>
std::size_t pl_list<T>::capacity() const
{
return capacity_;
}
template <class T>
bool pl_list<T>::empty() const
{
return size_ == 0;
}
template <class T>
typename pl_list<T>::iterator pl_list<T>::begin()
{
return iterator(first_);
}
template <class T>
typename pl_list<T>::iterator pl_list<T>::end()
{
return iterator(reinterpret_cast<pl_cell<T> *>(&endcell_));
}
template <class T>
typename pl_list<T>::const_iterator pl_list<T>::begin() const
{
return const_iterator(first_);
}
template <class T>
typename pl_list<T>::const_iterator pl_list<T>::end() const
{
return const_iterator(reinterpret_cast<const pl_cell<T> *>(&endcell_));
}
template <class T>
void pl_list<T>::clear()
{
std::size_t capacity = capacity_;
pl_cell<T> *cells = cells_;
pl_cell<T> *endcell = &*end();
size_ = 0;
first_ = endcell;
free_ = cells;
endcell->prev = NULL;
for(std::size_t i = 0; i < capacity; ++i)
{
cells[i].prev = (i > 0) ? &cells[i - 1] : NULL;
cells[i].next = (i + 1 < capacity) ? &cells[i + 1] : NULL;
cells[i].value = T();
}
}
template <class T>
pl_cell<T> &pl_list<T>::front()
{
return *first_;
}
template <class T>
const pl_cell<T> &pl_list<T>::front() const
{
return *first_;
}
template <class T>
pl_cell<T> &pl_list<T>::back()
{
iterator i = end();
return *--i;
}
template <class T>
const pl_cell<T> &pl_list<T>::back() const
{
const_iterator i = end();
return *--i;
}
template <class T>
typename pl_list<T>::iterator pl_list<T>::insert(iterator pos, const T &x)
{
pl_cell<T> *cell = allocate(&*pos);
if (!cell)
throw std::bad_alloc();
cell->value = x;
return iterator(cell);
}
template <class T>
typename pl_list<T>::iterator pl_list<T>::erase(iterator pos)
{
deallocate(&*(pos++));
return pos;
}
template <class T>
void pl_list<T>::push_front(const T &x)
{
insert(begin(), x);
}
template <class T>
void pl_list<T>::push_back(const T &x)
{
insert(end(), x);
}
template <class T>
void pl_list<T>::pop_front()
{
deallocate(first_);
}
template <class T>
void pl_list<T>::pop_back()
{
iterator i(&*end());
deallocate(&*--i);
}
template <class T>
typename pl_list<T>::iterator pl_list<T>::find(const T &x)
{
const_iterator i = const_cast<const pl_list<T> *>(this)->find(x);
return iterator(&const_cast<reference>(*i));
}
template <class T>
typename pl_list<T>::const_iterator pl_list<T>::find(const T &x) const
{
const_iterator e = end();
for (const_iterator i = begin(); i != e; ++i)
{
if(i->value == x)
return i;
}
return e;
}
template <class T>
template <class Pred>
typename pl_list<T>::iterator pl_list<T>::find_if(const Pred &p)
{
const_iterator i = const_cast<const pl_list<T> *>(this)->find_if(p);
return iterator(&const_cast<reference>(*i));
}
template <class T>
template <class Pred>
typename pl_list<T>::const_iterator pl_list<T>::find_if(const Pred &p) const
{
const_iterator e = end();
for (const_iterator i = begin(); i != e; ++i)
{
if(p(i->value))
return i;
}
return e;
}
template <class T>
void pl_list<T>::initialize(std::size_t capacity, pl_cell<T> *extcells)
{
cells_ = extcells ? extcells : new pl_cell<T>[capacity];
cells_allocd_ = extcells ? false : true;
capacity_ = capacity;
endcell_.next = NULL;
clear();
}
template <class T>
pl_cell<T> *pl_list<T>::allocate(pl_cell<T> *pos)
{
// remove free cells front
pl_cell<T> *cell = free_;
if(!cell)
return NULL;
free_ = cell->next;
if(free_)
free_->prev = NULL;
// insert at position
if (pos == first_)
first_ = cell;
cell->prev = pos->prev;
if (cell->prev)
cell->prev->next = cell;
cell->next = pos;
pos->prev = cell;
++size_;
return cell;
}
template <class T>
void pl_list<T>::deallocate(pl_cell<T> *cell)
{
if(cell->prev)
cell->prev->next = cell->next;
if(cell->next)
cell->next->prev = cell->prev;
if(cell == first_)
first_ = cell->next;
cell->prev = NULL;
cell->next = free_;
cell->value = T();
free_ = cell;
--size_;
}