/* daapd 0.2.4, a server for the DAA protocol (c) deleet 2003, Alexander Oberdoerster type library: database classes daapd 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. daapd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with daapd; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef DAAP_DBOUTPUT_H #define DAAP_DBOUTPUT_H #include #ifdef __GNUC__ // gcc version < 3.1.0 ? #if __GNUC__ < 3 || \ (__GNUC__ == 3 && __GNUC_MINOR__ < 1) #include #else #include #endif // GCC_VERSION #else #include #endif // __GNUC__ #ifdef __GNUC__ // gcc version < 3.1.0 ? #if __GNUC__ < 3 || \ (__GNUC__ == 3 && __GNUC_MINOR__ < 1) using std::hash_map; #else using __gnu_cxx::hash_map; #endif // GCC_VERSION #else using std::hash_map; #endif // __GNUC__ // template for dictionary output filtering template struct Filter { const T& var; const u64 fields; Filter( const T& _var, int _fields ) : var( _var ), fields( _fields ) {} }; template inline Filter Filtered( const T& _var, int _field ) { return( Filter( _var, _field )); } // general dictionary with automatic key/id management template class Dictionary { private: typedef hash_map Map; typedef typename Map::const_iterator MapIt; Map map; u32 maxId; public: Dictionary() : maxId( 1 ) {} ~Dictionary() { for( MapIt i = map.begin(); i != map.end(); ++i ) delete (*i).second; } // only call this function then U is an integer type // supply a key otherwise (next add function below) int add( T *element ) { element->id = maxId; // this (U) cast will wreak havoc when U is not an integer type map[(U) maxId] = element; maxId++; return( true ); } int add( T *element, U key ) { element->id = maxId; map[key] = element; maxId++; return( true ); } void collectKeys( std::vector& out ) const { out.clear(); out.reserve( map.size()); for( MapIt i=map.begin(); i!=map.end(); ++i ) out.push_back( (*i).first ); } void collectIds( std::vector& out ) const { out.clear(); out.reserve( map.size()); for( MapIt i=map.begin(); i!=map.end(); ++i ) out.push_back( (*i).second->id ); } void collectPointers( std::vector& out ) const { out.clear(); out.reserve( map.size()); for( MapIt i=map.begin(); i!=map.end(); ++i ) out.push_back( (*i).second ); } // fast inline T* find( U key ) const { MapIt item; item = map.find( key ); return( item != map.end() ? (*item).second : 0 ); } // expensive T* findId( u32 id ) const { for( MapIt i=map.begin(); i!=map.end(); ++i ) if( (*i).second->id == id ) return( (*i).second ); // id not found return( 0 ); } bool erase( U key ) { MapIt item; item = map.find( key ); if( item != map.end() ) { delete (*item).second; map.erase( key ); // recalc maxId maxId = 0; for( MapIt i=map.begin(); i!=map.end(); ++i ) if( (*i).second->id > maxId ) maxId = (*i).second->id; ++maxId; return true; } return false; } bool eraseId( u32 id ) { MapIt item; item = map.find( id ); if( item != map.end() ) { delete (*item).second; map.erase( (*item).second.path ); return true; } return false; } inline int size() const { return map.size(); } inline u32 getMaxId() const { return maxId; } friend TagOutput& operator << ( TagOutput& out, const Filter< Dictionary >& f ) { typename Dictionary::MapIt i; for( i = f.var.map.begin(); i != f.var.map.end(); ++i ) out << Filtered( *(*i).second, f.fields ); return( out ); } friend TagOutput& operator << ( TagOutput& out, const Dictionary& dict ) { typename Dictionary::MapIt i; for( i = dict.map.begin(); i != dict.map.end(); ++i ) out << *(*i).second; return( out ); } private: Dictionary( const Dictionary& ); Dictionary& operator = ( const Dictionary& ); }; // song type struct Song { bool present; u32 id; u8 kind; // all these std::strings are actually UTF8. // this is not the right way to do it, but it works and is the easiest way. std::string path; std::string name; std::string album; std::string artist; std::string composer; std::string comment; std::string description; std::string genre; u16 year; u32 time; u32 starttime; u32 stoptime; u32 size; u16 trackcount; u16 tracknumber; u16 disccount; u16 discnumber; u8 compilation; std::string format; u16 bitrate; u32 samplerate; u32 dateadded; u32 datemodified; u8 userrating; u16 bpm; std::string eqpreset; u8 relativevolume; u8 datakind; std::string dataurl; u8 disabled; Song() : present( false ), id( 0 ), kind( 2 ), name( "" ), album( "" ), artist( "" ), composer( "" ), comment( "" ), description( "" ), genre( "" ), year( 0 ), time( 0 ), starttime( 0 ), stoptime( 0 ), size( 0 ), trackcount( 0 ), tracknumber( 0 ), disccount( 0 ), discnumber( 0 ), compilation( 0 ), format( "mp3" ), bitrate( 0 ), samplerate( 0 ), dateadded( 0 ), datemodified( 0 ), userrating( 0 ), bpm( 0 ), eqpreset( "" ), relativevolume( 0 ), datakind( 0 ), dataurl( "" ), disabled( 0 ) {} private: Song( const Song& ); Song& operator = ( const Song& ); }; // container type struct Container { bool present; u32 id; std::string name; std::string path; u32 datemodified; std::map items; Container() : present( false ), id( 0 ), name( "" ), path( "" ), datemodified( 0 ) {} inline u32 size() const { return items.size(); } friend TagOutput& operator << ( TagOutput& out, const Filter& f ); friend TagOutput& operator << ( TagOutput& out, const Container& cont ); private: Container( const Container& ); Container& operator = ( const Container& ); }; #endif