1 /*
2  *
3  * Copyright (c) 1998-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         basic_regex.cpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Declares template class basic_regex.
17   */
18 
19 #ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP
20 #define BOOST_REGEX_V4_BASIC_REGEX_HPP
21 
22 #ifdef BOOST_HAS_ABI_HEADERS
23 #  include BOOST_ABI_PREFIX
24 #endif
25 
26 namespace boost{
27 #ifdef BOOST_MSVC
28 #pragma warning(push)
29 #pragma warning(disable : 4251 4231 4660)
30 #endif
31 
32 namespace re_detail{
33 
34 //
35 // forward declaration, we will need this one later:
36 //
37 template <class charT, class traits>
38 class basic_regex_parser;
39 
40 //
41 // class regex_data:
42 // represents the data we wish to expose to the matching algorithms.
43 //
44 template <class charT, class traits>
45 struct regex_data
46 {
47    typedef regex_constants::syntax_option_type   flag_type;
48    typedef std::size_t                           size_type;
49 
regex_databoost::re_detail::regex_data50    regex_data(const ::boost::shared_ptr<
51       ::boost::regex_traits_wrapper<traits> >& t)
52       : m_ptraits(t), m_expression(0), m_expression_len(0) {}
regex_databoost::re_detail::regex_data53    regex_data()
54       : m_ptraits(new ::boost::regex_traits_wrapper<traits>()), m_expression(0), m_expression_len(0) {}
55 
56    ::boost::shared_ptr<
57       ::boost::regex_traits_wrapper<traits>
58       >                        m_ptraits;                 // traits class instance
59    flag_type                   m_flags;                   // flags with which we were compiled
60    int                         m_status;                  // error code (0 implies OK).
61    const charT*                m_expression;              // the original expression
62    std::ptrdiff_t              m_expression_len;          // the length of the original expression
63    size_type                   m_mark_count;              // the number of marked sub-expressions
64    re_detail::re_syntax_base*  m_first_state;             // the first state of the machine
65    unsigned                    m_restart_type;            // search optimisation type
66    unsigned char               m_startmap[1 << CHAR_BIT]; // which characters can start a match
67    unsigned int                m_can_be_null;             // whether we can match a null string
68    re_detail::raw_storage      m_data;                    // the buffer in which our states are constructed
69 };
70 //
71 // class basic_regex_implementation
72 // pimpl implementation class for basic_regex.
73 //
74 template <class charT, class traits>
75 class basic_regex_implementation
76    : public regex_data<charT, traits>
77 {
78 public:
79    typedef regex_constants::syntax_option_type   flag_type;
80    typedef std::ptrdiff_t                        difference_type;
81    typedef std::size_t                           size_type;
82    typedef typename traits::locale_type          locale_type;
83    typedef const charT*                          const_iterator;
84 
basic_regex_implementation()85    basic_regex_implementation(){}
basic_regex_implementation(const::boost::shared_ptr<::boost::regex_traits_wrapper<traits>> & t)86    basic_regex_implementation(const ::boost::shared_ptr<
87       ::boost::regex_traits_wrapper<traits> >& t)
88       : regex_data<charT, traits>(t) {}
assign(const charT * arg_first,const charT * arg_last,flag_type f)89    void assign(const charT* arg_first,
90                           const charT* arg_last,
91                           flag_type f)
92    {
93       regex_data<charT, traits>* pdat = this;
94       basic_regex_parser<charT, traits> parser(pdat);
95       parser.parse(arg_first, arg_last, f);
96    }
97 
imbue(locale_type l)98    locale_type BOOST_REGEX_CALL imbue(locale_type l)
99    {
100       return this->m_ptraits->imbue(l);
101    }
getloc() const102    locale_type BOOST_REGEX_CALL getloc()const
103    {
104       return this->m_ptraits->getloc();
105    }
str() const106    std::basic_string<charT> BOOST_REGEX_CALL str()const
107    {
108       std::basic_string<charT> result;
109       if(this->m_status == 0)
110          result = std::basic_string<charT>(this->m_expression, this->m_expression_len);
111       return result;
112    }
expression() const113    const_iterator BOOST_REGEX_CALL expression()const
114    {
115       return this->m_expression;
116    }
117    //
118    // begin, end:
begin() const119    const_iterator BOOST_REGEX_CALL begin()const
120    {
121       return (!this->m_status ? 0 : this->m_expression);
122    }
end() const123    const_iterator BOOST_REGEX_CALL end()const
124    {
125       return (!this->m_status ? 0 : this->m_expression + this->m_expression_len);
126    }
flags() const127    flag_type BOOST_REGEX_CALL flags()const
128    {
129       return this->m_flags;
130    }
size() const131    size_type BOOST_REGEX_CALL size()const
132    {
133       return this->m_expression_len;
134    }
status() const135    int BOOST_REGEX_CALL status()const
136    {
137       return this->m_status;
138    }
mark_count() const139    size_type BOOST_REGEX_CALL mark_count()const
140    {
141       return this->m_mark_count;
142    }
get_first_state() const143    const re_detail::re_syntax_base* get_first_state()const
144    {
145       return this->m_first_state;
146    }
get_restart_type() const147    unsigned get_restart_type()const
148    {
149       return this->m_restart_type;
150    }
get_map() const151    const unsigned char* get_map()const
152    {
153       return this->m_startmap;
154    }
get_traits() const155    const ::boost::regex_traits_wrapper<traits>& get_traits()const
156    {
157       return *(this->m_ptraits);
158    }
can_be_null() const159    bool can_be_null()const
160    {
161       return this->m_can_be_null;
162    }
get_data() const163    const regex_data<charT, traits>& get_data()const
164    {
165       basic_regex_implementation<charT, traits> const* p = this;
166       return *static_cast<const regex_data<charT, traits>*>(p);
167    }
168 };
169 
170 } // namespace re_detail
171 //
172 // class basic_regex:
173 // represents the compiled
174 // regular expression:
175 //
176 
177 #ifdef BOOST_REGEX_NO_FWD
178 template <class charT, class traits = regex_traits<charT> >
179 #else
180 template <class charT, class traits >
181 #endif
182 class basic_regex : public regbase
183 {
184 public:
185    // typedefs:
186    typedef typename traits::size_type            traits_size_type;
187    typedef typename traits::string_type          traits_string_type;
188    typedef charT                                 char_type;
189    typedef traits                                traits_type;
190 
191    typedef charT                                 value_type;
192    typedef charT&                                reference;
193    typedef const charT&                          const_reference;
194    typedef const charT*                          const_iterator;
195    typedef const_iterator                        iterator;
196    typedef std::ptrdiff_t                        difference_type;
197    typedef std::size_t                           size_type;
198    typedef regex_constants::syntax_option_type   flag_type;
199    // locale_type
200    // placeholder for actual locale type used by the
201    // traits class to localise *this.
202    typedef typename traits::locale_type          locale_type;
203 
204 public:
basic_regex()205    explicit basic_regex(){}
basic_regex(const charT * p,flag_type f=regex_constants::normal)206    explicit basic_regex(const charT* p, flag_type f = regex_constants::normal)
207    {
208       assign(p, f);
209    }
basic_regex(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)210    basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
211    {
212       assign(p1, p2, f);
213    }
basic_regex(const charT * p,size_type len,flag_type f)214    basic_regex(const charT* p, size_type len, flag_type f)
215    {
216       assign(p, len, f);
217    }
basic_regex(const basic_regex & that)218    basic_regex(const basic_regex& that)
219       : m_pimpl(that.m_pimpl) {}
~basic_regex()220    ~basic_regex(){}
operator =(const basic_regex & that)221    basic_regex& BOOST_REGEX_CALL operator=(const basic_regex& that)
222    {
223       return assign(that);
224    }
operator =(const charT * ptr)225    basic_regex& BOOST_REGEX_CALL operator=(const charT* ptr)
226    {
227       return assign(ptr);
228    }
229 
230    //
231    // assign:
assign(const basic_regex & that)232    basic_regex& assign(const basic_regex& that)
233    {
234       m_pimpl = that.m_pimpl;
235       return *this;
236    }
assign(const charT * p,flag_type f=regex_constants::normal)237    basic_regex& assign(const charT* p, flag_type f = regex_constants::normal)
238    {
239       return assign(p, p + traits::length(p), f);
240    }
assign(const charT * p,size_type len,flag_type f)241    basic_regex& assign(const charT* p, size_type len, flag_type f)
242    {
243       return assign(p, p + len, f);
244    }
245 private:
246    basic_regex& do_assign(const charT* p1,
247                           const charT* p2,
248                           flag_type f);
249 public:
assign(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)250    basic_regex& assign(const charT* p1,
251                           const charT* p2,
252                           flag_type f = regex_constants::normal)
253    {
254       return do_assign(p1, p2, f);
255    }
256 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
257 
258    template <class ST, class SA>
set_expression(const std::basic_string<charT,ST,SA> & p,flag_type f=regex_constants::normal)259    unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
260    {
261       return set_expression(p.data(), p.data() + p.size(), f);
262    }
263 
264    template <class ST, class SA>
basic_regex(const std::basic_string<charT,ST,SA> & p,flag_type f=regex_constants::normal)265    explicit basic_regex(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
266    {
267       assign(p, f);
268    }
269 
270    template <class InputIterator>
basic_regex(InputIterator arg_first,InputIterator arg_last,flag_type f=regex_constants::normal)271    basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
272    {
273       typedef typename traits::string_type seq_type;
274       seq_type a(arg_first, arg_last);
275       if(a.size())
276          assign(&*a.begin(), &*a.begin() + a.size(), f);
277       else
278          assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
279    }
280 
281    template <class ST, class SA>
operator =(const std::basic_string<charT,ST,SA> & p)282    basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p)
283    {
284       return assign(p.data(), p.data() + p.size(), regex_constants::normal);
285    }
286 
287    template <class string_traits, class A>
assign(const std::basic_string<charT,string_traits,A> & s,flag_type f=regex_constants::normal)288    basic_regex& BOOST_REGEX_CALL assign(
289        const std::basic_string<charT, string_traits, A>& s,
290        flag_type f = regex_constants::normal)
291    {
292       return assign(s.data(), s.data() + s.size(), f);
293    }
294 
295    template <class InputIterator>
assign(InputIterator arg_first,InputIterator arg_last,flag_type f=regex_constants::normal)296    basic_regex& BOOST_REGEX_CALL assign(InputIterator arg_first,
297                           InputIterator arg_last,
298                           flag_type f = regex_constants::normal)
299    {
300       typedef typename traits::string_type seq_type;
301       seq_type a(arg_first, arg_last);
302       if(a.size())
303       {
304          const charT* p1 = &*a.begin();
305          const charT* p2 = &*a.begin() + a.size();
306          return assign(p1, p2, f);
307       }
308       return assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
309    }
310 #else
set_expression(const std::basic_string<charT> & p,flag_type f=regex_constants::normal)311    unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
312    {
313       return set_expression(p.data(), p.data() + p.size(), f);
314    }
315 
basic_regex(const std::basic_string<charT> & p,flag_type f=regex_constants::normal)316    basic_regex(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
317    {
318       assign(p, f);
319    }
320 
operator =(const std::basic_string<charT> & p)321    basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p)
322    {
323       return assign(p.data(), p.data() + p.size(), regex_constants::normal);
324    }
325 
assign(const std::basic_string<charT> & s,flag_type f=regex_constants::normal)326    basic_regex& BOOST_REGEX_CALL assign(
327        const std::basic_string<charT>& s,
328        flag_type f = regex_constants::normal)
329    {
330       return assign(s.data(), s.data() + s.size(), f);
331    }
332 
333 #endif
334 
335    //
336    // locale:
337    locale_type BOOST_REGEX_CALL imbue(locale_type l);
getloc() const338    locale_type BOOST_REGEX_CALL getloc()const
339    {
340       return m_pimpl.get() ? m_pimpl->getloc() : locale_type();
341    }
342    //
343    // getflags:
344    // retained for backwards compatibility only, "flags"
345    // is now the prefered name:
getflags() const346    flag_type BOOST_REGEX_CALL getflags()const
347    {
348       return flags();
349    }
flags() const350    flag_type BOOST_REGEX_CALL flags()const
351    {
352       return m_pimpl.get() ? m_pimpl->flags() : 0;
353    }
354    //
355    // str:
str() const356    std::basic_string<charT> BOOST_REGEX_CALL str()const
357    {
358       return m_pimpl.get() ? m_pimpl->str() : std::basic_string<charT>();
359    }
360    //
361    // begin, end:
begin() const362    const_iterator BOOST_REGEX_CALL begin()const
363    {
364       return (m_pimpl.get() ? m_pimpl->begin() : 0);
365    }
end() const366    const_iterator BOOST_REGEX_CALL end()const
367    {
368       return (m_pimpl.get() ? m_pimpl->end() : 0);
369    }
370    //
371    // swap:
swap(basic_regex & that)372    void BOOST_REGEX_CALL swap(basic_regex& that)throw()
373    {
374       m_pimpl.swap(that.m_pimpl);
375    }
376    //
377    // size:
size() const378    size_type BOOST_REGEX_CALL size()const
379    {
380       return (m_pimpl.get() ? m_pimpl->size() : 0);
381    }
382    //
383    // max_size:
max_size() const384    size_type BOOST_REGEX_CALL max_size()const
385    {
386       return UINT_MAX;
387    }
388    //
389    // empty:
empty() const390    bool BOOST_REGEX_CALL empty()const
391    {
392       return (m_pimpl.get() ? 0 != m_pimpl->status() : true);
393    }
394 
mark_count() const395    size_type BOOST_REGEX_CALL mark_count()const
396    {
397       return (m_pimpl.get() ? m_pimpl->mark_count() : 0);
398    }
399 
status() const400    int status()const
401    {
402       return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty);
403    }
404 
compare(const basic_regex & that) const405    int BOOST_REGEX_CALL compare(const basic_regex& that) const
406    {
407       if(m_pimpl.get() == that.m_pimpl.get())
408          return 0;
409       if(!m_pimpl.get())
410          return -1;
411       if(!that.m_pimpl.get())
412          return 1;
413       if(status() != that.status())
414          return status() - that.status();
415       if(flags() != that.flags())
416          return flags() - that.flags();
417       return str().compare(that.str());
418    }
operator ==(const basic_regex & e) const419    bool BOOST_REGEX_CALL operator==(const basic_regex& e)const
420    {
421       return compare(e) == 0;
422    }
operator !=(const basic_regex & e) const423    bool BOOST_REGEX_CALL operator != (const basic_regex& e)const
424    {
425       return compare(e) != 0;
426    }
operator <(const basic_regex & e) const427    bool BOOST_REGEX_CALL operator<(const basic_regex& e)const
428    {
429       return compare(e) < 0;
430    }
operator >(const basic_regex & e) const431    bool BOOST_REGEX_CALL operator>(const basic_regex& e)const
432    {
433       return compare(e) > 0;
434    }
operator <=(const basic_regex & e) const435    bool BOOST_REGEX_CALL operator<=(const basic_regex& e)const
436    {
437       return compare(e) <= 0;
438    }
operator >=(const basic_regex & e) const439    bool BOOST_REGEX_CALL operator>=(const basic_regex& e)const
440    {
441       return compare(e) >= 0;
442    }
443 
444    //
445    // The following are deprecated as public interfaces
446    // but are available for compatibility with earlier versions.
expression() const447    const charT* BOOST_REGEX_CALL expression()const
448    {
449       return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0);
450    }
set_expression(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)451    unsigned int BOOST_REGEX_CALL set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
452    {
453       assign(p1, p2, f | regex_constants::no_except);
454       return status();
455    }
set_expression(const charT * p,flag_type f=regex_constants::normal)456    unsigned int BOOST_REGEX_CALL set_expression(const charT* p, flag_type f = regex_constants::normal)
457    {
458       assign(p, f | regex_constants::no_except);
459       return status();
460    }
error_code() const461    unsigned int BOOST_REGEX_CALL error_code()const
462    {
463       return status();
464    }
465    //
466    // private access methods:
467    //
get_first_state() const468    const re_detail::re_syntax_base* get_first_state()const
469    {
470       BOOST_ASSERT(0 != m_pimpl.get());
471       return m_pimpl->get_first_state();
472    }
get_restart_type() const473    unsigned get_restart_type()const
474    {
475       BOOST_ASSERT(0 != m_pimpl.get());
476       return m_pimpl->get_restart_type();
477    }
get_map() const478    const unsigned char* get_map()const
479    {
480       BOOST_ASSERT(0 != m_pimpl.get());
481       return m_pimpl->get_map();
482    }
get_traits() const483    const ::boost::regex_traits_wrapper<traits>& get_traits()const
484    {
485       BOOST_ASSERT(0 != m_pimpl.get());
486       return m_pimpl->get_traits();
487    }
can_be_null() const488    bool can_be_null()const
489    {
490       BOOST_ASSERT(0 != m_pimpl.get());
491       return m_pimpl->can_be_null();
492    }
get_data() const493    const re_detail::regex_data<charT, traits>& get_data()const
494    {
495       BOOST_ASSERT(0 != m_pimpl.get());
496       return m_pimpl->get_data();
497    }
498 
499 private:
500    shared_ptr<re_detail::basic_regex_implementation<charT, traits> > m_pimpl;
501 };
502 
503 //
504 // out of line members;
505 // these are the only members that mutate the basic_regex object,
506 // and are designed to provide the strong exception guarentee
507 // (in the event of a throw, the state of the object remains unchanged).
508 //
509 template <class charT, class traits>
do_assign(const charT * p1,const charT * p2,flag_type f)510 basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1,
511                         const charT* p2,
512                         flag_type f)
513 {
514    shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp;
515    if(!m_pimpl.get())
516    {
517       temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>());
518    }
519    else
520    {
521       temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits));
522    }
523    temp->assign(p1, p2, f);
524    temp.swap(m_pimpl);
525    return *this;
526 }
527 
528 template <class charT, class traits>
imbue(locale_type l)529 typename basic_regex<charT, traits>::locale_type BOOST_REGEX_CALL basic_regex<charT, traits>::imbue(locale_type l)
530 {
531    shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp(new re_detail::basic_regex_implementation<charT, traits>());
532    locale_type result = temp->imbue(l);
533    temp.swap(m_pimpl);
534    return result;
535 }
536 
537 //
538 // non-members:
539 //
540 template <class charT, class traits>
swap(basic_regex<charT,traits> & e1,basic_regex<charT,traits> & e2)541 void swap(basic_regex<charT, traits>& e1, basic_regex<charT, traits>& e2)
542 {
543    e1.swap(e2);
544 }
545 
546 #ifndef BOOST_NO_STD_LOCALE
547 template <class charT, class traits, class traits2>
548 std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const basic_regex<charT,traits2> & e)549    operator << (std::basic_ostream<charT, traits>& os,
550                 const basic_regex<charT, traits2>& e)
551 {
552    return (os << e.str());
553 }
554 #else
555 template <class traits>
operator <<(std::ostream & os,const basic_regex<char,traits> & e)556 std::ostream& operator << (std::ostream& os, const basic_regex<char, traits>& e)
557 {
558    return (os << e.str());
559 }
560 #endif
561 
562 //
563 // class reg_expression:
564 // this is provided for backwards compatibility only,
565 // it is deprecated, no not use!
566 //
567 #ifdef BOOST_REGEX_NO_FWD
568 template <class charT, class traits = regex_traits<charT> >
569 #else
570 template <class charT, class traits >
571 #endif
572 class reg_expression : public basic_regex<charT, traits>
573 {
574 public:
575    typedef typename basic_regex<charT, traits>::flag_type flag_type;
576    typedef typename basic_regex<charT, traits>::size_type size_type;
reg_expression()577    explicit reg_expression(){}
reg_expression(const charT * p,flag_type f=regex_constants::normal)578    explicit reg_expression(const charT* p, flag_type f = regex_constants::normal)
579       : basic_regex<charT, traits>(p, f){}
reg_expression(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)580    reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
581       : basic_regex<charT, traits>(p1, p2, f){}
reg_expression(const charT * p,size_type len,flag_type f)582    reg_expression(const charT* p, size_type len, flag_type f)
583       : basic_regex<charT, traits>(p, len, f){}
reg_expression(const reg_expression & that)584    reg_expression(const reg_expression& that)
585       : basic_regex<charT, traits>(that) {}
~reg_expression()586    ~reg_expression(){}
operator =(const reg_expression & that)587    reg_expression& BOOST_REGEX_CALL operator=(const reg_expression& that)
588    {
589       return this->assign(that);
590    }
591 
592 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
593    template <class ST, class SA>
reg_expression(const std::basic_string<charT,ST,SA> & p,flag_type f=regex_constants::normal)594    explicit reg_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
595    : basic_regex<charT, traits>(p, f)
596    {
597    }
598 
599    template <class InputIterator>
reg_expression(InputIterator arg_first,InputIterator arg_last,flag_type f=regex_constants::normal)600    reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
601    : basic_regex<charT, traits>(arg_first, arg_last, f)
602    {
603    }
604 
605    template <class ST, class SA>
operator =(const std::basic_string<charT,ST,SA> & p)606    reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p)
607    {
608       this->assign(p);
609       return *this;
610    }
611 #else
reg_expression(const std::basic_string<charT> & p,flag_type f=regex_constants::normal)612    explicit reg_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
613    : basic_regex<charT, traits>(p, f)
614    {
615    }
616 
operator =(const std::basic_string<charT> & p)617    reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p)
618    {
619       this->assign(p);
620       return *this;
621    }
622 #endif
623 
624 };
625 
626 #ifdef BOOST_MSVC
627 #pragma warning (pop)
628 #endif
629 
630 } // namespace boost
631 
632 #ifdef BOOST_HAS_ABI_HEADERS
633 #  include BOOST_ABI_SUFFIX
634 #endif
635 
636 #endif
637 
638