1 #include <string>
2 #include <stdexcept>
3 #include "set_base.h"
4 #include "mass_tag.h"
5 #include "sedit.h"
6 #include "pattern.h"
7
8 /*
9
10 copyright (c) 2005 squell <squell@alumina.nl>
11
12 use, modification, copying and distribution of this software is permitted
13 under the conditions described in the file 'COPYING'.
14
15 */
16
17 using namespace tag;
18 using fileexp::mass_tag;
19 using std::string;
20 using std::wstring;
21 using charset::conv;
22
23 // "inside out" way of specifying what you want.
24 // - kind of lazy. but hey long live code reuse :)
25 // - assumes sedit() processes variables left-to-right
26
27 namespace {
28 struct counter : stredit::format {
29 handler* tag; // Borland doesn't like ref's in aggr's?
30 mutable unsigned w;
31 mutable ptr mod;
32
counter__anon3e2f22940111::counter33 counter(handler* h) : tag(h), w(0) { }
34 virtual result var (ptr& p, ptr end) const;
code__anon3e2f22940111::counter35 virtual result code (ptr& p, ptr end) const
36 { mod = p; return stredit::format::code(p, end); }
37 };
38
var(ptr & p,ptr) const39 counter::result counter::var(ptr& p, ptr) const
40 {
41 if(++w == 10) // limit reached
42 throw std::out_of_range("too many variables in pattern");
43 ID3field field = mass_tag::field(*p);
44 if(field < tag::FIELD_MAX) {
45 const string& pre = conv<wchar_t>(wstring(mod,p)).str<char>();
46 tag->set(field, pre + char('0'+w));
47 } else if(*p == 'x') {
48 ; // pass over in silence
49 } else {
50 static const char error[] = "illegal variable: %";
51 throw std::out_of_range(error+conv<wchar_t>(&*p, 1).str<char>());
52 }
53 return ++p, "*";
54 }
55 }
56
pattern(handler & tag,std::string mask)57 pattern::pattern(handler& tag, std::string mask)
58 {
59 string::size_type pos(0); // replace '*' with stubs
60 while((pos = mask.find('*',pos)) != string::npos) {
61 mask.replace(pos, 1, "%x");
62 }
63 counter var(&tag);
64 this->assign( var(mask) );
65 num = var.w;
66 }
67
68