1 /* 2 3 Interface for combining multiple tag operations 4 5 copyright (c) 2006, 2015 squell <squell@alumina.nl> 6 7 use, modification, copying and distribution of this software is permitted 8 under the conditions described in the file 'COPYING'. 9 10 */ 11 12 #ifndef __ZF_SETGROUP_HPP 13 #define __ZF_SETGROUP_HPP 14 15 #include <vector> 16 #include <memory> 17 #include "set_base.h" 18 19 namespace tag { 20 21 /////////////////////////////////////////////////////// 22 // placeholder metadata // 23 /////////////////////////////////////////////////////// 24 25 struct empty_metadata : metadata { 26 value_string operator[](ID3field) const { return value_string(); } listingempty_metadata27 array listing() const { return array(); } 28 operator bool() const { return false; } 29 }; 30 31 /////////////////////////////////////////////////////// 32 // generic implementation // 33 // run-time delegation using standard container // 34 /////////////////////////////////////////////////////// 35 36 #pragma clang diagnostic ignored "-Wempty-body" 37 38 template<class Interface> 39 class combined : public Interface, private std::vector<Interface*> { 40 public: 41 // publish some methods 42 typedef Interface interface; 43 typedef typename std::vector<interface*>::size_type size_type; 44 typedef typename std::vector<interface*>::iterator iterator; 45 typedef typename std::vector<interface*>::const_iterator const_iterator; 46 #ifndef __BORLANDC__ 47 using std::vector<interface*>::begin; 48 using std::vector<interface*>::end; 49 using std::vector<interface*>::size; 50 using std::vector<interface*>::operator[]; 51 #else begin()52 const_iterator begin() const { return std::vector<interface*>::begin(); } begin()53 iterator begin() { return std::vector<interface*>::begin(); } end()54 const_iterator end () const { return std::vector<interface*>::end(); } end()55 iterator end () { return std::vector<interface*>::end(); } size()56 size_type size () const { return std::vector<interface*>::size(); } 57 interface* operator[](size_type index) const 58 { return std::vector<interface*>::operator[](index); } 59 interface*& operator[](size_type index) 60 { return std::vector<interface*>::operator[](index); } 61 #endif 62 63 // registers tags with(interface & object)64 combined& with(interface& object) 65 { for(iterator p = begin(); p != end(); ++p) if(*p == &object) return *this; 66 this->push_back(&object); return *this; } 67 combined& ignore(size_type pos, size_type num = 1) 68 { this->erase(begin()+pos, begin()+pos+num); return *this; } 69 70 // handler functions set(ID3field f,std::string s)71 combined& set(ID3field f, std::string s) 72 { for(iterator p = begin(); p != end(); (*p++)->set(f, s)); return *this; } 73 combined& rewrite(bool b = true) 74 { for(iterator p = begin(); p != end(); (*p++)->rewrite(b)); return *this; } 75 combined& create(bool b = true) 76 { for(iterator p = begin(); p != end(); (*p++)->create(b)); return *this; } 77 from(const char * fn)78 bool from(const char* fn) 79 { 80 bool result = size() == 0; 81 for(const_iterator p = begin(); p != end(); ) 82 result |= (*p++)->from(fn); 83 return result; 84 } 85 86 // reader functions read(const char * fn)87 metadata* read(const char* fn) const 88 { 89 for(const_iterator p = begin(); p != end(); ) { 90 #if __cplusplus < 201103L 91 std::auto_ptr<metadata> tag( (*p++)->read(fn) ); 92 #else 93 std::unique_ptr<metadata> tag( (*p++)->read(fn) ); 94 #endif 95 if(tag.get() && *tag) 96 return tag.release(); 97 } 98 return new empty_metadata; 99 } 100 101 protected: vmodify(const char * fn,const stredit::function & func)102 bool vmodify(const char* fn, const stredit::function& func) const 103 { 104 bool success = true; 105 for(const_iterator p = begin(); p != end(); ) 106 success &= (*p++)->modify(fn, func); 107 return success; 108 } 109 }; 110 111 } 112 113 #endif 114 115