/*************************************************************************** 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 #include /** * @brief map + vector = XQMaptor, a template storage class whose data * items can be accessed via string keys and int indices. */ template 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 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 _data; XQMapIndex _index; }; #endif // XQMAPTOR_H