code:
//  Boost rational.hpp header file  ------------------------------------------//

//  (C) Copyright Paul Moore 1999. Permission to copy, use, modify, sell and
//  distribute this software is granted provided this copyright notice appears
//  in all copies. This software is provided "as is" without express or
//  implied warranty, and with no claim as to its suitability for any purpose.

// boostinspect:nolicense (don't complain about the lack of a Boost license)
// (Paul Moore hasn't been in contact for years, so there's no way to change the
// license.)

//  See http://www.boost.org/libs/rational for documentation.

//  Credits:
//  Thanks to the boost mailing list in general for useful comments.
//  Particular contributions included:
//    Andrew D Jewell, for reminding me to take care to avoid overflow
//    Ed Brey, for many comments, including picking up on some dreadful typos
//    Stephen Silver contributed the test suite and comments on user-defined
//    IntType
//    Nickolay Mladenov, for the implementation of operator+=

//  Revision History
//  02 Sep 13  Remove unneeded forward declarations; tweak private helper
//             function (Daryle Walker)
//  30 Aug 13  Improve exception safety of "assign"; start modernizing I/O code
//             (Daryle Walker)
//  27 Aug 13  Add cross-version constructor template, plus some private helper
//             functions; add constructor to exception class to take custom
//             messages (Daryle Walker)
//  25 Aug 13  Add constexpr qualification wherever possible (Daryle Walker)
//  05 May 12  Reduced use of implicit gcd (Mario Lang)
//  05 Nov 06  Change rational_cast to not depend on division between different
//             types (Daryle Walker)
//  04 Nov 06  Off-load GCD and LCM to Boost.Math; add some invariant checks;
//             add std::numeric_limits<> requirement to help GCD (Daryle Walker)
//  31 Oct 06  Recoded both operator< to use round-to-negative-infinity
//             divisions; the rational-value version now uses continued fraction
//             expansion to avoid overflows, for bug #798357 (Daryle Walker)
//  20 Oct 06  Fix operator bool_type for CW 8.3 (Joaquín M López Muñoz)
//  18 Oct 06  Use EXPLICIT_TEMPLATE_TYPE helper macros from Boost.Config
//             (Joaquín M López Muñoz)
//  27 Dec 05  Add Boolean conversion operator (Daryle Walker)
//  28 Sep 02  Use _left versions of operators from operators.hpp
//  05 Jul 01  Recode gcd(), avoiding std::swap (Helmut Zeisel)
//  03 Mar 01  Workarounds for Intel C++ 5.0 (David Abrahams)
//  05 Feb 01  Update operator>> to tighten up input syntax
//  05 Feb 01  Final tidy up of gcd code prior to the new release
//  27 Jan 01  Recode abs() without relying on abs(IntType)
//  21 Jan 01  Include Nickolay Mladenov's operator+= algorithm,
//             tidy up a number of areas, use newer features of operators.hpp
//             (reduces space overhead to zero), add operator!,
//             introduce explicit mixed-mode arithmetic operations
//  12 Jan 01  Include fixes to handle a user-defined IntType better
//  19 Nov 00  Throw on divide by zero in operator /= (John (EBo) David)
//  23 Jun 00  Incorporate changes from Mark Rodgers for Borland C++
//  22 Jun 00  Change _MSC_VER to BOOST_MSVC so other compilers are not
//             affected (Beman Dawes)
//   6 Mar 00  Fix operator-= normalization, #include <string> (Jens Maurer)
//  14 Dec 99  Modifications based on comments from the boost list
//  09 Dec 99  Initial Version (Paul Moore)

#ifndef BOOST_RATIONAL_HPP
#define BOOST_RATIONAL_HPP

#include <boost/config.hpp>      // for BOOST_NO_STDC_NAMESPACE, BOOST_MSVC, etc
#ifndef BOOST_NO_IOSTREAM
#include <iomanip>               // for std::setw
#include <ios>                   // for std::noskipws, streamsize
#include <istream>               // for std::istream
#include <ostream>               // for std::ostream
#include <sstream>               // for std::ostringstream
#endif
#include <cstddef>               // for NULL
#include <stdexcept>             // for std::domain_error
#include <string>                // for std::string implicit constructor
#include <boost/operators.hpp>   // for boost::addable etc
#include <cstdlib>               // for std::abs
#include <boost/call_traits.hpp> // for boost::call_traits
#include <boost/detail/workaround.hpp> // for BOOST_WORKAROUND
#include <boost/assert.hpp>      // for BOOST_ASSERT
#include <boost/integer/common_factor_rt.hpp> // for boost::integer::gcd, lcm
#include <limits>                // for std::numeric_limits
#include <boost/static_assert.hpp>  // for BOOST_STATIC_ASSERT
#include <boost/throw_exception.hpp>

// Control whether depreciated GCD and LCM functions are included (default: yes)
#ifndef BOOST_CONTROL_RATIONAL_HAS_GCD
#define BOOST_CONTROL_RATIONAL_HAS_GCD  1
#endif

