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