1240116Smarcel//
2240116Smarcel// Automated Testing Framework (atf)
3240116Smarcel//
4240116Smarcel// Copyright (c) 2007 The NetBSD Foundation, Inc.
5240116Smarcel// All rights reserved.
6240116Smarcel//
7240116Smarcel// Redistribution and use in source and binary forms, with or without
8240116Smarcel// modification, are permitted provided that the following conditions
9240116Smarcel// are met:
10240116Smarcel// 1. Redistributions of source code must retain the above copyright
11240116Smarcel//    notice, this list of conditions and the following disclaimer.
12240116Smarcel// 2. Redistributions in binary form must reproduce the above copyright
13240116Smarcel//    notice, this list of conditions and the following disclaimer in the
14240116Smarcel//    documentation and/or other materials provided with the distribution.
15240116Smarcel//
16240116Smarcel// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17240116Smarcel// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18240116Smarcel// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19240116Smarcel// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20240116Smarcel// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21240116Smarcel// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22240116Smarcel// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23240116Smarcel// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24240116Smarcel// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25240116Smarcel// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26240116Smarcel// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27240116Smarcel// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28240116Smarcel//
29240116Smarcel
30240116Smarcel#if !defined(_ATF_CXX_PARSER_HPP_)
31240116Smarcel#define _ATF_CXX_PARSER_HPP_
32240116Smarcel
33240116Smarcel#include <istream>
34240116Smarcel#include <map>
35240116Smarcel#include <ostream>
36240116Smarcel#include <stdexcept>
37240116Smarcel#include <string>
38240116Smarcel#include <utility>
39240116Smarcel#include <vector>
40240116Smarcel
41240116Smarcelnamespace atf {
42240116Smarcelnamespace parser {
43240116Smarcel
44240116Smarcel// ------------------------------------------------------------------------
45240116Smarcel// The "parse_error" class.
46240116Smarcel// ------------------------------------------------------------------------
47240116Smarcel
48240116Smarcelclass parse_error : public std::runtime_error,
49240116Smarcel                    public std::pair< size_t, std::string > {
50240116Smarcel    mutable std::string m_msg;
51240116Smarcel
52240116Smarcelpublic:
53240116Smarcel    parse_error(size_t, std::string);
54240116Smarcel    ~parse_error(void) throw();
55240116Smarcel
56240116Smarcel    const char* what(void) const throw();
57240116Smarcel
58240116Smarcel    operator std::string(void) const;
59240116Smarcel};
60240116Smarcel
61240116Smarcel// ------------------------------------------------------------------------
62240116Smarcel// The "parse_errors" class.
63240116Smarcel// ------------------------------------------------------------------------
64240116Smarcel
65240116Smarcelclass parse_errors : public std::runtime_error,
66240116Smarcel                     public std::vector< parse_error > {
67240116Smarcel    std::vector< parse_error > m_errors;
68240116Smarcel    mutable std::string m_msg;
69240116Smarcel
70240116Smarcelpublic:
71240116Smarcel    parse_errors(void);
72240116Smarcel    ~parse_errors(void) throw();
73240116Smarcel
74240116Smarcel    const char* what(void) const throw();
75240116Smarcel};
76240116Smarcel
77240116Smarcel// ------------------------------------------------------------------------
78240116Smarcel// The "format_error" class.
79240116Smarcel// ------------------------------------------------------------------------
80240116Smarcel
81240116Smarcelclass format_error : public std::runtime_error {
82240116Smarcelpublic:
83240116Smarcel    format_error(const std::string&);
84240116Smarcel};
85240116Smarcel
86240116Smarcel// ------------------------------------------------------------------------
87240116Smarcel// The "token" class.
88240116Smarcel// ------------------------------------------------------------------------
89240116Smarcel
90240116Smarceltypedef int token_type;
91240116Smarcel
92240116Smarcel//!
93240116Smarcel//! \brief Representation of a read token.
94240116Smarcel//!
95240116Smarcel//! A pair that contains the information of a token read from a stream.
96240116Smarcel//! It contains the token's type and its associated data, if any.
97240116Smarcel//!
98240116Smarcelstruct token {
99240116Smarcel    bool m_inited;
100240116Smarcel    size_t m_line;
101240116Smarcel    token_type m_type;
102240116Smarcel    std::string m_text;
103240116Smarcel
104240116Smarcelpublic:
105240116Smarcel    token(void);
106240116Smarcel    token(size_t, const token_type&, const std::string& = "");
107240116Smarcel
108240116Smarcel    size_t lineno(void) const;
109240116Smarcel    const token_type& type(void) const;
110240116Smarcel    const std::string& text(void) const;
111240116Smarcel
112240116Smarcel    operator bool(void) const;
113240116Smarcel    bool operator!(void) const;
114240116Smarcel};
115240116Smarcel
116240116Smarcel// ------------------------------------------------------------------------
117240116Smarcel// The "tokenizer" class.
118240116Smarcel// ------------------------------------------------------------------------
119240116Smarcel
120240116Smarcel//!
121240116Smarcel//! \brief A stream tokenizer.
122240116Smarcel//!
123240116Smarcel//! This template implements an extremely simple, line-oriented stream
124240116Smarcel//! tokenizer.  It is only able to recognize one character-long delimiters,
125240116Smarcel//! random-length keywords, skip whitespace and, anything that does not
126240116Smarcel//! match these rules is supposed to be a word.
127240116Smarcel//!
128240116Smarcel//! Parameter IS: The input stream's type.
129240116Smarcel//!
130240116Smarceltemplate< class IS >
131240116Smarcelclass tokenizer {
132240116Smarcel    IS& m_is;
133240116Smarcel    size_t m_lineno;
134240116Smarcel    token m_la;
135240116Smarcel
136240116Smarcel    bool m_skipws;
137240116Smarcel    token_type m_eof_type, m_nl_type, m_text_type;
138240116Smarcel
139240116Smarcel    std::map< char, token_type > m_delims_map;
140240116Smarcel    std::string m_delims_str;
141240116Smarcel
142240116Smarcel    char m_quotech;
143240116Smarcel    token_type m_quotetype;
144240116Smarcel
145240116Smarcel    std::map< std::string, token_type > m_keywords_map;
146240116Smarcel
147240116Smarcel    token_type alloc_type(void);
148240116Smarcel
149240116Smarcel    template< class TKZ >
150240116Smarcel    friend
151240116Smarcel    class parser;
152240116Smarcel
153240116Smarcelpublic:
154240116Smarcel    tokenizer(IS&, bool, const token_type&, const token_type&,
155240116Smarcel              const token_type&, size_t = 1);
156240116Smarcel
157240116Smarcel    size_t lineno(void) const;
158240116Smarcel
159240116Smarcel    void add_delim(char, const token_type&);
160240116Smarcel    void add_keyword(const std::string&, const token_type&);
161240116Smarcel    void add_quote(char, const token_type&);
162240116Smarcel
163240116Smarcel    token next(void);
164240116Smarcel    std::string rest_of_line(void);
165240116Smarcel};
166240116Smarcel
167240116Smarceltemplate< class IS >
168240116Smarceltokenizer< IS >::tokenizer(IS& p_is,
169240116Smarcel                           bool p_skipws,
170240116Smarcel                           const token_type& p_eof_type,
171240116Smarcel                           const token_type& p_nl_type,
172240116Smarcel                           const token_type& p_text_type,
173240116Smarcel                           size_t p_lineno) :
174240116Smarcel    m_is(p_is),
175240116Smarcel    m_lineno(p_lineno),
176240116Smarcel    m_skipws(p_skipws),
177240116Smarcel    m_eof_type(p_eof_type),
178240116Smarcel    m_nl_type(p_nl_type),
179240116Smarcel    m_text_type(p_text_type),
180240116Smarcel    m_quotech(-1)
181240116Smarcel{
182240116Smarcel}
183240116Smarcel
184240116Smarceltemplate< class IS >
185240116Smarcelsize_t
186240116Smarceltokenizer< IS >::lineno(void)
187240116Smarcel    const
188240116Smarcel{
189240116Smarcel    return m_lineno;
190240116Smarcel}
191240116Smarcel
192240116Smarceltemplate< class IS >
193240116Smarcelvoid
194240116Smarceltokenizer< IS >::add_delim(char delim, const token_type& type)
195240116Smarcel{
196240116Smarcel    m_delims_map[delim] = type;
197240116Smarcel    m_delims_str += delim;
198240116Smarcel}
199240116Smarcel
200240116Smarceltemplate< class IS >
201240116Smarcelvoid
202240116Smarceltokenizer< IS >::add_keyword(const std::string& keyword,
203240116Smarcel                             const token_type& type)
204240116Smarcel{
205240116Smarcel    m_keywords_map[keyword] = type;
206240116Smarcel}
207240116Smarcel
208240116Smarceltemplate< class IS >
209240116Smarcelvoid
210240116Smarceltokenizer< IS >::add_quote(char ch, const token_type& type)
211240116Smarcel{
212240116Smarcel    m_quotech = ch;
213240116Smarcel    m_quotetype = type;
214240116Smarcel}
215240116Smarcel
216240116Smarceltemplate< class IS >
217240116Smarceltoken
218240116Smarceltokenizer< IS >::next(void)
219240116Smarcel{
220240116Smarcel    if (m_la) {
221240116Smarcel        token t = m_la;
222240116Smarcel        m_la = token();
223240116Smarcel        if (t.type() == m_nl_type)
224240116Smarcel            m_lineno++;
225240116Smarcel        return t;
226240116Smarcel    }
227240116Smarcel
228240116Smarcel    char ch;
229240116Smarcel    std::string text;
230240116Smarcel
231240116Smarcel    bool done = false, quoted = false;
232240116Smarcel    token t(m_lineno, m_eof_type, "<<EOF>>");
233240116Smarcel    while (!done && m_is.get(ch).good()) {
234240116Smarcel        if (ch == m_quotech) {
235240116Smarcel            if (text.empty()) {
236240116Smarcel                bool escaped = false;
237240116Smarcel                while (!done && m_is.get(ch).good()) {
238240116Smarcel                    if (!escaped) {
239240116Smarcel                        if (ch == '\\')
240240116Smarcel                            escaped = true;
241240116Smarcel                        else if (ch == '\n') {
242240116Smarcel                            m_la = token(m_lineno, m_nl_type, "<<NEWLINE>>");
243240116Smarcel                            throw parse_error(t.lineno(),
244240116Smarcel                                              "Missing double quotes before "
245240116Smarcel                                              "end of line");
246240116Smarcel                        } else if (ch == m_quotech)
247240116Smarcel                            done = true;
248240116Smarcel                        else
249240116Smarcel                            text += ch;
250240116Smarcel                    } else {
251240116Smarcel                        text += ch;
252240116Smarcel                        escaped = false;
253240116Smarcel                    }
254240116Smarcel                }
255240116Smarcel                if (!m_is.good())
256240116Smarcel                    throw parse_error(t.lineno(),
257240116Smarcel                                      "Missing double quotes before "
258240116Smarcel                                      "end of file");
259240116Smarcel                t = token(m_lineno, m_text_type, text);
260240116Smarcel                quoted = true;
261240116Smarcel            } else {
262240116Smarcel                m_is.unget();
263240116Smarcel                done = true;
264240116Smarcel            }
265240116Smarcel        } else {
266240116Smarcel            typename std::map< char, token_type >::const_iterator idelim;
267240116Smarcel            idelim = m_delims_map.find(ch);
268240116Smarcel            if (idelim != m_delims_map.end()) {
269240116Smarcel                done = true;
270240116Smarcel                if (text.empty())
271240116Smarcel                    t = token(m_lineno, (*idelim).second,
272240116Smarcel                                   std::string("") + ch);
273240116Smarcel                else
274240116Smarcel                    m_is.unget();
275240116Smarcel            } else if (ch == '\n') {
276240116Smarcel                done = true;
277240116Smarcel                if (text.empty())
278240116Smarcel                    t = token(m_lineno, m_nl_type, "<<NEWLINE>>");
279240116Smarcel                else
280240116Smarcel                    m_is.unget();
281240116Smarcel            } else if (m_skipws && (ch == ' ' || ch == '\t')) {
282240116Smarcel                if (!text.empty())
283240116Smarcel                    done = true;
284240116Smarcel            } else
285240116Smarcel                text += ch;
286240116Smarcel        }
287240116Smarcel    }
288240116Smarcel
289240116Smarcel    if (!quoted && !text.empty()) {
290240116Smarcel        typename std::map< std::string, token_type >::const_iterator ikw;
291240116Smarcel        ikw = m_keywords_map.find(text);
292240116Smarcel        if (ikw != m_keywords_map.end())
293240116Smarcel            t = token(m_lineno, (*ikw).second, text);
294240116Smarcel        else
295240116Smarcel            t = token(m_lineno, m_text_type, text);
296240116Smarcel    }
297240116Smarcel
298240116Smarcel    if (t.type() == m_nl_type)
299240116Smarcel        m_lineno++;
300240116Smarcel
301240116Smarcel    return t;
302240116Smarcel}
303240116Smarcel
304240116Smarceltemplate< class IS >
305240116Smarcelstd::string
306240116Smarceltokenizer< IS >::rest_of_line(void)
307240116Smarcel{
308240116Smarcel    std::string str;
309240116Smarcel    while (m_is.good() && m_is.peek() != '\n')
310240116Smarcel        str += m_is.get();
311240116Smarcel    return str;
312240116Smarcel}
313240116Smarcel
314240116Smarcel// ------------------------------------------------------------------------
315240116Smarcel// The "parser" class.
316240116Smarcel// ------------------------------------------------------------------------
317240116Smarcel
318240116Smarceltemplate< class TKZ >
319240116Smarcelclass parser {
320240116Smarcel    TKZ& m_tkz;
321240116Smarcel    token m_last;
322240116Smarcel    parse_errors m_errors;
323240116Smarcel    bool m_thrown;
324240116Smarcel
325240116Smarcelpublic:
326240116Smarcel    parser(TKZ& tkz);
327240116Smarcel    ~parser(void);
328240116Smarcel
329240116Smarcel    bool good(void) const;
330240116Smarcel    void add_error(const parse_error&);
331240116Smarcel    bool has_errors(void) const;
332240116Smarcel
333240116Smarcel    token next(void);
334240116Smarcel    std::string rest_of_line(void);
335240116Smarcel    token reset(const token_type&);
336240116Smarcel
337240116Smarcel    token
338240116Smarcel    expect(const token_type&,
339240116Smarcel           const std::string&);
340240116Smarcel
341240116Smarcel    token
342240116Smarcel    expect(const token_type&,
343240116Smarcel           const token_type&,
344240116Smarcel           const std::string&);
345240116Smarcel
346240116Smarcel    token
347240116Smarcel    expect(const token_type&,
348240116Smarcel           const token_type&,
349240116Smarcel           const token_type&,
350240116Smarcel           const std::string&);
351240116Smarcel
352240116Smarcel    token
353240116Smarcel    expect(const token_type&,
354240116Smarcel           const token_type&,
355240116Smarcel           const token_type&,
356240116Smarcel           const token_type&,
357240116Smarcel           const std::string&);
358240116Smarcel
359240116Smarcel    token
360240116Smarcel    expect(const token_type&,
361240116Smarcel           const token_type&,
362240116Smarcel           const token_type&,
363240116Smarcel           const token_type&,
364240116Smarcel           const token_type&,
365240116Smarcel           const token_type&,
366240116Smarcel           const token_type&,
367240116Smarcel           const std::string&);
368240116Smarcel
369240116Smarcel    token
370240116Smarcel    expect(const token_type&,
371240116Smarcel           const token_type&,
372240116Smarcel           const token_type&,
373240116Smarcel           const token_type&,
374240116Smarcel           const token_type&,
375240116Smarcel           const token_type&,
376240116Smarcel           const token_type&,
377240116Smarcel           const token_type&,
378240116Smarcel           const std::string&);
379240116Smarcel};
380240116Smarcel
381240116Smarceltemplate< class TKZ >
382240116Smarcelparser< TKZ >::parser(TKZ& tkz) :
383240116Smarcel    m_tkz(tkz),
384240116Smarcel    m_thrown(false)
385240116Smarcel{
386240116Smarcel}
387240116Smarcel
388240116Smarceltemplate< class TKZ >
389240116Smarcelparser< TKZ >::~parser(void)
390240116Smarcel{
391240116Smarcel    if (!m_errors.empty() && !m_thrown)
392240116Smarcel        throw m_errors;
393240116Smarcel}
394240116Smarcel
395240116Smarceltemplate< class TKZ >
396240116Smarcelbool
397240116Smarcelparser< TKZ >::good(void)
398240116Smarcel    const
399240116Smarcel{
400240116Smarcel    return m_tkz.m_is.good();
401240116Smarcel}
402240116Smarcel
403240116Smarceltemplate< class TKZ >
404240116Smarcelvoid
405240116Smarcelparser< TKZ >::add_error(const parse_error& pe)
406240116Smarcel{
407240116Smarcel    m_errors.push_back(pe);
408240116Smarcel}
409240116Smarcel
410240116Smarceltemplate< class TKZ >
411240116Smarcelbool
412240116Smarcelparser< TKZ >::has_errors(void)
413240116Smarcel    const
414240116Smarcel{
415240116Smarcel    return !m_errors.empty();
416240116Smarcel}
417240116Smarcel
418240116Smarceltemplate< class TKZ >
419240116Smarceltoken
420240116Smarcelparser< TKZ >::next(void)
421240116Smarcel{
422240116Smarcel    token t = m_tkz.next();
423240116Smarcel
424240116Smarcel    m_last = t;
425240116Smarcel
426240116Smarcel    if (t.type() == m_tkz.m_eof_type) {
427240116Smarcel        if (!m_errors.empty()) {
428240116Smarcel            m_thrown = true;
429240116Smarcel            throw m_errors;
430240116Smarcel        }
431240116Smarcel    }
432240116Smarcel
433240116Smarcel    return t;
434240116Smarcel}
435240116Smarcel
436240116Smarceltemplate< class TKZ >
437240116Smarcelstd::string
438240116Smarcelparser< TKZ >::rest_of_line(void)
439240116Smarcel{
440240116Smarcel    return m_tkz.rest_of_line();
441240116Smarcel}
442240116Smarcel
443240116Smarceltemplate< class TKZ >
444240116Smarceltoken
445240116Smarcelparser< TKZ >::reset(const token_type& stop)
446240116Smarcel{
447240116Smarcel    token t = m_last;
448240116Smarcel
449240116Smarcel    while (t.type() != m_tkz.m_eof_type && t.type() != stop)
450240116Smarcel        t = next();
451240116Smarcel
452240116Smarcel    return t;
453240116Smarcel}
454240116Smarcel
455240116Smarceltemplate< class TKZ >
456240116Smarceltoken
457240116Smarcelparser< TKZ >::expect(const token_type& t1,
458240116Smarcel                      const std::string& textual)
459240116Smarcel{
460240116Smarcel    token t = next();
461240116Smarcel
462240116Smarcel    if (t.type() != t1)
463240116Smarcel        throw parse_error(t.lineno(),
464240116Smarcel                          "Unexpected token `" + t.text() +
465240116Smarcel                          "'; expected " + textual);
466240116Smarcel
467240116Smarcel    return t;
468240116Smarcel}
469240116Smarcel
470240116Smarceltemplate< class TKZ >
471240116Smarceltoken
472240116Smarcelparser< TKZ >::expect(const token_type& t1,
473240116Smarcel                      const token_type& t2,
474240116Smarcel                      const std::string& textual)
475240116Smarcel{
476240116Smarcel    token t = next();
477240116Smarcel
478240116Smarcel    if (t.type() != t1 && t.type() != t2)
479240116Smarcel        throw parse_error(t.lineno(),
480240116Smarcel                          "Unexpected token `" + t.text() +
481240116Smarcel                          "'; expected " + textual);
482240116Smarcel
483240116Smarcel    return t;
484240116Smarcel}
485240116Smarcel
486240116Smarceltemplate< class TKZ >
487240116Smarceltoken
488240116Smarcelparser< TKZ >::expect(const token_type& t1,
489240116Smarcel                      const token_type& t2,
490240116Smarcel                      const token_type& t3,
491240116Smarcel                      const std::string& textual)
492240116Smarcel{
493240116Smarcel    token t = next();
494240116Smarcel
495240116Smarcel    if (t.type() != t1 && t.type() != t2 && t.type() != t3)
496240116Smarcel        throw parse_error(t.lineno(),
497240116Smarcel                          "Unexpected token `" + t.text() +
498240116Smarcel                          "'; expected " + textual);
499240116Smarcel
500240116Smarcel    return t;
501240116Smarcel}
502240116Smarcel
503240116Smarceltemplate< class TKZ >
504240116Smarceltoken
505240116Smarcelparser< TKZ >::expect(const token_type& t1,
506240116Smarcel                      const token_type& t2,
507240116Smarcel                      const token_type& t3,
508240116Smarcel                      const token_type& t4,
509240116Smarcel                      const std::string& textual)
510240116Smarcel{
511240116Smarcel    token t = next();
512240116Smarcel
513240116Smarcel    if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
514240116Smarcel        t.type() != t4)
515240116Smarcel        throw parse_error(t.lineno(),
516240116Smarcel                          "Unexpected token `" + t.text() +
517240116Smarcel                          "'; expected " + textual);
518240116Smarcel
519240116Smarcel    return t;
520240116Smarcel}
521240116Smarcel
522240116Smarceltemplate< class TKZ >
523240116Smarceltoken
524240116Smarcelparser< TKZ >::expect(const token_type& t1,
525240116Smarcel                      const token_type& t2,
526240116Smarcel                      const token_type& t3,
527240116Smarcel                      const token_type& t4,
528240116Smarcel                      const token_type& t5,
529240116Smarcel                      const token_type& t6,
530240116Smarcel                      const token_type& t7,
531240116Smarcel                      const std::string& textual)
532240116Smarcel{
533240116Smarcel    token t = next();
534240116Smarcel
535240116Smarcel    if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
536240116Smarcel        t.type() != t4 && t.type() != t5 && t.type() != t6 &&
537240116Smarcel        t.type() != t7)
538240116Smarcel        throw parse_error(t.lineno(),
539240116Smarcel                          "Unexpected token `" + t.text() +
540240116Smarcel                          "'; expected " + textual);
541240116Smarcel
542240116Smarcel    return t;
543240116Smarcel}
544240116Smarcel
545240116Smarceltemplate< class TKZ >
546240116Smarceltoken
547240116Smarcelparser< TKZ >::expect(const token_type& t1,
548240116Smarcel                      const token_type& t2,
549240116Smarcel                      const token_type& t3,
550240116Smarcel                      const token_type& t4,
551240116Smarcel                      const token_type& t5,
552240116Smarcel                      const token_type& t6,
553240116Smarcel                      const token_type& t7,
554240116Smarcel                      const token_type& t8,
555240116Smarcel                      const std::string& textual)
556240116Smarcel{
557240116Smarcel    token t = next();
558240116Smarcel
559240116Smarcel    if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
560240116Smarcel        t.type() != t4 && t.type() != t5 && t.type() != t6 &&
561240116Smarcel        t.type() != t7 && t.type() != t8)
562240116Smarcel        throw parse_error(t.lineno(),
563240116Smarcel                          "Unexpected token `" + t.text() +
564240116Smarcel                          "'; expected " + textual);
565240116Smarcel
566240116Smarcel    return t;
567240116Smarcel}
568240116Smarcel
569240116Smarcel#define ATF_PARSER_CALLBACK(parser, func) \
570240116Smarcel    do { \
571240116Smarcel        if (!(parser).has_errors()) \
572240116Smarcel            func; \
573240116Smarcel    } while (false)
574240116Smarcel
575240116Smarcel// ------------------------------------------------------------------------
576240116Smarcel// Header parsing.
577240116Smarcel// ------------------------------------------------------------------------
578240116Smarcel
579240116Smarceltypedef std::map< std::string, std::string > attrs_map;
580240116Smarcel
581240116Smarcelclass header_entry {
582240116Smarcel    std::string m_name;
583240116Smarcel    std::string m_value;
584240116Smarcel    attrs_map m_attrs;
585240116Smarcel
586240116Smarcelpublic:
587240116Smarcel    header_entry(void);
588240116Smarcel    header_entry(const std::string&, const std::string&,
589240116Smarcel                 attrs_map = attrs_map());
590240116Smarcel
591240116Smarcel    const std::string& name(void) const;
592240116Smarcel    const std::string& value(void) const;
593240116Smarcel    const attrs_map& attrs(void) const;
594240116Smarcel    bool has_attr(const std::string&) const;
595240116Smarcel    const std::string& get_attr(const std::string&) const;
596240116Smarcel};
597240116Smarcel
598240116Smarceltypedef std::map< std::string, header_entry > headers_map;
599240116Smarcel
600240116Smarcelstd::pair< size_t, headers_map > read_headers(std::istream&, size_t);
601240116Smarcelvoid write_headers(const headers_map&, std::ostream&);
602240116Smarcelvoid validate_content_type(const headers_map&, const std::string&, int);
603240116Smarcel
604240116Smarcel} // namespace parser
605240116Smarcel} // namespace atf
606240116Smarcel
607240116Smarcel#endif // !defined(_ATF_CXX_PARSER_HPP_)
608