307 lines
5.3 KiB
C++
307 lines
5.3 KiB
C++
/***************************************************************************
|
|
|
|
source::worx xtree
|
|
Copyright © 2024-2025 c.holzheuer
|
|
christoph.holzheuer@gmail.com
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef XQMAPTOR_H
|
|
#define XQMAPTOR_H
|
|
|
|
#include <xqmapindex.h>
|
|
#include <xqexception.h>
|
|
|
|
|
|
/**
|
|
* @brief map + vector = XQMaptor, a template storage class whose data
|
|
* items can be accessed via string keys and int indices.
|
|
*/
|
|
|
|
template<class T>
|
|
class XQMaptor
|
|
{
|
|
|
|
public:
|
|
|
|
XQMaptor()
|
|
{
|
|
}
|
|
|
|
|
|
XQMaptor( int itemsize )
|
|
{
|
|
if( itemsize )
|
|
_data.resize( itemsize );
|
|
}
|
|
|
|
|
|
XQMaptor( const XQMaptor& src )
|
|
{
|
|
*this=src;
|
|
}
|
|
|
|
|
|
virtual ~XQMaptor()
|
|
{
|
|
|
|
}
|
|
|
|
XQMaptor& operator=( const XQMaptor& src )
|
|
{
|
|
if( this == &src )
|
|
return *this;
|
|
_data = src._data;
|
|
_index = src._index;
|
|
return *this;
|
|
}
|
|
|
|
// STL-like iterators
|
|
auto begin()
|
|
{
|
|
return _data.begin();
|
|
}
|
|
|
|
auto end()
|
|
{
|
|
return _data.end();
|
|
}
|
|
|
|
inline int size() const
|
|
{
|
|
return (int) _data.size();
|
|
}
|
|
|
|
|
|
inline bool isEmpty() const
|
|
{
|
|
return (_data.size()==0);
|
|
}
|
|
|
|
inline bool contains( int index ) const
|
|
{
|
|
return index < size() && index > -1;
|
|
}
|
|
|
|
inline bool contains( const QString& key ) const
|
|
{
|
|
return mapIndex().contains(key);
|
|
}
|
|
|
|
|
|
inline const XQMapIndex& mapIndex() const
|
|
{
|
|
return _index;
|
|
}
|
|
|
|
|
|
int indexOf( const QString& key ) const
|
|
{
|
|
return mapIndex().indexOf(key);
|
|
}
|
|
|
|
int indexOf(const T& entry) const
|
|
{
|
|
for (int i=0; i<_data.size(); ++i)
|
|
{
|
|
if (_data[i] == entry)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
virtual QString keyOf( int index ) const
|
|
{
|
|
return mapIndex().key( index );
|
|
}
|
|
|
|
|
|
T& operator[]( int index )
|
|
{
|
|
if( contains(index) )
|
|
return _data[index];
|
|
throw XQException("XQMaptor operator[ int index ]: out of range");
|
|
}
|
|
|
|
|
|
const T& operator[]( int index ) const
|
|
{
|
|
if ( contains(index) )
|
|
return _data[index];
|
|
throw XQException("XQMaptor const operator[ int index ]: out of range");
|
|
}
|
|
|
|
T& at( int index )
|
|
{
|
|
return (*this)[index];
|
|
}
|
|
|
|
const T& at( int index ) const
|
|
{
|
|
return (*this)[index];
|
|
}
|
|
|
|
T& operator[]( const QString& key )
|
|
{
|
|
if( key.isEmpty() || !contains(key) )
|
|
throw XQException("maprow operator[]: key empty || not found: " + key);
|
|
return _data[ _index[key] ];
|
|
}
|
|
|
|
|
|
const T& operator[]( const QString& key ) const
|
|
{
|
|
if (key.isEmpty() || !contains(key))
|
|
throw XQException("maprow operator[]: key empty || not found: " + key);
|
|
return _data[_index[key]];
|
|
}
|
|
|
|
|
|
T& at( const QString& key )
|
|
{
|
|
return (*this)[key];
|
|
}
|
|
|
|
const T& at( const QString& key ) const
|
|
{
|
|
return (*this)[key];
|
|
}
|
|
|
|
virtual int add( const T& item )
|
|
{
|
|
_data.push_back( item );
|
|
return _data.size()-1;
|
|
}
|
|
|
|
|
|
virtual void addAtIndex( int index, const T& item )
|
|
{
|
|
if(contains(index))
|
|
throw XQException( "QStringrow::add: index out of range!" );
|
|
_data[index] = item;
|
|
}
|
|
|
|
|
|
// convenience method to mimic QMap<T,QString>
|
|
virtual void insert( const T& item, const QString& key )
|
|
{
|
|
addAtKey(key, item );
|
|
}
|
|
|
|
|
|
virtual void addAtKey( const QString& key, const T& item )
|
|
{
|
|
XQMapIndex::iterator pos = _index.find( key );
|
|
if( pos == _index.end() )
|
|
{
|
|
_data.push_back( item );
|
|
_index[key] = _data.size()-1;
|
|
}
|
|
else
|
|
{
|
|
_data[pos.value()] = item;
|
|
}
|
|
}
|
|
|
|
|
|
bool addAlias( const QString& key, const QString& alias )
|
|
{
|
|
// look for 'original' key
|
|
int key_idx = indexOf(key);
|
|
// quit if not found
|
|
if( key_idx < 0 )
|
|
return false;
|
|
// look for alias
|
|
int alias_idx = indexOf(alias);
|
|
// quit if found: don't overwrite anything
|
|
if( alias_idx > -1 )
|
|
return false;
|
|
// store alias
|
|
_index[ alias ] = key_idx;
|
|
return true;
|
|
}
|
|
|
|
|
|
void addKey( const QString& key, int index )
|
|
{
|
|
_index.addKey( key, index );
|
|
}
|
|
|
|
|
|
virtual void clear()
|
|
{
|
|
_data.clear();
|
|
_index.clear();
|
|
}
|
|
|
|
|
|
virtual bool killEntry( const QString& key )
|
|
{
|
|
int idx = indexOf( key );
|
|
if( idx<0 )
|
|
return false;
|
|
return killEntry( (int) idx );
|
|
}
|
|
|
|
|
|
virtual bool killEntry( int index )
|
|
{
|
|
if( index >= this->_data.size() )
|
|
return false;
|
|
// eintrag lschen
|
|
this->_data.erase( this->_data.begin()+index );
|
|
// index updaten
|
|
_index.update( index );
|
|
return true;
|
|
}
|
|
|
|
|
|
virtual QString toString() const
|
|
{
|
|
return join( ";" );
|
|
}
|
|
|
|
|
|
virtual void dump() const
|
|
{
|
|
throw XQException("XQMaptor: dump not implemented!" );
|
|
}
|
|
|
|
|
|
virtual QString join( const QString& sep, int from=0, int to=-1) const
|
|
{
|
|
Q_UNUSED(sep)
|
|
Q_UNUSED(from)
|
|
Q_UNUSED(to)
|
|
throw XQException("XQMaptor: join not implemented!" );
|
|
return "--";
|
|
}
|
|
|
|
|
|
int replaceKey( const QString& oldkey, const QString& newkey )
|
|
{
|
|
int idx = indexOf( oldkey );
|
|
if( idx<0 || oldkey == newkey )
|
|
return idx;
|
|
_index.remove( oldkey );
|
|
_index[ newkey ] = idx;
|
|
return idx;
|
|
}
|
|
|
|
protected:
|
|
|
|
QVector<T> _data;
|
|
XQMapIndex _index;
|
|
|
|
};
|
|
|
|
|
|
#endif // XQMAPTOR_H
|