namespace boost {

#if BOOST_CONTROL_RATIONAL_HAS_GCD
template <typename IntType>
IntType gcd(IntType n, IntType m)
{
    // Defer to the version in Boost.Math
    return integer::gcd( n, m );
}

template <typename IntType>
IntType lcm(IntType n, IntType m)
{
    // Defer to the version in Boost.Math
    return integer::lcm( n, m );
}
#endif  // BOOST_CONTROL_RATIONAL_HAS_GCD

class bad_rational : public std::domain_error
{
public:
    explicit bad_rational() : std::domain_error("bad rational: zero denominator") {}
    explicit bad_rational( char const *what ) : std::domain_error( what ) {}
};

template <typename IntType>
class rational :
    less_than_comparable < rational<IntType>,
    equality_comparable < rational<IntType>,
    less_than_comparable2 < rational<IntType>, IntType,
    equality_comparable2 < rational<IntType>, IntType,
    addable < rational<IntType>,
    subtractable < rational<IntType>,
    multipliable < rational<IntType>,
    dividable < rational<IntType>,
    addable2 < rational<IntType>, IntType,
    subtractable2 < rational<IntType>, IntType,
    subtractable2_left < rational<IntType>, IntType,
    multipliable2 < rational<IntType>, IntType,
    dividable2 < rational<IntType>, IntType,
    dividable2_left < rational<IntType>, IntType,
    incrementable < rational<IntType>,
    decrementable < rational<IntType>
    > > > > > > > > > > > > > > > >
{
    // Class-wide pre-conditions
    BOOST_STATIC_ASSERT( ::std::numeric_limits<IntType>::is_specialized );

    // Helper types
    typedef typename boost::call_traits<IntType>::param_type param_type;

    struct helper { IntType parts[2]; };
    typedef IntType (helper::* bool_type)[2];

public:
    // Component type
    typedef IntType int_type;

    BOOST_CONSTEXPR
    rational() : num(0), den(1) {}
    BOOST_CONSTEXPR
    rational(param_type n) : num(n), den(1) {}
    rational(param_type n, param_type d) : num(n), den(d) { normalize(); }

#ifndef BOOST_NO_MEMBER_TEMPLATES
    template < typename NewType >
    BOOST_CONSTEXPR explicit
       rational(rational<NewType> const &r)
       : num(r.numerator()), den(is_normalized(int_type(r.numerator()),
       int_type(r.denominator())) ? r.denominator() :
       (BOOST_THROW_EXCEPTION(bad_rational("bad rational: denormalized conversion")), 0)){}
#endif

    // Default copy constructor and assignment are fine

    // Add assignment from IntType
    rational& operator=(param_type i) { num = i; den = 1; return *this; }

    // Assign in place
    rational& assign(param_type n, param_type d);

    // Access to representation
    BOOST_CONSTEXPR
    const IntType& numerator() const { return num; }
    BOOST_CONSTEXPR
    const IntType& denominator() const { return den; }

    // Arithmetic assignment operators
    rational& operator+= (const rational& r);
    rational& operator-= (const rational& r);
    rational& operator*= (const rational& r);
    rational& operator/= (const rational& r);

    rational& operator+= (param_type i) { num += i * den; return *this; }
    rational& operator-= (param_type i) { num -= i * den; return *this; }
    rational& operator*= (param_type i);
    rational& operator/= (param_type i);

    // Increment and decrement
    const rational& operator++() { num += den; return *this; }
    const rational& operator--() { num -= den; return *this; }

    // Operator not
    BOOST_CONSTEXPR
    bool operator!() const { return !num; }

    // Boolean conversion

#if BOOST_WORKAROUND(__MWERKS__,<=0x3003)
    // The "ISO C++ Template Parser" option in CW 8.3 chokes on the
    // following, hence we selectively disable that option for the
    // offending memfun.
#pragma parse_mfunc_templ off
#endif

    BOOST_CONSTEXPR
    operator bool_type() const { return operator !() ? 0 : &helper::parts; }

#if BOOST_WORKAROUND(__MWERKS__,<=0x3003)
#pragma parse_mfunc_templ reset
#endif

    // Comparison operators
    bool operator< (const rational& r) const;
    BOOST_CONSTEXPR
    bool operator== (const rational& r) const;

    bool operator< (param_type i) const;
    bool operator> (param_type i) const;
    BOOST_CONSTEXPR
    bool operator== (param_type i) const;

private:
    // Implementation - numerator and denominator (normalized).
    // Other possibilities - separate whole-part, or sign, fields?
    IntType num;
    IntType den;

    // Helper functions
    static BOOST_CONSTEXPR
    int_type inner_gcd( param_type a, param_type b, int_type const &zero =
     int_type(0) )
    { return b == zero ? a : inner_gcd(b, a % b, zero); }

    static BOOST_CONSTEXPR
    int_type inner_abs( param_type x, int_type const &zero = int_type(0) )
    { return x < zero ? -x : +x; }

    // Representation note: Fractions are kept in normalized form at all
    // times. normalized form is defined as gcd(num,den) == 1 and den > 0.
    // In particular, note that the implementation of abs() below relies
    // on den always being positive.
    bool test_invariant() const;
    void normalize();

    static BOOST_CONSTEXPR
    bool is_normalized( param_type n, param_type d, int_type const &zero =
     int_type(0), int_type const &one = int_type(1) )
    {
        return d > zero && ( n != zero || d == one ) && inner_abs( inner_gcd(n,
         d, zero), zero ) == one;
    }
};

// Assign in place
template <typename IntType>
inline rational<IntType>& rational<IntType>::assign(param_type n, param_type d)
{
    return *this = rational( n, d );
}

// Unary plus and minus
template <typename IntType>
BOOST_CONSTEXPR
inline rational<IntType> operator+ (const rational<IntType>& r)
{
    return r;
}

template <typename IntType>
inline rational<IntType> operator- (const rational<IntType>& r)
{
    return rational<IntType>(-r.numerator(), r.denominator());
}

// Arithmetic assignment operators
template <typename IntType>
rational<IntType>& rational<IntType>::operator+= (const rational<IntType>& r)
{
    // This calculation avoids overflow, and minimises the number of expensive
    // calculations. Thanks to Nickolay Mladenov for this algorithm.
    //
    // Proof:
    // We have to compute a/b + c/d, where gcd(a,b)=1 and gcd(b,c)=1.
    // Let g = gcd(b,d), and b = b1*g, d=d1*g. Then gcd(b1,d1)=1
    //
    // The result is (a*d1 + c*b1) / (b1*d1*g).
    // Now we have to normalize this ratio.
    // Let's assume h | gcd((a*d1 + c*b1), (b1*d1*g)), and h > 1
    // If h | b1 then gcd(h,d1)=1 and hence h|(a*d1+c*b1) => h|a.
    // But since gcd(a,b1)=1 we have h=1.
    // Similarly h|d1 leads to h=1.
    // So we have that h | gcd((a*d1 + c*b1) , (b1*d1*g)) => h|g
    // Finally we have gcd((a*d1 + c*b1), (b1*d1*g)) = gcd((a*d1 + c*b1), g)
    // Which proves that instead of normalizing the result, it is better to
    // divide num and den by gcd((a*d1 + c*b1), g)

    // Protect against self-modification
    IntType r_num = r.num;
    IntType r_den = r.den;

    IntType g = integer::gcd(den, r_den);
    den /= g;  // = b1 from the calculations above
    num = num * (r_den / g) + r_num * den;
    g = integer::gcd(num, g);
    num /= g;
    den *= r_den/g;

    return *this;
}

template <typename IntType>
rational<IntType>& rational<IntType>::operator-= (const rational<IntType>& r)
{
    // Protect against self-modification
    IntType r_num = r.num;
    IntType r_den = r.den;

    // This calculation avoids overflow, and minimises the number of expensive
    // calculations. It corresponds exactly to the += case above
    IntType g = integer::gcd(den, r_den);
    den /= g;
    num = num * (r_den / g) - r_num * den;
    g = integer::gcd(num, g);
    num /= g;
    den *= r_den/g;

    return *this;
}

template <typename IntType>
rational<IntType>& rational<IntType>::operator*= (const rational<IntType>& r)
{
    // Protect against self-modification
    IntType r_num = r.num;
    IntType r_den = r.den;

    // Avoid overflow and preserve normalization
    IntType gcd1 = integer::gcd(num, r_den);
    IntType gcd2 = integer::gcd(r_num, den);
    num = (num/gcd1) * (r_num/gcd2);
    den = (den/gcd2) * (r_den/gcd1);
    return *this;
}

template <typename IntType>
rational<IntType>& rational<IntType>::operator/= (const rational<IntType>& r)
{
    // Protect against self-modification
    IntType r_num = r.num;
    IntType r_den = r.den;

    // Avoid repeated construction
    IntType zero(0);

    // Trap division by zero
    if (r_num == zero)
        BOOST_THROW_EXCEPTION(bad_rational());
    if (num == zero)
        return *this;

    // Avoid overflow and preserve normalization
    IntType gcd1 = integer::gcd(num, r_num);
    IntType gcd2 = integer::gcd(r_den, den);
    num = (num/gcd1) * (r_den/gcd2);
    den = (den/gcd2) * (r_num/gcd1);

    if (den < zero) {
        num = -num;
        den = -den;
    }
    return *this;
}

// Mixed-mode operators
template <typename IntType>
inline rational<IntType>&
rational<IntType>::operator*= (param_type i)
{
    // Avoid overflow and preserve normalization
    IntType gcd = integer::gcd(i, den);
    num *= i / gcd;
    den /= gcd;

    return *this;
}

template <typename IntType>
rational<IntType>&
rational<IntType>::operator/= (param_type i)
{
    // Avoid repeated construction
    IntType const zero(0);

    if(i == zero) BOOST_THROW_EXCEPTION(bad_rational());
    if (num == zero) return *this;

    // Avoid overflow and preserve normalization
    IntType const gcd = integer::gcd(num, i);
    num /= gcd;
    den *= i / gcd;

    if (den < zero) {
        num = -num;
        den = -den;
    }

    return *this;
}

// Comparison operators
template <typename IntType>
bool rational<IntType>::operator< (const rational<IntType>& r) const
{
    // Avoid repeated construction
    int_type const  zero( 0 );

    // This should really be a class-wide invariant.  The reason for these
    // checks is that for 2's complement systems, INT_MIN has no corresponding
    // positive, so negating it during normalization keeps it INT_MIN, which
    // is bad for later calculations that assume a positive denominator.
    BOOST_ASSERT( this->den > zero );
    BOOST_ASSERT( r.den > zero );

    // Determine relative order by expanding each value to its simple continued
    // fraction representation using the Euclidian GCD algorithm.
    struct { int_type  n, d, q, r; }
     ts = { this->num, this->den, static_cast<int_type>(this->num / this->den),
     static_cast<int_type>(this->num % this->den) },
     rs = { r.num, r.den, static_cast<int_type>(r.num / r.den),
     static_cast<int_type>(r.num % r.den) };
    unsigned  reverse = 0u;

    // Normalize negative moduli by repeatedly adding the (positive) denominator
    // and decrementing the quotient.  Later cycles should have all positive
    // values, so this only has to be done for the first cycle.  (The rules of
    // C++ require a nonnegative quotient & remainder for a nonnegative dividend
    // & positive divisor.)
    while ( ts.r < zero )  { ts.r += ts.d; --ts.q; }
    while ( rs.r < zero )  { rs.r += rs.d; --rs.q; }

    // Loop through and compare each variable's continued-fraction components
    for ( ;; )
    {
        // The quotients of the current cycle are the continued-fraction
        // components.  Comparing two c.f. is comparing their sequences,
        // stopping at the first difference.
        if ( ts.q != rs.q )
        {
            // Since reciprocation changes the relative order of two variables,
            // and c.f. use reciprocals, the less/greater-than test reverses
            // after each index.  (Start w/ non-reversed @ whole-number place.)
            return reverse ? ts.q > rs.q : ts.q < rs.q;
        }

        // Prepare the next cycle
        reverse ^= 1u;

        if ( (ts.r == zero) || (rs.r == zero) )
        {
            // At least one variable's c.f. expansion has ended
            break;
        }

        ts.n = ts.d;         ts.d = ts.r;
        ts.q = ts.n / ts.d;  ts.r = ts.n % ts.d;
        rs.n = rs.d;         rs.d = rs.r;
        rs.q = rs.n / rs.d;  rs.r = rs.n % rs.d;
    }

    // Compare infinity-valued components for otherwise equal sequences
    if ( ts.r == rs.r )
    {
        // Both remainders are zero, so the next (and subsequent) c.f.
        // components for both sequences are infinity.  Therefore, the sequences
        // and their corresponding values are equal.
        return false;
    }
    else
    {
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4800)
#endif
        // Exactly one of the remainders is zero, so all following c.f.
        // components of that variable are infinity, while the other variable
        // has a finite next c.f. component.  So that other variable has the
        // lesser value (modulo the reversal flag!).
        return ( ts.r != zero ) != static_cast<bool>( reverse );
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
    }
}

template <typename IntType>
bool rational<IntType>::operator< (param_type i) const
{
    // Avoid repeated construction
    int_type const  zero( 0 );

    // Break value into mixed-fraction form, w/ always-nonnegative remainder
    BOOST_ASSERT( this->den > zero );
    int_type  q = this->num / this->den, r = this->num % this->den;
    while ( r < zero )  { r += this->den; --q; }

    // Compare with just the quotient, since the remainder always bumps the
    // value up.  [Since q = floor(n/d), and if n/d < i then q < i, if n/d == i
    // then q == i, if n/d == i + r/d then q == i, and if n/d >= i + 1 then
    // q >= i + 1 > i; therefore n/d < i iff q < i.]
    return q < i;
}

template <typename IntType>
bool rational<IntType>::operator> (param_type i) const
{
    return operator==(i)? false: !operator<(i);
}

template <typename IntType>
BOOST_CONSTEXPR
inline bool rational<IntType>::operator== (const rational<IntType>& r) const
{
    return ((num == r.num) && (den == r.den));
}

template <typename IntType>
BOOST_CONSTEXPR
inline bool rational<IntType>::operator== (param_type i) const
{
    return ((den == IntType(1)) && (num == i));
}

// Invariant check
template <typename IntType>
inline bool rational<IntType>::test_invariant() const
{
    return ( this->den > int_type(0) ) && ( integer::gcd(this->num, this->den) ==
     int_type(1) );
}

// Normalisation
template <typename IntType>
void rational<IntType>::normalize()
{
    // Avoid repeated construction
    IntType zero(0);

    if (den == zero)
       BOOST_THROW_EXCEPTION(bad_rational());

    // Handle the case of zero separately, to avoid division by zero
    if (num == zero) {
        den = IntType(1);
        return;
    }

    IntType g = integer::gcd(num, den);

    num /= g;
    den /= g;

    // Ensure that the denominator is positive
    if (den < zero) {
        num = -num;
        den = -den;
    }

    // ...But acknowledge that the previous step doesn't always work.
    // (Nominally, this should be done before the mutating steps, but this
    // member function is only called during the constructor, so we never have
    // to worry about zombie objects.)
    if (den < zero)
       BOOST_THROW_EXCEPTION(bad_rational("bad rational: non-zero singular denominator"));

    BOOST_ASSERT( this->test_invariant() );
}

#ifndef BOOST_NO_IOSTREAM
namespace detail {

    // A utility class to reset the format flags for an istream at end
    // of scope, even in case of exceptions
    struct resetter {
        resetter(std::istream& is) : is_(is), f_(is.flags()) {}
        ~resetter() { is_.flags(f_); }
        std::istream& is_;
        std::istream::fmtflags f_;      // old GNU c++ lib has no ios_base
    };

}

// Input and output
template <typename IntType>
std::istream& operator>> (std::istream& is, rational<IntType>& r)
{
    using std::ios;

    IntType n = IntType(0), d = IntType(1);
    char c = 0;
    detail::resetter sentry(is);

    if ( is >> n )
    {
        if ( is.get(c) )
        {
            if ( c == '/' )
            {
                if ( is >> std::noskipws >> d )
                    try {
                        r.assign( n, d );
                    } catch ( bad_rational & ) {        // normalization fail
                        try { is.setstate(ios::failbit); }
                        catch ( ... ) {}  // don't throw ios_base::failure...
                        if ( is.exceptions() & ios::failbit )
                            throw;   // ...but the original exception instead
                        // ELSE: suppress the exception, use just error flags
                    }
            }
            else
                is.setstate( ios::failbit );
        }
    }

    return is;
}

// Add manipulators for output format?
template <typename IntType>
std::ostream& operator<< (std::ostream& os, const rational<IntType>& r)
{
    // The slash directly precedes the denominator, which has no prefixes.
    std::ostringstream  ss;

    ss.copyfmt( os );
    ss.tie( NULL );
    ss.exceptions( std::ios::goodbit );
    ss.width( 0 );
    ss << std::noshowpos << std::noshowbase << '/' << r.denominator();

    // The numerator holds the showpos, internal, and showbase flags.
    std::string const   tail = ss.str();
    std::streamsize const  w =
        os.width() - static_cast<std::streamsize>( tail.size() );

    ss.clear();
    ss.str( "" );
    ss.flags( os.flags() );
    ss << std::setw( w < 0 || (os.flags() & std::ios::adjustfield) !=
                     std::ios::internal ? 0 : w ) << r.numerator();
    return os << ss.str() + tail;
}
#endif  // BOOST_NO_IOSTREAM

