speech-tools/include/EST_TIterator.h
2015-09-19 10:52:26 +02:00

299 lines
9.6 KiB
C++

/************************************************************************/
/* */
/* Centre for Speech Technology Research */
/* University of Edinburgh, UK */
/* Copyright (c) 1996,1997 */
/* All Rights Reserved. */
/* */
/* Permission is hereby granted, free of charge, to use and distribute */
/* this software and its documentation without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of this work, and to */
/* permit persons to whom this work is furnished to do so, subject to */
/* the following conditions: */
/* 1. The code must retain the above copyright notice, this list of */
/* conditions and the following disclaimer. */
/* 2. Any modifications must be clearly marked as such. */
/* 3. Original authors' names are not deleted. */
/* 4. The authors' names are not used to endorse or promote products */
/* derived from this software without specific prior written */
/* permission. */
/* */
/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
/* THIS SOFTWARE. */
/* */
/************************************************************************/
#ifndef __EST_TITERATOR_H__
#define __EST_TITERATOR_H__
/** Template class defining interface to an iterator, i.e an object
* which returns elements from a structure one at a time.
*
* This is template is usually hidden in the declaration of the
* container classes with a typedef for Entries providing a more
* convenient name for the iterator. However the interface is that
* defined here.
*
* We support two interfaces, a pointer like interface similar to
* specialised iteration code elsewhere in the speech tools library
* and to the iterators in the C++ standard template library and an
* interface similar to that of Enumerations in Java.
*
* <programlisting arch='c++'>
* MyContainer::Entries them;
*
* for(them.begin(container); them; them++)
* {
* MyContainer::Entry &it = *them;
* // Do Something With it
* }</programlisting>
*
* <programlisting arch='c++'>
* MyContainer::Entries them;
*
* them.begin(container);
* while (them.has_more_entries())
* {
* MyContainer::Entry &it = them.next_entry();
* // Do Something With it
* }</programlisting>
*
* @author Richard Caley <rjc@cstr.ed.ac.uk>
* @version $Id: EST_TIterator.h,v 1.7 2013/04/13 14:17:11 awb Exp $
*/
template <class Container, class IPointer, class Entry>
class EST_TStructIterator;
template <class Container, class IPointer, class Entry>
class EST_TRwIterator;
template <class Container, class IPointer, class Entry>
class EST_TRwStructIterator;
template <class Container, class IPointer, class Entry>
class EST_TIterator
{
protected:
/// The container we are looking at.
Container *cont;
/// Position in the structure. May or may not be useful.
unsigned int pos;
/** Structure defined by the container class which contains the
* current state of the iteration.
*/
IPointer pointer;
public:
/// Name for an iterator like this
typedef EST_TIterator<Container, IPointer, Entry> Iter;
/// Create an iterator not associated with any specific container.
EST_TIterator() {cont=NULL;}
/// Create an iterator ready to run over the given container.
EST_TIterator(const Container &over)
{ begin(over); }
/// Copy an iterator by assignment
Iter &operator = (const Iter &orig)
{ cont=orig.cont; pos=orig.pos; pointer=orig.pointer; return *this;}
/// Assigning a container to an iterator sets it ready to start.
Iter &operator = (const Container &over)
{ begin(over); return *this;}
/// Set the iterator ready to run over this container.
void begin(const Container &over)
{cont=((Container *)(void *)&over); beginning();}
/// Reset to the start of the container.
void beginning()
{if (cont) cont->point_to_first(pointer); pos=0;}
/**@name End Tests
*/
//@{
/// True if there are more elements to look at.
bool has_more_elements() const
{return cont && cont->points_to_something(pointer);}
/// True when there are no more.
bool at_end() const
{return !has_more_elements();}
/** Viewing the iterator as an integer (for instance in a test)
* sees a non-zero value iff there are elements still to look at.
*/
operator int() const
{return has_more_elements();}
//@}
/**@name Moving Forward
*/
//@{
/// Next moves to the next entry.
void next()
{cont->move_pointer_forwards(pointer); pos++;}
/// The increment operator does the same as next.
Iter &operator ++()
{next(); return *this;}
Iter operator ++(int dummy)
{
(void)dummy;
Iter old =*this;
next();
return old;
}
//@}
/**@name Access
*/
//@{
/// Return the element currently pointed to.
const Entry& current() const
{return cont->points_at(pointer);}
/// The * operator returns the current element.
const Entry &operator *() const
{return current();}
#if 0
// This only works for some Entry types.
const Entry *operator ->() const
{return &current();}
#endif
/// Return the current element and move the pointer forwards.
const Entry& next_element()
{
const Entry &it = cont->points_at(pointer);
cont->move_pointer_forwards(pointer);
return it;
}
/// Return the current position
unsigned int n() const { return pos; }
//@}
friend class EST_TStructIterator <Container, IPointer, Entry>;
friend class EST_TRwIterator <Container, IPointer, Entry>;
friend class EST_TRwStructIterator <Container, IPointer, Entry>;
};
template <class Container, class IPointer, class Entry>
class EST_TStructIterator
: public EST_TIterator<Container, IPointer, Entry>
{
public:
typedef EST_TIterator<Container, IPointer, Entry> Iter;
/// Create an iterator not associated with any specific container.
EST_TStructIterator() {this->cont=NULL;}
/// Copy an iterator by assignment
Iter &operator = (const Iter &orig)
{ this->cont=orig.cont; this->pos=orig.pos; this->pointer=orig.pointer; return *this;}
/// Create an iterator ready to run over the given container.
EST_TStructIterator(const Container &over)
{ this->begin(over); }
const Entry *operator ->() const
{return &this->current();}
};
template <class Container, class IPointer, class Entry>
class EST_TRwIterator
: public EST_TIterator<Container, IPointer, Entry>
{
private:
/// Can't access constant containers this way.
// EST_TRwIterator(const Container &over) { (void) over; }
/// Can't access constant containers this way.
// void begin(const Container &over) { (void) over; }
public:
typedef EST_TIterator<Container, IPointer, Entry> Iter;
/// Create an iterator not associated with any specific container.
EST_TRwIterator() {this->cont=NULL;}
/// Copy an iterator by assignment
Iter &operator = (const Iter &orig)
{ this->cont=orig.cont; this->pos=orig.pos; this->pointer=orig.pointer; return *this;}
/// Create an iterator ready to run over the given container.
EST_TRwIterator(Container &over)
{ begin(over); }
/// Set the iterator ready to run over this container.
void begin(Container &over)
{this->cont=&over; this->beginning();}
/**@name Access
*/
//@{
/// Return the element currently pointed to.
Entry& current() const
{return this->cont->points_at(this->pointer);}
/// The * operator returns the current element.
Entry &operator *() const
{return current();}
#if 0
Entry *operator ->() const
{return &current();}
#endif
/// Return the current element and move the pointer forwards.
Entry& next_element()
{
Entry &it = this->cont->points_at(this->pointer);
this->cont->move_pointer_forwards(this->pointer);
return it;
}
//@}
};
template <class Container, class IPointer, class Entry>
class EST_TRwStructIterator
: public EST_TRwIterator<Container, IPointer, Entry>
{
public:
typedef EST_TIterator<Container, IPointer, Entry> Iter;
/// Create an iterator not associated with any specific container.
EST_TRwStructIterator() {this->cont=NULL;}
/// Copy an iterator by assignment
Iter &operator = (const Iter &orig)
{ this->cont=orig.cont; this->pos=orig.pos; this->pointer=orig.pointer; return *this;}
/// Create an iterator ready to run over the given container.
EST_TRwStructIterator(Container &over)
{ this->begin(over); }
Entry *operator ->() const
{return &this->current();}
};
#endif