summaryrefslogtreecommitdiffabout
path: root/lib/fields.cc
blob: 916b603ded1787d0156f28490e8278b12eba0d37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <opkele/types.h>
#include <opkele/exception.h>
#include <opkele/util.h>

namespace opkele {
    using std::unary_function;

    struct __om_copier : public unary_function<const string&,void> {
	public:
	    const basic_fields& from;
	    basic_fields& to;

	    __om_copier(basic_fields& t,const basic_fields& f)
		: from(f), to(t) { }

	    result_type operator()(argument_type f) {
		to.set_field(f,from.get_field(f)); }
    };

    basic_fields::basic_fields(const basic_fields& x) {
	x.copy_to(*this);
    }
    void basic_fields::copy_to(basic_fields& x) const {
	x.reset_fields();
	for_each(fields_begin(),fields_end(),
		__om_copier(x,*this) );
    }
    void basic_fields::append_to(basic_fields& x) const {
	for_each(fields_begin(),fields_end(),
		__om_copier(x,*this) );
    }

    struct __om_query_builder : public unary_function<const string&,void> {
	public:
	    const basic_fields& om;
	    bool first;
	    string& rv;
	    const char *pfx;

	    __om_query_builder(const char *p,string& r,const basic_fields& m)
		: om(m), first(true), rv(r), pfx(p) {
		    for_each(om.fields_begin(),om.fields_end(),*this);
		}
	    __om_query_builder(const char *p,string& r,const basic_fields& m,const string& u)
		: om(m), first(true), rv(r), pfx(p) {
		    basic_fields::fields_iterator i=om.fields_begin(),
			ie=om.fields_end();
		    rv = u;
		    if(i!=ie) {
			if(rv.find('?')==string::npos)
			    rv += '?';
			else
			    first = false;
			for_each(i,ie,*this);
		    }
		}

	    result_type operator()(argument_type f) {
		if(first)
		    first = false;
		else
		    rv += '&';
		if(pfx) rv += pfx;
		rv+= f;
		rv += '=';
		rv += util::url_encode(om.get_field(f));
	    }
    };

    string basic_fields::append_query(const string& url,const char *pfx) const {
	string rv;
	return __om_query_builder(pfx,rv,*this,url).rv;
    }
    string basic_fields::query_string(const char *pfx) const {
	string rv;
	return __om_query_builder(pfx,rv,*this).rv;
    }

    void basic_fields::reset_fields() {
	throw not_implemented(OPKELE_CP_ "reset_fields() not implemented");
    }
    void basic_fields::set_field(const string&,const string&) {
	throw not_implemented(OPKELE_CP_ "set_field() not implemented");
    }
    void basic_fields::reset_field(const string&) {
	throw not_implemented(OPKELE_CP_ "reset_field() not implemented");
    }

    void basic_fields::from_query(const string& qs) {
	for(string::size_type p=0,np;;p=np+1) {
	    np = qs.find('&',p);
	    string::size_type eq = qs.find('=',p);
	    if(eq==string::npos) break;
	    if(np==string::npos) {
		set_field(
			util::url_decode(qs.substr(p,eq-p)),
			util::url_decode(qs.substr(eq+1)) );
		break;
	    }else if(eq<np) {
		set_field(
			util::url_decode(qs.substr(p,eq-p)),
			util::url_decode(qs.substr(eq+1,np-eq-1)) );
	    }
	}
    }


    bool fields_t::has_field(const string& n) const {
	return find(n)!=end();
    }
    const string& fields_t::get_field(const string& n) const {
	const_iterator i=find(n);
	if(i==end())
	    throw failed_lookup(OPKELE_CP_ n+": no such field");
	return i->second;
    }

    fields_t::fields_iterator fields_t::fields_begin() const {
	return util::map_keys_iterator<const_iterator,string,const string&,const string*>(begin(),end());
    }
    fields_t::fields_iterator fields_t::fields_end() const {
	return util::map_keys_iterator<const_iterator,string,const string&,const string*>(end(),end());
    }

    void fields_t::reset_fields() {
	clear();
    }
    void fields_t::set_field(const string& n,const string& v) {
	(*this)[n]=v;
    }
    void fields_t::reset_field(const string& n) {
	erase(n);
    }

}