// Type conversion
template <typename T, typename IntType>
BOOST_CONSTEXPR
inline T rational_cast(const rational<IntType>& src)
{
    return static_cast<T>(src.numerator())/static_cast<T>(src.denominator());
}

// Do not use any abs() defined on IntType - it isn't worth it, given the
// difficulties involved (Koenig lookup required, there may not *be* an abs()
// defined, etc etc).
template <typename IntType>
inline rational<IntType> abs(const rational<IntType>& r)
{
    return r.numerator() >= IntType(0)? r: -r;
}

namespace integer {

template <typename IntType>
struct gcd_evaluator< rational<IntType> >
{
    typedef rational<IntType> result_type,
                              first_argument_type, second_argument_type;
    result_type operator() (  first_argument_type const &a
                           , second_argument_type const &b
                           ) const
    {
        return result_type(integer::gcd(a.numerator(), b.numerator()),
                           integer::lcm(a.denominator(), b.denominator()));
    }
};

template <typename IntType>
struct lcm_evaluator< rational<IntType> >
{
    typedef rational<IntType> result_type,
                              first_argument_type, second_argument_type;
    result_type operator() (  first_argument_type const &a
                           , second_argument_type const &b
                           ) const
    {
        return result_type(integer::lcm(a.numerator(), b.numerator()),
                           integer::gcd(a.denominator(), b.denominator()));
    }
};

} // namespace integer

} // namespace boost

#endif  // BOOST_RATIONAL_HPP


code:
/*
 * Copyright (c) 2014 Glen Fernandes
 *
 * Distributed under the Boost Software License, Version 1.0. (See
 * accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_REF_HPP
#define BOOST_REF_HPP

// The header file at this path is deprecated;
// use boost/core/ref.hpp instead.

#include <boost/core/ref.hpp>

#endif

license: mit


code:
/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org/libs/regex for documentation.
  *   FILE         regex.cpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Declares boost::basic_regex<> and associated
  *                functions and classes. This header is the main
  *                entry point for the template regex code.
  */

/* start with C compatibility API */

#ifndef BOOST_RE_REGEX_HPP
#define BOOST_RE_REGEX_HPP

#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif

#include <boost/regex/v4/regex.hpp>

#endif  // include


code:
/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         config.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: regex extended config setup.
  */

#ifndef BOOST_REGEX_CONFIG_HPP
#define BOOST_REGEX_CONFIG_HPP
/*
 * Borland C++ Fix/error check
 * this has to go *before* we include any std lib headers:
 */
#if defined(__BORLANDC__)
#  include <boost/regex/config/borland.hpp>
#endif
#include <boost/version.hpp>

/*****************************************************************************
 *
 *  Include all the headers we need here:
 *
 ****************************************************************************/

#ifdef __cplusplus

#  ifndef BOOST_REGEX_USER_CONFIG
#     define BOOST_REGEX_USER_CONFIG <boost/regex/user.hpp>
#  endif

#  include BOOST_REGEX_USER_CONFIG

#  include <boost/config.hpp>
#  include <boost/predef.h>

#else
   /*
    * C build,
    * don't include <boost/config.hpp> because that may
    * do C++ specific things in future...
    */
#  include <stdlib.h>
#  include <stddef.h>
#  ifdef _MSC_VER
#     define BOOST_MSVC _MSC_VER
#  endif
#endif

/*****************************************************************************
 *
 *  Boilerplate regex config options:
 *
 ****************************************************************************/

/* Obsolete macro, use BOOST_VERSION instead: */
#define BOOST_RE_VERSION 320

/* fix: */
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

/*
* Define a macro for the namespace that details are placed in, this includes the Boost
* version number to avoid mismatched header and library versions:
*/
#define BOOST_REGEX_DETAIL_NS BOOST_JOIN(re_detail_, BOOST_VERSION)

/*
 * Fix for gcc prior to 3.4: std::ctype<wchar_t> doesn't allow
 * masks to be combined, for example:
 * std::use_facet<std::ctype<wchar_t> >.is(std::ctype_base::lower|std::ctype_base::upper, L'a');
 * returns *false*.
 */
#ifdef __GLIBCPP__
#  define BOOST_REGEX_BUGGY_CTYPE_FACET
#endif

/*
 * Intel C++ before 8.0 ends up with unresolved externals unless we turn off
 * extern template support:
 */
#if defined(BOOST_INTEL) && defined(__cplusplus) && (BOOST_INTEL <= 800)
#  define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#endif
/*
 * Visual C++ doesn't support external templates with C++ extensions turned off:
 */
#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
#  define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#endif
 /*
 * Oracle compiler in C++11 mode doesn't like external templates for some reason:
 */
#ifdef __SUNPRO_CC
#  define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#endif
 /*
 * Shared regex lib will crash without this, frankly it looks a lot like a gcc bug:
 */
#if defined(__MINGW32__)
#  define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#endif

/*
 * If there isn't good enough wide character support then there will
 * be no wide character regular expressions:
 */
#if (defined(BOOST_NO_CWCHAR) || defined(BOOST_NO_CWCTYPE) || defined(BOOST_NO_STD_WSTRING))
#  if !defined(BOOST_NO_WREGEX)
#     define BOOST_NO_WREGEX
#  endif
#else
#  if defined(__sgi) && (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))
      /* STLPort on IRIX is misconfigured: <cwctype> does not compile
       * as a temporary fix include <wctype.h> instead and prevent inclusion
       * of STLPort version of <cwctype> */
#     include <wctype.h>
#     define __STLPORT_CWCTYPE
#     define _STLP_CWCTYPE
#  endif

#ifdef __cplusplus
#  include <boost/regex/config/cwchar.hpp>
#endif

#endif

/*
 * If Win32 support has been disabled for boost in general, then
 * it is for regex in particular:
 */
#if defined(BOOST_DISABLE_WIN32) && !defined(BOOST_REGEX_NO_W32)
#  define BOOST_REGEX_NO_W32
#endif

/* disable our own file-iterators and mapfiles if we can't
 * support them: */
#if defined(_WIN32)
#  if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_RUNTIME
#    define BOOST_REGEX_NO_FILEITER
#  endif
#else // defined(_WIN32)
#  if !defined(BOOST_HAS_DIRENT_H)
#    define BOOST_REGEX_NO_FILEITER
#  endif
#endif

/* backwards compatibitity: */
#if defined(BOOST_RE_NO_LIB)
#  define BOOST_REGEX_NO_LIB
#endif

#if defined(__GNUC__) && (defined(_WIN32) || defined(__CYGWIN__))
/* gcc on win32 has problems if you include <windows.h>
   (sporadically generates bad code). */
#  define BOOST_REGEX_NO_W32
#endif
#if defined(__COMO__) && !defined(BOOST_REGEX_NO_W32) && !defined(_MSC_EXTENSIONS)
#  define BOOST_REGEX_NO_W32
#endif

/*****************************************************************************
 *
 *  Wide character workarounds:
 *
 ****************************************************************************/

/*
 * define BOOST_REGEX_HAS_OTHER_WCHAR_T when wchar_t is a native type, but the users
 * code may be built with wchar_t as unsigned short: basically when we're building
 * with MSVC and the /Zc:wchar_t option we place some extra unsigned short versions
 * of the non-inline functions in the library, so that users can still link to the lib,
 * irrespective of whether their own code is built with /Zc:wchar_t.
 * Note that this does NOT WORK with VC10 and VC14 when the C++ locale is in effect as
 * the locale's <unsigned short> facets simply do not compile in that case.
 * As we default to the C++ locale when compiling for the windows runtime we
 * skip in this case aswell.
 */
#if defined(__cplusplus) && \
      (defined(BOOST_MSVC) || defined(__ICL)) && \
      !defined(BOOST_NO_INTRINSIC_WCHAR_T) && \
      defined(BOOST_WINDOWS) && \
      !defined(__SGI_STL_PORT) && \
      !defined(_STLPORT_VERSION) && \
      !defined(BOOST_RWSTD_VER) && \
      ((_MSC_VER < 1600) || !defined(BOOST_REGEX_USE_CPP_LOCALE)) && \
      !BOOST_PLAT_WINDOWS_RUNTIME
#  define BOOST_REGEX_HAS_OTHER_WCHAR_T
#  ifdef BOOST_MSVC
#     pragma warning(push)
#     pragma warning(disable : 4251 4231)
#     if BOOST_MSVC < 1600
#        pragma warning(disable : 4660)
#     endif
#  endif
#  if defined(_DLL) && defined(BOOST_MSVC) && (BOOST_MSVC < 1600)
#     include <string>
      extern template class __declspec(dllimport) std::basic_string<unsigned short>;
#  endif
#  ifdef BOOST_MSVC
#     pragma warning(pop)
#  endif
#endif

/*****************************************************************************
 *
 *  Set up dll import/export options:
 *
 ****************************************************************************/

#ifndef BOOST_SYMBOL_EXPORT
#  define BOOST_SYMBOL_EXPORT
#  define BOOST_SYMBOL_IMPORT
#endif

#if (defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_REGEX_STATIC_LINK)
#  if defined(BOOST_REGEX_SOURCE)
#     define BOOST_REGEX_DECL BOOST_SYMBOL_EXPORT
#     define BOOST_REGEX_BUILD_DLL
#  else
#     define BOOST_REGEX_DECL BOOST_SYMBOL_IMPORT
#  endif
#else
#  define BOOST_REGEX_DECL
#endif

#if !defined(BOOST_REGEX_NO_LIB) && !defined(BOOST_REGEX_SOURCE) && !defined(BOOST_ALL_NO_LIB) && defined(__cplusplus)
#  define BOOST_LIB_NAME boost_regex
#  if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
#     define BOOST_DYN_LINK
#  endif
#  ifdef BOOST_REGEX_DIAG
#     define BOOST_LIB_DIAGNOSTIC
#  endif
#  include <boost/config/auto_link.hpp>
#endif

/*****************************************************************************
 *
 *  Set up function call type:
 *
 ****************************************************************************/

#if defined(BOOST_MSVC) && defined(_MSC_EXTENSIONS)
#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED) || defined(BOOST_REGEX_NO_FASTCALL)
#  define BOOST_REGEX_CALL __cdecl
#else
#  define BOOST_REGEX_CALL __fastcall
#endif
#  define BOOST_REGEX_CCALL __cdecl
#endif

#if defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)
#  define BOOST_REGEX_CALL __fastcall
#  define BOOST_REGEX_CCALL __stdcall
#endif

#ifndef BOOST_REGEX_CALL
#  define BOOST_REGEX_CALL
#endif
#ifndef BOOST_REGEX_CCALL
#define BOOST_REGEX_CCALL
#endif

/*****************************************************************************
 *
 *  Set up localisation model:
 *
 ****************************************************************************/

/* backwards compatibility: */
#ifdef BOOST_RE_LOCALE_C
#  define BOOST_REGEX_USE_C_LOCALE
#endif

#ifdef BOOST_RE_LOCALE_CPP
#  define BOOST_REGEX_USE_CPP_LOCALE
#endif

