summaryrefslogtreecommitdiffabout
path: root/lib/fields.cc
Unidiff
Diffstat (limited to 'lib/fields.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/fields.cc59
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
5namespace opkele { 5namespace 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}