
Hi Darren, Darren Garvey wrote:
On 20/08/07, Phil Endecott <spam_from_boost_dev@chezphil.org> wrote:
<!-- snip -->
cgi::request req; cgi::map& form_map = req.meta_form();
Good. If I were you, I would advertise this as the primary way to access the data, i.e.
string frob = req.form ["frob"];
<!-- snip -->
...we all know how to do this with a std::map:
cgi::map::const_iterator i = req.form.find("frob"); if (i==req.form.end()) { ....not set.... } else { string frob = i->second; ....... }
(OK, you might think that's ugly too, but it's "standard ugly". The main point is that a user already knows how to do this, and doesn't need to refer to your docs to discover your is_unset() function or whatever.)
I agree that the 'standard' way should be encouraged more. At the same time, the member function version has the advantage that there is no requirement to parse all of the variables unless it's needed, which is a bonus in the cast of POST data.
I think you could implement a map-like interface that parses the input lazily. Presumably you have a parser for each form-data format that provides some sort of iterator-adapter, which takes a forward iterator over the character data and returns an iterator over name-value string pairs. I think I've already suggested that these parsers should be accessible independent of the rest of the library.
Plus, I'm not too keen on allowing direct access to the variables.
Why?
What I put in for now seems (to me) like a reasonable compromise:
request req; cgi::map& form_map = req.form_(); // returns the map of the form variables std::string name = req.form_()["name"]; // direct access like this name = req.form_()["name"]->first; // or even like this! BOOST_ASSERT( name == req.form_("name")); // shortcut to the above (obviously)
The reasoning behind the trailing underscore, is to avoid req.get() and req.post(), which I think are misleading (as is req.get_var()). This is about the fifth iteration for these functions' names, but I quite like this one. Any better suggestions?
req.form_data
Note that [the data map] can't currently be used for environment variables: this will
probably change, but with the warning that it's going to be much slower for standard CGI.
Why? I don't think getenv is particularly slow. Actually a small library that implements a std::map-like interface to the environment variables would be useful in itself. I encourage you to take every opportunity to make components that can be used independently, as this could.
I finally discovered `extern char ** environ;`. Exactly what's needed; I've added this so now access is uniform across variable types. :) (if you're interested: *http://tinyurl.com/2delnd* - it's not a 'map-like interface' though, it just copies the environment data into a map<string,string>. It probably needs profiling and tweaking too).
Well a const map<string,const char*> would probably be about as good as you can get, i.e. don't copy the values of the environment variables. Regards, Phil.