#if defined(__CYGWIN__)
#  define BOOST_REGEX_USE_C_LOCALE
#endif

/* use C++ locale when targeting windows store */
#if BOOST_PLAT_WINDOWS_RUNTIME
#  define BOOST_REGEX_USE_CPP_LOCALE
#  define BOOST_REGEX_NO_WIN32_LOCALE
#endif

/* Win32 defaults to native Win32 locale: */
#if defined(_WIN32) && \
    !defined(BOOST_REGEX_USE_WIN32_LOCALE) && \
    !defined(BOOST_REGEX_USE_C_LOCALE) && \
    !defined(BOOST_REGEX_USE_CPP_LOCALE) && \
    !defined(BOOST_REGEX_NO_W32) && \
    !defined(BOOST_REGEX_NO_WIN32_LOCALE)
#  define BOOST_REGEX_USE_WIN32_LOCALE
#endif
/* otherwise use C++ locale if supported: */
#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) && !defined(BOOST_NO_STD_LOCALE)
#  define BOOST_REGEX_USE_CPP_LOCALE
#endif
/* otherwise use C+ locale: */
#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE)
#  define BOOST_REGEX_USE_C_LOCALE
#endif

#ifndef BOOST_REGEX_MAX_STATE_COUNT
#  define BOOST_REGEX_MAX_STATE_COUNT 100000000
#endif

/*****************************************************************************
 *
 *  Error Handling for exception free compilers:
 *
 ****************************************************************************/

#ifdef BOOST_NO_EXCEPTIONS
/*
 * If there are no exceptions then we must report critical-errors
 * the only way we know how; by terminating.
 */
#include <stdexcept>
#include <string>
#include <boost/throw_exception.hpp>

