1*00b67f09SDavid van Moolenbroek //
2*00b67f09SDavid van Moolenbroek // Automated Testing Framework (atf)
3*00b67f09SDavid van Moolenbroek //
4*00b67f09SDavid van Moolenbroek // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*00b67f09SDavid van Moolenbroek // All rights reserved.
6*00b67f09SDavid van Moolenbroek //
7*00b67f09SDavid van Moolenbroek // Redistribution and use in source and binary forms, with or without
8*00b67f09SDavid van Moolenbroek // modification, are permitted provided that the following conditions
9*00b67f09SDavid van Moolenbroek // are met:
10*00b67f09SDavid van Moolenbroek // 1. Redistributions of source code must retain the above copyright
11*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer.
12*00b67f09SDavid van Moolenbroek // 2. Redistributions in binary form must reproduce the above copyright
13*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer in the
14*00b67f09SDavid van Moolenbroek // documentation and/or other materials provided with the distribution.
15*00b67f09SDavid van Moolenbroek //
16*00b67f09SDavid van Moolenbroek // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*00b67f09SDavid van Moolenbroek // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*00b67f09SDavid van Moolenbroek // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*00b67f09SDavid van Moolenbroek // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*00b67f09SDavid van Moolenbroek // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*00b67f09SDavid van Moolenbroek // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*00b67f09SDavid van Moolenbroek // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*00b67f09SDavid van Moolenbroek // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*00b67f09SDavid van Moolenbroek // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*00b67f09SDavid van Moolenbroek // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*00b67f09SDavid van Moolenbroek // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*00b67f09SDavid van Moolenbroek // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*00b67f09SDavid van Moolenbroek //
29*00b67f09SDavid van Moolenbroek
30*00b67f09SDavid van Moolenbroek #include <sstream>
31*00b67f09SDavid van Moolenbroek
32*00b67f09SDavid van Moolenbroek #include "parser.hpp"
33*00b67f09SDavid van Moolenbroek #include "sanity.hpp"
34*00b67f09SDavid van Moolenbroek #include "text.hpp"
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek namespace impl = atf::parser;
37*00b67f09SDavid van Moolenbroek #define IMPL_NAME "atf::parser"
38*00b67f09SDavid van Moolenbroek
39*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
40*00b67f09SDavid van Moolenbroek // The "parse_error" class.
41*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
42*00b67f09SDavid van Moolenbroek
parse_error(size_t line,std::string msg)43*00b67f09SDavid van Moolenbroek impl::parse_error::parse_error(size_t line, std::string msg) :
44*00b67f09SDavid van Moolenbroek std::runtime_error(msg),
45*00b67f09SDavid van Moolenbroek std::pair< size_t, std::string >(line, msg)
46*00b67f09SDavid van Moolenbroek {
47*00b67f09SDavid van Moolenbroek }
48*00b67f09SDavid van Moolenbroek
~parse_error(void)49*00b67f09SDavid van Moolenbroek impl::parse_error::~parse_error(void)
50*00b67f09SDavid van Moolenbroek throw()
51*00b67f09SDavid van Moolenbroek {
52*00b67f09SDavid van Moolenbroek }
53*00b67f09SDavid van Moolenbroek
54*00b67f09SDavid van Moolenbroek const char*
what(void) const55*00b67f09SDavid van Moolenbroek impl::parse_error::what(void)
56*00b67f09SDavid van Moolenbroek const throw()
57*00b67f09SDavid van Moolenbroek {
58*00b67f09SDavid van Moolenbroek try {
59*00b67f09SDavid van Moolenbroek std::ostringstream oss;
60*00b67f09SDavid van Moolenbroek oss << "LONELY PARSE ERROR: " << first << ": " << second;
61*00b67f09SDavid van Moolenbroek m_msg = oss.str();
62*00b67f09SDavid van Moolenbroek return m_msg.c_str();
63*00b67f09SDavid van Moolenbroek } catch (...) {
64*00b67f09SDavid van Moolenbroek return "Could not format message for parsing error.";
65*00b67f09SDavid van Moolenbroek }
66*00b67f09SDavid van Moolenbroek }
67*00b67f09SDavid van Moolenbroek
operator std::string(void) const68*00b67f09SDavid van Moolenbroek impl::parse_error::operator std::string(void)
69*00b67f09SDavid van Moolenbroek const
70*00b67f09SDavid van Moolenbroek {
71*00b67f09SDavid van Moolenbroek return atf::text::to_string(first) + ": " + second;
72*00b67f09SDavid van Moolenbroek }
73*00b67f09SDavid van Moolenbroek
74*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
75*00b67f09SDavid van Moolenbroek // The "parse_errors" class.
76*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
77*00b67f09SDavid van Moolenbroek
parse_errors(void)78*00b67f09SDavid van Moolenbroek impl::parse_errors::parse_errors(void) :
79*00b67f09SDavid van Moolenbroek std::runtime_error("No parsing errors yet")
80*00b67f09SDavid van Moolenbroek {
81*00b67f09SDavid van Moolenbroek m_msg.clear();
82*00b67f09SDavid van Moolenbroek }
83*00b67f09SDavid van Moolenbroek
~parse_errors(void)84*00b67f09SDavid van Moolenbroek impl::parse_errors::~parse_errors(void)
85*00b67f09SDavid van Moolenbroek throw()
86*00b67f09SDavid van Moolenbroek {
87*00b67f09SDavid van Moolenbroek }
88*00b67f09SDavid van Moolenbroek
89*00b67f09SDavid van Moolenbroek const char*
what(void) const90*00b67f09SDavid van Moolenbroek impl::parse_errors::what(void)
91*00b67f09SDavid van Moolenbroek const throw()
92*00b67f09SDavid van Moolenbroek {
93*00b67f09SDavid van Moolenbroek try {
94*00b67f09SDavid van Moolenbroek m_msg = atf::text::join(*this, "\n");
95*00b67f09SDavid van Moolenbroek return m_msg.c_str();
96*00b67f09SDavid van Moolenbroek } catch (...) {
97*00b67f09SDavid van Moolenbroek return "Could not format messages for parsing errors.";
98*00b67f09SDavid van Moolenbroek }
99*00b67f09SDavid van Moolenbroek }
100*00b67f09SDavid van Moolenbroek
101*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
102*00b67f09SDavid van Moolenbroek // The "format_error" class.
103*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
104*00b67f09SDavid van Moolenbroek
format_error(const std::string & w)105*00b67f09SDavid van Moolenbroek impl::format_error::format_error(const std::string& w) :
106*00b67f09SDavid van Moolenbroek std::runtime_error(w.c_str())
107*00b67f09SDavid van Moolenbroek {
108*00b67f09SDavid van Moolenbroek }
109*00b67f09SDavid van Moolenbroek
110*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
111*00b67f09SDavid van Moolenbroek // The "token" class.
112*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
113*00b67f09SDavid van Moolenbroek
token(void)114*00b67f09SDavid van Moolenbroek impl::token::token(void) :
115*00b67f09SDavid van Moolenbroek m_inited(false)
116*00b67f09SDavid van Moolenbroek {
117*00b67f09SDavid van Moolenbroek }
118*00b67f09SDavid van Moolenbroek
token(size_t p_line,const token_type & p_type,const std::string & p_text)119*00b67f09SDavid van Moolenbroek impl::token::token(size_t p_line,
120*00b67f09SDavid van Moolenbroek const token_type& p_type,
121*00b67f09SDavid van Moolenbroek const std::string& p_text) :
122*00b67f09SDavid van Moolenbroek m_inited(true),
123*00b67f09SDavid van Moolenbroek m_line(p_line),
124*00b67f09SDavid van Moolenbroek m_type(p_type),
125*00b67f09SDavid van Moolenbroek m_text(p_text)
126*00b67f09SDavid van Moolenbroek {
127*00b67f09SDavid van Moolenbroek }
128*00b67f09SDavid van Moolenbroek
129*00b67f09SDavid van Moolenbroek size_t
lineno(void) const130*00b67f09SDavid van Moolenbroek impl::token::lineno(void)
131*00b67f09SDavid van Moolenbroek const
132*00b67f09SDavid van Moolenbroek {
133*00b67f09SDavid van Moolenbroek return m_line;
134*00b67f09SDavid van Moolenbroek }
135*00b67f09SDavid van Moolenbroek
136*00b67f09SDavid van Moolenbroek const impl::token_type&
type(void) const137*00b67f09SDavid van Moolenbroek impl::token::type(void)
138*00b67f09SDavid van Moolenbroek const
139*00b67f09SDavid van Moolenbroek {
140*00b67f09SDavid van Moolenbroek return m_type;
141*00b67f09SDavid van Moolenbroek }
142*00b67f09SDavid van Moolenbroek
143*00b67f09SDavid van Moolenbroek const std::string&
text(void) const144*00b67f09SDavid van Moolenbroek impl::token::text(void)
145*00b67f09SDavid van Moolenbroek const
146*00b67f09SDavid van Moolenbroek {
147*00b67f09SDavid van Moolenbroek return m_text;
148*00b67f09SDavid van Moolenbroek }
149*00b67f09SDavid van Moolenbroek
operator bool(void) const150*00b67f09SDavid van Moolenbroek impl::token::operator bool(void)
151*00b67f09SDavid van Moolenbroek const
152*00b67f09SDavid van Moolenbroek {
153*00b67f09SDavid van Moolenbroek return m_inited;
154*00b67f09SDavid van Moolenbroek }
155*00b67f09SDavid van Moolenbroek
156*00b67f09SDavid van Moolenbroek bool
operator !(void) const157*00b67f09SDavid van Moolenbroek impl::token::operator!(void)
158*00b67f09SDavid van Moolenbroek const
159*00b67f09SDavid van Moolenbroek {
160*00b67f09SDavid van Moolenbroek return !m_inited;
161*00b67f09SDavid van Moolenbroek }
162*00b67f09SDavid van Moolenbroek
163*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
164*00b67f09SDavid van Moolenbroek // The "header_entry" class.
165*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
166*00b67f09SDavid van Moolenbroek
header_entry(void)167*00b67f09SDavid van Moolenbroek impl::header_entry::header_entry(void)
168*00b67f09SDavid van Moolenbroek {
169*00b67f09SDavid van Moolenbroek }
170*00b67f09SDavid van Moolenbroek
header_entry(const std::string & n,const std::string & v,attrs_map as)171*00b67f09SDavid van Moolenbroek impl::header_entry::header_entry(const std::string& n, const std::string& v,
172*00b67f09SDavid van Moolenbroek attrs_map as) :
173*00b67f09SDavid van Moolenbroek m_name(n),
174*00b67f09SDavid van Moolenbroek m_value(v),
175*00b67f09SDavid van Moolenbroek m_attrs(as)
176*00b67f09SDavid van Moolenbroek {
177*00b67f09SDavid van Moolenbroek }
178*00b67f09SDavid van Moolenbroek
179*00b67f09SDavid van Moolenbroek const std::string&
name(void) const180*00b67f09SDavid van Moolenbroek impl::header_entry::name(void) const
181*00b67f09SDavid van Moolenbroek {
182*00b67f09SDavid van Moolenbroek return m_name;
183*00b67f09SDavid van Moolenbroek }
184*00b67f09SDavid van Moolenbroek
185*00b67f09SDavid van Moolenbroek const std::string&
value(void) const186*00b67f09SDavid van Moolenbroek impl::header_entry::value(void) const
187*00b67f09SDavid van Moolenbroek {
188*00b67f09SDavid van Moolenbroek return m_value;
189*00b67f09SDavid van Moolenbroek }
190*00b67f09SDavid van Moolenbroek
191*00b67f09SDavid van Moolenbroek const impl::attrs_map&
attrs(void) const192*00b67f09SDavid van Moolenbroek impl::header_entry::attrs(void) const
193*00b67f09SDavid van Moolenbroek {
194*00b67f09SDavid van Moolenbroek return m_attrs;
195*00b67f09SDavid van Moolenbroek }
196*00b67f09SDavid van Moolenbroek
197*00b67f09SDavid van Moolenbroek bool
has_attr(const std::string & n) const198*00b67f09SDavid van Moolenbroek impl::header_entry::has_attr(const std::string& n) const
199*00b67f09SDavid van Moolenbroek {
200*00b67f09SDavid van Moolenbroek return m_attrs.find(n) != m_attrs.end();
201*00b67f09SDavid van Moolenbroek }
202*00b67f09SDavid van Moolenbroek
203*00b67f09SDavid van Moolenbroek const std::string&
get_attr(const std::string & n) const204*00b67f09SDavid van Moolenbroek impl::header_entry::get_attr(const std::string& n) const
205*00b67f09SDavid van Moolenbroek {
206*00b67f09SDavid van Moolenbroek attrs_map::const_iterator iter = m_attrs.find(n);
207*00b67f09SDavid van Moolenbroek PRE(iter != m_attrs.end());
208*00b67f09SDavid van Moolenbroek return (*iter).second;
209*00b67f09SDavid van Moolenbroek }
210*00b67f09SDavid van Moolenbroek
211*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
212*00b67f09SDavid van Moolenbroek // The header tokenizer.
213*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek namespace header {
216*00b67f09SDavid van Moolenbroek
217*00b67f09SDavid van Moolenbroek static const impl::token_type eof_type = 0;
218*00b67f09SDavid van Moolenbroek static const impl::token_type nl_type = 1;
219*00b67f09SDavid van Moolenbroek static const impl::token_type text_type = 2;
220*00b67f09SDavid van Moolenbroek static const impl::token_type colon_type = 3;
221*00b67f09SDavid van Moolenbroek static const impl::token_type semicolon_type = 4;
222*00b67f09SDavid van Moolenbroek static const impl::token_type dblquote_type = 5;
223*00b67f09SDavid van Moolenbroek static const impl::token_type equal_type = 6;
224*00b67f09SDavid van Moolenbroek
225*00b67f09SDavid van Moolenbroek class tokenizer : public impl::tokenizer< std::istream > {
226*00b67f09SDavid van Moolenbroek public:
tokenizer(std::istream & is,size_t curline)227*00b67f09SDavid van Moolenbroek tokenizer(std::istream& is, size_t curline) :
228*00b67f09SDavid van Moolenbroek impl::tokenizer< std::istream >
229*00b67f09SDavid van Moolenbroek (is, true, eof_type, nl_type, text_type, curline)
230*00b67f09SDavid van Moolenbroek {
231*00b67f09SDavid van Moolenbroek add_delim(';', semicolon_type);
232*00b67f09SDavid van Moolenbroek add_delim(':', colon_type);
233*00b67f09SDavid van Moolenbroek add_delim('=', equal_type);
234*00b67f09SDavid van Moolenbroek add_quote('"', dblquote_type);
235*00b67f09SDavid van Moolenbroek }
236*00b67f09SDavid van Moolenbroek };
237*00b67f09SDavid van Moolenbroek
238*00b67f09SDavid van Moolenbroek static
239*00b67f09SDavid van Moolenbroek impl::parser< header::tokenizer >&
read(impl::parser<header::tokenizer> & p,impl::header_entry & he)240*00b67f09SDavid van Moolenbroek read(impl::parser< header::tokenizer >& p, impl::header_entry& he)
241*00b67f09SDavid van Moolenbroek {
242*00b67f09SDavid van Moolenbroek using namespace header;
243*00b67f09SDavid van Moolenbroek
244*00b67f09SDavid van Moolenbroek impl::token t = p.expect(text_type, nl_type, "a header name");
245*00b67f09SDavid van Moolenbroek if (t.type() == nl_type) {
246*00b67f09SDavid van Moolenbroek he = impl::header_entry();
247*00b67f09SDavid van Moolenbroek return p;
248*00b67f09SDavid van Moolenbroek }
249*00b67f09SDavid van Moolenbroek std::string hdr_name = t.text();
250*00b67f09SDavid van Moolenbroek
251*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
252*00b67f09SDavid van Moolenbroek
253*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "a textual value");
254*00b67f09SDavid van Moolenbroek std::string hdr_value = t.text();
255*00b67f09SDavid van Moolenbroek
256*00b67f09SDavid van Moolenbroek impl::attrs_map attrs;
257*00b67f09SDavid van Moolenbroek
258*00b67f09SDavid van Moolenbroek for (;;) {
259*00b67f09SDavid van Moolenbroek t = p.expect(eof_type, semicolon_type, nl_type,
260*00b67f09SDavid van Moolenbroek "eof, `;' or new line");
261*00b67f09SDavid van Moolenbroek if (t.type() == eof_type || t.type() == nl_type)
262*00b67f09SDavid van Moolenbroek break;
263*00b67f09SDavid van Moolenbroek
264*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "an attribute name");
265*00b67f09SDavid van Moolenbroek std::string attr_name = t.text();
266*00b67f09SDavid van Moolenbroek
267*00b67f09SDavid van Moolenbroek t = p.expect(equal_type, "`='");
268*00b67f09SDavid van Moolenbroek
269*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "word or quoted string");
270*00b67f09SDavid van Moolenbroek std::string attr_value = t.text();
271*00b67f09SDavid van Moolenbroek attrs[attr_name] = attr_value;
272*00b67f09SDavid van Moolenbroek }
273*00b67f09SDavid van Moolenbroek
274*00b67f09SDavid van Moolenbroek he = impl::header_entry(hdr_name, hdr_value, attrs);
275*00b67f09SDavid van Moolenbroek
276*00b67f09SDavid van Moolenbroek return p;
277*00b67f09SDavid van Moolenbroek }
278*00b67f09SDavid van Moolenbroek
279*00b67f09SDavid van Moolenbroek static
280*00b67f09SDavid van Moolenbroek std::ostream&
write(std::ostream & os,const impl::header_entry & he)281*00b67f09SDavid van Moolenbroek write(std::ostream& os, const impl::header_entry& he)
282*00b67f09SDavid van Moolenbroek {
283*00b67f09SDavid van Moolenbroek std::string line = he.name() + ": " + he.value();
284*00b67f09SDavid van Moolenbroek impl::attrs_map as = he.attrs();
285*00b67f09SDavid van Moolenbroek for (impl::attrs_map::const_iterator iter = as.begin(); iter != as.end();
286*00b67f09SDavid van Moolenbroek iter++) {
287*00b67f09SDavid van Moolenbroek PRE((*iter).second.find('\"') == std::string::npos);
288*00b67f09SDavid van Moolenbroek line += "; " + (*iter).first + "=\"" + (*iter).second + "\"";
289*00b67f09SDavid van Moolenbroek }
290*00b67f09SDavid van Moolenbroek
291*00b67f09SDavid van Moolenbroek os << line << "\n";
292*00b67f09SDavid van Moolenbroek
293*00b67f09SDavid van Moolenbroek return os;
294*00b67f09SDavid van Moolenbroek }
295*00b67f09SDavid van Moolenbroek
296*00b67f09SDavid van Moolenbroek } // namespace header
297*00b67f09SDavid van Moolenbroek
298*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
299*00b67f09SDavid van Moolenbroek // Free functions.
300*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
301*00b67f09SDavid van Moolenbroek
302*00b67f09SDavid van Moolenbroek std::pair< size_t, impl::headers_map >
read_headers(std::istream & is,size_t curline)303*00b67f09SDavid van Moolenbroek impl::read_headers(std::istream& is, size_t curline)
304*00b67f09SDavid van Moolenbroek {
305*00b67f09SDavid van Moolenbroek using impl::format_error;
306*00b67f09SDavid van Moolenbroek
307*00b67f09SDavid van Moolenbroek headers_map hm;
308*00b67f09SDavid van Moolenbroek
309*00b67f09SDavid van Moolenbroek //
310*00b67f09SDavid van Moolenbroek // Grammar
311*00b67f09SDavid van Moolenbroek //
312*00b67f09SDavid van Moolenbroek // header = entry+ nl
313*00b67f09SDavid van Moolenbroek // entry = line nl
314*00b67f09SDavid van Moolenbroek // line = text colon text
315*00b67f09SDavid van Moolenbroek // (semicolon (text equal (text | dblquote string dblquote)))*
316*00b67f09SDavid van Moolenbroek // string = quoted_string
317*00b67f09SDavid van Moolenbroek //
318*00b67f09SDavid van Moolenbroek
319*00b67f09SDavid van Moolenbroek header::tokenizer tkz(is, curline);
320*00b67f09SDavid van Moolenbroek impl::parser< header::tokenizer > p(tkz);
321*00b67f09SDavid van Moolenbroek
322*00b67f09SDavid van Moolenbroek bool first = true;
323*00b67f09SDavid van Moolenbroek for (;;) {
324*00b67f09SDavid van Moolenbroek try {
325*00b67f09SDavid van Moolenbroek header_entry he;
326*00b67f09SDavid van Moolenbroek if (!header::read(p, he).good() || he.name().empty())
327*00b67f09SDavid van Moolenbroek break;
328*00b67f09SDavid van Moolenbroek
329*00b67f09SDavid van Moolenbroek if (first && he.name() != "Content-Type")
330*00b67f09SDavid van Moolenbroek throw format_error("Could not determine content type");
331*00b67f09SDavid van Moolenbroek else
332*00b67f09SDavid van Moolenbroek first = false;
333*00b67f09SDavid van Moolenbroek
334*00b67f09SDavid van Moolenbroek hm[he.name()] = he;
335*00b67f09SDavid van Moolenbroek } catch (const impl::parse_error& pe) {
336*00b67f09SDavid van Moolenbroek p.add_error(pe);
337*00b67f09SDavid van Moolenbroek p.reset(header::nl_type);
338*00b67f09SDavid van Moolenbroek }
339*00b67f09SDavid van Moolenbroek }
340*00b67f09SDavid van Moolenbroek
341*00b67f09SDavid van Moolenbroek if (!is.good())
342*00b67f09SDavid van Moolenbroek throw format_error("Unexpected end of stream");
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek return std::pair< size_t, headers_map >(tkz.lineno(), hm);
345*00b67f09SDavid van Moolenbroek }
346*00b67f09SDavid van Moolenbroek
347*00b67f09SDavid van Moolenbroek void
write_headers(const impl::headers_map & hm,std::ostream & os)348*00b67f09SDavid van Moolenbroek impl::write_headers(const impl::headers_map& hm, std::ostream& os)
349*00b67f09SDavid van Moolenbroek {
350*00b67f09SDavid van Moolenbroek PRE(!hm.empty());
351*00b67f09SDavid van Moolenbroek headers_map::const_iterator ct = hm.find("Content-Type");
352*00b67f09SDavid van Moolenbroek PRE(ct != hm.end());
353*00b67f09SDavid van Moolenbroek header::write(os, (*ct).second);
354*00b67f09SDavid van Moolenbroek for (headers_map::const_iterator iter = hm.begin(); iter != hm.end();
355*00b67f09SDavid van Moolenbroek iter++) {
356*00b67f09SDavid van Moolenbroek if ((*iter).first != "Content-Type")
357*00b67f09SDavid van Moolenbroek header::write(os, (*iter).second);
358*00b67f09SDavid van Moolenbroek }
359*00b67f09SDavid van Moolenbroek os << "\n";
360*00b67f09SDavid van Moolenbroek }
361*00b67f09SDavid van Moolenbroek
362*00b67f09SDavid van Moolenbroek void
validate_content_type(const impl::headers_map & hm,const std::string & fmt,int version)363*00b67f09SDavid van Moolenbroek impl::validate_content_type(const impl::headers_map& hm, const std::string& fmt,
364*00b67f09SDavid van Moolenbroek int version)
365*00b67f09SDavid van Moolenbroek {
366*00b67f09SDavid van Moolenbroek using impl::format_error;
367*00b67f09SDavid van Moolenbroek
368*00b67f09SDavid van Moolenbroek headers_map::const_iterator iter = hm.find("Content-Type");
369*00b67f09SDavid van Moolenbroek if (iter == hm.end())
370*00b67f09SDavid van Moolenbroek throw format_error("Could not determine content type");
371*00b67f09SDavid van Moolenbroek
372*00b67f09SDavid van Moolenbroek const header_entry& he = (*iter).second;
373*00b67f09SDavid van Moolenbroek if (he.value() != fmt)
374*00b67f09SDavid van Moolenbroek throw format_error("Mismatched content type: expected `" + fmt +
375*00b67f09SDavid van Moolenbroek "' but got `" + he.value() + "'");
376*00b67f09SDavid van Moolenbroek
377*00b67f09SDavid van Moolenbroek if (!he.has_attr("version"))
378*00b67f09SDavid van Moolenbroek throw format_error("Could not determine version");
379*00b67f09SDavid van Moolenbroek const std::string& vstr = atf::text::to_string(version);
380*00b67f09SDavid van Moolenbroek if (he.get_attr("version") != vstr)
381*00b67f09SDavid van Moolenbroek throw format_error("Mismatched version: expected `" +
382*00b67f09SDavid van Moolenbroek vstr + "' but got `" +
383*00b67f09SDavid van Moolenbroek he.get_attr("version") + "'");
384*00b67f09SDavid van Moolenbroek }
385