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