-rw-r--r-- | lib/fields.cc | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/lib/fields.cc b/lib/fields.cc index d494098..916b603 100644 --- a/lib/fields.cc +++ b/lib/fields.cc | |||
@@ -1,86 +1,135 @@ | |||
1 | #include <opkele/types.h> | 1 | #include <opkele/types.h> |
2 | #include <opkele/exception.h> | 2 | #include <opkele/exception.h> |
3 | #include <opkele/util.h> | 3 | #include <opkele/util.h> |
4 | 4 | ||
5 | namespace opkele { | 5 | namespace opkele { |
6 | using std::unary_function; | 6 | using std::unary_function; |
7 | 7 | ||
8 | struct __om_copier : public unary_function<const string&,void> { | 8 | struct __om_copier : public unary_function<const string&,void> { |
9 | public: | 9 | public: |
10 | const basic_fields& from; | 10 | const basic_fields& from; |
11 | basic_fields& to; | 11 | basic_fields& to; |
12 | 12 | ||
13 | __om_copier(basic_fields& t,const basic_fields& f) | 13 | __om_copier(basic_fields& t,const basic_fields& f) |
14 | : from(f), to(t) { } | 14 | : from(f), to(t) { } |
15 | 15 | ||
16 | result_type operator()(argument_type f) { | 16 | result_type operator()(argument_type f) { |
17 | to.set_field(f,from.get_field(f)); } | 17 | to.set_field(f,from.get_field(f)); } |
18 | }; | 18 | }; |
19 | 19 | ||
20 | basic_fields::basic_fields(const basic_fields& x) { | 20 | basic_fields::basic_fields(const basic_fields& x) { |
21 | x.copy_to(*this); | 21 | x.copy_to(*this); |
22 | } | 22 | } |
23 | void basic_fields::copy_to(basic_fields& x) const { | 23 | void basic_fields::copy_to(basic_fields& x) const { |
24 | x.reset_fields(); | 24 | x.reset_fields(); |
25 | for_each(fields_begin(),fields_end(), | 25 | for_each(fields_begin(),fields_end(), |
26 | __om_copier(x,*this) ); | 26 | __om_copier(x,*this) ); |
27 | } | 27 | } |
28 | void basic_fields::append_to(basic_fields& x) const { | 28 | void basic_fields::append_to(basic_fields& x) const { |
29 | for_each(fields_begin(),fields_end(), | 29 | for_each(fields_begin(),fields_end(), |
30 | __om_copier(x,*this) ); | 30 | __om_copier(x,*this) ); |
31 | } | 31 | } |
32 | 32 | ||
33 | struct __om_query_builder : public unary_function<const string&,void> { | 33 | struct __om_query_builder : public unary_function<const string&,void> { |
34 | public: | 34 | public: |
35 | const basic_fields& om; | 35 | const basic_fields& om; |
36 | bool first; | 36 | bool first; |
37 | string& rv; | 37 | string& rv; |
38 | const char *pfx; | 38 | const char *pfx; |
39 | 39 | ||
40 | __om_query_builder(const char *p,string& r,const basic_fields& m) | 40 | __om_query_builder(const char *p,string& r,const basic_fields& m) |
41 | : om(m), first(true), rv(r), pfx(p) { | 41 | : om(m), first(true), rv(r), pfx(p) { |
42 | for_each(om.fields_begin(),om.fields_end(),*this); | 42 | for_each(om.fields_begin(),om.fields_end(),*this); |
43 | } | 43 | } |
44 | __om_query_builder(const char *p,string& r,const basic_fields& m,const string& u) | 44 | __om_query_builder(const char *p,string& r,const basic_fields& m,const string& u) |
45 | : om(m), first(true), rv(r), pfx(p) { | 45 | : om(m), first(true), rv(r), pfx(p) { |
46 | basic_fields::fields_iterator i=om.fields_begin(), | ||
47 | ie=om.fields_end(); | ||
46 | rv = u; | 48 | rv = u; |
47 | if(rv.find('?')==string::npos) | 49 | if(i!=ie) { |
48 | rv += '?'; | 50 | if(rv.find('?')==string::npos) |
49 | else | 51 | rv += '?'; |
50 | first = false; | 52 | else |
51 | for_each(om.fields_begin(),om.fields_end(),*this); | 53 | first = false; |
54 | for_each(i,ie,*this); | ||
55 | } | ||
52 | } | 56 | } |
53 | 57 | ||
54 | result_type operator()(argument_type f) { | 58 | result_type operator()(argument_type f) { |
55 | if(first) | 59 | if(first) |
56 | first = false; | 60 | first = false; |
57 | else | 61 | else |
58 | rv += '&'; | 62 | rv += '&'; |
59 | if(pfx) rv += pfx; | 63 | if(pfx) rv += pfx; |
60 | rv+= f; | 64 | rv+= f; |
61 | rv += '='; | 65 | rv += '='; |
62 | rv += util::url_encode(om.get_field(f)); | 66 | rv += util::url_encode(om.get_field(f)); |
63 | } | 67 | } |
64 | }; | 68 | }; |
65 | 69 | ||
66 | string basic_fields::append_query(const string& url,const char *pfx) const { | 70 | string basic_fields::append_query(const string& url,const char *pfx) const { |
67 | string rv; | 71 | string rv; |
68 | return __om_query_builder(pfx,rv,*this,url).rv; | 72 | return __om_query_builder(pfx,rv,*this,url).rv; |
69 | } | 73 | } |
70 | string basic_fields::query_string(const char *pfx) const { | 74 | string basic_fields::query_string(const char *pfx) const { |
71 | string rv; | 75 | string rv; |
72 | return __om_query_builder(pfx,rv,*this).rv; | 76 | return __om_query_builder(pfx,rv,*this).rv; |
73 | } | 77 | } |
74 | 78 | ||
75 | void basic_fields::reset_fields() { | 79 | void basic_fields::reset_fields() { |
76 | throw not_implemented(OPKELE_CP_ "reset_fields() not implemented"); | 80 | throw not_implemented(OPKELE_CP_ "reset_fields() not implemented"); |
77 | } | 81 | } |
78 | void basic_fields::set_field(const string&,const string&) { | 82 | void basic_fields::set_field(const string&,const string&) { |
79 | throw not_implemented(OPKELE_CP_ "set_field() not implemented"); | 83 | throw not_implemented(OPKELE_CP_ "set_field() not implemented"); |
80 | } | 84 | } |
81 | void basic_fields::reset_field(const string&) { | 85 | void basic_fields::reset_field(const string&) { |
82 | throw not_implemented(OPKELE_CP_ "reset_field() not implemented"); | 86 | throw not_implemented(OPKELE_CP_ "reset_field() not implemented"); |
83 | } | 87 | } |
84 | 88 | ||
89 | void basic_fields::from_query(const string& qs) { | ||
90 | for(string::size_type p=0,np;;p=np+1) { | ||
91 | np = qs.find('&',p); | ||
92 | string::size_type eq = qs.find('=',p); | ||
93 | if(eq==string::npos) break; | ||
94 | if(np==string::npos) { | ||
95 | set_field( | ||
96 | util::url_decode(qs.substr(p,eq-p)), | ||
97 | util::url_decode(qs.substr(eq+1)) ); | ||
98 | break; | ||
99 | }else if(eq<np) { | ||
100 | set_field( | ||
101 | util::url_decode(qs.substr(p,eq-p)), | ||
102 | util::url_decode(qs.substr(eq+1,np-eq-1)) ); | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | |||
108 | bool fields_t::has_field(const string& n) const { | ||
109 | return find(n)!=end(); | ||
110 | } | ||
111 | const string& fields_t::get_field(const string& n) const { | ||
112 | const_iterator i=find(n); | ||
113 | if(i==end()) | ||
114 | throw failed_lookup(OPKELE_CP_ n+": no such field"); | ||
115 | return i->second; | ||
116 | } | ||
117 | |||
118 | fields_t::fields_iterator fields_t::fields_begin() const { | ||
119 | return util::map_keys_iterator<const_iterator,string,const string&,const string*>(begin(),end()); | ||
120 | } | ||
121 | fields_t::fields_iterator fields_t::fields_end() const { | ||
122 | return util::map_keys_iterator<const_iterator,string,const string&,const string*>(end(),end()); | ||
123 | } | ||
124 | |||
125 | void fields_t::reset_fields() { | ||
126 | clear(); | ||
127 | } | ||
128 | void fields_t::set_field(const string& n,const string& v) { | ||
129 | (*this)[n]=v; | ||
130 | } | ||
131 | void fields_t::reset_field(const string& n) { | ||
132 | erase(n); | ||
133 | } | ||
85 | 134 | ||
86 | } | 135 | } |