Added object cache - internal state to traits classes is now cached.

Added first start to Unicode support.
Enabled external template instance support.
Fixed VC6 support.


[SVN r25914]
This commit is contained in:
John Maddock committed 2004-10-28 11:17:26 +00:00
1 parent 70508f307a
commit c05af49444
35 files changed
+3942 -2590

No files matched your search

+5 -10
View File
@@ -374,9 +374,9 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info();
#endif
#if defined(BOOST_REGEX_DIAG)
# pragma message ("BOOST_REGEX_DECL set as: " BOOST_STRINGIZE(BOOST_REGEX_DECL))
# pragma message ("BOOST_REGEX_CALL set as: " BOOST_STRINGIZE(BOOST_REGEX_CALL))
# pragma message ("BOOST_REGEX_CCALL set as: " BOOST_STRINGIZE(BOOST_REGEX_CCALL))
# 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
@@ -384,20 +384,15 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info();
#else
# pragma message ("Using Win32 locale in regex traits class")
#endif
#ifdef BOOST_REGEX_DYN_LINK
#if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# pragma message ("Dynamic linking enabled")
#endif
#ifdef BOOST_REGEX_NO_LIB
#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
#ifdef BOOST_REGEX_V3
# pragma message ("Using Version 3 regex code")
#else
# pragma message ("Using Version 4 regex code")
#endif
#endif
+200
View File
@@ -0,0 +1,200 @@
/*
*
* Copyright (c) 2004
* Dr 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 <bitset>
namespace boost{
namespace re_detail{
//
// Implementation details:
//
class icu_regex_traits_implementation
{
typedef UChar32 char_type;
typedef std::size_t size_type;
typedef std::vector<char_type> string_type;
typedef ::Locale locale_type;
typedef boost::uint_least32_t char_class_type;
public:
icu_regex_traits_implementation(const ::Locale& l)
: m_locale(l)
{
UErrorCode success = U_ZERO_ERROR;
m_collator.reset( ::Collator::createInstance(l, success));
if(U_SUCCESS(success) == 0)
init_error();
m_collator->setStrength(::Collator::IDENTICAL);
success = U_ZERO_ERROR;
m_primary_collator.reset( ::Collator::createInstance(l, success));
if(U_SUCCESS(success) == 0)
init_error();
m_primary_collator->setStrength(::Collator::PRIMARY);
}
::Locale getloc()const
{
return m_locale;
}
string_type do_transform(const char_type* p1, const char_type* p2, const ::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);
}
::Locale m_locale; // The ICU locale that we're using
boost::scoped_ptr< ::Collator> m_collator; // The full collation object
boost::scoped_ptr< ::Collator> m_primary_collator; // The primary collation object
};
inline boost::shared_ptr<icu_regex_traits_implementation> get_icu_regex_traits_implementation(const ::Locale& loc)
{
return boost::shared_ptr<icu_regex_traits_implementation>(new icu_regex_traits_implementation(loc));
}
}
class icu_regex_traits
{
public:
typedef UChar32 char_type;
typedef std::size_t size_type;
typedef std::vector<char_type> string_type;
typedef ::Locale locale_type;
typedef std::bitset<64> char_class_type;
struct boost_extensions_tag{};
icu_regex_traits()
: m_pimpl(re_detail::get_icu_regex_traits_implementation(::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)) ? re_detail::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)) ? re_detail::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;
int toi(const char_type*& p1, const char_type* p2, int radix)const
{
return re_detail::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 = re_detail::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 re_detail::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,
};
//
// 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;
boost::shared_ptr< ::boost::re_detail::icu_regex_traits_implementation> m_pimpl;
};
// types:
typedef basic_regex< ::UChar32, icu_regex_traits> u32regex;
typedef match_results<const ::UChar32*> u32match;
} // namespace boost.
#endif
@@ -0,0 +1,159 @@
/*
*
* Copyright (c) 2004
* Dr 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
{
typedef std::pair< ::boost::shared_ptr<Object>, 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;
public:
static boost::shared_ptr<Object> get(const Key& k, size_type max_cache_size);
private:
static boost::shared_ptr<Object> do_get(const Key& k, size_type max_cache_size);
struct data
{
list_type cont;
map_type index;
};
};
template <class Key, class Object>
boost::shared_ptr<Object> object_cache<Key, Object>::get(const Key& k, size_type 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, 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"));
return boost::shared_ptr<Object>();
#else
return do_get(k, max_cache_size);
#endif
}
template <class Key, class Object>
boost::shared_ptr<Object> object_cache<Key, Object>::do_get(const Key& k, size_type max_cache_size)
{
typedef typename object_cache<Key, Object>::data object_data;
typedef typename list_type::size_type list_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> result(new Object(k));
//
// Add it to the list, and index it:
//
s_data.cont.push_back(value_type(result, 0));
s_data.index[k] = --(s_data.cont.end());
s_data.cont.back().second = &(s_data.index.find(k)->first);
list_size_type s = s_data.cont.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 > 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 > 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
@@ -0,0 +1,180 @@
/*
*
* Copyright (c) 2004
* Dr 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 BOOST_REGEX_DECL scoped_static_mutex_lock;
class static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
pthread_mutex_t m_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();
operator void const*()const;
bool locked()const;
void lock();
void unlock();
private:
static_mutex& m_mutex;
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 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;
bool locked()const;
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&);
};
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
#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.
//
#include <boost/thread/once.hpp>
#include <boost/thread/recursive_mutex.hpp>
namespace boost{
class BOOST_REGEX_DECL scoped_static_mutex_lock;
extern "C" BOOST_REGEX_DECL void 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::recursive_mutex::scoped_lock* 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
@@ -0,0 +1,261 @@
/*
*
* Copyright (c) 2004
* Dr 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 unicode_iterator.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Iterator adapters for converting between different Unicode encodings.
*/
#ifndef BOOST_REGEX_UNICODE_ITERATOR_HPP
#define BOOST_REGEX_UNICODE_ITERATOR_HPP
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/static_assert.hpp>
#include <stdexcept>
#ifndef BOOST_NO_STD_LOCALE
#include <sstream>
#endif
namespace boost{
namespace detail{
static const ::boost::uint16_t high_surrogate_base = 0xD7C0u;
static const ::boost::uint16_t low_surrogate_base = 0xDC00u;
static const ::boost::uint32_t ten_bit_mask = 0x3FFu;
inline bool is_high_surrogate(::boost::uint16_t v)
{
return (v & 0xFC00u) == 0xd800u;
}
inline bool is_low_surrogate(::boost::uint16_t v)
{
return (v & 0xFC00u) == 0xdc00u;
}
template <class T>
inline bool is_surrogate(T v)
{
return (v & 0xF800u) == 0xd800;
}
}
template <class BaseIterator, class U16Type = ::boost::uint16_t>
class u32_to_u16_iterator
: public boost::iterator_facade<u32_to_u16_iterator<BaseIterator, U16Type>, U16Type, std::bidirectional_iterator_tag, const U16Type>
{
typedef boost::iterator_facade<u32_to_u16_iterator<BaseIterator>, U16Type, std::bidirectional_iterator_tag, const U16Type> base_type;
typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 32);
BOOST_STATIC_ASSERT(sizeof(U16Type)*CHAR_BIT == 16);
public:
typename base_type::reference
dereference()const
{
if(m_current == 2)
const_cast<u32_to_u16_iterator*>(this)->extract_current();
return m_values[m_current];
}
bool equal(const u32_to_u16_iterator& that)const
{
if(m_position == that.m_position)
{
if((m_current >= 2) && (that.m_current < 2))
const_cast<u32_to_u16_iterator*>(this)->extract_current();
else if((m_current < 2) && (that.m_current >= 2))
const_cast<u32_to_u16_iterator&>(that).extract_current();
if(m_current == that.m_current)
return true;
}
return false;
}
void increment()
{
// if we have a pending read then read now, so that we know whether
// to skip a position, or move to a low-surrogate:
if(m_current == 2)
{
// pending read:
extract_current();
}
// move to the next surrogate position:
++m_current;
// if we've reached the end skip a position:
if(m_values[m_current] == 0)
{
m_current = 2;
++m_position;
}
}
void decrement()
{
if(m_current != 1)
{
// decrementing an iterator always leads to a valid position:
--m_position;
extract_current();
m_current = m_values[1] ? 1 : 0;
}
else
{
m_current = 0;
}
}
BaseIterator base()const
{
return m_position;
}
// construct:
u32_to_u16_iterator() : m_position(), m_current(0)
{
m_values[2] = 0;
}
u32_to_u16_iterator(BaseIterator b) : m_position(b), m_current(2)
{
m_values[2] = 0;
}
private:
void invalid_code_point(::boost::uint32_t val)
{
#ifndef BOOST_NO_STD_LOCALE
std::stringstream ss;
ss << "Invalid UTF-32 code point U+" << std::showbase << std::hex << val << " encountered while trying to encode UTF-16 sequence";
std::out_of_range e(ss.str());
#else
std::out_of_range e("Invalid UTF-32 code point encountered while trying to encode UTF-16 sequence");
#endif
boost::throw_exception(e);
}
void extract_current()
{
// begin by checking for a code point out of range:
if(static_cast< ::boost::uint32_t>(*m_position) >= 0x10000u)
{
if(static_cast< ::boost::uint32_t>(*m_position) > 0x10FFFFu)
invalid_code_point(*m_position);
// split into two surrogates:
base_value_type v = *m_position;
m_values[0] = static_cast<U16Type>(v >> 10) + detail::high_surrogate_base;
m_values[1] = static_cast<U16Type>(v & detail::ten_bit_mask) + detail::low_surrogate_base;
m_current = 0;
BOOST_ASSERT(detail::is_high_surrogate(m_values[0]));
BOOST_ASSERT(detail::is_low_surrogate(m_values[1]));
}
else
{
// 16-bit code point:
m_values[0] = static_cast<U16Type>(*m_position);
m_values[1] = 0;
m_current = 0;
// value must not be a surrogate:
if(detail::is_surrogate(m_values[0]))
invalid_code_point(*m_position);
}
}
BaseIterator m_position;
U16Type m_values[3];
unsigned m_current;
};
template <class BaseIterator, class U32Type = ::boost::uint32_t>
class u16_to_u32_iterator
: public boost::iterator_facade<u16_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type>
{
typedef boost::iterator_facade<u16_to_u32_iterator<BaseIterator>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type;
// special values for pending iterator reads:
BOOST_STATIC_CONSTANT(::boost::uint32_t, pending_read = 0xffffffffu);
typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 16);
BOOST_STATIC_ASSERT(sizeof(U32Type)*CHAR_BIT == 32);
public:
typename base_type::reference
dereference()const
{
if(m_value == pending_read)
const_cast<u16_to_u32_iterator*>(this)->extract_current();
return m_value;
}
bool equal(const u16_to_u32_iterator& that)const
{
return m_position == that.m_position;
}
void increment()
{
// skip high surrogate first if there is one:
if(detail::is_high_surrogate(*m_position)) ++m_position;
++m_position;
m_value = pending_read;
}
void decrement()
{
--m_position;
// if we have a low surrogate then go back one more:
if(detail::is_low_surrogate(*m_position))
--m_position;
m_value = pending_read;
}
BaseIterator base()const
{
return m_position;
}
// construct:
u16_to_u32_iterator() : m_position()
{
}
u16_to_u32_iterator(BaseIterator b) : m_position(b)
{
m_value = pending_read;
}
private:
void invalid_code_point(::boost::uint16_t val)
{
#ifndef BOOST_NO_STD_LOCALE
std::stringstream ss;
ss << "Misplaced UTF-16 surrogate U+" << std::showbase << std::hex << val << " encountered while trying to encode UTF-32 sequence";
std::out_of_range e(ss.str());
#else
std::out_of_range e("Misplaced UTF-16 surrogate encountered while trying to encode UTF-32 sequence");
#endif
boost::throw_exception(e);
}
void extract_current()
{
m_value = static_cast<U32Type>(static_cast< ::boost::uint16_t>(*m_position));
// if the last value is a high surrogate then adjust m_position and m_value as needed:
if(detail::is_high_surrogate(*m_position))
{
// precondition; next value must have be a low-surrogate:
::boost::uint16_t t = *++m_position;
if((*m_position & 0xFC00u) != 0xDC00u)
invalid_code_point(t);
m_value = (m_value - detail::high_surrogate_base) << 10;
m_value |= (static_cast<U32Type>(static_cast< ::boost::uint16_t>(t)) & detail::ten_bit_mask);
--m_position;
}
// postcondition; result must not be a surrogate:
if(detail::is_surrogate(m_value))
invalid_code_point(static_cast< ::boost::uint16_t>(m_value));
}
BaseIterator m_position;
U32Type m_value;
};
}
#endif // BOOST_REGEX_UNICODE_ITERATOR_HPP
@@ -1257,7 +1257,7 @@ bool valid_value(charT, int v, const mpl::true_&)
return (v >> (sizeof(charT) * CHAR_BIT)) == 0;
}
template <class charT>
bool valid_value(charT, int v, const mpl::false_&)
bool valid_value(charT, int, const mpl::false_&)
{
return true; // v will alsways fit in a charT
}
+2
View File
@@ -71,6 +71,8 @@ template class BOOST_REGEX_DECL basic_regex< BOOST_REGEX_CHAR_T >;
template class BOOST_REGEX_DECL basic_regex< BOOST_REGEX_CHAR_T >;
template class BOOST_REGEX_DECL match_results< const BOOST_REGEX_CHAR_T* >;
template class BOOST_REGEX_DECL match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >;
template class BOOST_REGEX_DECL ::boost::re_detail::perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >;
# ifdef BOOST_MSVC
# pragma warning(pop)
@@ -72,6 +72,13 @@ struct regex_iterator_traits<wchar_t*> : pointer_iterator_traits<wchar_t>{};
template<>
struct regex_iterator_traits<const wchar_t*> : const_pointer_iterator_traits<wchar_t>{};
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
template<>
struct regex_iterator_traits<unsigned short*> : pointer_iterator_traits<unsigned short>{};
template<>
struct regex_iterator_traits<const unsigned short*> : const_pointer_iterator_traits<unsigned short>{};
#endif
#if defined(__SGI_STL_PORT) && defined(__STL_DEBUG)
template<>
struct regex_iterator_traits<std::string::iterator> : pointer_iterator_traits<char>{};
+1 -1
View File
@@ -149,7 +149,7 @@ public:
string_type format(const string_type& fmt,
match_flag_type flags = format_default) const
{
return regex_format(*this, fmt, flags);
return regex_format<BidiIterator, char_type>(*this, fmt, flags);
}
// format with locale:
template <class OutputIterator, class RegexT>
+13 -6
View File
@@ -24,7 +24,7 @@ namespace re_detail{
//
// error checking API:
//
BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex::flag_type ef, match_flag_type mf);
BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex_constants::syntax_option_type ef, match_flag_type mf);
//
// function can_start:
//
@@ -85,11 +85,11 @@ template <class Seq, class C>
inline int string_compare(const Seq& s, const C* p)
{
std::size_t i = 0;
while(p[i] && (p[i] == s[i]))
while((i < s.size()) && (p[i] == s[i]))
{
++i;
}
return s[i] - p[i];
return (i == s.size()) ? -p[i] : s[i] - p[i];
}
#endif
# define STR_COMP(s,p) string_compare(s,p)
@@ -354,7 +354,9 @@ private:
bool match_backstep();
bool match_assert_backref();
bool match_toggle_case();
#ifdef BOOST_REGEX_RECURSIVE
bool backtrack_till_match(std::size_t count);
#endif
// find procs stored in s_find_vtable:
bool find_restart_any();
@@ -450,9 +452,14 @@ private:
unsigned used_block_count;
#endif
// these operations aren't allowed, so are declared private:
perl_matcher& operator=(const perl_matcher&);
perl_matcher(const perl_matcher&);
// these operations aren't allowed, so are declared private,
// bodies are provided to keep explicit-instantiation requests happy:
perl_matcher& operator=(const perl_matcher&)
{
return *this;
}
perl_matcher(const perl_matcher& that)
: m_result(that.m_result), re(that.re), traits_inst(that.traits_inst), rep_obj(0) {}
};
} // namespace re_detail
-1
View File
@@ -87,7 +87,6 @@
#ifndef BOOST_REGEX_MATCHER_HPP
#include <boost/regex/v4/perl_matcher.hpp>
#endif
//
// template instances:
//
+4 -4
View File
@@ -534,7 +534,7 @@ OutputIterator regex_format(OutputIterator out,
)
{
re_detail::trivial_format_traits<charT> traits;
return regex_format_imp(out, m, fmt, fmt + traits.length(fmt), flags, traits);
return re_detail::regex_format_imp(out, m, fmt, fmt + traits.length(fmt), flags, traits);
}
template <class OutputIterator, class Iterator, class charT>
@@ -545,7 +545,7 @@ OutputIterator regex_format(OutputIterator out,
)
{
re_detail::trivial_format_traits<charT> traits;
return regex_format_imp(out, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
return re_detail::regex_format_imp(out, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
}
template <class Iterator, class charT>
@@ -556,7 +556,7 @@ std::basic_string<charT> regex_format(const match_results<Iterator>& m,
std::basic_string<charT> result;
re_detail::string_out_iterator<std::basic_string<charT> > i(result);
re_detail::trivial_format_traits<charT> traits;
regex_format_imp(i, m, fmt, fmt + traits.length(fmt), flags, traits);
re_detail::regex_format_imp(i, m, fmt, fmt + traits.length(fmt), flags, traits);
return result;
}
@@ -568,7 +568,7 @@ std::basic_string<charT> regex_format(const match_results<Iterator>& m,
std::basic_string<charT> result;
re_detail::string_out_iterator<std::basic_string<charT> > i(result);
re_detail::trivial_format_traits<charT> traits;
regex_format_imp(i, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
re_detail::regex_format_imp(i, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
return result;
}
@@ -229,6 +229,11 @@ BOOST_REGEX_DECL char BOOST_REGEX_CALL global_upper(char c);
BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_lower(wchar_t c);
BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_upper(wchar_t c);
#endif
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL global_lower(unsigned short c);
BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL global_upper(unsigned short c);
#endif
template <class charT>
int global_value(charT c)
{