1 /*
2  *
3  * Copyright (c) 2004
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the
7  * Boost Software License, Version 1.0. (See accompanying file
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11 
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE         info.hpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Error handling for test cases.
17   */
18 
19 #ifndef BOOST_REGEX_REGRESS_INFO_HPP
20 #define BOOST_REGEX_REGRESS_INFO_HPP
21 #include <iostream>
22 #include <string>
23 #include <boost/regex.hpp>
24 
25 #ifdef TEST_THREADS
26 #include <boost/thread/once.hpp>
27 #include <boost/thread.hpp>
28 #endif
29 //
30 // class test info,
31 // store information about the test we are about to conduct:
32 //
33 template <class charT>
34 class test_info_base
35 {
36 public:
37    typedef std::basic_string<charT> string_type;
38 private:
39    struct data_type
40    {
41       std::string file;
42       int line;
43       string_type expression;
44       boost::regex_constants::syntax_option_type options;
45       string_type search_text;
46       boost::regex_constants::match_flag_type match_options;
47       const int* answer_table;
48       string_type format_string;
49       string_type result_string;
50       bool need_to_print;
51       std::string expression_type_name;
52    };
53 #ifdef TEST_THREADS
do_get_data()54    static data_type& do_get_data()
55    {
56       static boost::thread_specific_ptr<data_type> pd;
57       if(pd.get() == 0)
58          pd.reset(new data_type());
59       return *(pd.get());
60    }
init_data()61    static void init_data()
62    {
63       do_get_data();
64    }
65 #endif
data()66    static data_type& data()
67    {
68 #ifdef TEST_THREADS
69       static boost::once_flag f = BOOST_ONCE_INIT;
70       boost::call_once(f,&init_data);
71       return do_get_data();
72 #else
73       static data_type d;
74       return d;
75 #endif
76    }
77 public:
test_info_base()78    test_info_base(){};
set_info(const char * file,int line,const string_type & ex,boost::regex_constants::syntax_option_type opt,const string_type & search_text=string_type (),boost::regex_constants::match_flag_type match_options=boost::match_default,const int * answer_table=0,const string_type & format_string=string_type (),const string_type & result_string=string_type ())79    static void set_info(
80       const char* file,
81       int line,
82       const string_type& ex,
83       boost::regex_constants::syntax_option_type opt,
84       const string_type& search_text = string_type(),
85       boost::regex_constants::match_flag_type match_options = boost::match_default,
86       const int* answer_table = 0,
87       const string_type& format_string = string_type(),
88       const string_type& result_string = string_type())
89    {
90       data_type& dat = data();
91       dat.file = file;
92       dat.line = line;
93       dat.expression = ex;
94       dat.options = opt;
95       dat.search_text = search_text;
96       dat.match_options = match_options;
97       dat.answer_table = answer_table;
98       dat.format_string = format_string;
99       dat.result_string = result_string;
100       dat.need_to_print = true;
101    }
set_typename(const std::string & n)102    static void set_typename(const std::string& n)
103    {
104       data().expression_type_name = n;
105    }
106 
expression()107    static const string_type& expression()
108    {
109       return data().expression;
110    }
syntax_options()111    static boost::regex_constants::syntax_option_type syntax_options()
112    {
113       return data().options;
114    }
search_text()115    static const string_type& search_text()
116    {
117       return data().search_text;
118    }
match_options()119    static boost::regex_constants::match_flag_type match_options()
120    {
121       return data().match_options;
122    }
answer_table()123    static const int* answer_table()
124    {
125       return data().answer_table;
126    }
format_string()127    static const string_type& format_string()
128    {
129       return data().format_string;
130    }
result_string()131    static const string_type& result_string()
132    {
133       return data().result_string;
134    }
need_to_print()135    static bool need_to_print()
136    {
137       return data().need_to_print;
138    }
file()139    static const std::string& file()
140    {
141       return data().file;
142    }
line()143    static int line()
144    {
145       return data().line;
146    }
clear()147    static void clear()
148    {
149       data().need_to_print = false;
150    }
expression_typename()151    static std::string& expression_typename()
152    {
153       return data().expression_type_name;
154    }
155 };
156 
157 template <class T>
158 struct test_info
159    : public test_info_base<wchar_t>
160 {};
161 
162 template<>
163 struct test_info<char>
164    : public test_info_base<char>
165 {};
166 
167 #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
168 
169 // Some template instantiation modes (namely local, implicit local, and weak) of
170 // this compiler need an explicit instantiation because otherwise we end up with
171 // multiple copies of the static variable defined in this method. This explicit
172 // instantiation generates the static variable with common linkage, which makes
173 // the linker choose only one of the available definitions. For more details,
174 // see "man ld".
175 
176 template test_info_base<wchar_t>::data_type & test_info_base<wchar_t>::data();
177 template test_info_base<char>::data_type & test_info_base<char>::data();
178 
179 #endif
180 
181 template <class charT>
operator <<(std::ostream & os,const test_info<charT> &)182 std::ostream& operator<<(std::ostream& os, const test_info<charT>&)
183 {
184    if(test_info<charT>::need_to_print())
185    {
186       os << test_info<charT>::file() << ":" << test_info<charT>::line() << ": Error in test here:" << std::endl;
187       test_info<charT>::clear();
188    }
189    return os;
190 }
191 //
192 // define some test macros:
193 //
194 extern int error_count;
195 
196 #define BOOST_REGEX_TEST_ERROR(msg, charT)\
197    ++error_count;\
198    std::cerr << test_info<charT>();\
199    std::cerr << "  " << __FILE__ << ":" << __LINE__ << ":" << msg \
200              << " (While testing " << test_info<charT>::expression_typename() << ")" << std::endl
201 
202 class errors_as_warnings
203 {
204 public:
errors_as_warnings()205    errors_as_warnings()
206    {
207       m_saved_error_count = error_count;
208    }
~errors_as_warnings()209    ~errors_as_warnings()
210    {
211       if(m_saved_error_count != error_count)
212       {
213          std::cerr << "<note>The above " << (error_count - m_saved_error_count) << " errors are treated as warnings only.</note>" << std::endl;
214          error_count = m_saved_error_count;
215       }
216    }
217 private:
218    int m_saved_error_count;
219 };
220 
221 #endif
222 
223