1 /*
2 
3   Interface for applicative tag classes
4 
5   copyright (c) 2004 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   Usage:
11 
12   Use a handler object to specify the changes to make and use the modify()
13   member to make those changes to multiple files. If rewrite() is used and no
14   changes were specified, modify() will remove any tags it encounters. To add
15   tags to files that don't already have them, also use create()
16 
17   modify() parses "%x" variables using string_parm::edit
18 
19   Restrictions:
20 
21   vmodify() should throw tag::failure on critical errors.
22 
23   virtual destructor in tag::handler and tag::provider ommitted for
24   filesize issues with gcc3.
25 
26 */
27 
28 #ifndef __ZF_SET_BASE_HPP
29 #define __ZF_SET_BASE_HPP
30 
31 #include <string>
32 #include <utility>
33 #include <vector>
34 #include <stdexcept>
35 #include "sedit.h"
36 
37 namespace tag {
38 
39     enum ID3field {
40         title, artist, album, year, cmnt, track, genre, FIELD_MAX
41     };
42 
43     class writer;              // interface for writing to files
44     class reader;              // interface for providing readers
45     class handler;             // abstract base class
46 
47     class metadata;            // class abstracting tag info
48 
49     class failure;             // exception class
50 
51 }
52 
53 
54 namespace tag {
55 
56   ///////////////////////////////////////////////////////
57   // tag writing interface                             //
58   ///////////////////////////////////////////////////////
59 
60 class writer {
61 public:
62     typedef stredit::function function;
63 
64     bool modify(const char* fn, const function& sub = stredit::identity()) const
65     { return vmodify(fn, sub); }
66 
modify(const char * fn,const T * var)67     template<class T> bool modify(const char* fn, const T* var) const
68     { return vmodify(fn, stredit::array(var)); }
69 
70 protected:
71     virtual bool vmodify(const char*, const function&) const = 0;
~writer()72     ~writer() { }              // disable outside destruction
73 };
74 
75   ///////////////////////////////////////////////////////
76   // tag reading interface                             //
77   ///////////////////////////////////////////////////////
78 
79 class reader {
80 public:
81     virtual metadata* read(const char*) const = 0;
82 protected:
~reader()83     ~reader() { }
84 };
85 
86 class metadata {
87 public:
88     typedef stredit::function::result value_string;
89     typedef std::vector< std::pair<std::string, value_string> > array;
90 
91     virtual value_string operator[](ID3field) const = 0;
92     virtual array        listing()            const = 0;
93     virtual operator bool()                   const = 0;
~metadata()94     virtual ~metadata() { }
95 
96 protected:                     // a pre-defined factory
97     template<class Instance> struct factory : reader {
readfactory98         virtual metadata* read(const char* fn) const
99         { return new Instance(fn); }
100     };
101 };
102 
103   ///////////////////////////////////////////////////////
104   // tag setting/getting interface                     //
105   ///////////////////////////////////////////////////////
106 
107 class handler : public writer {
108 public:
109 
110   // standard state set methods
111 
112     virtual handler& set(ID3field, std::string) = 0;
113     virtual handler& rewrite(bool = true) = 0;
114     virtual handler& create(bool = true) = 0;
115 
116   // free-form set methods (optional - default to no-op)
117 
118     virtual handler& reserve(std::size_t req = 0)
119     { return *this; }
set(std::string,std::string)120     virtual bool set(std::string, std::string)
121     { return false; }
rm(std::string)122     virtual bool rm(std::string)
123     { return false; }
from(const char * fn)124     virtual bool from(const char* fn)
125     { return false; }
126 
127 protected:
~handler()128     ~handler() { }             // disable outside destruction
129 };
130 
131   ///////////////////////////////////////////////////////
132   // severe error reporting                            //
133   ///////////////////////////////////////////////////////
134 
135 class failure : public std::runtime_error {
136 public:
137     explicit failure(const std::string& err, const std::string& extra = std::string())
138     : std::runtime_error(err + extra) { }
139 };
140 
141 }
142 
143 #endif
144 
145