#  define BOOST_REGEX_NOEH_ASSERT(x)\
if(0 == (x))\
{\
   std::string s("Error: critical regex++ failure in: ");\
   s.append(#x);\
   std::runtime_error e(s);\
   boost::throw_exception(e);\
}
#else
/*
 * With exceptions then error handling is taken care of and
 * there is no need for these checks:
 */
#  define BOOST_REGEX_NOEH_ASSERT(x)
#endif

/*****************************************************************************
 *
 *  Stack protection under MS Windows:
 *
 ****************************************************************************/

#if !defined(BOOST_REGEX_NO_W32) && !defined(BOOST_REGEX_V3)
#  if(defined(_WIN32) || defined(_WIN64) || defined(_WINCE)) \
        && !defined(__GNUC__) \
        && !(defined(__BORLANDC__) && (__BORLANDC__ >= 0x600)) \
        && !(defined(__MWERKS__) && (__MWERKS__ <= 0x3003))
#     define BOOST_REGEX_HAS_MS_STACK_GUARD
#  endif
#elif defined(BOOST_REGEX_HAS_MS_STACK_GUARD)
#  undef BOOST_REGEX_HAS_MS_STACK_GUARD
#endif

#if defined(__cplusplus) && defined(BOOST_REGEX_HAS_MS_STACK_GUARD)

namespace boost{
namespace BOOST_REGEX_DETAIL_NS{

BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page();

}
}

#endif

/*****************************************************************************
 *
 *  Algorithm selection and configuration:
 *
 ****************************************************************************/

#if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE)
#  if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(BOOST_MSVC) && (BOOST_MSVC >= 1400))
#     define BOOST_REGEX_RECURSIVE
#  else
#     define BOOST_REGEX_NON_RECURSIVE
#  endif
#endif

#ifdef BOOST_REGEX_NON_RECURSIVE
#  ifdef BOOST_REGEX_RECURSIVE
#     error "Can't set both BOOST_REGEX_RECURSIVE and BOOST_REGEX_NON_RECURSIVE"
#  endif
#  ifndef BOOST_REGEX_BLOCKSIZE
#     define BOOST_REGEX_BLOCKSIZE 4096
#  endif
#  if BOOST_REGEX_BLOCKSIZE < 512
#     error "BOOST_REGEX_BLOCKSIZE must be at least 512"
#  endif
#  ifndef BOOST_REGEX_MAX_BLOCKS
#     define BOOST_REGEX_MAX_BLOCKS 1024
#  endif
#  ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
#     undef BOOST_REGEX_HAS_MS_STACK_GUARD
#  endif
#  ifndef BOOST_REGEX_MAX_CACHE_BLOCKS
#     define BOOST_REGEX_MAX_CACHE_BLOCKS 16
#  endif
#endif

/*****************************************************************************
 *
 *  helper memory allocation functions:
 *
 ****************************************************************************/

#if defined(__cplusplus) && defined(BOOST_REGEX_NON_RECURSIVE)
namespace boost{ namespace BOOST_REGEX_DETAIL_NS{

BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block();
BOOST_REGEX_DECL void BOOST_REGEX_CALL put_mem_block(void*);

}} /* namespaces */
#endif

/*****************************************************************************
 *
 *  Diagnostics:
 *
 ****************************************************************************/

#ifdef BOOST_REGEX_CONFIG_INFO
BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info();
#endif

#if defined(BOOST_REGEX_DIAG)
#  pragma message ("BOOST_REGEX_DECL" BOOST_STRINGIZE(=BOOST_REGEX_DECL))
#  pragma message ("BOOST_REGEX_CALL" BOOST_STRINGIZE(=BOOST_REGEX_CALL))
#  pragma message ("BOOST_REGEX_CCALL" BOOST_STRINGIZE(=BOOST_REGEX_CCALL))
#ifdef BOOST_REGEX_USE_C_LOCALE
#  pragma message ("Using C locale in regex traits class")
#elif BOOST_REGEX_USE_CPP_LOCALE
#  pragma message ("Using C++ locale in regex traits class")
#else
#  pragma message ("Using Win32 locale in regex traits class")
#endif
#if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
#  pragma message ("Dynamic linking enabled")
#endif
#if defined(BOOST_REGEX_NO_LIB) || defined(BOOST_ALL_NO_LIB)
#  pragma message ("Auto-linking disabled")
#endif
#ifdef BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#  pragma message ("Extern templates disabled")
#endif

#endif

#endif


code:
/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         boost/regex/config/borland.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: regex borland-specific config setup.
  */

#if defined(__BORLANDC__)
#  if (__BORLANDC__ == 0x550) || (__BORLANDC__ == 0x551)
      // problems with std::basic_string and dll RTL:
#     if defined(_RTLDLL) && defined(_RWSTD_COMPILE_INSTANTIATE)
#        ifdef BOOST_REGEX_BUILD_DLL
#           error _RWSTD_COMPILE_INSTANTIATE must not be defined when building regex++ as a DLL
#        else
#           pragma message("Defining _RWSTD_COMPILE_INSTANTIATE when linking to the DLL version of the RTL may produce memory corruption problems in std::basic_string, as a result of separate versions of basic_string's static data in the RTL and you're exe/dll: be warned!!")
#        endif
#     endif
#     ifndef _RTLDLL
         // this is harmless for a staic link:
#        define _RWSTD_COMPILE_INSTANTIATE
#     endif
      // external templates cause problems for some reason:
#     define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#  endif
#  if (__BORLANDC__ <= 0x540) && !defined(BOOST_REGEX_NO_LIB) && !defined(_NO_VCL)
      // C++ Builder 4 and earlier, we can't tell whether we should be using
      // the VCL runtime or not, do a static link instead:
#     define BOOST_REGEX_STATIC_LINK
#  endif
   //
   // VCL support:
   // if we're building a console app then there can't be any VCL (can there?)
#  if !defined(__CONSOLE__) && !defined(_NO_VCL)
#     define BOOST_REGEX_USE_VCL
#  endif
   //
   // if this isn't Win32 then don't automatically select link
   // libraries:
   //
#  ifndef _Windows
#     ifndef BOOST_REGEX_NO_LIB
#        define BOOST_REGEX_NO_LIB
#     endif
#     ifndef BOOST_REGEX_STATIC_LINK
#        define BOOST_REGEX_STATIC_LINK
#     endif
#  endif

#if __BORLANDC__ < 0x600
//
// string workarounds:
//
#include <cstring>
#undef strcmp
#undef strcpy
#endif

#endif


code:
/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         boost/regex/config/cwchar.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: regex wide character string fixes.
  */

#ifndef BOOST_REGEX_CONFIG_CWCHAR_HPP
#define BOOST_REGEX_CONFIG_CWCHAR_HPP

#include <cwchar>
#include <cwctype>
#include <boost/config.hpp>

#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
// apparently this is required for the RW STL on Linux:
#undef iswalnum
#undef iswalpha
#undef iswblank
#undef iswcntrl
#undef iswdigit
#undef iswgraph
#undef iswlower
#undef iswprint
#undef iswprint
#undef iswpunct
#undef iswspace
#undef iswupper
#undef iswxdigit
#undef iswctype
#undef towlower
#undef towupper
#undef towctrans
#undef wctrans
#undef wctype
#endif

namespace std{

#ifndef BOOST_NO_STDC_NAMESPACE
extern "C"{
#endif

#ifdef iswalnum
inline int (iswalnum)(wint_t i)
{ return iswalnum(i); }
#undef iswalnum
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswalnum;
#endif

#ifdef iswalpha
inline int (iswalpha)(wint_t i)
{ return iswalpha(i); }
#undef iswalpha
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswalpha;
#endif

#ifdef iswcntrl
inline int (iswcntrl)(wint_t i)
{ return iswcntrl(i); }
#undef iswcntrl
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswcntrl;
#endif

#ifdef iswdigit
inline int (iswdigit)(wint_t i)
{ return iswdigit(i); }
#undef iswdigit
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswdigit;
#endif

#ifdef iswgraph
inline int (iswgraph)(wint_t i)
{ return iswgraph(i); }
#undef iswgraph
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswgraph;
#endif

#ifdef iswlower
inline int (iswlower)(wint_t i)
{ return iswlower(i); }
#undef iswlower
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswlower;
#endif

#ifdef iswprint
inline int (iswprint)(wint_t i)
{ return iswprint(i); }
#undef iswprint
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswprint;
#endif

#ifdef iswpunct
inline int (iswpunct)(wint_t i)
{ return iswpunct(i); }
#undef iswpunct
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswpunct;
#endif

#ifdef iswspace
inline int (iswspace)(wint_t i)
{ return iswspace(i); }
#undef iswspace
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswspace;
#endif

#ifdef iswupper
inline int (iswupper)(wint_t i)
{ return iswupper(i); }
#undef iswupper
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswupper;
#endif

#ifdef iswxdigit
inline int (iswxdigit)(wint_t i)
{ return iswxdigit(i); }
#undef iswxdigit
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswxdigit;
#endif

#ifdef towlower
inline wint_t (towlower)(wint_t i)
{ return towlower(i); }
#undef towlower
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::towlower;
#endif

#ifdef towupper
inline wint_t (towupper)(wint_t i)
{ return towupper(i); }
#undef towupper
#elif defined(BOOST_NO_STDC_NAMESPACE)
using :: towupper;
#endif

#ifdef wcscmp
inline int (wcscmp)(const wchar_t *p1, const wchar_t *p2)
{ return wcscmp(p1,p2); }
#undef wcscmp
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcscmp;
#endif

#ifdef wcscoll
inline int (wcscoll)(const wchar_t *p1, const wchar_t *p2)
{ return wcscoll(p1,p2); }
#undef wcscoll
#elif defined(BOOST_NO_STDC_NAMESPACE) && !defined(UNDER_CE)
using ::wcscoll;
#endif

#ifdef wcscpy
inline wchar_t *(wcscpy)(wchar_t *p1, const wchar_t *p2)
{ return wcscpy(p1,p2); }
#undef wcscpy
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcscpy;
#endif

#ifdef wcslen
inline size_t (wcslen)(const wchar_t *p)
{ return wcslen(p); }
#undef wcslen
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcslen;
#endif

#ifdef wcsxfrm
size_t wcsxfrm(wchar_t *p1, const wchar_t *p2, size_t s)
{ return wcsxfrm(p1,p2,s); }
#undef wcsxfrm
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcsxfrm;
#endif

#ifndef BOOST_NO_STDC_NAMESPACE
} // extern "C"
#endif

} // namespace std

#endif


code:
/*
 *
 * Copyright (c) 2004
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         icu.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Unicode regular expressions on top of the ICU Library.
  */

#ifndef BOOST_REGEX_ICU_HPP
#define BOOST_REGEX_ICU_HPP

#include <unicode/utypes.h>
#include <unicode/uchar.h>
#include <unicode/coll.h>
#include <boost/regex.hpp>
#include <boost/regex/pending/unicode_iterator.hpp>
#include <boost/mpl/int_fwd.hpp>
#include <bitset>

#ifdef BOOST_MSVC
#pragma warning (push)
#pragma warning (disable: 4251)
#endif

namespace boost{

namespace BOOST_REGEX_DETAIL_NS{

//
// Implementation details:
//
class BOOST_REGEX_DECL icu_regex_traits_implementation
{
   typedef UChar32                      char_type;
   typedef std::size_t                  size_type;
   typedef std::vector<char_type>       string_type;
   typedef U_NAMESPACE_QUALIFIER Locale locale_type;
   typedef boost::uint_least32_t        char_class_type;
public:
   icu_regex_traits_implementation(const U_NAMESPACE_QUALIFIER Locale& l)
      : m_locale(l)
   {
      UErrorCode success = U_ZERO_ERROR;
      m_collator.reset(U_NAMESPACE_QUALIFIER Collator::createInstance(l, success));
      if(U_SUCCESS(success) == 0)
         init_error();
      m_collator->setStrength(U_NAMESPACE_QUALIFIER Collator::IDENTICAL);
      success = U_ZERO_ERROR;
      m_primary_collator.reset(U_NAMESPACE_QUALIFIER Collator::createInstance(l, success));
      if(U_SUCCESS(success) == 0)
         init_error();
      m_primary_collator->setStrength(U_NAMESPACE_QUALIFIER Collator::PRIMARY);
   }
   U_NAMESPACE_QUALIFIER Locale getloc()const
   {
      return m_locale;
   }
   string_type do_transform(const char_type* p1, const char_type* p2, const U_NAMESPACE_QUALIFIER Collator* pcoll) const;
   string_type transform(const char_type* p1, const char_type* p2) const
   {
      return do_transform(p1, p2, m_collator.get());
   }
   string_type transform_primary(const char_type* p1, const char_type* p2) const
   {
      return do_transform(p1, p2, m_primary_collator.get());
   }
private:
   void init_error()
   {
      std::runtime_error e("Could not initialize ICU resources");
      boost::throw_exception(e);
   }
   U_NAMESPACE_QUALIFIER Locale m_locale;                                  // The ICU locale that we're using
   boost::scoped_ptr< U_NAMESPACE_QUALIFIER Collator> m_collator;          // The full collation object
   boost::scoped_ptr< U_NAMESPACE_QUALIFIER Collator> m_primary_collator;  // The primary collation object
};

inline boost::shared_ptr<icu_regex_traits_implementation> get_icu_regex_traits_implementation(const U_NAMESPACE_QUALIFIER Locale& loc)
{
   return boost::shared_ptr<icu_regex_traits_implementation>(new icu_regex_traits_implementation(loc));
}

}

class BOOST_REGEX_DECL icu_regex_traits
{
public:
   typedef UChar32                      char_type;
   typedef std::size_t                  size_type;
   typedef std::vector<char_type>       string_type;
   typedef U_NAMESPACE_QUALIFIER Locale locale_type;
#ifdef BOOST_NO_INT64_T
   typedef std::bitset<64>              char_class_type;
#else
   typedef boost::uint64_t              char_class_type;
#endif

   struct boost_extensions_tag{};

   icu_regex_traits()
      : m_pimpl(BOOST_REGEX_DETAIL_NS::get_icu_regex_traits_implementation(U_NAMESPACE_QUALIFIER Locale()))
   {
   }
   static size_type length(const char_type* p);

   ::boost::regex_constants::syntax_type syntax_type(char_type c)const
   {
      return ((c < 0x7f) && (c > 0)) ? BOOST_REGEX_DETAIL_NS::get_default_syntax_type(static_cast<char>(c)) : regex_constants::syntax_char;
   }
   ::boost::regex_constants::escape_syntax_type escape_syntax_type(char_type c) const
   {
      return ((c < 0x7f) && (c > 0)) ? BOOST_REGEX_DETAIL_NS::get_default_escape_syntax_type(static_cast<char>(c)) : regex_constants::syntax_char;
   }
   char_type translate(char_type c) const
   {
      return c;
   }
   char_type translate_nocase(char_type c) const
   {
      return ::u_tolower(c);
   }
   char_type translate(char_type c, bool icase) const
   {
      return icase ? translate_nocase(c) : translate(c);
   }
   char_type tolower(char_type c) const
   {
      return ::u_tolower(c);
   }
   char_type toupper(char_type c) const
   {
      return ::u_toupper(c);
   }
   string_type transform(const char_type* p1, const char_type* p2) const
   {
      return m_pimpl->transform(p1, p2);
   }
   string_type transform_primary(const char_type* p1, const char_type* p2) const
   {
      return m_pimpl->transform_primary(p1, p2);
   }
   char_class_type lookup_classname(const char_type* p1, const char_type* p2) const;
   string_type lookup_collatename(const char_type* p1, const char_type* p2) const;
   bool isctype(char_type c, char_class_type f) const;
   boost::intmax_t toi(const char_type*& p1, const char_type* p2, int radix)const
   {
      return BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
   }
   int value(char_type c, int radix)const
   {
      return u_digit(c, static_cast< ::int8_t>(radix));
   }
   locale_type imbue(locale_type l)
   {
      locale_type result(m_pimpl->getloc());
      m_pimpl = BOOST_REGEX_DETAIL_NS::get_icu_regex_traits_implementation(l);
      return result;
   }
   locale_type getloc()const
   {
      return locale_type();
   }
   std::string error_string(::boost::regex_constants::error_type n) const
   {
      return BOOST_REGEX_DETAIL_NS::get_default_error_string(n);
   }
private:
   icu_regex_traits(const icu_regex_traits&);
   icu_regex_traits& operator=(const icu_regex_traits&);

   //
   // define the bitmasks offsets we need for additional character properties:
   //
   enum{
      offset_blank = U_CHAR_CATEGORY_COUNT,
      offset_space = U_CHAR_CATEGORY_COUNT+1,
      offset_xdigit = U_CHAR_CATEGORY_COUNT+2,
      offset_underscore = U_CHAR_CATEGORY_COUNT+3,
      offset_unicode = U_CHAR_CATEGORY_COUNT+4,
      offset_any = U_CHAR_CATEGORY_COUNT+5,
      offset_ascii = U_CHAR_CATEGORY_COUNT+6,
      offset_horizontal = U_CHAR_CATEGORY_COUNT+7,
      offset_vertical = U_CHAR_CATEGORY_COUNT+8
   };

   //
   // and now the masks:
   //
   static const char_class_type mask_blank;
   static const char_class_type mask_space;
   static const char_class_type mask_xdigit;
   static const char_class_type mask_underscore;
   static const char_class_type mask_unicode;
   static const char_class_type mask_any;
   static const char_class_type mask_ascii;
   static const char_class_type mask_horizontal;
   static const char_class_type mask_vertical;

   static char_class_type lookup_icu_mask(const ::UChar32* p1, const ::UChar32* p2);

   boost::shared_ptr< ::boost::BOOST_REGEX_DETAIL_NS::icu_regex_traits_implementation> m_pimpl;
};

} // namespace boost

//
// template instances:
//
#define BOOST_REGEX_CHAR_T UChar32
#undef BOOST_REGEX_TRAITS_T
#define BOOST_REGEX_TRAITS_T , icu_regex_traits
#define BOOST_REGEX_ICU_INSTANCES
#ifdef BOOST_REGEX_ICU_INSTANTIATE
#  define BOOST_REGEX_INSTANTIATE
#endif
#include <boost/regex/v4/instances.hpp>
#undef BOOST_REGEX_CHAR_T
#undef BOOST_REGEX_TRAITS_T
#undef BOOST_REGEX_ICU_INSTANCES
#ifdef BOOST_REGEX_INSTANTIATE
#  undef BOOST_REGEX_INSTANTIATE
#endif

namespace boost{

// types:
typedef basic_regex< ::UChar32, icu_regex_traits> u32regex;
typedef match_results<const ::UChar32*> u32match;
typedef match_results<const ::UChar*> u16match;

//
// Construction of 32-bit regex types from UTF-8 and UTF-16 primitives:
//
namespace BOOST_REGEX_DETAIL_NS{

#if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
template <class InputIterator>
inline u32regex do_make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt,
                              const boost::mpl::int_<1>*)
{
   typedef boost::u8_to_u32_iterator<InputIterator, UChar32> conv_type;
   return u32regex(conv_type(i, i, j), conv_type(j, i, j), opt);
}

template <class InputIterator>
inline u32regex do_make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt,
                              const boost::mpl::int_<2>*)
{
   typedef boost::u16_to_u32_iterator<InputIterator, UChar32> conv_type;
   return u32regex(conv_type(i, i, j), conv_type(j, i, j), opt);
}

template <class InputIterator>
inline u32regex do_make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt,
                              const boost::mpl::int_<4>*)
{
   return u32regex(i, j, opt);
}
#else
template <class InputIterator>
inline u32regex do_make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt,
                              const boost::mpl::int_<1>*)
{
   typedef boost::u8_to_u32_iterator<InputIterator, UChar32> conv_type;
   typedef std::vector<UChar32> vector_type;
   vector_type v;
   conv_type a(i, i, j), b(j, i, j);
   while(a != b)
   {
      v.push_back(*a);
      ++a;
   }
   if(v.size())
      return u32regex(&*v.begin(), v.size(), opt);
   return u32regex(static_cast<UChar32 const*>(0), static_cast<u32regex::size_type>(0), opt);
}

