1 /*
2 
3   string replacement function
4 
5   copyright (c) 2006 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   stredit::function is an abtract class for string-to-string mapping
13 
14   Using stredit::format, any "%x"'s found will be processed; actual variables
15   will be passed on to a descendant class.
16 
17   Optional modifiers to %x:
18    "+"     Pass Throught A Capitalization Function
19    "-"     convert to lower case
20    "_"     Don't_eliminate_underscores_and   don't   compress    spaces
21    "#"     Pad numbers with (number of #'s-1) zero's.
22    "|alt|" Replace with alternate text if substitution would fail.
23 
24   Special forms:
25    "%%" -> %
26    "%?" -> used for %| alt || alt? || alt? |?
27 
28   stredit::array() will instantiate a formatter which looks up %0 to %9 in
29   the array passed as its argument.
30 
31   Example:
32 
33       char* tab[] = { "foo", "bar" };
34       string s = array(tab)("%1, %+0");   // "bar, Foo"
35 
36 */
37 
38 #ifndef __ZF_NSEDIT_HPP
39 #define __ZF_NSEDIT_HPP
40 
41 #include <string>
42 #include "charconv.h"
43 
44 namespace stredit {
45 
46     class function {
47     public:
48         struct result : charset::conv<char> {
resultresult49             result(const charset::conv<>& s, bool ok)
50             : charset::conv<char>(s), m_good(ok) { }
resultresult51             result(const charset::conv<>& s)
52             : charset::conv<char>(s), m_good(!s.empty()) { }
resultresult53             result(const std::string& s)
54             : charset::conv<char>(s), m_good(!s.empty()) { }
resultresult55             result(const char* p)
56             : charset::conv<char>(p), m_good(*p) { }
m_goodresult57             result(int ok = 0) : m_good(ok) { }
goodresult58             bool good() const { return m_good; }
59             operator charset::conv<char> const*() const
60             { return good()? this : 0; }
61         private:
62             bool m_good;
63         };
64 
65         virtual result operator()(const charset::conv<char>&) const = 0;
66     };
67 
68     class identity : public function {
operator()69         virtual result operator()(const charset::conv<char>& s) const
70         { return result(s,1); }
71     };
72 
73     class format : public function {
74     public:
75         static char const prefix = '%';
76 
operator()77         virtual result operator()(const charset::conv<char>& s) const
78         { return edit(charset::conv<wchar_t>(s), false); }
79     protected:
80         result edit(const std::wstring&, bool atomic) const;
81 
82         typedef std::wstring::const_iterator ptr;
83       // on entry, p != end
84         virtual result code (ptr& p, ptr end) const;
85         virtual result var  (ptr& p, ptr end) const = 0;
86         virtual ptr matching(ptr p,  ptr end) const;
87     };
88 
89     template<class T> struct format_wrapper : format {
format_wrapperformat_wrapper90         format_wrapper(T& i) : f(i) { }
varformat_wrapper91         virtual result var(ptr& p, ptr) const
92         { return (charset::conv<char>) f(*p++); }
93     private:
94         T& f;
95     };
96 
97     template<class F>
wrap(F & fun)98       format_wrapper<F> wrap(F& fun) { return fun; }
99 
100     template<class T> struct format_array : format {
format_arrayformat_array101         format_array(T i) : cont(i) { }
varformat_array102         virtual result var(ptr& p, ptr) const
103         { return (charset::conv<char>) cont[*p++ - '0']; }
104     private:
105         T cont;
106     };
107 
108     template<class A>
array(A & arr)109       format_array<A&> array(A& arr) { return format_array<A&>(arr); }
110     template<class A>
array(A * arr)111       format_array<A*> array(A* arr) { return format_array<A*>(arr); }
112 }
113 
114 #endif
115 
116