template <class InputIterator>
inline u32regex do_make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt,
                              const boost::mpl::int_<2>*)
{
   typedef boost::u16_to_u32_iterator<InputIterator, UChar32> conv_type;
   typedef std::vector<UChar32> vector_type;
   vector_type v;
   conv_type a(i, i, j), b(j, i, j);
   while(a != b)
   {
      v.push_back(*a);
      ++a;
   }
   if(v.size())
      return u32regex(&*v.begin(), v.size(), opt);
   return u32regex(static_cast<UChar32 const*>(0), static_cast<u32regex::size_type>(0), opt);
}

template <class InputIterator>
inline u32regex do_make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt,
                              const boost::mpl::int_<4>*)
{
   typedef std::vector<UChar32> vector_type;
   vector_type v;
   while(i != j)
   {
      v.push_back((UChar32)(*i));
      ++i;
   }
   if(v.size())
      return u32regex(&*v.begin(), v.size(), opt);
   return u32regex(static_cast<UChar32 const*>(0), static_cast<u32regex::size_type>(0), opt);
}
#endif
}

//
// Construction from an iterator pair:
//
template <class InputIterator>
inline u32regex make_u32regex(InputIterator i,
                              InputIterator j,
                              boost::regex_constants::syntax_option_type opt)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(i, j, opt, static_cast<boost::mpl::int_<sizeof(*i)> const*>(0));
}
//
// construction from UTF-8 nul-terminated strings:
//
inline u32regex make_u32regex(const char* p, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(p, p + std::strlen(p), opt, static_cast<boost::mpl::int_<1> const*>(0));
}
inline u32regex make_u32regex(const unsigned char* p, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(p, p + std::strlen(reinterpret_cast<const char*>(p)), opt, static_cast<boost::mpl::int_<1> const*>(0));
}
//
// construction from UTF-16 nul-terminated strings:
//
#ifndef BOOST_NO_WREGEX
inline u32regex make_u32regex(const wchar_t* p, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(p, p + std::wcslen(p), opt, static_cast<boost::mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2)
inline u32regex make_u32regex(const UChar* p, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(p, p + u_strlen(p), opt, static_cast<boost::mpl::int_<2> const*>(0));
}
#endif
//
// construction from basic_string class-template:
//
template<class C, class T, class A>
inline u32regex make_u32regex(const std::basic_string<C, T, A>& s, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(s.begin(), s.end(), opt, static_cast<boost::mpl::int_<sizeof(C)> const*>(0));
}
//
// Construction from ICU string type:
//
inline u32regex make_u32regex(const U_NAMESPACE_QUALIFIER UnicodeString& s, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
   return BOOST_REGEX_DETAIL_NS::do_make_u32regex(s.getBuffer(), s.getBuffer() + s.length(), opt, static_cast<boost::mpl::int_<2> const*>(0));
}

//
// regex_match overloads that widen the character type as appropriate:
//
namespace BOOST_REGEX_DETAIL_NS{
template<class MR1, class MR2>
void copy_results(MR1& out, MR2 const& in)
{
   // copy results from an adapted MR2 match_results:
   out.set_size(in.size(), in.prefix().first.base(), in.suffix().second.base());
   out.set_base(in.base().base());
   for(int i = 0; i < (int)in.size(); ++i)
   {
      if(in[i].matched || !i)
      {
         out.set_first(in[i].first.base(), i);
         out.set_second(in[i].second.base(), i, in[i].matched);
      }
   }
#ifdef BOOST_REGEX_MATCH_EXTRA
   // Copy full capture info as well:
   for(int i = 0; i < (int)in.size(); ++i)
   {
      if(in[i].captures().size())
      {
         out[i].get_captures().assign(in[i].captures().size(), typename MR1::value_type());
         for(int j = 0; j < out[i].captures().size(); ++j)
         {
            out[i].get_captures()[j].first = in[i].captures()[j].first.base();
            out[i].get_captures()[j].second = in[i].captures()[j].second.base();
            out[i].get_captures()[j].matched = in[i].captures()[j].matched;
         }
      }
   }
#endif
}

template <class BidiIterator, class Allocator>
inline bool do_regex_match(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 boost::mpl::int_<4> const*)
{
   return ::boost::regex_match(first, last, m, e, flags);
}
template <class BidiIterator, class Allocator>
bool do_regex_match(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 boost::mpl::int_<2> const*)
{
   typedef u16_to_u32_iterator<BidiIterator, UChar32> conv_type;
   typedef match_results<conv_type>                   match_type;
   //typedef typename match_type::allocator_type        alloc_type;
   match_type what;
   bool result = ::boost::regex_match(conv_type(first, first, last), conv_type(last, first, last), what, e, flags);
   // copy results across to m:
   if(result) copy_results(m, what);
   return result;
}
template <class BidiIterator, class Allocator>
bool do_regex_match(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 boost::mpl::int_<1> const*)
{
   typedef u8_to_u32_iterator<BidiIterator, UChar32>  conv_type;
   typedef match_results<conv_type>                   match_type;
   //typedef typename match_type::allocator_type        alloc_type;
   match_type what;
   bool result = ::boost::regex_match(conv_type(first, first, last), conv_type(last, first, last), what, e, flags);
   // copy results across to m:
   if(result) copy_results(m, what);
   return result;
}
} // namespace BOOST_REGEX_DETAIL_NS

template <class BidiIterator, class Allocator>
inline bool u32regex_match(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(first, last, m, e, flags, static_cast<mpl::int_<sizeof(*first)> const*>(0));
}
inline bool u32regex_match(const UChar* p,
                 match_results<const UChar*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+u_strlen(p), m, e, flags, static_cast<mpl::int_<2> const*>(0));
}
#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) && !defined(BOOST_NO_WREGEX)
inline bool u32regex_match(const wchar_t* p,
                 match_results<const wchar_t*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+std::wcslen(p), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_match(const char* p,
                 match_results<const char*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+std::strlen(p), m, e, flags, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_match(const unsigned char* p,
                 match_results<const unsigned char*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+std::strlen((const char*)p), m, e, flags, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_match(const std::string& s,
                        match_results<std::string::const_iterator>& m,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(s.begin(), s.end(), m, e, flags, static_cast<mpl::int_<1> const*>(0));
}
#ifndef BOOST_NO_STD_WSTRING
inline bool u32regex_match(const std::wstring& s,
                        match_results<std::wstring::const_iterator>& m,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(s.begin(), s.end(), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_match(const U_NAMESPACE_QUALIFIER UnicodeString& s,
                        match_results<const UChar*>& m,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_match(s.getBuffer(), s.getBuffer() + s.length(), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
//
// regex_match overloads that do not return what matched:
//
template <class BidiIterator>
inline bool u32regex_match(BidiIterator first, BidiIterator last,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<BidiIterator> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(first, last, m, e, flags, static_cast<mpl::int_<sizeof(*first)> const*>(0));
}
inline bool u32regex_match(const UChar* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const UChar*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+u_strlen(p), m, e, flags, static_cast<mpl::int_<2> const*>(0));
}
#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) && !defined(BOOST_NO_WREGEX)
inline bool u32regex_match(const wchar_t* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const wchar_t*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+std::wcslen(p), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_match(const char* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const char*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+std::strlen(p), m, e, flags, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_match(const unsigned char* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const unsigned char*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(p, p+std::strlen((const char*)p), m, e, flags, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_match(const std::string& s,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   match_results<std::string::const_iterator> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(s.begin(), s.end(), m, e, flags, static_cast<mpl::int_<1> const*>(0));
}
#ifndef BOOST_NO_STD_WSTRING
inline bool u32regex_match(const std::wstring& s,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   match_results<std::wstring::const_iterator> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(s.begin(), s.end(), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_match(const U_NAMESPACE_QUALIFIER UnicodeString& s,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   match_results<const UChar*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_match(s.getBuffer(), s.getBuffer() + s.length(), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}

//
// regex_search overloads that widen the character type as appropriate:
//
namespace BOOST_REGEX_DETAIL_NS{
template <class BidiIterator, class Allocator>
inline bool do_regex_search(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 BidiIterator base,
                 boost::mpl::int_<4> const*)
{
   return ::boost::regex_search(first, last, m, e, flags, base);
}
template <class BidiIterator, class Allocator>
bool do_regex_search(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 BidiIterator base,
                 boost::mpl::int_<2> const*)
{
   typedef u16_to_u32_iterator<BidiIterator, UChar32> conv_type;
   typedef match_results<conv_type>                   match_type;
   //typedef typename match_type::allocator_type        alloc_type;
   match_type what;
   bool result = ::boost::regex_search(conv_type(first, first, last), conv_type(last, first, last), what, e, flags, conv_type(base));
   // copy results across to m:
   if(result) copy_results(m, what);
   return result;
}
template <class BidiIterator, class Allocator>
bool do_regex_search(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 BidiIterator base,
                 boost::mpl::int_<1> const*)
{
   typedef u8_to_u32_iterator<BidiIterator, UChar32>  conv_type;
   typedef match_results<conv_type>                   match_type;
   //typedef typename match_type::allocator_type        alloc_type;
   match_type what;
   bool result = ::boost::regex_search(conv_type(first, first, last), conv_type(last, first, last), what, e, flags, conv_type(base));
   // copy results across to m:
   if(result) copy_results(m, what);
   return result;
}
}

template <class BidiIterator, class Allocator>
inline bool u32regex_search(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(first, last, m, e, flags, first, static_cast<mpl::int_<sizeof(*first)> const*>(0));
}
template <class BidiIterator, class Allocator>
inline bool u32regex_search(BidiIterator first, BidiIterator last,
                 match_results<BidiIterator, Allocator>& m,
                 const u32regex& e,
                 match_flag_type flags,
                 BidiIterator base)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(first, last, m, e, flags, base, static_cast<mpl::int_<sizeof(*first)> const*>(0));
}
inline bool u32regex_search(const UChar* p,
                 match_results<const UChar*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+u_strlen(p), m, e, flags, p, static_cast<mpl::int_<2> const*>(0));
}
#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) && !defined(BOOST_NO_WREGEX)
inline bool u32regex_search(const wchar_t* p,
                 match_results<const wchar_t*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+std::wcslen(p), m, e, flags, p, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_search(const char* p,
                 match_results<const char*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+std::strlen(p), m, e, flags, p, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_search(const unsigned char* p,
                 match_results<const unsigned char*>& m,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+std::strlen((const char*)p), m, e, flags, p, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_search(const std::string& s,
                        match_results<std::string::const_iterator>& m,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(s.begin(), s.end(), m, e, flags, s.begin(), static_cast<mpl::int_<1> const*>(0));
}
#ifndef BOOST_NO_STD_WSTRING
inline bool u32regex_search(const std::wstring& s,
                        match_results<std::wstring::const_iterator>& m,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(s.begin(), s.end(), m, e, flags, s.begin(), static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_search(const U_NAMESPACE_QUALIFIER UnicodeString& s,
                        match_results<const UChar*>& m,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::do_regex_search(s.getBuffer(), s.getBuffer() + s.length(), m, e, flags, s.getBuffer(), static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
template <class BidiIterator>
inline bool u32regex_search(BidiIterator first, BidiIterator last,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<BidiIterator> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(first, last, m, e, flags, first, static_cast<mpl::int_<sizeof(*first)> const*>(0));
}
inline bool u32regex_search(const UChar* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const UChar*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+u_strlen(p), m, e, flags, p, static_cast<mpl::int_<2> const*>(0));
}
#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) && !defined(BOOST_NO_WREGEX)
inline bool u32regex_search(const wchar_t* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const wchar_t*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+std::wcslen(p), m, e, flags, p, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_search(const char* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const char*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+std::strlen(p), m, e, flags, p, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_search(const unsigned char* p,
                 const u32regex& e,
                 match_flag_type flags = match_default)
{
   match_results<const unsigned char*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(p, p+std::strlen((const char*)p), m, e, flags, p, static_cast<mpl::int_<1> const*>(0));
}
inline bool u32regex_search(const std::string& s,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   match_results<std::string::const_iterator> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(s.begin(), s.end(), m, e, flags, s.begin(), static_cast<mpl::int_<1> const*>(0));
}
#ifndef BOOST_NO_STD_WSTRING
inline bool u32regex_search(const std::wstring& s,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   match_results<std::wstring::const_iterator> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(s.begin(), s.end(), m, e, flags, s.begin(), static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_search(const U_NAMESPACE_QUALIFIER UnicodeString& s,
                        const u32regex& e,
                        match_flag_type flags = match_default)
{
   match_results<const UChar*> m;
   return BOOST_REGEX_DETAIL_NS::do_regex_search(s.getBuffer(), s.getBuffer() + s.length(), m, e, flags, s.getBuffer(), static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}

//
// overloads for regex_replace with utf-8 and utf-16 data types:
//
namespace BOOST_REGEX_DETAIL_NS{
template <class I>
inline std::pair< boost::u8_to_u32_iterator<I>, boost::u8_to_u32_iterator<I> >
   make_utf32_seq(I i, I j, mpl::int_<1> const*)
{
   return std::pair< boost::u8_to_u32_iterator<I>, boost::u8_to_u32_iterator<I> >(boost::u8_to_u32_iterator<I>(i, i, j), boost::u8_to_u32_iterator<I>(j, i, j));
}
template <class I>
inline std::pair< boost::u16_to_u32_iterator<I>, boost::u16_to_u32_iterator<I> >
   make_utf32_seq(I i, I j, mpl::int_<2> const*)
{
   return std::pair< boost::u16_to_u32_iterator<I>, boost::u16_to_u32_iterator<I> >(boost::u16_to_u32_iterator<I>(i, i, j), boost::u16_to_u32_iterator<I>(j, i, j));
}
template <class I>
inline std::pair< I, I >
   make_utf32_seq(I i, I j, mpl::int_<4> const*)
{
   return std::pair< I, I >(i, j);
}
template <class charT>
inline std::pair< boost::u8_to_u32_iterator<const charT*>, boost::u8_to_u32_iterator<const charT*> >
   make_utf32_seq(const charT* p, mpl::int_<1> const*)
{
   std::size_t len = std::strlen((const char*)p);
   return std::pair< boost::u8_to_u32_iterator<const charT*>, boost::u8_to_u32_iterator<const charT*> >(boost::u8_to_u32_iterator<const charT*>(p, p, p+len), boost::u8_to_u32_iterator<const charT*>(p+len, p, p+len));
}
template <class charT>
inline std::pair< boost::u16_to_u32_iterator<const charT*>, boost::u16_to_u32_iterator<const charT*> >
   make_utf32_seq(const charT* p, mpl::int_<2> const*)
{
   std::size_t len = u_strlen((const UChar*)p);
   return std::pair< boost::u16_to_u32_iterator<const charT*>, boost::u16_to_u32_iterator<const charT*> >(boost::u16_to_u32_iterator<const charT*>(p, p, p + len), boost::u16_to_u32_iterator<const charT*>(p+len, p, p + len));
}
template <class charT>
inline std::pair< const charT*, const charT* >
   make_utf32_seq(const charT* p, mpl::int_<4> const*)
{
   return std::pair< const charT*, const charT* >(p, p+icu_regex_traits::length((UChar32 const*)p));
}
template <class OutputIterator>
inline OutputIterator make_utf32_out(OutputIterator o, mpl::int_<4> const*)
{
   return o;
}
template <class OutputIterator>
inline utf16_output_iterator<OutputIterator> make_utf32_out(OutputIterator o, mpl::int_<2> const*)
{
   return o;
}
template <class OutputIterator>
inline utf8_output_iterator<OutputIterator> make_utf32_out(OutputIterator o, mpl::int_<1> const*)
{
   return o;
}

template <class OutputIterator, class I1, class I2>
OutputIterator do_regex_replace(OutputIterator out,
                                 std::pair<I1, I1> const& in,
                                 const u32regex& e,
                                 const std::pair<I2, I2>& fmt,
                                 match_flag_type flags
                                 )
{
   // unfortunately we have to copy the format string in order to pass in onward:
   std::vector<UChar32> f;
#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
   f.assign(fmt.first, fmt.second);
#else
   f.clear();
   I2 pos = fmt.first;
   while(pos != fmt.second)
      f.push_back(*pos++);
#endif

   regex_iterator<I1, UChar32, icu_regex_traits> i(in.first, in.second, e, flags);
   regex_iterator<I1, UChar32, icu_regex_traits> j;
   if(i == j)
   {
      if(!(flags & regex_constants::format_no_copy))
         out = BOOST_REGEX_DETAIL_NS::copy(in.first, in.second, out);
   }
   else
   {
      I1 last_m = in.first;
      while(i != j)
      {
         if(!(flags & regex_constants::format_no_copy))
            out = BOOST_REGEX_DETAIL_NS::copy(i->prefix().first, i->prefix().second, out);
         if(f.size())
            out = ::boost::BOOST_REGEX_DETAIL_NS::regex_format_imp(out, *i, &*f.begin(), &*f.begin() + f.size(), flags, e.get_traits());
         else
            out = ::boost::BOOST_REGEX_DETAIL_NS::regex_format_imp(out, *i, static_cast<UChar32 const*>(0), static_cast<UChar32 const*>(0), flags, e.get_traits());
         last_m = (*i)[0].second;
         if(flags & regex_constants::format_first_only)
            break;
         ++i;
      }
      if(!(flags & regex_constants::format_no_copy))
         out = BOOST_REGEX_DETAIL_NS::copy(last_m, in.second, out);
   }
   return out;
}
template <class BaseIterator>
inline const BaseIterator& extract_output_base(const BaseIterator& b)
{
   return b;
}
template <class BaseIterator>
inline BaseIterator extract_output_base(const utf8_output_iterator<BaseIterator>& b)
{
   return b.base();
}
template <class BaseIterator>
inline BaseIterator extract_output_base(const utf16_output_iterator<BaseIterator>& b)
{
   return b.base();
}
}  // BOOST_REGEX_DETAIL_NS

template <class OutputIterator, class BidirectionalIterator, class charT>
inline OutputIterator u32regex_replace(OutputIterator out,
                         BidirectionalIterator first,
                         BidirectionalIterator last,
                         const u32regex& e,
                         const charT* fmt,
                         match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::extract_output_base
    (
      BOOST_REGEX_DETAIL_NS::do_regex_replace(
         BOOST_REGEX_DETAIL_NS::make_utf32_out(out, static_cast<mpl::int_<sizeof(*first)> const*>(0)),
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(first, last, static_cast<mpl::int_<sizeof(*first)> const*>(0)),
         e,
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(fmt, static_cast<mpl::int_<sizeof(*fmt)> const*>(0)),
         flags)
      );
}

template <class OutputIterator, class Iterator, class charT>
inline OutputIterator u32regex_replace(OutputIterator out,
                         Iterator first,
                         Iterator last,
                         const u32regex& e,
                         const std::basic_string<charT>& fmt,
                         match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::extract_output_base
    (
      BOOST_REGEX_DETAIL_NS::do_regex_replace(
         BOOST_REGEX_DETAIL_NS::make_utf32_out(out, static_cast<mpl::int_<sizeof(*first)> const*>(0)),
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(first, last, static_cast<mpl::int_<sizeof(*first)> const*>(0)),
         e,
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(fmt.begin(), fmt.end(), static_cast<mpl::int_<sizeof(charT)> const*>(0)),
         flags)
      );
}

template <class OutputIterator, class Iterator>
inline OutputIterator u32regex_replace(OutputIterator out,
                         Iterator first,
                         Iterator last,
                         const u32regex& e,
                         const U_NAMESPACE_QUALIFIER UnicodeString& fmt,
                         match_flag_type flags = match_default)
{
   return BOOST_REGEX_DETAIL_NS::extract_output_base
   (
      BOOST_REGEX_DETAIL_NS::do_regex_replace(
         BOOST_REGEX_DETAIL_NS::make_utf32_out(out, static_cast<mpl::int_<sizeof(*first)> const*>(0)),
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(first, last, static_cast<mpl::int_<sizeof(*first)> const*>(0)),
         e,
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(fmt.getBuffer(), fmt.getBuffer() + fmt.length(), static_cast<mpl::int_<2> const*>(0)),
         flags)
      );
}

template <class charT>
std::basic_string<charT> u32regex_replace(const std::basic_string<charT>& s,
                         const u32regex& e,
                         const charT* fmt,
                         match_flag_type flags = match_default)
{
   std::basic_string<charT> result;
   BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<charT> > i(result);
   u32regex_replace(i, s.begin(), s.end(), e, fmt, flags);
   return result;
}

template <class charT>
std::basic_string<charT> u32regex_replace(const std::basic_string<charT>& s,
                         const u32regex& e,
                         const std::basic_string<charT>& fmt,
                         match_flag_type flags = match_default)
{
   std::basic_string<charT> result;
   BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<charT> > i(result);
   u32regex_replace(i, s.begin(), s.end(), e, fmt.c_str(), flags);
   return result;
}

namespace BOOST_REGEX_DETAIL_NS{

class unicode_string_out_iterator
{
   U_NAMESPACE_QUALIFIER UnicodeString* out;
public:
   unicode_string_out_iterator(U_NAMESPACE_QUALIFIER UnicodeString& s) : out(&s) {}
   unicode_string_out_iterator& operator++() { return *this; }
   unicode_string_out_iterator& operator++(int) { return *this; }
   unicode_string_out_iterator& operator*() { return *this; }
   unicode_string_out_iterator& operator=(UChar v)
   {
      *out += v;
      return *this;
   }
   typedef std::ptrdiff_t difference_type;
   typedef UChar value_type;
   typedef value_type* pointer;
   typedef value_type& reference;
   typedef std::output_iterator_tag iterator_category;
};

}

inline U_NAMESPACE_QUALIFIER UnicodeString u32regex_replace(const U_NAMESPACE_QUALIFIER UnicodeString& s,
                         const u32regex& e,
                         const UChar* fmt,
                         match_flag_type flags = match_default)
{
   U_NAMESPACE_QUALIFIER UnicodeString result;
   BOOST_REGEX_DETAIL_NS::unicode_string_out_iterator i(result);
   u32regex_replace(i, s.getBuffer(), s.getBuffer()+s.length(), e, fmt, flags);
   return result;
}

inline U_NAMESPACE_QUALIFIER UnicodeString u32regex_replace(const U_NAMESPACE_QUALIFIER UnicodeString& s,
                         const u32regex& e,
                         const U_NAMESPACE_QUALIFIER UnicodeString& fmt,
                         match_flag_type flags = match_default)
{
   U_NAMESPACE_QUALIFIER UnicodeString result;
   BOOST_REGEX_DETAIL_NS::unicode_string_out_iterator i(result);
   BOOST_REGEX_DETAIL_NS::do_regex_replace(
         BOOST_REGEX_DETAIL_NS::make_utf32_out(i, static_cast<mpl::int_<2> const*>(0)),
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(s.getBuffer(), s.getBuffer()+s.length(), static_cast<mpl::int_<2> const*>(0)),
         e,
         BOOST_REGEX_DETAIL_NS::make_utf32_seq(fmt.getBuffer(), fmt.getBuffer() + fmt.length(), static_cast<mpl::int_<2> const*>(0)),
         flags);
   return result;
}

} // namespace boost.

#ifdef BOOST_MSVC
#pragma warning (pop)
#endif

#include <boost/regex/v4/u32regex_iterator.hpp>
#include <boost/regex/v4/u32regex_token_iterator.hpp>

#endif


code:
/*
 *
 * Copyright (c) 1998-2002
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         pattern_except.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Declares pattern-matching exception classes.
  */

#ifndef BOOST_RE_PAT_EXCEPT_HPP
#define BOOST_RE_PAT_EXCEPT_HPP

#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif

#include <stdexcept>
#include <cstddef>
#include <boost/regex/v4/error_type.hpp>

namespace boost{

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_PREFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4275)
#endif
class BOOST_REGEX_DECL regex_error : public std::runtime_error
{
public:
   explicit regex_error(const std::string& s, regex_constants::error_type err = regex_constants::error_unknown, std::ptrdiff_t pos = 0);
   explicit regex_error(regex_constants::error_type err);
   ~regex_error() throw();
   regex_constants::error_type code()const
   { return m_error_code; }
   std::ptrdiff_t position()const
   { return m_position; }
   void raise()const;
private:
   regex_constants::error_type m_error_code;
   std::ptrdiff_t m_position;
};

typedef regex_error bad_pattern;
typedef regex_error bad_expression;

namespace BOOST_REGEX_DETAIL_NS{

BOOST_REGEX_DECL void BOOST_REGEX_CALL raise_runtime_error(const std::runtime_error& ex);

template <class traits>
void raise_error(const traits& t, regex_constants::error_type code)
{
   (void)t;  // warning suppression
   std::runtime_error e(t.error_string(code));
   ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(e);
}

}

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

} // namespace boost

#endif


code:
/*
 *
 * Copyright (c) 2004
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         object_cache.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Implements a generic object cache.
  */

#ifndef BOOST_REGEX_OBJECT_CACHE_HPP
#define BOOST_REGEX_OBJECT_CACHE_HPP

#include <map>
#include <list>
#include <stdexcept>
#include <string>
#include <boost/config.hpp>
#include <boost/shared_ptr.hpp>
#ifdef BOOST_HAS_THREADS
#include <boost/regex/pending/static_mutex.hpp>
#endif

namespace boost{

template <class Key, class Object>
class object_cache
{
public:
   typedef std::pair< ::boost::shared_ptr<Object const>, Key const*> value_type;
   typedef std::list<value_type> list_type;
   typedef typename list_type::iterator list_iterator;
   typedef std::map<Key, list_iterator> map_type;
   typedef typename map_type::iterator map_iterator;
   typedef typename list_type::size_type size_type;
   static boost::shared_ptr<Object const> get(const Key& k, size_type l_max_cache_size);

private:
   static boost::shared_ptr<Object const> do_get(const Key& k, size_type l_max_cache_size);

   struct data
   {
      list_type   cont;
      map_type    index;
   };

   // Needed by compilers not implementing the resolution to DR45. For reference,
   // see http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
   friend struct data;
};

template <class Key, class Object>
boost::shared_ptr<Object const> object_cache<Key, Object>::get(const Key& k, size_type l_max_cache_size)
{
#ifdef BOOST_HAS_THREADS
   static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT;

   boost::static_mutex::scoped_lock l(mut);
   if(l)
   {
      return do_get(k, l_max_cache_size);
   }
   //
   // what do we do if the lock fails?
   // for now just throw, but we should never really get here...
   //
   ::boost::throw_exception(std::runtime_error("Error in thread safety code: could not acquire a lock"));
#if defined(BOOST_NO_UNREACHABLE_RETURN_DETECTION) || defined(BOOST_NO_EXCEPTIONS)
   return boost::shared_ptr<Object>();
#endif
#else
   return do_get(k, l_max_cache_size);
#endif
}

template <class Key, class Object>
boost::shared_ptr<Object const> object_cache<Key, Object>::do_get(const Key& k, size_type l_max_cache_size)
{
   typedef typename object_cache<Key, Object>::data object_data;
   typedef typename map_type::size_type map_size_type;
   static object_data s_data;

   //
   // see if the object is already in the cache:
   //
   map_iterator mpos = s_data.index.find(k);
   if(mpos != s_data.index.end())
   {
      //
      // Eureka!
      // We have a cached item, bump it up the list and return it:
      //
      if(--(s_data.cont.end()) != mpos->second)
      {
         // splice out the item we want to move:
         list_type temp;
         temp.splice(temp.end(), s_data.cont, mpos->second);
         // and now place it at the end of the list:
         s_data.cont.splice(s_data.cont.end(), temp, temp.begin());
         BOOST_ASSERT(*(s_data.cont.back().second) == k);
         // update index with new position:
         mpos->second = --(s_data.cont.end());
         BOOST_ASSERT(&(mpos->first) == mpos->second->second);
         BOOST_ASSERT(&(mpos->first) == s_data.cont.back().second);
      }
      return s_data.cont.back().first;
   }
   //
   // if we get here then the item is not in the cache,
   // so create it:
   //
   boost::shared_ptr<Object const> result(new Object(k));
   //
   // Add it to the list, and index it:
   //
   s_data.cont.push_back(value_type(result, static_cast<Key const*>(0)));
   s_data.index.insert(std::make_pair(k, --(s_data.cont.end())));
   s_data.cont.back().second = &(s_data.index.find(k)->first);
   map_size_type s = s_data.index.size();
   BOOST_ASSERT(s_data.index[k]->first.get() == result.get());
   BOOST_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second);
   BOOST_ASSERT(s_data.index.find(k)->first == k);
   if(s > l_max_cache_size)
   {
      //
      // We have too many items in the list, so we need to start
      // popping them off the back of the list, but only if they're
      // being held uniquely by us:
      //
      list_iterator pos = s_data.cont.begin();
      list_iterator last = s_data.cont.end();
      while((pos != last) && (s > l_max_cache_size))
      {
         if(pos->first.unique())
         {
            list_iterator condemmed(pos);
            ++pos;
            // now remove the items from our containers,
            // then order has to be as follows:
            BOOST_ASSERT(s_data.index.find(*(condemmed->second)) != s_data.index.end());
            s_data.index.erase(*(condemmed->second));
            s_data.cont.erase(condemmed);
            --s;
         }
         else
            ++pos;
      }
      BOOST_ASSERT(s_data.index[k]->first.get() == result.get());
      BOOST_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second);
      BOOST_ASSERT(s_data.index.find(k)->first == k);
   }
   return result;
}

}

#endif


code:
/*
 *
 * Copyright (c) 2004
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         static_mutex.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Declares static_mutex lock type, there are three different
  *                implementations: POSIX pthreads, WIN32 threads, and portable,
  *                these are described in more detail below.
  */

#ifndef BOOST_REGEX_STATIC_MUTEX_HPP
#define BOOST_REGEX_STATIC_MUTEX_HPP

#include <boost/config.hpp>
#include <boost/regex/config.hpp> // dll import/export options.

#ifdef BOOST_HAS_PTHREADS
#include <pthread.h>
#endif

#if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER)
//
// pthreads version:
// simple wrap around a pthread_mutex_t initialized with
// PTHREAD_MUTEX_INITIALIZER.
//
namespace boost{

class static_mutex;

#define BOOST_STATIC_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, }

class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
   scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
   ~scoped_static_mutex_lock();
   inline bool locked()const
   {
      return m_have_lock;
   }
   inline operator void const*()const
   {
      return locked() ? this : 0;
   }
   void lock();
   void unlock();
private:
   static_mutex& m_mutex;
   bool m_have_lock;
};

class static_mutex
{
public:
   typedef scoped_static_mutex_lock scoped_lock;
   pthread_mutex_t m_mutex;
};

} // namespace boost
#elif defined(BOOST_HAS_WINTHREADS)
//
// Win32 version:
// Use a 32-bit int as a lock, along with a test-and-set
// implementation using InterlockedCompareExchange.
//

#include <boost/cstdint.hpp>

namespace boost{

class BOOST_REGEX_DECL scoped_static_mutex_lock;

class static_mutex
{
public:
   typedef scoped_static_mutex_lock scoped_lock;
   boost::int32_t m_mutex;
};

#define BOOST_STATIC_MUTEX_INIT { 0, }

class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
   scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
   ~scoped_static_mutex_lock();
   operator void const*()const
   {
      return locked() ? this : 0;
   }
   bool locked()const
   {
      return m_have_lock;
   }
   void lock();
   void unlock();
private:
   static_mutex& m_mutex;
   bool m_have_lock;
   scoped_static_mutex_lock(const scoped_static_mutex_lock&);
   scoped_static_mutex_lock& operator=(const scoped_static_mutex_lock&);
};

} // namespace

#else
//
// Portable version of a static mutex based on Boost.Thread library:
// This has to use a single mutex shared by all instances of static_mutex
// because boost::call_once doesn't alow us to pass instance information
// down to the initialisation proceedure.  In fact the initialisation routine
// may need to be called more than once - but only once per instance.
//
// Since this preprocessor path is almost never taken, we hide these header
// dependencies so that build tools don't find them.
//
#define BOOST_REGEX_H1 <boost/thread/once.hpp>
#define BOOST_REGEX_H2 <boost/thread/recursive_mutex.hpp>
#define BOOST_REGEX_H3 <boost/thread/lock_types.hpp>
#include BOOST_REGEX_H1
#include BOOST_REGEX_H2
#include BOOST_REGEX_H3
#undef BOOST_REGEX_H1
#undef BOOST_REGEX_H2
#undef BOOST_REGEX_H3

namespace boost{

class BOOST_REGEX_DECL scoped_static_mutex_lock;
extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex();

class BOOST_REGEX_DECL static_mutex
{
public:
   typedef scoped_static_mutex_lock scoped_lock;
   static void init();
   static boost::recursive_mutex* m_pmutex;
   static boost::once_flag m_once;
};

#define BOOST_STATIC_MUTEX_INIT {  }

class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
   scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
   ~scoped_static_mutex_lock();
   operator void const*()const;
   bool locked()const;
   void lock();
   void unlock();
private:
   boost::unique_lock<boost::recursive_mutex>* m_plock;
   bool m_have_lock;
};

inline scoped_static_mutex_lock::operator void const*()const
{
   return locked() ? this : 0;
}

inline bool scoped_static_mutex_lock::locked()const
{
   return m_have_lock;
}

} // namespace

#endif

#endif