diff options
author | JINMEI Tatuya <jinmei@isc.org> | 2010-03-08 20:21:25 +0100 |
---|---|---|
committer | JINMEI Tatuya <jinmei@isc.org> | 2010-03-08 20:21:25 +0100 |
commit | 64593f39e0058ee7db459341db9f5050729eec2d (patch) | |
tree | 56f3d41d866bab1fb41fb7b2c4db5d2ee187501d /ext | |
parent | sync with trunk (diff) | |
download | kea-64593f39e0058ee7db459341db9f5050729eec2d.tar.xz kea-64593f39e0058ee7db459341db9f5050729eec2d.zip |
added more dependency for asio
git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-asio@1212 e5f2f494-b856-4b98-b285-d166d9295462
Diffstat (limited to 'ext')
175 files changed, 45033 insertions, 0 deletions
diff --git a/ext/boost/date_time/adjust_functors.hpp b/ext/boost/date_time/adjust_functors.hpp new file mode 100644 index 0000000000..7854ae4b76 --- /dev/null +++ b/ext/boost/date_time/adjust_functors.hpp @@ -0,0 +1,178 @@ +#ifndef _DATE_TIME_ADJUST_FUNCTORS_HPP___ +#define _DATE_TIME_ADJUST_FUNCTORS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/date.hpp" +#include "boost/date_time/wrapping_int.hpp" + +namespace boost { +namespace date_time { + + + //! Functor to iterate a fixed number of days + template<class date_type> + class day_functor + { + public: + typedef typename date_type::duration_type duration_type; + day_functor(int f) : f_(f) {} + duration_type get_offset(const date_type& d) const + { + // why is 'd' a parameter??? + // fix compiler warnings + d.year(); + return duration_type(f_); + } + duration_type get_neg_offset(const date_type& d) const + { + // fix compiler warnings + d.year(); + return duration_type(-f_); + } + private: + int f_; + }; + + + //! Provides calculation to find next nth month given a date + /*! This adjustment function provides the logic for 'month-based' + * advancement on a ymd based calendar. The policy it uses + * to handle the non existant end of month days is to back + * up to the last day of the month. Also, if the starting + * date is the last day of a month, this functor will attempt + * to adjust to the end of the month. + + */ + template<class date_type> + class month_functor + { + public: + typedef typename date_type::duration_type duration_type; + typedef typename date_type::calendar_type cal_type; + typedef typename cal_type::ymd_type ymd_type; + typedef typename cal_type::day_type day_type; + + month_functor(int f) : f_(f), origDayOfMonth_(0) {} + duration_type get_offset(const date_type& d) const + { + ymd_type ymd(d.year_month_day()); + if (origDayOfMonth_ == 0) { + origDayOfMonth_ = ymd.day; + day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month)); + if (endOfMonthDay == ymd.day) { + origDayOfMonth_ = -1; //force the value to the end of month + } + } + typedef date_time::wrapping_int2<short,1,12> wrap_int2; + typedef typename wrap_int2::int_type int_type; + wrap_int2 wi(ymd.month); + //calc the year wrap around, add() returns 0 or 1 if wrapped + int_type year = wi.add(static_cast<int_type>(f_)); + year = static_cast<int_type>(year + ymd.year); //calculate resulting year +// std::cout << "trace wi: " << wi.as_int() << std::endl; +// std::cout << "trace year: " << year << std::endl; + //find the last day for the new month + day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int())); + //original was the end of month -- force to last day of month + if (origDayOfMonth_ == -1) { + return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d; + } + day_type dayOfMonth = origDayOfMonth_; + if (dayOfMonth > resultingEndOfMonthDay) { + dayOfMonth = resultingEndOfMonthDay; + } + return date_type(year, wi.as_int(), dayOfMonth) - d; + } + //! Returns a negative duration_type + duration_type get_neg_offset(const date_type& d) const + { + ymd_type ymd(d.year_month_day()); + if (origDayOfMonth_ == 0) { + origDayOfMonth_ = ymd.day; + day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month)); + if (endOfMonthDay == ymd.day) { + origDayOfMonth_ = -1; //force the value to the end of month + } + } + typedef date_time::wrapping_int2<short,1,12> wrap_int2; + typedef typename wrap_int2::int_type int_type; + wrap_int2 wi(ymd.month); + //calc the year wrap around, add() returns 0 or 1 if wrapped + int_type year = wi.subtract(static_cast<int_type>(f_)); + year = static_cast<int_type>(year + ymd.year); //calculate resulting year + //find the last day for the new month + day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int())); + //original was the end of month -- force to last day of month + if (origDayOfMonth_ == -1) { + return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d; + } + day_type dayOfMonth = origDayOfMonth_; + if (dayOfMonth > resultingEndOfMonthDay) { + dayOfMonth = resultingEndOfMonthDay; + } + return date_type(year, wi.as_int(), dayOfMonth) - d; + } + private: + int f_; + mutable short origDayOfMonth_; + }; + + + //! Functor to iterate a over weeks + template<class date_type> + class week_functor + { + public: + typedef typename date_type::duration_type duration_type; + typedef typename date_type::calendar_type calendar_type; + week_functor(int f) : f_(f) {} + duration_type get_offset(const date_type& d) const + { + // why is 'd' a parameter??? + // fix compiler warnings + d.year(); + return duration_type(f_*calendar_type::days_in_week()); + } + duration_type get_neg_offset(const date_type& d) const + { + // fix compiler warnings + d.year(); + return duration_type(-f_*calendar_type::days_in_week()); + } + private: + int f_; + }; + + //! Functor to iterate by a year adjusting for leap years + template<class date_type> + class year_functor + { + public: + //typedef typename date_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + year_functor(int f) : _mf(f * 12) {} + duration_type get_offset(const date_type& d) const + { + return _mf.get_offset(d); + } + duration_type get_neg_offset(const date_type& d) const + { + return _mf.get_neg_offset(d); + } + private: + month_functor<date_type> _mf; + }; + + +} }//namespace date_time + + +#endif + diff --git a/ext/boost/date_time/c_local_time_adjustor.hpp b/ext/boost/date_time/c_local_time_adjustor.hpp new file mode 100644 index 0000000000..f8025828f7 --- /dev/null +++ b/ext/boost/date_time/c_local_time_adjustor.hpp @@ -0,0 +1,66 @@ +#ifndef DATE_TIME_C_LOCAL_TIME_ADJUSTOR_HPP__ +#define DATE_TIME_C_LOCAL_TIME_ADJUSTOR_HPP__ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +/*! @file c_local_time_adjustor.hpp + Time adjustment calculations based on machine +*/ + +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/c_time.hpp> + +namespace boost { +namespace date_time { + + //! Adjust to / from utc using the C API + /*! Warning!!! This class assumes that timezone settings of the + * machine are correct. This can be a very dangerous assumption. + */ + template<class time_type> + class c_local_adjustor { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + typedef typename date_type::duration_type date_duration_type; + //! Convert a utc time to local time + static time_type utc_to_local(const time_type& t) + { + date_type time_t_start_day(1970,1,1); + time_type time_t_start_time(time_t_start_day,time_duration_type(0,0,0)); + if (t < time_t_start_time) { + boost::throw_exception(std::out_of_range("Cannot convert dates prior to Jan 1, 1970")); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return time_t_start_time); // should never reach + } + date_duration_type dd = t.date() - time_t_start_day; + time_duration_type td = t.time_of_day(); + std::time_t t2 = dd.days()*86400 + td.hours()*3600 + td.minutes()*60 + td.seconds(); + std::tm tms, *tms_ptr; + tms_ptr = c_time::localtime(&t2, &tms); + date_type d(static_cast<unsigned short>(tms_ptr->tm_year + 1900), + static_cast<unsigned short>(tms_ptr->tm_mon + 1), + static_cast<unsigned short>(tms_ptr->tm_mday)); + time_duration_type td2(tms_ptr->tm_hour, + tms_ptr->tm_min, + tms_ptr->tm_sec, + t.time_of_day().fractional_seconds()); + + return time_type(d,td2); + } + }; + + + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/c_time.hpp b/ext/boost/date_time/c_time.hpp new file mode 100644 index 0000000000..42902a533b --- /dev/null +++ b/ext/boost/date_time/c_time.hpp @@ -0,0 +1,105 @@ +#ifndef DATE_TIME_C_TIME_HPP___ +#define DATE_TIME_C_TIME_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +/*! @file c_time.hpp + Provide workarounds related to the ctime header +*/ + +#include <ctime> +#include <string> // to be able to convert from string literals to exceptions +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/date_time/compiler_config.hpp> + +//Work around libraries that don't put time_t and time in namespace std +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::time_t; using ::time; using ::localtime; + using ::tm; using ::gmtime; } +#endif // BOOST_NO_STDC_NAMESPACE + +//The following is used to support high precision time clocks +#ifdef BOOST_HAS_GETTIMEOFDAY +#include <sys/time.h> +#endif + +#ifdef BOOST_HAS_FTIME +#include <time.h> +#endif + +namespace boost { +namespace date_time { + //! Provides a uniform interface to some 'ctime' functions + /*! Provides a uniform interface to some ctime functions and + * their '_r' counterparts. The '_r' functions require a pointer to a + * user created std::tm struct whereas the regular functions use a + * staticly created struct and return a pointer to that. These wrapper + * functions require the user to create a std::tm struct and send in a + * pointer to it. A pointer to the user created struct will be returned. + * All functions do proper checking of the C function results and throw + * exceptions on error. Therefore the functions will never return NULL. + */ + struct c_time { + public: +#if defined(BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS) + //! requires a pointer to a user created std::tm struct + inline + static std::tm* localtime(const std::time_t* t, std::tm* result) + { + // localtime_r() not in namespace std??? + result = localtime_r(t, result); + if (!result) + boost::throw_exception(std::runtime_error("could not convert calendar time to local time")); + return result; + } + //! requires a pointer to a user created std::tm struct + inline + static std::tm* gmtime(const std::time_t* t, std::tm* result) + { + // gmtime_r() not in namespace std??? + result = gmtime_r(t, result); + if (!result) + boost::throw_exception(std::runtime_error("could not convert calendar time to UTC time")); + return result; + } +#else // BOOST_HAS_THREADS + +#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) +#pragma warning(push) // preserve warning settings +#pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8 +#endif // _MSC_VER >= 1400 + //! requires a pointer to a user created std::tm struct + inline + static std::tm* localtime(const std::time_t* t, std::tm* result) + { + result = std::localtime(t); + if (!result) + boost::throw_exception(std::runtime_error("could not convert calendar time to local time")); + return result; + } + //! requires a pointer to a user created std::tm struct + inline + static std::tm* gmtime(const std::time_t* t, std::tm* result) + { + result = std::gmtime(t); + if (!result) + boost::throw_exception(std::runtime_error("could not convert calendar time to UTC time")); + return result; + } +#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) +#pragma warning(pop) // restore warnings to previous state +#endif // _MSC_VER >= 1400 + +#endif // BOOST_HAS_THREADS + }; +}} // namespaces + +#endif // DATE_TIME_C_TIME_HPP___ diff --git a/ext/boost/date_time/compiler_config.hpp b/ext/boost/date_time/compiler_config.hpp new file mode 100644 index 0000000000..0dc893f9fb --- /dev/null +++ b/ext/boost/date_time/compiler_config.hpp @@ -0,0 +1,171 @@ +#ifndef DATE_TIME_COMPILER_CONFIG_HPP___ +#define DATE_TIME_COMPILER_CONFIG_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <cstdlib> +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +// With boost release 1.33, date_time will be using a different, +// more flexible, IO system. This new system is not compatible with +// old compilers. The original date_time IO system remains for those +// compilers. They must define this macro to use the legacy IO. +// (defined(__BORLANDC__) && (__BORLANDC__ <= 0x0581) ) ) && + #if( BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) \ + || BOOST_WORKAROUND( __GNUC__, < 3) \ + || (BOOST_WORKAROUND( _MSC_VER, <= 1300) ) \ + ) \ + && !defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +# define USE_DATE_TIME_PRE_1_33_FACET_IO +#endif + + +// This file performs some local compiler configurations + +#include <boost/date_time/locale_config.hpp> //set up locale configurations + +//Set up a configuration parameter for platforms that have +//GetTimeOfDay +#if defined(BOOST_HAS_GETTIMEOFDAY) || defined(BOOST_HAS_FTIME) +#define BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK +#endif + +// To Force no default constructors for date & ptime, un-comment following +//#define DATE_TIME_NO_DEFAULT_CONSTRUCTOR + +// Include extensions to date_duration - comment out to remove this feature +#define BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +// these extensions are known to cause problems with gcc295 +#if defined(__GNUC__) && (__GNUC__ < 3) +#undef BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +#endif + +#if (defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) || BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) ) +#define BOOST_DATE_TIME_NO_MEMBER_INIT +#endif + +// include these types before we try to re-define them +#include <boost/cstdint.hpp> + +//Define INT64_C for compilers that don't have it +#if (!defined(INT64_C)) +#define INT64_C(value) int64_t(value) +#endif + + +/* Workaround for Borland iterator error. Error was "Cannot convert 'istream *' to 'wistream *' in function istream_iterator<>::istream_iterator() */ +#if defined(__BORLANDC__) && defined(BOOST_BCB_WITH_RW_LIB) +#define BOOST_DATE_TIME_NO_WISTREAM_ITERATOR +#endif + + +// Borland v5.64 does not have the following in std namespace; v5.5.1 does +#if defined(__BORLANDC__) && defined(BOOST_BCB_WITH_STLPORT) +#include <locale> +namespace std { + using stlport::tolower; + using stlport::ctype; + using stlport::use_facet; +} +#endif + +// workaround for errors associated with output for date classes +// modifications and input streaming for time classes. +// Compilers affected are: +// gcc295, msvc (neither with STLPort), any borland +// +#if (((defined(__GNUC__) && (__GNUC__ < 3)) || \ + (defined(_MSC_VER) && (_MSC_VER < 1300)) ) && \ + !defined(_STLP_OWN_IOSTREAMS) ) || \ + BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) +#define BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS +#endif + +// The macro marks up places where compiler complains for missing return statement or +// uninitialized variables after calling to boost::throw_exception. +// BOOST_UNREACHABLE_RETURN doesn't work since even compilers that support +// unreachable statements detection emit such warnings. +#if defined(_MSC_VER) +// Use special MSVC extension to markup unreachable code +# define BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(x) __assume(false) +#elif !defined(BOOST_NO_UNREACHABLE_RETURN_DETECTION) +// Call to a non-returning function should suppress the warning +# if defined(BOOST_NO_STDC_NAMESPACE) +namespace std { + using ::abort; +} +# endif // defined(BOOST_NO_STDC_NAMESPACE) +# define BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(x) std::abort() +#else +// For other poor compilers the specified expression is compiled. Usually, this would be a return statement. +# define BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(x) x +#endif + +/* The following handles the definition of the necessary macros + * for dll building on Win32 platforms. + * + * For code that will be placed in the date_time .dll, + * it must be properly prefixed with BOOST_DATE_TIME_DECL. + * The corresponding .cpp file must have BOOST_DATE_TIME_SOURCE + * defined before including its header. For examples see: + * greg_month.hpp & greg_month.cpp + * + */ + +#ifdef BOOST_HAS_DECLSPEC // defined in config system + // we need to import/export our code only if the user has specifically + // asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost + // libraries to be dynamically linked, or BOOST_DATE_TIME_DYN_LINK + // if they want just this one to be dynamically liked: +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK) + // export if this is our own source, otherwise import: +# ifdef BOOST_DATE_TIME_SOURCE +# define BOOST_DATE_TIME_DECL __declspec(dllexport) +# else +# define BOOST_DATE_TIME_DECL __declspec(dllimport) +# endif // BOOST_DATE_TIME_SOURCE +# endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC +// +// if BOOST_WHATEVER_DECL isn't defined yet define it now: +#ifndef BOOST_DATE_TIME_DECL +# define BOOST_DATE_TIME_DECL +#endif + +// +// Automatically link to the correct build variant where possible. +// +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_DATE_TIME_NO_LIB) && !defined(BOOST_DATE_TIME_SOURCE) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_date_time +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include <boost/config/auto_link.hpp> +#endif // auto-linking disabled + +#if defined(BOOST_HAS_THREADS) +# if defined(_MSC_VER) || defined(__MWERKS__) || defined(__MINGW32__) || defined(__BORLANDC__) + //no reentrant posix functions (eg: localtime_r) +# elif (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT))) +# define BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS +# endif +#endif + + +#endif diff --git a/ext/boost/date_time/constrained_value.hpp b/ext/boost/date_time/constrained_value.hpp new file mode 100644 index 0000000000..b273dd5aa8 --- /dev/null +++ b/ext/boost/date_time/constrained_value.hpp @@ -0,0 +1,121 @@ +#ifndef CONSTRAINED_VALUE_HPP___ +#define CONSTRAINED_VALUE_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <exception> +#include <stdexcept> +#include <boost/config.hpp> +#include <boost/throw_exception.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_base_of.hpp> + +namespace boost { + +//! Namespace containing constrained_value template and types +namespace CV { + //! Represent a min or max violation type + enum violation_enum {min_violation, max_violation}; + + //! A template to specify a constrained basic value type + /*! This template provides a quick way to generate + * an integer type with a constrained range. The type + * provides for the ability to specify the min, max, and + * and error handling policy. + * + * <b>value policies</b> + * A class that provides the range limits via the min and + * max functions as well as a function on_error that + * determines how errors are handled. A common strategy + * would be to assert or throw and exception. The on_error + * is passed both the current value and the new value that + * is in error. + * + */ + template<class value_policies> + class constrained_value { + public: + typedef typename value_policies::value_type value_type; + // typedef except_type exception_type; + constrained_value(value_type value) : value_((min)()) + { + assign(value); + } + constrained_value& operator=(value_type v) + { + assign(v); + return *this; + } + //! Return the max allowed value (traits method) + static value_type max BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::max)();} + //! Return the min allowed value (traits method) + static value_type min BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::min)();} + //! Coerce into the representation type + operator value_type() const {return value_;} + protected: + value_type value_; + private: + void assign(value_type value) + { + //adding 1 below gets rid of a compiler warning which occurs when the + //min_value is 0 and the type is unsigned.... + if (value+1 < (min)()+1) { + value_policies::on_error(value_, value, min_violation); + return; + } + if (value > (max)()) { + value_policies::on_error(value_, value, max_violation); + return; + } + value_ = value; + } +}; + + //! Template to shortcut the constrained_value policy creation process + template<typename rep_type, rep_type min_value, + rep_type max_value, class exception_type> + class simple_exception_policy + { + struct exception_wrapper : public exception_type + { + // In order to support throw_exception mechanism in the BOOST_NO_EXCEPTIONS mode, + // we'll have to provide a way to acquire std::exception from the exception being thrown. + // However, we cannot derive from it, since it would make it interceptable by this class, + // which might not be what the user wanted. + operator std::out_of_range () const + { + // TODO: Make the message more descriptive by using arguments to on_error + return std::out_of_range("constrained value boundary has been violated"); + } + }; + + typedef typename mpl::if_< + is_base_of< std::exception, exception_type >, + exception_type, + exception_wrapper + >::type actual_exception_type; + + public: + typedef rep_type value_type; + static rep_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return min_value; } + static rep_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return max_value; } + static void on_error(rep_type, rep_type, violation_enum) + { + boost::throw_exception(actual_exception_type()); + } + }; + + + +} } //namespace CV + + + + +#endif diff --git a/ext/boost/date_time/date.hpp b/ext/boost/date_time/date.hpp new file mode 100644 index 0000000000..beab047700 --- /dev/null +++ b/ext/boost/date_time/date.hpp @@ -0,0 +1,197 @@ +#ifndef DATE_TIME_DATE_HPP___ +#define DATE_TIME_DATE_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/year_month_day.hpp" +#include "boost/date_time/special_defs.hpp" +#include "boost/operators.hpp" + +namespace boost { +namespace date_time { + + //!Representation of timepoint at the one day level resolution. + /*! + The date template represents an interface shell for a date class + that is based on a year-month-day system such as the gregorian + or iso systems. It provides basic operations to enable calculation + and comparisons. + + <b>Theory</b> + + This date representation fundamentally departs from the C tm struct + approach. The goal for this type is to provide efficient date + operations (add, subtract) and storage (minimize space to represent) + in a concrete class. Thus, the date uses a count internally to + represent a particular date. The calendar parameter defines + the policies for converting the the year-month-day and internal + counted form here. Applications that need to perform heavy + formatting of the same date repeatedly will perform better + by using the year-month-day representation. + + Internally the date uses a day number to represent the date. + This is a monotonic time representation. This representation + allows for fast comparison as well as simplifying + the creation of writing numeric operations. Essentially, the + internal day number is like adjusted julian day. The adjustment + is determined by the Epoch date which is represented as day 1 of + the calendar. Day 0 is reserved for negative infinity so that + any actual date is automatically greater than negative infinity. + When a date is constructed from a date or formatted for output, + the appropriate conversions are applied to create the year, month, + day representations. + */ + + + template<class T, class calendar, class duration_type_> + class date : private + boost::less_than_comparable<T + , boost::equality_comparable<T + > > + { + public: + typedef T date_type; + typedef calendar calendar_type; + typedef typename calendar::date_traits_type traits_type; + typedef duration_type_ duration_type; + typedef typename calendar::year_type year_type; + typedef typename calendar::month_type month_type; + typedef typename calendar::day_type day_type; + typedef typename calendar::ymd_type ymd_type; + typedef typename calendar::date_rep_type date_rep_type; + typedef typename calendar::date_int_type date_int_type; + typedef typename calendar::day_of_week_type day_of_week_type; + date(year_type y, month_type m, day_type d) + : days_(calendar::day_number(ymd_type(y, m, d))) + {} + date(const ymd_type& ymd) + : days_(calendar::day_number(ymd)) + {} + //let the compiler write copy, assignment, and destructor + year_type year() const + { + ymd_type ymd = calendar::from_day_number(days_); + return ymd.year; + } + month_type month() const + { + ymd_type ymd = calendar::from_day_number(days_); + return ymd.month; + } + day_type day() const + { + ymd_type ymd = calendar::from_day_number(days_); + return ymd.day; + } + day_of_week_type day_of_week() const + { + ymd_type ymd = calendar::from_day_number(days_); + return calendar::day_of_week(ymd); + } + ymd_type year_month_day() const + { + return calendar::from_day_number(days_); + } + bool operator<(const date_type& rhs) const + { + return days_ < rhs.days_; + } + bool operator==(const date_type& rhs) const + { + return days_ == rhs.days_; + } + //! check to see if date is a special value + bool is_special()const + { + return(is_not_a_date() || is_infinity()); + } + //! check to see if date is not a value + bool is_not_a_date() const + { + return traits_type::is_not_a_number(days_); + } + //! check to see if date is one of the infinity values + bool is_infinity() const + { + return traits_type::is_inf(days_); + } + //! check to see if date is greater than all possible dates + bool is_pos_infinity() const + { + return traits_type::is_pos_inf(days_); + } + //! check to see if date is greater than all possible dates + bool is_neg_infinity() const + { + return traits_type::is_neg_inf(days_); + } + //! return as a special value or a not_special if a normal date + special_values as_special() const + { + return traits_type::to_special(days_); + } + duration_type operator-(const date_type& d) const + { + date_rep_type val = date_rep_type(days_) - date_rep_type(d.days_); + return duration_type(val.as_number()); + } + + date_type operator-(const duration_type& dd) const + { + if(dd.is_special()) + { + return date_type(date_rep_type(days_) - dd.get_rep()); + } + return date_type(date_rep_type(days_) - dd.days()); + } + date_type operator-=(const duration_type& dd) + { + *this = *this - dd; + return date_type(days_); + } + date_rep_type day_count() const + { + return days_; + }; + //allow internal access from operators + date_type operator+(const duration_type& dd) const + { + if(dd.is_special()) + { + return date_type(date_rep_type(days_) + dd.get_rep()); + } + return date_type(date_rep_type(days_) + dd.days()); + } + date_type operator+=(const duration_type& dd) + { + *this = *this + dd; + return date_type(days_); + } + + //see reference + protected: + /*! This is a private constructor which allows for the creation of new + dates. It is not exposed to users since that would require class + users to understand the inner workings of the date class. + */ + explicit date(date_int_type days) : days_(days) {}; + explicit date(date_rep_type days) : days_(days.as_number()) {}; + date_int_type days_; + + }; + + + + +} } // namespace date_time + + + + +#endif diff --git a/ext/boost/date_time/date_clock_device.hpp b/ext/boost/date_time/date_clock_device.hpp new file mode 100644 index 0000000000..6ccb26e254 --- /dev/null +++ b/ext/boost/date_time/date_clock_device.hpp @@ -0,0 +1,77 @@ +#ifndef DATE_CLOCK_DEVICE_HPP___ +#define DATE_CLOCK_DEVICE_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/c_time.hpp" + + +namespace boost { +namespace date_time { + + //! A clock providing day level services based on C time_t capabilities + /*! This clock uses Posix interfaces as its implementation and hence + * uses the timezone settings of the operating system. Incorrect + * user settings will result in incorrect results for the calls + * to local_day. + */ + template<class date_type> + class day_clock + { + public: + typedef typename date_type::ymd_type ymd_type; + //! Get the local day as a date type + static date_type local_day() + { + return date_type(local_day_ymd()); + } + //! Get the local day as a ymd_type + static typename date_type::ymd_type local_day_ymd() + { + ::std::tm result; + ::std::tm* curr = get_local_time(result); + return ymd_type(curr->tm_year + 1900, + curr->tm_mon + 1, + curr->tm_mday); + } + //! Get the current day in universal date as a ymd_type + static typename date_type::ymd_type universal_day_ymd() + { + ::std::tm result; + ::std::tm* curr = get_universal_time(result); + return ymd_type(curr->tm_year + 1900, + curr->tm_mon + 1, + curr->tm_mday); + } + //! Get the UTC day as a date type + static date_type universal_day() + { + return date_type(universal_day_ymd()); + } + + private: + static ::std::tm* get_local_time(std::tm& result) + { + ::std::time_t t; + ::std::time(&t); + return c_time::localtime(&t, &result); + } + static ::std::tm* get_universal_time(std::tm& result) + { + ::std::time_t t; + ::std::time(&t); + return c_time::gmtime(&t, &result); + } + + }; + +} } //namespace date_time + + +#endif diff --git a/ext/boost/date_time/date_defs.hpp b/ext/boost/date_time/date_defs.hpp new file mode 100644 index 0000000000..bc25b56c0d --- /dev/null +++ b/ext/boost/date_time/date_defs.hpp @@ -0,0 +1,26 @@ +#ifndef DATE_TIME_DATE_DEFS_HPP +#define DATE_TIME_DATE_DEFS_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + + //! An enumeration of weekday names + enum weekdays {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}; + + //! Simple enum to allow for nice programming with Jan, Feb, etc + enum months_of_year {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,NotAMonth,NumMonths}; + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/date_duration.hpp b/ext/boost/date_time/date_duration.hpp new file mode 100644 index 0000000000..3871aac0ce --- /dev/null +++ b/ext/boost/date_time/date_duration.hpp @@ -0,0 +1,146 @@ +#ifndef DATE_TIME_DATE_DURATION__ +#define DATE_TIME_DATE_DURATION__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +#include <boost/operators.hpp> +#include <boost/date_time/special_defs.hpp> + +namespace boost { +namespace date_time { + + + //! Duration type with date level resolution + template<class duration_rep_traits> + class date_duration : private + boost::less_than_comparable1< date_duration< duration_rep_traits > + , boost::equality_comparable1< date_duration< duration_rep_traits > + , boost::addable1< date_duration< duration_rep_traits > + , boost::subtractable1< date_duration< duration_rep_traits > + , boost::dividable2< date_duration< duration_rep_traits >, int + > > > > > + { + public: + typedef typename duration_rep_traits::int_type duration_rep_type; + typedef typename duration_rep_traits::impl_type duration_rep; + + //! Construct from a day count + explicit date_duration(duration_rep day_count) : days_(day_count) {}; + + /*! construct from special_values - only works when + * instantiated with duration_traits_adapted */ + date_duration(special_values sv) : + days_(duration_rep::from_special(sv)) + {} + + // copy constructor required for addable<> & subtractable<> + //! Construct from another date_duration (Copy Constructor) + date_duration(const date_duration<duration_rep_traits>& other) : + days_(other.days_) + {} + + //! returns days_ as it's instantiated type - used for streaming + duration_rep get_rep()const + { + return days_; + } + bool is_special()const + { + return days_.is_special(); + } + //! returns days as value, not object. + duration_rep_type days() const + { + return duration_rep_traits::as_number(days_); + } + //! Returns the smallest duration -- used by to calculate 'end' + static date_duration unit() + { + return date_duration<duration_rep_traits>(1); + } + //! Equality + bool operator==(const date_duration& rhs) const + { + return days_ == rhs.days_; + } + //! Less + bool operator<(const date_duration& rhs) const + { + return days_ < rhs.days_; + } + + /* For shortcut operators (+=, -=, etc) simply using + * "days_ += days_" may not work. If instantiated with + * an int_adapter, shortcut operators are not present, + * so this will not compile */ + + //! Subtract another duration -- result is signed + date_duration& operator-=(const date_duration& rhs) + { + //days_ -= rhs.days_; + days_ = days_ - rhs.days_; + return *this; + } + //! Add a duration -- result is signed + date_duration& operator+=(const date_duration& rhs) + { + days_ = days_ + rhs.days_; + return *this; + } + + //! unary- Allows for dd = -date_duration(2); -> dd == -2 + date_duration operator-() const + { + return date_duration<duration_rep_traits>(get_rep() * (-1)); + } + //! Division operations on a duration with an integer. + date_duration& operator/=(int divisor) + { + days_ = days_ / divisor; + return *this; + } + + //! return sign information + bool is_negative() const + { + return days_ < 0; + } + + private: + duration_rep days_; + }; + + + /*! Struct for instantiating date_duration with <b>NO</b> special values + * functionality. Allows for transparent implementation of either + * date_duration<long> or date_duration<int_adapter<long> > */ + struct duration_traits_long + { + typedef long int_type; + typedef long impl_type; + static int_type as_number(impl_type i) { return i; }; + }; + + /*! Struct for instantiating date_duration <b>WITH</b> special values + * functionality. Allows for transparent implementation of either + * date_duration<long> or date_duration<int_adapter<long> > */ + struct duration_traits_adapted + { + typedef long int_type; + typedef boost::date_time::int_adapter<long> impl_type; + static int_type as_number(impl_type i) { return i.as_number(); }; + }; + + +} } //namspace date_time + + +#endif + diff --git a/ext/boost/date_time/date_duration_types.hpp b/ext/boost/date_time/date_duration_types.hpp new file mode 100644 index 0000000000..1512c0ef20 --- /dev/null +++ b/ext/boost/date_time/date_duration_types.hpp @@ -0,0 +1,269 @@ +#ifndef DATE_DURATION_TYPES_HPP___ +#define DATE_DURATION_TYPES_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include <boost/date_time/int_adapter.hpp> +#include <boost/date_time/special_defs.hpp> +#include <boost/date_time/date_duration.hpp> + +namespace boost { +namespace date_time { + + + //! Additional duration type that represents a number of n*7 days + template <class duration_config> + class weeks_duration : public date_duration<duration_config> { + public: + weeks_duration(typename duration_config::impl_type w) + : date_duration<duration_config>(w * 7) {} + weeks_duration(special_values sv) + : date_duration<duration_config>(sv) {} + }; + + // predeclare + template<class t> + class years_duration; + + //! additional duration type that represents a logical month + /*! A logical month enables things like: "date(2002,Mar,2) + months(2) -> + * 2002-May2". If the date is a last day-of-the-month, the result will + * also be a last-day-of-the-month. + */ + template<class base_config> + class months_duration + { + private: + typedef typename base_config::int_rep int_rep; + typedef typename int_rep::int_type int_type; + typedef typename base_config::date_type date_type; + typedef typename date_type::duration_type duration_type; + typedef typename base_config::month_adjustor_type month_adjustor_type; + typedef months_duration<base_config> months_type; + typedef years_duration<base_config> years_type; + public: + months_duration(int_rep num) : _m(num) {} + months_duration(special_values sv) : _m(sv) + { + _m = int_rep::from_special(sv); + } + int_rep number_of_months() const { return _m; } + //! returns a negative duration + duration_type get_neg_offset(const date_type& d) const + { + month_adjustor_type m_adj(_m.as_number()); + return duration_type(m_adj.get_neg_offset(d)); + } + duration_type get_offset(const date_type& d) const + { + month_adjustor_type m_adj(_m.as_number()); + return duration_type(m_adj.get_offset(d)); + } + bool operator==(const months_type& rhs) const + { + return(_m == rhs._m); + } + bool operator!=(const months_type& rhs) const + { + return(_m != rhs._m); + } + months_type operator+(const months_type& rhs)const + { + return months_type(_m + rhs._m); + } + months_type& operator+=(const months_type& rhs) + { + _m = _m + rhs._m; + return *this; + } + months_type operator-(const months_type& rhs)const + { + return months_type(_m - rhs._m); + } + months_type& operator-=(const months_type& rhs) + { + _m = _m - rhs._m; + return *this; + } + months_type operator*(const int_type rhs)const + { + return months_type(_m * rhs); + } + months_type& operator*=(const int_type rhs) + { + _m = _m * rhs; + return *this; + } + months_type operator/(const int_type rhs)const + { + return months_type(_m / rhs); + } + months_type& operator/=(const int_type rhs) + { + _m = _m / rhs; + return *this; + } + months_type operator+(const years_type& y)const + { + return months_type(y.number_of_years() * 12 + _m); + } + months_type& operator+=(const years_type& y) + { + _m = y.number_of_years() * 12 + _m; + return *this; + } + months_type operator-(const years_type& y) const + { + return months_type(_m - y.number_of_years() * 12); + } + months_type& operator-=(const years_type& y) + { + _m = _m - y.number_of_years() * 12; + return *this; + } + + // + friend date_type operator+(const date_type& d, const months_type& m) + { + return d + m.get_offset(d); + } + friend date_type operator+=(date_type& d, const months_type& m) + { + return d += m.get_offset(d); + } + friend date_type operator-(const date_type& d, const months_type& m) + { + // get_neg_offset returns a negative duration, so we add + return d + m.get_neg_offset(d); + } + friend date_type operator-=(date_type& d, const months_type& m) + { + // get_neg_offset returns a negative duration, so we add + return d += m.get_neg_offset(d); + } + + private: + int_rep _m; + }; + + //! additional duration type that represents a logical year + /*! A logical year enables things like: "date(2002,Mar,2) + years(2) -> + * 2004-Mar-2". If the date is a last day-of-the-month, the result will + * also be a last-day-of-the-month (ie date(2001-Feb-28) + years(3) -> + * 2004-Feb-29). + */ + template<class base_config> + class years_duration + { + private: + typedef typename base_config::int_rep int_rep; + typedef typename int_rep::int_type int_type; + typedef typename base_config::date_type date_type; + typedef typename date_type::duration_type duration_type; + typedef typename base_config::month_adjustor_type month_adjustor_type; + typedef years_duration<base_config> years_type; + typedef months_duration<base_config> months_type; + public: + years_duration(int_rep num) : _y(num) {} + years_duration(special_values sv) : _y(sv) + { + _y = int_rep::from_special(sv); + } + int_rep number_of_years() const { return _y; } + //! returns a negative duration + duration_type get_neg_offset(const date_type& d) const + { + month_adjustor_type m_adj(_y.as_number() * 12); + return duration_type(m_adj.get_neg_offset(d)); + } + duration_type get_offset(const date_type& d) const + { + month_adjustor_type m_adj(_y.as_number() * 12); + return duration_type(m_adj.get_offset(d)); + } + bool operator==(const years_type& rhs) const + { + return(_y == rhs._y); + } + bool operator!=(const years_type& rhs) const + { + return(_y != rhs._y); + } + years_type operator+(const years_type& rhs)const + { + return years_type(_y + rhs._y); + } + years_type& operator+=(const years_type& rhs) + { + _y = _y + rhs._y; + return *this; + } + years_type operator-(const years_type& rhs)const + { + return years_type(_y - rhs._y); + } + years_type& operator-=(const years_type& rhs) + { + _y = _y - rhs._y; + return *this; + } + years_type operator*(const int_type rhs)const + { + return years_type(_y * rhs); + } + years_type& operator*=(const int_type rhs) + { + _y = _y * rhs; + return *this; + } + years_type operator/(const int_type rhs)const + { + return years_type(_y / rhs); + } + years_type& operator/=(const int_type rhs) + { + _y = _y / rhs; + return *this; + } + months_type operator+(const months_type& m) const + { + return(months_type(_y * 12 + m.number_of_months())); + } + months_type operator-(const months_type& m) const + { + return(months_type(_y * 12 - m.number_of_months())); + } + + // + friend date_type operator+(const date_type& d, const years_type& y) + { + return d + y.get_offset(d); + } + friend date_type operator+=(date_type& d, const years_type& y) + { + return d += y.get_offset(d); + } + friend date_type operator-(const date_type& d, const years_type& y) + { + // get_neg_offset returns a negative duration, so we add + return d + y.get_neg_offset(d); + } + friend date_type operator-=(date_type& d, const years_type& y) + { + // get_neg_offset returns a negative duration, so we add + return d += y.get_neg_offset(d); + } + + private: + int_rep _y; + }; + +}} // namespace boost::date_time + +#endif // DATE_DURATION_TYPES_HPP___ diff --git a/ext/boost/date_time/date_facet.hpp b/ext/boost/date_time/date_facet.hpp new file mode 100644 index 0000000000..3eda4c7d09 --- /dev/null +++ b/ext/boost/date_time/date_facet.hpp @@ -0,0 +1,764 @@ +#ifndef _DATE_TIME_DATE_FACET__HPP___ +#define _DATE_TIME_DATE_FACET__HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Martin Andrian, Jeff Garland, Bart Garst + * $Date: 2009-06-04 07:40:18 -0400 (Thu, 04 Jun 2009) $ + */ + +#include <locale> +#include <string> +#include <vector> +#include <iterator> // ostreambuf_iterator +#include <boost/throw_exception.hpp> +#include <boost/algorithm/string/replace.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/period.hpp> +#include <boost/date_time/special_defs.hpp> +#include <boost/date_time/special_values_formatter.hpp> +#include <boost/date_time/period_formatter.hpp> +#include <boost/date_time/period_parser.hpp> +#include <boost/date_time/date_generator_formatter.hpp> +#include <boost/date_time/date_generator_parser.hpp> +#include <boost/date_time/format_date_parser.hpp> + +namespace boost { namespace date_time { + + + /*! Class that provides format based I/O facet for date types. + * + * This class allows the formatting of dates by using format string. + * Format strings are: + * + * - %A => long_weekday_format - Full name Ex: Tuesday + * - %a => short_weekday_format - Three letter abbreviation Ex: Tue + * - %B => long_month_format - Full name Ex: October + * - %b => short_month_format - Three letter abbreviation Ex: Oct + * - %x => standard_format_specifier - defined by the locale + * - %Y-%b-%d => default_date_format - YYYY-Mon-dd + * + * Default month format == %b + * Default weekday format == %a + */ + template <class date_type, + class CharT, + class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > + class date_facet : public std::locale::facet { + public: + typedef typename date_type::duration_type duration_type; + // greg_weekday is gregorian_calendar::day_of_week_type + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::month_type month_type; + typedef boost::date_time::period<date_type,duration_type> period_type; + typedef std::basic_string<CharT> string_type; + typedef CharT char_type; + typedef boost::date_time::period_formatter<CharT> period_formatter_type; + typedef boost::date_time::special_values_formatter<CharT> special_values_formatter_type; + typedef std::vector<std::basic_string<CharT> > input_collection_type; + // used for the output of the date_generators + typedef date_generator_formatter<date_type, CharT> date_gen_formatter_type; + typedef partial_date<date_type> partial_date_type; + typedef nth_kday_of_month<date_type> nth_kday_type; + typedef first_kday_of_month<date_type> first_kday_type; + typedef last_kday_of_month<date_type> last_kday_type; + typedef first_kday_after<date_type> kday_after_type; + typedef first_kday_before<date_type> kday_before_type; + static const char_type long_weekday_format[3]; + static const char_type short_weekday_format[3]; + static const char_type long_month_format[3]; + static const char_type short_month_format[3]; + static const char_type default_period_separator[4]; + static const char_type standard_format_specifier[3]; + static const char_type iso_format_specifier[7]; + static const char_type iso_format_extended_specifier[9]; + static const char_type default_date_format[9]; // YYYY-Mon-DD + static std::locale::id id; + +#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) + std::locale::id& __get_id (void) const { return id; } +#endif + + explicit date_facet(::size_t a_ref = 0) + : std::locale::facet(a_ref), + //m_format(standard_format_specifier) + m_format(default_date_format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format) + {} + + explicit date_facet(const char_type* format_str, + const input_collection_type& short_names, + ::size_t ref_count = 0) + : std::locale::facet(ref_count), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_month_short_names(short_names) + {} + + + explicit date_facet(const char_type* format_str, + period_formatter_type per_formatter = period_formatter_type(), + special_values_formatter_type sv_formatter = special_values_formatter_type(), + date_gen_formatter_type dg_formatter = date_gen_formatter_type(), + ::size_t ref_count = 0) + : std::locale::facet(ref_count), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_period_formatter(per_formatter), + m_date_gen_formatter(dg_formatter), + m_special_values_formatter(sv_formatter) + {} + void format(const char_type* const format_str) { + m_format = format_str; + } + virtual void set_iso_format() + { + m_format = iso_format_specifier; + } + virtual void set_iso_extended_format() + { + m_format = iso_format_extended_specifier; + } + void month_format(const char_type* const format_str) { + m_month_format = format_str; + } + void weekday_format(const char_type* const format_str) { + m_weekday_format = format_str; + } + + void period_formatter(period_formatter_type per_formatter) { + m_period_formatter= per_formatter; + } + void special_values_formatter(const special_values_formatter_type& svf) + { + m_special_values_formatter = svf; + } + void short_weekday_names(const input_collection_type& short_names) + { + m_weekday_short_names = short_names; + } + void long_weekday_names(const input_collection_type& long_names) + { + m_weekday_long_names = long_names; + } + + void short_month_names(const input_collection_type& short_names) + { + m_month_short_names = short_names; + } + + void long_month_names(const input_collection_type& long_names) + { + m_month_long_names = long_names; + } + + void date_gen_phrase_strings(const input_collection_type& new_strings, + typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first) + { + m_date_gen_formatter.elements(new_strings, beg_pos); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const date_type& d) const + { + if (d.is_special()) { + return do_put_special(next, a_ios, fill_char, d.as_special()); + } + //The following line of code required the date to support a to_tm function + return do_put_tm(next, a_ios, fill_char, to_tm(d), m_format); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const duration_type& dd) const + { + if (dd.is_special()) { + return do_put_special(next, a_ios, fill_char, dd.get_rep().as_special()); + } + + typedef std::num_put<CharT, OutItrT> num_put; + if (std::has_facet<num_put>(a_ios.getloc())) { + return std::use_facet<num_put>(a_ios.getloc()).put(next, a_ios, fill_char, dd.get_rep().as_number()); + } + else { + num_put* f = new num_put(); + std::locale l = std::locale(a_ios.getloc(), f); + a_ios.imbue(l); + return f->put(next, a_ios, fill_char, dd.get_rep().as_number()); + } + + } + + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const month_type& m) const + { + //if (d.is_special()) { + // return do_put_special(next, a_ios, fill_char, d.as_special()); + //} + //The following line of code required the date to support a to_tm function + std::tm dtm = {}; + dtm.tm_mon = m - 1; + return do_put_tm(next, a_ios, fill_char, dtm, m_month_format); + } + + //! puts the day of month + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const day_type& day) const + { + std::tm dtm = {}; + dtm.tm_mday = day.as_number(); + char_type tmp[3] = {'%','d'}; + string_type temp_format(tmp); + return do_put_tm(next, a_ios, fill_char, dtm, temp_format); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const day_of_week_type& dow) const + { + //if (d.is_special()) { + // return do_put_special(next, a_ios, fill_char, d.as_special()); + //} + //The following line of code required the date to support a to_tm function + std::tm dtm = {}; + dtm.tm_wday = dow; + return do_put_tm(next, a_ios, fill_char, dtm, m_weekday_format); + } + + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const period_type& p) const + { + return m_period_formatter.put_period(next, a_ios, fill_char, p, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const partial_date_type& pd) const + { + return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const nth_kday_type& nkd) const + { + return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const first_kday_type& fkd) const + { + return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const last_kday_type& lkd) const + { + return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const kday_before_type& fkb) const + { + return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const kday_after_type& fka) const + { + return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this); + } + + protected: + virtual OutItrT do_put_special(OutItrT next, + std::ios_base& /*a_ios*/, + char_type /*fill_char*/, + const boost::date_time::special_values sv) const + { + m_special_values_formatter.put_special(next, sv); + return next; + } + virtual OutItrT do_put_tm(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const tm& tm_value, + string_type a_format) const + { + // update format string with custom names + if (m_weekday_long_names.size()) { + boost::algorithm::replace_all(a_format, + long_weekday_format, + m_weekday_long_names[tm_value.tm_wday]); + } + if (m_weekday_short_names.size()) { + boost::algorithm::replace_all(a_format, + short_weekday_format, + m_weekday_short_names[tm_value.tm_wday]); + + } + if (m_month_long_names.size()) { + boost::algorithm::replace_all(a_format, + long_month_format, + m_month_long_names[tm_value.tm_mon]); + } + if (m_month_short_names.size()) { + boost::algorithm::replace_all(a_format, + short_month_format, + m_month_short_names[tm_value.tm_mon]); + } + // use time_put facet to create final string + const char_type* p_format = a_format.c_str(); + return std::use_facet<std::time_put<CharT> >(a_ios.getloc()).put(next, a_ios, + fill_char, + &tm_value, + p_format, + p_format + a_format.size()); + } + protected: + string_type m_format; + string_type m_month_format; + string_type m_weekday_format; + period_formatter_type m_period_formatter; + date_gen_formatter_type m_date_gen_formatter; + special_values_formatter_type m_special_values_formatter; + input_collection_type m_month_short_names; + input_collection_type m_month_long_names; + input_collection_type m_weekday_short_names; + input_collection_type m_weekday_long_names; + private: + }; + + template <class date_type, class CharT, class OutItrT> + std::locale::id date_facet<date_type, CharT, OutItrT>::id; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '}; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] = + {'%', 'x' }; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] = + {'%', 'Y', '%', 'm', '%', 'd' }; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; + + template <class date_type, class CharT, class OutItrT> + const typename date_facet<date_type, CharT, OutItrT>::char_type + date_facet<date_type, CharT, OutItrT>::default_date_format[9] = + {'%','Y','-','%','b','-','%','d'}; + + + + //! Input facet + template <class date_type, + class CharT, + class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > > + class date_input_facet : public std::locale::facet { + public: + typedef typename date_type::duration_type duration_type; + // greg_weekday is gregorian_calendar::day_of_week_type + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef boost::date_time::period<date_type,duration_type> period_type; + typedef std::basic_string<CharT> string_type; + typedef CharT char_type; + typedef boost::date_time::period_parser<date_type, CharT> period_parser_type; + typedef boost::date_time::special_values_parser<date_type,CharT> special_values_parser_type; + typedef std::vector<std::basic_string<CharT> > input_collection_type; + typedef format_date_parser<date_type, CharT> format_date_parser_type; + // date_generators stuff goes here + typedef date_generator_parser<date_type, CharT> date_gen_parser_type; + typedef partial_date<date_type> partial_date_type; + typedef nth_kday_of_month<date_type> nth_kday_type; + typedef first_kday_of_month<date_type> first_kday_type; + typedef last_kday_of_month<date_type> last_kday_type; + typedef first_kday_after<date_type> kday_after_type; + typedef first_kday_before<date_type> kday_before_type; + + static const char_type long_weekday_format[3]; + static const char_type short_weekday_format[3]; + static const char_type long_month_format[3]; + static const char_type short_month_format[3]; + static const char_type four_digit_year_format[3]; + static const char_type two_digit_year_format[3]; + static const char_type default_period_separator[4]; + static const char_type standard_format_specifier[3]; + static const char_type iso_format_specifier[7]; + static const char_type iso_format_extended_specifier[9]; + static const char_type default_date_format[9]; // YYYY-Mon-DD + static std::locale::id id; + + explicit date_input_facet(::size_t a_ref = 0) + : std::locale::facet(a_ref), + m_format(default_date_format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_year_format(four_digit_year_format), + m_parser(m_format, std::locale::classic()) + // default period_parser & special_values_parser used + {} + + explicit date_input_facet(const string_type& format_str, + ::size_t a_ref = 0) + : std::locale::facet(a_ref), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_year_format(four_digit_year_format), + m_parser(m_format, std::locale::classic()) + // default period_parser & special_values_parser used + {} + + explicit date_input_facet(const string_type& format_str, + const format_date_parser_type& date_parser, + const special_values_parser_type& sv_parser, + const period_parser_type& per_parser, + const date_gen_parser_type& date_gen_parser, + ::size_t ref_count = 0) + : std::locale::facet(ref_count), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_year_format(four_digit_year_format), + m_parser(date_parser), + m_date_gen_parser(date_gen_parser), + m_period_parser(per_parser), + m_sv_parser(sv_parser) + {} + + + void format(const char_type* const format_str) { + m_format = format_str; + } + virtual void set_iso_format() + { + m_format = iso_format_specifier; + } + virtual void set_iso_extended_format() + { + m_format = iso_format_extended_specifier; + } + void month_format(const char_type* const format_str) { + m_month_format = format_str; + } + void weekday_format(const char_type* const format_str) { + m_weekday_format = format_str; + } + void year_format(const char_type* const format_str) { + m_year_format = format_str; + } + + void period_parser(period_parser_type per_parser) { + m_period_parser = per_parser; + } + void short_weekday_names(const input_collection_type& weekday_names) + { + m_parser.short_weekday_names(weekday_names); + } + void long_weekday_names(const input_collection_type& weekday_names) + { + m_parser.long_weekday_names(weekday_names); + } + + void short_month_names(const input_collection_type& month_names) + { + m_parser.short_month_names(month_names); + } + + void long_month_names(const input_collection_type& month_names) + { + m_parser.long_month_names(month_names); + } + + void date_gen_element_strings(const input_collection_type& col) + { + m_date_gen_parser.element_strings(col); + } + void date_gen_element_strings(const string_type& first, + const string_type& second, + const string_type& third, + const string_type& fourth, + const string_type& fifth, + const string_type& last, + const string_type& before, + const string_type& after, + const string_type& of) + + { + m_date_gen_parser.element_strings(first,second,third,fourth,fifth,last,before,after,of); + } + + void special_values_parser(special_values_parser_type sv_parser) + { + m_sv_parser = sv_parser; + } + + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + date_type& d) const + { + d = m_parser.parse_date(from, to, m_format, m_sv_parser); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + month_type& m) const + { + m = m_parser.parse_month(from, to, m_month_format); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + day_of_week_type& wd) const + { + wd = m_parser.parse_weekday(from, to, m_weekday_format); + return from; + } + //! Expects 1 or 2 digit day range: 1-31 + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + day_type& d) const + { + d = m_parser.parse_var_day_of_month(from, to); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + year_type& y) const + { + y = m_parser.parse_year(from, to, m_year_format); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + duration_type& dd) const + { + // skip leading whitespace + while(std::isspace(*from) && from != to) { ++from; } + + /* num_get.get() will always consume the first character if it + * is a sign indicator (+/-). Special value strings may begin + * with one of these signs so we'll need a copy of it + * in case num_get.get() fails. */ + char_type c = '\0'; + // TODO Are these characters somewhere in the locale? + if(*from == '-' || *from == '+') { + c = *from; + } + typedef std::num_get<CharT, InItrT> num_get; + typename duration_type::duration_rep_type val = 0; + std::ios_base::iostate err = std::ios_base::goodbit; + + if (std::has_facet<num_get>(a_ios.getloc())) { + from = std::use_facet<num_get>(a_ios.getloc()).get(from, to, a_ios, err, val); + } + else { + num_get* ng = new num_get(); + std::locale l = std::locale(a_ios.getloc(), ng); + a_ios.imbue(l); + from = ng->get(from, to, a_ios, err, val); + } + if(err & std::ios_base::failbit){ + typedef typename special_values_parser_type::match_results match_results; + match_results mr; + if(c == '-' || c == '+') { // was the first character consumed? + mr.cache += c; + } + m_sv_parser.match(from, to, mr); + if(mr.current_match == match_results::PARSE_ERROR) { + boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'")); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return from); // should never reach + } + dd = duration_type(static_cast<special_values>(mr.current_match)); + } + else { + dd = duration_type(val); + } + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + period_type& p) const + { + p = m_period_parser.get_period(from, to, a_ios, p, duration_type::unit(), *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + nth_kday_type& nkd) const + { + nkd = m_date_gen_parser.get_nth_kday_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + partial_date_type& pd) const + { + + pd = m_date_gen_parser.get_partial_date_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + first_kday_type& fkd) const + { + fkd = m_date_gen_parser.get_first_kday_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + last_kday_type& lkd) const + { + lkd = m_date_gen_parser.get_last_kday_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + kday_before_type& fkb) const + { + fkb = m_date_gen_parser.get_kday_before_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + kday_after_type& fka) const + { + fka = m_date_gen_parser.get_kday_after_type(from, to, a_ios, *this); + return from; + } + + protected: + string_type m_format; + string_type m_month_format; + string_type m_weekday_format; + string_type m_year_format; + format_date_parser_type m_parser; + date_gen_parser_type m_date_gen_parser; + period_parser_type m_period_parser; + special_values_parser_type m_sv_parser; + private: + }; + + + template <class date_type, class CharT, class OutItrT> + std::locale::id date_input_facet<date_type, CharT, OutItrT>::id; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::four_digit_year_format[3] = {'%','Y'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::two_digit_year_format[3] = {'%','y'}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '}; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] = + {'%', 'x' }; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] = + {'%', 'Y', '%', 'm', '%', 'd' }; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; + + template <class date_type, class CharT, class OutItrT> + const typename date_input_facet<date_type, CharT, OutItrT>::char_type + date_input_facet<date_type, CharT, OutItrT>::default_date_format[9] = + {'%','Y','-','%','b','-','%','d'}; + +} } // namespaces + + +#endif diff --git a/ext/boost/date_time/date_format_simple.hpp b/ext/boost/date_time/date_format_simple.hpp new file mode 100644 index 0000000000..be21ce4a57 --- /dev/null +++ b/ext/boost/date_time/date_format_simple.hpp @@ -0,0 +1,159 @@ +#ifndef DATE_TIME_SIMPLE_FORMAT_HPP___ +#define DATE_TIME_SIMPLE_FORMAT_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/parse_format_base.hpp" + +namespace boost { +namespace date_time { + +//! Class to provide simple basic formatting rules +template<class charT> +class simple_format { +public: + + //! String used printed is date is invalid + static const charT* not_a_date() + { + return "not-a-date-time"; + } + //! String used to for positive infinity value + static const charT* pos_infinity() + { + return "+infinity"; + } + //! String used to for positive infinity value + static const charT* neg_infinity() + { + return "-infinity"; + } + //! Describe month format + static month_format_spec month_format() + { + return month_as_short_string; + } + static ymd_order_spec date_order() + { + return ymd_order_iso; //YYYY-MM-DD + } + //! This format uses '-' to separate date elements + static bool has_date_sep_chars() + { + return true; + } + //! Char to sep? + static charT year_sep_char() + { + return '-'; + } + //! char between year-month + static charT month_sep_char() + { + return '-'; + } + //! Char to separate month-day + static charT day_sep_char() + { + return '-'; + } + //! char between date-hours + static charT hour_sep_char() + { + return ' '; + } + //! char between hour and minute + static charT minute_sep_char() + { + return ':'; + } + //! char for second + static charT second_sep_char() + { + return ':'; + } + +}; + +#ifndef BOOST_NO_STD_WSTRING + +//! Specialization of formmating rules for wchar_t +template<> +class simple_format<wchar_t> { +public: + + //! String used printed is date is invalid + static const wchar_t* not_a_date() + { + return L"not-a-date-time"; + } + //! String used to for positive infinity value + static const wchar_t* pos_infinity() + { + return L"+infinity"; + } + //! String used to for positive infinity value + static const wchar_t* neg_infinity() + { + return L"-infinity"; + } + //! Describe month format + static month_format_spec month_format() + { + return month_as_short_string; + } + static ymd_order_spec date_order() + { + return ymd_order_iso; //YYYY-MM-DD + } + //! This format uses '-' to separate date elements + static bool has_date_sep_chars() + { + return true; + } + //! Char to sep? + static wchar_t year_sep_char() + { + return '-'; + } + //! char between year-month + static wchar_t month_sep_char() + { + return '-'; + } + //! Char to separate month-day + static wchar_t day_sep_char() + { + return '-'; + } + //! char between date-hours + static wchar_t hour_sep_char() + { + return ' '; + } + //! char between hour and minute + static wchar_t minute_sep_char() + { + return ':'; + } + //! char for second + static wchar_t second_sep_char() + { + return ':'; + } + +}; + +#endif // BOOST_NO_STD_WSTRING +} } //namespace date_time + + + + +#endif diff --git a/ext/boost/date_time/date_formatting.hpp b/ext/boost/date_time/date_formatting.hpp new file mode 100644 index 0000000000..abe547a5f7 --- /dev/null +++ b/ext/boost/date_time/date_formatting.hpp @@ -0,0 +1,127 @@ +#ifndef DATE_TIME_DATE_FORMATTING_HPP___ +#define DATE_TIME_DATE_FORMATTING_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/compiler_config.hpp" +#include <string> +#include <sstream> +#include <iomanip> + +/* NOTE: "formatter" code for older compilers, ones that define + * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in + * date_formatting_limited.hpp + */ + +namespace boost { +namespace date_time { + + //! Formats a month as as string into an ostream + template<class month_type, class format_type, class charT=char> + class month_formatter + { + typedef std::basic_ostream<charT> ostream_type; + public: + //! Formats a month as as string into an ostream + /*! This function demands that month_type provide + * functions for converting to short and long strings + * if that capability is used. + */ + static ostream_type& format_month(const month_type& month, + ostream_type &os) + { + switch (format_type::month_format()) + { + case month_as_short_string: + { + os << month.as_short_string(); + break; + } + case month_as_long_string: + { + os << month.as_long_string(); + break; + } + case month_as_integer: + { + os << std::setw(2) << std::setfill(os.widen('0')) << month.as_number(); + break; + } + + } + return os; + } // format_month + }; + + + //! Convert ymd to a standard string formatting policies + template<class ymd_type, class format_type, class charT=char> + class ymd_formatter + { + public: + //! Convert ymd to a standard string formatting policies + /*! This is standard code for handling date formatting with + * year-month-day based date information. This function + * uses the format_type to control whether the string will + * contain separator characters, and if so what the character + * will be. In addtion, it can format the month as either + * an integer or a string as controled by the formatting + * policy + */ + static std::basic_string<charT> ymd_to_string(ymd_type ymd) + { + typedef typename ymd_type::month_type month_type; + std::basic_ostringstream<charT> ss; + ss << ymd.year; + if (format_type::has_date_sep_chars()) { + ss << format_type::month_sep_char(); + } + //this name is a bit ugly, oh well.... + month_formatter<month_type,format_type,charT>::format_month(ymd.month, ss); + if (format_type::has_date_sep_chars()) { + ss << format_type::day_sep_char(); + } + ss << std::setw(2) << std::setfill(ss.widen('0')) + << ymd.day; + return ss.str(); + } + }; + + + //! Convert a date to string using format policies + template<class date_type, class format_type, class charT=char> + class date_formatter + { + public: + typedef std::basic_string<charT> string_type; + //! Convert to a date to standard string using format policies + static string_type date_to_string(date_type d) + { + typedef typename date_type::ymd_type ymd_type; + if (d.is_not_a_date()) { + return string_type(format_type::not_a_date()); + } + if (d.is_neg_infinity()) { + return string_type(format_type::neg_infinity()); + } + if (d.is_pos_infinity()) { + return string_type(format_type::pos_infinity()); + } + ymd_type ymd = d.year_month_day(); + return ymd_formatter<ymd_type, format_type, charT>::ymd_to_string(ymd); + } + }; + + +} } //namespace date_time + + +#endif + diff --git a/ext/boost/date_time/date_formatting_limited.hpp b/ext/boost/date_time/date_formatting_limited.hpp new file mode 100644 index 0000000000..38fee07b91 --- /dev/null +++ b/ext/boost/date_time/date_formatting_limited.hpp @@ -0,0 +1,121 @@ +#ifndef DATE_TIME_DATE_FORMATTING_LIMITED_HPP___ +#define DATE_TIME_DATE_FORMATTING_LIMITED_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/compiler_config.hpp" +#include <string> +#include <sstream> +#include <iomanip> + + +namespace boost { +namespace date_time { + + //! Formats a month as as string into an ostream + template<class month_type, class format_type> + class month_formatter + { + public: + //! Formats a month as as string into an ostream + /*! This function demands that month_type provide + * functions for converting to short and long strings + * if that capability is used. + */ + static std::ostream& format_month(const month_type& month, + std::ostream& os) + { + switch (format_type::month_format()) + { + case month_as_short_string: + { + os << month.as_short_string(); + break; + } + case month_as_long_string: + { + os << month.as_long_string(); + break; + } + case month_as_integer: + { + os << std::setw(2) << std::setfill('0') << month.as_number(); + break; + } + + } + return os; + } // format_month + }; + + + //! Convert ymd to a standard string formatting policies + template<class ymd_type, class format_type> + class ymd_formatter + { + public: + //! Convert ymd to a standard string formatting policies + /*! This is standard code for handling date formatting with + * year-month-day based date information. This function + * uses the format_type to control whether the string will + * contain separator characters, and if so what the character + * will be. In addtion, it can format the month as either + * an integer or a string as controled by the formatting + * policy + */ + static std::string ymd_to_string(ymd_type ymd) + { + typedef typename ymd_type::month_type month_type; + std::ostringstream ss; + ss << ymd.year; + if (format_type::has_date_sep_chars()) { + ss << format_type::month_sep_char(); + } + //this name is a bit ugly, oh well.... + month_formatter<month_type,format_type>::format_month(ymd.month, ss); + if (format_type::has_date_sep_chars()) { + ss << format_type::day_sep_char(); + } + ss << std::setw(2) << std::setfill('0') + << ymd.day; + return ss.str(); + } + }; + + + //! Convert a date to string using format policies + template<class date_type, class format_type> + class date_formatter + { + public: + //! Convert to a date to standard string using format policies + static std::string date_to_string(date_type d) + { + typedef typename date_type::ymd_type ymd_type; + if (d.is_not_a_date()) { + return format_type::not_a_date(); + } + if (d.is_neg_infinity()) { + return format_type::neg_infinity(); + } + if (d.is_pos_infinity()) { + return format_type::pos_infinity(); + } + ymd_type ymd = d.year_month_day(); + return ymd_formatter<ymd_type, format_type>::ymd_to_string(ymd); + } + }; + + +} } //namespace date_time + + +#endif + diff --git a/ext/boost/date_time/date_formatting_locales.hpp b/ext/boost/date_time/date_formatting_locales.hpp new file mode 100644 index 0000000000..4ac9c4e401 --- /dev/null +++ b/ext/boost/date_time/date_formatting_locales.hpp @@ -0,0 +1,233 @@ +#ifndef DATE_TIME_DATE_FORMATTING_LOCALES_HPP___ +#define DATE_TIME_DATE_FORMATTING_LOCALES_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/locale_config.hpp" // set BOOST_DATE_TIME_NO_LOCALE + +#ifndef BOOST_DATE_TIME_NO_LOCALE + +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_names_put.hpp" +#include "boost/date_time/parse_format_base.hpp" +//#include <string> +#include <sstream> +#include <iomanip> + + +namespace boost { +namespace date_time { + + //! Formats a month as as string into an ostream + template<class facet_type, + class charT = char> + class ostream_month_formatter + { + public: + typedef typename facet_type::month_type month_type; + typedef std::basic_ostream<charT> ostream_type; + + //! Formats a month as as string into an output iterator + static void format_month(const month_type& month, + ostream_type& os, + const facet_type& f) + { + + switch (f.month_format()) + { + case month_as_short_string: + { + std::ostreambuf_iterator<charT> oitr(os); + f.put_month_short(oitr, month.as_enum()); + break; + } + case month_as_long_string: + { + std::ostreambuf_iterator<charT> oitr(os); + f.put_month_long(oitr, month.as_enum()); + break; + } + case month_as_integer: + { + charT fill_char = '0'; + os << std::setw(2) << std::setfill(fill_char) << month.as_number(); + break; + } + + } + } // format_month + + }; + + + //! Formats a weekday + template<class weekday_type, + class facet_type, + class charT = char> + class ostream_weekday_formatter + { + public: + typedef typename facet_type::month_type month_type; + typedef std::basic_ostream<charT> ostream_type; + + //! Formats a month as as string into an output iterator + static void format_weekday(const weekday_type& wd, + ostream_type& os, + const facet_type& f, + bool as_long_string) + { + + std::ostreambuf_iterator<charT> oitr(os); + if (as_long_string) { + f.put_weekday_long(oitr, wd.as_enum()); + } + else { + f.put_weekday_short(oitr, wd.as_enum()); + } + + } // format_weekday + + }; + + + //! Convert ymd to a standard string formatting policies + template<class ymd_type, + class facet_type, + class charT = char> + class ostream_ymd_formatter + { + public: + typedef typename ymd_type::month_type month_type; + typedef ostream_month_formatter<facet_type, charT> month_formatter_type; + typedef std::basic_ostream<charT> ostream_type; + typedef std::basic_string<charT> foo_type; + + //! Convert ymd to a standard string formatting policies + /*! This is standard code for handling date formatting with + * year-month-day based date information. This function + * uses the format_type to control whether the string will + * contain separator characters, and if so what the character + * will be. In addtion, it can format the month as either + * an integer or a string as controled by the formatting + * policy + */ + // static string_type ymd_to_string(ymd_type ymd) +// { +// std::ostringstream ss; +// facet_type dnp; +// ymd_put(ymd, ss, dnp); +// return ss.str(); +// } + + + // Put ymd to ostream -- part of ostream refactor + static void ymd_put(ymd_type ymd, + ostream_type& os, + const facet_type& f) + { + std::ostreambuf_iterator<charT> oitr(os); + charT fill_char = '0'; + switch (f.date_order()) { + case ymd_order_iso: { + os << ymd.year; + if (f.has_date_sep_chars()) { + f.month_sep_char(oitr); + } + month_formatter_type::format_month(ymd.month, os, f); + if (f.has_date_sep_chars()) { + f.day_sep_char(oitr); + } + os << std::setw(2) << std::setfill(fill_char) + << ymd.day; + break; + } + case ymd_order_us: { + month_formatter_type::format_month(ymd.month, os, f); + if (f.has_date_sep_chars()) { + f.day_sep_char(oitr); + } + os << std::setw(2) << std::setfill(fill_char) + << ymd.day; + if (f.has_date_sep_chars()) { + f.month_sep_char(oitr); + } + os << ymd.year; + break; + } + case ymd_order_dmy: { + os << std::setw(2) << std::setfill(fill_char) + << ymd.day; + if (f.has_date_sep_chars()) { + f.day_sep_char(oitr); + } + month_formatter_type::format_month(ymd.month, os, f); + if (f.has_date_sep_chars()) { + f.month_sep_char(oitr); + } + os << ymd.year; + break; + } + } + } + }; + + + //! Convert a date to string using format policies + template<class date_type, + class facet_type, + class charT = char> + class ostream_date_formatter + { + public: + typedef std::basic_ostream<charT> ostream_type; + typedef typename date_type::ymd_type ymd_type; + + //! Put date into an ostream + static void date_put(const date_type& d, + ostream_type& os, + const facet_type& f) + { + special_values sv = d.as_special(); + if (sv == not_special) { + ymd_type ymd = d.year_month_day(); + ostream_ymd_formatter<ymd_type, facet_type, charT>::ymd_put(ymd, os, f); + } + else { // output a special value + std::ostreambuf_iterator<charT> coi(os); + f.put_special_value(coi, sv); + } + } + + + //! Put date into an ostream + static void date_put(const date_type& d, + ostream_type& os) + { + //retrieve the local from the ostream + std::locale locale = os.getloc(); + if (std::has_facet<facet_type>(locale)) { + const facet_type& f = std::use_facet<facet_type>(locale); + date_put(d, os, f); + } + else { + //default to something sensible if no facet installed + facet_type default_facet; + date_put(d, os, default_facet); + } + } // date_to_ostream + }; //class date_formatter + + +} } //namespace date_time + +#endif + +#endif + diff --git a/ext/boost/date_time/date_generator_formatter.hpp b/ext/boost/date_time/date_generator_formatter.hpp new file mode 100644 index 0000000000..88cd7e1aba --- /dev/null +++ b/ext/boost/date_time/date_generator_formatter.hpp @@ -0,0 +1,265 @@ +#ifndef _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ +#define _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-13 14:05:31 -0500 (Thu, 13 Nov 2008) $ + */ + +#include <iostream> +#include <string> +#include <vector> +#include <algorithm> +#include "boost/date_time/date_generators.hpp" + +namespace boost { +namespace date_time { + + //! Formats date_generators for output + /*! Formatting of date_generators follows specific orders for the + * various types of date_generators. + * - partial_date => "dd Month" + * - nth_day_of_the_week_in_month => "nth weekday of month" + * - first_day_of_the_week_in_month => "first weekday of month" + * - last_day_of_the_week_in_month => "last weekday of month" + * - first_day_of_the_week_after => "weekday after" + * - first_day_of_the_week_before => "weekday before" + * While the order of the elements in these phrases cannot be changed, + * the elements themselves can be. Weekday and Month get their formats + * and names from the date_facet. The remaining elements are stored in + * the date_generator_formatter and can be customized upon construction + * or via a member function. The default elements are those shown in the + * examples above. + */ + template <class date_type, class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > + class date_generator_formatter { + public: + typedef partial_date<date_type> partial_date_type; + typedef nth_kday_of_month<date_type> nth_kday_type; + typedef first_kday_of_month<date_type> first_kday_type; + typedef last_kday_of_month<date_type> last_kday_type; + typedef first_kday_after<date_type> kday_after_type; + typedef first_kday_before<date_type> kday_before_type; + + typedef CharT char_type; + typedef std::basic_string<char_type> string_type; + typedef std::vector<string_type> collection_type; + static const char_type first_string[6]; + static const char_type second_string[7]; + static const char_type third_string[6]; + static const char_type fourth_string[7]; + static const char_type fifth_string[6]; + static const char_type last_string[5]; + static const char_type before_string[8]; + static const char_type after_string[6]; + static const char_type of_string[3]; + + enum phrase_elements {first=0, second, third, fourth, fifth, last, + before, after, of, number_of_phrase_elements}; + + //! Default format elements used + date_generator_formatter() + { + phrase_strings.reserve(number_of_phrase_elements); + phrase_strings.push_back(string_type(first_string)); + phrase_strings.push_back(string_type(second_string)); + phrase_strings.push_back(string_type(third_string)); + phrase_strings.push_back(string_type(fourth_string)); + phrase_strings.push_back(string_type(fifth_string)); + phrase_strings.push_back(string_type(last_string)); + phrase_strings.push_back(string_type(before_string)); + phrase_strings.push_back(string_type(after_string)); + phrase_strings.push_back(string_type(of_string)); + } + + //! Constructor that allows for a custom set of phrase elements + date_generator_formatter(const string_type& first_str, + const string_type& second_str, + const string_type& third_str, + const string_type& fourth_str, + const string_type& fifth_str, + const string_type& last_str, + const string_type& before_str, + const string_type& after_str, + const string_type& of_str) + { + phrase_strings.reserve(number_of_phrase_elements); + phrase_strings.push_back(first_str); + phrase_strings.push_back(second_str); + phrase_strings.push_back(third_str); + phrase_strings.push_back(fourth_str); + phrase_strings.push_back(fifth_str); + phrase_strings.push_back(last_str); + phrase_strings.push_back(before_str); + phrase_strings.push_back(after_str); + phrase_strings.push_back(of_str); + } + + //! Replace the set of phrase elements with those contained in new_strings + /*! The order of the strings in the given collection is important. + * They must follow: + * - first, second, third, fourth, fifth, last, before, after, of. + * + * It is not necessary to send in a complete set if only a few + * elements are to be replaced as long as the correct beg_pos is used. + * + * Ex: To keep the default first through fifth elements, but replace + * the rest with a collection of: + * - "final", "prior", "following", "in". + * The beg_pos of date_generator_formatter::last would be used. + */ + void elements(const collection_type& new_strings, + phrase_elements beg_pos=first) + { + if(beg_pos < number_of_phrase_elements) { + typename collection_type::iterator itr = phrase_strings.begin(); + itr += beg_pos; + std::copy(new_strings.begin(), new_strings.end(), + itr); + //phrase_strings.begin()); + } + } + + //!Put a partial_date => "dd Month" + template<class facet_type> + OutItrT put_partial_date(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const partial_date_type& pd, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, pd.day()); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, pd.month()); + return next; + } + + //! Put an nth_day_of_the_week_in_month => "nth weekday of month" + template<class facet_type> + OutItrT put_nth_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const nth_kday_type& nkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[nkd.nth_week() -1]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, nkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, nkd.month()); + return next; + } + + //! Put a first_day_of_the_week_in_month => "first weekday of month" + template<class facet_type> + OutItrT put_first_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const first_kday_type& fkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[first]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, fkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, fkd.month()); + return next; + } + + //! Put a last_day_of_the_week_in_month => "last weekday of month" + template<class facet_type> + OutItrT put_last_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const last_kday_type& lkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[last]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, lkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, lkd.month()); + return next; + } + + //! Put a first_day_of_the_week_before => "weekday before" + template<class facet_type> + OutItrT put_kday_before(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const kday_before_type& fkb, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, fkb.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, phrase_strings[before]); + return next; + } + + //! Put a first_day_of_the_week_after => "weekday after" + template<class facet_type> + OutItrT put_kday_after(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const kday_after_type& fka, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, fka.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, phrase_strings[after]); + return next; + } + + + private: + collection_type phrase_strings; + + //! helper function to put the various member string into stream + OutItrT put_string(OutItrT next, const string_type& str) const + { + typename string_type::const_iterator itr = str.begin(); + while(itr != str.end()) { + *next = *itr; + ++itr; + ++next; + } + return next; + } + }; + + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::first_string[6] = + {'f','i','r','s','t'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::second_string[7] = + {'s','e','c','o','n','d'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::third_string[6] = + {'t','h','i','r','d'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::fourth_string[7] = + {'f','o','u','r','t','h'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::fifth_string[6] = + {'f','i','f','t','h'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::last_string[5] = + {'l','a','s','t'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::before_string[8] = + {'b','e','f','o','r','e'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::after_string[6] = + {'a','f','t','e','r'}; + template<class date_type, class CharT, class OutItrT> + const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type + date_generator_formatter<date_type, CharT, OutItrT>::of_string[3] = + {'o','f'}; +} } // namespaces + +#endif // _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ diff --git a/ext/boost/date_time/date_generator_parser.hpp b/ext/boost/date_time/date_generator_parser.hpp new file mode 100644 index 0000000000..f11eb42d52 --- /dev/null +++ b/ext/boost/date_time/date_generator_parser.hpp @@ -0,0 +1,330 @@ + +#ifndef DATE_TIME_DATE_GENERATOR_PARSER_HPP__ +#define DATE_TIME_DATE_GENERATOR_PARSER_HPP__ + +/* Copyright (c) 2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <string> +#include <vector> +#include <iterator> // istreambuf_iterator +#include <boost/throw_exception.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/string_parse_tree.hpp> +#include <boost/date_time/date_generators.hpp> +#include <boost/date_time/format_date_parser.hpp> + +namespace boost { namespace date_time { + + //! Class for date_generator parsing + /*! The elements of a date_generator "phrase" are parsed from the input stream in a + * particular order. All elements are required and the order in which they appear + * cannot change, however, the elements themselves can be changed. The default + * elements and their order are as follows: + * + * - partial_date => "dd Month" + * - nth_day_of_the_week_in_month => "nth weekday of month" + * - first_day_of_the_week_in_month => "first weekday of month" + * - last_day_of_the_week_in_month => "last weekday of month" + * - first_day_of_the_week_after => "weekday after" + * - first_day_of_the_week_before => "weekday before" + * + * Weekday and Month names and formats are handled via the date_input_facet. + * + */ + template<class date_type, typename charT> + class date_generator_parser + { + public: + typedef std::basic_string<charT> string_type; + typedef std::istreambuf_iterator<charT> stream_itr_type; + + typedef typename date_type::month_type month_type; + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + + typedef string_parse_tree<charT> parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector<std::basic_string<charT> > collection_type; + + typedef partial_date<date_type> partial_date_type; + typedef nth_kday_of_month<date_type> nth_kday_type; + typedef first_kday_of_month<date_type> first_kday_type; + typedef last_kday_of_month<date_type> last_kday_type; + typedef first_kday_after<date_type> kday_after_type; + typedef first_kday_before<date_type> kday_before_type; + + typedef charT char_type; + static const char_type first_string[6]; + static const char_type second_string[7]; + static const char_type third_string[6]; + static const char_type fourth_string[7]; + static const char_type fifth_string[6]; + static const char_type last_string[5]; + static const char_type before_string[8]; + static const char_type after_string[6]; + static const char_type of_string[3]; + + enum phrase_elements {first=0, second, third, fourth, fifth, last, + before, after, of, number_of_phrase_elements}; + + //! Creates a date_generator_parser with the default set of "element_strings" + date_generator_parser() + { + element_strings(string_type(first_string), + string_type(second_string), + string_type(third_string), + string_type(fourth_string), + string_type(fifth_string), + string_type(last_string), + string_type(before_string), + string_type(after_string), + string_type(of_string)); + } + + //! Creates a date_generator_parser using a user defined set of element strings + date_generator_parser(const string_type& first_str, + const string_type& second_str, + const string_type& third_str, + const string_type& fourth_str, + const string_type& fifth_str, + const string_type& last_str, + const string_type& before_str, + const string_type& after_str, + const string_type& of_str) + { + element_strings(first_str, second_str, third_str, fourth_str, fifth_str, + last_str, before_str, after_str, of_str); + } + + //! Replace strings that determine nth week for generator + void element_strings(const string_type& first_str, + const string_type& second_str, + const string_type& third_str, + const string_type& fourth_str, + const string_type& fifth_str, + const string_type& last_str, + const string_type& before_str, + const string_type& after_str, + const string_type& of_str) + { + collection_type phrases; + phrases.push_back(first_str); + phrases.push_back(second_str); + phrases.push_back(third_str); + phrases.push_back(fourth_str); + phrases.push_back(fifth_str); + phrases.push_back(last_str); + phrases.push_back(before_str); + phrases.push_back(after_str); + phrases.push_back(of_str); + m_element_strings = parse_tree_type(phrases, this->first); // enum first + } + + void element_strings(const collection_type& col) + { + m_element_strings = parse_tree_type(col, this->first); // enum first + } + + //! returns partial_date parsed from stream + template<class facet_type> + partial_date_type + get_partial_date_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_type d(1); + month_type m(1); + facet.get(sitr, stream_end, a_ios, d); + facet.get(sitr, stream_end, a_ios, m); + + return partial_date_type(d,m); + } + + //! returns nth_kday_of_week parsed from stream + template<class facet_type> + nth_kday_type + get_nth_kday_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + typename nth_kday_type::week_num wn; + day_of_week_type wd(0); // no default constructor + month_type m(1); // no default constructor + + match_results mr = m_element_strings.match(sitr, stream_end); + switch(mr.current_match) { + case first : { wn = nth_kday_type::first; break; } + case second : { wn = nth_kday_type::second; break; } + case third : { wn = nth_kday_type::third; break; } + case fourth : { wn = nth_kday_type::fourth; break; } + case fifth : { wn = nth_kday_type::fifth; break; } + default: + { + boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'")); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(wn = nth_kday_type::first); + } + } // week num + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, of); // "of" element + facet.get(sitr, stream_end, a_ios, m); // month + + return nth_kday_type(wn, wd, m); + } + + //! returns first_kday_of_week parsed from stream + template<class facet_type> + first_kday_type + get_first_kday_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + month_type m(1); // no default constructor + + extract_element(sitr, stream_end, first); // "first" element + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, of); // "of" element + facet.get(sitr, stream_end, a_ios, m); // month + + + return first_kday_type(wd, m); + } + + //! returns last_kday_of_week parsed from stream + template<class facet_type> + last_kday_type + get_last_kday_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + month_type m(1); // no default constructor + + extract_element(sitr, stream_end, last); // "last" element + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, of); // "of" element + facet.get(sitr, stream_end, a_ios, m); // month + + + return last_kday_type(wd, m); + } + + //! returns first_kday_of_week parsed from stream + template<class facet_type> + kday_before_type + get_kday_before_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, before);// "before" element + + return kday_before_type(wd); + } + + //! returns first_kday_of_week parsed from stream + template<class facet_type> + kday_after_type + get_kday_after_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, after); // "after" element + + return kday_after_type(wd); + } + + private: + parse_tree_type m_element_strings; + + //! Extracts phrase element from input. Throws ios_base::failure on error. + void extract_element(stream_itr_type& sitr, + stream_itr_type& stream_end, + typename date_generator_parser::phrase_elements ele) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + match_results mr = m_element_strings.match(sitr, stream_end); + if(mr.current_match != ele) { + boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'")); + } + } + + }; + + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::first_string[6] = + {'f','i','r','s','t'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::second_string[7] = + {'s','e','c','o','n','d'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::third_string[6] = + {'t','h','i','r','d'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::fourth_string[7] = + {'f','o','u','r','t','h'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::fifth_string[6] = + {'f','i','f','t','h'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::last_string[5] = + {'l','a','s','t'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::before_string[8] = + {'b','e','f','o','r','e'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::after_string[6] = + {'a','f','t','e','r'}; + template<class date_type, class CharT> + const typename date_generator_parser<date_type, CharT>::char_type + date_generator_parser<date_type, CharT>::of_string[3] = + {'o','f'}; + +} } //namespace + +#endif // DATE_TIME_DATE_GENERATOR_PARSER_HPP__ + diff --git a/ext/boost/date_time/date_generators.hpp b/ext/boost/date_time/date_generators.hpp new file mode 100644 index 0000000000..1f1a34a667 --- /dev/null +++ b/ext/boost/date_time/date_generators.hpp @@ -0,0 +1,509 @@ +#ifndef DATE_TIME_DATE_GENERATORS_HPP__ +#define DATE_TIME_DATE_GENERATORS_HPP__ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +/*! @file date_generators.hpp + Definition and implementation of date algorithm templates +*/ + +#include <stdexcept> +#include <sstream> +#include <boost/throw_exception.hpp> +#include <boost/date_time/date.hpp> +#include <boost/date_time/compiler_config.hpp> + +namespace boost { +namespace date_time { + + //! Base class for all generators that take a year and produce a date. + /*! This class is a base class for polymorphic function objects that take + a year and produce a concrete date. + @param date_type The type representing a date. This type must + export a calender_type which defines a year_type. + */ + template<class date_type> + class year_based_generator + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::year_type year_type; + year_based_generator() {}; + virtual ~year_based_generator() {}; + virtual date_type get_date(year_type y) const = 0; + //! Returns a string for use in a POSIX time_zone string + virtual std::string to_string() const =0; + }; + + //! Generates a date by applying the year to the given month and day. + /*! + Example usage: + @code + partial_date pd(1, Jan); + partial_date pd2(70); + date d = pd.get_date(2002); //2002-Jan-01 + date d2 = pd2.get_date(2002); //2002-Mar-10 + @endcode + \ingroup date_alg + */ + template<class date_type> + class partial_date : public year_based_generator<date_type> + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_type day_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + typedef typename duration_type::duration_rep duration_rep; + partial_date(day_type d, month_type m) : + day_(d), + month_(m) + {} + //! Partial date created from number of days into year. Range 1-366 + /*! Allowable values range from 1 to 366. 1=Jan1, 366=Dec31. If argument + * exceeds range, partial_date will be created with closest in-range value. + * 60 will always be Feb29, if get_date() is called with a non-leap year + * an exception will be thrown */ + partial_date(duration_rep days) : + day_(1), // default values + month_(1) + { + date_type d1(2000,1,1); + if(days > 1) { + if(days > 366) // prevents wrapping + { + days = 366; + } + days = days - 1; + duration_type dd(days); + d1 = d1 + dd; + } + day_ = d1.day(); + month_ = d1.month(); + } + //! Return a concrete date when provided with a year specific year. + /*! Will throw an 'invalid_argument' exception if a partial_date object, + * instantiated with Feb-29, has get_date called with a non-leap year. + * Example: + * @code + * partial_date pd(29, Feb); + * pd.get_date(2003); // throws invalid_argument exception + * pg.get_date(2000); // returns 2000-2-29 + * @endcode + */ + date_type get_date(year_type y) const + { + if((day_ == 29) && (month_ == 2) && !(calendar_type::is_leap_year(y))) { + std::ostringstream ss; + ss << "No Feb 29th in given year of " << y << "."; + boost::throw_exception(std::invalid_argument(ss.str())); + } + return date_type(y, month_, day_); + } + date_type operator()(year_type y) const + { + return get_date(y); + //return date_type(y, month_, day_); + } + bool operator==(const partial_date& rhs) const + { + return (month_ == rhs.month_) && (day_ == rhs.day_); + } + bool operator<(const partial_date& rhs) const + { + if (month_ < rhs.month_) return true; + if (month_ > rhs.month_) return false; + //months are equal + return (day_ < rhs.day_); + } + + // added for streaming purposes + month_type month() const + { + return month_; + } + day_type day() const + { + return day_; + } + + //! Returns string suitable for use in POSIX time zone string + /*! Returns string formatted with up to 3 digits: + * Jan-01 == "0" + * Feb-29 == "58" + * Dec-31 == "365" */ + virtual std::string to_string() const + { + std::ostringstream ss; + date_type d(2004, month_, day_); + unsigned short c = d.day_of_year(); + c--; // numbered 0-365 while day_of_year is 1 based... + ss << c; + return ss.str(); + } + private: + day_type day_; + month_type month_; + }; + + + //! Returns nth arg as string. 1 -> "first", 2 -> "second", max is 5. + BOOST_DATE_TIME_DECL const char* nth_as_str(int n); + + //! Useful generator functor for finding holidays + /*! Based on the idea in Cal. Calc. for finding holidays that are + * the 'first Monday of September'. When instantiated with + * 'fifth' kday of month, the result will be the last kday of month + * which can be the fourth or fifth depending on the structure of + * the month. + * + * The algorithm here basically guesses for the first + * day of the month. Then finds the first day of the correct + * type. That is, if the first of the month is a Tuesday + * and it needs Wenesday then we simply increment by a day + * and then we can add the length of a week until we get + * to the 'nth kday'. There are probably more efficient + * algorithms based on using a mod 7, but this one works + * reasonably well for basic applications. + * \ingroup date_alg + */ + template<class date_type> + class nth_kday_of_month : public year_based_generator<date_type> + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + enum week_num {first=1, second, third, fourth, fifth}; + nth_kday_of_month(week_num week_no, + day_of_week_type dow, + month_type m) : + month_(m), + wn_(week_no), + dow_(dow) + {} + //! Return a concrete date when provided with a year specific year. + date_type get_date(year_type y) const + { + date_type d(y, month_, 1); //first day of month + duration_type one_day(1); + duration_type one_week(7); + while (dow_ != d.day_of_week()) { + d = d + one_day; + } + int week = 1; + while (week < wn_) { + d = d + one_week; + week++; + } + // remove wrapping to next month behavior + if(d.month() != month_) { + d = d - one_week; + } + return d; + } + // added for streaming + month_type month() const + { + return month_; + } + week_num nth_week() const + { + return wn_; + } + day_of_week_type day_of_week() const + { + return dow_; + } + const char* nth_week_as_str() const + { + return nth_as_str(wn_); + } + //! Returns string suitable for use in POSIX time zone string + /*! Returns a string formatted as "M4.3.0" ==> 3rd Sunday in April. */ + virtual std::string to_string() const + { + std::ostringstream ss; + ss << 'M' + << static_cast<int>(month_) << '.' + << static_cast<int>(wn_) << '.' + << static_cast<int>(dow_); + return ss.str(); + } + private: + month_type month_; + week_num wn_; + day_of_week_type dow_; + }; + + //! Useful generator functor for finding holidays and daylight savings + /*! Similar to nth_kday_of_month, but requires less paramters + * \ingroup date_alg + */ + template<class date_type> + class first_kday_of_month : public year_based_generator<date_type> + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + //!Specify the first 'Sunday' in 'April' spec + /*!@param dow The day of week, eg: Sunday, Monday, etc + * @param m The month of the year, eg: Jan, Feb, Mar, etc + */ + first_kday_of_month(day_of_week_type dow, month_type m) : + month_(m), + dow_(dow) + {} + //! Return a concrete date when provided with a year specific year. + date_type get_date(year_type year) const + { + date_type d(year, month_,1); + duration_type one_day(1); + while (dow_ != d.day_of_week()) { + d = d + one_day; + } + return d; + } + // added for streaming + month_type month() const + { + return month_; + } + day_of_week_type day_of_week() const + { + return dow_; + } + //! Returns string suitable for use in POSIX time zone string + /*! Returns a string formatted as "M4.1.0" ==> 1st Sunday in April. */ + virtual std::string to_string() const + { + std::ostringstream ss; + ss << 'M' + << static_cast<int>(month_) << '.' + << 1 << '.' + << static_cast<int>(dow_); + return ss.str(); + } + private: + month_type month_; + day_of_week_type dow_; + }; + + + + //! Calculate something like Last Sunday of January + /*! Useful generator functor for finding holidays and daylight savings + * Get the last day of the month and then calculate the difference + * to the last previous day. + * @param date_type A date class that exports day_of_week, month_type, etc. + * \ingroup date_alg + */ + template<class date_type> + class last_kday_of_month : public year_based_generator<date_type> + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + //!Specify the date spec like last 'Sunday' in 'April' spec + /*!@param dow The day of week, eg: Sunday, Monday, etc + * @param m The month of the year, eg: Jan, Feb, Mar, etc + */ + last_kday_of_month(day_of_week_type dow, month_type m) : + month_(m), + dow_(dow) + {} + //! Return a concrete date when provided with a year specific year. + date_type get_date(year_type year) const + { + date_type d(year, month_, calendar_type::end_of_month_day(year,month_)); + duration_type one_day(1); + while (dow_ != d.day_of_week()) { + d = d - one_day; + } + return d; + } + // added for streaming + month_type month() const + { + return month_; + } + day_of_week_type day_of_week() const + { + return dow_; + } + //! Returns string suitable for use in POSIX time zone string + /*! Returns a string formatted as "M4.5.0" ==> last Sunday in April. */ + virtual std::string to_string() const + { + std::ostringstream ss; + ss << 'M' + << static_cast<int>(month_) << '.' + << 5 << '.' + << static_cast<int>(dow_); + return ss.str(); + } + private: + month_type month_; + day_of_week_type dow_; + }; + + + //! Calculate something like "First Sunday after Jan 1,2002 + /*! Date generator that takes a date and finds kday after + *@code + typedef boost::date_time::first_kday_after<date> firstkdayafter; + firstkdayafter fkaf(Monday); + fkaf.get_date(date(2002,Feb,1)); + @endcode + * \ingroup date_alg + */ + template<class date_type> + class first_kday_after + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename date_type::duration_type duration_type; + first_kday_after(day_of_week_type dow) : + dow_(dow) + {} + //! Return next kday given. + date_type get_date(date_type start_day) const + { + duration_type one_day(1); + date_type d = start_day + one_day; + while (dow_ != d.day_of_week()) { + d = d + one_day; + } + return d; + } + // added for streaming + day_of_week_type day_of_week() const + { + return dow_; + } + private: + day_of_week_type dow_; + }; + + //! Calculate something like "First Sunday before Jan 1,2002 + /*! Date generator that takes a date and finds kday after + *@code + typedef boost::date_time::first_kday_before<date> firstkdaybefore; + firstkdaybefore fkbf(Monday); + fkbf.get_date(date(2002,Feb,1)); + @endcode + * \ingroup date_alg + */ + template<class date_type> + class first_kday_before + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename date_type::duration_type duration_type; + first_kday_before(day_of_week_type dow) : + dow_(dow) + {} + //! Return next kday given. + date_type get_date(date_type start_day) const + { + duration_type one_day(1); + date_type d = start_day - one_day; + while (dow_ != d.day_of_week()) { + d = d - one_day; + } + return d; + } + // added for streaming + day_of_week_type day_of_week() const + { + return dow_; + } + private: + day_of_week_type dow_; + }; + + //! Calculates the number of days until the next weekday + /*! Calculates the number of days until the next weekday. + * If the date given falls on a Sunday and the given weekday + * is Tuesday the result will be 2 days */ + template<typename date_type, class weekday_type> + inline + typename date_type::duration_type days_until_weekday(const date_type& d, const weekday_type& wd) + { + typedef typename date_type::duration_type duration_type; + duration_type wks(0); + duration_type dd(wd.as_number() - d.day_of_week().as_number()); + if(dd.is_negative()){ + wks = duration_type(7); + } + return dd + wks; + } + + //! Calculates the number of days since the previous weekday + /*! Calculates the number of days since the previous weekday + * If the date given falls on a Sunday and the given weekday + * is Tuesday the result will be 5 days. The answer will be a positive + * number because Tuesday is 5 days before Sunday, not -5 days before. */ + template<typename date_type, class weekday_type> + inline + typename date_type::duration_type days_before_weekday(const date_type& d, const weekday_type& wd) + { + typedef typename date_type::duration_type duration_type; + duration_type wks(0); + duration_type dd(wd.as_number() - d.day_of_week().as_number()); + if(dd.days() > 0){ + wks = duration_type(7); + } + // we want a number of days, not an offset. The value returned must + // be zero or larger. + return (-dd + wks); + } + + //! Generates a date object representing the date of the following weekday from the given date + /*! Generates a date object representing the date of the following + * weekday from the given date. If the date given is 2004-May-9 + * (a Sunday) and the given weekday is Tuesday then the resulting date + * will be 2004-May-11. */ + template<class date_type, class weekday_type> + inline + date_type next_weekday(const date_type& d, const weekday_type& wd) + { + return d + days_until_weekday(d, wd); + } + + //! Generates a date object representing the date of the previous weekday from the given date + /*! Generates a date object representing the date of the previous + * weekday from the given date. If the date given is 2004-May-9 + * (a Sunday) and the given weekday is Tuesday then the resulting date + * will be 2004-May-4. */ + template<class date_type, class weekday_type> + inline + date_type previous_weekday(const date_type& d, const weekday_type& wd) + { + return d - days_before_weekday(d, wd); + } + +} } //namespace date_time + + + + +#endif + diff --git a/ext/boost/date_time/date_iterator.hpp b/ext/boost/date_time/date_iterator.hpp new file mode 100644 index 0000000000..284dc749d0 --- /dev/null +++ b/ext/boost/date_time/date_iterator.hpp @@ -0,0 +1,101 @@ +#ifndef DATE_ITERATOR_HPP___ +#define DATE_ITERATOR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include <iterator> + +namespace boost { +namespace date_time { + //! An iterator over dates with varying resolution (day, week, month, year, etc) + enum date_resolutions {day, week, months, year, decade, century, NumDateResolutions}; + + //! Base date iterator type + /*! This class provides the skeleton for the creation of iterators. + * New and interesting interators can be created by plugging in a new + * function that derives the next value from the current state. + * generation of various types of -based information. + * + * <b>Template Parameters</b> + * + * <b>date_type</b> + * + * The date_type is a concrete date_type. The date_type must + * define a duration_type and a calendar_type. + */ + template<class date_type> + class date_itr_base { + // works, but benefit unclear at the moment + // class date_itr_base : public std::iterator<std::input_iterator_tag, + // date_type, void, void, void>{ + public: + typedef typename date_type::duration_type duration_type; + typedef date_type value_type; + typedef std::input_iterator_tag iterator_category; + + date_itr_base(date_type d) : current_(d) {} + virtual ~date_itr_base() {}; + date_itr_base& operator++() + { + current_ = current_ + get_offset(current_); + return *this; + } + date_itr_base& operator--() + { + current_ = current_ + get_neg_offset(current_); + return *this; + } + virtual duration_type get_offset(const date_type& current) const=0; + virtual duration_type get_neg_offset(const date_type& current) const=0; + date_type operator*() {return current_;}; + date_type* operator->() {return ¤t_;}; + bool operator< (const date_type& d) {return current_ < d;} + bool operator<= (const date_type& d) {return current_ <= d;} + bool operator> (const date_type& d) {return current_ > d;} + bool operator>= (const date_type& d) {return current_ >= d;} + bool operator== (const date_type& d) {return current_ == d;} + bool operator!= (const date_type& d) {return current_ != d;} + private: + date_type current_; + }; + + //! Overrides the base date iterator providing hook for functors + /* + * <b>offset_functor</b> + * + * The offset functor must define a get_offset function that takes the + * current point in time and calculates and offset. + * + */ + template<class offset_functor, class date_type> + class date_itr : public date_itr_base<date_type> { + public: + typedef typename date_type::duration_type duration_type; + date_itr(date_type d, int factor=1) : + date_itr_base<date_type>(d), + of_(factor) + {} + private: + virtual duration_type get_offset(const date_type& current) const + { + return of_.get_offset(current); + } + virtual duration_type get_neg_offset(const date_type& current) const + { + return of_.get_neg_offset(current); + } + offset_functor of_; + }; + + + +} } //namespace date_time + + +#endif diff --git a/ext/boost/date_time/date_names_put.hpp b/ext/boost/date_time/date_names_put.hpp new file mode 100644 index 0000000000..c6f0ce2a6f --- /dev/null +++ b/ext/boost/date_time/date_names_put.hpp @@ -0,0 +1,320 @@ +#ifndef DATE_TIME_DATE_NAMES_PUT_HPP___ +#define DATE_TIME_DATE_NAMES_PUT_HPP___ + +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/locale_config.hpp" // set BOOST_DATE_TIME_NO_LOCALE + +#ifndef BOOST_DATE_TIME_NO_LOCALE + +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/date_defs.hpp" +#include "boost/date_time/parse_format_base.hpp" +#include "boost/lexical_cast.hpp" +#include <locale> + + +namespace boost { +namespace date_time { + + //! Output facet base class for gregorian dates. + /*! This class is a base class for date facets used to localize the + * names of months and the names of days in the week. + * + * Requirements of Config + * - define an enumeration month_enum that enumerates the months. + * The enumeration should be '1' based eg: Jan==1 + * - define as_short_string and as_long_string + * + * (see langer & kreft p334). + * + */ + template<class Config, + class charT = char, + class OutputIterator = std::ostreambuf_iterator<charT> > + class date_names_put : public std::locale::facet + { + public: + date_names_put() {}; + typedef OutputIterator iter_type; + typedef typename Config::month_type month_type; + typedef typename Config::month_enum month_enum; + typedef typename Config::weekday_enum weekday_enum; + typedef typename Config::special_value_enum special_value_enum; + //typedef typename Config::format_type format_type; + typedef std::basic_string<charT> string_type; + typedef charT char_type; + static const char_type default_special_value_names[3][17]; + static const char_type separator[2]; + + static std::locale::id id; + +#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) + std::locale::id& __get_id (void) const { return id; } +#endif + + void put_special_value(iter_type& oitr, special_value_enum sv) const + { + do_put_special_value(oitr, sv); + } + void put_month_short(iter_type& oitr, month_enum moy) const + { + do_put_month_short(oitr, moy); + } + void put_month_long(iter_type& oitr, month_enum moy) const + { + do_put_month_long(oitr, moy); + } + void put_weekday_short(iter_type& oitr, weekday_enum wd) const + { + do_put_weekday_short(oitr, wd); + } + void put_weekday_long(iter_type& oitr, weekday_enum wd) const + { + do_put_weekday_long(oitr, wd); + } + bool has_date_sep_chars() const + { + return do_has_date_sep_chars(); + } + void year_sep_char(iter_type& oitr) const + { + do_year_sep_char(oitr); + } + //! char between year-month + void month_sep_char(iter_type& oitr) const + { + do_month_sep_char(oitr); + } + //! Char to separate month-day + void day_sep_char(iter_type& oitr) const + { + do_day_sep_char(oitr); + } + //! Determines the order to put the date elements + ymd_order_spec date_order() const + { + return do_date_order(); + } + //! Determines if month is displayed as integer, short or long string + month_format_spec month_format() const + { + return do_month_format(); + } + + protected: + //! Default facet implementation uses month_type defaults + virtual void do_put_month_short(iter_type& oitr, month_enum moy) const + { + month_type gm(moy); + charT c = '\0'; + put_string(oitr, gm.as_short_string(c)); + } + //! Default facet implementation uses month_type defaults + virtual void do_put_month_long(iter_type& oitr, + month_enum moy) const + { + month_type gm(moy); + charT c = '\0'; + put_string(oitr, gm.as_long_string(c)); + } + //! Default facet implementation for special value types + virtual void do_put_special_value(iter_type& oitr, special_value_enum sv) const + { + if(sv <= 2) { // only output not_a_date_time, neg_infin, or pos_infin + string_type s(default_special_value_names[sv]); + put_string(oitr, s); + } + } + virtual void do_put_weekday_short(iter_type&, weekday_enum) const + { + } + virtual void do_put_weekday_long(iter_type&, weekday_enum) const + { + } + virtual bool do_has_date_sep_chars() const + { + return true; + } + virtual void do_year_sep_char(iter_type& oitr) const + { + string_type s(separator); + put_string(oitr, s); + } + //! char between year-month + virtual void do_month_sep_char(iter_type& oitr) const + { + string_type s(separator); + put_string(oitr, s); + } + //! Char to separate month-day + virtual void do_day_sep_char(iter_type& oitr) const + { + string_type s(separator); //put in '-' + put_string(oitr, s); + } + //! Default for date order + virtual ymd_order_spec do_date_order() const + { + return ymd_order_iso; + } + //! Default month format + virtual month_format_spec do_month_format() const + { + return month_as_short_string; + } + void put_string(iter_type& oi, const charT* const s) const + { + string_type s1(boost::lexical_cast<string_type>(s)); + typename string_type::iterator si,end; + for (si=s1.begin(), end=s1.end(); si!=end; si++, oi++) { + *oi = *si; + } + } + void put_string(iter_type& oi, const string_type& s1) const + { + typename string_type::const_iterator si,end; + for (si=s1.begin(), end=s1.end(); si!=end; si++, oi++) { + *oi = *si; + } + } + }; + + template<class Config, class charT, class OutputIterator> + const typename date_names_put<Config, charT, OutputIterator>::char_type + date_names_put<Config, charT, OutputIterator>::default_special_value_names[3][17] = { + {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}, + {'-','i','n','f','i','n','i','t','y'}, + {'+','i','n','f','i','n','i','t','y'} }; + + template<class Config, class charT, class OutputIterator> + const typename date_names_put<Config, charT, OutputIterator>::char_type + date_names_put<Config, charT, OutputIterator>::separator[2] = + {'-', '\0'} ; + + + //! Generate storage location for a std::locale::id + template<class Config, class charT, class OutputIterator> + std::locale::id date_names_put<Config, charT, OutputIterator>::id; + + //! A date name output facet that takes an array of char* to define strings + template<class Config, + class charT = char, + class OutputIterator = std::ostreambuf_iterator<charT> > + class all_date_names_put : public date_names_put<Config, charT, OutputIterator> + { + public: + all_date_names_put(const charT* const month_short_names[], + const charT* const month_long_names[], + const charT* const special_value_names[], + const charT* const weekday_short_names[], + const charT* const weekday_long_names[], + charT separator_char = '-', + ymd_order_spec order_spec = ymd_order_iso, + month_format_spec month_format = month_as_short_string) : + month_short_names_(month_short_names), + month_long_names_(month_long_names), + special_value_names_(special_value_names), + weekday_short_names_(weekday_short_names), + weekday_long_names_(weekday_long_names), + order_spec_(order_spec), + month_format_spec_(month_format) + { + separator_char_[0] = separator_char; + separator_char_[1] = '\0'; + + }; + typedef OutputIterator iter_type; + typedef typename Config::month_enum month_enum; + typedef typename Config::weekday_enum weekday_enum; + typedef typename Config::special_value_enum special_value_enum; + + const charT* const* get_short_month_names() const + { + return month_short_names_; + } + const charT* const* get_long_month_names() const + { + return month_long_names_; + } + const charT* const* get_special_value_names() const + { + return special_value_names_; + } + const charT* const* get_short_weekday_names()const + { + return weekday_short_names_; + } + const charT* const* get_long_weekday_names()const + { + return weekday_long_names_; + } + + protected: + //! Generic facet that takes array of chars + virtual void do_put_month_short(iter_type& oitr, month_enum moy) const + { + this->put_string(oitr, month_short_names_[moy-1]); + } + //! Long month names + virtual void do_put_month_long(iter_type& oitr, month_enum moy) const + { + this->put_string(oitr, month_long_names_[moy-1]); + } + //! Special values names + virtual void do_put_special_value(iter_type& oitr, special_value_enum sv) const + { + this->put_string(oitr, special_value_names_[sv]); + } + virtual void do_put_weekday_short(iter_type& oitr, weekday_enum wd) const + { + this->put_string(oitr, weekday_short_names_[wd]); + } + virtual void do_put_weekday_long(iter_type& oitr, weekday_enum wd) const + { + this->put_string(oitr, weekday_long_names_[wd]); + } + //! char between year-month + virtual void do_month_sep_char(iter_type& oitr) const + { + this->put_string(oitr, separator_char_); + } + //! Char to separate month-day + virtual void do_day_sep_char(iter_type& oitr) const + { + this->put_string(oitr, separator_char_); + } + //! Set the date ordering + virtual ymd_order_spec do_date_order() const + { + return order_spec_; + } + //! Set the date ordering + virtual month_format_spec do_month_format() const + { + return month_format_spec_; + } + + private: + const charT* const* month_short_names_; + const charT* const* month_long_names_; + const charT* const* special_value_names_; + const charT* const* weekday_short_names_; + const charT* const* weekday_long_names_; + charT separator_char_[2]; + ymd_order_spec order_spec_; + month_format_spec month_format_spec_; + }; + +} } //namespace boost::date_time + +#endif //BOOST_NO_STD_LOCALE + +#endif diff --git a/ext/boost/date_time/date_parsing.hpp b/ext/boost/date_time/date_parsing.hpp new file mode 100644 index 0000000000..f361bc8096 --- /dev/null +++ b/ext/boost/date_time/date_parsing.hpp @@ -0,0 +1,316 @@ +#ifndef _DATE_TIME_DATE_PARSING_HPP___ +#define _DATE_TIME_DATE_PARSING_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 04:24:49 -0400 (Thu, 04 Jun 2009) $ + */ + +#include <string> +#include <iterator> +#include <algorithm> +#include <boost/tokenizer.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/parse_format_base.hpp> + +#if defined(BOOST_DATE_TIME_NO_LOCALE) +#include <cctype> // ::tolower(int) +#else +#include <locale> // std::tolower(char, locale) +#endif + +namespace boost { +namespace date_time { + + //! A function to replace the std::transform( , , ,tolower) construct + /*! This function simply takes a string, and changes all the characters + * in that string to lowercase (according to the default system locale). + * In the event that a compiler does not support locales, the old + * C style tolower() is used. + */ + inline + std::string + convert_to_lower(std::string inp) + { +#if !defined(BOOST_DATE_TIME_NO_LOCALE) + const std::locale loc(std::locale::classic()); +#endif + std::string::size_type i = 0, n = inp.length(); + for (; i < n; ++i) { + inp[i] = +#if defined(BOOST_DATE_TIME_NO_LOCALE) + static_cast<char>(std::tolower(inp[i])); +#else + // tolower and others were brought in to std for borland >= v564 + // in compiler_config.hpp + std::tolower(inp[i], loc); +#endif + } + return inp; + } + + //! Helper function for parse_date. + /* Used by-value parameter because we change the string and may + * want to preserve the original argument */ + template<class month_type> + inline unsigned short + month_str_to_ushort(std::string const& s) { + if((s.at(0) >= '0') && (s.at(0) <= '9')) { + return boost::lexical_cast<unsigned short>(s); + } + else { + std::string str = convert_to_lower(s); + typename month_type::month_map_ptr_type ptr = month_type::get_month_map_ptr(); + typename month_type::month_map_type::iterator iter = ptr->find(str); + if(iter != ptr->end()) { // required for STLport + return iter->second; + } + } + return 13; // intentionally out of range - name not found + } + + //! Find index of a string in either of 2 arrays + /*! find_match searches both arrays for a match to 's'. Both arrays + * must contain 'size' elements. The index of the match is returned. + * If no match is found, 'size' is returned. + * Ex. "Jan" returns 0, "Dec" returns 11, "Tue" returns 2. + * 'size' can be sent in with: (greg_month::max)() (which 12), + * (greg_weekday::max)() + 1 (which is 7) or date_time::NumSpecialValues */ + template<class charT> + short find_match(const charT* const* short_names, + const charT* const* long_names, + short size, + const std::basic_string<charT>& s) { + for(short i = 0; i < size; ++i){ + if(short_names[i] == s || long_names[i] == s){ + return i; + } + } + return size; // not-found, return a value out of range + } + + //! Generic function to parse a delimited date (eg: 2002-02-10) + /*! Accepted formats are: "2003-02-10" or " 2003-Feb-10" or + * "2003-Feburary-10" + * The order in which the Month, Day, & Year appear in the argument + * string can be accomodated by passing in the appropriate ymd_order_spec + */ + template<class date_type> + date_type + parse_date(const std::string& s, int order_spec = ymd_order_iso) { + std::string spec_str; + if(order_spec == ymd_order_iso) { + spec_str = "ymd"; + } + else if(order_spec == ymd_order_dmy) { + spec_str = "dmy"; + } + else { // (order_spec == ymd_order_us) + spec_str = "mdy"; + } + + typedef typename date_type::year_type year_type; + typedef typename date_type::month_type month_type; + unsigned pos = 0; + unsigned short year(0), month(0), day(0); + typedef typename std::basic_string<char>::traits_type traits_type; + typedef boost::char_separator<char, traits_type> char_separator_type; + typedef boost::tokenizer<char_separator_type, + std::basic_string<char>::const_iterator, + std::basic_string<char> > tokenizer; + typedef boost::tokenizer<char_separator_type, + std::basic_string<char>::const_iterator, + std::basic_string<char> >::iterator tokenizer_iterator; + // may need more delimiters, these work for the regression tests + const char sep_char[] = {',','-','.',' ','/','\0'}; + char_separator_type sep(sep_char); + tokenizer tok(s,sep); + for(tokenizer_iterator beg=tok.begin(); + beg!=tok.end() && pos < spec_str.size(); + ++beg, ++pos) { + switch(spec_str.at(pos)) { + case 'y': + { + year = boost::lexical_cast<unsigned short>(*beg); + break; + } + case 'm': + { + month = month_str_to_ushort<month_type>(*beg); + break; + } + case 'd': + { + day = boost::lexical_cast<unsigned short>(*beg); + break; + } + } //switch + } + return date_type(year, month, day); + } + + //! Generic function to parse undelimited date (eg: 20020201) + template<class date_type> + date_type + parse_undelimited_date(const std::string& s) { + int offsets[] = {4,2,2}; + int pos = 0; + typedef typename date_type::year_type year_type; + //typename date_type::ymd_type ymd((year_type::min)(),1,1); + unsigned short y = 0, m = 0, d = 0; + + /* The two bool arguments state that parsing will not wrap + * (only the first 8 characters will be parsed) and partial + * strings will not be parsed. + * Ex: + * "2005121" will parse 2005 & 12, but not the "1" */ + boost::offset_separator osf(offsets, offsets+3, false, false); + + typedef typename boost::tokenizer<boost::offset_separator, + std::basic_string<char>::const_iterator, + std::basic_string<char> > tokenizer_type; + tokenizer_type tok(s, osf); + for(typename tokenizer_type::iterator ti=tok.begin(); ti!=tok.end();++ti) { + unsigned short i = boost::lexical_cast<unsigned short>(*ti); + switch(pos) { + case 0: y = i; break; + case 1: m = i; break; + case 2: d = i; break; + } + pos++; + } + return date_type(y,m,d); + } + + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the iterators that reference the + * begining & end of a char[] or string. All elements are + * used in output string */ + template<class date_type, class iterator_type> + inline + date_type + from_stream_type(iterator_type& beg, + iterator_type const& end, + char) + { + std::ostringstream ss; + while(beg != end) { + ss << *beg++; + } + return parse_date<date_type>(ss.str()); + } + + //! Helper function for 'date gregorian::from_stream()' + /*! Returns the first string found in the stream referenced by the + * begining & end iterators */ + template<class date_type, class iterator_type> + inline + date_type + from_stream_type(iterator_type& beg, + iterator_type const& /* end */, + std::string const&) + { + return parse_date<date_type>(*beg); + } + + /* I believe the wchar stuff would be best elsewhere, perhaps in + * parse_date<>()? In the mean time this gets us started... */ + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the iterators that reference the + * begining & end of a wstring. All elements are + * used in output string */ + template<class date_type, class iterator_type> + inline + date_type from_stream_type(iterator_type& beg, + iterator_type const& end, + wchar_t) + { + std::ostringstream ss; +#if !defined(BOOST_DATE_TIME_NO_LOCALE) + std::locale loc; + std::ctype<wchar_t> const& fac = std::use_facet<std::ctype<wchar_t> >(loc); + while(beg != end) { + ss << fac.narrow(*beg++, 'X'); // 'X' will cause exception to be thrown + } +#else + while(beg != end) { + char c = 'X'; // 'X' will cause exception to be thrown + const wchar_t wc = *beg++; + if (wc >= 0 && wc <= 127) + c = static_cast< char >(wc); + ss << c; + } +#endif + return parse_date<date_type>(ss.str()); + } +#ifndef BOOST_NO_STD_WSTRING + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the first wstring found in the stream + * referenced by the begining & end iterators */ + template<class date_type, class iterator_type> + inline + date_type + from_stream_type(iterator_type& beg, + iterator_type const& /* end */, + std::wstring const&) { + std::wstring ws = *beg; + std::ostringstream ss; + std::wstring::iterator wsb = ws.begin(), wse = ws.end(); +#if !defined(BOOST_DATE_TIME_NO_LOCALE) + std::locale loc; + std::ctype<wchar_t> const& fac = std::use_facet<std::ctype<wchar_t> >(loc); + while(wsb != wse) { + ss << fac.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown + } +#else + while(wsb != wse) { + char c = 'X'; // 'X' will cause exception to be thrown + const wchar_t wc = *wsb++; + if (wc >= 0 && wc <= 127) + c = static_cast< char >(wc); + ss << c; + } +#endif + return parse_date<date_type>(ss.str()); + } +#endif // BOOST_NO_STD_WSTRING +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings +#else + //! function called by wrapper functions: date_period_from_(w)string() + template<class date_type, class charT> + period<date_type, typename date_type::duration_type> + from_simple_string_type(const std::basic_string<charT>& s){ + typedef typename std::basic_string<charT>::traits_type traits_type; + typedef typename boost::char_separator<charT, traits_type> char_separator; + typedef typename boost::tokenizer<char_separator, + typename std::basic_string<charT>::const_iterator, + std::basic_string<charT> > tokenizer; + const charT sep_list[4] = {'[','/',']','\0'}; + char_separator sep(sep_list); + tokenizer tokens(s, sep); + typename tokenizer::iterator tok_it = tokens.begin(); + std::basic_string<charT> date_string = *tok_it; + // get 2 string iterators and generate a date from them + typename std::basic_string<charT>::iterator date_string_start = date_string.begin(), + date_string_end = date_string.end(); + typedef typename std::iterator_traits<typename std::basic_string<charT>::iterator>::value_type value_type; + date_type d1 = from_stream_type<date_type>(date_string_start, date_string_end, value_type()); + date_string = *(++tok_it); // next token + date_string_start = date_string.begin(), date_string_end = date_string.end(); + date_type d2 = from_stream_type<date_type>(date_string_start, date_string_end, value_type()); + return period<date_type, typename date_type::duration_type>(d1, d2); + } +#endif + +} } //namespace date_time + + + + +#endif + diff --git a/ext/boost/date_time/dst_rules.hpp b/ext/boost/date_time/dst_rules.hpp new file mode 100644 index 0000000000..20cb40b676 --- /dev/null +++ b/ext/boost/date_time/dst_rules.hpp @@ -0,0 +1,391 @@ +#ifndef DATE_TIME_DST_RULES_HPP__ +#define DATE_TIME_DST_RULES_HPP__ + +/* Copyright (c) 2002,2003, 2007 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file dst_rules.hpp + Contains template class to provide static dst rule calculations +*/ + +#include "boost/date_time/date_generators.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/date_defs.hpp" +#include <stdexcept> + +namespace boost { + namespace date_time { + + enum time_is_dst_result {is_not_in_dst, is_in_dst, + ambiguous, invalid_time_label}; + + + //! Dynamic class used to caluclate dst transition information + template<class date_type_, + class time_duration_type_> + class dst_calculator + { + public: + typedef time_duration_type_ time_duration_type; + typedef date_type_ date_type; + + //! Check the local time offset when on dst start day + /*! On this dst transition, the time label between + * the transition boundary and the boudary + the offset + * are invalid times. If before the boundary then still + * not in dst. + *@param time_of_day Time offset in the day for the local time + *@param dst_start_offset_minutes Local day offset for start of dst + *@param dst_length_minutes Number of minutes to adjust clock forward + *@retval status of time label w.r.t. dst + */ + static time_is_dst_result + process_local_dst_start_day(const time_duration_type& time_of_day, + unsigned int dst_start_offset_minutes, + long dst_length_minutes) + { + //std::cout << "here" << std::endl; + if (time_of_day < time_duration_type(0,dst_start_offset_minutes,0)) { + return is_not_in_dst; + } + long offset = dst_start_offset_minutes + dst_length_minutes; + if (time_of_day >= time_duration_type(0,offset,0)) { + return is_in_dst; + } + return invalid_time_label; + } + + //! Check the local time offset when on the last day of dst + /*! This is the calculation for the DST end day. On that day times + * prior to the conversion time - dst_length (1 am in US) are still + * in dst. Times between the above and the switch time are + * ambiguous. Times after the start_offset are not in dst. + *@param time_of_day Time offset in the day for the local time + *@param dst_end_offset_minutes Local time of day for end of dst + *@retval status of time label w.r.t. dst + */ + static time_is_dst_result + process_local_dst_end_day(const time_duration_type& time_of_day, + unsigned int dst_end_offset_minutes, + long dst_length_minutes) + { + //in US this will be 60 so offset in day is 1,0,0 + int offset = dst_end_offset_minutes-dst_length_minutes; + if (time_of_day < time_duration_type(0,offset,0)) { + return is_in_dst; + } + if (time_of_day >= time_duration_type(0,dst_end_offset_minutes,0)) { + return is_not_in_dst; + } + return ambiguous; + } + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @param current_day The day to check for dst + * @param time_of_day Time offset within the day to check + * @param dst_start_day Starting day of dst for the given locality + * @param dst_start_offset Time offset within day for dst boundary + * @param dst_end_day Ending day of dst for the given locality + * @param dst_end_offset Time offset within day given in dst for dst boundary + * @param dst_length lenght of dst adjusment + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result + local_is_dst(const date_type& current_day, + const time_duration_type& time_of_day, + const date_type& dst_start_day, + const time_duration_type& dst_start_offset, + const date_type& dst_end_day, + const time_duration_type& dst_end_offset, + const time_duration_type& dst_length_minutes) + { + unsigned int start_minutes = + dst_start_offset.hours() * 60 + dst_start_offset.minutes(); + unsigned int end_minutes = + dst_end_offset.hours() * 60 + dst_end_offset.minutes(); + long length_minutes = + dst_length_minutes.hours() * 60 + dst_length_minutes.minutes(); + + return local_is_dst(current_day, time_of_day, + dst_start_day, start_minutes, + dst_end_day, end_minutes, + length_minutes); + } + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @param current_day The day to check for dst + * @param time_of_day Time offset within the day to check + * @param dst_start_day Starting day of dst for the given locality + * @param dst_start_offset_minutes Offset within day for dst + * boundary (eg 120 for US which is 02:00:00) + * @param dst_end_day Ending day of dst for the given locality + * @param dst_end_offset_minutes Offset within day given in dst for dst + * boundary (eg 120 for US which is 02:00:00) + * @param dst_length_minutes Length of dst adjusment (eg: 60 for US) + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result + local_is_dst(const date_type& current_day, + const time_duration_type& time_of_day, + const date_type& dst_start_day, + unsigned int dst_start_offset_minutes, + const date_type& dst_end_day, + unsigned int dst_end_offset_minutes, + long dst_length_minutes) + { + //in northern hemisphere dst is in the middle of the year + if (dst_start_day < dst_end_day) { + if ((current_day > dst_start_day) && (current_day < dst_end_day)) { + return is_in_dst; + } + if ((current_day < dst_start_day) || (current_day > dst_end_day)) { + return is_not_in_dst; + } + } + else {//southern hemisphere dst is at begining /end of year + if ((current_day < dst_start_day) && (current_day > dst_end_day)) { + return is_not_in_dst; + } + if ((current_day > dst_start_day) || (current_day < dst_end_day)) { + return is_in_dst; + } + } + + if (current_day == dst_start_day) { + return process_local_dst_start_day(time_of_day, + dst_start_offset_minutes, + dst_length_minutes); + } + + if (current_day == dst_end_day) { + return process_local_dst_end_day(time_of_day, + dst_end_offset_minutes, + dst_length_minutes); + } + //you should never reach this statement + return invalid_time_label; + } + + }; + + + //! Compile-time configurable daylight savings time calculation engine + /* This template provides the ability to configure a daylight savings + * calculation at compile time covering all the cases. Unfortunately + * because of the number of dimensions related to daylight savings + * calculation the number of parameters is high. In addition, the + * start and end transition rules are complex types that specify + * an algorithm for calculation of the starting day and ending + * day of daylight savings time including the month and day + * specifications (eg: last sunday in October). + * + * @param date_type A type that represents dates, typically gregorian::date + * @param time_duration_type Used for the offset in the day calculations + * @param dst_traits A set of traits that define the rules of dst + * calculation. The dst_trait must include the following: + * start_rule_functor - Rule to calculate the starting date of a + * dst transition (eg: last_kday_of_month). + * start_day - static function that returns month of dst start for + * start_rule_functor + * start_month -static function that returns day or day of week for + * dst start of dst + * end_rule_functor - Rule to calculate the end of dst day. + * end_day - static fucntion that returns end day for end_rule_functor + * end_month - static function that returns end month for end_rule_functor + * dst_start_offset_minutes - number of minutes from start of day to transition to dst -- 120 (or 2:00 am) is typical for the U.S. and E.U. + * dst_start_offset_minutes - number of minutes from start of day to transition off of dst -- 180 (or 3:00 am) is typical for E.U. + * dst_length_minutes - number of minutes that dst shifts clock + */ + template<class date_type, + class time_duration_type, + class dst_traits> + class dst_calc_engine + { + public: + typedef typename date_type::year_type year_type; + typedef typename date_type::calendar_type calendar_type; + typedef dst_calculator<date_type, time_duration_type> dstcalc; + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result local_is_dst(const date_type& d, + const time_duration_type& td) + { + + year_type y = d.year(); + date_type dst_start = local_dst_start_day(y); + date_type dst_end = local_dst_end_day(y); + return dstcalc::local_is_dst(d,td, + dst_start, + dst_traits::dst_start_offset_minutes(), + dst_end, + dst_traits::dst_end_offset_minutes(), + dst_traits::dst_shift_length_minutes()); + + } + + static bool is_dst_boundary_day(date_type d) + { + year_type y = d.year(); + return ((d == local_dst_start_day(y)) || + (d == local_dst_end_day(y))); + } + + //! The time of day for the dst transition (eg: typically 01:00:00 or 02:00:00) + static time_duration_type dst_offset() + { + return time_duration_type(0,dst_traits::dst_shift_length_minutes(),0); + } + + static date_type local_dst_start_day(year_type year) + { + return dst_traits::local_dst_start_day(year); + } + + static date_type local_dst_end_day(year_type year) + { + return dst_traits::local_dst_end_day(year); + } + + + }; + + //! Depricated: Class to calculate dst boundaries for US time zones + /* Use dst_calc_engine instead. + * In 2007 US/Canada DST rules changed + * (http://en.wikipedia.org/wiki/Energy_Policy_Act_of_2005#Change_to_daylight_saving_time). + */ + template<class date_type_, + class time_duration_type_, + unsigned int dst_start_offset_minutes=120, //from start of day + short dst_length_minutes=60> //1 hour == 60 min in US + class us_dst_rules + { + public: + typedef time_duration_type_ time_duration_type; + typedef date_type_ date_type; + typedef typename date_type::year_type year_type; + typedef typename date_type::calendar_type calendar_type; + typedef date_time::last_kday_of_month<date_type> lkday; + typedef date_time::first_kday_of_month<date_type> fkday; + typedef date_time::nth_kday_of_month<date_type> nkday; + typedef dst_calculator<date_type, time_duration_type> dstcalc; + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result local_is_dst(const date_type& d, + const time_duration_type& td) + { + + year_type y = d.year(); + date_type dst_start = local_dst_start_day(y); + date_type dst_end = local_dst_end_day(y); + return dstcalc::local_is_dst(d,td, + dst_start,dst_start_offset_minutes, + dst_end, dst_start_offset_minutes, + dst_length_minutes); + + } + + + static bool is_dst_boundary_day(date_type d) + { + year_type y = d.year(); + return ((d == local_dst_start_day(y)) || + (d == local_dst_end_day(y))); + } + + static date_type local_dst_start_day(year_type year) + { + if (year >= year_type(2007)) { + //second sunday in march + nkday ssim(nkday::second, Sunday, gregorian::Mar); + return ssim.get_date(year); + } else { + //first sunday in april + fkday fsia(Sunday, gregorian::Apr); + return fsia.get_date(year); + } + } + + static date_type local_dst_end_day(year_type year) + { + if (year >= year_type(2007)) { + //first sunday in november + fkday fsin(Sunday, gregorian::Nov); + return fsin.get_date(year); + } else { + //last sunday in october + lkday lsio(Sunday, gregorian::Oct); + return lsio.get_date(year); + } + } + + static time_duration_type dst_offset() + { + return time_duration_type(0,dst_length_minutes,0); + } + + private: + + + }; + + //! Used for local time adjustments in places that don't use dst + template<class date_type_, class time_duration_type_> + class null_dst_rules + { + public: + typedef time_duration_type_ time_duration_type; + typedef date_type_ date_type; + + + //! Calculates if the given local time is dst or not + /*! @retval Always is_not_in_dst since this is for zones without dst + */ + static time_is_dst_result local_is_dst(const date_type&, + const time_duration_type&) + { + return is_not_in_dst; + } + + //! Calculates if the given utc time is in dst + static time_is_dst_result utc_is_dst(const date_type&, + const time_duration_type&) + { + return is_not_in_dst; + } + + static bool is_dst_boundary_day(date_type d) + { + return false; + } + + static time_duration_type dst_offset() + { + return time_duration_type(0,0,0); + } + + }; + + + } } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/dst_transition_generators.hpp b/ext/boost/date_time/dst_transition_generators.hpp new file mode 100644 index 0000000000..6c4da1c3c9 --- /dev/null +++ b/ext/boost/date_time/dst_transition_generators.hpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + */ +#ifndef DATE_TIME_DATE_DST_TRANSITION_DAY_GEN_HPP__ +#define DATE_TIME_DATE_DST_TRANSITION_DAY_GEN_HPP__ + + + +namespace boost { +namespace date_time { + + //! Defines base interface for calculating start and end date of daylight savings + template<class date_type> + class dst_day_calc_rule + { + public: + typedef typename date_type::year_type year_type; + virtual ~dst_day_calc_rule() {}; + virtual date_type start_day(year_type y) const=0; + virtual std::string start_rule_as_string() const=0; + virtual date_type end_day(year_type y) const=0; + virtual std::string end_rule_as_string() const=0; + + }; + + //! Canonical form for a class that provides day rule calculation + /*! This class is used to generate specific sets of dst rules + * + *@param spec Provides a specifiction of the function object types used + * to generate start and end days of daylight savings as well + * as the date type. + */ + template<class spec> + class day_calc_dst_rule : public dst_day_calc_rule<typename spec::date_type> + { + public: + typedef typename spec::date_type date_type; + typedef typename date_type::year_type year_type; + typedef typename spec::start_rule start_rule; + typedef typename spec::end_rule end_rule; + day_calc_dst_rule(start_rule dst_start, + end_rule dst_end) : + dst_start_(dst_start), + dst_end_(dst_end) + {} + virtual date_type start_day(year_type y) const + { + return dst_start_.get_date(y); + } + virtual std::string start_rule_as_string() const + { + return dst_start_.to_string(); + } + virtual date_type end_day(year_type y) const + { + return dst_end_.get_date(y); + } + virtual std::string end_rule_as_string() const + { + return dst_end_.to_string(); + } + private: + start_rule dst_start_; + end_rule dst_end_; + }; + + +} }//namespace + + + +#endif diff --git a/ext/boost/date_time/filetime_functions.hpp b/ext/boost/date_time/filetime_functions.hpp new file mode 100644 index 0000000000..27ed754f74 --- /dev/null +++ b/ext/boost/date_time/filetime_functions.hpp @@ -0,0 +1,170 @@ +#ifndef DATE_TIME_FILETIME_FUNCTIONS_HPP__ +#define DATE_TIME_FILETIME_FUNCTIONS_HPP__ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-06 07:24:09 -0400 (Sat, 06 Jun 2009) $ + */ + +/*! @file filetime_functions.hpp + * Function(s) for converting between a FILETIME structure and a + * time object. This file is only available on systems that have + * BOOST_HAS_FTIME defined. + */ + +#include <boost/date_time/compiler_config.hpp> + +#if defined(BOOST_HAS_FTIME) // skip this file if no FILETIME + +#if defined(BOOST_USE_WINDOWS_H) +# include <windows.h> +#endif + +#include <boost/cstdint.hpp> +#include <boost/date_time/time.hpp> +#include <boost/date_time/date_defs.hpp> + +namespace boost { + +namespace date_time { + +namespace winapi { + +#if !defined(BOOST_USE_WINDOWS_H) + + extern "C" { + + struct FILETIME + { + boost::uint32_t dwLowDateTime; + boost::uint32_t dwHighDateTime; + }; + struct SYSTEMTIME + { + boost::uint16_t wYear; + boost::uint16_t wMonth; + boost::uint16_t wDayOfWeek; + boost::uint16_t wDay; + boost::uint16_t wHour; + boost::uint16_t wMinute; + boost::uint16_t wSecond; + boost::uint16_t wMilliseconds; + }; + + __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(FILETIME* lpFileTime); + __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const FILETIME* lpFileTime, FILETIME* lpLocalFileTime); + __declspec(dllimport) void __stdcall GetSystemTime(SYSTEMTIME* lpSystemTime); + __declspec(dllimport) int __stdcall SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, FILETIME* lpFileTime); + + } // extern "C" + +#endif // defined(BOOST_USE_WINDOWS_H) + + typedef FILETIME file_time; + typedef SYSTEMTIME system_time; + + inline void get_system_time_as_file_time(file_time& ft) + { +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + // Some runtime library implementations expect local times as the norm for ctime. + file_time ft_utc; + GetSystemTimeAsFileTime(&ft_utc); + FileTimeToLocalFileTime(&ft_utc, &ft); +#elif defined(BOOST_NO_GETSYSTEMTIMEASFILETIME) + system_time st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); +#else + GetSystemTimeAsFileTime(&ft); +#endif + } + + /*! + * The function converts file_time into number of microseconds elapsed since 1970-Jan-01 + * + * \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped. + * + * \note The function is templated on the FILETIME type, so that + * it can be used with both native FILETIME and the ad-hoc + * boost::date_time::winapi::file_time type. + */ + template< typename FileTimeT > + inline boost::uint64_t file_time_to_microseconds(FileTimeT const& ft) + { + /* shift is difference between 1970-Jan-01 & 1601-Jan-01 + * in 100-nanosecond intervals */ + const uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008 + + union { + FileTimeT as_file_time; + uint64_t as_integer; // 100-nanos since 1601-Jan-01 + } caster; + caster.as_file_time = ft; + + caster.as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01 + return (caster.as_integer / 10); // truncate to microseconds + } + +} // namespace winapi + +//! Create a time object from an initialized FILETIME struct. +/*! + * Create a time object from an initialized FILETIME struct. + * A FILETIME struct holds 100-nanosecond units (0.0000001). When + * built with microsecond resolution the file_time's sub second value + * will be truncated. Nanosecond resolution has no truncation. + * + * \note The function is templated on the FILETIME type, so that + * it can be used with both native FILETIME and the ad-hoc + * boost::date_time::winapi::file_time type. + */ +template< typename TimeT, typename FileTimeT > +inline +TimeT time_from_ftime(const FileTimeT& ft) +{ + typedef typename TimeT::date_type date_type; + typedef typename TimeT::date_duration_type date_duration_type; + typedef typename TimeT::time_duration_type time_duration_type; + + // https://svn.boost.org/trac/boost/ticket/2523 + // Since this function can be called with arbitrary times, including ones that + // are before 1970-Jan-01, we'll have to cast the time a bit differently, + // than it is done in the file_time_to_microseconds function. This allows to + // avoid integer wrapping for dates before 1970-Jan-01. + union { + FileTimeT as_file_time; + uint64_t as_integer; // 100-nanos since 1601-Jan-01 + } caster; + caster.as_file_time = ft; + + uint64_t sec = caster.as_integer / 10000000UL; + uint32_t sub_sec = (caster.as_integer % 10000000UL) // 100-nanoseconds since the last second +#if !defined(BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG) + / 10; // microseconds since the last second +#else + * 100; // nanoseconds since the last second +#endif + + // split sec into usable chunks: days, hours, minutes, & seconds + const uint32_t sec_per_day = 86400; // seconds per day + uint32_t days = static_cast< uint32_t >(sec / sec_per_day); + uint32_t tmp = static_cast< uint32_t >(sec % sec_per_day); + uint32_t hours = tmp / 3600; // sec_per_hour + tmp %= 3600; + uint32_t minutes = tmp / 60; // sec_per_min + tmp %= 60; + uint32_t seconds = tmp; // seconds + + date_duration_type dd(days); + date_type d = date_type(1601, Jan, 01) + dd; + return TimeT(d, time_duration_type(hours, minutes, seconds, sub_sec)); +} + +}} // boost::date_time + +#endif // BOOST_HAS_FTIME + +#endif // DATE_TIME_FILETIME_FUNCTIONS_HPP__ diff --git a/ext/boost/date_time/format_date_parser.hpp b/ext/boost/date_time/format_date_parser.hpp new file mode 100644 index 0000000000..a4a4d0dfbe --- /dev/null +++ b/ext/boost/date_time/format_date_parser.hpp @@ -0,0 +1,743 @@ + +#ifndef DATE_TIME_FORMAT_DATE_PARSER_HPP__ +#define DATE_TIME_FORMAT_DATE_PARSER_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 04:24:49 -0400 (Thu, 04 Jun 2009) $ + */ + + +#include "boost/lexical_cast.hpp" +#include "boost/date_time/string_parse_tree.hpp" +#include "boost/date_time/strings_from_facet.hpp" +#include "boost/date_time/special_values_parser.hpp" +#include <string> +#include <vector> +#include <sstream> +#include <iterator> +#ifndef BOOST_NO_STDC_NAMESPACE +# include <cctype> +#else +# include <ctype.h> +#endif + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { + using ::isspace; + using ::isdigit; +} +#endif +namespace boost { namespace date_time { + +//! Helper function for parsing fixed length strings into integers +/*! Will consume 'length' number of characters from stream. Consumed + * character are transfered to parse_match_result struct. + * Returns '-1' if no number can be parsed or incorrect number of + * digits in stream. */ +template<typename int_type, typename charT> +inline +int_type +fixed_string_to_int(std::istreambuf_iterator<charT>& itr, + std::istreambuf_iterator<charT>& stream_end, + parse_match_result<charT>& mr, + unsigned int length, + const charT& fill_char) +{ + //typedef std::basic_string<charT> string_type; + unsigned int j = 0; + //string_type s; + while (j < length && itr != stream_end && + (std::isdigit(*itr) || *itr == fill_char)) { + if(*itr == fill_char) { + /* Since a fill_char can be anything, we convert it to a zero. + * lexical_cast will behave predictably when zero is used as fill. */ + mr.cache += ('0'); + } + else { + mr.cache += (*itr); + } + itr++; + j++; + } + int_type i = -1; + // mr.cache will hold leading zeros. size() tells us when input is too short. + if(mr.cache.size() < length) { + return i; + } + try { + i = boost::lexical_cast<int_type>(mr.cache); + }catch(bad_lexical_cast&){ + // we want to return -1 if the cast fails so nothing to do here + } + return i; +} + +//! Helper function for parsing fixed length strings into integers +/*! Will consume 'length' number of characters from stream. Consumed + * character are transfered to parse_match_result struct. + * Returns '-1' if no number can be parsed or incorrect number of + * digits in stream. */ +template<typename int_type, typename charT> +inline +int_type +fixed_string_to_int(std::istreambuf_iterator<charT>& itr, + std::istreambuf_iterator<charT>& stream_end, + parse_match_result<charT>& mr, + unsigned int length) +{ + return fixed_string_to_int<int_type, charT>(itr, stream_end, mr, length, '0'); +} + +//! Helper function for parsing varied length strings into integers +/*! Will consume 'max_length' characters from stream only if those + * characters are digits. Returns '-1' if no number can be parsed. + * Will not parse a number preceeded by a '+' or '-'. */ +template<typename int_type, typename charT> +inline +int_type +var_string_to_int(std::istreambuf_iterator<charT>& itr, + const std::istreambuf_iterator<charT>& stream_end, + unsigned int max_length) +{ + typedef std::basic_string<charT> string_type; + unsigned int j = 0; + string_type s; + while (itr != stream_end && (j < max_length) && std::isdigit(*itr)) { + s += (*itr); + ++itr; + ++j; + } + int_type i = -1; + if(!s.empty()) { + i = boost::lexical_cast<int_type>(s); + } + return i; +} + + +//! Class with generic date parsing using a format string +/*! The following is the set of recognized format specifiers + - %a - Short weekday name + - %A - Long weekday name + - %b - Abbreviated month name + - %B - Full month name + - %d - Day of the month as decimal 01 to 31 + - %j - Day of year as decimal from 001 to 366 + - %m - Month name as a decimal 01 to 12 + - %U - Week number 00 to 53 with first Sunday as the first day of week 1? + - %w - Weekday as decimal number 0 to 6 where Sunday == 0 + - %W - Week number 00 to 53 where Monday is first day of week 1 + - %x - facet default date representation + - %y - Year without the century - eg: 04 for 2004 + - %Y - Year with century + + The weekday specifiers (%a and %A) do not add to the date construction, + but they provide a way to skip over the weekday names for formats that + provide them. + + todo -- Another interesting feature that this approach could provide is + an option to fill in any missing fields with the current values + from the clock. So if you have %m-%d the parser would detect + the missing year value and fill it in using the clock. + + todo -- What to do with the %x. %x in the classic facet is just bad... + + */ +template<class date_type, typename charT> +class format_date_parser +{ + public: + typedef std::basic_string<charT> string_type; + typedef std::basic_istringstream<charT> stringstream_type; + typedef std::istreambuf_iterator<charT> stream_itr_type; + typedef typename string_type::const_iterator const_itr; + typedef typename date_type::year_type year_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::duration_type duration_type; + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_of_year_type day_of_year_type; + typedef string_parse_tree<charT> parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector<std::basic_string<charT> > input_collection_type; + + // TODO sv_parser uses its default constructor - write the others + + format_date_parser(const string_type& format_str, + const input_collection_type& month_short_names, + const input_collection_type& month_long_names, + const input_collection_type& weekday_short_names, + const input_collection_type& weekday_long_names) : + m_format(format_str), + m_month_short_names(month_short_names, 1), + m_month_long_names(month_long_names, 1), + m_weekday_short_names(weekday_short_names), + m_weekday_long_names(weekday_long_names) + {} + + format_date_parser(const string_type& format_str, + const std::locale& locale) : + m_format(format_str), + m_month_short_names(gather_month_strings<charT>(locale), 1), + m_month_long_names(gather_month_strings<charT>(locale, false), 1), + m_weekday_short_names(gather_weekday_strings<charT>(locale)), + m_weekday_long_names(gather_weekday_strings<charT>(locale, false)) + {} + + format_date_parser(const format_date_parser<date_type,charT>& fdp) + { + this->m_format = fdp.m_format; + this->m_month_short_names = fdp.m_month_short_names; + this->m_month_long_names = fdp.m_month_long_names; + this->m_weekday_short_names = fdp.m_weekday_short_names; + this->m_weekday_long_names = fdp.m_weekday_long_names; + } + + string_type format() const + { + return m_format; + } + + void format(string_type format_str) + { + m_format = format_str; + } + + void short_month_names(const input_collection_type& month_names) + { + m_month_short_names = parse_tree_type(month_names, 1); + } + void long_month_names(const input_collection_type& month_names) + { + m_month_long_names = parse_tree_type(month_names, 1); + } + void short_weekday_names(const input_collection_type& weekday_names) + { + m_weekday_short_names = parse_tree_type(weekday_names); + } + void long_weekday_names(const input_collection_type& weekday_names) + { + m_weekday_long_names = parse_tree_type(weekday_names); + } + + date_type + parse_date(const string_type& value, + const string_type& format_str, + const special_values_parser<date_type,charT>& sv_parser) const + { + stringstream_type ss(value); + stream_itr_type sitr(ss); + stream_itr_type stream_end; + return parse_date(sitr, stream_end, format_str, sv_parser); + } + + date_type + parse_date(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + const special_values_parser<date_type,charT>& sv_parser) const + { + return parse_date(sitr, stream_end, m_format, sv_parser); + } + + /*! Of all the objects that the format_date_parser can parse, only a + * date can be a special value. Therefore, only parse_date checks + * for special_values. */ + date_type + parse_date(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str, + const special_values_parser<date_type,charT>& sv_parser) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + short year(0), month(0), day(0), day_of_year(0);// wkday(0); + /* Initialized the following to their minimum values. These intermediate + * objects are used so we get specific exceptions when part of the input + * is unparsable. + * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ + year_type t_year(1400); + month_type t_month(1); + day_type t_day(1); + day_of_week_type wkday(0); + + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'a': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + match_results mr = m_weekday_short_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'A': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + match_results mr = m_weekday_long_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'b': + { + match_results mr = m_month_short_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + t_month = month_type(mr.current_match); + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'B': + { + match_results mr = m_month_long_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + t_month = month_type(mr.current_match); + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'd': + { + match_results mr; + day = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2); + if(day == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + t_day = day_type(day); + break; + } + case 'e': + { + match_results mr; + day = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2, ' '); + if(day == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + t_day = day_type(day); + break; + } + case 'j': + { + match_results mr; + day_of_year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 3); + if(day_of_year == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + // these next two lines are so we get an exception with bad input + day_of_year_type t_day_of_year(1); + t_day_of_year = day_of_year_type(day_of_year); + break; + } + case 'm': + { + match_results mr; + month = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2); + if(month == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + t_month = month_type(month); + break; + } + case 'Y': + { + match_results mr; + year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 4); + if(year == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + t_year = year_type(year); + break; + } + case 'y': + { + match_results mr; + year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2); + if(year == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast<special_values>(mr.current_match)); + } + } + year += 2000; //make 2 digit years in this century + t_year = year_type(year); + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + if (day_of_year > 0) { + date_type d(static_cast<unsigned short>(year-1),12,31); //end of prior year + return d + duration_type(day_of_year); + } + + return date_type(t_year, t_month, t_day); // exceptions were thrown earlier + // if input was no good + } + + //! Throws bad_month if unable to parse + month_type + parse_month(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str) const + { + match_results mr; + return parse_month(sitr, stream_end, format_str, mr); + } + + //! Throws bad_month if unable to parse + month_type + parse_month(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str, + match_results& mr) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + short month(0); + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'b': + { + mr = m_month_short_names.match(sitr, stream_end); + month = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'B': + { + mr = m_month_long_names.match(sitr, stream_end); + month = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'm': + { + month = var_string_to_int<short, charT>(sitr, stream_end, 2); + // var_string_to_int returns -1 if parse failed. That will + // cause a bad_month exception to be thrown so we do nothing here + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + return month_type(month); // throws bad_month exception when values are zero + } + + //! Expects 1 or 2 digits 1-31. Throws bad_day_of_month if unable to parse + day_type + parse_var_day_of_month(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + return day_type(var_string_to_int<short, charT>(sitr, stream_end, 2)); + } + //! Expects 2 digits 01-31. Throws bad_day_of_month if unable to parse + day_type + parse_day_of_month(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + //return day_type(var_string_to_int<short, charT>(sitr, stream_end, 2)); + match_results mr; + return day_type(fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2)); + } + + day_of_week_type + parse_weekday(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str) const + { + match_results mr; + return parse_weekday(sitr, stream_end, format_str, mr); + } + day_of_week_type + parse_weekday(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str, + match_results& mr) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + short wkday(0); + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'a': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + mr = m_weekday_short_names.match(sitr, stream_end); + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'A': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + mr = m_weekday_long_names.match(sitr, stream_end); + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'w': + { + // weekday as number 0-6, Sunday == 0 + wkday = var_string_to_int<short, charT>(sitr, stream_end, 2); + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + return day_of_week_type(wkday); // throws bad_day_of_month exception + // when values are zero + } + + //! throws bad_year if unable to parse + year_type + parse_year(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str) const + { + match_results mr; + return parse_year(sitr, stream_end, format_str, mr); + } + + //! throws bad_year if unable to parse + year_type + parse_year(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + string_type format_str, + match_results& mr) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + unsigned short year(0); + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + //match_results mr; + switch(*itr) { + case 'Y': + { + // year from 4 digit string + year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 4); + break; + } + case 'y': + { + // year from 2 digit string (no century) + year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2); + year += 2000; //make 2 digit years in this century + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + return year_type(year); // throws bad_year exception when values are zero + } + + + private: + string_type m_format; + parse_tree_type m_month_short_names; + parse_tree_type m_month_long_names; + parse_tree_type m_weekday_short_names; + parse_tree_type m_weekday_long_names; + +}; + +} } //namespace + +#endif + + + diff --git a/ext/boost/date_time/gregorian/conversion.hpp b/ext/boost/date_time/gregorian/conversion.hpp new file mode 100644 index 0000000000..f35796ee7f --- /dev/null +++ b/ext/boost/date_time/gregorian/conversion.hpp @@ -0,0 +1,66 @@ +#ifndef _GREGORIAN__CONVERSION_HPP___ +#define _GREGORIAN__CONVERSION_HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-06 07:27:35 -0400 (Sat, 06 Jun 2009) $ + */ + +#include <string> +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/date_time/c_time.hpp> +#include <boost/date_time/special_defs.hpp> +#include <boost/date_time/gregorian/gregorian_types.hpp> + +namespace boost { + +namespace gregorian { + + //! Converts a date to a tm struct. Throws out_of_range exception if date is a special value + inline + std::tm to_tm(const date& d) + { + if (d.is_special()) + { + std::string s = "tm unable to handle "; + switch (d.as_special()) + { + case date_time::not_a_date_time: + s += "not-a-date-time value"; break; + case date_time::neg_infin: + s += "-infinity date value"; break; + case date_time::pos_infin: + s += "+infinity date value"; break; + default: + s += "a special date value"; break; + } + boost::throw_exception(std::out_of_range(s)); + } + + std::tm datetm = {}; // zero initialization is needed for extension members, like tm_zone + boost::gregorian::date::ymd_type ymd = d.year_month_day(); + datetm.tm_year = ymd.year - 1900; + datetm.tm_mon = ymd.month - 1; + datetm.tm_mday = ymd.day; + datetm.tm_wday = d.day_of_week(); + datetm.tm_yday = d.day_of_year() - 1; + datetm.tm_isdst = -1; // negative because not enough info to set tm_isdst + return datetm; + } + + //! Converts a tm structure into a date dropping the any time values. + inline + date date_from_tm(const std::tm& datetm) + { + return date(static_cast<unsigned short>(datetm.tm_year+1900), + static_cast<unsigned short>(datetm.tm_mon+1), + static_cast<unsigned short>(datetm.tm_mday)); + } + +} } //namespace boost::gregorian + +#endif diff --git a/ext/boost/date_time/gregorian/formatters.hpp b/ext/boost/date_time/gregorian/formatters.hpp new file mode 100644 index 0000000000..786e79f2c1 --- /dev/null +++ b/ext/boost/date_time/gregorian/formatters.hpp @@ -0,0 +1,162 @@ +#ifndef GREGORIAN_FORMATTERS_HPP___ +#define GREGORIAN_FORMATTERS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/gregorian/gregorian_types.hpp" +#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +#include "boost/date_time/date_formatting_limited.hpp" +#else +#include "boost/date_time/date_formatting.hpp" +#endif +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" + +/* NOTE: "to_*_string" code for older compilers, ones that define + * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in + * formatters_limited.hpp + */ + +namespace boost { +namespace gregorian { + + // wrapper function for to_simple_(w)string(date) + template<class charT> + inline + std::basic_string<charT> to_simple_string_type(const date& d) { + return date_time::date_formatter<date,date_time::simple_format<charT>,charT>::date_to_string(d); + } + //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date& d) { + return to_simple_string_type<char>(d); + } + + + // wrapper function for to_simple_(w)string(date_period) + template<class charT> + inline std::basic_string<charT> to_simple_string_type(const date_period& d) { + typedef std::basic_string<charT> string_type; + charT b = '[', m = '/', e=']'; + + string_type d1(date_time::date_formatter<date,date_time::simple_format<charT>,charT>::date_to_string(d.begin())); + string_type d2(date_time::date_formatter<date,date_time::simple_format<charT>,charT>::date_to_string(d.last())); + return string_type(b + d1 + m + d2 + e); + } + //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date_period& d) { + return to_simple_string_type<char>(d); + } + + // wrapper function for to_iso_(w)string(date_period) + template<class charT> + inline std::basic_string<charT> to_iso_string_type(const date_period& d) { + charT sep = '/'; + std::basic_string<charT> s(date_time::date_formatter<date,date_time::iso_format<charT>,charT>::date_to_string(d.begin())); + return s + sep + date_time::date_formatter<date,date_time::iso_format<charT>,charT>::date_to_string(d.last()); + } + //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date_period& d) { + return to_iso_string_type<char>(d); + } + + + // wrapper function for to_iso_extended_(w)string(date) + template<class charT> + inline std::basic_string<charT> to_iso_extended_string_type(const date& d) { + return date_time::date_formatter<date,date_time::iso_extended_format<charT>,charT>::date_to_string(d); + } + //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 + /*!\ingroup date_format + */ + inline std::string to_iso_extended_string(const date& d) { + return to_iso_extended_string_type<char>(d); + } + + // wrapper function for to_iso_(w)string(date) + template<class charT> + inline std::basic_string<charT> to_iso_string_type(const date& d) { + return date_time::date_formatter<date,date_time::iso_format<charT>,charT>::date_to_string(d); + } + //! Convert to iso standard string YYYYMMDD. Example: 20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date& d) { + return to_iso_string_type<char>(d); + } + + + + + // wrapper function for to_sql_(w)string(date) + template<class charT> + inline std::basic_string<charT> to_sql_string_type(const date& d) + { + date::ymd_type ymd = d.year_month_day(); + std::basic_ostringstream<charT> ss; + ss << ymd.year << "-" + << std::setw(2) << std::setfill(ss.widen('0')) + << ymd.month.as_number() //solves problem with gcc 3.1 hanging + << "-" + << std::setw(2) << std::setfill(ss.widen('0')) + << ymd.day; + return ss.str(); + } + inline std::string to_sql_string(const date& d) { + return to_sql_string_type<char>(d); + } + + +#if !defined(BOOST_NO_STD_WSTRING) + //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] + /*!\ingroup date_format + */ + inline std::wstring to_simple_wstring(const date_period& d) { + return to_simple_string_type<wchar_t>(d); + } + //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 + /*!\ingroup date_format + */ + inline std::wstring to_simple_wstring(const date& d) { + return to_simple_string_type<wchar_t>(d); + } + //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 + /*!\ingroup date_format + */ + inline std::wstring to_iso_wstring(const date_period& d) { + return to_iso_string_type<wchar_t>(d); + } + //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 + /*!\ingroup date_format + */ + inline std::wstring to_iso_extended_wstring(const date& d) { + return to_iso_extended_string_type<wchar_t>(d); + } + //! Convert to iso standard string YYYYMMDD. Example: 20021231 + /*!\ingroup date_format + */ + inline std::wstring to_iso_wstring(const date& d) { + return to_iso_string_type<wchar_t>(d); + } + inline std::wstring to_sql_wstring(const date& d) { + return to_sql_string_type<wchar_t>(d); + } +#endif // BOOST_NO_STD_WSTRING + +} } //namespace gregorian + + +#endif + diff --git a/ext/boost/date_time/gregorian/formatters_limited.hpp b/ext/boost/date_time/gregorian/formatters_limited.hpp new file mode 100644 index 0000000000..4531ebec13 --- /dev/null +++ b/ext/boost/date_time/gregorian/formatters_limited.hpp @@ -0,0 +1,81 @@ +#ifndef GREGORIAN_FORMATTERS_LIMITED_HPP___ +#define GREGORIAN_FORMATTERS_LIMITED_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/date_formatting_limited.hpp" +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/compiler_config.hpp" + +namespace boost { +namespace gregorian { + + //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date& d) { + return date_time::date_formatter<date,date_time::simple_format<char> >::date_to_string(d); + } + + //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date_period& d) { + std::string s("["); + std::string d1(date_time::date_formatter<date,date_time::simple_format<char> >::date_to_string(d.begin())); + std::string d2(date_time::date_formatter<date,date_time::simple_format<char> >::date_to_string(d.last())); + return std::string("[" + d1 + "/" + d2 + "]"); + } + + //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date_period& d) { + std::string s(date_time::date_formatter<date,date_time::iso_format<char> >::date_to_string(d.begin())); + return s + "/" + date_time::date_formatter<date,date_time::iso_format<char> >::date_to_string(d.last()); + } + + + //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 + /*!\ingroup date_format + */ + inline std::string to_iso_extended_string(const date& d) { + return date_time::date_formatter<date,date_time::iso_extended_format<char> >::date_to_string(d); + } + + //! Convert to iso standard string YYYYMMDD. Example: 20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date& d) { + return date_time::date_formatter<date,date_time::iso_format<char> >::date_to_string(d); + } + + + + inline std::string to_sql_string(const date& d) + { + date::ymd_type ymd = d.year_month_day(); + std::ostringstream ss; + ss << ymd.year << "-" + << std::setw(2) << std::setfill('0') + << ymd.month.as_number() //solves problem with gcc 3.1 hanging + << "-" + << std::setw(2) << std::setfill('0') + << ymd.day; + return ss.str(); + } + + +} } //namespace gregorian + + +#endif + diff --git a/ext/boost/date_time/gregorian/greg_calendar.hpp b/ext/boost/date_time/gregorian/greg_calendar.hpp new file mode 100644 index 0000000000..b8b1f5a69d --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_calendar.hpp @@ -0,0 +1,47 @@ +#ifndef GREGORIAN_GREGORIAN_CALENDAR_HPP__ +#define GREGORIAN_GREGORIAN_CALENDAR_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_weekday.hpp" +#include "boost/date_time/gregorian/greg_day_of_year.hpp" +#include "boost/date_time/gregorian_calendar.hpp" +#include "boost/date_time/gregorian/greg_ymd.hpp" +#include "boost/date_time/int_adapter.hpp" + +namespace boost { +namespace gregorian { + + //!An internal date representation that includes infinities, not a date + typedef date_time::int_adapter<unsigned long> fancy_date_rep; + + //! Gregorian calendar for this implementation, hard work in the base + class gregorian_calendar : + public date_time::gregorian_calendar_base<greg_year_month_day, fancy_date_rep::int_type> { + public: + //! Type to hold a weekday (eg: Sunday, Monday,...) + typedef greg_weekday day_of_week_type; + //! Counter type from 1 to 366 for gregorian dates. + typedef greg_day_of_year_rep day_of_year_type; + //! Internal date representation that handles infinity, not a date + typedef fancy_date_rep date_rep_type; + //! Date rep implements the traits stuff as well + typedef fancy_date_rep date_traits_type; + + + private: + }; + +} } //namespace gregorian + + + + +#endif + diff --git a/ext/boost/date_time/gregorian/greg_date.hpp b/ext/boost/date_time/gregorian/greg_date.hpp new file mode 100644 index 0000000000..56d576fe2d --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_date.hpp @@ -0,0 +1,136 @@ +#ifndef GREG_DATE_HPP___ +#define GREG_DATE_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <boost/throw_exception.hpp> +#include <boost/date_time/date.hpp> +#include <boost/date_time/special_defs.hpp> +#include <boost/date_time/gregorian/greg_calendar.hpp> +#include <boost/date_time/gregorian/greg_duration.hpp> + +namespace boost { +namespace gregorian { + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + + //! A date type based on gregorian_calendar + /*! This class is the primary interface for programming with + greogorian dates. The is a lightweight type that can be + freely passed by value. All comparison operators are + supported. + \ingroup date_basics + */ + class date : public date_time::date<date, gregorian_calendar, date_duration> + { + public: + typedef gregorian_calendar::year_type year_type; + typedef gregorian_calendar::month_type month_type; + typedef gregorian_calendar::day_type day_type; + typedef gregorian_calendar::day_of_year_type day_of_year_type; + typedef gregorian_calendar::ymd_type ymd_type; + typedef gregorian_calendar::date_rep_type date_rep_type; + typedef gregorian_calendar::date_int_type date_int_type; + typedef date_duration duration_type; +#if !defined(DATE_TIME_NO_DEFAULT_CONSTRUCTOR) + //! Default constructor constructs with not_a_date_time + date(): + date_time::date<date, gregorian_calendar, date_duration>(date_rep_type::from_special(not_a_date_time)) + {} +#endif // DATE_TIME_NO_DEFAULT_CONSTRUCTOR + //! Main constructor with year, month, day + date(year_type y, month_type m, day_type d) + : date_time::date<date, gregorian_calendar, date_duration>(y, m, d) + { + if (gregorian_calendar::end_of_month_day(y, m) < d) { + boost::throw_exception(bad_day_of_month(std::string("Day of month is not valid for year"))); + } + } + //! Constructor from a ymd_type structure + explicit date(const ymd_type& ymd) + : date_time::date<date, gregorian_calendar, date_duration>(ymd) + {} + //! Needed copy constructor + explicit date(const date_int_type& rhs): + date_time::date<date,gregorian_calendar, date_duration>(rhs) + {} + //! Needed copy constructor + explicit date(date_rep_type rhs): + date_time::date<date,gregorian_calendar, date_duration>(rhs) + {} + //! Constructor for infinities, not a date, max and min date + explicit date(special_values sv): + date_time::date<date, gregorian_calendar, date_duration>(date_rep_type::from_special(sv)) + { + if (sv == min_date_time) + { + *this = date(1400, 1, 1); + } + if (sv == max_date_time) + { + *this = date(9999, 12, 31); + } + + } + //!Return the Julian Day number for the date. + date_int_type julian_day() const + { + ymd_type ymd = year_month_day(); + return gregorian_calendar::julian_day_number(ymd); + } + //!Return the day of year 1..365 or 1..366 (for leap year) + day_of_year_type day_of_year() const + { + date start_of_year(year(), 1, 1); + unsigned short doy = static_cast<unsigned short>((*this-start_of_year).days() + 1); + return day_of_year_type(doy); + } + //!Return the Modified Julian Day number for the date. + long modjulian_day() const + { + ymd_type ymd = year_month_day(); + return gregorian_calendar::modjulian_day_number(ymd); + } + //!Return the iso 8601 week number 1..53 + int week_number() const + { + ymd_type ymd = year_month_day(); + return gregorian_calendar::week_number(ymd); + } + //! Return the day number from the calendar + date_int_type day_number() const + { + return days_; + } + //! Return the last day of the current month + date end_of_month() const + { + ymd_type ymd = year_month_day(); + short eom_day = gregorian_calendar::end_of_month_day(ymd.year, ymd.month); + return date(ymd.year, ymd.month, eom_day); + } + + private: + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/greg_day.hpp b/ext/boost/date_time/gregorian/greg_day.hpp new file mode 100644 index 0000000000..92ea6ab07e --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_day.hpp @@ -0,0 +1,57 @@ +#ifndef GREG_DAY_HPP___ +#define GREG_DAY_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include <stdexcept> +#include <string> + +namespace boost { +namespace gregorian { + + //! Exception type for gregorian day of month (1..31) + struct bad_day_of_month : public std::out_of_range + { + bad_day_of_month() : + std::out_of_range(std::string("Day of month value is out of range 1..31")) + {} + //! Allow other classes to throw with unique string for bad day like Feb 29 + bad_day_of_month(const std::string& s) : + std::out_of_range(s) + {} + }; + //! Policy class that declares error handling and day of month ranges + typedef CV::simple_exception_policy<unsigned short, 1, 31, bad_day_of_month> greg_day_policies; + + //! Generated represetation for gregorian day of month + typedef CV::constrained_value<greg_day_policies> greg_day_rep; + + //! Represent a day of the month (range 1 - 31) + /*! This small class allows for simple conversion an integer value into + a day of the month for a standard gregorian calendar. The type + is automatically range checked so values outside of the range 1-31 + will cause a bad_day_of_month exception + */ + class greg_day : public greg_day_rep { + public: + greg_day(unsigned short day_of_month) : greg_day_rep(day_of_month) {} + unsigned short as_number() const {return value_;} + operator unsigned short() const {return value_;} + private: + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/greg_day_of_year.hpp b/ext/boost/date_time/gregorian/greg_day_of_year.hpp new file mode 100644 index 0000000000..36b22c2b75 --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_day_of_year.hpp @@ -0,0 +1,38 @@ +#ifndef GREG_DAY_OF_YEAR_HPP___ +#define GREG_DAY_OF_YEAR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include <stdexcept> +#include <string> + +namespace boost { +namespace gregorian { + + //! Exception type for day of year (1..366) + struct bad_day_of_year : public std::out_of_range + { + bad_day_of_year() : + std::out_of_range(std::string("Day of year value is out of range 1..366")) + {} + }; + + //! A day of the year range (1..366) + typedef CV::simple_exception_policy<unsigned short,1,366,bad_day_of_year> greg_day_of_year_policies; + + //! Define a range representation type for the day of the year 1..366 + typedef CV::constrained_value<greg_day_of_year_policies> greg_day_of_year_rep; + + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/greg_duration.hpp b/ext/boost/date_time/gregorian/greg_duration.hpp new file mode 100644 index 0000000000..fd7554201e --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_duration.hpp @@ -0,0 +1,134 @@ +#ifndef GREG_DURATION_HPP___ +#define GREG_DURATION_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <boost/date_time/date_duration.hpp> +#include <boost/date_time/int_adapter.hpp> +#include <boost/date_time/special_defs.hpp> + +namespace boost { +namespace gregorian { + + //!An internal date representation that includes infinities, not a date + typedef boost::date_time::duration_traits_adapted date_duration_rep; + + //! Durations in days for gregorian system + /*! \ingroup date_basics + */ + class date_duration : + public boost::date_time::date_duration< date_duration_rep > + { + typedef boost::date_time::date_duration< date_duration_rep > base_type; + + public: + typedef base_type::duration_rep duration_rep; + + //! Construct from a day count + explicit date_duration(duration_rep day_count = 0) : base_type(day_count) {} + + //! construct from special_values + date_duration(date_time::special_values sv) : base_type(sv) {} + + //! Copy constructor + date_duration(const date_duration& other) : base_type(static_cast< base_type const& >(other)) + {} + + //! Construct from another date_duration + date_duration(const base_type& other) : base_type(other) + {} + + // Relational operators + // NOTE: Because of date_time::date_duration< T > design choice we don't use Boost.Operators here, + // because we need the class to be a direct base. Either lose EBO, or define operators by hand. + // The latter is more effecient. + bool operator== (const date_duration& rhs) const + { + return base_type::operator== (rhs); + } + bool operator!= (const date_duration& rhs) const + { + return !operator== (rhs); + } + bool operator< (const date_duration& rhs) const + { + return base_type::operator< (rhs); + } + bool operator> (const date_duration& rhs) const + { + return !(base_type::operator< (rhs) || base_type::operator== (rhs)); + } + bool operator<= (const date_duration& rhs) const + { + return (base_type::operator< (rhs) || base_type::operator== (rhs)); + } + bool operator>= (const date_duration& rhs) const + { + return !base_type::operator< (rhs); + } + + //! Subtract another duration -- result is signed + date_duration& operator-= (const date_duration& rhs) + { + base_type::operator-= (rhs); + return *this; + } + friend date_duration operator- (date_duration rhs, date_duration const& lhs) + { + rhs -= lhs; + return rhs; + } + + //! Add a duration -- result is signed + date_duration& operator+= (const date_duration& rhs) + { + base_type::operator+= (rhs); + return *this; + } + friend date_duration operator+ (date_duration rhs, date_duration const& lhs) + { + rhs += lhs; + return rhs; + } + + //! unary- Allows for dd = -date_duration(2); -> dd == -2 + date_duration operator- ()const + { + return date_duration(get_rep() * (-1)); + } + + //! Division operations on a duration with an integer. + date_duration& operator/= (int divisor) + { + base_type::operator/= (divisor); + return *this; + } + friend date_duration operator/ (date_duration rhs, int lhs) + { + rhs /= lhs; + return rhs; + } + + //! Returns the smallest duration -- used by to calculate 'end' + static date_duration unit() + { + return date_duration(base_type::unit().get_rep()); + } + }; + + //! Shorthand for date_duration + typedef date_duration days; + +} } //namespace gregorian + +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include <boost/date_time/date_duration_types.hpp> +#endif + +#endif diff --git a/ext/boost/date_time/gregorian/greg_duration_types.hpp b/ext/boost/date_time/gregorian/greg_duration_types.hpp new file mode 100644 index 0000000000..3d1ce62183 --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_duration_types.hpp @@ -0,0 +1,43 @@ +#ifndef GREG_DURATION_TYPES_HPP___ +#define GREG_DURATION_TYPES_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +#include <boost/date_time/gregorian/greg_date.hpp> +#include <boost/date_time/int_adapter.hpp> +#include <boost/date_time/adjust_functors.hpp> +#include <boost/date_time/date_duration_types.hpp> +#include <boost/date_time/gregorian/greg_duration.hpp> + +namespace boost { +namespace gregorian { + + //! config struct for additional duration types (ie months_duration<> & years_duration<>) + struct greg_durations_config { + typedef date date_type; + typedef date_time::int_adapter<int> int_rep; + typedef date_time::month_functor<date_type> month_adjustor_type; + }; + + typedef date_time::months_duration<greg_durations_config> months; + typedef date_time::years_duration<greg_durations_config> years; + + class weeks_duration : public date_duration { + public: + weeks_duration(duration_rep w) + : date_duration(w * 7) {} + weeks_duration(date_time::special_values sv) + : date_duration(sv) {} + }; + + typedef weeks_duration weeks; + +}} // namespace boost::gregorian + +#endif // GREG_DURATION_TYPES_HPP___ diff --git a/ext/boost/date_time/gregorian/greg_facet.hpp b/ext/boost/date_time/gregorian/greg_facet.hpp new file mode 100644 index 0000000000..9c3877ed03 --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_facet.hpp @@ -0,0 +1,354 @@ +#ifndef GREGORIAN_FACET_HPP___ +#define GREGORIAN_FACET_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-23 06:13:35 -0500 (Sun, 23 Nov 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/date_formatting_locales.hpp" // sets BOOST_DATE_TIME_NO_LOCALE +#include "boost/date_time/gregorian/parsers.hpp" + +//This file is basically commented out if locales are not supported +#ifndef BOOST_DATE_TIME_NO_LOCALE + +#include <string> +#include <memory> +#include <locale> +#include <iostream> +#include <exception> + +namespace boost { +namespace gregorian { + + //! Configuration of the output facet template + struct greg_facet_config + { + typedef boost::gregorian::greg_month month_type; + typedef boost::date_time::special_values special_value_enum; + typedef boost::gregorian::months_of_year month_enum; + typedef boost::date_time::weekdays weekday_enum; + }; + +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + //! Create the base facet type for gregorian::date + typedef boost::date_time::date_names_put<greg_facet_config> greg_base_facet; + + //! ostream operator for gregorian::date + /*! Uses the date facet to determine various output parameters including: + * - string values for the month (eg: Jan, Feb, Mar) (default: English) + * - string values for special values (eg: not-a-date-time) (default: English) + * - selection of long, short strings, or numerical month representation (default: short string) + * - month day year order (default yyyy-mmm-dd) + */ + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const date& d) + { + typedef boost::date_time::date_names_put<greg_facet_config, charT> facet_def; + typedef boost::date_time::ostream_date_formatter<date, facet_def, charT> greg_ostream_formatter; + greg_ostream_formatter::date_put(d, os); + return os; + } + + //! operator<< for gregorian::greg_month typically streaming: Jan, Feb, Mar... + /*! Uses the date facet to determine output string as well as selection of long or short strings. + * Default if no facet is installed is to output a 2 wide numeric value for the month + * eg: 01 == Jan, 02 == Feb, ... 12 == Dec. + */ + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const greg_month& m) + { + typedef boost::date_time::date_names_put<greg_facet_config, charT> facet_def; + typedef boost::date_time::ostream_month_formatter<facet_def, charT> greg_month_formatter; + std::locale locale = os.getloc(); + if (std::has_facet<facet_def>(locale)) { + const facet_def& f = std::use_facet<facet_def>(locale); + greg_month_formatter::format_month(m, os, f); + + } + else { //default to numeric + charT fill_char = '0'; + os << std::setw(2) << std::setfill(fill_char) << m.as_number(); + } + + return os; + } + + //! operator<< for gregorian::greg_weekday typically streaming: Sun, Mon, Tue, ... + /*! Uses the date facet to determine output string as well as selection of long or short string. + * Default if no facet is installed is to output a 3 char english string for the + * day of the week. + */ + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const greg_weekday& wd) + { + typedef boost::date_time::date_names_put<greg_facet_config, charT> facet_def; + typedef boost::date_time::ostream_weekday_formatter<greg_weekday, facet_def, charT> greg_weekday_formatter; + std::locale locale = os.getloc(); + if (std::has_facet<facet_def>(locale)) { + const facet_def& f = std::use_facet<facet_def>(locale); + greg_weekday_formatter::format_weekday(wd.as_enum(), os, f, true); + } + else { //default to short English string eg: Sun, Mon, Tue, Wed... + os << wd.as_short_string(); + } + + return os; + } + + //! operator<< for gregorian::date_period typical output: [2002-Jan-01/2002-Jan-31] + /*! Uses the date facet to determine output string as well as selection of long + * or short string fr dates. + * Default if no facet is installed is to output a 3 char english string for the + * day of the week. + */ + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const date_period& dp) + { + os << '['; //TODO: facet or manipulator for periods? + os << dp.begin(); + os << '/'; //TODO: facet or manipulator for periods? + os << dp.last(); + os << ']'; + return os; + } + + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const date_duration& dd) + { + //os << dd.days(); + os << dd.get_rep(); + return os; + } + + //! operator<< for gregorian::partial_date. Output: "Jan 1" + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const partial_date& pd) + { + os << std::setw(2) << std::setfill('0') << pd.day() << ' ' + << pd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::nth_kday_of_month. Output: "first Mon of Jun" + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, + const nth_kday_of_month& nkd) + { + os << nkd.nth_week_as_str() << ' ' + << nkd.day_of_week() << " of " + << nkd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::first_kday_of_month. Output: "first Mon of Jun" + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, + const first_kday_of_month& fkd) + { + os << "first " << fkd.day_of_week() << " of " + << fkd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::last_kday_of_month. Output: "last Mon of Jun" + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, + const last_kday_of_month& lkd) + { + os << "last " << lkd.day_of_week() << " of " + << lkd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::first_kday_after. Output: "first Mon after" + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, + const first_kday_after& fka) + { + os << fka.day_of_week() << " after"; + return os; + } + + //! operator<< for gregorian::first_kday_before. Output: "first Mon before" + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, + const first_kday_before& fkb) + { + os << fkb.day_of_week() << " before"; + return os; + } +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + /**************** Input Streaming ******************/ + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) + //! operator>> for gregorian::date + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, date& d) + { + std::istream_iterator<std::basic_string<charT>, charT> beg(is), eos; + + typedef boost::date_time::all_date_names_put<greg_facet_config, charT> facet_def; + d = from_stream(beg, eos); + return is; + } +#endif // BOOST_NO_STD_ITERATOR_TRAITS + + //! operator>> for gregorian::date_duration + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, + date_duration& dd) + { + long v; + is >> v; + dd = date_duration(v); + return is; + } + + //! operator>> for gregorian::date_period + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, + date_period& dp) + { + std::basic_string<charT> s; + is >> s; + dp = date_time::from_simple_string_type<date>(s); + return is; + } + + //! generates a locale with the set of gregorian name-strings of type char* + BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, char type); + + //! Returns a pointer to a facet with a default set of names (English) + /* Necessary in the event an exception is thrown from op>> for + * weekday or month. See comments in those functions for more info */ + BOOST_DATE_TIME_DECL boost::date_time::all_date_names_put<greg_facet_config, char>* create_facet_def(char type); + +#ifndef BOOST_NO_STD_WSTRING + //! generates a locale with the set of gregorian name-strings of type wchar_t* + BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, wchar_t type); + //! Returns a pointer to a facet with a default set of names (English) + /* Necessary in the event an exception is thrown from op>> for + * weekday or month. See comments in those functions for more info */ + BOOST_DATE_TIME_DECL boost::date_time::all_date_names_put<greg_facet_config, wchar_t>* create_facet_def(wchar_t type); +#endif // BOOST_NO_STD_WSTRING + + //! operator>> for gregorian::greg_month - throws exception if invalid month given + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is,greg_month& m) + { + typedef boost::date_time::all_date_names_put<greg_facet_config, charT> facet_def; + + std::basic_string<charT> s; + is >> s; + + if(!std::has_facet<facet_def>(is.getloc())) { + std::locale loc = is.getloc(); + charT a = '\0'; + is.imbue(generate_locale(loc, a)); + } + + short num = 0; + + try{ + const facet_def& f = std::use_facet<facet_def>(is.getloc()); + num = date_time::find_match(f.get_short_month_names(), + f.get_long_month_names(), + (greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size, + // which is needed by find_match + } + /* bad_cast will be thrown if the desired facet is not accessible + * so we can generate the facet. This has the drawback of using english + * names as a default. */ + catch(std::bad_cast&){ + charT a = '\0'; + std::auto_ptr< const facet_def > f(create_facet_def(a)); + num = date_time::find_match(f->get_short_month_names(), + f->get_long_month_names(), + (greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size, + // which is needed by find_match + } + + ++num; // months numbered 1-12 + m = greg_month(num); + + return is; + } + + //! operator>> for gregorian::greg_weekday - throws exception if invalid weekday given + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is,greg_weekday& wd) + { + typedef boost::date_time::all_date_names_put<greg_facet_config, charT> facet_def; + + std::basic_string<charT> s; + is >> s; + + if(!std::has_facet<facet_def>(is.getloc())) { + std::locale loc = is.getloc(); + charT a = '\0'; + is.imbue(generate_locale(loc, a)); + } + + short num = 0; + try{ + const facet_def& f = std::use_facet<facet_def>(is.getloc()); + num = date_time::find_match(f.get_short_weekday_names(), + f.get_long_weekday_names(), + (greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed + // to form the array size which is needed by find_match + } + /* bad_cast will be thrown if the desired facet is not accessible + * so we can generate the facet. This has the drawback of using english + * names as a default. */ + catch(std::bad_cast&){ + charT a = '\0'; + std::auto_ptr< const facet_def > f(create_facet_def(a)); + num = date_time::find_match(f->get_short_weekday_names(), + f->get_long_weekday_names(), + (greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed + // to form the array size which is needed by find_match + } + + wd = greg_weekday(num); // weekdays numbered 0-6 + return is; + } + +} } //namespace gregorian + +#endif + + +#endif + diff --git a/ext/boost/date_time/gregorian/greg_month.hpp b/ext/boost/date_time/gregorian/greg_month.hpp new file mode 100644 index 0000000000..fc9c86148d --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_month.hpp @@ -0,0 +1,105 @@ +#ifndef GREG_MONTH_HPP___ +#define GREG_MONTH_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include "boost/date_time/date_defs.hpp" +#include "boost/shared_ptr.hpp" +#include "boost/date_time/compiler_config.hpp" +#include <stdexcept> +#include <string> +#include <map> +#include <algorithm> +#include <cctype> + +namespace boost { +namespace gregorian { + + typedef date_time::months_of_year months_of_year; + + //bring enum values into the namespace + using date_time::Jan; + using date_time::Feb; + using date_time::Mar; + using date_time::Apr; + using date_time::May; + using date_time::Jun; + using date_time::Jul; + using date_time::Aug; + using date_time::Sep; + using date_time::Oct; + using date_time::Nov; + using date_time::Dec; + using date_time::NotAMonth; + using date_time::NumMonths; + + //! Exception thrown if a greg_month is constructed with a value out of range + struct bad_month : public std::out_of_range + { + bad_month() : std::out_of_range(std::string("Month number is out of range 1..12")) {} + }; + //! Build a policy class for the greg_month_rep + typedef CV::simple_exception_policy<unsigned short, 1, 12, bad_month> greg_month_policies; + //! A constrained range that implements the gregorian_month rules + typedef CV::constrained_value<greg_month_policies> greg_month_rep; + + + //! Wrapper class to represent months in gregorian based calendar + class BOOST_DATE_TIME_DECL greg_month : public greg_month_rep { + public: + typedef date_time::months_of_year month_enum; + typedef std::map<std::string, unsigned short> month_map_type; + typedef boost::shared_ptr<month_map_type> month_map_ptr_type; + //! Construct a month from the months_of_year enumeration + greg_month(month_enum theMonth) : + greg_month_rep(static_cast<greg_month_rep::value_type>(theMonth)) {} + //! Construct from a short value + greg_month(unsigned short theMonth) : greg_month_rep(theMonth) {} + //! Convert the value back to a short + operator unsigned short() const {return value_;} + //! Returns month as number from 1 to 12 + unsigned short as_number() const {return value_;} + month_enum as_enum() const {return static_cast<month_enum>(value_);} + const char* as_short_string() const; + const char* as_long_string() const; +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* as_short_wstring() const; + const wchar_t* as_long_wstring() const; +#endif // BOOST_NO_STD_WSTRING + //! Shared pointer to a map of Month strings (Names & Abbrev) & numbers + static month_map_ptr_type get_month_map_ptr(); + + /* parameterized as_*_string functions are intended to be called + * from a template function: "... as_short_string(charT c='\0');" */ + const char* as_short_string(char) const + { + return as_short_string(); + } + const char* as_long_string(char) const + { + return as_long_string(); + } +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* as_short_string(wchar_t) const + { + return as_short_wstring(); + } + const wchar_t* as_long_string(wchar_t) const + { + return as_long_wstring(); + } +#endif // BOOST_NO_STD_WSTRING + }; + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/greg_serialize.hpp b/ext/boost/date_time/gregorian/greg_serialize.hpp new file mode 100644 index 0000000000..c48cc0ae37 --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_serialize.hpp @@ -0,0 +1,489 @@ +#ifndef GREGORIAN_SERIALIZE_HPP___ +#define GREGORIAN_SERIALIZE_HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/gregorian/parsers.hpp" +#include "boost/serialization/split_free.hpp" + + +// macros to split serialize functions into save & load functions +// An expanded version is below for gregorian::date +// NOTE: these macros define template functions in the boost::serialization namespace. +// They must be expanded *outside* of any namespace +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration::duration_rep) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_period) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_day) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_weekday) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::partial_date) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::nth_kday_of_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_of_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::last_kday_of_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_before) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_after) + +namespace boost { +namespace serialization { + +/*! Method that does serialization for gregorian::date -- splits to load/save + */ +template<class Archive> +inline void serialize(Archive & ar, + ::boost::gregorian::date & d, + const unsigned int file_version) +{ + split_free(ar, d, file_version); +} + +//! Function to save gregorian::date objects using serialization lib +/*! Dates are serialized into a string for transport and storage. + * While it would be more efficient to store the internal + * integer used to manipulate the dates, it is an unstable solution. + */ +template<class Archive> +void save(Archive & ar, + const ::boost::gregorian::date & d, + unsigned int /* version */) +{ + std::string ds = to_iso_string(d); + ar & make_nvp("date", ds); +} + +//! Function to load gregorian::date objects using serialization lib +/*! Dates are serialized into a string for transport and storage. + * While it would be more efficient to store the internal + * integer used to manipulate the dates, it is an unstable solution. + */ +template<class Archive> +void load(Archive & ar, + ::boost::gregorian::date & d, + unsigned int /*version*/) +{ + std::string ds; + ar & make_nvp("date", ds); + try{ + d = ::boost::gregorian::from_undelimited_string(ds); + }catch(bad_lexical_cast&) { + gregorian::special_values sv = gregorian::special_value_from_string(ds); + if(sv == gregorian::not_special) { + throw; // no match found, rethrow original exception + } + else { + d = gregorian::date(sv); + } + } +} + + +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + ::boost::gregorian::date* dp, + const unsigned int /*file_version*/) +{ + // retrieve data from archive required to construct new + // invoke inplace constructor to initialize instance of date + ::new(dp) ::boost::gregorian::date(::boost::gregorian::not_a_date_time); +} + +/**** date_duration ****/ + +//! Function to save gregorian::date_duration objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::date_duration & dd, + unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep dr = dd.get_rep(); + ar & make_nvp("date_duration", dr); +} +//! Function to load gregorian::date_duration objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::date_duration & dd, unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep dr(0); + ar & make_nvp("date_duration", dr); + dd = gregorian::date_duration(dr); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::date_duration* dd, + const unsigned int /*file_version*/) +{ + ::new(dd) gregorian::date_duration(gregorian::not_a_date_time); +} + +/**** date_duration::duration_rep (most likely int_adapter) ****/ + +//! helper unction to save date_duration objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::date_duration::duration_rep & dr, + unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep::int_type it = dr.as_number(); + ar & make_nvp("date_duration_duration_rep", it); +} +//! helper function to load date_duration objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::date_duration::duration_rep & dr, unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep::int_type it(0); + ar & make_nvp("date_duration_duration_rep", it); + dr = gregorian::date_duration::duration_rep::int_type(it); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::date_duration::duration_rep* dr, + const unsigned int /*file_version*/) +{ + ::new(dr) gregorian::date_duration::duration_rep(0); +} + +/**** date_period ****/ + +//! Function to save gregorian::date_period objects using serialization lib +/*! date_period objects are broken down into 2 parts for serialization: + * the begining date object and the end date object + */ +template<class Archive> +void save(Archive & ar, const gregorian::date_period& dp, + unsigned int /*version*/) +{ + gregorian::date d1 = dp.begin(); + gregorian::date d2 = dp.end(); + ar & make_nvp("date_period_begin_date", d1); + ar & make_nvp("date_period_end_date", d2); +} +//! Function to load gregorian::date_period objects using serialization lib +/*! date_period objects are broken down into 2 parts for serialization: + * the begining date object and the end date object + */ +template<class Archive> +void load(Archive & ar, gregorian::date_period& dp, unsigned int /*version*/) +{ + gregorian::date d1(gregorian::not_a_date_time); + gregorian::date d2(gregorian::not_a_date_time); + ar & make_nvp("date_period_begin_date", d1); + ar & make_nvp("date_period_end_date", d2); + dp = gregorian::date_period(d1,d2); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::date_period* dp, + const unsigned int /*file_version*/) +{ + gregorian::date d(gregorian::not_a_date_time); + gregorian::date_duration dd(1); + ::new(dp) gregorian::date_period(d,dd); +} + +/**** greg_month ****/ + +//! Function to save gregorian::greg_month objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::greg_month& gm, + unsigned int /*version*/) +{ + unsigned short us = gm.as_number(); + ar & make_nvp("greg_month", us); +} +//! Function to load gregorian::greg_month objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::greg_month& gm, unsigned int /*version*/) +{ + unsigned short us; + ar & make_nvp("greg_month", us); + gm = gregorian::greg_month(us); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::greg_month* gm, + const unsigned int /*file_version*/) +{ + ::new(gm) gregorian::greg_month(1); +} + +/**** greg_day ****/ + +//! Function to save gregorian::greg_day objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::greg_day& gd, + unsigned int /*version*/) +{ + unsigned short us = gd.as_number(); + ar & make_nvp("greg_day", us); +} +//! Function to load gregorian::greg_day objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::greg_day& gd, unsigned int /*version*/) +{ + unsigned short us; + ar & make_nvp("greg_day", us); + gd = gregorian::greg_day(us); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::greg_day* gd, + const unsigned int /*file_version*/) +{ + ::new(gd) gregorian::greg_day(1); +} + +/**** greg_weekday ****/ + +//! Function to save gregorian::greg_weekday objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::greg_weekday& gd, + unsigned int /*version*/) +{ + unsigned short us = gd.as_number(); + ar & make_nvp("greg_weekday", us); +} +//! Function to load gregorian::greg_weekday objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::greg_weekday& gd, unsigned int /*version*/) +{ + unsigned short us; + ar & make_nvp("greg_weekday", us); + gd = gregorian::greg_weekday(us); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::greg_weekday* gd, + const unsigned int /*file_version*/) +{ + ::new(gd) gregorian::greg_weekday(1); +} + +/**** date_generators ****/ + +/**** partial_date ****/ + +//! Function to save gregorian::partial_date objects using serialization lib +/*! partial_date objects are broken down into 2 parts for serialization: + * the day (typically greg_day) and month (typically greg_month) objects + */ +template<class Archive> +void save(Archive & ar, const gregorian::partial_date& pd, + unsigned int /*version*/) +{ + gregorian::greg_day gd(pd.day()); + gregorian::greg_month gm(pd.month().as_number()); + ar & make_nvp("partial_date_day", gd); + ar & make_nvp("partial_date_month", gm); +} +//! Function to load gregorian::partial_date objects using serialization lib +/*! partial_date objects are broken down into 2 parts for serialization: + * the day (greg_day) and month (greg_month) objects + */ +template<class Archive> +void load(Archive & ar, gregorian::partial_date& pd, unsigned int /*version*/) +{ + gregorian::greg_day gd(1); + gregorian::greg_month gm(1); + ar & make_nvp("partial_date_day", gd); + ar & make_nvp("partial_date_month", gm); + pd = gregorian::partial_date(gd,gm); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, gregorian::partial_date* pd, + const unsigned int /*file_version*/) +{ + gregorian::greg_month gm(1); + gregorian::greg_day gd(1); + ::new(pd) gregorian::partial_date(gd,gm); +} + +/**** nth_kday_of_month ****/ + +//! Function to save nth_day_of_the_week_in_month objects using serialization lib +/*! nth_day_of_the_week_in_month objects are broken down into 3 parts for + * serialization: the week number, the day of the week, and the month + */ +template<class Archive> +void save(Archive & ar, const gregorian::nth_kday_of_month& nkd, + unsigned int /*version*/) +{ + typename gregorian::nth_kday_of_month::week_num wn(nkd.nth_week()); + typename gregorian::nth_kday_of_month::day_of_week_type d(nkd.day_of_week().as_number()); + typename gregorian::nth_kday_of_month::month_type m(nkd.month().as_number()); + ar & make_nvp("nth_kday_of_month_week_num", wn); + ar & make_nvp("nth_kday_of_month_day_of_week", d); + ar & make_nvp("nth_kday_of_month_month", m); +} +//! Function to load nth_day_of_the_week_in_month objects using serialization lib +/*! nth_day_of_the_week_in_month objects are broken down into 3 parts for + * serialization: the week number, the day of the week, and the month + */ +template<class Archive> +void load(Archive & ar, gregorian::nth_kday_of_month& nkd, unsigned int /*version*/) +{ + typename gregorian::nth_kday_of_month::week_num wn(gregorian::nth_kday_of_month::first); + typename gregorian::nth_kday_of_month::day_of_week_type d(gregorian::Monday); + typename gregorian::nth_kday_of_month::month_type m(gregorian::Jan); + ar & make_nvp("nth_kday_of_month_week_num", wn); + ar & make_nvp("nth_kday_of_month_day_of_week", d); + ar & make_nvp("nth_kday_of_month_month", m); + + nkd = gregorian::nth_kday_of_month(wn,d,m); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + gregorian::nth_kday_of_month* nkd, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(nkd) gregorian::nth_kday_of_month(gregorian::nth_kday_of_month::first, + gregorian::Monday,gregorian::Jan); +} + +/**** first_kday_of_month ****/ + +//! Function to save first_day_of_the_week_in_month objects using serialization lib +/*! first_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template<class Archive> +void save(Archive & ar, const gregorian::first_kday_of_month& fkd, + unsigned int /*version*/) +{ + typename gregorian::first_kday_of_month::day_of_week_type d(fkd.day_of_week().as_number()); + typename gregorian::first_kday_of_month::month_type m(fkd.month().as_number()); + ar & make_nvp("first_kday_of_month_day_of_week", d); + ar & make_nvp("first_kday_of_month_month", m); +} +//! Function to load first_day_of_the_week_in_month objects using serialization lib +/*! first_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template<class Archive> +void load(Archive & ar, gregorian::first_kday_of_month& fkd, unsigned int /*version*/) +{ + typename gregorian::first_kday_of_month::day_of_week_type d(gregorian::Monday); + typename gregorian::first_kday_of_month::month_type m(gregorian::Jan); + ar & make_nvp("first_kday_of_month_day_of_week", d); + ar & make_nvp("first_kday_of_month_month", m); + + fkd = gregorian::first_kday_of_month(d,m); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + gregorian::first_kday_of_month* fkd, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(fkd) gregorian::first_kday_of_month(gregorian::Monday,gregorian::Jan); +} + +/**** last_kday_of_month ****/ + +//! Function to save last_day_of_the_week_in_month objects using serialization lib +/*! last_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template<class Archive> +void save(Archive & ar, const gregorian::last_kday_of_month& lkd, + unsigned int /*version*/) +{ + typename gregorian::last_kday_of_month::day_of_week_type d(lkd.day_of_week().as_number()); + typename gregorian::last_kday_of_month::month_type m(lkd.month().as_number()); + ar & make_nvp("last_kday_of_month_day_of_week", d); + ar & make_nvp("last_kday_of_month_month", m); +} +//! Function to load last_day_of_the_week_in_month objects using serialization lib +/*! last_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template<class Archive> +void load(Archive & ar, gregorian::last_kday_of_month& lkd, unsigned int /*version*/) +{ + typename gregorian::last_kday_of_month::day_of_week_type d(gregorian::Monday); + typename gregorian::last_kday_of_month::month_type m(gregorian::Jan); + ar & make_nvp("last_kday_of_month_day_of_week", d); + ar & make_nvp("last_kday_of_month_month", m); + + lkd = gregorian::last_kday_of_month(d,m); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + gregorian::last_kday_of_month* lkd, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(lkd) gregorian::last_kday_of_month(gregorian::Monday,gregorian::Jan); +} + +/**** first_kday_before ****/ + +//! Function to save first_day_of_the_week_before objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::first_kday_before& fkdb, + unsigned int /*version*/) +{ + typename gregorian::first_kday_before::day_of_week_type d(fkdb.day_of_week().as_number()); + ar & make_nvp("first_kday_before_day_of_week", d); +} +//! Function to load first_day_of_the_week_before objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::first_kday_before& fkdb, unsigned int /*version*/) +{ + typename gregorian::first_kday_before::day_of_week_type d(gregorian::Monday); + ar & make_nvp("first_kday_before_day_of_week", d); + + fkdb = gregorian::first_kday_before(d); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + gregorian::first_kday_before* fkdb, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(fkdb) gregorian::first_kday_before(gregorian::Monday); +} + +/**** first_kday_after ****/ + +//! Function to save first_day_of_the_week_after objects using serialization lib +template<class Archive> +void save(Archive & ar, const gregorian::first_kday_after& fkda, + unsigned int /*version*/) +{ + typename gregorian::first_kday_after::day_of_week_type d(fkda.day_of_week().as_number()); + ar & make_nvp("first_kday_after_day_of_week", d); +} +//! Function to load first_day_of_the_week_after objects using serialization lib +template<class Archive> +void load(Archive & ar, gregorian::first_kday_after& fkda, unsigned int /*version*/) +{ + typename gregorian::first_kday_after::day_of_week_type d(gregorian::Monday); + ar & make_nvp("first_kday_after_day_of_week", d); + + fkda = gregorian::first_kday_after(d); +} +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + gregorian::first_kday_after* fkda, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(fkda) gregorian::first_kday_after(gregorian::Monday); +} + +} // namespace serialization +} // namespace boost + +#endif diff --git a/ext/boost/date_time/gregorian/greg_weekday.hpp b/ext/boost/date_time/gregorian/greg_weekday.hpp new file mode 100644 index 0000000000..9b566c440d --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_weekday.hpp @@ -0,0 +1,66 @@ +#ifndef GREG_WEEKDAY_HPP___ +#define GREG_WEEKDAY_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include "boost/date_time/date_defs.hpp" +#include "boost/date_time/compiler_config.hpp" +#include <stdexcept> +#include <string> + +namespace boost { +namespace gregorian { + + //bring enum values into the namespace + using date_time::Sunday; + using date_time::Monday; + using date_time::Tuesday; + using date_time::Wednesday; + using date_time::Thursday; + using date_time::Friday; + using date_time::Saturday; + + + //! Exception that flags that a weekday number is incorrect + struct bad_weekday : public std::out_of_range + { + bad_weekday() : std::out_of_range(std::string("Weekday is out of range 0..6")) {} + }; + typedef CV::simple_exception_policy<unsigned short, 0, 6, bad_weekday> greg_weekday_policies; + typedef CV::constrained_value<greg_weekday_policies> greg_weekday_rep; + + + //! Represent a day within a week (range 0==Sun to 6==Sat) + class BOOST_DATE_TIME_DECL greg_weekday : public greg_weekday_rep { + public: + typedef boost::date_time::weekdays weekday_enum; + greg_weekday(unsigned short day_of_week_num) : + greg_weekday_rep(day_of_week_num) + {} + + unsigned short as_number() const {return value_;} + const char* as_short_string() const; + const char* as_long_string() const; +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* as_short_wstring() const; + const wchar_t* as_long_wstring() const; +#endif // BOOST_NO_STD_WSTRING + weekday_enum as_enum() const {return static_cast<weekday_enum>(value_);} + + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/greg_year.hpp b/ext/boost/date_time/gregorian/greg_year.hpp new file mode 100644 index 0000000000..ef1735f427 --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_year.hpp @@ -0,0 +1,53 @@ +#ifndef GREG_YEAR_HPP___ +#define GREG_YEAR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include <stdexcept> +#include <string> + +namespace boost { +namespace gregorian { + + //! Exception type for gregorian year + struct bad_year : public std::out_of_range + { + bad_year() : + std::out_of_range(std::string("Year is out of valid range: 1400..10000")) + {} + }; + //! Policy class that declares error handling gregorian year type + typedef CV::simple_exception_policy<unsigned short, 1400, 10000, bad_year> greg_year_policies; + + //! Generated representation for gregorian year + typedef CV::constrained_value<greg_year_policies> greg_year_rep; + + //! Represent a day of the month (range 1900 - 10000) + /*! This small class allows for simple conversion an integer value into + a year for the gregorian calendar. This currently only allows a + range of 1900 to 10000. Both ends of the range are a bit arbitrary + at the moment, but they are the limits of current testing of the + library. As such they may be increased in the future. + */ + class greg_year : public greg_year_rep { + public: + greg_year(unsigned short year) : greg_year_rep(year) {} + operator unsigned short() const {return value_;} + private: + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/greg_ymd.hpp b/ext/boost/date_time/gregorian/greg_ymd.hpp new file mode 100644 index 0000000000..086e73df4a --- /dev/null +++ b/ext/boost/date_time/gregorian/greg_ymd.hpp @@ -0,0 +1,33 @@ +#ifndef DATE_TIME_GREG_YMD_HPP__ +#define DATE_TIME_GREG_YMD_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/year_month_day.hpp" +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/gregorian/greg_day.hpp" +#include "boost/date_time/gregorian/greg_year.hpp" +#include "boost/date_time/gregorian/greg_month.hpp" + +namespace boost { +namespace gregorian { + + typedef date_time::year_month_day_base<greg_year, + greg_month, + greg_day> greg_year_month_day; + + + +} } //namespace gregorian + + + + +#endif + diff --git a/ext/boost/date_time/gregorian/gregorian.hpp b/ext/boost/date_time/gregorian/gregorian.hpp new file mode 100644 index 0000000000..bfafa1b037 --- /dev/null +++ b/ext/boost/date_time/gregorian/gregorian.hpp @@ -0,0 +1,38 @@ +#ifndef GREGORIAN_HPP__ +#define GREGORIAN_HPP__ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file gregorian.hpp + Single file header that provides overall include for all elements of + the gregorian date-time system. This includes the various types + defined, but also other functions for formatting and parsing. +*/ + + +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/gregorian/conversion.hpp" +#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +#include "boost/date_time/gregorian/formatters_limited.hpp" +#else +#include "boost/date_time/gregorian/formatters.hpp" +#endif + +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/gregorian/greg_facet.hpp" +#else +#include "boost/date_time/gregorian/gregorian_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + +#include "boost/date_time/gregorian/parsers.hpp" + + + +#endif diff --git a/ext/boost/date_time/gregorian/gregorian_io.hpp b/ext/boost/date_time/gregorian/gregorian_io.hpp new file mode 100644 index 0000000000..62a759f55c --- /dev/null +++ b/ext/boost/date_time/gregorian/gregorian_io.hpp @@ -0,0 +1,784 @@ +#ifndef DATE_TIME_GREGORIAN_IO_HPP__ +#define DATE_TIME_GREGORIAN_IO_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <locale> +#include <iostream> +#include <iterator> // i/ostreambuf_iterator +#include <boost/io/ios_state.hpp> +#include <boost/date_time/date_facet.hpp> +#include <boost/date_time/period_parser.hpp> +#include <boost/date_time/period_formatter.hpp> +#include <boost/date_time/special_values_parser.hpp> +#include <boost/date_time/special_values_formatter.hpp> +#include <boost/date_time/gregorian/gregorian_types.hpp> +#include <boost/date_time/gregorian/conversion.hpp> // to_tm will be needed in the facets + +namespace boost { +namespace gregorian { + + + typedef boost::date_time::period_formatter<wchar_t> wperiod_formatter; + typedef boost::date_time::period_formatter<char> period_formatter; + + typedef boost::date_time::date_facet<date,wchar_t> wdate_facet; + typedef boost::date_time::date_facet<date,char> date_facet; + + typedef boost::date_time::period_parser<date,char> period_parser; + typedef boost::date_time::period_parser<date,wchar_t> wperiod_parser; + + typedef boost::date_time::special_values_formatter<char> special_values_formatter; + typedef boost::date_time::special_values_formatter<wchar_t> wspecial_values_formatter; + + typedef boost::date_time::special_values_parser<date,char> special_values_parser; + typedef boost::date_time::special_values_parser<date,wchar_t> wspecial_values_parser; + + typedef boost::date_time::date_input_facet<date,char> date_input_facet; + typedef boost::date_time::date_input_facet<date,wchar_t> wdate_input_facet; + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::date& d) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), d); + else { + //instantiate a custom facet for dealing with dates since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every date + //if the locale did not already exist. Of course this will be overridden + //if the user imbues at some later point. With the default settings + //for the facet the resulting format will be the same as the + //std::time_facet settings. + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), d); + } + return os; + } + + //! input operator for date + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, date& d) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, d); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, d); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::date_duration& dd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), dd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), dd); + + } + return os; + } + + //! input operator for date_duration + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, date_duration& dd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, dd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, dd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::date_period& dp) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), dp); + else { + //instantiate a custom facet for dealing with date periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues at some later point. With the default settings + //for the facet the resulting format will be the same as the + //std::time_facet settings. + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), dp); + + } + return os; + } + + //! input operator for date_period + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, date_period& dp) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, dp); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, dp); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + /********** small gregorian types **********/ + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::greg_month& gm) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), gm); + else { + custom_date_facet* f = new custom_date_facet();//-> 10/1074199752/32 because year & day not initialized in put(...) + //custom_date_facet* f = new custom_date_facet("%B"); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), gm); + } + return os; + } + + //! input operator for greg_month + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, greg_month& m) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, m); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, m); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::greg_weekday& gw) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), gw); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), gw); + } + return os; + } + + //! input operator for greg_weekday + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, greg_weekday& wd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, wd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, wd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + //NOTE: output operator for greg_day was not necessary + + //! input operator for greg_day + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, greg_day& gd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, gd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, gd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + //NOTE: output operator for greg_year was not necessary + + //! input operator for greg_year + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, greg_year& gy) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, gy); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, gy); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + /********** date generator types **********/ + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::partial_date& pd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), pd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), pd); + } + return os; + } + + //! input operator for partial_date + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, partial_date& pd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, pd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, pd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::nth_day_of_the_week_in_month& nkd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), nkd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), nkd); + } + return os; + } + + //! input operator for nth_day_of_the_week_in_month + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, + nth_day_of_the_week_in_month& nday) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, nday); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, nday); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::first_day_of_the_week_in_month& fkd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), fkd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), fkd); + } + return os; + } + + //! input operator for first_day_of_the_week_in_month + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, + first_day_of_the_week_in_month& fkd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, fkd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, fkd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::last_day_of_the_week_in_month& lkd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), lkd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), lkd); + } + return os; + } + + //! input operator for last_day_of_the_week_in_month + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, + last_day_of_the_week_in_month& lkd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, lkd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, lkd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::first_day_of_the_week_after& fda) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) { + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), fda); + } + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), fda); + } + return os; + } + + //! input operator for first_day_of_the_week_after + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, + first_day_of_the_week_after& fka) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, fka); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, fka); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template <class CharT, class TraitsT> + inline std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::first_day_of_the_week_before& fdb) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet<date, CharT> custom_date_facet; + std::ostreambuf_iterator<CharT> output_itr(os); + if (std::has_facet<custom_date_facet>(os.getloc())) { + std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), fdb); + } + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), fdb); + } + return os; + } + + //! input operator for first_day_of_the_week_before + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, + first_day_of_the_week_before& fkb) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet<date, CharT> date_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<date_input_facet>(is.getloc())) { + std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, fkb); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, fkb); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + +} } // namespaces + +#endif // DATE_TIME_GREGORIAN_IO_HPP__ diff --git a/ext/boost/date_time/gregorian/gregorian_types.hpp b/ext/boost/date_time/gregorian/gregorian_types.hpp new file mode 100644 index 0000000000..0c74857a25 --- /dev/null +++ b/ext/boost/date_time/gregorian/gregorian_types.hpp @@ -0,0 +1,109 @@ +#ifndef _GREGORIAN_TYPES_HPP__ +#define _GREGORIAN_TYPES_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file gregorian_types.hpp + Single file header that defines most of the types for the gregorian + date-time system. +*/ + +#include "boost/date_time/date.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/gregorian/greg_calendar.hpp" +#include "boost/date_time/gregorian/greg_duration.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#endif +#include "boost/date_time/gregorian/greg_date.hpp" +#include "boost/date_time/date_generators.hpp" +#include "boost/date_time/date_clock_device.hpp" +#include "boost/date_time/date_iterator.hpp" +#include "boost/date_time/adjust_functors.hpp" + +namespace boost { + +//! Gregorian date system based on date_time components +/*! This date system defines a full complement of types including + * a date, date_duration, date_period, day_clock, and a + * day_iterator. + */ +namespace gregorian { + //! Date periods for the gregorian system + /*!\ingroup date_basics + */ + typedef date_time::period<date, date_duration> date_period; + + //! A unifying date_generator base type + /*! A unifying date_generator base type for: + * partial_date, nth_day_of_the_week_in_month, + * first_day_of_the_week_in_month, and last_day_of_the_week_in_month + */ + typedef date_time::year_based_generator<date> year_based_generator; + + //! A date generation object type + typedef date_time::partial_date<date> partial_date; + + typedef date_time::nth_kday_of_month<date> nth_kday_of_month; + typedef nth_kday_of_month nth_day_of_the_week_in_month; + + typedef date_time::first_kday_of_month<date> first_kday_of_month; + typedef first_kday_of_month first_day_of_the_week_in_month; + + typedef date_time::last_kday_of_month<date> last_kday_of_month; + typedef last_kday_of_month last_day_of_the_week_in_month; + + typedef date_time::first_kday_after<date> first_kday_after; + typedef first_kday_after first_day_of_the_week_after; + + typedef date_time::first_kday_before<date> first_kday_before; + typedef first_kday_before first_day_of_the_week_before; + + //! A clock to get the current day from the local computer + /*!\ingroup date_basics + */ + typedef date_time::day_clock<date> day_clock; + + //! Base date_iterator type for gregorian types. + /*!\ingroup date_basics + */ + typedef date_time::date_itr_base<date> date_iterator; + + //! A day level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr<date_time::day_functor<date>, + date> day_iterator; + //! A week level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr<date_time::week_functor<date>, + date> week_iterator; + //! A month level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr<date_time::month_functor<date>, + date> month_iterator; + //! A year level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr<date_time::year_functor<date>, + date> year_iterator; + + // bring in these date_generator functions from date_time namespace + using date_time::days_until_weekday; + using date_time::days_before_weekday; + using date_time::next_weekday; + using date_time::previous_weekday; + +} } //namespace gregorian + + + +#endif diff --git a/ext/boost/date_time/gregorian/parsers.hpp b/ext/boost/date_time/gregorian/parsers.hpp new file mode 100644 index 0000000000..95d4f23dec --- /dev/null +++ b/ext/boost/date_time/gregorian/parsers.hpp @@ -0,0 +1,91 @@ +#ifndef GREGORIAN_PARSERS_HPP___ +#define GREGORIAN_PARSERS_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/date_parsing.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/parse_format_base.hpp" +#include <string> +#include <sstream> + +namespace boost { +namespace gregorian { + + //! Return special_value from string argument + /*! Return special_value from string argument. If argument is + * not one of the special value names (defined in src/gregorian/names.hpp), + * return 'not_special' */ + BOOST_DATE_TIME_DECL special_values special_value_from_string(const std::string& s); + + //! Deprecated: Use from_simple_string + inline date from_string(std::string s) { + return date_time::parse_date<date>(s); + } + + //! From delimited date string where with order year-month-day eg: 2002-1-25 or 2003-Jan-25 (full month name is also accepted) + inline date from_simple_string(std::string s) { + return date_time::parse_date<date>(s, date_time::ymd_order_iso); + } + + //! From delimited date string where with order year-month-day eg: 1-25-2003 or Jan-25-2003 (full month name is also accepted) + inline date from_us_string(std::string s) { + return date_time::parse_date<date>(s, date_time::ymd_order_us); + } + + //! From delimited date string where with order day-month-year eg: 25-1-2002 or 25-Jan-2003 (full month name is also accepted) + inline date from_uk_string(std::string s) { + return date_time::parse_date<date>(s, date_time::ymd_order_dmy); + } + + //! From iso type date string where with order year-month-day eg: 20020125 + inline date from_undelimited_string(std::string s) { + return date_time::parse_undelimited_date<date>(s); + } + + //! From iso type date string where with order year-month-day eg: 20020125 + inline date date_from_iso_string(const std::string& s) { + return date_time::parse_undelimited_date<date>(s); + } + +#if !(defined(BOOST_NO_STD_ITERATOR_TRAITS)) + //! Stream should hold a date in the form of: 2002-1-25. Month number, abbrev, or name are accepted + /* Arguments passed in by-value for convertability of char[] + * to iterator_type. Calls to from_stream_type are by-reference + * since conversion is already done */ + template<class iterator_type> + inline date from_stream(iterator_type beg, iterator_type end) { + if(beg == end) + { + return date(not_a_date_time); + } + typedef typename std::iterator_traits<iterator_type>::value_type value_type; + return date_time::from_stream_type<date>(beg, end, value_type()); + } +#endif //BOOST_NO_STD_ITERATOR_TRAITS + +#if (defined(_MSC_VER) && (_MSC_VER < 1300)) + // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings +#else + //! Function to parse a date_period from a string (eg: [2003-Oct-31/2003-Dec-25]) + inline date_period date_period_from_string(const std::string& s){ + return date_time::from_simple_string_type<date,char>(s); + } +# if !defined(BOOST_NO_STD_WSTRING) + //! Function to parse a date_period from a wstring (eg: [2003-Oct-31/2003-Dec-25]) + inline date_period date_period_from_wstring(const std::wstring& s){ + return date_time::from_simple_string_type<date,wchar_t>(s); + } +# endif // BOOST_NO_STD_WSTRING +#endif + +} } //namespace gregorian + +#endif diff --git a/ext/boost/date_time/gregorian_calendar.hpp b/ext/boost/date_time/gregorian_calendar.hpp new file mode 100644 index 0000000000..6386008bea --- /dev/null +++ b/ext/boost/date_time/gregorian_calendar.hpp @@ -0,0 +1,70 @@ +#ifndef DATE_TIME_GREGORIAN_CALENDAR_HPP__ +#define DATE_TIME_GREGORIAN_CALENDAR_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + + + //! An implementation of the Gregorian calendar + /*! This is a parameterized implementation of a proleptic Gregorian Calendar that + can be used in the creation of date systems or just to perform calculations. + All the methods of this class are static functions, so the intent is to + never create instances of this class. + @param ymd_type_ Struct type representing the year, month, day. The ymd_type must + define a of types for the year, month, and day. These types need to be + arithmetic types. + @param date_int_type_ Underlying type for the date count. Must be an arithmetic type. + */ + template<typename ymd_type_, typename date_int_type_> + class gregorian_calendar_base { + public: + //! define a type a date split into components + typedef ymd_type_ ymd_type; + //! define a type for representing months + typedef typename ymd_type::month_type month_type; + //! define a type for representing days + typedef typename ymd_type::day_type day_type; + //! Type to hold a stand alone year value (eg: 2002) + typedef typename ymd_type::year_type year_type; + //! Define the integer type to use for internal calculations + typedef date_int_type_ date_int_type; + + + static unsigned short day_of_week(const ymd_type& ymd); + static int week_number(const ymd_type&ymd); + //static unsigned short day_of_year(date_int_type); + static date_int_type day_number(const ymd_type& ymd); + static date_int_type julian_day_number(const ymd_type& ymd); + static long modjulian_day_number(const ymd_type& ymd); + static ymd_type from_day_number(date_int_type); + static ymd_type from_julian_day_number(date_int_type); + static ymd_type from_modjulian_day_number(long); + static bool is_leap_year(year_type); + static unsigned short end_of_month_day(year_type y, month_type m); + static ymd_type epoch(); + static unsigned short days_in_week(); + + }; + + + +} } //namespace + +#ifndef NO_BOOST_DATE_TIME_INLINE +#include "boost/date_time/gregorian_calendar.ipp" +#endif + + + +#endif + + diff --git a/ext/boost/date_time/gregorian_calendar.ipp b/ext/boost/date_time/gregorian_calendar.ipp new file mode 100644 index 0000000000..b7628fc178 --- /dev/null +++ b/ext/boost/date_time/gregorian_calendar.ipp @@ -0,0 +1,219 @@ +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#ifndef NO_BOOST_DATE_TIME_INLINE + #undef BOOST_DATE_TIME_INLINE + #define BOOST_DATE_TIME_INLINE inline +#endif + +namespace boost { +namespace date_time { + //! Return the day of the week (0==Sunday, 1==Monday, etc) + /*! Converts a year-month-day into a day of the week number + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + unsigned short + gregorian_calendar_base<ymd_type_,date_int_type_>::day_of_week(const ymd_type& ymd) { + unsigned short a = static_cast<unsigned short>((14-ymd.month)/12); + unsigned short y = static_cast<unsigned short>(ymd.year - a); + unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 2); + unsigned short d = static_cast<unsigned short>((ymd.day + y + (y/4) - (y/100) + (y/400) + (31*m)/12) % 7); + //std::cout << year << "-" << month << "-" << day << " is day: " << d << "\n"; + return d; + } + + //!Return the iso week number for the date + /*!Implements the rules associated with the iso 8601 week number. + Basically the rule is that Week 1 of the year is the week that contains + January 4th or the week that contains the first Thursday in January. + Reference for this algorithm is the Calendar FAQ by Claus Tondering, April 2000. + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + int + gregorian_calendar_base<ymd_type_,date_int_type_>::week_number(const ymd_type& ymd) { + unsigned long julianbegin = julian_day_number(ymd_type(ymd.year,1,1)); + unsigned long juliantoday = julian_day_number(ymd); + unsigned long day = (julianbegin + 3) % 7; + unsigned long week = (juliantoday + day - julianbegin + 4)/7; + + if ((week >= 1) && (week <= 52)) { + return week; + } + + if ((week == 53)) { + if((day==6) ||(day == 5 && is_leap_year(ymd.year))) { + return week; //under these circumstances week == 53. + } else { + return 1; //monday - wednesday is in week 1 of next year + } + } + //if the week is not in current year recalculate using the previous year as the beginning year + else if (week == 0) { + julianbegin = julian_day_number(ymd_type(static_cast<unsigned short>(ymd.year-1),1,1)); + juliantoday = julian_day_number(ymd); + day = (julianbegin + 3) % 7; + week = (juliantoday + day - julianbegin + 4)/7; + return week; + } + + return week; //not reachable -- well except if day == 5 and is_leap_year != true + + } + + //! Convert a ymd_type into a day number + /*! The day number is an absolute number of days since the start of count + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + date_int_type_ + gregorian_calendar_base<ymd_type_,date_int_type_>::day_number(const ymd_type& ymd) + { + unsigned short a = static_cast<unsigned short>((14-ymd.month)/12); + unsigned short y = static_cast<unsigned short>(ymd.year + 4800 - a); + unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 3); + unsigned long d = ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045; + return d; + } + + //! Convert a year-month-day into the julian day number + /*! Since this implementation uses julian day internally, this is the same as the day_number. + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + date_int_type_ + gregorian_calendar_base<ymd_type_,date_int_type_>::julian_day_number(const ymd_type& ymd) + { + return day_number(ymd); + } + + //! Convert year-month-day into a modified julian day number + /*! The day number is an absolute number of days. + * MJD 0 thus started on 17 Nov 1858(Gregorian) at 00:00:00 UTC + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + long + gregorian_calendar_base<ymd_type_,date_int_type_>::modjulian_day_number(const ymd_type& ymd) + { + return julian_day_number(ymd)-2400001; //prerounded + } + + //! Change a day number into a year-month-day + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base<ymd_type_,date_int_type_>::from_day_number(date_int_type dayNumber) + { + date_int_type a = dayNumber + 32044; + date_int_type b = (4*a + 3)/146097; + date_int_type c = a-((146097*b)/4); + date_int_type d = (4*c + 3)/1461; + date_int_type e = c - (1461*d)/4; + date_int_type m = (5*e + 2)/153; + unsigned short day = static_cast<unsigned short>(e - ((153*m + 2)/5) + 1); + unsigned short month = static_cast<unsigned short>(m + 3 - 12 * (m/10)); + year_type year = static_cast<unsigned short>(100*b + d - 4800 + (m/10)); + //std::cout << year << "-" << month << "-" << day << "\n"; + + return ymd_type(static_cast<unsigned short>(year),month,day); + } + + //! Change a day number into a year-month-day + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base<ymd_type_,date_int_type_>::from_julian_day_number(date_int_type dayNumber) + { + date_int_type a = dayNumber + 32044; + date_int_type b = (4*a+3)/146097; + date_int_type c = a - ((146097*b)/4); + date_int_type d = (4*c + 3)/1461; + date_int_type e = c - ((1461*d)/4); + date_int_type m = (5*e + 2)/153; + unsigned short day = static_cast<unsigned short>(e - ((153*m + 2)/5) + 1); + unsigned short month = static_cast<unsigned short>(m + 3 - 12 * (m/10)); + year_type year = static_cast<year_type>(100*b + d - 4800 + (m/10)); + //std::cout << year << "-" << month << "-" << day << "\n"; + + return ymd_type(year,month,day); + } + + //! Change a modified julian day number into a year-month-day + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base<ymd_type_,date_int_type_>::from_modjulian_day_number(long dayNumber) { + date_int_type jd = dayNumber + 2400001; //is 2400000.5 prerounded + return from_julian_day_number(jd); + } + + //! Determine if the provided year is a leap year + /*! + *@return true if year is a leap year, false otherwise + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + bool + gregorian_calendar_base<ymd_type_,date_int_type_>::is_leap_year(year_type year) + { + //divisible by 4, not if divisible by 100, but true if divisible by 400 + return (!(year % 4)) && ((year % 100) || (!(year % 400))); + } + + //! Calculate the last day of the month + /*! Find the day which is the end of the month given year and month + * No error checking is performed. + */ + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + unsigned short + gregorian_calendar_base<ymd_type_,date_int_type_>::end_of_month_day(year_type year, + month_type month) + { + switch (month) { + case 2: + if (is_leap_year(year)) { + return 29; + } else { + return 28; + }; + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + }; + + } + + //! Provide the ymd_type specification for the calandar start + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base<ymd_type_,date_int_type_>::epoch() + { + return ymd_type(1400,1,1); + } + + //! Defines length of a week for week calculations + template<typename ymd_type_, typename date_int_type_> + BOOST_DATE_TIME_INLINE + unsigned short + gregorian_calendar_base<ymd_type_,date_int_type_>::days_in_week() + { + return 7; + } + + +} } //namespace gregorian + + diff --git a/ext/boost/date_time/int_adapter.hpp b/ext/boost/date_time/int_adapter.hpp new file mode 100644 index 0000000000..fc98fc1278 --- /dev/null +++ b/ext/boost/date_time/int_adapter.hpp @@ -0,0 +1,509 @@ +#ifndef _DATE_TIME_INT_ADAPTER_HPP__ +#define _DATE_TIME_INT_ADAPTER_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +#include "boost/config.hpp" +#include "boost/limits.hpp" //work around compilers without limits +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/locale_config.hpp" +#ifndef BOOST_DATE_TIME_NO_LOCALE +# include <ostream> +#endif + +namespace boost { +namespace date_time { + + +//! Adapter to create integer types with +-infinity, and not a value +/*! This class is used internally in counted date/time representations. + * It adds the floating point like features of infinities and + * not a number. It also provides mathmatical operations with + * consideration to special values following these rules: + *@code + * +infinity - infinity == Not A Number (NAN) + * infinity * non-zero == infinity + * infinity * zero == NAN + * +infinity * -integer == -infinity + * infinity / infinity == NAN + * infinity * infinity == infinity + *@endcode + */ +template<typename int_type_> +class int_adapter { +public: + typedef int_type_ int_type; + int_adapter(int_type v) : + value_(v) + {} + static bool has_infinity() + { + return true; + } + static const int_adapter pos_infinity() + { + return (::std::numeric_limits<int_type>::max)(); + } + static const int_adapter neg_infinity() + { + return (::std::numeric_limits<int_type>::min)(); + } + static const int_adapter not_a_number() + { + return (::std::numeric_limits<int_type>::max)()-1; + } + static int_adapter max BOOST_PREVENT_MACRO_SUBSTITUTION () + { + return (::std::numeric_limits<int_type>::max)()-2; + } + static int_adapter min BOOST_PREVENT_MACRO_SUBSTITUTION () + { + return (::std::numeric_limits<int_type>::min)()+1; + } + static int_adapter from_special(special_values sv) + { + switch (sv) { + case not_a_date_time: return not_a_number(); + case neg_infin: return neg_infinity(); + case pos_infin: return pos_infinity(); + case max_date_time: return (max)(); + case min_date_time: return (min)(); + default: return not_a_number(); + } + } + static bool is_inf(int_type v) + { + return (v == neg_infinity().as_number() || + v == pos_infinity().as_number()); + } + static bool is_neg_inf(int_type v) + { + return (v == neg_infinity().as_number()); + } + static bool is_pos_inf(int_type v) + { + return (v == pos_infinity().as_number()); + } + static bool is_not_a_number(int_type v) + { + return (v == not_a_number().as_number()); + } + //! Returns either special value type or is_not_special + static special_values to_special(int_type v) + { + if (is_not_a_number(v)) return not_a_date_time; + if (is_neg_inf(v)) return neg_infin; + if (is_pos_inf(v)) return pos_infin; + return not_special; + } + + //-3 leaves room for representations of infinity and not a date + static int_type maxcount() + { + return (::std::numeric_limits<int_type>::max)()-3; + } + bool is_infinity() const + { + return (value_ == neg_infinity().as_number() || + value_ == pos_infinity().as_number()); + } + bool is_pos_infinity()const + { + return(value_ == pos_infinity().as_number()); + } + bool is_neg_infinity()const + { + return(value_ == neg_infinity().as_number()); + } + bool is_nan() const + { + return (value_ == not_a_number().as_number()); + } + bool is_special() const + { + return(is_infinity() || is_nan()); + } + bool operator==(const int_adapter& rhs) const + { + return (compare(rhs) == 0); + } + bool operator==(const int& rhs) const + { + // quiets compiler warnings + bool is_signed = std::numeric_limits<int_type>::is_signed; + if(!is_signed) + { + if(is_neg_inf(value_) && rhs == 0) + { + return false; + } + } + return (compare(rhs) == 0); + } + bool operator!=(const int_adapter& rhs) const + { + return (compare(rhs) != 0); + } + bool operator!=(const int& rhs) const + { + // quiets compiler warnings + bool is_signed = std::numeric_limits<int_type>::is_signed; + if(!is_signed) + { + if(is_neg_inf(value_) && rhs == 0) + { + return true; + } + } + return (compare(rhs) != 0); + } + bool operator<(const int_adapter& rhs) const + { + return (compare(rhs) == -1); + } + bool operator<(const int& rhs) const + { + // quiets compiler warnings + bool is_signed = std::numeric_limits<int_type>::is_signed; + if(!is_signed) + { + if(is_neg_inf(value_) && rhs == 0) + { + return true; + } + } + return (compare(rhs) == -1); + } + bool operator>(const int_adapter& rhs) const + { + return (compare(rhs) == 1); + } + int_type as_number() const + { + return value_; + } + //! Returns either special value type or is_not_special + special_values as_special() const + { + return int_adapter::to_special(value_); + } + //creates nasty ambiguities +// operator int_type() const +// { +// return value_; +// } + + /*! Operator allows for adding dissimilar int_adapter types. + * The return type will match that of the the calling object's type */ + template<class rhs_type> + inline + int_adapter operator+(const int_adapter<rhs_type>& rhs) const + { + if(is_special() || rhs.is_special()) + { + if (is_nan() || rhs.is_nan()) + { + return int_adapter::not_a_number(); + } + if((is_pos_inf(value_) && rhs.is_neg_inf(rhs.as_number())) || + (is_neg_inf(value_) && rhs.is_pos_inf(rhs.as_number())) ) + { + return int_adapter::not_a_number(); + } + if (is_infinity()) + { + return *this; + } + if (rhs.is_pos_inf(rhs.as_number())) + { + return int_adapter::pos_infinity(); + } + if (rhs.is_neg_inf(rhs.as_number())) + { + return int_adapter::neg_infinity(); + } + } + return int_adapter<int_type>(value_ + rhs.as_number()); + } + + int_adapter operator+(const int_type rhs) const + { + if(is_special()) + { + if (is_nan()) + { + return int_adapter<int_type>(not_a_number()); + } + if (is_infinity()) + { + return *this; + } + } + return int_adapter<int_type>(value_ + rhs); + } + + /*! Operator allows for subtracting dissimilar int_adapter types. + * The return type will match that of the the calling object's type */ + template<class rhs_type> + inline + int_adapter operator-(const int_adapter<rhs_type>& rhs)const + { + if(is_special() || rhs.is_special()) + { + if (is_nan() || rhs.is_nan()) + { + return int_adapter::not_a_number(); + } + if((is_pos_inf(value_) && rhs.is_pos_inf(rhs.as_number())) || + (is_neg_inf(value_) && rhs.is_neg_inf(rhs.as_number())) ) + { + return int_adapter::not_a_number(); + } + if (is_infinity()) + { + return *this; + } + if (rhs.is_pos_inf(rhs.as_number())) + { + return int_adapter::neg_infinity(); + } + if (rhs.is_neg_inf(rhs.as_number())) + { + return int_adapter::pos_infinity(); + } + } + return int_adapter<int_type>(value_ - rhs.as_number()); + } + int_adapter operator-(const int_type rhs) const + { + if(is_special()) + { + if (is_nan()) + { + return int_adapter<int_type>(not_a_number()); + } + if (is_infinity()) + { + return *this; + } + } + return int_adapter<int_type>(value_ - rhs); + } + + // should templatize this to be consistant with op +- + int_adapter operator*(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + return mult_div_specials(rhs); + } + return int_adapter<int_type>(value_ * rhs.value_); + } + /*! Provided for cases when automatic conversion from + * 'int' to 'int_adapter' causes incorrect results. */ + int_adapter operator*(const int rhs) const + { + if(is_special()) + { + return mult_div_specials(rhs); + } + return int_adapter<int_type>(value_ * rhs); + } + + // should templatize this to be consistant with op +- + int_adapter operator/(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + if(is_infinity() && rhs.is_infinity()) + { + return int_adapter<int_type>(not_a_number()); + } + if(rhs != 0) + { + return mult_div_specials(rhs); + } + else { // let divide by zero blow itself up + return int_adapter<int_type>(value_ / rhs.value_); + } + } + return int_adapter<int_type>(value_ / rhs.value_); + } + /*! Provided for cases when automatic conversion from + * 'int' to 'int_adapter' causes incorrect results. */ + int_adapter operator/(const int rhs) const + { + if(is_special() && rhs != 0) + { + return mult_div_specials(rhs); + } + return int_adapter<int_type>(value_ / rhs); + } + + // should templatize this to be consistant with op +- + int_adapter operator%(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + if(is_infinity() && rhs.is_infinity()) + { + return int_adapter<int_type>(not_a_number()); + } + if(rhs != 0) + { + return mult_div_specials(rhs); + } + else { // let divide by zero blow itself up + return int_adapter<int_type>(value_ % rhs.value_); + } + } + return int_adapter<int_type>(value_ % rhs.value_); + } + /*! Provided for cases when automatic conversion from + * 'int' to 'int_adapter' causes incorrect results. */ + int_adapter operator%(const int rhs) const + { + if(is_special() && rhs != 0) + { + return mult_div_specials(rhs); + } + return int_adapter<int_type>(value_ % rhs); + } +private: + int_type value_; + + //! returns -1, 0, 1, or 2 if 'this' is <, ==, >, or 'nan comparison' rhs + int compare(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + if(this->is_nan() || rhs.is_nan()) { + if(this->is_nan() && rhs.is_nan()) { + return 0; // equal + } + else { + return 2; // nan + } + } + if((is_neg_inf(value_) && !is_neg_inf(rhs.value_)) || + (is_pos_inf(rhs.value_) && !is_pos_inf(value_)) ) + { + return -1; // less than + } + if((is_pos_inf(value_) && !is_pos_inf(rhs.value_)) || + (is_neg_inf(rhs.value_) && !is_neg_inf(value_)) ) { + return 1; // greater than + } + } + if(value_ < rhs.value_) return -1; + if(value_ > rhs.value_) return 1; + // implied-> if(value_ == rhs.value_) + return 0; + } + /* When multiplying and dividing with at least 1 special value + * very simmilar rules apply. In those cases where the rules + * are different, they are handled in the respective operator + * function. */ + //! Assumes at least 'this' or 'rhs' is a special value + int_adapter mult_div_specials(const int_adapter& rhs)const + { + int min_value; + // quiets compiler warnings + bool is_signed = std::numeric_limits<int_type>::is_signed; + if(is_signed) { + min_value = 0; + } + else { + min_value = 1;// there is no zero with unsigned + } + if(this->is_nan() || rhs.is_nan()) { + return int_adapter<int_type>(not_a_number()); + } + if((*this > 0 && rhs > 0) || (*this < min_value && rhs < min_value)) { + return int_adapter<int_type>(pos_infinity()); + } + if((*this > 0 && rhs < min_value) || (*this < min_value && rhs > 0)) { + return int_adapter<int_type>(neg_infinity()); + } + //implied -> if(this->value_ == 0 || rhs.value_ == 0) + return int_adapter<int_type>(not_a_number()); + } + /* Overloaded function necessary because of special + * situation where int_adapter is instantiated with + * 'unsigned' and func is called with negative int. + * It would produce incorrect results since 'unsigned' + * wraps around when initialized with a negative value */ + //! Assumes 'this' is a special value + int_adapter mult_div_specials(const int& rhs) const + { + int min_value; + // quiets compiler warnings + bool is_signed = std::numeric_limits<int_type>::is_signed; + if(is_signed) { + min_value = 0; + } + else { + min_value = 1;// there is no zero with unsigned + } + if(this->is_nan()) { + return int_adapter<int_type>(not_a_number()); + } + if((*this > 0 && rhs > 0) || (*this < min_value && rhs < 0)) { + return int_adapter<int_type>(pos_infinity()); + } + if((*this > 0 && rhs < 0) || (*this < min_value && rhs > 0)) { + return int_adapter<int_type>(neg_infinity()); + } + //implied -> if(this->value_ == 0 || rhs.value_ == 0) + return int_adapter<int_type>(not_a_number()); + } + +}; + +#ifndef BOOST_DATE_TIME_NO_LOCALE + /*! Expected output is either a numeric representation + * or a special values representation.<BR> + * Ex. "12", "+infinity", "not-a-number", etc. */ + //template<class charT = char, class traits = std::traits<charT>, typename int_type> + template<class charT, class traits, typename int_type> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const int_adapter<int_type>& ia) + { + if(ia.is_special()) { + // switch copied from date_names_put.hpp + switch(ia.as_special()) + { + case not_a_date_time: + os << "not-a-number"; + break; + case pos_infin: + os << "+infinity"; + break; + case neg_infin: + os << "-infinity"; + break; + default: + os << ""; + } + } + else { + os << ia.as_number(); + } + return os; + } +#endif + + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/iso_format.hpp b/ext/boost/date_time/iso_format.hpp new file mode 100644 index 0000000000..8262fa2117 --- /dev/null +++ b/ext/boost/date_time/iso_format.hpp @@ -0,0 +1,303 @@ +#ifndef ISO_FORMAT_HPP___ +#define ISO_FORMAT_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/parse_format_base.hpp" + +namespace boost { +namespace date_time { + +//! Class to provide common iso formatting spec +template<class charT> +class iso_format_base { +public: + //! Describe month format -- its an integer in iso format + static month_format_spec month_format() + { + return month_as_integer; + } + + //! String used printed is date is invalid + static const charT* not_a_date() + { + return "not-a-date-time"; + } + //! String used to for positive infinity value + static const charT* pos_infinity() + { + return "+infinity"; + } + //! String used to for positive infinity value + static const charT* neg_infinity() + { + return "-infinity"; + } + + //! ISO char for a year -- used in durations + static charT year_sep_char() + { + return 'Y'; + } + //! ISO char for a month + static charT month_sep_char() + { + return '-'; + } + //! ISO char for a day + static charT day_sep_char() + { + return '-'; + } + //! char for minute + static charT hour_sep_char() + { + return ':'; + } + //! char for minute + static charT minute_sep_char() + { + return ':'; + } + //! char for second + static charT second_sep_char() + { + return ':'; + } + //! ISO char for a period + static charT period_start_char() + { + return 'P'; + } + //! Used in time in mixed strings to set start of time + static charT time_start_char() + { + return 'T'; + } + + //! Used in mixed strings to identify start of a week number + static charT week_start_char() + { + return 'W'; + } + + //! Separators for periods + static charT period_sep_char() + { + return '/'; + } + //! Separator for hh:mm:ss + static charT time_sep_char() + { + return ':'; + } + //! Preferred Separator for hh:mm:ss,decimal_fraction + static charT fractional_time_sep_char() + { + return ','; + } + + static bool is_component_sep(charT sep) + { + switch(sep) { + case 'H': + case 'M': + case 'S': + case 'W': + case 'T': + case 'Y': + case 'D':return true; + default: + return false; + } + } + + static bool is_fractional_time_sep(charT sep) + { + switch(sep) { + case ',': + case '.': return true; + default: return false; + } + } + static bool is_timezone_sep(charT sep) + { + switch(sep) { + case '+': + case '-': return true; + default: return false; + } + } + static charT element_sep_char() + { + return '-'; + } + +}; + +#ifndef BOOST_NO_STD_WSTRING + +//! Class to provide common iso formatting spec +template<> +class iso_format_base<wchar_t> { +public: + //! Describe month format -- its an integer in iso format + static month_format_spec month_format() + { + return month_as_integer; + } + + //! String used printed is date is invalid + static const wchar_t* not_a_date() + { + return L"not-a-date-time"; + } + //! String used to for positive infinity value + static const wchar_t* pos_infinity() + { + return L"+infinity"; + } + //! String used to for positive infinity value + static const wchar_t* neg_infinity() + { + return L"-infinity"; + } + + //! ISO char for a year -- used in durations + static wchar_t year_sep_char() + { + return 'Y'; + } + //! ISO char for a month + static wchar_t month_sep_char() + { + return '-'; + } + //! ISO char for a day + static wchar_t day_sep_char() + { + return '-'; + } + //! char for minute + static wchar_t hour_sep_char() + { + return ':'; + } + //! char for minute + static wchar_t minute_sep_char() + { + return ':'; + } + //! char for second + static wchar_t second_sep_char() + { + return ':'; + } + //! ISO char for a period + static wchar_t period_start_char() + { + return 'P'; + } + //! Used in time in mixed strings to set start of time + static wchar_t time_start_char() + { + return 'T'; + } + + //! Used in mixed strings to identify start of a week number + static wchar_t week_start_char() + { + return 'W'; + } + + //! Separators for periods + static wchar_t period_sep_char() + { + return '/'; + } + //! Separator for hh:mm:ss + static wchar_t time_sep_char() + { + return ':'; + } + //! Preferred Separator for hh:mm:ss,decimal_fraction + static wchar_t fractional_time_sep_char() + { + return ','; + } + + static bool is_component_sep(wchar_t sep) + { + switch(sep) { + case 'H': + case 'M': + case 'S': + case 'W': + case 'T': + case 'Y': + case 'D':return true; + default: + return false; + } + } + + static bool is_fractional_time_sep(wchar_t sep) + { + switch(sep) { + case ',': + case '.': return true; + default: return false; + } + } + static bool is_timezone_sep(wchar_t sep) + { + switch(sep) { + case '+': + case '-': return true; + default: return false; + } + } + static wchar_t element_sep_char() + { + return '-'; + } + +}; + +#endif // BOOST_NO_STD_WSTRING + +//! Format description for iso normal YYYYMMDD +template<class charT> +class iso_format : public iso_format_base<charT> { +public: + //! The ios standard format doesn't use char separators + static bool has_date_sep_chars() + { + return false; + } +}; + +//! Extended format uses seperators YYYY-MM-DD +template<class charT> +class iso_extended_format : public iso_format_base<charT> { +public: + //! Extended format needs char separators + static bool has_date_sep_chars() + { + return true; + } + +}; + +} } //namespace date_time + + + + +#endif diff --git a/ext/boost/date_time/local_time/conversion.hpp b/ext/boost/date_time/local_time/conversion.hpp new file mode 100644 index 0000000000..13e4d3eb5c --- /dev/null +++ b/ext/boost/date_time/local_time/conversion.hpp @@ -0,0 +1,34 @@ +#ifndef DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ +#define DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 04:24:49 -0400 (Thu, 04 Jun 2009) $ + */ + + +#include "boost/date_time/posix_time/conversion.hpp" +#include "boost/date_time/c_time.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" + +namespace boost { +namespace local_time { + +//! Function that creates a tm struct from a local_date_time +inline +std::tm to_tm(const local_date_time& lt) { + std::tm lt_tm = posix_time::to_tm(lt.local_time()); + if(lt.is_dst()){ + lt_tm.tm_isdst = 1; + } + else{ + lt_tm.tm_isdst = 0; + } + return lt_tm; +} + + +}} // namespaces +#endif // DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ diff --git a/ext/boost/date_time/local_time/custom_time_zone.hpp b/ext/boost/date_time/local_time/custom_time_zone.hpp new file mode 100644 index 0000000000..a6c1d42055 --- /dev/null +++ b/ext/boost/date_time/local_time/custom_time_zone.hpp @@ -0,0 +1,169 @@ +#ifndef LOCAL_TIME_CUSTOM_TIME_ZONE_HPP__ +#define LOCAL_TIME_CUSTOM_TIME_ZONE_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/time_zone_names.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/string_convert.hpp" +//#include "boost/date_time/special_defs.hpp" +#include "boost/shared_ptr.hpp" + +namespace boost { +namespace local_time { + + //typedef boost::date_time::time_zone_names time_zone_names; + typedef boost::date_time::dst_adjustment_offsets<boost::posix_time::time_duration> dst_adjustment_offsets; + //typedef boost::date_time::time_zone_base<boost::posix_time::ptime> time_zone; + typedef boost::shared_ptr<dst_calc_rule> dst_calc_rule_ptr; + + //! A real time zone + template<class CharT> + class custom_time_zone_base : public date_time::time_zone_base<posix_time::ptime,CharT> { + public: + typedef boost::posix_time::time_duration time_duration_type; + typedef date_time::time_zone_base<posix_time::ptime,CharT> base_type; + typedef typename base_type::string_type string_type; + typedef typename base_type::stringstream_type stringstream_type; + typedef date_time::time_zone_names_base<CharT> time_zone_names; + typedef CharT char_type; + + custom_time_zone_base(const time_zone_names& zone_names, + const time_duration_type& utc_offset, + const dst_adjustment_offsets& dst_shift, + boost::shared_ptr<dst_calc_rule> calc_rule) : + zone_names_(zone_names), + base_utc_offset_(utc_offset), + dst_offsets_(dst_shift), + dst_calc_rules_(calc_rule) + {}; + virtual ~custom_time_zone_base() {}; + virtual string_type dst_zone_abbrev() const + { + return zone_names_.dst_zone_abbrev(); + } + virtual string_type std_zone_abbrev() const + { + return zone_names_.std_zone_abbrev(); + } + virtual string_type dst_zone_name() const + { + return zone_names_.dst_zone_name(); + } + virtual string_type std_zone_name() const + { + return zone_names_.std_zone_name(); + } + //! True if zone uses daylight savings adjustments + virtual bool has_dst() const + { + return (dst_calc_rules_); //if calc_rule is set the tz has dst + } + //! Local time that DST starts -- NADT if has_dst is false + virtual posix_time::ptime dst_local_start_time(gregorian::greg_year y) const + { + gregorian::date d(gregorian::not_a_date_time); + if (dst_calc_rules_) { + d = dst_calc_rules_->start_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_start_offset_); + } + //! Local time that DST ends -- NADT if has_dst is false + virtual posix_time::ptime dst_local_end_time(gregorian::greg_year y) const + { + gregorian::date d(gregorian::not_a_date_time); + if (dst_calc_rules_) { + d = dst_calc_rules_->end_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_end_offset_); + } + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset() const + { + return base_utc_offset_; + } + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset() const + { + return dst_offsets_.dst_adjust_; + } + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const + { + // std offset dst [offset],start[/time],end[/time] - w/o spaces + stringstream_type ss; + ss.fill('0'); + boost::shared_ptr<dst_calc_rule> no_rules; + // std + ss << std_zone_abbrev(); + // offset + if(base_utc_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << base_utc_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << base_utc_offset().hours(); + } + if(base_utc_offset().minutes() != 0 || base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().minutes(); + if(base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().seconds(); + } + } + if(dst_calc_rules_ != no_rules) { + // dst + ss << dst_zone_abbrev(); + // dst offset + if(dst_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << dst_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << dst_offset().hours(); + } + if(dst_offset().minutes() != 0 || dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().minutes(); + if(dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().seconds(); + } + } + // start/time + ss << ',' << date_time::convert_string_type<char, char_type>(dst_calc_rules_->start_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_start_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_start_offset_.minutes(); + if(dst_offsets_.dst_start_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_start_offset_.seconds(); + } + // end/time + ss << ',' << date_time::convert_string_type<char, char_type>(dst_calc_rules_->end_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_end_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_end_offset_.minutes(); + if(dst_offsets_.dst_end_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_end_offset_.seconds(); + } + } + + return ss.str(); + } + private: + time_zone_names zone_names_; + bool has_dst_; + time_duration_type base_utc_offset_; + dst_adjustment_offsets dst_offsets_; + boost::shared_ptr<dst_calc_rule> dst_calc_rules_; + }; + + typedef custom_time_zone_base<char> custom_time_zone; + +} }//namespace + + + +#endif diff --git a/ext/boost/date_time/local_time/date_duration_operators.hpp b/ext/boost/date_time/local_time/date_duration_operators.hpp new file mode 100644 index 0000000000..ee870227a9 --- /dev/null +++ b/ext/boost/date_time/local_time/date_duration_operators.hpp @@ -0,0 +1,115 @@ +#ifndef LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ +#define LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" + +namespace boost { +namespace local_time { + + /*!@file date_duration_operators.hpp Operators for local_date_time and + * optional gregorian types. Operators use snap-to-end-of-month behavior. + * Further details on this behavior can be found in reference for + * date_time/date_duration_types.hpp and documentation for + * month and year iterators. + */ + + + /*! Adds a months object and a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator+(const local_date_time& t, const boost::gregorian::months& m) + { + return t + m.get_offset(t.utc_time().date()); + } + + /*! Adds a months object to a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator+=(local_date_time& t, const boost::gregorian::months& m) + { + return t += m.get_offset(t.utc_time().date()); + } + + /*! Subtracts a months object and a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator-(const local_date_time& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t + m.get_neg_offset(t.utc_time().date()); + } + + /*! Subtracts a months object from a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator-=(local_date_time& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t += m.get_neg_offset(t.utc_time().date()); + } + + // local_date_time & years + + /*! Adds a years object and a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator+(const local_date_time& t, const boost::gregorian::years& y) + { + return t + y.get_offset(t.utc_time().date()); + } + + /*! Adds a years object to a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator+=(local_date_time& t, const boost::gregorian::years& y) + { + return t += y.get_offset(t.utc_time().date()); + } + + /*! Subtracts a years object and a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator-(const local_date_time& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t + y.get_neg_offset(t.utc_time().date()); + } + + /*! Subtracts a years object from a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator-=(local_date_time& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t += y.get_neg_offset(t.utc_time().date()); + } + + +}} // namespaces + +#endif // LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ diff --git a/ext/boost/date_time/local_time/dst_transition_day_rules.hpp b/ext/boost/date_time/local_time/dst_transition_day_rules.hpp new file mode 100644 index 0000000000..3d6cfbacf4 --- /dev/null +++ b/ext/boost/date_time/local_time/dst_transition_day_rules.hpp @@ -0,0 +1,77 @@ +#ifndef LOCAL_TIME_DST_TRANSITION_DAY_RULES_HPP__ +#define LOCAL_TIME_DST_TRANSITION_DAY_RULES_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/dst_transition_generators.hpp" + +namespace boost { +namespace local_time { + + //! Provides rule of the form starting Apr 30 ending Oct 21 + typedef date_time::dst_day_calc_rule<gregorian::date> dst_calc_rule; + + struct partial_date_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::partial_date start_rule; + typedef gregorian::partial_date end_rule; + }; + + //! Provides rule of the form first Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule<partial_date_rule_spec> partial_date_dst_rule; + + struct first_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::first_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule of the form first Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule<first_last_rule_spec> first_last_dst_rule; + + struct last_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::last_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule of the form last Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule<last_last_rule_spec> last_last_dst_rule; + + struct nth_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::nth_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April, last Sunday in Oct + typedef date_time::day_calc_dst_rule<nth_last_rule_spec> nth_last_dst_rule; + + struct nth_kday_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::nth_kday_of_month start_rule; + typedef gregorian::nth_kday_of_month end_rule; + }; + + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April/October + typedef date_time::day_calc_dst_rule<nth_kday_rule_spec> nth_kday_dst_rule; + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April/October + typedef date_time::day_calc_dst_rule<nth_kday_rule_spec> nth_day_of_the_week_in_month_dst_rule; + + +} }//namespace + + +#endif diff --git a/ext/boost/date_time/local_time/local_date_time.hpp b/ext/boost/date_time/local_time/local_date_time.hpp new file mode 100644 index 0000000000..36609c3316 --- /dev/null +++ b/ext/boost/date_time/local_time/local_date_time.hpp @@ -0,0 +1,527 @@ +#ifndef LOCAL_TIME_LOCAL_DATE_TIME_HPP__ +#define LOCAL_TIME_LOCAL_DATE_TIME_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <string> +#include <iomanip> +#include <sstream> +#include <stdexcept> +#include <boost/shared_ptr.hpp> +#include <boost/throw_exception.hpp> +#include <boost/date_time/time.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> //todo remove? +#include <boost/date_time/dst_rules.hpp> +#include <boost/date_time/time_zone_base.hpp> +#include <boost/date_time/special_defs.hpp> + +namespace boost { +namespace local_time { + + //! simple exception for reporting when STD or DST cannot be determined + struct ambiguous_result : public std::logic_error + { + ambiguous_result (std::string const& msg = std::string()) : + std::logic_error(std::string("Daylight Savings Results are ambiguous: " + msg)) {} + }; + //! simple exception for when time label given cannot exist + struct time_label_invalid : public std::logic_error + { + time_label_invalid (std::string const& msg = std::string()) : + std::logic_error(std::string("Time label given is invalid: " + msg)) {} + }; + struct dst_not_valid: public std::logic_error + { + dst_not_valid(std::string const& msg = std::string()) : + std::logic_error(std::string("is_dst flag does not match resulting dst for time label given: " + msg)) {} + }; + + //TODO: I think these should be in local_date_time_base and not + // necessarily brought into the namespace + using date_time::time_is_dst_result; + using date_time::is_in_dst; + using date_time::is_not_in_dst; + using date_time::ambiguous; + using date_time::invalid_time_label; + + //! Representation of "wall-clock" time in a particular time zone + /*! Representation of "wall-clock" time in a particular time zone + * Local_date_time_base holds a time value (date and time offset from 00:00) + * along with a time zone. The time value is stored as UTC and conversions + * to wall clock time are made as needed. This approach allows for + * operations between wall-clock times in different time zones, and + * daylight savings time considerations, to be made. Time zones are + * required to be in the form of a boost::shared_ptr<time_zone_base>. + */ + template<class utc_time_=posix_time::ptime, + class tz_type=date_time::time_zone_base<utc_time_,char> > + class local_date_time_base : public date_time::base_time<utc_time_, + boost::posix_time::posix_time_system> { + public: + typedef utc_time_ utc_time_type; + typedef typename utc_time_type::time_duration_type time_duration_type; + typedef typename utc_time_type::date_type date_type; + typedef typename date_type::duration_type date_duration_type; + typedef typename utc_time_type::time_system_type time_system_type; + /*! This constructor interprets the passed time as a UTC time. + * So, for example, if the passed timezone is UTC-5 then the + * time will be adjusted back 5 hours. The time zone allows for + * automatic calculation of whether the particular time is adjusted for + * daylight savings, etc. + * If the time zone shared pointer is null then time stays unadjusted. + *@param t A UTC time + *@param tz Timezone for to adjust the UTC time to. + */ + local_date_time_base(utc_time_type t, + boost::shared_ptr<tz_type> tz) : + date_time::base_time<utc_time_type, time_system_type>(t), + zone_(tz) + { + // param was already utc so nothing more to do + } + + /*! This constructs a local time -- the passed time information + * understood to be in the passed tz. The DST flag must be passed + * to indicate whether the time is in daylight savings or not. + * @throws -- time_label_invalid if the time passed does not exist in + * the given locale. The non-existent case occurs typically + * during the shift-back from daylight savings time. When + * the clock is shifted forward a range of times + * (2 am to 3 am in the US) is skipped and hence is invalid. + * @throws -- dst_not_valid if the DST flag is passed for a period + * where DST is not active. + */ + local_date_time_base(date_type d, + time_duration_type td, + boost::shared_ptr<tz_type> tz, + bool dst_flag) : //necessary for constr_adj() + date_time::base_time<utc_time_type,time_system_type>(construction_adjustment(utc_time_type(d, td), tz, dst_flag)), + zone_(tz) + { + if(tz != boost::shared_ptr<tz_type>() && tz->has_dst()){ + + // d & td are already local so we use them + time_is_dst_result result = check_dst(d, td, tz); + bool in_dst = (result == is_in_dst); // less processing than is_dst() + + // ambig occurs at end, invalid at start + if(result == invalid_time_label){ + // Ex: 2:15am local on trans-in day in nyc, dst_flag irrelevant + std::ostringstream ss; + ss << "time given: " << d << ' ' << td; + boost::throw_exception(time_label_invalid(ss.str())); + } + else if(result != ambiguous && in_dst != dst_flag){ + // is dst_flag accurate? + // Ex: false flag in NYC in June + std::ostringstream ss; + ss.setf(std::ios_base::boolalpha); + ss << "flag given: dst=" << dst_flag << ", dst calculated: dst=" << in_dst; + boost::throw_exception(dst_not_valid(ss.str())); + } + + // everything checks out and conversion to utc already done + } + } + + //TODO maybe not the right set...Ignore the last 2 for now... + enum DST_CALC_OPTIONS { EXCEPTION_ON_ERROR, NOT_DATE_TIME_ON_ERROR }; + //ASSUME_DST_ON_ERROR, ASSUME_NOT_DST_ON_ERROR }; + + /*! This constructs a local time -- the passed time information + * understood to be in the passed tz. The DST flag is calculated + * according to the specified rule. + */ + local_date_time_base(date_type d, + time_duration_type td, + boost::shared_ptr<tz_type> tz, + DST_CALC_OPTIONS calc_option) : + // dummy value - time_ is set in constructor code + date_time::base_time<utc_time_type,time_system_type>(utc_time_type(d,td)), + zone_(tz) + { + time_is_dst_result result = check_dst(d, td, tz); + if(result == ambiguous) { + if(calc_option == EXCEPTION_ON_ERROR){ + std::ostringstream ss; + ss << "time given: " << d << ' ' << td; + boost::throw_exception(ambiguous_result(ss.str())); + } + else{ // NADT on error + this->time_ = posix_time::posix_time_system::get_time_rep(date_type(date_time::not_a_date_time), time_duration_type(date_time::not_a_date_time)); + } + } + else if(result == invalid_time_label){ + if(calc_option == EXCEPTION_ON_ERROR){ + std::ostringstream ss; + ss << "time given: " << d << ' ' << td; + boost::throw_exception(time_label_invalid(ss.str())); + } + else{ // NADT on error + this->time_ = posix_time::posix_time_system::get_time_rep(date_type(date_time::not_a_date_time), time_duration_type(date_time::not_a_date_time)); + } + } + else if(result == is_in_dst){ + utc_time_type t = + construction_adjustment(utc_time_type(d, td), tz, true); + this->time_ = posix_time::posix_time_system::get_time_rep(t.date(), + t.time_of_day()); + } + else{ + utc_time_type t = + construction_adjustment(utc_time_type(d, td), tz, false); + this->time_ = posix_time::posix_time_system::get_time_rep(t.date(), + t.time_of_day()); + } + } + + + //! Determines if given time label is in daylight savings for given zone + /*! Determines if given time label is in daylight savings for given zone. + * Takes a date and time_duration representing a local time, along + * with time zone, and returns a time_is_dst_result object as result. + */ + static time_is_dst_result check_dst(date_type d, + time_duration_type td, + boost::shared_ptr<tz_type> tz) + { + if(tz != boost::shared_ptr<tz_type>() && tz->has_dst()) { + typedef typename date_time::dst_calculator<date_type, time_duration_type> dst_calculator; + return dst_calculator::local_is_dst( + d, td, + tz->dst_local_start_time(d.year()).date(), + tz->dst_local_start_time(d.year()).time_of_day(), + tz->dst_local_end_time(d.year()).date(), + tz->dst_local_end_time(d.year()).time_of_day(), + tz->dst_offset() + ); + } + else{ + return is_not_in_dst; + } + } + + //! Simple destructor, releases time zone if last referrer + ~local_date_time_base() {}; + + //! Copy constructor + local_date_time_base(const local_date_time_base& rhs) : + date_time::base_time<utc_time_type, time_system_type>(rhs), + zone_(rhs.zone_) + {} + + //! Special values constructor + explicit local_date_time_base(const boost::date_time::special_values sv, + boost::shared_ptr<tz_type> tz = boost::shared_ptr<tz_type>()) : + date_time::base_time<utc_time_type, time_system_type>(utc_time_type(sv)), + zone_(tz) + {} + + //! returns time zone associated with calling instance + boost::shared_ptr<tz_type> zone() const + { + return zone_; + } + //! returns false is time_zone is NULL and if time value is a special_value + bool is_dst() const + { + if(zone_ != boost::shared_ptr<tz_type>() && zone_->has_dst() && !this->is_special()) { + // check_dst takes a local time, *this is utc + utc_time_type lt(this->time_); + lt += zone_->base_utc_offset(); + // dst_offset only needs to be considered with ambiguous time labels + // make that adjustment there + + switch(check_dst(lt.date(), lt.time_of_day(), zone_)){ + case is_not_in_dst: + return false; + case is_in_dst: + return true; + case ambiguous: + if(lt + zone_->dst_offset() < zone_->dst_local_end_time(lt.date().year())) { + return true; + } + break; + case invalid_time_label: + if(lt >= zone_->dst_local_start_time(lt.date().year())) { + return true; + } + break; + } + } + return false; + } + //! Returns object's time value as a utc representation + utc_time_type utc_time() const + { + return utc_time_type(this->time_); + } + //! Returns object's time value as a local representation + utc_time_type local_time() const + { + if(zone_ != boost::shared_ptr<tz_type>()){ + utc_time_type lt = this->utc_time() + zone_->base_utc_offset(); + if (is_dst()) { + lt += zone_->dst_offset(); + } + return lt; + } + return utc_time_type(this->time_); + } + //! Returns string in the form "2003-Aug-20 05:00:00 EDT" + /*! Returns string in the form "2003-Aug-20 05:00:00 EDT". If + * time_zone is NULL the time zone abbreviation will be "UTC". The time + * zone abbrev will not be included if calling object is a special_value*/ + std::string to_string() const + { + //TODO is this a temporary function ??? + std::ostringstream ss; + if(this->is_special()){ + ss << utc_time(); + return ss.str(); + } + if(zone_ == boost::shared_ptr<tz_type>()) { + ss << utc_time() << " UTC"; + return ss.str(); + } + bool is_dst_ = is_dst(); + utc_time_type lt = this->utc_time() + zone_->base_utc_offset(); + if (is_dst_) { + lt += zone_->dst_offset(); + } + ss << local_time() << " "; + if (is_dst()) { + ss << zone_->dst_zone_abbrev(); + } + else { + ss << zone_->std_zone_abbrev(); + } + return ss.str(); + } + /*! returns a local_date_time_base in the given time zone with the + * optional time_duration added. */ + local_date_time_base local_time_in(boost::shared_ptr<tz_type> new_tz, + time_duration_type td=time_duration_type(0,0,0)) const + { + return local_date_time_base(utc_time_type(this->time_) + td, new_tz); + } + + //! Returns name of associated time zone or "Coordinated Universal Time". + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00" extended iso format). Empty string is returned for + * classes that do not use a time_zone */ + std::string zone_name(bool as_offset=false) const + { + if(zone_ == boost::shared_ptr<tz_type>()) { + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("Coordinated Universal Time"); + } + } + if (is_dst()) { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->dst_zone_name(); + } + } + else { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->std_zone_name(); + } + } + } + //! Returns abbreviation of associated time zone or "UTC". + /*! Optional bool parameter will return time zone as an offset + * (ie "+0700" iso format). Empty string is returned for classes + * that do not use a time_zone */ + std::string zone_abbrev(bool as_offset=false) const + { + if(zone_ == boost::shared_ptr<tz_type>()) { + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("UTC"); + } + } + if (is_dst()) { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->dst_zone_abbrev(); + } + } + else { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->std_zone_abbrev(); + } + } + } + + //! returns a posix_time_zone string for the associated time_zone. If no time_zone, "UTC+00" is returned. + std::string zone_as_posix_string() const + { + if(zone_ == shared_ptr<tz_type>()) { + return std::string("UTC+00"); + } + return zone_->to_posix_string(); + } + + //! Equality comparison operator + /*bool operator==(const date_time::base_time<boost::posix_time::ptime,boost::posix_time::posix_time_system>& rhs) const + { // fails due to rhs.time_ being protected + return date_time::base_time<boost::posix_time::ptime,boost::posix_time::posix_time_system>::operator==(rhs); + //return this->time_ == rhs.time_; + }*/ + //! Equality comparison operator + bool operator==(const local_date_time_base& rhs) const + { + return time_system_type::is_equal(this->time_, rhs.time_); + } + //! Non-Equality comparison operator + bool operator!=(const local_date_time_base& rhs) const + { + return !(*this == rhs); + } + //! Less than comparison operator + bool operator<(const local_date_time_base& rhs) const + { + return time_system_type::is_less(this->time_, rhs.time_); + } + //! Less than or equal to comparison operator + bool operator<=(const local_date_time_base& rhs) const + { + return (*this < rhs || *this == rhs); + } + //! Greater than comparison operator + bool operator>(const local_date_time_base& rhs) const + { + return !(*this <= rhs); + } + //! Greater than or equal to comparison operator + bool operator>=(const local_date_time_base& rhs) const + { + return (*this > rhs || *this == rhs); + } + + //! Local_date_time + date_duration + local_date_time_base operator+(const date_duration_type& dd) const + { + return local_date_time_base(time_system_type::add_days(this->time_,dd), zone_); + } + //! Local_date_time += date_duration + local_date_time_base operator+=(const date_duration_type& dd) + { + this->time_ = time_system_type::add_days(this->time_,dd); + return *this; + } + //! Local_date_time - date_duration + local_date_time_base operator-(const date_duration_type& dd) const + { + return local_date_time_base(time_system_type::subtract_days(this->time_,dd), zone_); + } + //! Local_date_time -= date_duration + local_date_time_base operator-=(const date_duration_type& dd) + { + this->time_ = time_system_type::subtract_days(this->time_,dd); + return *this; + } + //! Local_date_time + time_duration + local_date_time_base operator+(const time_duration_type& td) const + { + return local_date_time_base(time_system_type::add_time_duration(this->time_,td), zone_); + } + //! Local_date_time += time_duration + local_date_time_base operator+=(const time_duration_type& td) + { + this->time_ = time_system_type::add_time_duration(this->time_,td); + return *this; + } + //! Local_date_time - time_duration + local_date_time_base operator-(const time_duration_type& td) const + { + return local_date_time_base(time_system_type::subtract_time_duration(this->time_,td), zone_); + } + //! Local_date_time -= time_duration + local_date_time_base operator-=(const time_duration_type& td) + { + this->time_ = time_system_type::subtract_time_duration(this->time_,td); + return *this; + } + //! local_date_time -= local_date_time --> time_duration_type + time_duration_type operator-(const local_date_time_base& rhs) const + { + return utc_time_type(this->time_) - utc_time_type(rhs.time_); + } + private: + boost::shared_ptr<tz_type> zone_; + //bool is_dst_; + + /*! Adjust the passed in time to UTC? + */ + utc_time_type construction_adjustment(utc_time_type t, + boost::shared_ptr<tz_type> z, + bool dst_flag) + { + if(z != boost::shared_ptr<tz_type>()) { + if(dst_flag && z->has_dst()) { + t -= z->dst_offset(); + } // else no adjust + t -= z->base_utc_offset(); + } + return t; + } + + /*! Simple formatting code -- todo remove this? + */ + std::string zone_as_offset(const time_duration_type& td, + const std::string& separator) const + { + std::ostringstream ss; + if(td.is_negative()) { + // a negative duration is represented as "-[h]h:mm" + // we require two digits for the hour. A positive duration + // with the %H flag will always give two digits + ss << "-"; + } + else { + ss << "+"; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()) + << separator + << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()); + return ss.str(); + } + }; + + //!Use the default parameters to define local_date_time + typedef local_date_time_base<> local_date_time; + +} } + + +#endif diff --git a/ext/boost/date_time/local_time/local_time.hpp b/ext/boost/date_time/local_time/local_time.hpp new file mode 100644 index 0000000000..f7d4cc68e3 --- /dev/null +++ b/ext/boost/date_time/local_time/local_time.hpp @@ -0,0 +1,24 @@ +#ifndef LOCAL_TIME_LOCAL_TIME_HPP__ +#define LOCAL_TIME_LOCAL_TIME_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/local_time/local_time_types.hpp" +#if !defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/local_time/local_time_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO +#include "boost/date_time/local_time/posix_time_zone.hpp" +#include "boost/date_time/local_time/custom_time_zone.hpp" +#include "boost/date_time/local_time/tz_database.hpp" +#include "boost/date_time/local_time/conversion.hpp" +#include "boost/date_time/time_zone_base.hpp" + + +#endif diff --git a/ext/boost/date_time/local_time/local_time_io.hpp b/ext/boost/date_time/local_time/local_time_io.hpp new file mode 100644 index 0000000000..c161ff7e23 --- /dev/null +++ b/ext/boost/date_time/local_time/local_time_io.hpp @@ -0,0 +1,186 @@ +#ifndef BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ +#define BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-13 14:05:31 -0500 (Thu, 13 Nov 2008) $ + */ + +#include <locale> +#include <iostream> +#include <iterator> // i/ostreambuf_iterator +#include <boost/io/ios_state.hpp> +#include <boost/date_time/time_facet.hpp> +#include <boost/date_time/string_convert.hpp> +#include <boost/date_time/local_time/local_date_time.hpp> +#include <boost/date_time/local_time/posix_time_zone.hpp> +#include <boost/date_time/local_time/conversion.hpp> // to_tm will be needed in the facets + +namespace boost { +namespace local_time { + + typedef boost::date_time::time_facet<local_date_time, wchar_t> wlocal_time_facet; + typedef boost::date_time::time_facet<local_date_time, char> local_time_facet; + + typedef boost::date_time::time_input_facet<local_date_time::utc_time_type,wchar_t> wlocal_time_input_facet; + typedef boost::date_time::time_input_facet<local_date_time::utc_time_type,char> local_time_input_facet; + + //! operator<< for local_date_time - see local_time docs for formatting details + template<class CharT, class TraitsT> + inline + std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, const local_date_time& ldt) + { + boost::io::ios_flags_saver iflags(os); + typedef local_date_time time_type;//::utc_time_type typename + typedef date_time::time_facet<time_type, CharT> custom_time_facet; + typedef std::time_put<CharT> std_time_facet; + std::ostreambuf_iterator<CharT> oitr(os); + + if(std::has_facet<custom_time_facet>(os.getloc())) { + std::use_facet<custom_time_facet>(os.getloc()).put(oitr, + os, + os.fill(), + ldt); + } + else { + custom_time_facet* f = new custom_time_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), ldt); + } + + return os; + } + + + //! input operator for local_date_time + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, local_date_time& ldt) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename local_date_time::utc_time_type utc_time_type; + typedef typename date_time::time_input_facet<utc_time_type, CharT> time_input_facet; + + // intermediate objects + std::basic_string<CharT> tz_str; + utc_time_type pt(not_a_date_time); + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<time_input_facet>(is.getloc())) { + std::use_facet<time_input_facet>(is.getloc()).get_local_time(sit, str_end, is, pt, tz_str); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get_local_time(sit, str_end, is, pt, tz_str); + } + if(tz_str.empty()) { + time_zone_ptr null_ptr; + // a null time_zone_ptr creates a local_date_time that is UTC + ldt = local_date_time(pt, null_ptr); + } + else { + time_zone_ptr tz_ptr(new posix_time_zone(date_time::convert_string_type<CharT,char>(tz_str))); + // the "date & time" constructor expects the time label to *not* be utc. + // a posix_tz_string also expects the time label to *not* be utc. + ldt = local_date_time(pt.date(), pt.time_of_day(), tz_ptr, local_date_time::EXCEPTION_ON_ERROR); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + //! output operator for local_time_period + template <class CharT, class TraitsT> + inline + std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, + const boost::local_time::local_time_period& p) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet<local_date_time, CharT> custom_facet; + typedef std::time_put<CharT> std_time_facet; + std::ostreambuf_iterator<CharT> oitr(os); + if (std::has_facet<custom_facet>(os.getloc())) { + std::use_facet<custom_facet>(os.getloc()).put(oitr, os, os.fill(), p); + } + else { + //instantiate a custom facet for dealing with periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues as some later point. + custom_facet* f = new custom_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + //! input operator for local_time_period + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, boost::local_time::local_time_period& tp) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet<local_date_time, CharT> time_input_facet; + + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<time_input_facet>(is.getloc())) { + std::use_facet<time_input_facet>(is.getloc()).get(sit, str_end, is, tp); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, tp); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + +} } // namespaces + +#endif // BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ diff --git a/ext/boost/date_time/local_time/local_time_types.hpp b/ext/boost/date_time/local_time/local_time_types.hpp new file mode 100644 index 0000000000..ed58b8018a --- /dev/null +++ b/ext/boost/date_time/local_time/local_time_types.hpp @@ -0,0 +1,52 @@ +#ifndef LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ +#define LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/time_iterator.hpp" +#include "boost/date_time/compiler_config.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/local_time/date_duration_operators.hpp" +#endif //BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +#include "boost/date_time/local_time/custom_time_zone.hpp" + +namespace boost { +namespace local_time { + + typedef boost::date_time::period<local_date_time, + boost::posix_time::time_duration> local_time_period; + + typedef date_time::time_itr<local_date_time> local_time_iterator; + + typedef date_time::second_clock<local_date_time> local_sec_clock; + typedef date_time::microsec_clock<local_date_time> local_microsec_clock; + + typedef date_time::time_zone_base<posix_time::ptime, char> time_zone; + typedef date_time::time_zone_base<posix_time::ptime, wchar_t> wtime_zone; + + //! Shared Pointer for custom_time_zone and posix_time_zone objects + typedef boost::shared_ptr<time_zone> time_zone_ptr; + typedef boost::shared_ptr<wtime_zone> wtime_zone_ptr; + + typedef date_time::time_zone_names_base<char> time_zone_names; + typedef date_time::time_zone_names_base<wchar_t> wtime_zone_names; + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + +}} // namespaces + +#endif // LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ diff --git a/ext/boost/date_time/local_time/posix_time_zone.hpp b/ext/boost/date_time/local_time/posix_time_zone.hpp new file mode 100644 index 0000000000..f8d968aa4e --- /dev/null +++ b/ext/boost/date_time/local_time/posix_time_zone.hpp @@ -0,0 +1,464 @@ +#ifndef _DATE_TIME_POSIX_TIME_ZONE__ +#define _DATE_TIME_POSIX_TIME_ZONE__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-26 10:39:19 -0500 (Wed, 26 Nov 2008) $ + */ + +#include <string> +#include <sstream> +#include <stdexcept> +#include <boost/tokenizer.hpp> +#include <boost/throw_exception.hpp> +#include <boost/date_time/gregorian/gregorian.hpp> +#include <boost/date_time/time_zone_names.hpp> +#include <boost/date_time/time_zone_base.hpp> +#include <boost/date_time/local_time/dst_transition_day_rules.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/date_time/string_convert.hpp> +#include <boost/date_time/time_parsing.hpp> + +namespace boost{ +namespace local_time{ + + //! simple exception for UTC and Daylight savings start/end offsets + struct bad_offset : public std::out_of_range + { + bad_offset(std::string const& msg = std::string()) : + std::out_of_range(std::string("Offset out of range: " + msg)) {} + }; + //! simple exception for UTC daylight savings adjustment + struct bad_adjustment : public std::out_of_range + { + bad_adjustment(std::string const& msg = std::string()) : + std::out_of_range(std::string("Adjustment out of range: " + msg)) {} + }; + + typedef boost::date_time::dst_adjustment_offsets<boost::posix_time::time_duration> dst_adjustment_offsets; + + //! A time zone class constructed from a POSIX time zone string + /*! A POSIX time zone string takes the form of:<br> + * "std offset dst [offset],start[/time],end[/time]" (w/no spaces) + * 'std' specifies the abbrev of the time zone.<br> + * 'offset' is the offset from UTC.<br> + * 'dst' specifies the abbrev of the time zone during daylight savings time.<br> + * The second offset is how many hours changed during DST. Default=1<br> + * 'start' and'end' are the dates when DST goes into (and out of) effect.<br> + * 'offset' takes the form of: [+|-]hh[:mm[:ss]] {h=0-23, m/s=0-59}<br> + * 'time' and 'offset' take the same form. Time defaults=02:00:00<br> + * 'start' and 'end' can be one of three forms:<br> + * Mm.w.d {month=1-12, week=1-5 (5 is always last), day=0-6}<br> + * Jn {n=1-365 Feb29 is never counted}<br> + * n {n=0-365 Feb29 is counted in leap years}<br> + * Example "PST-5PDT01:00:00,M4.1.0/02:00:00,M10.1.0/02:00:00" + * <br> + * Exceptions will be thrown under these conditions:<br> + * An invalid date spec (see date class)<br> + * A boost::local_time::bad_offset exception will be thrown for:<br> + * A DST start or end offset that is negative or more than 24 hours<br> + * A UTC zone that is greater than +12 or less than -12 hours<br> + * A boost::local_time::bad_adjustment exception will be thrown for:<br> + * A DST adjustment that is 24 hours or more (positive or negative)<br> + */ + template<class CharT> + class posix_time_zone_base : public date_time::time_zone_base<posix_time::ptime,CharT> { + public: + typedef boost::posix_time::time_duration time_duration_type; + typedef date_time::time_zone_names_base<CharT> time_zone_names; + typedef date_time::time_zone_base<posix_time::ptime,CharT> base_type; + typedef typename base_type::string_type string_type; + typedef CharT char_type; + typedef typename base_type::stringstream_type stringstream_type; + typedef boost::char_separator<char_type, std::char_traits<char_type> > char_separator_type; + typedef boost::tokenizer<char_separator_type, + typename string_type::const_iterator, + string_type> tokenizer_type; + typedef typename boost::tokenizer<char_separator_type, + typename string_type::const_iterator, + string_type>::iterator tokenizer_iterator_type; + + //! Construct from a POSIX time zone string + posix_time_zone_base(const string_type& s) : + //zone_names_("std_name","std_abbrev","no-dst","no-dst"), + zone_names_(), + has_dst_(false), + base_utc_offset_(posix_time::hours(0)), + dst_offsets_(posix_time::hours(0),posix_time::hours(0),posix_time::hours(0)), + dst_calc_rules_() + { +#ifdef __HP_aCC + // Work around bug in aC++ compiler: see QXCR1000880488 in the + // HP bug tracking system + const char_type sep_chars[2] = {',',0}; +#else + const char_type sep_chars[2] = {','}; +#endif + char_separator_type sep(sep_chars); + tokenizer_type tokens(s, sep); + tokenizer_iterator_type it = tokens.begin(); + calc_zone(*it++); + if(has_dst_){ + string_type tmp_str = *it++; + calc_rules(tmp_str, *it); + } + } + virtual ~posix_time_zone_base() {}; + //!String for the zone when not in daylight savings (eg: EST) + virtual string_type std_zone_abbrev()const + { + return zone_names_.std_zone_abbrev(); + } + //!String for the timezone when in daylight savings (eg: EDT) + /*! For those time zones that have no DST, an empty string is used */ + virtual string_type dst_zone_abbrev() const + { + return zone_names_.dst_zone_abbrev(); + } + //!String for the zone when not in daylight savings (eg: Eastern Standard Time) + /*! The full STD name is not extracted from the posix time zone string. + * Therefore, the STD abbreviation is used in it's place */ + virtual string_type std_zone_name()const + { + return zone_names_.std_zone_name(); + } + //!String for the timezone when in daylight savings (eg: Eastern Daylight Time) + /*! The full DST name is not extracted from the posix time zone string. + * Therefore, the STD abbreviation is used in it's place. For time zones + * that have no DST, an empty string is used */ + virtual string_type dst_zone_name()const + { + return zone_names_.dst_zone_name(); + } + //! True if zone uses daylight savings adjustments otherwise false + virtual bool has_dst()const + { + return has_dst_; + } + //! Local time that DST starts -- NADT if has_dst is false + virtual posix_time::ptime dst_local_start_time(gregorian::greg_year y)const + { + gregorian::date d(gregorian::not_a_date_time); + if(has_dst_) + { + d = dst_calc_rules_->start_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_start_offset_); + } + //! Local time that DST ends -- NADT if has_dst is false + virtual posix_time::ptime dst_local_end_time(gregorian::greg_year y)const + { + gregorian::date d(gregorian::not_a_date_time); + if(has_dst_) + { + d = dst_calc_rules_->end_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_end_offset_); + } + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset()const + { + return base_utc_offset_; + } + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset()const + { + return dst_offsets_.dst_adjust_; + } + + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const + { + // std offset dst [offset],start[/time],end[/time] - w/o spaces + stringstream_type ss; + ss.fill('0'); + boost::shared_ptr<dst_calc_rule> no_rules; + // std + ss << std_zone_abbrev(); + // offset + if(base_utc_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << base_utc_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << base_utc_offset().hours(); + } + if(base_utc_offset().minutes() != 0 || base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().minutes(); + if(base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().seconds(); + } + } + if(dst_calc_rules_ != no_rules) { + // dst + ss << dst_zone_abbrev(); + // dst offset + if(dst_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << dst_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << dst_offset().hours(); + } + if(dst_offset().minutes() != 0 || dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().minutes(); + if(dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().seconds(); + } + } + // start/time + ss << ',' << date_time::convert_string_type<char, char_type>(dst_calc_rules_->start_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_start_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_start_offset_.minutes(); + if(dst_offsets_.dst_start_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_start_offset_.seconds(); + } + // end/time + ss << ',' << date_time::convert_string_type<char, char_type>(dst_calc_rules_->end_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_end_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_end_offset_.minutes(); + if(dst_offsets_.dst_end_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_end_offset_.seconds(); + } + } + + return ss.str(); + } + private: + time_zone_names zone_names_; + bool has_dst_; + time_duration_type base_utc_offset_; + dst_adjustment_offsets dst_offsets_; + boost::shared_ptr<dst_calc_rule> dst_calc_rules_; + + /*! Extract time zone abbreviations for STD & DST as well + * as the offsets for the time shift that occurs and how + * much of a shift. At this time full time zone names are + * NOT extracted so the abbreviations are used in their place */ + void calc_zone(const string_type& obj){ + const char_type empty_string[2] = {'\0'}; + stringstream_type ss(empty_string); + typename string_type::const_pointer sit = obj.c_str(), obj_end = sit + obj.size(); + string_type l_std_zone_abbrev, l_dst_zone_abbrev; + + // get 'std' name/abbrev + while(std::isalpha(*sit)){ + ss << *sit++; + } + l_std_zone_abbrev = ss.str(); + ss.str(empty_string); + + // get UTC offset + if(sit != obj_end){ + // get duration + while(sit != obj_end && !std::isalpha(*sit)){ + ss << *sit++; + } + base_utc_offset_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(ss.str()); + ss.str(empty_string); + + // base offset must be within range of -12 hours to +12 hours + if(base_utc_offset_ < time_duration_type(-12,0,0) || + base_utc_offset_ > time_duration_type(12,0,0)) + { + boost::throw_exception(bad_offset(posix_time::to_simple_string(base_utc_offset_))); + } + } + + // get DST data if given + if(sit != obj_end){ + has_dst_ = true; + + // get 'dst' name/abbrev + while(sit != obj_end && std::isalpha(*sit)){ + ss << *sit++; + } + l_dst_zone_abbrev = ss.str(); + ss.str(empty_string); + + // get DST offset if given + if(sit != obj_end){ + // get duration + while(sit != obj_end && !std::isalpha(*sit)){ + ss << *sit++; + } + dst_offsets_.dst_adjust_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(ss.str()); + ss.str(empty_string); + } + else{ // default DST offset + dst_offsets_.dst_adjust_ = posix_time::hours(1); + } + + // adjustment must be within +|- 1 day + if(dst_offsets_.dst_adjust_ <= time_duration_type(-24,0,0) || + dst_offsets_.dst_adjust_ >= time_duration_type(24,0,0)) + { + boost::throw_exception(bad_adjustment(posix_time::to_simple_string(dst_offsets_.dst_adjust_))); + } + } + // full names not extracted so abbrevs used in their place + zone_names_ = time_zone_names(l_std_zone_abbrev, l_std_zone_abbrev, l_dst_zone_abbrev, l_dst_zone_abbrev); + } + + void calc_rules(const string_type& start, const string_type& end){ +#ifdef __HP_aCC + // Work around bug in aC++ compiler: see QXCR1000880488 in the + // HP bug tracking system + const char_type sep_chars[2] = {'/',0}; +#else + const char_type sep_chars[2] = {'/'}; +#endif + char_separator_type sep(sep_chars); + tokenizer_type st_tok(start, sep); + tokenizer_type et_tok(end, sep); + tokenizer_iterator_type sit = st_tok.begin(); + tokenizer_iterator_type eit = et_tok.begin(); + + // generate date spec + char_type x = string_type(*sit).at(0); + if(x == 'M'){ + M_func(*sit, *eit); + } + else if(x == 'J'){ + julian_no_leap(*sit, *eit); + } + else{ + julian_day(*sit, *eit); + } + + ++sit; + ++eit; + // generate durations + // starting offset + if(sit != st_tok.end()){ + dst_offsets_.dst_start_offset_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(*sit); + } + else{ + // default + dst_offsets_.dst_start_offset_ = posix_time::hours(2); + } + // start/end offsets must fall on given date + if(dst_offsets_.dst_start_offset_ < time_duration_type(0,0,0) || + dst_offsets_.dst_start_offset_ >= time_duration_type(24,0,0)) + { + boost::throw_exception(bad_offset(posix_time::to_simple_string(dst_offsets_.dst_start_offset_))); + } + + // ending offset + if(eit != et_tok.end()){ + dst_offsets_.dst_end_offset_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(*eit); + } + else{ + // default + dst_offsets_.dst_end_offset_ = posix_time::hours(2); + } + // start/end offsets must fall on given date + if(dst_offsets_.dst_end_offset_ < time_duration_type(0,0,0) || + dst_offsets_.dst_end_offset_ >= time_duration_type(24,0,0)) + { + boost::throw_exception(bad_offset(posix_time::to_simple_string(dst_offsets_.dst_end_offset_))); + } + } + + /* Parses out a start/end date spec from a posix time zone string. + * Date specs come in three possible formats, this function handles + * the 'M' spec. Ex "M2.2.4" => 2nd month, 2nd week, 4th day . + */ + void M_func(const string_type& s, const string_type& e){ + typedef gregorian::nth_kday_of_month nkday; + unsigned short sm=0,sw=0,sd=0,em=0,ew=0,ed=0; // start/end month,week,day +#ifdef __HP_aCC + // Work around bug in aC++ compiler: see QXCR1000880488 in the + // HP bug tracking system + const char_type sep_chars[3] = {'M','.',0}; +#else + const char_type sep_chars[3] = {'M','.'}; +#endif + char_separator_type sep(sep_chars); + tokenizer_type stok(s, sep), etok(e, sep); + + tokenizer_iterator_type it = stok.begin(); + sm = lexical_cast<unsigned short>(*it++); + sw = lexical_cast<unsigned short>(*it++); + sd = lexical_cast<unsigned short>(*it); + + it = etok.begin(); + em = lexical_cast<unsigned short>(*it++); + ew = lexical_cast<unsigned short>(*it++); + ed = lexical_cast<unsigned short>(*it); + + dst_calc_rules_ = shared_ptr<dst_calc_rule>( + new nth_kday_dst_rule( + nth_last_dst_rule::start_rule( + static_cast<nkday::week_num>(sw),sd,sm), + nth_last_dst_rule::start_rule( + static_cast<nkday::week_num>(ew),ed,em) + ) + ); + } + + //! Julian day. Feb29 is never counted, even in leap years + // expects range of 1-365 + void julian_no_leap(const string_type& s, const string_type& e){ + typedef gregorian::gregorian_calendar calendar; + const unsigned short year = 2001; // Non-leap year + unsigned short sm=1; + int sd=0; + sd = lexical_cast<int>(s.substr(1)); // skip 'J' + while(sd >= calendar::end_of_month_day(year,sm)){ + sd -= calendar::end_of_month_day(year,sm++); + } + unsigned short em=1; + int ed=0; + ed = lexical_cast<int>(e.substr(1)); // skip 'J' + while(ed > calendar::end_of_month_day(year,em)){ + ed -= calendar::end_of_month_day(year,em++); + } + + dst_calc_rules_ = shared_ptr<dst_calc_rule>( + new partial_date_dst_rule( + partial_date_dst_rule::start_rule( + sd, static_cast<date_time::months_of_year>(sm)), + partial_date_dst_rule::end_rule( + ed, static_cast<date_time::months_of_year>(em)) + ) + ); + } + + //! Julian day. Feb29 is always counted, but exception thrown in non-leap years + // expects range of 0-365 + void julian_day(const string_type& s, const string_type& e){ + int sd=0, ed=0; + sd = lexical_cast<int>(s); + ed = lexical_cast<int>(e); + dst_calc_rules_ = shared_ptr<dst_calc_rule>( + new partial_date_dst_rule( + partial_date_dst_rule::start_rule(++sd),// args are 0-365 + partial_date_dst_rule::end_rule(++ed) // pd expects 1-366 + ) + ); + } + + //! helper function used when throwing exceptions + static std::string td_as_string(const time_duration_type& td) + { + std::string s; +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + s = posix_time::to_simple_string(td); +#else + std::stringstream ss; + ss << td; + s = ss.str(); +#endif + return s; + } + }; + + typedef posix_time_zone_base<char> posix_time_zone; + +} } // namespace boost::local_time + + +#endif // _DATE_TIME_POSIX_TIME_ZONE__ diff --git a/ext/boost/date_time/local_time/tz_database.hpp b/ext/boost/date_time/local_time/tz_database.hpp new file mode 100644 index 0000000000..4cfca45c18 --- /dev/null +++ b/ext/boost/date_time/local_time/tz_database.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_DATE_TIME_TZ_DATABASE_HPP__ +#define BOOST_DATE_TIME_TZ_DATABASE_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include <string> +#include "boost/date_time/local_time/custom_time_zone.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/tz_db_base.hpp" + + +namespace boost { +namespace local_time { + + using date_time::data_not_accessible; + using date_time::bad_field_count; + + //! Object populated with boost::shared_ptr<time_zone_base> objects + /*! Object populated with boost::shared_ptr<time_zone_base> objects + * Database is populated from specs stored in external csv file. See + * date_time::tz_db_base for greater detail */ + typedef date_time::tz_db_base<custom_time_zone, nth_kday_dst_rule> tz_database; + +}} // namespace + +#endif // BOOST_DATE_TIME_TZ_DATABASE_HPP__ + diff --git a/ext/boost/date_time/local_time_adjustor.hpp b/ext/boost/date_time/local_time_adjustor.hpp new file mode 100644 index 0000000000..eea4d37ae3 --- /dev/null +++ b/ext/boost/date_time/local_time_adjustor.hpp @@ -0,0 +1,218 @@ +#ifndef DATE_TIME_LOCAL_TIME_ADJUSTOR_HPP__ +#define DATE_TIME_LOCAL_TIME_ADJUSTOR_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +/*! @file local_time_adjustor.hpp + Time adjustment calculations for local times +*/ + +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/date_generators.hpp> +#include <boost/date_time/dst_rules.hpp> +#include <boost/date_time/time_defs.hpp> // boost::date_time::dst_flags +#include <boost/date_time/special_defs.hpp> // not_a_date_time + +namespace boost { + namespace date_time { + + + //! Provides a base offset adjustment from utc + template<class time_duration_type, + short hours, unsigned short minutes = 0> + class utc_adjustment + { + public: + static time_duration_type local_to_utc_base_offset() + { + time_duration_type td(hours,minutes,0); + return td.invert_sign(); + } + static time_duration_type utc_to_local_base_offset() + { + return time_duration_type(hours,minutes,0); + } + }; + + + + //! Allow sliding utc adjustment with fixed dst rules + template<class time_type, class dst_rules> + class dynamic_local_time_adjustor : public dst_rules + { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + + dynamic_local_time_adjustor(time_duration_type utc_offset) : + utc_offset_(utc_offset) + {} + + //! Presumes local time + time_duration_type utc_offset(bool is_dst) + { + if (is_dst) { + return utc_offset_ + this->dst_offset(); + } + else { + return utc_offset_; + } + + } + private: + time_duration_type utc_offset_; + + }; + + + + //! Embed the rules for local time adjustments at compile time + template<class time_type, class dst_rules, class utc_offset_rules> + class static_local_time_adjustor: public dst_rules, public utc_offset_rules + { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + + //! Calculates the offset from a utc time to local based on dst and utc offset + /*! @param t UTC time to calculate offset to local time + * This adjustment depends on the following observations about the + * workings of the DST boundary offset. Since UTC time labels are + * monotonically increasing we can determine if a given local time + * is in DST or not and therefore adjust the offset appropriately. + * + * The logic is as follows. Starting with UTC time use the offset to + * create a label for an non-dst adjusted local time. Then call + * dst_rules::local_is_dst with the non adjust local time. The + * results of this function will either unabiguously decide that + * the initial local time is in dst or return an illegal or + * ambiguous result. An illegal result only occurs at the end + * of dst (where labels are skipped) and indicates that dst has + * ended. An ambiguous result means that we need to recheck by + * making a dst adjustment and then rechecking. If the dst offset + * is added to the utc time and the recheck proves non-ambiguous + * then we are past the boundary. If it is still ambiguous then + * we are ahead of the boundary and dst is still in effect. + * + * TODO -- check if all dst offsets are positive. If not then + * the algorithm needs to check for this and reverse the + * illegal/ambiguous logic. + */ + static time_duration_type utc_to_local_offset(const time_type& t) + { + //get initial local time guess by applying utc offset + time_type initial = t + utc_offset_rules::utc_to_local_base_offset(); + time_is_dst_result dst_flag = + dst_rules::local_is_dst(initial.date(), initial.time_of_day()); + switch(dst_flag) { + case is_in_dst: return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset(); + case is_not_in_dst: return utc_offset_rules::utc_to_local_base_offset(); + case invalid_time_label:return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset(); + case ambiguous: { + time_type retry = initial + dst_rules::dst_offset(); + dst_flag = dst_rules::local_is_dst(retry.date(), retry.time_of_day()); + //if still ambibuous then the utc time still translates to a dst time + if (dst_flag == ambiguous) { + return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset(); + } + // we are past the dst boundary + else { + return utc_offset_rules::utc_to_local_base_offset(); + } + } + }//case + //TODO better exception type + boost::throw_exception(std::out_of_range("Unreachable case")); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return time_duration_type(not_a_date_time)); // should never reach + } + + //! Get the offset to UTC given a local time + static time_duration_type local_to_utc_offset(const time_type& t, + date_time::dst_flags dst=date_time::calculate) + { + switch (dst) { + case is_dst: + return utc_offset_rules::local_to_utc_base_offset() - dst_rules::dst_offset(); + case not_dst: + return utc_offset_rules::local_to_utc_base_offset(); + case calculate: + time_is_dst_result res = + dst_rules::local_is_dst(t.date(), t.time_of_day()); + switch(res) { + case is_in_dst: return utc_offset_rules::local_to_utc_base_offset() - dst_rules::dst_offset(); + case is_not_in_dst: return utc_offset_rules::local_to_utc_base_offset(); + case ambiguous: return utc_offset_rules::local_to_utc_base_offset(); + case invalid_time_label: break; + } + } + boost::throw_exception(std::out_of_range("Time label invalid")); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return time_duration_type(not_a_date_time)); // should never reach + } + + + private: + + }; + + void dummy_to_prevent_msvc6_ice(); //why ask why? + + //! Template that simplifies the creation of local time calculator + /*! Use this template to create the timezone to utc convertors as required. + * + * This class will also work for other regions that don't use dst and + * have a utc offset which is an integral number of hours. + * + * <b>Template Parameters</b> + * -time_type -- Time class to use + * -utc_offset -- Number hours local time is adjust from utc + * -use_dst -- true (default) if region uses dst, false otherwise + * For example: + * @code + * //eastern timezone is utc-5 + typedef date_time::local_adjustor<ptime, -5, us_dst> us_eastern; + typedef date_time::local_adjustor<ptime, -6, us_dst> us_central; + typedef date_time::local_adjustor<ptime, -7, us_dst> us_mountain; + typedef date_time::local_adjustor<ptime, -8, us_dst> us_pacific; + typedef date_time::local_adjustor<ptime, -7, no_dst> us_arizona; + @endcode + + */ + template<class time_type, short utc_offset, class dst_rule> + class local_adjustor + { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + typedef static_local_time_adjustor<time_type, + dst_rule, + utc_adjustment<time_duration_type, + utc_offset> > dst_adjustor; + //! Convert a utc time to local time + static time_type utc_to_local(const time_type& t) + { + time_duration_type td = dst_adjustor::utc_to_local_offset(t); + return t + td; + } + //! Convert a local time to utc + static time_type local_to_utc(const time_type& t, + date_time::dst_flags dst=date_time::calculate) + { + time_duration_type td = dst_adjustor::local_to_utc_offset(t, dst); + return t + td; + } + }; + + + } } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/local_timezone_defs.hpp b/ext/boost/date_time/local_timezone_defs.hpp new file mode 100644 index 0000000000..fd6d3c2fab --- /dev/null +++ b/ext/boost/date_time/local_timezone_defs.hpp @@ -0,0 +1,193 @@ +#ifndef DATE_TIME_LOCAL_TIMEZONE_DEFS_HPP__ +#define DATE_TIME_LOCAL_TIMEZONE_DEFS_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-11-13 15:10:23 -0500 (Thu, 13 Nov 2008) $ + */ + +#include "boost/date_time/dst_rules.hpp" + +namespace boost { + namespace date_time { + + // Configurations for common dst rules cases: + // See http://www.wharton.co.uk/Support/sup_dst.htm for more + // information on how various locales use dst rules + + //! Specification for daylight savings start rules in US + /*! This class is used to configure dst_calc_engine template typically + as follows: + @code + using namespace boost::gregorian; + using namespace boost::posix_time; + typedef us_dst_trait<date> us_dst_traits; + typedef boost::date_time::dst_calc_engine<date, time_duration, + us_dst_traits> + us_dst_calc; + //calculate the 2002 transition day of USA April 7 2002 + date dst_start = us_dst_calc::local_dst_start_day(2002); + + //calculate the 2002 transition day of USA Oct 27 2002 + date dst_end = us_dst_calc::local_dst_end_day(2002); + + //check if a local time is in dst or not -- posible answers + //are yes, no, invalid time label, ambiguous + ptime t(...some time...); + if (us_dst::local_is_dst(t.date(), t.time_of_day()) + == boost::date_time::is_not_in_dst) + { + + } + + @endcode + This generates a type suitable for the calculation of dst + transitions for the United States. Of course other templates + can be used for other locales. + + */ + + template<class date_type> + struct us_dst_trait + { + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef date_time::nth_kday_of_month<date_type> start_rule_functor; + typedef date_time::first_kday_of_month<date_type> end_rule_functor; + typedef date_time::first_kday_of_month<date_type> start_rule_functor_pre2007; + typedef date_time::last_kday_of_month<date_type> end_rule_functor_pre2007; + static day_of_week_type start_day(year_type) {return Sunday;} + static month_type start_month(year_type y) + { + if (y < 2007) return Apr; + return Mar; + } + static day_of_week_type end_day(year_type) {return Sunday;} + static month_type end_month(year_type y) + { + if (y < 2007) return Oct; + return Nov; + } + static date_type local_dst_start_day(year_type year) + { + if (year < 2007) { + start_rule_functor_pre2007 start1(start_day(year), + start_month(year)); + return start1.get_date(year); + } + start_rule_functor start(start_rule_functor::second, + start_day(year), + start_month(year)); + return start.get_date(year); + + } + static date_type local_dst_end_day(year_type year) + { + if (year < 2007) { + end_rule_functor_pre2007 end_rule(end_day(year), + end_month(year)); + return end_rule.get_date(year); + } + end_rule_functor end(end_day(year), + end_month(year)); + return end.get_date(year); + } + static int dst_start_offset_minutes() { return 120;} + static int dst_end_offset_minutes() { return 120; } + static int dst_shift_length_minutes() { return 60; } + }; + + //!Rules for daylight savings start in the EU (Last Sun in Mar) + /*!These amount to the following: + - Start of dst day is last Sunday in March + - End day of dst is last Sunday in Oct + - Going forward switch time is 2:00 am (offset 120 minutes) + - Going back switch time is 3:00 am (off set 180 minutes) + - Shift duration is one hour (60 minutes) + */ + template<class date_type> + struct eu_dst_trait + { + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef date_time::last_kday_of_month<date_type> start_rule_functor; + typedef date_time::last_kday_of_month<date_type> end_rule_functor; + static day_of_week_type start_day(year_type) {return Sunday;} + static month_type start_month(year_type) {return Mar;} + static day_of_week_type end_day(year_type) {return Sunday;} + static month_type end_month(year_type) {return Oct;} + static int dst_start_offset_minutes() { return 120;} + static int dst_end_offset_minutes() { return 180; } + static int dst_shift_length_minutes() { return 60; } + static date_type local_dst_start_day(year_type year) + { + start_rule_functor start(start_day(year), + start_month(year)); + return start.get_date(year); + } + static date_type local_dst_end_day(year_type year) + { + end_rule_functor end(end_day(year), + end_month(year)); + return end.get_date(year); + } + }; + + //! Alternative dst traits for some parts of the United Kingdom + /* Several places in the UK use EU start and end rules for the + day, but different local conversion times (eg: forward change at 1:00 + am local and backward change at 2:00 am dst instead of 2:00am + forward and 3:00am back for the EU). + */ + template<class date_type> + struct uk_dst_trait : public eu_dst_trait<date_type> + { + static int dst_start_offset_minutes() { return 60;} + static int dst_end_offset_minutes() { return 120; } + static int dst_shift_length_minutes() { return 60; } + }; + + //Rules for Adelaide Australia + template<class date_type> + struct acst_dst_trait + { + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef date_time::last_kday_of_month<date_type> start_rule_functor; + typedef date_time::last_kday_of_month<date_type> end_rule_functor; + static day_of_week_type start_day(year_type) {return Sunday;} + static month_type start_month(year_type) {return Oct;} + static day_of_week_type end_day(year_type) {return Sunday;} + static month_type end_month(year_type) {return Mar;} + static int dst_start_offset_minutes() { return 120;} + static int dst_end_offset_minutes() { return 180; } + static int dst_shift_length_minutes() { return 60; } + static date_type local_dst_start_day(year_type year) + { + start_rule_functor start(start_day(year), + start_month(year)); + return start.get_date(year); + } + static date_type local_dst_end_day(year_type year) + { + end_rule_functor end(end_day(year), + end_month(year)); + return end.get_date(year); + } + }; + + + + + + +} } //namespace boost::date_time + + +#endif diff --git a/ext/boost/date_time/locale_config.hpp b/ext/boost/date_time/locale_config.hpp new file mode 100644 index 0000000000..d01e008fea --- /dev/null +++ b/ext/boost/date_time/locale_config.hpp @@ -0,0 +1,31 @@ +#ifndef DATE_TIME_LOCALE_CONFIG_HPP___ +#define DATE_TIME_LOCALE_CONFIG_HPP___ + +/* Copyright (c) 2002-2006 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +// This file configures whether the library will support locales and hence +// iostream based i/o. Even if a compiler has some support for locales, +// any failure to be compatible gets the compiler on the exclusion list. +// +// At the moment this is defined for MSVC 6 and any compiler that +// defines BOOST_NO_STD_LOCALE (gcc 2.95.x) + +#include "boost/config.hpp" //sets BOOST_NO_STD_LOCALE +#include "boost/detail/workaround.hpp" + +//This file basically becomes a noop if locales are not properly supported +#if (defined(BOOST_NO_STD_LOCALE) \ + || (BOOST_WORKAROUND( BOOST_MSVC, < 1300)) \ + || (BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x581 )) ) ) +#define BOOST_DATE_TIME_NO_LOCALE +#endif + + +#endif + diff --git a/ext/boost/date_time/microsec_time_clock.hpp b/ext/boost/date_time/microsec_time_clock.hpp new file mode 100644 index 0000000000..e6f3b8ecdf --- /dev/null +++ b/ext/boost/date_time/microsec_time_clock.hpp @@ -0,0 +1,127 @@ +#ifndef DATE_TIME_HIGHRES_TIME_CLOCK_HPP___ +#define DATE_TIME_HIGHRES_TIME_CLOCK_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 07:36:43 -0400 (Thu, 04 Jun 2009) $ + */ + + +/*! @file microsec_time_clock.hpp + This file contains a high resolution time clock implementation. +*/ + +#include <boost/cstdint.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/c_time.hpp> +#include <boost/date_time/time_clock.hpp> +#include <boost/date_time/filetime_functions.hpp> + +#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK + +namespace boost { +namespace date_time { + + //! A clock providing microsecond level resolution + /*! A high precision clock that measures the local time + * at a resolution up to microseconds and adjusts to the + * resolution of the time system. For example, for the + * a library configuration with nano second resolution, + * the last 3 places of the fractional seconds will always + * be 000 since there are 1000 nano-seconds in a micro second. + */ + template<class time_type> + class microsec_clock + { + private: + //! Type for the function used to convert time_t to tm + typedef std::tm* (*time_converter)(const std::time_t*, std::tm*); + + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_duration_type::rep_type resolution_traits_type; + + //! return a local time object for the given zone, based on computer clock + //JKG -- looks like we could rewrite this against universal_time + template<class time_zone_type> + static time_type local_time(shared_ptr<time_zone_type> tz_ptr) + { + typedef typename time_type::utc_time_type utc_time_type; + typedef second_clock<utc_time_type> second_clock; + // we'll need to know the utc_offset this machine has + // in order to get a utc_time_type set to utc + utc_time_type utc_time = second_clock::universal_time(); + time_duration_type utc_offset = second_clock::local_time() - utc_time; + // use micro clock to get a local time with sub seconds + // and adjust it to get a true utc time reading with sub seconds + utc_time = microsec_clock<utc_time_type>::local_time() - utc_offset; + return time_type(utc_time, tz_ptr); + } + + //! Returns the local time based on computer clock settings + static time_type local_time() + { + return create_time(&c_time::localtime); + } + + //! Returns the UTC time based on computer settings + static time_type universal_time() + { + return create_time(&c_time::gmtime); + } + + private: + static time_type create_time(time_converter converter) + { +#ifdef BOOST_HAS_GETTIMEOFDAY + timeval tv; + gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux. + std::time_t t = tv.tv_sec; + boost::uint32_t sub_sec = tv.tv_usec; +#elif defined(BOOST_HAS_FTIME) + winapi::file_time ft; + winapi::get_system_time_as_file_time(ft); + uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time + // and cannot be before 1970-Jan-01 + std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch + // microseconds -- static casts supress warnings + boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL); +#else +#error Internal Boost.DateTime error: BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK is defined, however neither gettimeofday nor FILETIME support is detected. +#endif + + std::tm curr; + std::tm* curr_ptr = converter(&t, &curr); + date_type d(curr_ptr->tm_year + 1900, + curr_ptr->tm_mon + 1, + curr_ptr->tm_mday); + + //The following line will adjust the fractional second tick in terms + //of the current time system. For example, if the time system + //doesn't support fractional seconds then res_adjust returns 0 + //and all the fractional seconds return 0. + int adjust = static_cast< int >(resolution_traits_type::res_adjust() / 1000000); + + time_duration_type td(curr_ptr->tm_hour, + curr_ptr->tm_min, + curr_ptr->tm_sec, + sub_sec * adjust); + + return time_type(d,td); + } + }; + + +} } //namespace date_time + +#endif //BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK + + +#endif + diff --git a/ext/boost/date_time/parse_format_base.hpp b/ext/boost/date_time/parse_format_base.hpp new file mode 100644 index 0000000000..b17a5c8e77 --- /dev/null +++ b/ext/boost/date_time/parse_format_base.hpp @@ -0,0 +1,29 @@ +#ifndef DATE_TIME_PARSE_FORMAT_BASE__ +#define DATE_TIME_PARSE_FORMAT_BASE__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +namespace boost { +namespace date_time { + + //! Enum for distinguishing parsing and formatting options + enum month_format_spec {month_as_integer, month_as_short_string, + month_as_long_string}; + + //! Enum for distinguishing the order of Month, Day, & Year. + /*! Enum for distinguishing the order in which Month, Day, & Year + * will appear in a date string */ + enum ymd_order_spec {ymd_order_iso, //order is year-month-day + ymd_order_dmy, //day-month-year + ymd_order_us}; //order is month-day-year + + +} }//namespace date_time + +#endif diff --git a/ext/boost/date_time/period.hpp b/ext/boost/date_time/period.hpp new file mode 100644 index 0000000000..c67bc36c65 --- /dev/null +++ b/ext/boost/date_time/period.hpp @@ -0,0 +1,377 @@ +#ifndef DATE_TIME_PERIOD_HPP___ +#define DATE_TIME_PERIOD_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! \file period.hpp + This file contain the implementation of the period abstraction. This is + basically the same idea as a range. Although this class is intended for + use in the time library, it is pretty close to general enough for other + numeric uses. + +*/ + +#include "boost/operators.hpp" + + +namespace boost { +namespace date_time { + //!Provides generalized period type useful in date-time systems + /*!This template uses a class to represent a time point within the period + and another class to represent a duration. As a result, this class is + not appropriate for use when the number and duration representation + are the same (eg: in the regular number domain). + + A period can be specified by providing either the begining point and + a duration or the begining point and the end point( end is NOT part + of the period but 1 unit past it. A period will be "invalid" if either + end_point <= begin_point or the given duration is <= 0. Any valid period + will return false for is_null(). + + Zero length periods are also considered invalid. Zero length periods are + periods where the begining and end points are the same, or, the given + duration is zero. For a zero length period, the last point will be one + unit less than the begining point. + + In the case that the begin and last are the same, the period has a + length of one unit. + + The best way to handle periods is usually to provide a begining point and + a duration. So, day1 + 7 days is a week period which includes all of the + first day and 6 more days (eg: Sun to Sat). + + */ + template<class point_rep, class duration_rep> + class period : private + boost::less_than_comparable<period<point_rep, duration_rep> + , boost::equality_comparable< period<point_rep, duration_rep> + > > + { + public: + typedef point_rep point_type; + typedef duration_rep duration_type; + + period(point_rep first_point, point_rep end_point); + period(point_rep first_point, duration_rep len); + point_rep begin() const; + point_rep end() const; + point_rep last() const; + duration_rep length() const; + bool is_null() const; + bool operator==(const period& rhs) const; + bool operator<(const period& rhs) const; + void shift(const duration_rep& d); + void expand(const duration_rep& d); + bool contains(const point_rep& point) const; + bool contains(const period& other) const; + bool intersects(const period& other) const; + bool is_adjacent(const period& other) const; + bool is_before(const point_rep& point) const; + bool is_after(const point_rep& point) const; + period intersection(const period& other) const; + period merge(const period& other) const; + period span(const period& other) const; + private: + point_rep begin_; + point_rep last_; + }; + + //! create a period from begin to last eg: [begin,end) + /*! If end <= begin then the period will be invalid + */ + template<class point_rep, class duration_rep> + inline + period<point_rep,duration_rep>::period(point_rep first_point, + point_rep end_point) : + begin_(first_point), + last_(end_point - duration_rep::unit()) + {} + + //! create a period as [begin, begin+len) + /*! If len is <= 0 then the period will be invalid + */ + template<class point_rep, class duration_rep> + inline + period<point_rep,duration_rep>::period(point_rep first_point, duration_rep len) : + begin_(first_point), + last_(first_point + len-duration_rep::unit()) + { } + + + //! Return the first element in the period + template<class point_rep, class duration_rep> + inline + point_rep period<point_rep,duration_rep>::begin() const + { + return begin_; + } + + //! Return one past the last element + template<class point_rep, class duration_rep> + inline + point_rep period<point_rep,duration_rep>::end() const + { + return last_ + duration_rep::unit(); + } + + //! Return the last item in the period + template<class point_rep, class duration_rep> + inline + point_rep period<point_rep,duration_rep>::last() const + { + return last_; + } + + //! True if period is ill formed (length is zero or less) + template<class point_rep, class duration_rep> + inline + bool period<point_rep,duration_rep>::is_null() const + { + return end() <= begin_; + } + + //! Return the length of the period + template<class point_rep, class duration_rep> + inline + duration_rep period<point_rep,duration_rep>::length() const + { + if(last_ < begin_){ // invalid period + return last_+duration_rep::unit() - begin_; + } + else{ + return end() - begin_; // normal case + } + } + + //! Equality operator + template<class point_rep, class duration_rep> + inline + bool period<point_rep,duration_rep>::operator==(const period& rhs) const + { + return ((begin_ == rhs.begin_) && + (last_ == rhs.last_)); + } + + //! Strict as defined by rhs.last <= lhs.last + template<class point_rep, class duration_rep> + inline + bool period<point_rep,duration_rep>::operator<(const period& rhs) const + { + return (last_ < rhs.begin_); + } + + + //! Shift the start and end by the specified amount + template<class point_rep, class duration_rep> + inline + void period<point_rep,duration_rep>::shift(const duration_rep& d) + { + begin_ = begin_ + d; + last_ = last_ + d; + } + + /** Expands the size of the period by the duration on both ends. + * + *So before expand + *@code + * + * [-------] + * ^ ^ ^ ^ ^ ^ ^ + * 1 2 3 4 5 6 7 + * + *@endcode + * After expand(2) + *@code + * + * [----------------------] + * ^ ^ ^ ^ ^ ^ ^ + * 1 2 3 4 5 6 7 + * + *@endcode + */ + template<class point_rep, class duration_rep> + inline + void period<point_rep,duration_rep>::expand(const duration_rep& d) + { + begin_ = begin_ - d; + last_ = last_ + d; + } + + //! True if the point is inside the period, zero length periods contain no points + template<class point_rep, class duration_rep> + inline + bool period<point_rep,duration_rep>::contains(const point_rep& point) const + { + return ((point >= begin_) && + (point <= last_)); + } + + + //! True if this period fully contains (or equals) the other period + template<class point_rep, class duration_rep> + inline + bool period<point_rep,duration_rep>::contains(const period<point_rep,duration_rep>& other) const + { + return ((begin_ <= other.begin_) && (last_ >= other.last_)); + } + + + //! True if periods are next to each other without a gap. + /* In the example below, p1 and p2 are adjacent, but p3 is not adjacent + * with either of p1 or p2. + *@code + * [-p1-) + * [-p2-) + * [-p3-) + *@endcode + */ + template<class point_rep, class duration_rep> + inline + bool + period<point_rep,duration_rep>::is_adjacent(const period<point_rep,duration_rep>& other) const + { + return (other.begin() == end() || + begin_ == other.end()); + } + + + //! True if all of the period is prior or t < start + /* In the example below only point 1 would evaluate to true. + *@code + * [---------]) + * ^ ^ ^ ^ ^ + * 1 2 3 4 5 + * + *@endcode + */ + template<class point_rep, class duration_rep> + inline + bool + period<point_rep,duration_rep>::is_after(const point_rep& t) const + { + if (is_null()) + { + return false; //null period isn't after + } + + return t < begin_; + } + + //! True if all of the period is prior to the passed point or end <= t + /* In the example below points 4 and 5 return true. + *@code + * [---------]) + * ^ ^ ^ ^ ^ + * 1 2 3 4 5 + * + *@endcode + */ + template<class point_rep, class duration_rep> + inline + bool + period<point_rep,duration_rep>::is_before(const point_rep& t) const + { + if (is_null()) + { + return false; //null period isn't before anything + } + + return last_ < t; + } + + + //! True if the periods overlap in any way + /* In the example below p1 intersects with p2, p4, and p6. + *@code + * [---p1---) + * [---p2---) + * [---p3---) + * [---p4---) + * [-p5-) + * [-p6-) + *@endcode + */ + template<class point_rep, class duration_rep> + inline + bool period<point_rep,duration_rep>::intersects(const period<point_rep,duration_rep>& other) const + { + return ( contains(other.begin_) || + other.contains(begin_) || + ((other.begin_ < begin_) && (other.last_ >= begin_))); + } + + //! Returns the period of intersection or invalid range no intersection + template<class point_rep, class duration_rep> + inline + period<point_rep,duration_rep> + period<point_rep,duration_rep>::intersection(const period<point_rep,duration_rep>& other) const + { + if (begin_ > other.begin_) { + if (last_ <= other.last_) { //case2 + return *this; + } + //case 1 + return period<point_rep,duration_rep>(begin_, other.end()); + } + else { + if (last_ <= other.last_) { //case3 + return period<point_rep,duration_rep>(other.begin_, this->end()); + } + //case4 + return other; + } + //unreachable + } + + //! Returns the union of intersecting periods -- or null period + /*! + */ + template<class point_rep, class duration_rep> + inline + period<point_rep,duration_rep> + period<point_rep,duration_rep>::merge(const period<point_rep,duration_rep>& other) const + { + if (this->intersects(other)) { + if (begin_ < other.begin_) { + return period<point_rep,duration_rep>(begin_, last_ > other.last_ ? this->end() : other.end()); + } + + return period<point_rep,duration_rep>(other.begin_, last_ > other.last_ ? this->end() : other.end()); + + } + return period<point_rep,duration_rep>(begin_,begin_); // no intersect return null + } + + //! Combine two periods with earliest start and latest end. + /*! Combines two periods and any gap between them such that + * start = min(p1.start, p2.start) + * end = max(p1.end , p2.end) + *@code + * [---p1---) + * [---p2---) + * result: + * [-----------p3----------) + *@endcode + */ + template<class point_rep, class duration_rep> + inline + period<point_rep,duration_rep> + period<point_rep,duration_rep>::span(const period<point_rep,duration_rep>& other) const + { + point_rep start((begin_ < other.begin_) ? begin() : other.begin()); + point_rep newend((last_ < other.last_) ? other.end() : this->end()); + return period<point_rep,duration_rep>(start, newend); + } + + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/period_formatter.hpp b/ext/boost/date_time/period_formatter.hpp new file mode 100644 index 0000000000..08082e10f6 --- /dev/null +++ b/ext/boost/date_time/period_formatter.hpp @@ -0,0 +1,196 @@ + +#ifndef DATETIME_PERIOD_FORMATTER_HPP___ +#define DATETIME_PERIOD_FORMATTER_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + + +namespace boost { namespace date_time { + + + //! Not a facet, but a class used to specify and control period formats + /*! Provides settings for the following: + * - period_separator -- default '/' + * - period_open_start_delimeter -- default '[' + * - period_open_range_end_delimeter -- default ')' + * - period_closed_range_end_delimeter -- default ']' + * - display_as_open_range, display_as_closed_range -- default closed_range + * + * Thus the default formatting for a period is as follows: + *@code + * [period.start()/period.last()] + *@endcode + * So for a typical date_period this would be + *@code + * [2004-Jan-04/2004-Feb-01] + *@endcode + * where the date formatting is controlled by the date facet + */ + template <class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > + class period_formatter { + public: + typedef std::basic_string<CharT> string_type; + typedef CharT char_type; + typedef typename std::basic_string<char_type>::const_iterator const_itr_type; + typedef std::vector<std::basic_string<CharT> > collection_type; + + static const char_type default_period_separator[2]; + static const char_type default_period_start_delimeter[2]; + static const char_type default_period_open_range_end_delimeter[2]; + static const char_type default_period_closed_range_end_delimeter[2]; + + enum range_display_options { AS_OPEN_RANGE, AS_CLOSED_RANGE }; + + //! Constructor that sets up period formatter options -- default should suffice most cases. + period_formatter(range_display_options range_option_in = AS_CLOSED_RANGE, + const char_type* const period_separator = default_period_separator, + const char_type* const period_start_delimeter = default_period_start_delimeter, + const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, + const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) : + m_range_option(range_option_in), + m_period_separator(period_separator), + m_period_start_delimeter(period_start_delimeter), + m_open_range_end_delimeter(period_open_range_end_delimeter), + m_closed_range_end_delimeter(period_closed_range_end_delimeter) + {} + + //! Puts the characters between period elements into stream -- default is / + OutItrT put_period_separator(OutItrT& oitr) const + { + const_itr_type ci = m_period_separator.begin(); + while (ci != m_period_separator.end()) { + *oitr = *ci; + ci++; + } + return oitr; + } + + //! Puts the period start characters into stream -- default is [ + OutItrT put_period_start_delimeter(OutItrT& oitr) const + { + const_itr_type ci = m_period_start_delimeter.begin(); + while (ci != m_period_start_delimeter.end()) { + *oitr = *ci; + ci++; + } + return oitr; + } + + //! Puts the period end characters into stream as controled by open/closed range setting. + OutItrT put_period_end_delimeter(OutItrT& oitr) const + { + + const_itr_type ci, end; + if (m_range_option == AS_OPEN_RANGE) { + ci = m_open_range_end_delimeter.begin(); + end = m_open_range_end_delimeter.end(); + } + else { + ci = m_closed_range_end_delimeter.begin(); + end = m_closed_range_end_delimeter.end(); + } + while (ci != end) { + *oitr = *ci; + ci++; + } + return oitr; + } + + range_display_options range_option() const + { + return m_range_option; + } + + //! Reset the range_option control + void + range_option(range_display_options option) const + { + m_range_option = option; + } + void delimiter_strings(const string_type& separator, + const string_type& start_delim, + const string_type& open_end_delim, + const string_type& closed_end_delim) + { + m_period_separator; + m_period_start_delimeter; + m_open_range_end_delimeter; + m_closed_range_end_delimeter; + } + + + //! Generic code to output a period -- no matter the period type. + /*! This generic code will output any period using a facet to + * to output the 'elements'. For example, in the case of a date_period + * the elements will be instances of a date which will be formatted + * according the to setup in the passed facet parameter. + * + * The steps for formatting a period are always the same: + * - put the start delimiter + * - put start element + * - put the separator + * - put either last or end element depending on range settings + * - put end delimeter depending on range settings + * + * Thus for a typical date period the result might look like this: + *@code + * + * [March 01, 2004/June 07, 2004] <-- closed range + * [March 01, 2004/June 08, 2004) <-- open range + * + *@endcode + */ + template<class period_type, class facet_type> + OutItrT put_period(OutItrT next, + std::ios_base& a_ios, + char_type a_fill, + const period_type& p, + const facet_type& facet) const { + put_period_start_delimeter(next); + next = facet.put(next, a_ios, a_fill, p.begin()); + put_period_separator(next); + if (m_range_option == AS_CLOSED_RANGE) { + facet.put(next, a_ios, a_fill, p.last()); + } + else { + facet.put(next, a_ios, a_fill, p.end()); + } + put_period_end_delimeter(next); + return next; + } + + + private: + range_display_options m_range_option; + string_type m_period_separator; + string_type m_period_start_delimeter; + string_type m_open_range_end_delimeter; + string_type m_closed_range_end_delimeter; + }; + + template <class CharT, class OutItrT> + const typename period_formatter<CharT, OutItrT>::char_type + period_formatter<CharT, OutItrT>::default_period_separator[2] = {'/'}; + + template <class CharT, class OutItrT> + const typename period_formatter<CharT, OutItrT>::char_type + period_formatter<CharT, OutItrT>::default_period_start_delimeter[2] = {'['}; + + template <class CharT, class OutItrT> + const typename period_formatter<CharT, OutItrT>::char_type + period_formatter<CharT, OutItrT>::default_period_open_range_end_delimeter[2] = {')'}; + + template <class CharT, class OutItrT> + const typename period_formatter<CharT, OutItrT>::char_type + period_formatter<CharT, OutItrT>::default_period_closed_range_end_delimeter[2] = {']'}; + + } } //namespace boost::date_time + +#endif diff --git a/ext/boost/date_time/period_parser.hpp b/ext/boost/date_time/period_parser.hpp new file mode 100644 index 0000000000..9cd57e18c7 --- /dev/null +++ b/ext/boost/date_time/period_parser.hpp @@ -0,0 +1,198 @@ + +#ifndef DATETIME_PERIOD_PARSER_HPP___ +#define DATETIME_PERIOD_PARSER_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-13 15:10:23 -0500 (Thu, 13 Nov 2008) $ + */ + +#include <boost/throw_exception.hpp> +#include <boost/date_time/string_parse_tree.hpp> +#include <boost/date_time/string_convert.hpp> + + +namespace boost { namespace date_time { + + + //! Not a facet, but a class used to specify and control period parsing + /*! Provides settings for the following: + * - period_separator -- default '/' + * - period_open_start_delimeter -- default '[' + * - period_open_range_end_delimeter -- default ')' + * - period_closed_range_end_delimeter -- default ']' + * - display_as_open_range, display_as_closed_range -- default closed_range + * + * For a typical date_period, the contents of the input stream would be + *@code + * [2004-Jan-04/2004-Feb-01] + *@endcode + * where the date format is controlled by the date facet + */ + template<class date_type, typename CharT> + class period_parser { + public: + typedef std::basic_string<CharT> string_type; + typedef CharT char_type; + //typedef typename std::basic_string<char_type>::const_iterator const_itr_type; + typedef std::istreambuf_iterator<CharT> stream_itr_type; + typedef string_parse_tree<CharT> parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector<std::basic_string<CharT> > collection_type; + + static const char_type default_period_separator[2]; + static const char_type default_period_start_delimeter[2]; + static const char_type default_period_open_range_end_delimeter[2]; + static const char_type default_period_closed_range_end_delimeter[2]; + + enum period_range_option { AS_OPEN_RANGE, AS_CLOSED_RANGE }; + + //! Constructor that sets up period parser options + period_parser(period_range_option range_opt = AS_CLOSED_RANGE, + const char_type* const period_separator = default_period_separator, + const char_type* const period_start_delimeter = default_period_start_delimeter, + const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, + const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) + : m_range_option(range_opt) + { + delimiters.push_back(string_type(period_separator)); + delimiters.push_back(string_type(period_start_delimeter)); + delimiters.push_back(string_type(period_open_range_end_delimeter)); + delimiters.push_back(string_type(period_closed_range_end_delimeter)); + } + + period_parser(const period_parser<date_type,CharT>& p_parser) + { + this->delimiters = p_parser.delimiters; + this->m_range_option = p_parser.m_range_option; + } + + period_range_option range_option() const + { + return m_range_option; + } + void range_option(period_range_option option) + { + m_range_option = option; + } + collection_type delimiter_strings() const + { + return delimiters; + } + void delimiter_strings(const string_type& separator, + const string_type& start_delim, + const string_type& open_end_delim, + const string_type& closed_end_delim) + { + delimiters.clear(); + delimiters.push_back(separator); + delimiters.push_back(start_delim); + delimiters.push_back(open_end_delim); + delimiters.push_back(closed_end_delim); + } + + //! Generic code to parse a period -- no matter the period type. + /*! This generic code will parse any period using a facet to + * to get the 'elements'. For example, in the case of a date_period + * the elements will be instances of a date which will be parsed + * according the to setup in the passed facet parameter. + * + * The steps for parsing a period are always the same: + * - consume the start delimiter + * - get start element + * - consume the separator + * - get either last or end element depending on range settings + * - consume the end delimeter depending on range settings + * + * Thus for a typical date period the contents of the input stream + * might look like this: + *@code + * + * [March 01, 2004/June 07, 2004] <-- closed range + * [March 01, 2004/June 08, 2004) <-- open range + * + *@endcode + */ + template<class period_type, class duration_type, class facet_type> + period_type get_period(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const period_type& /* p */, + const duration_type& dur_unit, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + typedef typename period_type::point_type point_type; + point_type p1(not_a_date_time), p2(not_a_date_time); + + + consume_delim(sitr, stream_end, delimiters[START]); // start delim + facet.get(sitr, stream_end, a_ios, p1); // first point + consume_delim(sitr, stream_end, delimiters[SEPARATOR]); // separator + facet.get(sitr, stream_end, a_ios, p2); // second point + + // period construction parameters are always open range [begin, end) + if (m_range_option == AS_CLOSED_RANGE) { + consume_delim(sitr, stream_end, delimiters[CLOSED_END]);// end delim + // add 1 duration unit to p2 to make range open + p2 += dur_unit; + } + else { + consume_delim(sitr, stream_end, delimiters[OPEN_END]); // end delim + } + + return period_type(p1, p2); + } + + private: + collection_type delimiters; + period_range_option m_range_option; + + enum delim_ids { SEPARATOR, START, OPEN_END, CLOSED_END }; + + //! throws ios_base::failure if delimiter and parsed data do not match + void consume_delim(stream_itr_type& sitr, + stream_itr_type& stream_end, + const string_type& delim) const + { + /* string_parse_tree will not parse a string of punctuation characters + * without knowing exactly how many characters to process + * Ex [2000. Will not parse out the '[' string without knowing + * to process only one character. By using length of the delimiter + * string we can safely iterate past it. */ + string_type s; + for(unsigned int i = 0; i < delim.length() && sitr != stream_end; ++i) { + s += *sitr; + ++sitr; + } + if(s != delim) { + boost::throw_exception(std::ios_base::failure("Parse failed. Expected '" + + convert_string_type<char_type,char>(delim) + "' but found '" + convert_string_type<char_type,char>(s) + "'")); + } + } + }; + + template <class date_type, class char_type> + const typename period_parser<date_type, char_type>::char_type + period_parser<date_type, char_type>::default_period_separator[2] = {'/'}; + + template <class date_type, class char_type> + const typename period_parser<date_type, char_type>::char_type + period_parser<date_type, char_type>::default_period_start_delimeter[2] = {'['}; + + template <class date_type, class char_type> + const typename period_parser<date_type, char_type>::char_type + period_parser<date_type, char_type>::default_period_open_range_end_delimeter[2] = {')'}; + + template <class date_type, class char_type> + const typename period_parser<date_type, char_type>::char_type + period_parser<date_type, char_type>::default_period_closed_range_end_delimeter[2] = {']'}; + + } } //namespace boost::date_time + +#endif // DATETIME_PERIOD_PARSER_HPP___ diff --git a/ext/boost/date_time/posix_time/conversion.hpp b/ext/boost/date_time/posix_time/conversion.hpp new file mode 100644 index 0000000000..6d35f4fc56 --- /dev/null +++ b/ext/boost/date_time/posix_time/conversion.hpp @@ -0,0 +1,91 @@ +#ifndef POSIX_TIME_CONVERSION_HPP___ +#define POSIX_TIME_CONVERSION_HPP___ + +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 04:24:49 -0400 (Thu, 04 Jun 2009) $ + */ + +#include "boost/date_time/posix_time/ptime.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/filetime_functions.hpp" +#include "boost/date_time/c_time.hpp" +#include "boost/date_time/gregorian/conversion.hpp" + +namespace boost { + +namespace posix_time { + + + //! Function that converts a time_t into a ptime. + inline + ptime from_time_t(std::time_t t) + { + ptime start(gregorian::date(1970,1,1)); + return start + seconds(static_cast<long>(t)); + } + + //! Convert a time to a tm structure truncating any fractional seconds + inline + std::tm to_tm(const boost::posix_time::ptime& t) { + std::tm timetm = boost::gregorian::to_tm(t.date()); + boost::posix_time::time_duration td = t.time_of_day(); + timetm.tm_hour = td.hours(); + timetm.tm_min = td.minutes(); + timetm.tm_sec = td.seconds(); + timetm.tm_isdst = -1; // -1 used when dst info is unknown + return timetm; + } + //! Convert a time_duration to a tm structure truncating any fractional seconds and zeroing fields for date components + inline + std::tm to_tm(const boost::posix_time::time_duration& td) { + std::tm timetm = {}; + timetm.tm_hour = date_time::absolute_value(td.hours()); + timetm.tm_min = date_time::absolute_value(td.minutes()); + timetm.tm_sec = date_time::absolute_value(td.seconds()); + timetm.tm_isdst = -1; // -1 used when dst info is unknown + return timetm; + } + + //! Convert a tm struct to a ptime ignoring is_dst flag + inline + ptime ptime_from_tm(const std::tm& timetm) { + boost::gregorian::date d = boost::gregorian::date_from_tm(timetm); + return ptime(d, time_duration(timetm.tm_hour, timetm.tm_min, timetm.tm_sec)); + } + + +#if defined(BOOST_HAS_FTIME) + + //! Function to create a time object from an initialized FILETIME struct. + /*! Function to create a time object from an initialized FILETIME struct. + * A FILETIME struct holds 100-nanosecond units (0.0000001). When + * built with microsecond resolution the FILETIME's sub second value + * will be truncated. Nanosecond resolution has no truncation. + * + * \note FILETIME is part of the Win32 API, so it is not portable to non-windows + * platforms. + * + * \note The function is templated on the FILETIME type, so that + * it can be used with both native FILETIME and the ad-hoc + * boost::date_time::winapi::file_time type. + */ + template< typename TimeT, typename FileTimeT > + inline + TimeT from_ftime(const FileTimeT& ft) + { + return boost::date_time::time_from_ftime<TimeT>(ft); + } + +#endif // BOOST_HAS_FTIME + +} } //namespace boost::posix_time + + + + +#endif + diff --git a/ext/boost/date_time/posix_time/date_duration_operators.hpp b/ext/boost/date_time/posix_time/date_duration_operators.hpp new file mode 100644 index 0000000000..e6899ba0aa --- /dev/null +++ b/ext/boost/date_time/posix_time/date_duration_operators.hpp @@ -0,0 +1,114 @@ +#ifndef DATE_DURATION_OPERATORS_HPP___ +#define DATE_DURATION_OPERATORS_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#include "boost/date_time/posix_time/ptime.hpp" + +namespace boost { +namespace posix_time { + + /*!@file date_duration_operators.hpp Operators for ptime and + * optional gregorian types. Operators use snap-to-end-of-month behavior. + * Further details on this behavior can be found in reference for + * date_time/date_duration_types.hpp and documentation for + * month and year iterators. + */ + + + /*! Adds a months object and a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator+(const ptime& t, const boost::gregorian::months& m) + { + return t + m.get_offset(t.date()); + } + + /*! Adds a months object to a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator+=(ptime& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t += m.get_offset(t.date()); + } + + /*! Subtracts a months object and a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator-(const ptime& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t + m.get_neg_offset(t.date()); + } + + /*! Subtracts a months object from a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator-=(ptime& t, const boost::gregorian::months& m) + { + return t += m.get_neg_offset(t.date()); + } + + // ptime & years + + /*! Adds a years object and a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator+(const ptime& t, const boost::gregorian::years& y) + { + return t + y.get_offset(t.date()); + } + + /*! Adds a years object to a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator+=(ptime& t, const boost::gregorian::years& y) + { + return t += y.get_offset(t.date()); + } + + /*! Subtracts a years object and a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator-(const ptime& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t + y.get_neg_offset(t.date()); + } + + /*! Subtracts a years object from a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator-=(ptime& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t += y.get_neg_offset(t.date()); + } + +}} // namespaces + +#endif // DATE_DURATION_OPERATORS_HPP___ diff --git a/ext/boost/date_time/posix_time/posix_time.hpp b/ext/boost/date_time/posix_time/posix_time.hpp new file mode 100644 index 0000000000..4e9294c426 --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time.hpp @@ -0,0 +1,39 @@ +#ifndef POSIX_TIME_HPP___ +#define POSIX_TIME_HPP___ + +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ +/*!@file posix_time.hpp Global header file to get all of posix time types + */ + +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/posix_time/ptime.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/posix_time/date_duration_operators.hpp" +#endif + +// output functions +#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +#include "boost/date_time/posix_time/time_formatters_limited.hpp" +#else +#include "boost/date_time/posix_time/time_formatters.hpp" +#endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS + +// streaming operators +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/posix_time/posix_time_legacy_io.hpp" +#else +#include "boost/date_time/posix_time/posix_time_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + +#include "boost/date_time/posix_time/time_parsers.hpp" +#include "boost/date_time/posix_time/conversion.hpp" + + +#endif + diff --git a/ext/boost/date_time/posix_time/posix_time_config.hpp b/ext/boost/date_time/posix_time/posix_time_config.hpp new file mode 100644 index 0000000000..60c3f7ee37 --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time_config.hpp @@ -0,0 +1,178 @@ +#ifndef POSIX_TIME_CONFIG_HPP___ +#define POSIX_TIME_CONFIG_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 07:52:28 -0400 (Thu, 04 Jun 2009) $ + */ + +#include <cstdlib> //for MCW 7.2 std::abs(long long) +#include <boost/limits.hpp> +#include <boost/cstdint.hpp> +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/date_time/time_duration.hpp> +#include <boost/date_time/time_resolution_traits.hpp> +#include <boost/date_time/gregorian/gregorian_types.hpp> +#include <boost/date_time/wrapping_int.hpp> +#include <boost/date_time/compiler_config.hpp> + +namespace boost { +namespace posix_time { + +//Remove the following line if you want 64 bit millisecond resolution time +//#define BOOST_GDTL_POSIX_TIME_STD_CONFIG + +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + // set up conditional test compilations +#define BOOST_DATE_TIME_HAS_MILLISECONDS +#define BOOST_DATE_TIME_HAS_MICROSECONDS +#define BOOST_DATE_TIME_HAS_NANOSECONDS + typedef date_time::time_resolution_traits<boost::date_time::time_resolution_traits_adapted64_impl, boost::date_time::nano, + 1000000000, 9 > time_res_traits; +#else + // set up conditional test compilations +#define BOOST_DATE_TIME_HAS_MILLISECONDS +#define BOOST_DATE_TIME_HAS_MICROSECONDS +#undef BOOST_DATE_TIME_HAS_NANOSECONDS + typedef date_time::time_resolution_traits< + boost::date_time::time_resolution_traits_adapted64_impl, boost::date_time::micro, + 1000000, 6 > time_res_traits; + + +// #undef BOOST_DATE_TIME_HAS_MILLISECONDS +// #undef BOOST_DATE_TIME_HAS_MICROSECONDS +// #undef BOOST_DATE_TIME_HAS_NANOSECONDS +// typedef date_time::time_resolution_traits<boost::int64_t, boost::date_time::tenth, +// 10, 0 > time_res_traits; + +#endif + + + //! Base time duration type + /*! \ingroup time_basics + */ + class time_duration : + public date_time::time_duration<time_duration, time_res_traits> + { + public: + typedef time_res_traits rep_type; + typedef time_res_traits::day_type day_type; + typedef time_res_traits::hour_type hour_type; + typedef time_res_traits::min_type min_type; + typedef time_res_traits::sec_type sec_type; + typedef time_res_traits::fractional_seconds_type fractional_seconds_type; + typedef time_res_traits::tick_type tick_type; + typedef time_res_traits::impl_type impl_type; + time_duration(hour_type hour, + min_type min, + sec_type sec, + fractional_seconds_type fs=0) : + date_time::time_duration<time_duration, time_res_traits>(hour,min,sec,fs) + {} + time_duration() : + date_time::time_duration<time_duration, time_res_traits>(0,0,0) + {} + //! Construct from special_values + time_duration(boost::date_time::special_values sv) : + date_time::time_duration<time_duration, time_res_traits>(sv) + {} + //Give duration access to ticks constructor -- hide from users + friend class date_time::time_duration<time_duration, time_res_traits>; + private: + explicit time_duration(impl_type tick_count) : + date_time::time_duration<time_duration, time_res_traits>(tick_count) + {} + }; + +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + + //! Simple implementation for the time rep + struct simple_time_rep + { + typedef gregorian::date date_type; + typedef time_duration time_duration_type; + simple_time_rep(date_type d, time_duration_type tod) : + day(d), + time_of_day(tod) + { + // make sure we have sane values for date & time + if(!day.is_special() && !time_of_day.is_special()){ + if(time_of_day >= time_duration_type(24,0,0)) { + while(time_of_day >= time_duration_type(24,0,0)) { + day += date_type::duration_type(1); + time_of_day -= time_duration_type(24,0,0); + } + } + else if(time_of_day.is_negative()) { + while(time_of_day.is_negative()) { + day -= date_type::duration_type(1); + time_of_day += time_duration_type(24,0,0); + } + } + } + } + date_type day; + time_duration_type time_of_day; + bool is_special()const + { + return(is_pos_infinity() || is_neg_infinity() || is_not_a_date_time()); + } + bool is_pos_infinity()const + { + return(day.is_pos_infinity() || time_of_day.is_pos_infinity()); + } + bool is_neg_infinity()const + { + return(day.is_neg_infinity() || time_of_day.is_neg_infinity()); + } + bool is_not_a_date_time()const + { + return(day.is_not_a_date() || time_of_day.is_not_a_date_time()); + } + }; + + class posix_time_system_config + { + public: + typedef simple_time_rep time_rep_type; + typedef gregorian::date date_type; + typedef gregorian::date_duration date_duration_type; + typedef time_duration time_duration_type; + typedef time_res_traits::tick_type int_type; + typedef time_res_traits resolution_traits; +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) //help bad compilers +#else + BOOST_STATIC_CONSTANT(boost::int64_t, tick_per_second = 1000000000); +#endif + }; + +#else + + class millisec_posix_time_system_config + { + public: + typedef boost::int64_t time_rep_type; + //typedef time_res_traits::tick_type time_rep_type; + typedef gregorian::date date_type; + typedef gregorian::date_duration date_duration_type; + typedef time_duration time_duration_type; + typedef time_res_traits::tick_type int_type; + typedef time_res_traits::impl_type impl_type; + typedef time_res_traits resolution_traits; +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) //help bad compilers +#else + BOOST_STATIC_CONSTANT(boost::int64_t, tick_per_second = 1000000); +#endif + }; + +#endif + +} }//namespace posix_time + + +#endif + + diff --git a/ext/boost/date_time/posix_time/posix_time_duration.hpp b/ext/boost/date_time/posix_time/posix_time_duration.hpp new file mode 100644 index 0000000000..db3b85fec3 --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time_duration.hpp @@ -0,0 +1,82 @@ +#ifndef POSIX_TIME_DURATION_HPP___ +#define POSIX_TIME_DURATION_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time_config.hpp" + +namespace boost { +namespace posix_time { + + //! Allows expression of durations as an hour count + /*! \ingroup time_basics + */ + class hours : public time_duration + { + public: + explicit hours(long h) : + time_duration(h,0,0) + {} + }; + + //! Allows expression of durations as a minute count + /*! \ingroup time_basics + */ + class minutes : public time_duration + { + public: + explicit minutes(long m) : + time_duration(0,m,0) + {} + }; + + //! Allows expression of durations as a seconds count + /*! \ingroup time_basics + */ + class seconds : public time_duration + { + public: + explicit seconds(long s) : + time_duration(0,0,s) + {} + }; + + + //! Allows expression of durations as milli seconds + /*! \ingroup time_basics + */ + typedef date_time::subsecond_duration<time_duration,1000> millisec; + typedef date_time::subsecond_duration<time_duration,1000> milliseconds; + + //! Allows expression of durations as micro seconds + /*! \ingroup time_basics + */ + typedef date_time::subsecond_duration<time_duration,1000000> microsec; + typedef date_time::subsecond_duration<time_duration,1000000> microseconds; + + //This is probably not needed anymore... +#if defined(BOOST_DATE_TIME_HAS_NANOSECONDS) + + //! Allows expression of durations as nano seconds + /*! \ingroup time_basics + */ + typedef date_time::subsecond_duration<time_duration,1000000000> nanosec; + typedef date_time::subsecond_duration<time_duration,1000000000> nanoseconds; + + +#endif + + + + +} }//namespace posix_time + + +#endif + diff --git a/ext/boost/date_time/posix_time/posix_time_io.hpp b/ext/boost/date_time/posix_time/posix_time_io.hpp new file mode 100644 index 0000000000..9a80737a47 --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time_io.hpp @@ -0,0 +1,239 @@ +#ifndef DATE_TIME_POSIX_TIME_IO_HPP__ +#define DATE_TIME_POSIX_TIME_IO_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-13 14:05:31 -0500 (Thu, 13 Nov 2008) $ + */ + +#include <locale> +#include <iostream> +#include <iterator> // i/ostreambuf_iterator +#include <boost/io/ios_state.hpp> +#include <boost/date_time/time_facet.hpp> +#include <boost/date_time/period_formatter.hpp> +#include <boost/date_time/posix_time/ptime.hpp> +#include <boost/date_time/posix_time/time_period.hpp> +#include <boost/date_time/posix_time/posix_time_duration.hpp> +#include <boost/date_time/posix_time/conversion.hpp> // to_tm will be needed in the facets + +namespace boost { +namespace posix_time { + + + //! wptime_facet is depricated and will be phased out. use wtime_facet instead + //typedef boost::date_time::time_facet<ptime, wchar_t> wptime_facet; + //! ptime_facet is depricated and will be phased out. use time_facet instead + //typedef boost::date_time::time_facet<ptime, char> ptime_facet; + + //! wptime_input_facet is depricated and will be phased out. use wtime_input_facet instead + //typedef boost::date_time::time_input_facet<ptime,wchar_t> wptime_input_facet; + //! ptime_input_facet is depricated and will be phased out. use time_input_facet instead + //typedef boost::date_time::time_input_facet<ptime,char> ptime_input_facet; + + typedef boost::date_time::time_facet<ptime, wchar_t> wtime_facet; + typedef boost::date_time::time_facet<ptime, char> time_facet; + + typedef boost::date_time::time_input_facet<ptime, wchar_t> wtime_input_facet; + typedef boost::date_time::time_input_facet<ptime, char> time_input_facet; + + template <class CharT, class TraitsT> + inline + std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, + const ptime& p) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet<ptime, CharT> custom_ptime_facet; + typedef std::time_put<CharT> std_ptime_facet; + std::ostreambuf_iterator<CharT> oitr(os); + if (std::has_facet<custom_ptime_facet>(os.getloc())) + std::use_facet<custom_ptime_facet>(os.getloc()).put(oitr, os, os.fill(), p); + else { + //instantiate a custom facet for dealing with times since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the locale did not already exist. Of course this will be overridden + //if the user imbues as some later point. + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + //! input operator for ptime + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, ptime& pt) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet<ptime, CharT> time_input_facet; + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<time_input_facet>(is.getloc())) { + std::use_facet<time_input_facet>(is.getloc()).get(sit, str_end, is, pt); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, pt); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + } + } + return is; + } + + + template <class CharT, class TraitsT> + inline + std::basic_ostream<CharT, TraitsT>& + operator<<(std::basic_ostream<CharT, TraitsT>& os, + const boost::posix_time::time_period& p) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet<ptime, CharT> custom_ptime_facet; + typedef std::time_put<CharT> std_time_facet; + std::ostreambuf_iterator<CharT> oitr(os); + if (std::has_facet<custom_ptime_facet>(os.getloc())) { + std::use_facet<custom_ptime_facet>(os.getloc()).put(oitr, os, os.fill(), p); + } + else { + //instantiate a custom facet for dealing with periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues as some later point. + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + //! input operator for time_period + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, time_period& tp) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet<ptime, CharT> time_input_facet; + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<time_input_facet>(is.getloc())) { + std::use_facet<time_input_facet>(is.getloc()).get(sit, str_end, is, tp); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, tp); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + } + } + return is; + } + + + //! ostream operator for posix_time::time_duration + // todo fix to use facet -- place holder for now... + template <class CharT, class Traits> + inline + std::basic_ostream<CharT, Traits>& + operator<<(std::basic_ostream<CharT, Traits>& os, const time_duration& td) + { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet<ptime, CharT> custom_ptime_facet; + typedef std::time_put<CharT> std_ptime_facet; + std::ostreambuf_iterator<CharT> oitr(os); + if (std::has_facet<custom_ptime_facet>(os.getloc())) + std::use_facet<custom_ptime_facet>(os.getloc()).put(oitr, os, os.fill(), td); + else { + //instantiate a custom facet for dealing with times since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the locale did not already exist. Of course this will be overridden + //if the user imbues as some later point. + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), td); + } + return os; + } + + //! input operator for time_duration + template <class CharT, class Traits> + inline + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, time_duration& td) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet<ptime, CharT> time_input_facet; + std::istreambuf_iterator<CharT,Traits> sit(is), str_end; + if(std::has_facet<time_input_facet>(is.getloc())) { + std::use_facet<time_input_facet>(is.getloc()).get(sit, str_end, is, td); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, td); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + } + } + return is; + } + +} } // namespaces +#endif // DATE_TIME_POSIX_TIME_IO_HPP__ diff --git a/ext/boost/date_time/posix_time/posix_time_legacy_io.hpp b/ext/boost/date_time/posix_time/posix_time_legacy_io.hpp new file mode 100644 index 0000000000..f5b20a8f8b --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time_legacy_io.hpp @@ -0,0 +1,153 @@ +#ifndef POSIX_TIME_PRE133_OPERATORS_HPP___ +#define POSIX_TIME_PRE133_OPERATORS_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file posix_time_pre133_operators.hpp + * These input and output operators are for use with the + * pre 1.33 version of the date_time libraries io facet code. + * The operators used in version 1.33 and later can be found + * in posix_time_io.hpp */ + +#include <iostream> +#include <string> +#include <sstream> +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/posix_time/ptime.hpp" +#include "boost/date_time/posix_time/time_period.hpp" +#include "boost/date_time/time_parsing.hpp" + +namespace boost { +namespace posix_time { + + +//The following code is removed for configurations with poor std::locale support (eg: MSVC6, gcc 2.9x) +#ifndef BOOST_DATE_TIME_NO_LOCALE +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + //! ostream operator for posix_time::time_duration + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const time_duration& td) + { + typedef boost::date_time::ostream_time_duration_formatter<time_duration, charT> duration_formatter; + duration_formatter::duration_put(td, os); + return os; + } + + //! ostream operator for posix_time::ptime + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const ptime& t) + { + typedef boost::date_time::ostream_time_formatter<ptime, charT> time_formatter; + time_formatter::time_put(t, os); + return os; + } + + //! ostream operator for posix_time::time_period + template <class charT, class traits> + inline + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const time_period& tp) + { + typedef boost::date_time::ostream_time_period_formatter<time_period, charT> period_formatter; + period_formatter::period_put(tp, os); + return os; + } +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO +/******** input streaming ********/ + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, time_duration& td) + { + // need to create a std::string and parse it + std::basic_string<charT> inp_s; + std::stringstream out_ss; + is >> inp_s; + typename std::basic_string<charT>::iterator b = inp_s.begin(); + // need to use both iterators because there is no requirement + // for the data held by a std::basic_string<> be terminated with + // any marker (such as '\0'). + typename std::basic_string<charT>::iterator e = inp_s.end(); + while(b != e){ + out_ss << out_ss.narrow(*b, 0); + ++b; + } + + td = date_time::parse_delimited_time_duration<time_duration>(out_ss.str()); + return is; + } + + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, ptime& pt) + { + gregorian::date d(not_a_date_time); + time_duration td(0,0,0); + is >> d >> td; + pt = ptime(d, td); + + return is; + } + + /** operator>> for time_period. time_period must be in + * "[date time_duration/date time_duration]" format. */ + template<class charT> + inline + std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, time_period& tp) + { + gregorian::date d(not_a_date_time); + time_duration td(0,0,0); + ptime beg(d, td); + ptime end(beg); + std::basic_string<charT> s; + // get first date string and remove leading '[' + is >> s; + { + std::basic_stringstream<charT> ss; + ss << s.substr(s.find('[')+1); + ss >> d; + } + // get first time_duration & second date string, remove the '/' + // and split into 2 strings + is >> s; + { + std::basic_stringstream<charT> ss; + ss << s.substr(0, s.find('/')); + ss >> td; + } + beg = ptime(d, td); + { + std::basic_stringstream<charT> ss; + ss << s.substr(s.find('/')+1); + ss >> d; + } + // get last time_duration and remove the trailing ']' + is >> s; + { + std::basic_stringstream<charT> ss; + ss << s.substr(0, s.find(']')); + ss >> td; + } + end = ptime(d, td); + + tp = time_period(beg,end); + return is; + } + + +#endif //BOOST_DATE_TIME_NO_LOCALE + +} } // namespaces + +#endif // POSIX_TIME_PRE133_OPERATORS_HPP___ diff --git a/ext/boost/date_time/posix_time/posix_time_system.hpp b/ext/boost/date_time/posix_time/posix_time_system.hpp new file mode 100644 index 0000000000..3d44e0ff00 --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time_system.hpp @@ -0,0 +1,68 @@ +#ifndef POSIX_TIME_SYSTEM_HPP___ +#define POSIX_TIME_SYSTEM_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/posix_time/posix_time_config.hpp" +#include "boost/date_time/time_system_split.hpp" +#include "boost/date_time/time_system_counted.hpp" +#include "boost/date_time/compiler_config.hpp" + + +namespace boost { +namespace posix_time { + +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) //help bad compilers + typedef date_time::split_timedate_system<posix_time_system_config, 1000000000> posix_time_system; +#else + typedef date_time::split_timedate_system<posix_time_system_config> posix_time_system; +#endif + +#else + + typedef date_time::counted_time_rep<millisec_posix_time_system_config> int64_time_rep; + typedef date_time::counted_time_system<int64_time_rep> posix_time_system; + +#endif + +} }//namespace posix_time + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/boost/date_time/posix_time/posix_time_types.hpp b/ext/boost/date_time/posix_time/posix_time_types.hpp new file mode 100644 index 0000000000..f2488f8bed --- /dev/null +++ b/ext/boost/date_time/posix_time/posix_time_types.hpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + */ +#ifndef POSIX_TIME_TYPES_HPP___ +#define POSIX_TIME_TYPES_HPP___ + +#include "boost/date_time/time_clock.hpp" +#include "boost/date_time/microsec_time_clock.hpp" +#include "boost/date_time/posix_time/ptime.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/posix_time/date_duration_operators.hpp" +#endif +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/posix_time/posix_time_system.hpp" +#include "boost/date_time/posix_time/time_period.hpp" +#include "boost/date_time/time_iterator.hpp" +#include "boost/date_time/dst_rules.hpp" + +namespace boost { + +//!Defines a non-adjusted time system with nano-second resolution and stable calculation properties +namespace posix_time { + + //! Iterator over a defined time duration + /*! \ingroup time_basics + */ + typedef date_time::time_itr<ptime> time_iterator; + //! A time clock that has a resolution of one second + /*! \ingroup time_basics + */ + typedef date_time::second_clock<ptime> second_clock; + +#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK + //! A time clock that has a resolution of one microsecond + /*! \ingroup time_basics + */ + typedef date_time::microsec_clock<ptime> microsec_clock; +#endif + + //! Define a dst null dst rule for the posix_time system + typedef date_time::null_dst_rules<ptime::date_type, time_duration> no_dst; + //! Define US dst rule calculator for the posix_time system + typedef date_time::us_dst_rules<ptime::date_type, time_duration> us_dst; + + +} } //namespace posix_time + + + + +#endif + diff --git a/ext/boost/date_time/posix_time/ptime.hpp b/ext/boost/date_time/posix_time/ptime.hpp new file mode 100644 index 0000000000..2abc02d318 --- /dev/null +++ b/ext/boost/date_time/posix_time/ptime.hpp @@ -0,0 +1,65 @@ +#ifndef POSIX_PTIME_HPP___ +#define POSIX_PTIME_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time_system.hpp" +#include "boost/date_time/time.hpp" + +namespace boost { + +namespace posix_time { + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + + //! Time type with no timezone or other adjustments + /*! \ingroup time_basics + */ + class ptime : public date_time::base_time<ptime, posix_time_system> + { + public: + typedef posix_time_system time_system_type; + typedef time_system_type::time_rep_type time_rep_type; + typedef time_system_type::time_duration_type time_duration_type; + typedef ptime time_type; + //! Construct with date and offset in day + ptime(gregorian::date d,time_duration_type td) : date_time::base_time<time_type,time_system_type>(d,td) + {} + //! Construct a time at start of the given day (midnight) + explicit ptime(gregorian::date d) : date_time::base_time<time_type,time_system_type>(d,time_duration_type(0,0,0)) + {} + //! Copy from time_rep + ptime(const time_rep_type& rhs): + date_time::base_time<time_type,time_system_type>(rhs) + {} + //! Construct from special value + ptime(const special_values sv) : date_time::base_time<time_type,time_system_type>(sv) + {} +#if !defined(DATE_TIME_NO_DEFAULT_CONSTRUCTOR) + // Default constructor constructs to not_a_date_time + ptime() : date_time::base_time<time_type,time_system_type>(gregorian::date(not_a_date_time), time_duration_type(not_a_date_time)) + {} +#endif // DATE_TIME_NO_DEFAULT_CONSTRUCTOR + + }; + + + +} }//namespace posix_time + + +#endif + diff --git a/ext/boost/date_time/posix_time/time_formatters.hpp b/ext/boost/date_time/posix_time/time_formatters.hpp new file mode 100644 index 0000000000..dc8facf57a --- /dev/null +++ b/ext/boost/date_time/posix_time/time_formatters.hpp @@ -0,0 +1,289 @@ +#ifndef POSIXTIME_FORMATTERS_HPP___ +#define POSIXTIME_FORMATTERS_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/posix_time/posix_time_types.hpp" +#include "boost/date_time/time_formatting_streams.hpp" + +#include "boost/date_time/time_parsing.hpp" + +/* NOTE: The "to_*_string" code for older compilers, ones that define + * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in + * formatters_limited.hpp + */ + +namespace boost { + +namespace posix_time { + + // template function called by wrapper functions: + // to_*_string(time_duration) & to_*_wstring(time_duration) + template<class charT> + inline std::basic_string<charT> to_simple_string_type(time_duration td) { + std::basic_ostringstream<charT> ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) + { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + charT fill_char = '0'; + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.hours()) << ":"; + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.minutes()) << ":"; + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + charT buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill(fill_char) + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + //! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456 + /*!\ingroup time_format + */ + inline std::string to_simple_string(time_duration td) { + return to_simple_string_type<char>(td); + } + + + // template function called by wrapper functions: + // to_*_string(time_duration) & to_*_wstring(time_duration) + template<class charT> + inline std::basic_string<charT> to_iso_string_type(time_duration td) + { + std::basic_ostringstream<charT> ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + charT fill_char = '0'; + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.hours()); + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.minutes()); + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + charT buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill(fill_char) + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + //! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456 + /*!\ingroup time_format + */ + inline std::string to_iso_string(time_duration td){ + return to_iso_string_type<char>(td); + } + + //! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff + /*!\ingroup time_format + */ + template<class charT> + inline std::basic_string<charT> to_simple_string_type(ptime t) + { + // can't use this w/gcc295, no to_simple_string_type<>(td) available + std::basic_string<charT> ts = gregorian::to_simple_string_type<charT>(t.date());// + " "; + if(!t.time_of_day().is_special()) { + charT space = ' '; + return ts + space + to_simple_string_type<charT>(t.time_of_day()); + } + else { + return ts; + } + } + inline std::string to_simple_string(ptime t){ + return to_simple_string_type<char>(t); + } + + // function called by wrapper functions to_*_string(time_period) + // & to_*_wstring(time_period) + template<class charT> + inline std::basic_string<charT> to_simple_string_type(time_period tp) + { + charT beg = '[', mid = '/', end = ']'; + std::basic_string<charT> d1(to_simple_string_type<charT>(tp.begin())); + std::basic_string<charT> d2(to_simple_string_type<charT>(tp.last())); + return std::basic_string<charT>(beg + d1 + mid + d2 + end); + } + //! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] + /*!\ingroup time_format + */ + inline std::string to_simple_string(time_period tp){ + return to_simple_string_type<char>(tp); + } + + // function called by wrapper functions to_*_string(time_period) + // & to_*_wstring(time_period) + template<class charT> + inline std::basic_string<charT> to_iso_string_type(ptime t) + { + std::basic_string<charT> ts = gregorian::to_iso_string_type<charT>(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + charT sep = 'T'; + return ts + sep + to_iso_string_type<charT>(t.time_of_day()); + } + else { + return ts; + } + } + //! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::string to_iso_string(ptime t){ + return to_iso_string_type<char>(t); + } + + + // function called by wrapper functions to_*_string(time_period) + // & to_*_wstring(time_period) + template<class charT> + inline std::basic_string<charT> to_iso_extended_string_type(ptime t) + { + std::basic_string<charT> ts = gregorian::to_iso_extended_string_type<charT>(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + charT sep = 'T'; + return ts + sep + to_simple_string_type<charT>(t.time_of_day()); + } + else { + return ts; + } + } + //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::string to_iso_extended_string(ptime t){ + return to_iso_extended_string_type<char>(t); + } + +#if !defined(BOOST_NO_STD_WSTRING) + //! Time duration to wstring -hh::mm::ss.fffffff. Example: 10:09:03.0123456 + /*!\ingroup time_format + */ + inline std::wstring to_simple_wstring(time_duration td) { + return to_simple_string_type<wchar_t>(td); + } + //! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456 + /*!\ingroup time_format + */ + inline std::wstring to_iso_wstring(time_duration td){ + return to_iso_string_type<wchar_t>(td); + } + inline std::wstring to_simple_wstring(ptime t){ + return to_simple_string_type<wchar_t>(t); + } + //! Convert to wstring of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] + /*!\ingroup time_format + */ + inline std::wstring to_simple_wstring(time_period tp){ + return to_simple_string_type<wchar_t>(tp); + } + //! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::wstring to_iso_wstring(ptime t){ + return to_iso_string_type<wchar_t>(t); + } + //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::wstring to_iso_extended_wstring(ptime t){ + return to_iso_extended_string_type<wchar_t>(t); + } + +#endif // BOOST_NO_STD_WSTRING + + +} } //namespace posix_time + + +#endif + diff --git a/ext/boost/date_time/posix_time/time_formatters_limited.hpp b/ext/boost/date_time/posix_time/time_formatters_limited.hpp new file mode 100644 index 0000000000..def51694a1 --- /dev/null +++ b/ext/boost/date_time/posix_time/time_formatters_limited.hpp @@ -0,0 +1,211 @@ +#ifndef POSIXTIME_FORMATTERS_LIMITED_HPP___ +#define POSIXTIME_FORMATTERS_LIMITED_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/posix_time/posix_time_types.hpp" +#include "boost/date_time/time_formatting_streams.hpp" + +namespace boost { + +namespace posix_time { + + //! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456 + /*!\ingroup time_format + */ + inline std::string to_simple_string(time_duration td) { + std::ostringstream ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) + { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()) << ":"; + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()) << ":"; + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + char buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill('0') + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + + //! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456 + /*!\ingroup time_format + */ + inline + std::string + to_iso_string(time_duration td) + { + std::ostringstream ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()); + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()); + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + char buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill('0') + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + + //! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff + /*!\ingroup time_format + */ + inline + std::string + to_simple_string(ptime t) + { + std::string ts = gregorian::to_simple_string(t.date());// + " "; + if(!t.time_of_day().is_special()) { + return ts + " " + to_simple_string(t.time_of_day()); + } + else { + return ts; + } + } + + //! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] + /*!\ingroup time_format + */ + inline + std::string + to_simple_string(time_period tp) + { + std::string d1(to_simple_string(tp.begin())); + std::string d2(to_simple_string(tp.last())); + return std::string("[" + d1 + "/" + d2 +"]"); + } + + //! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator + /*!\ingroup time_format + */ + inline + std::string to_iso_string(ptime t) + { + std::string ts = gregorian::to_iso_string(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + return ts + "T" + to_iso_string(t.time_of_day()); + } + else { + return ts; + } + } + + //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator + /*!\ingroup time_format + */ + inline + std::string + to_iso_extended_string(ptime t) + { + std::string ts = gregorian::to_iso_extended_string(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + return ts + "T" + to_simple_string(t.time_of_day()); + } + else { + return ts; + } + } + + +} } //namespace posix_time + + +#endif + diff --git a/ext/boost/date_time/posix_time/time_parsers.hpp b/ext/boost/date_time/posix_time/time_parsers.hpp new file mode 100644 index 0000000000..8a352f6e2b --- /dev/null +++ b/ext/boost/date_time/posix_time/time_parsers.hpp @@ -0,0 +1,44 @@ +#ifndef POSIXTIME_PARSERS_HPP___ +#define POSIXTIME_PARSERS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/time_parsing.hpp" +#include "boost/date_time/posix_time/posix_time_types.hpp" + + +namespace boost { + +namespace posix_time { + + //! Creates a time_duration object from a delimited string + /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". + * A negative duration will be created if the first character in + * string is a '-', all other '-' will be treated as delimiters. + * Accepted delimiters are "-:,.". */ + inline time_duration duration_from_string(const std::string& s) { + return date_time::parse_delimited_time_duration<time_duration>(s); + } + + inline ptime time_from_string(const std::string& s) { + return date_time::parse_delimited_time<ptime>(s, ' '); + } + + inline ptime from_iso_string(const std::string& s) { + return date_time::parse_iso_time<ptime>(s, 'T'); + } + + + +} } //namespace posix_time + + +#endif + diff --git a/ext/boost/date_time/posix_time/time_period.hpp b/ext/boost/date_time/posix_time/time_period.hpp new file mode 100644 index 0000000000..cb7bf07f47 --- /dev/null +++ b/ext/boost/date_time/posix_time/time_period.hpp @@ -0,0 +1,29 @@ +#ifndef POSIX_TIME_PERIOD_HPP___ +#define POSIX_TIME_PERIOD_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/period.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/posix_time/ptime.hpp" + +namespace boost { +namespace posix_time { + + //! Time period type + /*! \ingroup time_basics + */ + typedef date_time::period<ptime, time_duration> time_period; + + +} }//namespace posix_time + + +#endif + diff --git a/ext/boost/date_time/posix_time/time_serialize.hpp b/ext/boost/date_time/posix_time/time_serialize.hpp new file mode 100644 index 0000000000..acadd57bb3 --- /dev/null +++ b/ext/boost/date_time/posix_time/time_serialize.hpp @@ -0,0 +1,200 @@ +#ifndef POSIX_TIME_SERIALIZE_HPP___ +#define POSIX_TIME_SERIALIZE_HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/gregorian/greg_serialize.hpp" +#include "boost/serialization/split_free.hpp" + + +// macros to split serialize functions into save & load functions +// NOTE: these macros define template functions in the boost::serialization namespace. +// They must be expanded *outside* of any namespace +BOOST_SERIALIZATION_SPLIT_FREE(boost::posix_time::ptime) +BOOST_SERIALIZATION_SPLIT_FREE(boost::posix_time::time_duration) +BOOST_SERIALIZATION_SPLIT_FREE(boost::posix_time::time_period) + +namespace boost { +namespace serialization { + + +/*** time_duration ***/ + +//! Function to save posix_time::time_duration objects using serialization lib +/*! time_duration objects are broken down into 4 parts for serialization: + * types are hour_type, min_type, sec_type, and fractional_seconds_type + * as defined in the time_duration class + */ +template<class Archive> +void save(Archive & ar, + const posix_time::time_duration& td, + unsigned int /*version*/) +{ + // serialize a bool so we know how to read this back in later + bool is_special = td.is_special(); + ar & make_nvp("is_special", is_special); + if(is_special) { + std::string s = to_simple_string(td); + ar & make_nvp("sv_time_duration", s); + } + else { + typename posix_time::time_duration::hour_type h = td.hours(); + typename posix_time::time_duration::min_type m = td.minutes(); + typename posix_time::time_duration::sec_type s = td.seconds(); + typename posix_time::time_duration::fractional_seconds_type fs = td.fractional_seconds(); + ar & make_nvp("time_duration_hours", h); + ar & make_nvp("time_duration_minutes", m); + ar & make_nvp("time_duration_seconds", s); + ar & make_nvp("time_duration_fractional_seconds", fs); + } +} + +//! Function to load posix_time::time_duration objects using serialization lib +/*! time_duration objects are broken down into 4 parts for serialization: + * types are hour_type, min_type, sec_type, and fractional_seconds_type + * as defined in the time_duration class + */ +template<class Archive> +void load(Archive & ar, + posix_time::time_duration & td, + unsigned int /*version*/) +{ + bool is_special = false; + ar & make_nvp("is_special", is_special); + if(is_special) { + std::string s; + ar & make_nvp("sv_time_duration", s); + posix_time::special_values sv = gregorian::special_value_from_string(s); + td = posix_time::time_duration(sv); + } + else { + typename posix_time::time_duration::hour_type h(0); + typename posix_time::time_duration::min_type m(0); + typename posix_time::time_duration::sec_type s(0); + typename posix_time::time_duration::fractional_seconds_type fs(0); + ar & make_nvp("time_duration_hours", h); + ar & make_nvp("time_duration_minutes", m); + ar & make_nvp("time_duration_seconds", s); + ar & make_nvp("time_duration_fractional_seconds", fs); + td = posix_time::time_duration(h,m,s,fs); + } +} + +// no load_construct_data function provided as time_duration provides a +// default constructor + +/*** ptime ***/ + +//! Function to save posix_time::ptime objects using serialization lib +/*! ptime objects are broken down into 2 parts for serialization: + * a date object and a time_duration onject + */ +template<class Archive> +void save(Archive & ar, + const posix_time::ptime& pt, + unsigned int /*version*/) +{ + // from_iso_string does not include fractional seconds + // therefore date and time_duration are used + typename posix_time::ptime::date_type d = pt.date(); + ar & make_nvp("ptime_date", d); + if(!pt.is_special()) { + typename posix_time::ptime::time_duration_type td = pt.time_of_day(); + ar & make_nvp("ptime_time_duration", td); + } +} + +//! Function to load posix_time::ptime objects using serialization lib +/*! ptime objects are broken down into 2 parts for serialization: + * a date object and a time_duration onject + */ +template<class Archive> +void load(Archive & ar, + posix_time::ptime & pt, + unsigned int /*version*/) +{ + // from_iso_string does not include fractional seconds + // therefore date and time_duration are used + typename posix_time::ptime::date_type d(posix_time::not_a_date_time); + typename posix_time::ptime::time_duration_type td; + ar & make_nvp("ptime_date", d); + if(!d.is_special()) { + ar & make_nvp("ptime_time_duration", td); + pt = boost::posix_time::ptime(d,td); + } + else { + pt = boost::posix_time::ptime(d.as_special()); + } + +} + +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + posix_time::ptime* pt, + const unsigned int /*file_version*/) +{ + // retrieve data from archive required to construct new + // invoke inplace constructor to initialize instance of date + new(pt) boost::posix_time::ptime(boost::posix_time::not_a_date_time); +} + +/*** time_period ***/ + +//! Function to save posix_time::time_period objects using serialization lib +/*! time_period objects are broken down into 2 parts for serialization: + * a begining ptime object and an ending ptime object + */ +template<class Archive> +void save(Archive & ar, + const posix_time::time_period& tp, + unsigned int /*version*/) +{ + posix_time::ptime beg(tp.begin().date(), tp.begin().time_of_day()); + posix_time::ptime end(tp.end().date(), tp.end().time_of_day()); + ar & make_nvp("time_period_begin", beg); + ar & make_nvp("time_period_end", end); +} + +//! Function to load posix_time::time_period objects using serialization lib +/*! time_period objects are broken down into 2 parts for serialization: + * a begining ptime object and an ending ptime object + */ +template<class Archive> +void load(Archive & ar, + boost::posix_time::time_period & tp, + unsigned int /*version*/) +{ + posix_time::time_duration td(1,0,0); + gregorian::date d(gregorian::not_a_date_time); + posix_time::ptime beg(d,td); + posix_time::ptime end(d,td); + ar & make_nvp("time_period_begin", beg); + ar & make_nvp("time_period_end", end); + tp = boost::posix_time::time_period(beg, end); +} + +//!override needed b/c no default constructor +template<class Archive> +inline void load_construct_data(Archive & ar, + boost::posix_time::time_period* tp, + const unsigned int /*file_version*/) +{ + posix_time::time_duration td(1,0,0); + gregorian::date d(gregorian::not_a_date_time); + posix_time::ptime beg(d,td); + posix_time::ptime end(d,td); + new(tp) boost::posix_time::time_period(beg,end); +} + +} // namespace serialization +} // namespace boost + +#endif diff --git a/ext/boost/date_time/special_defs.hpp b/ext/boost/date_time/special_defs.hpp new file mode 100644 index 0000000000..56eb6fea1d --- /dev/null +++ b/ext/boost/date_time/special_defs.hpp @@ -0,0 +1,25 @@ +#ifndef DATE_TIME_SPECIAL_DEFS_HPP__ +#define DATE_TIME_SPECIAL_DEFS_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +namespace boost { +namespace date_time { + + enum special_values {not_a_date_time, + neg_infin, pos_infin, + min_date_time, max_date_time, + not_special, NumSpecialValues}; + + +} } //namespace date_time + + +#endif + diff --git a/ext/boost/date_time/special_values_formatter.hpp b/ext/boost/date_time/special_values_formatter.hpp new file mode 100644 index 0000000000..33542b6e42 --- /dev/null +++ b/ext/boost/date_time/special_values_formatter.hpp @@ -0,0 +1,96 @@ + +#ifndef DATETIME_SPECIAL_VALUE_FORMATTER_HPP___ +#define DATETIME_SPECIAL_VALUE_FORMATTER_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include <vector> +#include <string> +#include "boost/date_time/special_defs.hpp" + +namespace boost { namespace date_time { + + + //! Class that provides generic formmatting ostream formatting for special values + /*! This class provides for the formmating of special values to an output stream. + * In particular, it produces strings for the values of negative and positive + * infinity as well as not_a_date_time. + * + * While not a facet, this class is used by the date and time facets for formatting + * special value types. + * + */ + template <class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > + class special_values_formatter + { + public: + typedef std::basic_string<CharT> string_type; + typedef CharT char_type; + typedef std::vector<string_type> collection_type; + static const char_type default_special_value_names[3][17]; + + //! Construct special values formatter using default strings. + /*! Default strings are not-a-date-time -infinity +infinity + */ + special_values_formatter() + { + std::copy(&default_special_value_names[0], + &default_special_value_names[3], + std::back_inserter(m_special_value_names)); + } + + //! Construct special values formatter from array of strings + /*! This constructor will take pair of iterators from an array of strings + * that represent the special values and copy them for use in formatting + * special values. + *@code + * const char* const special_value_names[]={"nadt","-inf","+inf" }; + * + * special_value_formatter svf(&special_value_names[0], &special_value_names[3]); + *@endcode + */ + special_values_formatter(const char_type* const* begin, const char_type* const* end) + { + std::copy(begin, end, std::back_inserter(m_special_value_names)); + } + special_values_formatter(typename collection_type::iterator beg, typename collection_type::iterator end) + { + std::copy(beg, end, std::back_inserter(m_special_value_names)); + } + + OutItrT put_special(OutItrT next, + const boost::date_time::special_values& value) const + { + + unsigned int index = value; + if (index < m_special_value_names.size()) { + std::copy(m_special_value_names[index].begin(), + m_special_value_names[index].end(), + next); + } + return next; + } + protected: + collection_type m_special_value_names; + }; + + //! Storage for the strings used to indicate special values + /* using c_strings to initialize these worked fine in testing, however, + * a project that compiled its objects separately, then linked in a separate + * step wound up with redefinition errors for the values in this array. + * Initializing individual characters eliminated this problem */ + template <class CharT, class OutItrT> + const typename special_values_formatter<CharT, OutItrT>::char_type special_values_formatter<CharT, OutItrT>::default_special_value_names[3][17] = { + {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}, + {'-','i','n','f','i','n','i','t','y'}, + {'+','i','n','f','i','n','i','t','y'} }; + + } } //namespace boost::date_time + +#endif diff --git a/ext/boost/date_time/special_values_parser.hpp b/ext/boost/date_time/special_values_parser.hpp new file mode 100644 index 0000000000..e48ec5fda9 --- /dev/null +++ b/ext/boost/date_time/special_values_parser.hpp @@ -0,0 +1,159 @@ + +#ifndef DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ +#define DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ + +/* Copyright (c) 2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: + */ + + +#include "boost/date_time/string_parse_tree.hpp" +#include "boost/date_time/special_defs.hpp" +#include <string> +#include <vector> + +namespace boost { namespace date_time { + + //! Class for special_value parsing + /*! + * TODO: add doc-comments for which elements can be changed + * Parses input stream for strings representing special_values. + * Special values parsed are: + * - not_a_date_time + * - neg_infin + * - pod_infin + * - min_date_time + * - max_date_time + */ + template<class date_type, typename charT> + class special_values_parser + { + public: + typedef std::basic_string<charT> string_type; + //typedef std::basic_stringstream<charT> stringstream_type; + typedef std::istreambuf_iterator<charT> stream_itr_type; + //typedef typename string_type::const_iterator const_itr; + //typedef typename date_type::year_type year_type; + //typedef typename date_type::month_type month_type; + typedef typename date_type::duration_type duration_type; + //typedef typename date_type::day_of_week_type day_of_week_type; + //typedef typename date_type::day_type day_type; + typedef string_parse_tree<charT> parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector<std::basic_string<charT> > collection_type; + + typedef charT char_type; + static const char_type nadt_string[16]; + static const char_type neg_inf_string[10]; + static const char_type pos_inf_string[10]; + static const char_type min_date_time_string[18]; + static const char_type max_date_time_string[18]; + + //! Creates a special_values_parser with the default set of "sv_strings" + special_values_parser() + { + sv_strings(string_type(nadt_string), + string_type(neg_inf_string), + string_type(pos_inf_string), + string_type(min_date_time_string), + string_type(max_date_time_string)); + } + + //! Creates a special_values_parser using a user defined set of element strings + special_values_parser(const string_type& nadt_str, + const string_type& neg_inf_str, + const string_type& pos_inf_str, + const string_type& min_dt_str, + const string_type& max_dt_str) + { + sv_strings(nadt_str, neg_inf_str, pos_inf_str, min_dt_str, max_dt_str); + } + + special_values_parser(typename collection_type::iterator beg, typename collection_type::iterator end) + { + collection_type phrases; + std::copy(beg, end, std::back_inserter(phrases)); + m_sv_strings = parse_tree_type(phrases, static_cast<int>(not_a_date_time)); + } + + special_values_parser(const special_values_parser<date_type,charT>& svp) + { + this->m_sv_strings = svp.m_sv_strings; + } + + //! Replace special value strings + void sv_strings(const string_type& nadt_str, + const string_type& neg_inf_str, + const string_type& pos_inf_str, + const string_type& min_dt_str, + const string_type& max_dt_str) + { + collection_type phrases; + phrases.push_back(nadt_str); + phrases.push_back(neg_inf_str); + phrases.push_back(pos_inf_str); + phrases.push_back(min_dt_str); + phrases.push_back(max_dt_str); + m_sv_strings = parse_tree_type(phrases, static_cast<int>(not_a_date_time)); + } + + /* Does not return a special_value because if the parsing fails, + * the return value will always be not_a_date_time + * (mr.current_match retains its default value of -1 on a failed + * parse and that casts to not_a_date_time). */ + //! Sets match_results.current_match to the corresponding special_value or -1 + bool match(stream_itr_type& sitr, + stream_itr_type& str_end, + match_results& mr) const + { + unsigned int level = 0; + m_sv_strings.match(sitr, str_end, mr, level); + return (mr.current_match != match_results::PARSE_ERROR); + } + /*special_values match(stream_itr_type& sitr, + stream_itr_type& str_end, + match_results& mr) const + { + unsigned int level = 0; + m_sv_strings.match(sitr, str_end, mr, level); + if(mr.current_match == match_results::PARSE_ERROR) { + throw std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"); + } + return static_cast<special_values>(mr.current_match); + }*/ + + + private: + parse_tree_type m_sv_strings; + + }; + + template<class date_type, class CharT> + const typename special_values_parser<date_type, CharT>::char_type + special_values_parser<date_type, CharT>::nadt_string[16] = + {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}; + template<class date_type, class CharT> + const typename special_values_parser<date_type, CharT>::char_type + special_values_parser<date_type, CharT>::neg_inf_string[10] = + {'-','i','n','f','i','n','i','t','y'}; + template<class date_type, class CharT> + const typename special_values_parser<date_type, CharT>::char_type + special_values_parser<date_type, CharT>::pos_inf_string[10] = + {'+','i','n','f','i','n','i','t','y'}; + template<class date_type, class CharT> + const typename special_values_parser<date_type, CharT>::char_type + special_values_parser<date_type, CharT>::min_date_time_string[18] = + {'m','i','n','i','m','u','m','-','d','a','t','e','-','t','i','m','e'}; + template<class date_type, class CharT> + const typename special_values_parser<date_type, CharT>::char_type + special_values_parser<date_type, CharT>::max_date_time_string[18] = + {'m','a','x','i','m','u','m','-','d','a','t','e','-','t','i','m','e'}; + +} } //namespace + +#endif // DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ + diff --git a/ext/boost/date_time/string_convert.hpp b/ext/boost/date_time/string_convert.hpp new file mode 100644 index 0000000000..54a979c70f --- /dev/null +++ b/ext/boost/date_time/string_convert.hpp @@ -0,0 +1,33 @@ +#ifndef _STRING_CONVERT_HPP___ +#define _STRING_CONVERT_HPP___ + +/* Copyright (c) 2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/compiler_config.hpp" +#include <string> + +namespace boost { +namespace date_time { + + //! Converts a string from one value_type to another + /*! Converts a wstring to a string (or a string to wstring). If both template parameters + * are of same type, a copy of the input string is returned. */ + template<class InputT, class OutputT> + inline + std::basic_string<OutputT> convert_string_type(const std::basic_string<InputT>& inp_str) + { + typedef std::basic_string<InputT> input_type; + typedef std::basic_string<OutputT> output_type; + output_type result; + result.insert(result.begin(), inp_str.begin(), inp_str.end()); + return result; + } + +}} // namespace boost::date_time + +#endif // _STRING_CONVERT_HPP___ diff --git a/ext/boost/date_time/string_parse_tree.hpp b/ext/boost/date_time/string_parse_tree.hpp new file mode 100644 index 0000000000..0d515ff824 --- /dev/null +++ b/ext/boost/date_time/string_parse_tree.hpp @@ -0,0 +1,278 @@ +#ifndef BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__ +#define BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +#include "boost/lexical_cast.hpp" //error without? +#include "boost/algorithm/string/case_conv.hpp" +#include <map> +#include <string> +#include <vector> +#include <algorithm> + +namespace boost { namespace date_time { + + +template<typename charT> +struct parse_match_result +{ + parse_match_result() : + match_depth(0), + current_match(-1)// -1 is match_not-found value + {} + typedef std::basic_string<charT> string_type; + string_type remaining() const + { + if (match_depth == cache.size()) { + return string_type(); + } + if (current_match == -1) { + return cache; + } + //some of the cache was used return the rest + return string_type(cache, match_depth); + } + charT last_char() const + { + return cache[cache.size()-1]; + } + //! Returns true if more characters were parsed than was necessary + /*! Should be used in conjunction with last_char() + * to get the remaining character. + */ + bool has_remaining() const + { + return (cache.size() > match_depth); + } + + // cache will hold characters that have been read from the stream + string_type cache; + unsigned short match_depth; + short current_match; + enum PARSE_STATE { PARSE_ERROR= -1 }; +}; + + //for debug -- really only char streams... +template<typename charT> +std::basic_ostream<charT>& +operator<<(std::basic_ostream<charT>& os, parse_match_result<charT>& mr) +{ + os << "cm: " << mr.current_match + << " C: '" << mr.cache + << "' md: " << mr.match_depth + << " R: " << mr.remaining(); + return os; +} + + + +//! Recursive data structure to allow efficient parsing of various strings +/*! This class provides a quick lookup by building what amounts to a + * tree data structure. It also features a match function which can + * can handle nasty input interators by caching values as it recurses + * the tree so that it can backtrack as needed. + */ +template<typename charT> +struct string_parse_tree +{ +#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) + typedef std::multimap<charT, string_parse_tree< charT> > ptree_coll; +#else + typedef std::multimap<charT, string_parse_tree > ptree_coll; +#endif + typedef typename ptree_coll::value_type value_type; + typedef typename ptree_coll::iterator iterator; + typedef typename ptree_coll::const_iterator const_iterator; + typedef std::basic_string<charT> string_type; + typedef std::vector<std::basic_string<charT> > collection_type; + typedef parse_match_result<charT> parse_match_result_type; + + /*! Parameter "starting_point" designates where the numbering begins. + * A starting_point of zero will start the numbering at zero + * (Sun=0, Mon=1, ...) were a starting_point of one starts the + * numbering at one (Jan=1, Feb=2, ...). The default is zero, + * negative vaules are not allowed */ + string_parse_tree(collection_type names, unsigned int starting_point=0) + { + // iterate thru all the elements and build the tree + unsigned short index = 0; + while (index != names.size() ) { + string_type s = boost::algorithm::to_lower_copy(names[index]); + insert(s, static_cast<unsigned short>(index + starting_point)); + index++; + } + //set the last tree node = index+1 indicating a value + index++; + } + + + string_parse_tree(short value = -1) : + m_value(value) + {} + ptree_coll m_next_chars; + short m_value; + + void insert(const string_type& s, unsigned short value) + { + unsigned int i = 0; + iterator ti; + while(i < s.size()) { + if (i==0) { + if (i == (s.size()-1)) { + ti = m_next_chars.insert(value_type(s[i], + string_parse_tree<charT>(value))); + } + else { + ti = m_next_chars.insert(value_type(s[i], + string_parse_tree<charT>())); + } + } + else { + if (i == (s.size()-1)) { + ti = ti->second.m_next_chars.insert(value_type(s[i], + string_parse_tree<charT>(value))); + } + + else { + ti = ti->second.m_next_chars.insert(value_type(s[i], + string_parse_tree<charT>())); + } + + } + i++; + } + } + + + //! Recursive function that finds a matching string in the tree. + /*! Must check match_results::has_remaining() after match() is + * called. This is required so the user can determine if + * stream iterator is already pointing to the expected + * character or not (match() might advance sitr to next char in stream). + * + * A parse_match_result that has been returned from a failed match + * attempt can be sent in to the match function of a different + * string_parse_tree to attempt a match there. Use the iterators + * for the partially consumed stream, the parse_match_result object, + * and '0' for the level parameter. */ + short + match(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end, + parse_match_result_type& result, + unsigned int& level) const + { + + level++; + charT c; + // if we conditionally advance sitr, we won't have + // to consume the next character past the input + bool adv_itr = true; + if (level > result.cache.size()) { + if (sitr == stream_end) return 0; //bail - input exhausted + c = static_cast<charT>(std::tolower(*sitr)); + //result.cache += c; + //sitr++; + } + else { + // if we're looking for characters from the cache, + // we don't want to increment sitr + adv_itr = false; + c = static_cast<charT>(std::tolower(result.cache[level-1])); + } + const_iterator litr = m_next_chars.lower_bound(c); + const_iterator uitr = m_next_chars.upper_bound(c); + while (litr != uitr) { // equal if not found + if(adv_itr) { + sitr++; + result.cache += c; + } + if (litr->second.m_value != -1) { // -1 is default value + if (result.match_depth < level) { + result.current_match = litr->second.m_value; + result.match_depth = static_cast<unsigned short>(level); + } + litr->second.match(sitr, stream_end, + result, level); + level--; + } + else { + litr->second.match(sitr, stream_end, + result, level); + level--; + } + + if(level <= result.cache.size()) { + adv_itr = false; + } + + litr++; + } + return result.current_match; + + } + + /*! Must check match_results::has_remaining() after match() is + * called. This is required so the user can determine if + * stream iterator is already pointing to the expected + * character or not (match() might advance sitr to next char in stream). + */ + parse_match_result_type + match(std::istreambuf_iterator<charT>& sitr, + std::istreambuf_iterator<charT>& stream_end) const + { + // lookup to_lower of char in tree. + unsigned int level = 0; + // string_type cache; + parse_match_result_type result; + match(sitr, stream_end, result, level); + return result; + } + + void printme(std::ostream& os, int& level) + { + level++; + iterator itr = m_next_chars.begin(); + iterator end = m_next_chars.end(); + // os << "starting level: " << level << std::endl; + while (itr != end) { + os << "level: " << level + << " node: " << itr->first + << " value: " << itr->second.m_value + << std::endl; + itr->second.printme(os, level); + itr++; + } + level--; + } + + void print(std::ostream& os) + { + int level = 0; + printme(os, level); + } + + void printmatch(std::ostream& os, charT c) + { + iterator litr = m_next_chars.lower_bound(c); + iterator uitr = m_next_chars.upper_bound(c); + os << "matches for: " << c << std::endl; + while (litr != uitr) { + os << " node: " << litr->first + << " value: " << litr->second.m_value + << std::endl; + litr++; + } + } + +}; + + +} } //namespace +#endif diff --git a/ext/boost/date_time/strings_from_facet.hpp b/ext/boost/date_time/strings_from_facet.hpp new file mode 100644 index 0000000000..2bc26fb33e --- /dev/null +++ b/ext/boost/date_time/strings_from_facet.hpp @@ -0,0 +1,125 @@ +#ifndef DATE_TIME_STRINGS_FROM_FACET__HPP___ +#define DATE_TIME_STRINGS_FROM_FACET__HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2009-02-01 06:29:43 -0500 (Sun, 01 Feb 2009) $ + */ + +#include <sstream> +#include <string> +#include <vector> +#include <locale> + +namespace boost { namespace date_time { + +//! This function gathers up all the month strings from a std::locale +/*! Using the time_put facet, this function creates a collection of + * all the month strings from a locale. This is handy when building + * custom date parsers or formatters that need to be localized. + * + *@param charT The type of char to use when gathering typically char + * or wchar_t. + *@param locale The locale to use when gathering the strings + *@param short_strings True(default) to gather short strings, + * false for long strings. + *@return A vector of strings containing the strings in order. eg: + * Jan, Feb, Mar, etc. + */ +template<typename charT> +std::vector<std::basic_string<charT> > +gather_month_strings(const std::locale& locale, bool short_strings=true) +{ + typedef std::basic_string<charT> string_type; + typedef std::vector<string_type> collection_type; + typedef std::basic_ostringstream<charT> ostream_type; + typedef std::ostreambuf_iterator<charT> ostream_iter_type; + typedef std::basic_ostringstream<charT> stringstream_type; + typedef std::time_put<charT> time_put_facet_type; + charT short_fmt[3] = { '%', 'b' }; + charT long_fmt[3] = { '%', 'B' }; + collection_type months; + string_type outfmt(short_fmt); + if (!short_strings) { + outfmt = long_fmt; + } + { + //grab the needed strings by using the locale to + //output each month + const charT* p_outfmt = outfmt.c_str(), *p_outfmt_end = p_outfmt + outfmt.size(); + for (int m=0; m < 12; m++) { + tm tm_value; + tm_value.tm_mon = m; + stringstream_type ss; + ostream_iter_type oitr(ss); + std::use_facet<time_put_facet_type>(locale).put(oitr, ss, ss.fill(), + &tm_value, + p_outfmt, + p_outfmt_end); + months.push_back(ss.str()); + } + } + return months; +} + +//! This function gathers up all the weekday strings from a std::locale +/*! Using the time_put facet, this function creates a collection of + * all the weekday strings from a locale starting with the string for + * 'Sunday'. This is handy when building custom date parsers or + * formatters that need to be localized. + * + *@param charT The type of char to use when gathering typically char + * or wchar_t. + *@param locale The locale to use when gathering the strings + *@param short_strings True(default) to gather short strings, + * false for long strings. + *@return A vector of strings containing the weekdays in order. eg: + * Sun, Mon, Tue, Wed, Thu, Fri, Sat + */ +template<typename charT> +std::vector<std::basic_string<charT> > +gather_weekday_strings(const std::locale& locale, bool short_strings=true) +{ + typedef std::basic_string<charT> string_type; + typedef std::vector<string_type> collection_type; + typedef std::basic_ostringstream<charT> ostream_type; + typedef std::ostreambuf_iterator<charT> ostream_iter_type; + typedef std::basic_ostringstream<charT> stringstream_type; + typedef std::time_put<charT> time_put_facet_type; + charT short_fmt[3] = { '%', 'a' }; + charT long_fmt[3] = { '%', 'A' }; + + collection_type weekdays; + + + string_type outfmt(short_fmt); + if (!short_strings) { + outfmt = long_fmt; + } + { + //grab the needed strings by using the locale to + //output each month / weekday + const charT* p_outfmt = outfmt.c_str(), *p_outfmt_end = p_outfmt + outfmt.size(); + for (int i=0; i < 7; i++) { + tm tm_value; + tm_value.tm_wday = i; + stringstream_type ss; + ostream_iter_type oitr(ss); + std::use_facet<time_put_facet_type>(locale).put(oitr, ss, ss.fill(), + &tm_value, + p_outfmt, + p_outfmt_end); + + weekdays.push_back(ss.str()); + } + } + return weekdays; +} + +} } //namespace + + +#endif diff --git a/ext/boost/date_time/time.hpp b/ext/boost/date_time/time.hpp new file mode 100644 index 0000000000..6a6cbe1f89 --- /dev/null +++ b/ext/boost/date_time/time.hpp @@ -0,0 +1,191 @@ +#ifndef DATE_TIME_TIME_HPP___ +#define DATE_TIME_TIME_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +/*! @file time.hpp + This file contains the interface for the time associated classes. +*/ +#include <string> +#include <boost/operators.hpp> +#include <boost/date_time/time_defs.hpp> +#include <boost/date_time/special_defs.hpp> + +namespace boost { +namespace date_time { + + //! Representation of a precise moment in time, including the date. + /*! + This class is a skeleton for the interface of a temporal type + with a resolution that is higher than a day. It is intended that + this class be the base class and that the actual time + class be derived using the BN pattern. In this way, the derived + class can make decisions such as 'should there be a default constructor' + and what should it set its value to, should there be optional constructors + say allowing only an time_durations that generate a time from a clock,etc. + So, in fact multiple time types can be created for a time_system with + different construction policies, and all of them can perform basic + operations by only writing a copy constructor. Finally, compiler + errors are also shorter. + + The real behavior of the time class is provided by the time_system + template parameter. This class must provide all the logic + for addition, subtraction, as well as define all the interface + types. + + */ + + template <class T, class time_system> + class base_time : private + boost::less_than_comparable<T + , boost::equality_comparable<T + > > + { + public: + typedef T time_type; + typedef typename time_system::time_rep_type time_rep_type; + typedef typename time_system::date_type date_type; + typedef typename time_system::date_duration_type date_duration_type; + typedef typename time_system::time_duration_type time_duration_type; + //typedef typename time_system::hms_type hms_type; + + base_time(const date_type& day, + const time_duration_type& td, + dst_flags dst=not_dst) : + time_(time_system::get_time_rep(day, td, dst)) + {} + base_time(special_values sv) : + time_(time_system::get_time_rep(sv)) + {} + base_time(const time_rep_type& rhs) : + time_(rhs) + {} + date_type date() const + { + return time_system::get_date(time_); + } + time_duration_type time_of_day() const + { + return time_system::get_time_of_day(time_); + } + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00"). Empty string is returned for classes that do + * not use a time_zone */ + std::string zone_name(bool /*as_offset*/=false) const + { + return time_system::zone_name(time_); + } + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00"). Empty string is returned for classes that do + * not use a time_zone */ + std::string zone_abbrev(bool /*as_offset*/=false) const + { + return time_system::zone_name(time_); + } + //! An empty string is returned for classes that do not use a time_zone + std::string zone_as_posix_string() const + { + return std::string(); + } + + //! check to see if date is not a value + bool is_not_a_date_time() const + { + return time_.is_not_a_date_time(); + } + //! check to see if date is one of the infinity values + bool is_infinity() const + { + return (is_pos_infinity() || is_neg_infinity()); + } + //! check to see if date is greater than all possible dates + bool is_pos_infinity() const + { + return time_.is_pos_infinity(); + } + //! check to see if date is greater than all possible dates + bool is_neg_infinity() const + { + return time_.is_neg_infinity(); + } + //! check to see if time is a special value + bool is_special() const + { + return(is_not_a_date_time() || is_infinity()); + } + //!Equality operator -- others generated by boost::equality_comparable + bool operator==(const time_type& rhs) const + { + return time_system::is_equal(time_,rhs.time_); + } + //!Equality operator -- others generated by boost::less_than_comparable + bool operator<(const time_type& rhs) const + { + return time_system::is_less(time_,rhs.time_); + } + //! difference between two times + time_duration_type operator-(const time_type& rhs) const + { + return time_system::subtract_times(time_, rhs.time_); + } + //! add date durations + time_type operator+(const date_duration_type& dd) const + { + return time_system::add_days(time_, dd); + } + time_type operator+=(const date_duration_type& dd) + { + time_ = (time_system::get_time_rep(date() + dd, time_of_day())); + return time_type(time_); + } + //! subtract date durations + time_type operator-(const date_duration_type& dd) const + { + return time_system::subtract_days(time_, dd); + } + time_type operator-=(const date_duration_type& dd) + { + time_ = (time_system::get_time_rep(date() - dd, time_of_day())); + return time_type(time_); + } + //! add time durations + time_type operator+(const time_duration_type& td) const + { + return time_type(time_system::add_time_duration(time_, td)); + } + time_type operator+=(const time_duration_type& td) + { + time_ = (time_system::get_time_rep(date(), time_of_day() + td)); + return time_type(time_); + } + //! subtract time durations + time_type operator-(const time_duration_type& rhs) const + { + return time_system::subtract_time_duration(time_, rhs); + } + time_type operator-=(const time_duration_type& td) + { + time_ = (time_system::get_time_rep(date(), time_of_day() - td)); + return time_type(time_); + } + + protected: + time_rep_type time_; + }; + + + + + +} } //namespace date_time::boost + + +#endif + diff --git a/ext/boost/date_time/time_clock.hpp b/ext/boost/date_time/time_clock.hpp new file mode 100644 index 0000000000..1ea5d2e8bd --- /dev/null +++ b/ext/boost/date_time/time_clock.hpp @@ -0,0 +1,83 @@ +#ifndef DATE_TIME_TIME_CLOCK_HPP___ +#define DATE_TIME_TIME_CLOCK_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file time_clock.hpp + This file contains the interface for clock devices. +*/ + +#include "boost/date_time/c_time.hpp" +#include "boost/shared_ptr.hpp" + +namespace boost { +namespace date_time { + + + //! A clock providing time level services based on C time_t capabilities + /*! This clock provides resolution to the 1 second level + */ + template<class time_type> + class second_clock + { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + + static time_type local_time() + { + ::std::time_t t; + ::std::time(&t); + ::std::tm curr, *curr_ptr; + //curr_ptr = ::std::localtime(&t); + curr_ptr = c_time::localtime(&t, &curr); + return create_time(curr_ptr); + } + + + //! Get the current day in universal date as a ymd_type + static time_type universal_time() + { + + ::std::time_t t; + ::std::time(&t); + ::std::tm curr, *curr_ptr; + //curr_ptr = ::std::gmtime(&t); + curr_ptr = c_time::gmtime(&t, &curr); + return create_time(curr_ptr); + } + + template<class time_zone_type> + static time_type local_time(boost::shared_ptr<time_zone_type> tz_ptr) + { + typedef typename time_type::utc_time_type utc_time_type; + utc_time_type utc_time = second_clock<utc_time_type>::universal_time(); + return time_type(utc_time, tz_ptr); + } + + + private: + static time_type create_time(::std::tm* current) + { + date_type d(static_cast<unsigned short>(current->tm_year + 1900), + static_cast<unsigned short>(current->tm_mon + 1), + static_cast<unsigned short>(current->tm_mday)); + time_duration_type td(current->tm_hour, + current->tm_min, + current->tm_sec); + return time_type(d,td); + } + + }; + + +} } //namespace date_time + + +#endif diff --git a/ext/boost/date_time/time_defs.hpp b/ext/boost/date_time/time_defs.hpp new file mode 100644 index 0000000000..55fe42a594 --- /dev/null +++ b/ext/boost/date_time/time_defs.hpp @@ -0,0 +1,43 @@ +#ifndef DATE_TIME_TIME_PRECISION_LIMITS_HPP +#define DATE_TIME_TIME_PRECISION_LIMITS_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + + +/*! \file time_defs.hpp + This file contains nice definitions for handling the resoluion of various time + reprsentations. +*/ + +namespace boost { +namespace date_time { + + //!Defines some nice types for handling time level resolutions + enum time_resolutions { + sec, + tenth, + hundreth, // deprecated misspelled version of hundredth + hundredth = hundreth, + milli, + ten_thousandth, + micro, + nano, + NumResolutions + }; + + //! Flags for daylight savings or summer time + enum dst_flags {not_dst, is_dst, calculate}; + + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/time_duration.hpp b/ext/boost/date_time/time_duration.hpp new file mode 100644 index 0000000000..2fd259012e --- /dev/null +++ b/ext/boost/date_time/time_duration.hpp @@ -0,0 +1,282 @@ +#ifndef DATE_TIME_TIME_DURATION_HPP___ +#define DATE_TIME_TIME_DURATION_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 04:24:49 -0400 (Thu, 04 Jun 2009) $ + */ + +#include <boost/cstdint.hpp> +#include <boost/operators.hpp> +#include <boost/date_time/time_defs.hpp> +#include <boost/date_time/special_defs.hpp> +#include <boost/date_time/compiler_config.hpp> + +namespace boost { +namespace date_time { + + + //! Represents some amount of elapsed time measure to a given resolution + /*! This class represents a standard set of capabilities for all + counted time durations. Time duration implementations should derive + from this class passing their type as the first template parameter. + This design allows the subclass duration types to provide custom + construction policies or other custom features not provided here. + + @param T The subclass type + @param rep_type The time resolution traits for this duration type. + */ + template<class T, typename rep_type> + class time_duration : private + boost::less_than_comparable<T + , boost::equality_comparable<T + > > + /* dividable, addable, and subtractable operator templates + * won't work with this class (MSVC++ 6.0). return type + * from '+=' is different than expected return type + * from '+'. multipliable probably wont work + * either (haven't tried) */ + { + public: + typedef T duration_type; //the subclass + typedef rep_type traits_type; + typedef typename rep_type::day_type day_type; + typedef typename rep_type::hour_type hour_type; + typedef typename rep_type::min_type min_type; + typedef typename rep_type::sec_type sec_type; + typedef typename rep_type::fractional_seconds_type fractional_seconds_type; + typedef typename rep_type::tick_type tick_type; + typedef typename rep_type::impl_type impl_type; + + time_duration() : ticks_(0) {} + time_duration(hour_type hours_in, + min_type minutes_in, + sec_type seconds_in=0, + fractional_seconds_type frac_sec_in = 0) : + ticks_(rep_type::to_tick_count(hours_in,minutes_in,seconds_in,frac_sec_in)) + {} + // copy constructor required for dividable<> + //! Construct from another time_duration (Copy constructor) + time_duration(const time_duration<T, rep_type>& other) + : ticks_(other.ticks_) + {} + //! Construct from special_values + time_duration(special_values sv) : ticks_(impl_type::from_special(sv)) + {} + //! Returns smallest representable duration + static duration_type unit() + { + return duration_type(0,0,0,1); + } + //! Return the number of ticks in a second + static tick_type ticks_per_second() + { + return rep_type::res_adjust(); + } + //! Provide the resolution of this duration type + static time_resolutions resolution() + { + return rep_type::resolution(); + } + //! Returns number of hours in the duration + hour_type hours() const + { + return static_cast<hour_type>(ticks() / (3600*ticks_per_second())); + } + //! Returns normalized number of minutes + min_type minutes() const + { + return static_cast<min_type>((ticks() / (60*ticks_per_second())) % 60); + } + //! Returns normalized number of seconds (0..60) + sec_type seconds() const + { + return static_cast<sec_type>((ticks()/ticks_per_second()) % 60); + } + //! Returns total number of seconds truncating any fractional seconds + sec_type total_seconds() const + { + return static_cast<sec_type>(ticks() / ticks_per_second()); + } + //! Returns total number of milliseconds truncating any fractional seconds + tick_type total_milliseconds() const + { + if (ticks_per_second() < 1000) { + return ticks() * (static_cast<tick_type>(1000) / ticks_per_second()); + } + return ticks() / (ticks_per_second() / static_cast<tick_type>(1000)) ; + } + //! Returns total number of nanoseconds truncating any sub millisecond values + tick_type total_nanoseconds() const + { + if (ticks_per_second() < 1000000000) { + return ticks() * (static_cast<tick_type>(1000000000) / ticks_per_second()); + } + return ticks() / (ticks_per_second() / static_cast<tick_type>(1000000000)) ; + } + //! Returns total number of microseconds truncating any sub microsecond values + tick_type total_microseconds() const + { + if (ticks_per_second() < 1000000) { + return ticks() * (static_cast<tick_type>(1000000) / ticks_per_second()); + } + return ticks() / (ticks_per_second() / static_cast<tick_type>(1000000)) ; + } + //! Returns count of fractional seconds at given resolution + fractional_seconds_type fractional_seconds() const + { + return (ticks() % ticks_per_second()); + } + //! Returns number of possible digits in fractional seconds + static unsigned short num_fractional_digits() + { + return rep_type::num_fractional_digits(); + } + duration_type invert_sign() const + { + return duration_type(ticks_ * (-1)); + } + bool is_negative() const + { + return ticks_ < 0; + } + bool operator<(const time_duration& rhs) const + { + return ticks_ < rhs.ticks_; + } + bool operator==(const time_duration& rhs) const + { + return ticks_ == rhs.ticks_; + } + //! unary- Allows for time_duration td = -td1 + duration_type operator-()const + { + return duration_type(ticks_ * (-1)); + } + duration_type operator-(const duration_type& d) const + { + return duration_type(ticks_ - d.ticks_); + } + duration_type operator+(const duration_type& d) const + { + return duration_type(ticks_ + d.ticks_); + } + duration_type operator/(int divisor) const + { + return duration_type(ticks_ / divisor); + } + duration_type operator-=(const duration_type& d) + { + ticks_ = ticks_ - d.ticks_; + return duration_type(ticks_); + } + duration_type operator+=(const duration_type& d) + { + ticks_ = ticks_ + d.ticks_; + return duration_type(ticks_); + } + //! Division operations on a duration with an integer. + duration_type operator/=(int divisor) + { + ticks_ = ticks_ / divisor; + return duration_type(ticks_); + } + //! Multiplication operations an a duration with an integer + duration_type operator*(int rhs) const + { + return duration_type(ticks_ * rhs); + } + duration_type operator*=(int divisor) + { + ticks_ = ticks_ * divisor; + return duration_type(ticks_); + } + tick_type ticks() const + { + return traits_type::as_number(ticks_); + } + + //! Is ticks_ a special value? + bool is_special()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_special(); + } + else{ + return false; + } + } + //! Is duration pos-infinity + bool is_pos_infinity()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_pos_infinity(); + } + else{ + return false; + } + } + //! Is duration neg-infinity + bool is_neg_infinity()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_neg_infinity(); + } + else{ + return false; + } + } + //! Is duration not-a-date-time + bool is_not_a_date_time()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_nan(); + } + else{ + return false; + } + } + + //! Used for special_values output + impl_type get_rep()const + { + return ticks_; + } + + protected: + explicit time_duration(impl_type in) : ticks_(in) {}; + impl_type ticks_; + }; + + + + //! Template for instantiating derived adjusting durations + /* These templates are designed to work with multiples of + * 10 for frac_of_second and resoultion adjustment + */ + template<class base_duration, boost::int64_t frac_of_second> + class subsecond_duration : public base_duration + { + public: + typedef typename base_duration::traits_type traits_type; + explicit subsecond_duration(boost::int64_t ss) : + base_duration(0,0,0,ss*traits_type::res_adjust()/frac_of_second) + {} + }; + + + +} } //namespace date_time + + + + +#endif + diff --git a/ext/boost/date_time/time_facet.hpp b/ext/boost/date_time/time_facet.hpp new file mode 100644 index 0000000000..c1a2f8e863 --- /dev/null +++ b/ext/boost/date_time/time_facet.hpp @@ -0,0 +1,1327 @@ + +#ifndef _DATE_TIME_FACET__HPP__ +#define _DATE_TIME_FACET__HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Martin Andrian, Jeff Garland, Bart Garst + * $Date: 2008-11-23 06:13:35 -0500 (Sun, 23 Nov 2008) $ + */ + +#include <cctype> +#include <locale> +#include <limits> +#include <string> +#include <sstream> +#include <iomanip> +#include <iterator> // i/ostreambuf_iterator +#include <exception> +#include <boost/assert.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/throw_exception.hpp> +#include <boost/algorithm/string/erase.hpp> +#include <boost/algorithm/string/replace.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/date_facet.hpp> +#include <boost/date_time/string_convert.hpp> +#include <boost/date_time/special_defs.hpp> + +namespace boost { +namespace date_time { + + template <class CharT> + struct time_formats { + public: + typedef CharT char_type; + static const char_type fractional_seconds_format[3]; // f + static const char_type fractional_seconds_or_none_format[3]; // F + static const char_type seconds_with_fractional_seconds_format[3]; // s + static const char_type seconds_format[3]; // S + static const char_type hours_format[3]; // H + static const char_type unrestricted_hours_format[3]; // O + static const char_type standard_format[9]; // x X + static const char_type zone_abbrev_format[3]; // z + static const char_type zone_name_format[3]; // Z + static const char_type zone_iso_format[3]; // q + static const char_type zone_iso_extended_format[3]; // Q + static const char_type posix_zone_string_format[4]; // ZP + static const char_type duration_sign_negative_only[3]; // - + static const char_type duration_sign_always[3]; // + + static const char_type duration_seperator[2]; + static const char_type negative_sign[2]; //- + static const char_type positive_sign[2]; //+ + static const char_type iso_time_format_specifier[18]; + static const char_type iso_time_format_extended_specifier[22]; + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + static const char_type default_time_format[23]; + // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev + static const char_type default_time_input_format[24]; + //default time_duration format is HH:MM:SS[.fff...] + static const char_type default_time_duration_format[11]; + }; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::fractional_seconds_format[3] = {'%','f'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::fractional_seconds_or_none_format[3] = {'%','F'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::seconds_with_fractional_seconds_format[3] = + {'%','s'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::seconds_format[3] = {'%','S'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::hours_format[3] = {'%','H'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::unrestricted_hours_format[3] = {'%','O'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + //time_formats<CharT>::standard_format[5] = {'%','c',' ','%','z'}; + time_formats<CharT>::standard_format[9] = {'%','x',' ','%','X',' ','%','z'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::zone_abbrev_format[3] = {'%','z'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::zone_name_format[3] = {'%','Z'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::zone_iso_format[3] = {'%','q'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::zone_iso_extended_format[3] ={'%','Q'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::posix_zone_string_format[4] ={'%','Z','P'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::duration_seperator[2] = {':'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::negative_sign[2] = {'-'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::positive_sign[2] = {'+'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::duration_sign_negative_only[3] ={'%','-'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::duration_sign_always[3] ={'%','+'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::iso_time_format_specifier[18] = + {'%', 'Y', '%', 'm', '%', 'd', 'T', + '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' }; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::iso_time_format_extended_specifier[22] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', + '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::default_time_format[23] = + {'%','Y','-','%','b','-','%','d',' ', + '%','H',':','%','M',':','%','S','%','F',' ','%','z'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::default_time_input_format[24] = + {'%','Y','-','%','b','-','%','d',' ', + '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'}; + + template <class CharT> + const typename time_formats<CharT>::char_type + time_formats<CharT>::default_time_duration_format[11] = + {'%','H',':','%','M',':','%','S','%','F'}; + + + + /*! Facet used for format-based output of time types + * This class provides for the use of format strings to output times. In addition + * to the flags for formatting date elements, the following are the allowed format flags: + * - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z") + * - %f => fractional seconds ".123456" + * - %F => fractional seconds or none: like frac sec but empty if frac sec == 0 + * - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f) + * - %S => seconds "02" + * - %z => abbreviated time zone "EDT" + * - %Z => full time zone name "Eastern Daylight Time" + */ + template <class time_type, + class CharT, + class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > + class time_facet : + public boost::date_time::date_facet<typename time_type::date_type , CharT, OutItrT> { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef boost::date_time::period<time_type,time_duration_type> period_type; + typedef boost::date_time::date_facet<typename time_type::date_type, CharT, OutItrT> base_type; + typedef typename base_type::string_type string_type; + typedef typename base_type::char_type char_type; + typedef typename base_type::period_formatter_type period_formatter_type; + typedef typename base_type::special_values_formatter_type special_values_formatter_type; + typedef typename base_type::date_gen_formatter_type date_gen_formatter_type; + static const char_type* fractional_seconds_format; // %f + static const char_type* fractional_seconds_or_none_format; // %F + static const char_type* seconds_with_fractional_seconds_format; // %s + static const char_type* seconds_format; // %S + static const char_type* hours_format; // %H + static const char_type* unrestricted_hours_format; // %O + static const char_type* standard_format; // %x X + static const char_type* zone_abbrev_format; // %z + static const char_type* zone_name_format; // %Z + static const char_type* zone_iso_format; // %q + static const char_type* zone_iso_extended_format; // %Q + static const char_type* posix_zone_string_format; // %ZP + static const char_type* duration_seperator; + static const char_type* duration_sign_always; // %+ + static const char_type* duration_sign_negative_only; // %- + static const char_type* negative_sign; //- + static const char_type* positive_sign; //+ + static const char_type* iso_time_format_specifier; + static const char_type* iso_time_format_extended_specifier; + + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + static const char_type* default_time_format; + //default time_duration format is HH:MM:SS[.fff...] + static const char_type* default_time_duration_format; + static std::locale::id id; + +#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) + std::locale::id& __get_id (void) const { return id; } +#endif + + //! sets default formats for ptime, local_date_time, and time_duration + explicit time_facet(::size_t a_ref = 0) + : base_type(default_time_format, period_formatter_type(), special_values_formatter_type(), date_gen_formatter_type(), a_ref), + m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) + {} + + //! Construct the facet with an explicitly specified format + explicit time_facet(const char_type* a_format, + period_formatter_type period_formatter = period_formatter_type(), + const special_values_formatter_type& special_value_formatter = special_values_formatter_type(), + date_gen_formatter_type dg_formatter = date_gen_formatter_type(), + ::size_t a_ref = 0) + : base_type(a_format, + period_formatter, + special_value_formatter, + dg_formatter, + a_ref), + m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) + {} + + //! Changes format for time_duration + void time_duration_format(const char_type* const format) + { + m_time_duration_format = format; + } + + virtual void set_iso_format() + { + this->m_format = iso_time_format_specifier; + } + virtual void set_iso_extended_format() + { + this->m_format = iso_time_format_extended_specifier; + } + + OutItrT put(OutItrT a_next, + std::ios_base& a_ios, + char_type a_fill, + const time_type& a_time) const + { + if (a_time.is_special()) { + return this->do_put_special(a_next, a_ios, a_fill, + a_time.date().as_special()); + } + string_type format(this->m_format); + + string_type frac_str; + if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { + // replace %s with %S.nnn + frac_str = + fractional_seconds_as_string(a_time.time_of_day(), false); + char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point(); + + string_type replace_string(seconds_format); + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + seconds_with_fractional_seconds_format, + replace_string); + } + /* NOTE: replacing posix_zone_string_format must be done BEFORE + * zone_name_format: "%ZP" & "%Z", if Z is checked first it will + * incorrectly replace a zone_name where a posix_string should go */ + if (format.find(posix_zone_string_format) != string_type::npos) { + if(a_time.zone_abbrev().empty()) { + // if zone_abbrev() returns an empty string, we want to + // erase posix_zone_string_format from format + boost::algorithm::erase_all(format, posix_zone_string_format); + } + else{ + boost::algorithm::replace_all(format, + posix_zone_string_format, + a_time.zone_as_posix_string()); + } + } + if (format.find(zone_name_format) != string_type::npos) { + if(a_time.zone_name().empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_name() returns an empty string, we want to + // erase zone_name_format & one preceeding space + std::basic_ostringstream<char_type> ss; + ss << ' ' << zone_name_format; + boost::algorithm::erase_all(format, ss.str()); + } + else{ + boost::algorithm::replace_all(format, + zone_name_format, + a_time.zone_name()); + } + } + if (format.find(zone_abbrev_format) != string_type::npos) { + if(a_time.zone_abbrev(false).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_abbrev() returns an empty string, we want to + // erase zone_abbrev_format & one preceeding space + std::basic_ostringstream<char_type> ss; + ss << ' ' << zone_abbrev_format; + boost::algorithm::erase_all(format, ss.str()); + } + else{ + boost::algorithm::replace_all(format, + zone_abbrev_format, + a_time.zone_abbrev(false)); + } + } + if (format.find(zone_iso_extended_format) != string_type::npos) { + if(a_time.zone_name(true).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_name() returns an empty string, we want to + // erase zone_iso_extended_format from format + boost::algorithm::erase_all(format, zone_iso_extended_format); + } + else{ + boost::algorithm::replace_all(format, + zone_iso_extended_format, + a_time.zone_name(true)); + } + } + + if (format.find(zone_iso_format) != string_type::npos) { + if(a_time.zone_abbrev(true).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_abbrev() returns an empty string, we want to + // erase zone_iso_format from format + boost::algorithm::erase_all(format, zone_iso_format); + } + else{ + boost::algorithm::replace_all(format, + zone_iso_format, + a_time.zone_abbrev(true)); + } + } + if (format.find(fractional_seconds_format) != string_type::npos) { + // replace %f with nnnnnnn + if (!frac_str.size()) { + frac_str = fractional_seconds_as_string(a_time.time_of_day(), false); + } + boost::algorithm::replace_all(format, + fractional_seconds_format, + frac_str); + } + + if (format.find(fractional_seconds_or_none_format) != string_type::npos) { + // replace %F with nnnnnnn or nothing if fs == 0 + frac_str = + fractional_seconds_as_string(a_time.time_of_day(), true); + if (frac_str.size()) { + char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point(); + string_type replace_string; + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + fractional_seconds_or_none_format, + replace_string); + } + else { + boost::algorithm::erase_all(format, + fractional_seconds_or_none_format); + } + } + + return this->do_put_tm(a_next, a_ios, a_fill, + to_tm(a_time), format); + } + + //! put function for time_duration + OutItrT put(OutItrT a_next, + std::ios_base& a_ios, + char_type a_fill, + const time_duration_type& a_time_dur) const + { + if (a_time_dur.is_special()) { + return this->do_put_special(a_next, a_ios, a_fill, + a_time_dur.get_rep().as_special()); + } + + string_type format(m_time_duration_format); + if (a_time_dur.is_negative()) { + // replace %- with minus sign. Should we use the numpunct facet? + boost::algorithm::replace_all(format, + duration_sign_negative_only, + negative_sign); + // remove all the %+ in the string with '-' + boost::algorithm::replace_all(format, + duration_sign_always, + negative_sign); + } + else { //duration is positive + // remove all the %- combos from the string + boost::algorithm::erase_all(format, duration_sign_negative_only); + // remove all the %+ in the string with '+' + boost::algorithm::replace_all(format, + duration_sign_always, + positive_sign); + } + + /* + * It is possible for a time duration to span more then 24 hours. + * Standard time_put::put is obliged to behave the same as strftime + * (See ISO 14882-2003 22.2.5.3.1 par. 1) and strftime's behavior is + * unspecified for the case when tm_hour field is outside 0-23 range + * (See ISO 9899-1999 7.23.3.5 par. 3). So we must output %H and %O + * here ourself. + */ + string_type hours_str; + if (format.find(unrestricted_hours_format) != string_type::npos) { + hours_str = hours_as_string(a_time_dur); + boost::algorithm::replace_all(format, unrestricted_hours_format, hours_str); + } + // We still have to process restricted hours format specifier. In order to + // support parseability of durations in ISO format (%H%M%S), we'll have to + // restrict the stringified hours length to 2 characters. + if (format.find(hours_format) != string_type::npos) { + if (hours_str.empty()) + hours_str = hours_as_string(a_time_dur); + BOOST_ASSERT(hours_str.length() <= 2); + boost::algorithm::replace_all(format, hours_format, hours_str); + } + + string_type frac_str; + if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { + // replace %s with %S.nnn + frac_str = + fractional_seconds_as_string(a_time_dur, false); + char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point(); + + string_type replace_string(seconds_format); + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + seconds_with_fractional_seconds_format, + replace_string); + } + if (format.find(fractional_seconds_format) != string_type::npos) { + // replace %f with nnnnnnn + if (!frac_str.size()) { + frac_str = fractional_seconds_as_string(a_time_dur, false); + } + boost::algorithm::replace_all(format, + fractional_seconds_format, + frac_str); + } + + if (format.find(fractional_seconds_or_none_format) != string_type::npos) { + // replace %F with nnnnnnn or nothing if fs == 0 + frac_str = + fractional_seconds_as_string(a_time_dur, true); + if (frac_str.size()) { + char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point(); + string_type replace_string; + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + fractional_seconds_or_none_format, + replace_string); + } + else { + boost::algorithm::erase_all(format, + fractional_seconds_or_none_format); + } + } + + return this->do_put_tm(a_next, a_ios, a_fill, + to_tm(a_time_dur), format); + } + + OutItrT put(OutItrT next, std::ios_base& a_ios, + char_type fill, const period_type& p) const + { + return this->m_period_formatter.put_period(next, a_ios, fill,p,*this); + } + + + protected: + + static + string_type + fractional_seconds_as_string(const time_duration_type& a_time, + bool null_when_zero) + { + typename time_duration_type::fractional_seconds_type frac_sec = + a_time.fractional_seconds(); + + if (null_when_zero && (frac_sec == 0)) { + return string_type(); + } + + //make sure there is no sign + return integral_as_string( + date_time::absolute_value(frac_sec), + time_duration_type::num_fractional_digits()); + } + + static + string_type + hours_as_string(const time_duration_type& a_time, int width = 2) + { + return integral_as_string(date_time::absolute_value(a_time.hours()), width); + } + + template< typename IntT > + static + string_type + integral_as_string(IntT val, int width = 2) + { + std::basic_ostringstream<char_type> ss; + ss.imbue(std::locale::classic()); // don't want any formatting + ss << std::setw(width) + << std::setfill(static_cast<char_type>('0')); +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + // JDG [7/6/02 VC++ compatibility] + char_type buff[34]; + ss << _i64toa(static_cast<boost::int64_t>(val), buff, 10); +#else + ss << val; +#endif + return ss.str(); + } + + private: + string_type m_time_duration_format; + + }; + + template <class time_type, class CharT, class OutItrT> + std::locale::id time_facet<time_type, CharT, OutItrT>::id; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::seconds_with_fractional_seconds_format = + time_formats<CharT>::seconds_with_fractional_seconds_format; + + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::zone_name_format = time_formats<CharT>::zone_name_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::zone_iso_extended_format =time_formats<CharT>::zone_iso_extended_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::posix_zone_string_format =time_formats<CharT>::posix_zone_string_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::seconds_format = time_formats<CharT>::seconds_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::hours_format = time_formats<CharT>::hours_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::unrestricted_hours_format = time_formats<CharT>::unrestricted_hours_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::standard_format = time_formats<CharT>::standard_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::duration_seperator = time_formats<CharT>::duration_seperator; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::negative_sign = time_formats<CharT>::negative_sign; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::positive_sign = time_formats<CharT>::positive_sign; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::duration_sign_negative_only = time_formats<CharT>::duration_sign_negative_only; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::duration_sign_always = time_formats<CharT>::duration_sign_always; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type,CharT, OutItrT>::char_type* + time_facet<time_type,CharT, OutItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::default_time_format = + time_formats<CharT>::default_time_format; + + template <class time_type, class CharT, class OutItrT> + const typename time_facet<time_type, CharT, OutItrT>::char_type* + time_facet<time_type, CharT, OutItrT>::default_time_duration_format = + time_formats<CharT>::default_time_duration_format; + + + //! Facet for format-based input. + /*! + */ + template <class time_type, + class CharT, + class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > > + class time_input_facet : + public boost::date_time::date_input_facet<typename time_type::date_type , CharT, InItrT> { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type; + typedef boost::date_time::period<time_type,time_duration_type> period_type; + typedef boost::date_time::date_input_facet<typename time_type::date_type, CharT, InItrT> base_type; + typedef typename base_type::duration_type date_duration_type; + typedef typename base_type::year_type year_type; + typedef typename base_type::month_type month_type; + typedef typename base_type::day_type day_type; + typedef typename base_type::string_type string_type; + typedef typename string_type::const_iterator const_itr; + typedef typename base_type::char_type char_type; + typedef typename base_type::format_date_parser_type format_date_parser_type; + typedef typename base_type::period_parser_type period_parser_type; + typedef typename base_type::special_values_parser_type special_values_parser_type; + typedef typename base_type::date_gen_parser_type date_gen_parser_type; + typedef typename base_type::special_values_parser_type::match_results match_results; + + static const char_type* fractional_seconds_format; // f + static const char_type* fractional_seconds_or_none_format; // F + static const char_type* seconds_with_fractional_seconds_format; // s + static const char_type* seconds_format; // S + static const char_type* standard_format; // x X + static const char_type* zone_abbrev_format; // z + static const char_type* zone_name_format; // Z + static const char_type* zone_iso_format; // q + static const char_type* zone_iso_extended_format; // Q + static const char_type* duration_seperator; + static const char_type* iso_time_format_specifier; + static const char_type* iso_time_format_extended_specifier; + static const char_type* default_time_input_format; + static const char_type* default_time_duration_format; + static std::locale::id id; + + //! Constructor that takes a format string for a ptime + explicit time_input_facet(const string_type& format, ::size_t a_ref = 0) + : base_type(format, a_ref), + m_time_duration_format(default_time_duration_format) + { } + + explicit time_input_facet(const string_type& format, + const format_date_parser_type& date_parser, + const special_values_parser_type& sv_parser, + const period_parser_type& per_parser, + const date_gen_parser_type& date_gen_parser, + ::size_t a_ref = 0) + : base_type(format, + date_parser, + sv_parser, + per_parser, + date_gen_parser, + a_ref), + m_time_duration_format(default_time_duration_format) + {} + + //! sets default formats for ptime, local_date_time, and time_duration + explicit time_input_facet(::size_t a_ref = 0) + : base_type(default_time_input_format, a_ref), + m_time_duration_format(default_time_duration_format) + { } + + //! Set the format for time_duration + void time_duration_format(const char_type* const format) { + m_time_duration_format = format; + } + virtual void set_iso_format() + { + this->m_format = iso_time_format_specifier; + } + virtual void set_iso_extended_format() + { + this->m_format = iso_time_format_extended_specifier; + } + + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + period_type& p) const + { + p = this->m_period_parser.get_period(sitr, + stream_end, + a_ios, + p, + time_duration_type::unit(), + *this); + return sitr; + } + + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...] + + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_duration_type& td) const + { + // skip leading whitespace + while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } + + bool use_current_char = false; + + // num_get will consume the +/-, we may need a copy if special_value + char_type c = '\0'; + if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { + c = *sitr; + } + + typedef typename time_duration_type::hour_type hour_type; + typedef typename time_duration_type::min_type min_type; + typedef typename time_duration_type::sec_type sec_type; + + hour_type hour = 0; + min_type min = 0; + sec_type sec = 0; + typename time_duration_type::fractional_seconds_type frac(0); + + typedef std::num_get<CharT, InItrT> num_get; + if(!std::has_facet<num_get>(a_ios.getloc())) { + num_get* ng = new num_get(); + std::locale loc = std::locale(a_ios.getloc(), ng); + a_ios.imbue(loc); + } + + const_itr itr(m_time_duration_format.begin()); + while (itr != m_time_duration_format.end() && (sitr != stream_end)) { + if (*itr == '%') { + ++itr; + if (*itr != '%') { + switch(*itr) { + case 'O': + { + // A period may span more than 24 hours. In that case the format + // string should be composed with the unrestricted hours specifier. + hour = var_string_to_int<hour_type, CharT>(sitr, stream_end, + std::numeric_limits<hour_type>::digits10 + 1); + if(hour == -1){ + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 'H': + { + match_results mr; + hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2); + if(hour == -1){ + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 'M': + { + match_results mr; + min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2); + if(min == -1){ + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 's': + case 'S': + { + match_results mr; + sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2); + if(sec == -1){ + return check_special_value(sitr, stream_end, td, c); + } + if (*itr == 'S') + break; + // %s is the same as %S%f so we drop through into %f + } + case 'f': + { + // check for decimal, check special_values if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 'F': + { + // check for decimal, skip if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + // nothing was parsed so we don't want to advance sitr + use_current_char = true; + } + break; + } + default: + {} // ignore what we don't understand? + }// switch + } + else { // itr == '%', second consecutive + ++sitr; + } + + ++itr; //advance past format specifier + } + else { //skip past chars in format and in buffer + ++itr; + // set use_current_char when sitr is already + // pointing at the next character to process + if (use_current_char) { + use_current_char = false; + } + else { + ++sitr; + } + } + } + + td = time_duration_type(hour, min, sec, frac); + return sitr; + } + + + //! Parses a time object from the input stream + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_type& t) const + { + string_type tz_str; + return get(sitr, stream_end, a_ios, t, tz_str, false); + } + //! Expects a time_zone in the input stream + InItrT get_local_time(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_type& t, + string_type& tz_str) const + { + return get(sitr, stream_end, a_ios, t, tz_str, true); + } + + protected: + + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_type& t, + string_type& tz_str, + bool time_is_local) const + { + // skip leading whitespace + while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } + + bool use_current_char = false; + bool use_current_format_char = false; // used whith two character flags + + // num_get will consume the +/-, we may need a copy if special_value + char_type c = '\0'; + if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { + c = *sitr; + } + + typedef typename time_duration_type::hour_type hour_type; + typedef typename time_duration_type::min_type min_type; + typedef typename time_duration_type::sec_type sec_type; + + // time elements + hour_type hour = 0; + min_type min = 0; + sec_type sec = 0; + typename time_duration_type::fractional_seconds_type frac(0); + // date elements + short day_of_year(0); + /* Initialized the following to their minimum values. These intermediate + * objects are used so we get specific exceptions when part of the input + * is unparsable. + * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ + year_type t_year(1400); + month_type t_month(1); + day_type t_day(1); + + typedef std::num_get<CharT, InItrT> num_get; + if(!std::has_facet<num_get>(a_ios.getloc())) { + num_get* ng = new num_get(); + std::locale loc = std::locale(a_ios.getloc(), ng); + a_ios.imbue(loc); + } + + const_itr itr(this->m_format.begin()); + while (itr != this->m_format.end() && (sitr != stream_end)) { + if (*itr == '%') { + ++itr; + if (*itr != '%') { + // the cases are grouped by date & time flags - not alphabetical order + switch(*itr) { + // date flags + case 'Y': + case 'y': + { + char_type cs[3] = { '%', *itr }; + string_type s(cs); + match_results mr; + try { + t_year = this->m_parser.parse_year(sitr, stream_end, s, mr); + } + catch(std::out_of_range&) { // base class for bad_year exception + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast<special_values>(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_year + } + } + break; + } + case 'B': + case 'b': + case 'm': + { + char_type cs[3] = { '%', *itr }; + string_type s(cs); + match_results mr; + try { + t_month = this->m_parser.parse_month(sitr, stream_end, s, mr); + } + catch(std::out_of_range&) { // base class for bad_month exception + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast<special_values>(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_month + } + } + // did m_parser already advance sitr to next char? + if(mr.has_remaining()) { + use_current_char = true; + } + break; + } + case 'a': + case 'A': + case 'w': + { + // weekday is not used in construction but we need to get it out of the stream + char_type cs[3] = { '%', *itr }; + string_type s(cs); + match_results mr; + typename date_type::day_of_week_type wd(0); + try { + wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr); + } + catch(std::out_of_range&) { // base class for bad_weekday exception + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast<special_values>(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_weekday + } + } + // did m_parser already advance sitr to next char? + if(mr.has_remaining()) { + use_current_char = true; + } + break; + } + case 'j': + { + // code that gets julian day (from format_date_parser) + match_results mr; + day_of_year = fixed_string_to_int<unsigned short, CharT>(sitr, stream_end, mr, 3); + if(day_of_year == -1) { + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast<special_values>(mr.current_match)); + return sitr; + } + } + // these next two lines are so we get an exception with bad input + typedef typename time_type::date_type::day_of_year_type day_of_year_type; + day_of_year_type t_day_of_year(day_of_year); + break; + } + case 'd': + { + try { + t_day = this->m_parser.parse_day_of_month(sitr, stream_end); + } + catch(std::out_of_range&) { // base class for exception bad_day_of_month + match_results mr; + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast<special_values>(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_day_of_month + } + } + break; + } + // time flags + case 'H': + { + match_results mr; + hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2); + if(hour == -1){ + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 'M': + { + match_results mr; + min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2); + if(min == -1){ + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 's': + case 'S': + { + match_results mr; + sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2); + if(sec == -1){ + return check_special_value(sitr, stream_end, t, c); + } + if (*itr == 'S') + break; + // %s is the same as %S%f so we drop through into %f + } + case 'f': + { + // check for decimal, check SV if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 'F': + { + // check for decimal, skip if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + // nothing was parsed so we don't want to advance sitr + use_current_char = true; + } + break; + } + // time_zone flags + //case 'q': + //case 'Q': + //case 'z': + case 'Z': + { + if(time_is_local) { // skip if 't' is a ptime + ++itr; + if(*itr == 'P') { + // skip leading whitespace + while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } + // parse zone + while((sitr != stream_end) && (!std::isspace(*sitr))) { + tz_str += *sitr; + ++sitr; + } + } + else { + use_current_format_char = true; + } + + } + else { + // nothing was parsed so we don't want to advance sitr + use_current_char = true; + } + + break; + } + default: + {} // ignore what we don't understand? + }// switch + } + else { // itr == '%', second consecutive + ++sitr; + } + + if(use_current_format_char) { + use_current_format_char = false; + } + else { + ++itr; //advance past format specifier + } + + } + else { //skip past chars in format and in buffer + ++itr; + // set use_current_char when sitr is already + // pointing at the next character to process + if (use_current_char) { + use_current_char = false; + } + else { + ++sitr; + } + } + } + + date_type d(not_a_date_time); + if (day_of_year > 0) { + d = date_type(static_cast<unsigned short>(t_year-1),12,31) + date_duration_type(day_of_year); + } + else { + d = date_type(t_year, t_month, t_day); + } + + time_duration_type td(hour, min, sec, frac); + t = time_type(d, td); + return sitr; + } + + //! Helper function to check for special_value + /*! First character may have been consumed during original parse + * attempt. Parameter 'c' should be a copy of that character. + * Throws ios_base::failure if parse fails. */ + template<class temporal_type> + inline + InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const + { + match_results mr; + if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed? + mr.cache += c; + } + this->m_sv_parser.match(sitr, stream_end, mr); + if(mr.current_match == match_results::PARSE_ERROR) { + std::string tmp = convert_string_type<char_type, char>(mr.cache); + boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + tmp + "'")); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return sitr); // should never reach + } + tt = temporal_type(static_cast<special_values>(mr.current_match)); + return sitr; + } + + //! Helper function for parsing a fractional second type from the stream + void parse_frac_type(InItrT& sitr, + InItrT& stream_end, + fracional_seconds_type& frac) const + { + string_type cache; + while((sitr != stream_end) && std::isdigit(*sitr)) { + cache += *sitr; + ++sitr; + } + if(cache.size() > 0) { + unsigned short precision = time_duration_type::num_fractional_digits(); + // input may be only the first few decimal places + if(cache.size() < precision) { + frac = lexical_cast<fracional_seconds_type>(cache); + frac = decimal_adjust(frac, static_cast<unsigned short>(precision - cache.size())); + } + else { + // if input has too many decimal places, drop excess digits + frac = lexical_cast<fracional_seconds_type>(cache.substr(0, precision)); + } + } + } + + private: + string_type m_time_duration_format; + + //! Helper function to adjust trailing zeros when parsing fractional digits + template<class int_type> + inline + int_type decimal_adjust(int_type val, const unsigned short places) const + { + unsigned long factor = 1; + for(int i = 0; i < places; ++i){ + factor *= 10; // shift decimal to the right + } + return val * factor; + } + + }; + +template <class time_type, class CharT, class InItrT> + std::locale::id time_input_facet<time_type, CharT, InItrT>::id; + +template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::seconds_with_fractional_seconds_format = time_formats<CharT>::seconds_with_fractional_seconds_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::seconds_format = time_formats<CharT>::seconds_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::standard_format = time_formats<CharT>::standard_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::zone_name_format = time_formats<CharT>::zone_name_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::zone_iso_extended_format = time_formats<CharT>::zone_iso_extended_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::duration_seperator = time_formats<CharT>::duration_seperator; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::default_time_input_format = time_formats<CharT>::default_time_input_format; + + template <class time_type, class CharT, class InItrT> + const typename time_input_facet<time_type, CharT, InItrT>::char_type* + time_input_facet<time_type, CharT, InItrT>::default_time_duration_format = time_formats<CharT>::default_time_duration_format; + + +} } // namespaces + + +#endif + diff --git a/ext/boost/date_time/time_formatting_streams.hpp b/ext/boost/date_time/time_formatting_streams.hpp new file mode 100644 index 0000000000..3537c103cc --- /dev/null +++ b/ext/boost/date_time/time_formatting_streams.hpp @@ -0,0 +1,122 @@ +#ifndef DATE_TIME_TIME_FORMATTING_STREAMS_HPP___ +#define DATE_TIME_TIME_FORMATTING_STREAMS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <boost/date_time/compiler_config.hpp> + +#ifndef BOOST_DATE_TIME_NO_LOCALE + +#include <locale> +#include <iomanip> +#include <iostream> +#include <boost/date_time/date_formatting_locales.hpp> +#include <boost/date_time/time_resolution_traits.hpp> + +namespace boost { +namespace date_time { + + + //! Put a time type into a stream using appropriate facets + template<class time_duration_type, + class charT = char> + class ostream_time_duration_formatter + { + public: + typedef std::basic_ostream<charT> ostream_type; + typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type; + + //! Put time into an ostream + static void duration_put(const time_duration_type& td, + ostream_type& os) + { + if(td.is_special()) { + os << td.get_rep(); + } + else { + charT fill_char = '0'; + if(td.is_negative()) { + os << '-'; + } + os << std::setw(2) << std::setfill(fill_char) + << absolute_value(td.hours()) << ":"; + os << std::setw(2) << std::setfill(fill_char) + << absolute_value(td.minutes()) << ":"; + os << std::setw(2) << std::setfill(fill_char) + << absolute_value(td.seconds()); + fractional_seconds_type frac_sec = + absolute_value(td.fractional_seconds()); + if (frac_sec != 0) { + os << "." + << std::setw(time_duration_type::num_fractional_digits()) + << std::setfill(fill_char) + << frac_sec; + } + } // else + } // duration_put + }; //class ostream_time_duration_formatter + + //! Put a time type into a stream using appropriate facets + template<class time_type, + class charT = char> + class ostream_time_formatter + { + public: + typedef std::basic_ostream<charT> ostream_type; + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef ostream_time_duration_formatter<time_duration_type, charT> duration_formatter; + + //! Put time into an ostream + static void time_put(const time_type& t, + ostream_type& os) + { + date_type d = t.date(); + os << d; + if(!d.is_infinity() && !d.is_not_a_date()) + { + os << " "; //TODO: fix the separator here. + duration_formatter::duration_put(t.time_of_day(), os); + } + + } // time_to_ostream + }; //class ostream_time_formatter + + + //! Put a time period into a stream using appropriate facets + template<class time_period_type, + class charT = char> + class ostream_time_period_formatter + { + public: + typedef std::basic_ostream<charT> ostream_type; + typedef typename time_period_type::point_type time_type; + typedef ostream_time_formatter<time_type, charT> time_formatter; + + //! Put time into an ostream + static void period_put(const time_period_type& tp, + ostream_type& os) + { + os << '['; //TODO: facet or manipulator for periods? + time_formatter::time_put(tp.begin(), os); + os << '/'; //TODO: facet or manipulator for periods? + time_formatter::time_put(tp.last(), os); + os << ']'; + + } // period_put + + }; //class ostream_time_period_formatter + + + +} } //namespace date_time + +#endif //BOOST_DATE_TIME_NO_LOCALE + +#endif diff --git a/ext/boost/date_time/time_iterator.hpp b/ext/boost/date_time/time_iterator.hpp new file mode 100644 index 0000000000..2258a3308e --- /dev/null +++ b/ext/boost/date_time/time_iterator.hpp @@ -0,0 +1,52 @@ +#ifndef DATE_TIME_TIME_ITERATOR_HPP___ +#define DATE_TIME_TIME_ITERATOR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + + + //! Simple time iterator skeleton class + template<class time_type> + class time_itr { + public: + typedef typename time_type::time_duration_type time_duration_type; + time_itr(time_type t, time_duration_type d) : current_(t), offset_(d) {}; + time_itr& operator++() + { + current_ = current_ + offset_; + return *this; + } + time_itr& operator--() + { + current_ = current_ - offset_; + return *this; + } + time_type operator*() {return current_;}; + time_type* operator->() {return ¤t_;}; + bool operator< (const time_type& t) {return current_ < t;}; + bool operator<= (const time_type& t) {return current_ <= t;}; + bool operator!= (const time_type& t) {return current_ != t;}; + bool operator== (const time_type& t) {return current_ == t;}; + bool operator> (const time_type& t) {return current_ > t;}; + bool operator>= (const time_type& t) {return current_ >= t;}; + + private: + time_type current_; + time_duration_type offset_; + }; + + + +} }//namespace date_time + + +#endif diff --git a/ext/boost/date_time/time_parsing.hpp b/ext/boost/date_time/time_parsing.hpp new file mode 100644 index 0000000000..dfccf6a1df --- /dev/null +++ b/ext/boost/date_time/time_parsing.hpp @@ -0,0 +1,321 @@ +#ifndef _DATE_TIME_TIME_PARSING_HPP___ +#define _DATE_TIME_TIME_PARSING_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/tokenizer.hpp" +#include "boost/lexical_cast.hpp" +#include "boost/date_time/date_parsing.hpp" +#include "boost/cstdint.hpp" +#include <iostream> + +namespace boost { +namespace date_time { + + //! computes exponential math like 2^8 => 256, only works with positive integers + //Not general purpose, but needed b/c std::pow is not available + //everywehere. Hasn't been tested with negatives and zeros + template<class int_type> + inline + int_type power(int_type base, int_type exponent) + { + int_type result = 1; + for(int i = 0; i < exponent; ++i){ + result *= base; + } + return result; + } + + //! Creates a time_duration object from a delimited string + /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". + * If the number of fractional digits provided is greater than the + * precision of the time duration type then the extra digits are + * truncated. + * + * A negative duration will be created if the first character in + * string is a '-', all other '-' will be treated as delimiters. + * Accepted delimiters are "-:,.". + */ + template<class time_duration, class char_type> + inline + time_duration + str_from_delimited_time_duration(const std::basic_string<char_type>& s) + { + unsigned short min=0, sec =0; + int hour =0; + bool is_neg = (s.at(0) == '-'); + boost::int64_t fs=0; + int pos = 0; + + typedef typename std::basic_string<char_type>::traits_type traits_type; + typedef boost::char_separator<char_type, traits_type> char_separator_type; + typedef boost::tokenizer<char_separator_type, + typename std::basic_string<char_type>::const_iterator, + std::basic_string<char_type> > tokenizer; + typedef typename boost::tokenizer<char_separator_type, + typename std::basic_string<char_type>::const_iterator, + typename std::basic_string<char_type> >::iterator tokenizer_iterator; + + char_type sep_chars[5] = {'-',':',',','.'}; + char_separator_type sep(sep_chars); + tokenizer tok(s,sep); + for(tokenizer_iterator beg=tok.begin(); beg!=tok.end();++beg){ + switch(pos) { + case 0: { + hour = boost::lexical_cast<int>(*beg); + break; + } + case 1: { + min = boost::lexical_cast<unsigned short>(*beg); + break; + } + case 2: { + sec = boost::lexical_cast<unsigned short>(*beg); + break; + }; + case 3: { + int digits = static_cast<int>(beg->length()); + //Works around a bug in MSVC 6 library that does not support + //operator>> thus meaning lexical_cast will fail to compile. +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + // msvc wouldn't compile 'time_duration::num_fractional_digits()' + // (required template argument list) as a workaround a temp + // time_duration object was used + time_duration td(hour,min,sec,fs); + int precision = td.num_fractional_digits(); + // _atoi64 is an MS specific function + if(digits >= precision) { + // drop excess digits + fs = _atoi64(beg->substr(0, precision).c_str()); + } + else { + fs = _atoi64(beg->c_str()); + } +#else + int precision = time_duration::num_fractional_digits(); + if(digits >= precision) { + // drop excess digits + fs = boost::lexical_cast<boost::int64_t>(beg->substr(0, precision)); + } + else { + fs = boost::lexical_cast<boost::int64_t>(*beg); + } +#endif + if(digits < precision){ + // trailing zeros get dropped from the string, + // "1:01:01.1" would yield .000001 instead of .100000 + // the power() compensates for the missing decimal places + fs *= power(10, precision - digits); + } + + break; + } + }//switch + pos++; + } + if(is_neg) { + return -time_duration(hour, min, sec, fs); + } + else { + return time_duration(hour, min, sec, fs); + } + } + + //! Creates a time_duration object from a delimited string + /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". + * If the number of fractional digits provided is greater than the + * precision of the time duration type then the extra digits are + * truncated. + * + * A negative duration will be created if the first character in + * string is a '-', all other '-' will be treated as delimiters. + * Accepted delimiters are "-:,.". + */ + template<class time_duration> + inline + time_duration + parse_delimited_time_duration(const std::string& s) + { + return str_from_delimited_time_duration<time_duration,char>(s); + } + + //! Utility function to split appart string + inline + bool + split(const std::string& s, + char sep, + std::string& first, + std::string& second) + { + int sep_pos = static_cast<int>(s.find(sep)); + first = s.substr(0,sep_pos); + second = s.substr(sep_pos+1); + return true; + } + + + template<class time_type> + inline + time_type + parse_delimited_time(const std::string& s, char sep) + { + typedef typename time_type::time_duration_type time_duration; + typedef typename time_type::date_type date_type; + + //split date/time on a unique delimiter char such as ' ' or 'T' + std::string date_string, tod_string; + split(s, sep, date_string, tod_string); + //call parse_date with first string + date_type d = parse_date<date_type>(date_string); + //call parse_time_duration with remaining string + time_duration td = parse_delimited_time_duration<time_duration>(tod_string); + //construct a time + return time_type(d, td); + + } + + //! Parse time duration part of an iso time of form: [-]hhmmss[.fff...] (eg: 120259.123 is 12 hours, 2 min, 59 seconds, 123000 microseconds) + template<class time_duration> + inline + time_duration + parse_undelimited_time_duration(const std::string& s) + { + int precision = 0; + { + // msvc wouldn't compile 'time_duration::num_fractional_digits()' + // (required template argument list) as a workaround, a temp + // time_duration object was used + time_duration tmp(0,0,0,1); + precision = tmp.num_fractional_digits(); + } + // 'precision+1' is so we grab all digits, plus the decimal + int offsets[] = {2,2,2, precision+1}; + int pos = 0, sign = 0; + int hours = 0; + short min=0, sec=0; + boost::int64_t fs=0; + // increment one position if the string was "signed" + if(s.at(sign) == '-') + { + ++sign; + } + // stlport choked when passing s.substr() to tokenizer + // using a new string fixed the error + std::string remain = s.substr(sign); + /* We do not want the offset_separator to wrap the offsets, we + * will never want to process more than: + * 2 char, 2 char, 2 char, frac_sec length. + * We *do* want the offset_separator to give us a partial for the + * last characters if there were not enough provided in the input string. */ + bool wrap_off = false; + bool ret_part = true; + boost::offset_separator osf(offsets, offsets+4, wrap_off, ret_part); + typedef boost::tokenizer<boost::offset_separator, + std::basic_string<char>::const_iterator, + std::basic_string<char> > tokenizer; + typedef boost::tokenizer<boost::offset_separator, + std::basic_string<char>::const_iterator, + std::basic_string<char> >::iterator tokenizer_iterator; + tokenizer tok(remain, osf); + for(tokenizer_iterator ti=tok.begin(); ti!=tok.end();++ti){ + switch(pos) { + case 0: + { + hours = boost::lexical_cast<int>(*ti); + break; + } + case 1: + { + min = boost::lexical_cast<short>(*ti); + break; + } + case 2: + { + sec = boost::lexical_cast<short>(*ti); + break; + } + case 3: + { + std::string char_digits(ti->substr(1)); // digits w/no decimal + int digits = static_cast<int>(char_digits.length()); + + //Works around a bug in MSVC 6 library that does not support + //operator>> thus meaning lexical_cast will fail to compile. +#if (defined(BOOST_MSVC) && (_MSC_VER <= 1200)) // 1200 == VC++ 6.0 + // _atoi64 is an MS specific function + if(digits >= precision) { + // drop excess digits + fs = _atoi64(char_digits.substr(0, precision).c_str()); + } + else if(digits == 0) { + fs = 0; // just in case _atoi64 doesn't like an empty string + } + else { + fs = _atoi64(char_digits.c_str()); + } +#else + if(digits >= precision) { + // drop excess digits + fs = boost::lexical_cast<boost::int64_t>(char_digits.substr(0, precision)); + } + else if(digits == 0) { + fs = 0; // lexical_cast doesn't like empty strings + } + else { + fs = boost::lexical_cast<boost::int64_t>(char_digits); + } +#endif + if(digits < precision){ + // trailing zeros get dropped from the string, + // "1:01:01.1" would yield .000001 instead of .100000 + // the power() compensates for the missing decimal places + fs *= power(10, precision - digits); + } + + break; + } + }; + pos++; + } + if(sign) { + return -time_duration(hours, min, sec, fs); + } + else { + return time_duration(hours, min, sec, fs); + } + } + + //! Parse time string of form YYYYMMDDThhmmss where T is delimeter between date and time + template<class time_type> + inline + time_type + parse_iso_time(const std::string& s, char sep) + { + typedef typename time_type::time_duration_type time_duration; + typedef typename time_type::date_type date_type; + + //split date/time on a unique delimiter char such as ' ' or 'T' + std::string date_string, tod_string; + split(s, sep, date_string, tod_string); + //call parse_date with first string + date_type d = parse_undelimited_date<date_type>(date_string); + //call parse_time_duration with remaining string + time_duration td = parse_undelimited_time_duration<time_duration>(tod_string); + //construct a time + return time_type(d, td); + } + + + +} }//namespace date_time + + + + +#endif diff --git a/ext/boost/date_time/time_resolution_traits.hpp b/ext/boost/date_time/time_resolution_traits.hpp new file mode 100644 index 0000000000..658f3d207c --- /dev/null +++ b/ext/boost/date_time/time_resolution_traits.hpp @@ -0,0 +1,144 @@ +#ifndef DATE_TIME_TIME_RESOLUTION_TRAITS_HPP +#define DATE_TIME_TIME_RESOLUTION_TRAITS_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-06 07:25:55 -0400 (Sat, 06 Jun 2009) $ + */ + + +#include <boost/cstdint.hpp> +#include <boost/date_time/time_defs.hpp> +#include <boost/date_time/int_adapter.hpp> +#include <boost/date_time/compiler_config.hpp> + +namespace boost { +namespace date_time { + + //! Simple function to calculate absolute value of a numeric type + template <typename T> + // JDG [7/6/02 made a template], + // moved here from time_duration.hpp 2003-Sept-4. + inline T absolute_value(T x) + { + return x < 0 ? -x : x; + } + + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_bi32_impl { + typedef boost::int32_t int_type; + typedef boost::int32_t impl_type; + static int_type as_number(impl_type i){ return i;} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return false;} + }; + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_adapted32_impl { + typedef boost::int32_t int_type; + typedef boost::date_time::int_adapter<boost::int32_t> impl_type; + static int_type as_number(impl_type i){ return i.as_number();} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return true;} + }; + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_bi64_impl { + typedef boost::int64_t int_type; + typedef boost::int64_t impl_type; + static int_type as_number(impl_type i){ return i;} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return false;} + }; + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_adapted64_impl { + typedef boost::int64_t int_type; + typedef boost::date_time::int_adapter<boost::int64_t> impl_type; + static int_type as_number(impl_type i){ return i.as_number();} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return true;} + }; + + template<typename frac_sec_type, + time_resolutions res, +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t resolution_adjust, +#else + typename frac_sec_type::int_type resolution_adjust, +#endif + unsigned short frac_digits, + typename v_type = boost::int32_t > + class time_resolution_traits { + public: + typedef typename frac_sec_type::int_type fractional_seconds_type; + typedef typename frac_sec_type::int_type tick_type; + typedef typename frac_sec_type::impl_type impl_type; + typedef v_type day_type; + typedef v_type hour_type; + typedef v_type min_type; + typedef v_type sec_type; + + // bring in function from frac_sec_type traits structs + static fractional_seconds_type as_number(impl_type i) + { + return frac_sec_type::as_number(i); + } + static bool is_adapted() + { + return frac_sec_type::is_adapted(); + } + + //Would like this to be frac_sec_type, but some compilers complain +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + BOOST_STATIC_CONSTANT(boost::int64_t, ticks_per_second = resolution_adjust); +#else + BOOST_STATIC_CONSTANT(fractional_seconds_type, ticks_per_second = resolution_adjust); +#endif + + static time_resolutions resolution() + { + return res; + } + static unsigned short num_fractional_digits() + { + return frac_digits; + } + static fractional_seconds_type res_adjust() + { + return resolution_adjust; + } + //! Any negative argument results in a negative tick_count + static tick_type to_tick_count(hour_type hours, + min_type minutes, + sec_type seconds, + fractional_seconds_type fs) + { + if(hours < 0 || minutes < 0 || seconds < 0 || fs < 0) + { + hours = absolute_value(hours); + minutes = absolute_value(minutes); + seconds = absolute_value(seconds); + fs = absolute_value(fs); + return (((((fractional_seconds_type(hours)*3600) + + (fractional_seconds_type(minutes)*60) + + seconds)*res_adjust()) + fs) * -1); + } + + return (((fractional_seconds_type(hours)*3600) + + (fractional_seconds_type(minutes)*60) + + seconds)*res_adjust()) + fs; + } + + }; + + typedef time_resolution_traits<time_resolution_traits_adapted32_impl, milli, 1000, 3 > milli_res; + typedef time_resolution_traits<time_resolution_traits_adapted64_impl, micro, 1000000, 6 > micro_res; + typedef time_resolution_traits<time_resolution_traits_adapted64_impl, nano, 1000000000, 9 > nano_res; + + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/time_system_counted.hpp b/ext/boost/date_time/time_system_counted.hpp new file mode 100644 index 0000000000..fa883907eb --- /dev/null +++ b/ext/boost/date_time/time_system_counted.hpp @@ -0,0 +1,254 @@ +#ifndef DATE_TIME_TIME_SYSTEM_COUNTED_HPP +#define DATE_TIME_TIME_SYSTEM_COUNTED_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + + +#include "boost/date_time/time_defs.hpp" +#include <string> + + +namespace boost { +namespace date_time { + + //! Time representation that uses a single integer count + template<class config> + struct counted_time_rep + { + typedef typename config::int_type int_type; + typedef typename config::date_type date_type; + typedef typename config::impl_type impl_type; + typedef typename date_type::duration_type date_duration_type; + typedef typename date_type::calendar_type calendar_type; + typedef typename date_type::ymd_type ymd_type; + typedef typename config::time_duration_type time_duration_type; + typedef typename config::resolution_traits resolution_traits; + + counted_time_rep(const date_type& d, const time_duration_type& time_of_day) + : time_count_(1) + { + if(d.is_infinity() || d.is_not_a_date() || time_of_day.is_special()) { + time_count_ = time_of_day.get_rep() + d.day_count(); + //std::cout << time_count_ << std::endl; + } + else { + time_count_ = (d.day_number() * frac_sec_per_day()) + time_of_day.ticks(); + } + } + explicit counted_time_rep(int_type count) : + time_count_(count) + {} + explicit counted_time_rep(impl_type count) : + time_count_(count) + {} + date_type date() const + { + if(time_count_.is_special()) { + return date_type(time_count_.as_special()); + } + else { + typename calendar_type::date_int_type dc = day_count(); + //std::cout << "time_rep here:" << dc << std::endl; + ymd_type ymd = calendar_type::from_day_number(dc); + return date_type(ymd); + } + } + //int_type day_count() const + unsigned long day_count() const + { + /* resolution_traits::as_number returns a boost::int64_t & + * frac_sec_per_day is also a boost::int64_t so, naturally, + * the division operation returns a boost::int64_t. + * The static_cast to an unsigned long is ok (results in no data loss) + * because frac_sec_per_day is either the number of + * microseconds per day, or the number of nanoseconds per day. + * Worst case scenario: resolution_traits::as_number returns the + * maximum value an int64_t can hold and frac_sec_per_day + * is microseconds per day (lowest possible value). + * The division operation will then return a value of 106751991 - + * easily fitting in an unsigned long. + */ + return static_cast<unsigned long>(resolution_traits::as_number(time_count_) / frac_sec_per_day()); + } + int_type time_count() const + { + return resolution_traits::as_number(time_count_); + } + int_type tod() const + { + return resolution_traits::as_number(time_count_) % frac_sec_per_day(); + } + static int_type frac_sec_per_day() + { + int_type seconds_per_day = 60*60*24; + int_type fractional_sec_per_sec(resolution_traits::res_adjust()); + return seconds_per_day*fractional_sec_per_sec; + } + bool is_pos_infinity()const + { + return impl_type::is_pos_inf(time_count_.as_number()); + } + bool is_neg_infinity()const + { + return impl_type::is_neg_inf(time_count_.as_number()); + } + bool is_not_a_date_time()const + { + return impl_type::is_not_a_number(time_count_.as_number()); + } + bool is_special()const + { + return time_count_.is_special(); + } + impl_type get_rep()const + { + return time_count_; + } + private: + impl_type time_count_; + }; + + //! An unadjusted time system implementation. + template<class time_rep> + class counted_time_system + { + public: + typedef time_rep time_rep_type; + typedef typename time_rep_type::impl_type impl_type; + typedef typename time_rep_type::time_duration_type time_duration_type; + typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type; + typedef typename time_rep_type::date_type date_type; + typedef typename time_rep_type::date_duration_type date_duration_type; + + + template<class T> static void unused_var(const T&) {} + + static time_rep_type get_time_rep(const date_type& day, + const time_duration_type& tod, + date_time::dst_flags dst=not_dst) + { + unused_var(dst); + return time_rep_type(day, tod); + } + + static time_rep_type get_time_rep(special_values sv) + { + switch (sv) { + case not_a_date_time: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + case pos_infin: + return time_rep_type(date_type(pos_infin), + time_duration_type(pos_infin)); + case neg_infin: + return time_rep_type(date_type(neg_infin), + time_duration_type(neg_infin)); + case max_date_time: { + time_duration_type td = time_duration_type(24,0,0,0) - time_duration_type(0,0,0,1); + return time_rep_type(date_type(max_date_time), td); + } + case min_date_time: + return time_rep_type(date_type(min_date_time), time_duration_type(0,0,0,0)); + + default: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + + } + + } + + static date_type get_date(const time_rep_type& val) + { + return val.date(); + } + static time_duration_type get_time_of_day(const time_rep_type& val) + { + if(val.is_special()) { + return time_duration_type(val.get_rep().as_special()); + } + else{ + return time_duration_type(0,0,0,val.tod()); + } + } + static std::string zone_name(const time_rep_type&) + { + return ""; + } + static bool is_equal(const time_rep_type& lhs, const time_rep_type& rhs) + { + return (lhs.time_count() == rhs.time_count()); + } + static bool is_less(const time_rep_type& lhs, const time_rep_type& rhs) + { + return (lhs.time_count() < rhs.time_count()); + } + static time_rep_type add_days(const time_rep_type& base, + const date_duration_type& dd) + { + if(base.is_special() || dd.is_special()) { + return(time_rep_type(base.get_rep() + dd.get_rep())); + } + else { + return time_rep_type(base.time_count() + (dd.days() * time_rep_type::frac_sec_per_day())); + } + } + static time_rep_type subtract_days(const time_rep_type& base, + const date_duration_type& dd) + { + if(base.is_special() || dd.is_special()) { + return(time_rep_type(base.get_rep() - dd.get_rep())); + } + else{ + return time_rep_type(base.time_count() - (dd.days() * time_rep_type::frac_sec_per_day())); + } + } + static time_rep_type subtract_time_duration(const time_rep_type& base, + const time_duration_type& td) + { + if(base.is_special() || td.is_special()) { + return(time_rep_type(base.get_rep() - td.get_rep())); + } + else { + return time_rep_type(base.time_count() - td.ticks()); + } + } + static time_rep_type add_time_duration(const time_rep_type& base, + time_duration_type td) + { + if(base.is_special() || td.is_special()) { + return(time_rep_type(base.get_rep() + td.get_rep())); + } + else { + return time_rep_type(base.time_count() + td.ticks()); + } + } + static time_duration_type subtract_times(const time_rep_type& lhs, + const time_rep_type& rhs) + { + if(lhs.is_special() || rhs.is_special()) { + return(time_duration_type( + impl_type::to_special((lhs.get_rep() - rhs.get_rep()).as_number()))); + } + else { + fractional_seconds_type fs = lhs.time_count() - rhs.time_count(); + return time_duration_type(0,0,0,fs); + } + } + + }; + + +} } //namespace date_time + + + +#endif + diff --git a/ext/boost/date_time/time_system_split.hpp b/ext/boost/date_time/time_system_split.hpp new file mode 100644 index 0000000000..08ea1ec2d1 --- /dev/null +++ b/ext/boost/date_time/time_system_split.hpp @@ -0,0 +1,207 @@ +#ifndef DATE_TIME_TIME_SYSTEM_SPLIT_HPP +#define DATE_TIME_TIME_SYSTEM_SPLIT_HPP + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-13 15:10:23 -0500 (Thu, 13 Nov 2008) $ + */ + + +#include <string> +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/special_defs.hpp" + +namespace boost { +namespace date_time { + + //! An unadjusted time system implementation. +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) + template<typename config, boost::int32_t ticks_per_second> +#else + template<typename config> +#endif + class split_timedate_system + { + public: + typedef typename config::time_rep_type time_rep_type; + typedef typename config::date_type date_type; + typedef typename config::time_duration_type time_duration_type; + typedef typename config::date_duration_type date_duration_type; + typedef typename config::int_type int_type; + typedef typename config::resolution_traits resolution_traits; + + //86400 is number of seconds in a day... +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) + typedef date_time::wrapping_int<int_type, INT64_C(86400) * ticks_per_second > wrap_int_type; +#else + private: + BOOST_STATIC_CONSTANT(int_type, ticks_per_day = INT64_C(86400) * config::tick_per_second); + public: +# if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0X581) ) + typedef date_time::wrapping_int< split_timedate_system::int_type, split_timedate_system::ticks_per_day> wrap_int_type; +# else + typedef date_time::wrapping_int<int_type, ticks_per_day> wrap_int_type; +#endif +#endif + + static time_rep_type get_time_rep(special_values sv) + { + switch (sv) { + case not_a_date_time: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + case pos_infin: + return time_rep_type(date_type(pos_infin), + time_duration_type(pos_infin)); + case neg_infin: + return time_rep_type(date_type(neg_infin), + time_duration_type(neg_infin)); + case max_date_time: { + time_duration_type td = time_duration_type(24,0,0,0) - time_duration_type(0,0,0,1); + return time_rep_type(date_type(max_date_time), td); + } + case min_date_time: + return time_rep_type(date_type(min_date_time), time_duration_type(0,0,0,0)); + + default: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + + } + + } + + static time_rep_type get_time_rep(const date_type& day, + const time_duration_type& tod, + date_time::dst_flags /* dst */ = not_dst) + { + if(day.is_special() || tod.is_special()) { + if(day.is_not_a_date() || tod.is_not_a_date_time()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else if(day.is_pos_infinity()) { + if(tod.is_neg_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(day, time_duration_type(pos_infin)); + } + } + else if(day.is_neg_infinity()) { + if(tod.is_pos_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(day, time_duration_type(neg_infin)); + } + } + else if(tod.is_pos_infinity()) { + if(day.is_neg_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(date_type(pos_infin), tod); + } + } + else if(tod.is_neg_infinity()) { + if(day.is_pos_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(date_type(neg_infin), tod); + } + } + } + return time_rep_type(day, tod); + } + static date_type get_date(const time_rep_type& val) + { + return date_type(val.day); + } + static time_duration_type get_time_of_day(const time_rep_type& val) + { + return time_duration_type(val.time_of_day); + } + static std::string zone_name(const time_rep_type&) + { + return std::string(); + } + static bool is_equal(const time_rep_type& lhs, const time_rep_type& rhs) + { + return ((lhs.day == rhs.day) && (lhs.time_of_day == rhs.time_of_day)); + } + static bool is_less(const time_rep_type& lhs, const time_rep_type& rhs) + { + if (lhs.day < rhs.day) return true; + if (lhs.day > rhs.day) return false; + return (lhs.time_of_day < rhs.time_of_day); + } + static time_rep_type add_days(const time_rep_type& base, + const date_duration_type& dd) + { + return time_rep_type(base.day+dd, base.time_of_day); + } + static time_rep_type subtract_days(const time_rep_type& base, + const date_duration_type& dd) + { + return split_timedate_system::get_time_rep(base.day-dd, base.time_of_day); + } + static time_rep_type subtract_time_duration(const time_rep_type& base, + const time_duration_type& td) + { + if(base.day.is_special() || td.is_special()) + { + return split_timedate_system::get_time_rep(base.day, -td); + } + if (td.is_negative()) { + time_duration_type td1 = td.invert_sign(); + return add_time_duration(base,td1); + } + + wrap_int_type day_offset(base.time_of_day.ticks()); + date_duration_type day_overflow(static_cast<typename date_duration_type::duration_rep_type>(day_offset.subtract(td.ticks()))); + + return time_rep_type(base.day-day_overflow, + time_duration_type(0,0,0,day_offset.as_int())); + } + static time_rep_type add_time_duration(const time_rep_type& base, + time_duration_type td) + { + if(base.day.is_special() || td.is_special()) { + return split_timedate_system::get_time_rep(base.day, td); + } + if (td.is_negative()) { + time_duration_type td1 = td.invert_sign(); + return subtract_time_duration(base,td1); + } + + wrap_int_type day_offset(base.time_of_day.ticks()); + date_duration_type day_overflow(static_cast< typename date_duration_type::duration_rep_type >(day_offset.add(td.ticks()))); + + return time_rep_type(base.day+day_overflow, + time_duration_type(0,0,0,day_offset.as_int())); + } + static time_duration_type subtract_times(const time_rep_type& lhs, + const time_rep_type& rhs) + { + date_duration_type dd = lhs.day - rhs.day; + time_duration_type td(dd.days()*24,0,0); //days * 24 hours + time_duration_type td2 = lhs.time_of_day - rhs.time_of_day; + return td+td2; + // return time_rep_type(base.day-dd, base.time_of_day); + } + + }; + +} } //namespace date_time + + +#endif diff --git a/ext/boost/date_time/time_zone_base.hpp b/ext/boost/date_time/time_zone_base.hpp new file mode 100644 index 0000000000..0d3cb903e6 --- /dev/null +++ b/ext/boost/date_time/time_zone_base.hpp @@ -0,0 +1,99 @@ +#ifndef _DATE_TIME_TIME_ZONE_BASE__ +#define _DATE_TIME_TIME_ZONE_BASE__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include <string> +#include <sstream> + +namespace boost { +namespace date_time { + + + + //! Interface class for dynamic time zones. + /*! This class represents the base interface for all timezone + * representations. Subclasses may provide different systems + * for identifying a particular zone. For example some may + * provide a geographical based zone construction while others + * may specify the offset from GMT. Another possible implementation + * would be to convert from POSIX timezone strings. Regardless of + * the construction technique, this is the interface that these + * time zone types must provide. + * + * Note that this class is intended to be used as a shared + * resource (hence the derivation from boost::counted_base. + */ + template<typename time_type, typename CharT> + class time_zone_base { + public: + typedef CharT char_type; + typedef std::basic_string<CharT> string_type; + typedef std::basic_ostringstream<CharT> stringstream_type; + typedef typename time_type::date_type::year_type year_type; + typedef typename time_type::time_duration_type time_duration_type; + + time_zone_base() {}; + virtual ~time_zone_base() {}; + //!String for the timezone when in daylight savings (eg: EDT) + virtual string_type dst_zone_abbrev() const=0; + //!String for the zone when not in daylight savings (eg: EST) + virtual string_type std_zone_abbrev() const=0; + //!String for the timezone when in daylight savings (eg: Eastern Daylight Time) + virtual string_type dst_zone_name() const=0; + //!String for the zone when not in daylight savings (eg: Eastern Standard Time) + virtual string_type std_zone_name() const=0; + //! True if zone uses daylight savings adjustments otherwise false + virtual bool has_dst() const=0; + //! Local time that DST starts -- undefined if has_dst is false + virtual time_type dst_local_start_time(year_type y) const=0; + //! Local time that DST ends -- undefined if has_dst is false + virtual time_type dst_local_end_time(year_type y) const=0; + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset() const=0; + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset() const=0; + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const =0; + + private: + + }; + + + //! Structure which holds the time offsets associated with daylight savings time + /*! + *@param time_duration_type A type used to represent the offset + */ + template<class time_duration_type> + class dst_adjustment_offsets + { + public: + dst_adjustment_offsets(const time_duration_type& dst_adjust, + const time_duration_type& dst_start_offset, + const time_duration_type& dst_end_offset) : + dst_adjust_(dst_adjust), + dst_start_offset_(dst_start_offset), + dst_end_offset_(dst_end_offset) + {} + + //! Amount DST adjusts the clock eg: plus one hour + time_duration_type dst_adjust_; + //! Time past midnight on start transition day that dst starts + time_duration_type dst_start_offset_; + //! Time past midnight on end transition day that dst ends + time_duration_type dst_end_offset_; + }; + + +} } //namespace date_time + + + +#endif diff --git a/ext/boost/date_time/time_zone_names.hpp b/ext/boost/date_time/time_zone_names.hpp new file mode 100644 index 0000000000..05260c7162 --- /dev/null +++ b/ext/boost/date_time/time_zone_names.hpp @@ -0,0 +1,98 @@ +#ifndef DATE_TIME_TIME_ZONE_NAMES_HPP__ +#define DATE_TIME_TIME_ZONE_NAMES_HPP__ + +/* Copyright (c) 2002-2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include <string> + +namespace boost { +namespace date_time { + + template<class CharT> + struct default_zone_names { + public: + typedef CharT char_type; + static const char_type standard_name[9]; + static const char_type standard_abbrev[11]; + static const char_type non_dst_identifier[7]; + }; + template <class CharT> + const typename default_zone_names<CharT>::char_type + default_zone_names<CharT>::standard_name[9] = + {'s','t','d','_','n','a','m','e'}; + + template <class CharT> + const typename default_zone_names<CharT>::char_type + default_zone_names<CharT>::standard_abbrev[11] = + {'s','t','d','_','a','b','b','r','e','v'}; + + template <class CharT> + const typename default_zone_names<CharT>::char_type + default_zone_names<CharT>::non_dst_identifier[7] = + {'n','o','-','d','s','t'}; + + //! Base type that holds various string names for timezone output. + /*! Class that holds various types of strings used for timezones. + * For example, for the western United States there is the full + * name: Pacific Standard Time and the abbreviated name: PST. + * During daylight savings there are additional names: + * Pacific Daylight Time and PDT. + *@parm CharT Allows class to support different character types + */ + template<class CharT> + class time_zone_names_base + { + public: + typedef std::basic_string<CharT> string_type; + time_zone_names_base() : + std_zone_name_(default_zone_names<CharT>::standard_name), + std_zone_abbrev_(default_zone_names<CharT>::standard_abbrev), + dst_zone_name_(default_zone_names<CharT>::non_dst_identifier), + dst_zone_abbrev_(default_zone_names<CharT>::non_dst_identifier) + {} + time_zone_names_base(const string_type& std_zone_name_str, + const string_type& std_zone_abbrev_str, + const string_type& dst_zone_name_str, + const string_type& dst_zone_abbrev_str) : + std_zone_name_(std_zone_name_str), + std_zone_abbrev_(std_zone_abbrev_str), + dst_zone_name_(dst_zone_name_str), + dst_zone_abbrev_(dst_zone_abbrev_str) + {} + string_type dst_zone_abbrev() const + { + return dst_zone_abbrev_; + } + string_type std_zone_abbrev() const + { + return std_zone_abbrev_; + } + string_type dst_zone_name() const + { + return dst_zone_name_; + } + string_type std_zone_name() const + { + return std_zone_name_; + } + private: + string_type std_zone_name_; + string_type std_zone_abbrev_; + string_type dst_zone_name_; + string_type dst_zone_abbrev_; + + }; + + //! Specialization of timezone names for standard char. + //typedef time_zone_names_base<char> time_zone_names; + +} } //namespace + + +#endif diff --git a/ext/boost/date_time/tz_db_base.hpp b/ext/boost/date_time/tz_db_base.hpp new file mode 100644 index 0000000000..2440115460 --- /dev/null +++ b/ext/boost/date_time/tz_db_base.hpp @@ -0,0 +1,378 @@ +#ifndef DATE_TIME_TZ_DB_BASE_HPP__ +#define DATE_TIME_TZ_DB_BASE_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include <map> +#include <vector> +#include <string> +#include <sstream> +#include <fstream> +#include <stdexcept> +#include <boost/tokenizer.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/throw_exception.hpp> +#include <boost/date_time/compiler_config.hpp> +#include <boost/date_time/time_zone_names.hpp> +#include <boost/date_time/time_zone_base.hpp> +#include <boost/date_time/time_parsing.hpp> + +namespace boost { + namespace date_time { + + //! Exception thrown when tz database cannot locate requested data file + class data_not_accessible : public std::logic_error + { + public: + data_not_accessible() : + std::logic_error(std::string("Unable to locate or access the required datafile.")) + {} + data_not_accessible(const std::string& filespec) : + std::logic_error(std::string("Unable to locate or access the required datafile. Filespec: " + filespec)) + {} + }; + + //! Exception thrown when tz database locates incorrect field structure in data file + class bad_field_count : public std::out_of_range + { + public: + bad_field_count(const std::string& s) : + std::out_of_range(s) + {} + }; + + //! Creates a database of time_zones from csv datafile + /*! The csv file containing the zone_specs used by the + * tz_db_base is intended to be customized by the + * library user. When customizing this file (or creating your own) the + * file must follow a specific format. + * + * This first line is expected to contain column headings and is therefore + * not processed by the tz_db_base. + * + * Each record (line) must have eleven fields. Some of those fields can + * be empty. Every field (even empty ones) must be enclosed in + * double-quotes. + * Ex: + * @code + * "America/Phoenix" <- string enclosed in quotes + * "" <- empty field + * @endcode + * + * Some fields represent a length of time. The format of these fields + * must be: + * @code + * "{+|-}hh:mm[:ss]" <- length-of-time format + * @endcode + * Where the plus or minus is mandatory and the seconds are optional. + * + * Since some time zones do not use daylight savings it is not always + * necessary for every field in a zone_spec to contain a value. All + * zone_specs must have at least ID and GMT offset. Zones that use + * daylight savings must have all fields filled except: + * STD ABBR, STD NAME, DST NAME. You should take note + * that DST ABBR is mandatory for zones that use daylight savings + * (see field descriptions for further details). + * + * ******* Fields and their description/details ********* + * + * ID: + * Contains the identifying string for the zone_spec. Any string will + * do as long as it's unique. No two ID's can be the same. + * + * STD ABBR: + * STD NAME: + * DST ABBR: + * DST NAME: + * These four are all the names and abbreviations used by the time + * zone being described. While any string will do in these fields, + * care should be taken. These fields hold the strings that will be + * used in the output of many of the local_time classes. + * Ex: + * @code + * time_zone nyc = tz_db.time_zone_from_region("America/New_York"); + * local_time ny_time(date(2004, Aug, 30), IS_DST, nyc); + * cout << ny_time.to_long_string() << endl; + * // 2004-Aug-30 00:00:00 Eastern Daylight Time + * cout << ny_time.to_short_string() << endl; + * // 2004-Aug-30 00:00:00 EDT + * @endcode + * + * NOTE: The exact format/function names may vary - see local_time + * documentation for further details. + * + * GMT offset: + * This is the number of hours added to utc to get the local time + * before any daylight savings adjustments are made. Some examples + * are: America/New_York offset -5 hours, & Africa/Cairo offset +2 hours. + * The format must follow the length-of-time format described above. + * + * DST adjustment: + * The amount of time added to gmt_offset when daylight savings is in + * effect. The format must follow the length-of-time format described + * above. + * + * DST Start Date rule: + * This is a specially formatted string that describes the day of year + * in which the transition take place. It holds three fields of it's own, + * separated by semicolons. + * The first field indicates the "nth" weekday of the month. The possible + * values are: 1 (first), 2 (second), 3 (third), 4 (fourth), 5 (fifth), + * and -1 (last). + * The second field indicates the day-of-week from 0-6 (Sun=0). + * The third field indicates the month from 1-12 (Jan=1). + * + * Examples are: "-1;5;9"="Last Friday of September", + * "2;1;3"="Second Monday of March" + * + * Start time: + * Start time is the number of hours past midnight, on the day of the + * start transition, the transition takes place. More simply put, the + * time of day the transition is made (in 24 hours format). The format + * must follow the length-of-time format described above with the + * exception that it must always be positive. + * + * DST End date rule: + * See DST Start date rule. The difference here is this is the day + * daylight savings ends (transition to STD). + * + * End time: + * Same as Start time. + */ + template<class time_zone_type, class rule_type> + class tz_db_base { + public: + /* Having CharT as a template parameter created problems + * with posix_time::duration_from_string. Templatizing + * duration_from_string was not possible at this time, however, + * it should be possible in the future (when poor compilers get + * fixed or stop being used). + * Since this class was designed to use CharT as a parameter it + * is simply typedef'd here to ease converting in back to a + * parameter the future */ + typedef char char_type; + + typedef typename time_zone_type::base_type time_zone_base_type; + typedef typename time_zone_type::time_duration_type time_duration_type; + typedef time_zone_names_base<char_type> time_zone_names; + typedef boost::date_time::dst_adjustment_offsets<time_duration_type> dst_adjustment_offsets; + typedef std::basic_string<char_type> string_type; + + //! Constructs an empty database + tz_db_base() {} + + //! Process csv data file, may throw exceptions + /*! May throw data_not_accessible, or bad_field_count exceptions */ + void load_from_file(const std::string& pathspec) + { + string_type in_str; + std::string buff; + + std::ifstream ifs(pathspec.c_str()); + if(!ifs){ + boost::throw_exception(data_not_accessible(pathspec)); + } + std::getline(ifs, buff); // first line is column headings + + while( std::getline(ifs, buff)) { + parse_string(buff); + } + } + + //! returns true if record successfully added to map + /*! Takes a region name in the form of "America/Phoenix", and a + * time_zone object for that region. The id string must be a unique + * name that does not already exist in the database. */ + bool add_record(const string_type& region, + boost::shared_ptr<time_zone_base_type> tz) + { + typename map_type::value_type p(region, tz); + return (m_zone_map.insert(p)).second; + } + + //! Returns a time_zone object built from the specs for the given region + /*! Returns a time_zone object built from the specs for the given + * region. If region does not exist a local_time::record_not_found + * exception will be thrown */ + boost::shared_ptr<time_zone_base_type> + time_zone_from_region(const string_type& region) const + { + // get the record + typename map_type::const_iterator record = m_zone_map.find(region); + if(record == m_zone_map.end()){ + return boost::shared_ptr<time_zone_base_type>(); //null pointer + } + return record->second; + } + + //! Returns a vector of strings holding the time zone regions in the database + std::vector<std::string> region_list() const + { + typedef std::vector<std::string> vector_type; + vector_type regions; + typename map_type::const_iterator itr = m_zone_map.begin(); + while(itr != m_zone_map.end()) { + regions.push_back(itr->first); + ++itr; + } + return regions; + } + + private: + typedef std::map<string_type, boost::shared_ptr<time_zone_base_type> > map_type; + map_type m_zone_map; + + // start and end rule are of the same type + typedef typename rule_type::start_rule::week_num week_num; + + /* TODO: mechanisms need to be put in place to handle different + * types of rule specs. parse_rules() only handles nth_kday + * rule types. */ + + //! parses rule specs for transition day rules + rule_type* parse_rules(const string_type& sr, const string_type& er) const + { + using namespace gregorian; + // start and end rule are of the same type, + // both are included here for readability + typedef typename rule_type::start_rule start_rule; + typedef typename rule_type::end_rule end_rule; + + // these are: [start|end] nth, day, month + int s_nth = 0, s_d = 0, s_m = 0; + int e_nth = 0, e_d = 0, e_m = 0; + split_rule_spec(s_nth, s_d, s_m, sr); + split_rule_spec(e_nth, e_d, e_m, er); + + typename start_rule::week_num s_wn, e_wn; + s_wn = get_week_num(s_nth); + e_wn = get_week_num(e_nth); + + + return new rule_type(start_rule(s_wn, s_d, s_m), + end_rule(e_wn, e_d, e_m)); + } + //! helper function for parse_rules() + week_num get_week_num(int nth) const + { + typedef typename rule_type::start_rule start_rule; + switch(nth){ + case 1: + return start_rule::first; + case 2: + return start_rule::second; + case 3: + return start_rule::third; + case 4: + return start_rule::fourth; + case 5: + case -1: + return start_rule::fifth; + default: + // shouldn't get here - add error handling later + break; + } + return start_rule::fifth; // silence warnings + } + + //! splits the [start|end]_date_rule string into 3 ints + void split_rule_spec(int& nth, int& d, int& m, string_type rule) const + { + typedef boost::char_separator<char_type, std::char_traits<char_type> > char_separator_type; + typedef boost::tokenizer<char_separator_type, + std::basic_string<char_type>::const_iterator, + std::basic_string<char_type> > tokenizer; + typedef boost::tokenizer<char_separator_type, + std::basic_string<char_type>::const_iterator, + std::basic_string<char_type> >::iterator tokenizer_iterator; + + const char_type sep_char[] = { ';', '\0'}; + char_separator_type sep(sep_char); + tokenizer tokens(rule, sep); // 3 fields + + tokenizer_iterator tok_iter = tokens.begin(); + nth = std::atoi(tok_iter->c_str()); ++tok_iter; + d = std::atoi(tok_iter->c_str()); ++tok_iter; + m = std::atoi(tok_iter->c_str()); + } + + + //! Take a line from the csv, turn it into a time_zone_type. + /*! Take a line from the csv, turn it into a time_zone_type, + * and add it to the map. Zone_specs in csv file are expected to + * have eleven fields that describe the time zone. Returns true if + * zone_spec successfully added to database */ + bool parse_string(string_type& s) + { + std::vector<string_type> result; + typedef boost::token_iterator_generator<boost::escaped_list_separator<char_type>, string_type::const_iterator, string_type >::type token_iter_type; + + token_iter_type i = boost::make_token_iterator<string_type>(s.begin(), s.end(),boost::escaped_list_separator<char_type>()); + + token_iter_type end; + while (i != end) { + result.push_back(*i); + i++; + } + + enum db_fields { ID, STDABBR, STDNAME, DSTABBR, DSTNAME, GMTOFFSET, + DSTADJUST, START_DATE_RULE, START_TIME, END_DATE_RULE, + END_TIME, FIELD_COUNT }; + + //take a shot at fixing gcc 4.x error + const unsigned int expected_fields = static_cast<unsigned int>(FIELD_COUNT); + if (result.size() != expected_fields) { + std::ostringstream msg; + msg << "Expecting " << FIELD_COUNT << " fields, got " + << result.size() << " fields in line: " << s; + boost::throw_exception(bad_field_count(msg.str())); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return false); // should never reach + } + + // initializations + bool has_dst = true; + if(result[DSTABBR] == std::string()){ + has_dst = false; + } + + + // start building components of a time_zone + time_zone_names names(result[STDNAME], result[STDABBR], + result[DSTNAME], result[DSTABBR]); + + time_duration_type utc_offset = + str_from_delimited_time_duration<time_duration_type,char_type>(result[GMTOFFSET]); + + dst_adjustment_offsets adjust(time_duration_type(0,0,0), + time_duration_type(0,0,0), + time_duration_type(0,0,0)); + + boost::shared_ptr<rule_type> rules; + + if(has_dst){ + adjust = dst_adjustment_offsets( + str_from_delimited_time_duration<time_duration_type,char_type>(result[DSTADJUST]), + str_from_delimited_time_duration<time_duration_type,char_type>(result[START_TIME]), + str_from_delimited_time_duration<time_duration_type,char_type>(result[END_TIME]) + ); + + rules = + boost::shared_ptr<rule_type>(parse_rules(result[START_DATE_RULE], + result[END_DATE_RULE])); + } + string_type id(result[ID]); + boost::shared_ptr<time_zone_base_type> zone(new time_zone_type(names, utc_offset, adjust, rules)); + return (add_record(id, zone)); + + } + + }; + +} } // namespace + +#endif // DATE_TIME_TZ_DB_BASE_HPP__ diff --git a/ext/boost/date_time/wrapping_int.hpp b/ext/boost/date_time/wrapping_int.hpp new file mode 100644 index 0000000000..969b078ac1 --- /dev/null +++ b/ext/boost/date_time/wrapping_int.hpp @@ -0,0 +1,169 @@ +#ifndef _DATE_TIME_WRAPPING_INT_HPP__ +#define _DATE_TIME_WRAPPING_INT_HPP__ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + + +namespace boost { +namespace date_time { + +//! A wrapping integer used to support time durations (WARNING: only instantiate with a signed type) +/*! In composite date and time types this type is used to + * wrap at the day boundary. + * Ex: + * A wrapping_int<short, 10> will roll over after nine, and + * roll under below zero. This gives a range of [0,9] + * + * NOTE: it is strongly recommended that wrapping_int2 be used + * instead of wrapping_int as wrapping_int is to be depricated + * at some point soon. + * + * Also Note that warnings will occur if instantiated with an + * unsigned type. Only a signed type should be used! + */ +template<typename int_type_, int_type_ wrap_val> +class wrapping_int { +public: + typedef int_type_ int_type; + //typedef overflow_type_ overflow_type; + static int_type wrap_value() {return wrap_val;} + //!Add, return true if wrapped + wrapping_int(int_type v) : value_(v) {}; + //! Explicit converion method + int_type as_int() const {return value_;} + operator int_type() const {return value_;} + //!Add, return number of wraps performed + /*! The sign of the returned value will indicate which direction the + * wraps went. Ex: add a negative number and wrapping under could occur, + * this would be indicated by a negative return value. If wrapping over + * took place, a positive value would be returned */ + template< typename IntT > + IntT add(IntT v) + { + int_type remainder = static_cast<int_type>(v % (wrap_val)); + IntT overflow = static_cast<IntT>(v / (wrap_val)); + value_ = static_cast<int_type>(value_ + remainder); + return calculate_wrap(overflow); + } + //! Subtract will return '+d' if wrapping under took place ('d' is the number of wraps) + /*! The sign of the returned value will indicate which direction the + * wraps went (positive indicates wrap under, negative indicates wrap over). + * Ex: subtract a negative number and wrapping over could + * occur, this would be indicated by a negative return value. If + * wrapping under took place, a positive value would be returned. */ + template< typename IntT > + IntT subtract(IntT v) + { + int_type remainder = static_cast<int_type>(v % (wrap_val)); + IntT underflow = static_cast<IntT>(-(v / (wrap_val))); + value_ = static_cast<int_type>(value_ - remainder); + return calculate_wrap(underflow) * -1; + } +private: + int_type value_; + + template< typename IntT > + IntT calculate_wrap(IntT wrap) + { + if ((value_) >= wrap_val) + { + ++wrap; + value_ -= (wrap_val); + } + else if(value_ < 0) + { + --wrap; + value_ += (wrap_val); + } + return wrap; + } + +}; + + +//! A wrapping integer used to wrap around at the top (WARNING: only instantiate with a signed type) +/*! Bad name, quick impl to fix a bug -- fix later!! + * This allows the wrap to restart at a value other than 0. + */ +template<typename int_type_, int_type_ wrap_min, int_type_ wrap_max> +class wrapping_int2 { +public: + typedef int_type_ int_type; + static int_type wrap_value() {return wrap_max;} + static int_type min_value() {return wrap_min;} + /*! If initializing value is out of range of [wrap_min, wrap_max], + * value will be initialized to closest of min or max */ + wrapping_int2(int_type v) : value_(v) { + if(value_ < wrap_min) + { + value_ = wrap_min; + } + if(value_ > wrap_max) + { + value_ = wrap_max; + } + } + //! Explicit converion method + int_type as_int() const {return value_;} + operator int_type() const {return value_;} + //!Add, return number of wraps performed + /*! The sign of the returned value will indicate which direction the + * wraps went. Ex: add a negative number and wrapping under could occur, + * this would be indicated by a negative return value. If wrapping over + * took place, a positive value would be returned */ + template< typename IntT > + IntT add(IntT v) + { + int_type remainder = static_cast<int_type>(v % (wrap_max - wrap_min + 1)); + IntT overflow = static_cast<IntT>(v / (wrap_max - wrap_min + 1)); + value_ = static_cast<int_type>(value_ + remainder); + return calculate_wrap(overflow); + } + //! Subtract will return '-d' if wrapping under took place ('d' is the number of wraps) + /*! The sign of the returned value will indicate which direction the + * wraps went. Ex: subtract a negative number and wrapping over could + * occur, this would be indicated by a positive return value. If + * wrapping under took place, a negative value would be returned */ + template< typename IntT > + IntT subtract(IntT v) + { + int_type remainder = static_cast<int_type>(v % (wrap_max - wrap_min + 1)); + IntT underflow = static_cast<IntT>(-(v / (wrap_max - wrap_min + 1))); + value_ = static_cast<int_type>(value_ - remainder); + return calculate_wrap(underflow); + } + +private: + int_type value_; + + template< typename IntT > + IntT calculate_wrap(IntT wrap) + { + if ((value_) > wrap_max) + { + ++wrap; + value_ -= (wrap_max - wrap_min + 1); + } + else if((value_) < wrap_min) + { + --wrap; + value_ += (wrap_max - wrap_min + 1); + } + return wrap; + } +}; + + + +} } //namespace date_time + + + +#endif + diff --git a/ext/boost/date_time/year_month_day.hpp b/ext/boost/date_time/year_month_day.hpp new file mode 100644 index 0000000000..802ce42eb9 --- /dev/null +++ b/ext/boost/date_time/year_month_day.hpp @@ -0,0 +1,45 @@ +#ifndef YearMonthDayBase_HPP__ +#define YearMonthDayBase_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +namespace boost { +namespace date_time { + + //! Allow rapid creation of ymd triples of different types + template<typename YearType, typename MonthType, typename DayType> + struct year_month_day_base { + year_month_day_base(YearType year, + MonthType month, + DayType day); + YearType year; + MonthType month; + DayType day; + typedef YearType year_type; + typedef MonthType month_type; + typedef DayType day_type; + }; + + + //! A basic constructor + template<typename YearType, typename MonthType, typename DayType> + inline + year_month_day_base<YearType,MonthType,DayType>::year_month_day_base(YearType y, + MonthType m, + DayType d) : + year(y), + month(m), + day(d) + {} + +} }//namespace date_time + + +#endif + diff --git a/ext/boost/functional/detail/container_fwd.hpp b/ext/boost/functional/detail/container_fwd.hpp new file mode 100644 index 0000000000..9a69d155b2 --- /dev/null +++ b/ext/boost/functional/detail/container_fwd.hpp @@ -0,0 +1,19 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Forwarding header for container_fwd.hpp's new location. +// This header is deprecated, I'll be adding a warning in a future release, +// then converting it to an error and finally removing this header completely. + +#if !defined(BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP) +#define BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/detail/container_fwd.hpp> + +#endif diff --git a/ext/boost/functional/hash.hpp b/ext/boost/functional/hash.hpp new file mode 100644 index 0000000000..44983f19b2 --- /dev/null +++ b/ext/boost/functional/hash.hpp @@ -0,0 +1,7 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +#include <boost/functional/hash/hash.hpp> + diff --git a/ext/boost/functional/hash/detail/float_functions.hpp b/ext/boost/functional/hash/detail/float_functions.hpp new file mode 100644 index 0000000000..01cac09722 --- /dev/null +++ b/ext/boost/functional/hash/detail/float_functions.hpp @@ -0,0 +1,246 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP) +#define BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP + +#include <boost/config.hpp> +#include <boost/config/no_tr1/cmath.hpp> + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// The C++ standard requires that the C float functions are overloarded +// for float, double and long double in the std namespace, but some of the older +// library implementations don't support this. On some that don't, the C99 +// float functions (frexpf, frexpl, etc.) are available. +// +// The following tries to automatically detect which are available. + +namespace boost { + namespace hash_detail { + + // Returned by dummy versions of the float functions. + + struct not_found { + // Implicitly convertible to float and long double in order to avoid + // a compile error when the dummy float functions are used. + + inline operator float() const { return 0; } + inline operator long double() const { return 0; } + }; + + // A type for detecting the return type of functions. + + template <typename T> struct is; + template <> struct is<float> { char x[10]; }; + template <> struct is<double> { char x[20]; }; + template <> struct is<long double> { char x[30]; }; + template <> struct is<boost::hash_detail::not_found> { char x[40]; }; + + // Used to convert the return type of a function to a type for sizeof. + + template <typename T> is<T> float_type(T); + + // call_ldexp + // + // This will get specialized for float and long double + + template <typename Float> struct call_ldexp + { + typedef double float_type; + + inline double operator()(double a, int b) const + { + using namespace std; + return ldexp(a, b); + } + }; + + // call_frexp + // + // This will get specialized for float and long double + + template <typename Float> struct call_frexp + { + typedef double float_type; + + inline double operator()(double a, int* b) const + { + using namespace std; + return frexp(a, b); + } + }; + } +} + +// A namespace for dummy functions to detect when the actual function we want +// isn't available. ldexpl, ldexpf etc. might be added tby the macros below. +// +// AFAICT these have to be outside of the boost namespace, as if they're in +// the boost namespace they'll always be preferable to any other function +// (since the arguments are built in types, ADL can't be used). + +namespace BOOST_HASH_DETECT_FLOAT_FUNCTIONS { + template <class Float> boost::hash_detail::not_found ldexp(Float, int); + template <class Float> boost::hash_detail::not_found frexp(Float, int*); +} + +// Macros for generating specializations of call_ldexp and call_frexp. +// +// check_cpp and check_c99 check if the C++ or C99 functions are available. +// +// Then the call_* functions select an appropriate implementation. +// +// I used c99_func in a few places just to get a unique name. +// +// Important: when using 'using namespace' at namespace level, include as +// little as possible in that namespace, as Visual C++ has an odd bug which +// can cause the namespace to be imported at the global level. This seems to +// happen mainly when there's a template in the same namesapce. + +#define BOOST_HASH_CALL_FLOAT_FUNC(cpp_func, c99_func, type1, type2) \ +namespace BOOST_HASH_DETECT_FLOAT_FUNCTIONS { \ + template <class Float> \ + boost::hash_detail::not_found c99_func(Float, type2); \ +} \ + \ +namespace boost { \ + namespace hash_detail { \ + namespace c99_func##_detect { \ + using namespace std; \ + using namespace BOOST_HASH_DETECT_FLOAT_FUNCTIONS; \ + \ + struct check { \ + static type1 x; \ + static type2 y; \ + BOOST_STATIC_CONSTANT(bool, cpp = \ + sizeof(float_type(cpp_func(x,y))) \ + == sizeof(is<type1>)); \ + BOOST_STATIC_CONSTANT(bool, c99 = \ + sizeof(float_type(c99_func(x,y))) \ + == sizeof(is<type1>)); \ + }; \ + } \ + \ + template <bool x> \ + struct call_c99_##c99_func : \ + boost::hash_detail::call_##cpp_func<double> {}; \ + \ + template <> \ + struct call_c99_##c99_func<true> { \ + typedef type1 float_type; \ + \ + template <typename T> \ + inline type1 operator()(type1 a, T b) const \ + { \ + using namespace std; \ + return c99_func(a, b); \ + } \ + }; \ + \ + template <bool x> \ + struct call_cpp_##c99_func : \ + call_c99_##c99_func< \ + ::boost::hash_detail::c99_func##_detect::check::c99 \ + > {}; \ + \ + template <> \ + struct call_cpp_##c99_func<true> { \ + typedef type1 float_type; \ + \ + template <typename T> \ + inline type1 operator()(type1 a, T b) const \ + { \ + using namespace std; \ + return cpp_func(a, b); \ + } \ + }; \ + \ + template <> \ + struct call_##cpp_func<type1> : \ + call_cpp_##c99_func< \ + ::boost::hash_detail::c99_func##_detect::check::cpp \ + > {}; \ + } \ +} + +#define BOOST_HASH_CALL_FLOAT_MACRO(cpp_func, c99_func, type1, type2) \ +namespace boost { \ + namespace hash_detail { \ + \ + template <> \ + struct call_##cpp_func<type1> { \ + typedef type1 float_type; \ + inline type1 operator()(type1 x, type2 y) const { \ + return c99_func(x, y); \ + } \ + }; \ + } \ +} + +#if defined(ldexpf) +BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpf, float, int) +#else +BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpf, float, int) +#endif + +#if defined(ldexpl) +BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpl, long double, int) +#else +BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpl, long double, int) +#endif + +#if defined(frexpf) +BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpf, float, int*) +#else +BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpf, float, int*) +#endif + +#if defined(frexpl) +BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpl, long double, int*) +#else +BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpl, long double, int*) +#endif + +#undef BOOST_HASH_CALL_FLOAT_MACRO +#undef BOOST_HASH_CALL_FLOAT_FUNC + + +namespace boost +{ + namespace hash_detail + { + template <typename Float1, typename Float2> + struct select_hash_type_impl { + typedef double type; + }; + + template <> + struct select_hash_type_impl<float, float> { + typedef float type; + }; + + template <> + struct select_hash_type_impl<long double, long double> { + typedef long double type; + }; + + + // select_hash_type + // + // If there is support for a particular floating point type, use that + // otherwise use double (there's always support for double). + + template <typename Float> + struct select_hash_type : select_hash_type_impl< + BOOST_DEDUCED_TYPENAME call_ldexp<Float>::float_type, + BOOST_DEDUCED_TYPENAME call_frexp<Float>::float_type + > {}; + } +} + +#endif diff --git a/ext/boost/functional/hash/detail/hash_float.hpp b/ext/boost/functional/hash/detail/hash_float.hpp new file mode 100644 index 0000000000..ea1bc25f48 --- /dev/null +++ b/ext/boost/functional/hash/detail/hash_float.hpp @@ -0,0 +1,101 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_HEADER) +#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_HEADER + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/config.hpp> +#include <boost/functional/hash/detail/float_functions.hpp> +#include <boost/functional/hash/detail/limits.hpp> +#include <boost/integer/static_log2.hpp> +#include <boost/cstdint.hpp> +#include <boost/assert.hpp> + +// Include hash implementation for the current platform. + +// Cygwn +#if defined(__CYGWIN__) +# if defined(__i386__) || defined(_M_IX86) +# include <boost/functional/hash/detail/hash_float_x86.hpp> +# else +# include <boost/functional/hash/detail/hash_float_generic.hpp> +# endif +#else +# include <boost/functional/hash/detail/hash_float_generic.hpp> +#endif + +// Can we use fpclassify? + +// STLport +#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +#define BOOST_HASH_USE_FPCLASSIFY 0 + +// GNU libstdc++ 3 +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +# define BOOST_HASH_USE_FPCLASSIFY 1 +# else +# define BOOST_HASH_USE_FPCLASSIFY 0 +# endif + +// Everything else +#else +# define BOOST_HASH_USE_FPCLASSIFY 0 +#endif + +#if BOOST_HASH_USE_FPCLASSIFY + +#include <boost/config/no_tr1/cmath.hpp> + +namespace boost +{ + namespace hash_detail + { + template <class T> + inline std::size_t float_hash_value(T v) + { + using namespace std; + switch (fpclassify(v)) { + case FP_ZERO: + return 0; + case FP_INFINITE: + return (std::size_t)(v > 0 ? -1 : -2); + case FP_NAN: + return (std::size_t)(-3); + case FP_NORMAL: + case FP_SUBNORMAL: + return float_hash_impl(v); + default: + BOOST_ASSERT(0); + return 0; + } + } + } +} + +#else // !BOOST_HASH_USE_FPCLASSIFY + +namespace boost +{ + namespace hash_detail + { + template <class T> + inline std::size_t float_hash_value(T v) + { + return v == 0 ? 0 : float_hash_impl(v); + } + } +} + +#endif // BOOST_HASH_USE_FPCLASSIFY + +#undef BOOST_HASH_USE_FPCLASSIFY + +#endif diff --git a/ext/boost/functional/hash/detail/hash_float_generic.hpp b/ext/boost/functional/hash/detail/hash_float_generic.hpp new file mode 100644 index 0000000000..f9acee9cd1 --- /dev/null +++ b/ext/boost/functional/hash/detail/hash_float_generic.hpp @@ -0,0 +1,93 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +// A general purpose hash function for non-zero floating point values. + +#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_GENERIC_HEADER) +#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_GENERIC_HEADER + +#include <boost/functional/hash/detail/float_functions.hpp> +#include <boost/integer/static_log2.hpp> +#include <boost/functional/hash/detail/limits.hpp> + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(BOOST_MSVC) +#pragma warning(push) +#if BOOST_MSVC >= 1400 +#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does + // not satisfy test. Loop body not executed +#endif +#endif + +namespace boost +{ + namespace hash_detail + { + inline void hash_float_combine(std::size_t& seed, std::size_t value) + { + seed ^= value + (seed<<6) + (seed>>2); + } + + template <class T> + inline std::size_t float_hash_impl2(T v) + { + boost::hash_detail::call_frexp<T> frexp; + boost::hash_detail::call_ldexp<T> ldexp; + + int exp = 0; + + v = frexp(v, &exp); + + // A postive value is easier to hash, so combine the + // sign with the exponent and use the absolute value. + if(v < 0) { + v = -v; + exp += limits<T>::max_exponent - + limits<T>::min_exponent; + } + + // The result of frexp is always between 0.5 and 1, so its + // top bit will always be 1. Subtract by 0.5 to remove that. + v -= T(0.5); + v = ldexp(v, limits<std::size_t>::digits + 1); + std::size_t seed = static_cast<std::size_t>(v); + v -= seed; + + // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; + std::size_t const length + = (limits<T>::digits * + boost::static_log2<limits<T>::radix>::value - 1) + / limits<std::size_t>::digits; + + for(std::size_t i = 0; i != length; ++i) + { + v = ldexp(v, limits<std::size_t>::digits); + std::size_t part = static_cast<std::size_t>(v); + v -= part; + hash_float_combine(seed, part); + } + + hash_float_combine(seed, exp); + + return seed; + } + + template <class T> + inline std::size_t float_hash_impl(T v) + { + typedef BOOST_DEDUCED_TYPENAME select_hash_type<T>::type type; + return float_hash_impl2(static_cast<type>(v)); + } + } +} + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif diff --git a/ext/boost/functional/hash/detail/hash_float_x86.hpp b/ext/boost/functional/hash/detail/hash_float_x86.hpp new file mode 100644 index 0000000000..b39bb0d081 --- /dev/null +++ b/ext/boost/functional/hash/detail/hash_float_x86.hpp @@ -0,0 +1,56 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +// A non-portable hash function form non-zero floats on x86. +// +// Even if you're on an x86 platform, this might not work if their floating +// point isn't set up as this expects. So this should only be used if it's +// absolutely certain that it will work. + +#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_X86_HEADER) +#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_X86_HEADER + +#include <boost/cstdint.hpp> + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace boost +{ + namespace hash_detail + { + inline void hash_float_combine(std::size_t& seed, std::size_t value) + { + seed ^= value + (seed<<6) + (seed>>2); + } + + inline std::size_t float_hash_impl(float v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr; + return seed; + } + + inline std::size_t float_hash_impl(double v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr++; + hash_float_combine(seed, *ptr); + return seed; + } + + inline std::size_t float_hash_impl(long double v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr++; + hash_float_combine(seed, *ptr++); + hash_float_combine(seed, *(boost::uint16_t*)ptr); + return seed; + } + } +} + +#endif diff --git a/ext/boost/functional/hash/detail/limits.hpp b/ext/boost/functional/hash/detail/limits.hpp new file mode 100644 index 0000000000..f5b520ea9d --- /dev/null +++ b/ext/boost/functional/hash/detail/limits.hpp @@ -0,0 +1,61 @@ + +// Copyright 2005-2009 Daniel James. +// 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) +// +// On some platforms std::limits gives incorrect values for long double. +// This tries to work around them. + +#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER) +#define BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/limits.hpp> + +// On OpenBSD, numeric_limits is not reliable for long doubles, but +// the macros defined in <float.h> are and support long double when STLport +// doesn't. + +#if defined(__OpenBSD__) || defined(_STLP_NO_LONG_DOUBLE) +#include <float.h> +#endif + +namespace boost +{ + namespace hash_detail + { + template <class T> + struct limits : std::numeric_limits<T> {}; + +#if defined(__OpenBSD__) || defined(_STLP_NO_LONG_DOUBLE) + template <> + struct limits<long double> + : std::numeric_limits<long double> + { + static long double epsilon() { + return LDBL_EPSILON; + } + + static long double (max)() { + return LDBL_MAX; + } + + static long double (min)() { + return LDBL_MIN; + } + + BOOST_STATIC_CONSTANT(int, digits = LDBL_MANT_DIG); + BOOST_STATIC_CONSTANT(int, max_exponent = LDBL_MAX_EXP); + BOOST_STATIC_CONSTANT(int, min_exponent = LDBL_MIN_EXP); +#if defined(_STLP_NO_LONG_DOUBLE) + BOOST_STATIC_CONSTANT(int, radix = FLT_RADIX); +#endif + }; +#endif // __OpenBSD__ + } +} + +#endif diff --git a/ext/boost/functional/hash/extensions.hpp b/ext/boost/functional/hash/extensions.hpp new file mode 100644 index 0000000000..3c587a3bf5 --- /dev/null +++ b/ext/boost/functional/hash/extensions.hpp @@ -0,0 +1,286 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +// This implements the extensions to the standard. +// It's undocumented, so you shouldn't use it.... + +#if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) +#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP + +#include <boost/functional/hash/hash.hpp> +#include <boost/detail/container_fwd.hpp> + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) +#include <boost/type_traits/is_array.hpp> +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +#include <boost/type_traits/is_const.hpp> +#endif + +namespace boost +{ + template <class A, class B> + std::size_t hash_value(std::pair<A, B> const&); + template <class T, class A> + std::size_t hash_value(std::vector<T, A> const&); + template <class T, class A> + std::size_t hash_value(std::list<T, A> const& v); + template <class T, class A> + std::size_t hash_value(std::deque<T, A> const& v); + template <class K, class C, class A> + std::size_t hash_value(std::set<K, C, A> const& v); + template <class K, class C, class A> + std::size_t hash_value(std::multiset<K, C, A> const& v); + template <class K, class T, class C, class A> + std::size_t hash_value(std::map<K, T, C, A> const& v); + template <class K, class T, class C, class A> + std::size_t hash_value(std::multimap<K, T, C, A> const& v); + + template <class T> + std::size_t hash_value(std::complex<T> const&); + + template <class A, class B> + std::size_t hash_value(std::pair<A, B> const& v) + { + std::size_t seed = 0; + hash_combine(seed, v.first); + hash_combine(seed, v.second); + return seed; + } + + template <class T, class A> + std::size_t hash_value(std::vector<T, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class T, class A> + std::size_t hash_value(std::list<T, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class T, class A> + std::size_t hash_value(std::deque<T, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class K, class C, class A> + std::size_t hash_value(std::set<K, C, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class K, class C, class A> + std::size_t hash_value(std::multiset<K, C, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class K, class T, class C, class A> + std::size_t hash_value(std::map<K, T, C, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class K, class T, class C, class A> + std::size_t hash_value(std::multimap<K, T, C, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + template <class T> + std::size_t hash_value(std::complex<T> const& v) + { + boost::hash<T> hasher; + std::size_t seed = hasher(v.imag()); + seed ^= hasher(v.real()) + (seed<<6) + (seed>>2); + return seed; + } + + // + // call_hash_impl + // + + // On compilers without function template ordering, this deals with arrays. + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + namespace hash_detail + { + template <bool IsArray> + struct call_hash_impl + { + template <class T> + struct inner + { + static std::size_t call(T const& v) + { + using namespace boost; + return hash_value(v); + } + }; + }; + + template <> + struct call_hash_impl<true> + { + template <class Array> + struct inner + { +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + static std::size_t call(Array const& v) +#else + static std::size_t call(Array& v) +#endif + { + const int size = sizeof(v) / sizeof(*v); + return boost::hash_range(v, v + size); + } + }; + }; + + template <class T> + struct call_hash + : public call_hash_impl<boost::is_array<T>::value> + ::BOOST_NESTED_TEMPLATE inner<T> + { + }; + } +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + // + // boost::hash + // + + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template <class T> struct hash + : std::unary_function<T, std::size_t> + { +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + std::size_t operator()(T const& val) const + { + return hash_value(val); + } +#else + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash<T>::call(val); + } +#endif + }; + +#if BOOST_WORKAROUND(__DMC__, <= 0x848) + template <class T, unsigned int n> struct hash<T[n]> + : std::unary_function<T[n], std::size_t> + { + std::size_t operator()(const T* val) const + { + return boost::hash_range(val, val+n); + } + }; +#endif + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // On compilers without partial specialization, boost::hash<T> + // has already been declared to deal with pointers, so just + // need to supply the non-pointer version of hash_impl. + + namespace hash_detail + { + template <bool IsPointer> + struct hash_impl; + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + template <> + struct hash_impl<false> + { + template <class T> + struct inner + : std::unary_function<T, std::size_t> + { +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + std::size_t operator()(T const& val) const + { + return hash_value(val); + } +#else + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash<T>::call(val); + } +#endif + }; + }; + +#else // Visual C++ 6.5 + + // Visual C++ 6.5 has problems with nested member functions and + // applying const to const types in templates. So we get this: + + template <bool IsConst> + struct hash_impl_msvc + { + template <class T> + struct inner + : public std::unary_function<T, std::size_t> + { + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash<T const>::call(val); + } + + std::size_t operator()(T& val) const + { + return hash_detail::call_hash<T>::call(val); + } + }; + }; + + template <> + struct hash_impl_msvc<true> + { + template <class T> + struct inner + : public std::unary_function<T, std::size_t> + { + std::size_t operator()(T& val) const + { + return hash_detail::call_hash<T>::call(val); + } + }; + }; + + template <class T> + struct hash_impl_msvc2 + : public hash_impl_msvc<boost::is_const<T>::value> + ::BOOST_NESTED_TEMPLATE inner<T> {}; + + template <> + struct hash_impl<false> + { + template <class T> + struct inner : public hash_impl_msvc2<T> {}; + }; + +#endif // Visual C++ 6.5 + } +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +} + +#endif diff --git a/ext/boost/functional/hash/hash.hpp b/ext/boost/functional/hash/hash.hpp new file mode 100644 index 0000000000..6784f3ef6b --- /dev/null +++ b/ext/boost/functional/hash/hash.hpp @@ -0,0 +1,478 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP) +#define BOOST_FUNCTIONAL_HASH_HASH_HPP + +#include <boost/functional/hash/hash_fwd.hpp> +#include <functional> +#include <boost/functional/hash/detail/hash_float.hpp> +#include <string> +#include <boost/limits.hpp> + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +#include <boost/type_traits/is_pointer.hpp> +#endif + +#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +#define BOOST_HASH_CHAR_TRAITS string_char_traits +#else +#define BOOST_HASH_CHAR_TRAITS char_traits +#endif + +namespace boost +{ + std::size_t hash_value(bool); + std::size_t hash_value(char); + std::size_t hash_value(unsigned char); + std::size_t hash_value(signed char); + std::size_t hash_value(short); + std::size_t hash_value(unsigned short); + std::size_t hash_value(int); + std::size_t hash_value(unsigned int); + std::size_t hash_value(long); + std::size_t hash_value(unsigned long); + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + std::size_t hash_value(wchar_t); +#endif + +#if defined(BOOST_HAS_LONG_LONG) + std::size_t hash_value(boost::long_long_type); + std::size_t hash_value(boost::ulong_long_type); +#endif + +#if !BOOST_WORKAROUND(__DMC__, <= 0x848) + template <class T> std::size_t hash_value(T* const&); +#else + template <class T> std::size_t hash_value(T*); +#endif + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template< class T, unsigned N > + std::size_t hash_value(const T (&x)[N]); + + template< class T, unsigned N > + std::size_t hash_value(T (&x)[N]); +#endif + + std::size_t hash_value(float v); + std::size_t hash_value(double v); + std::size_t hash_value(long double v); + + template <class Ch, class A> + std::size_t hash_value(std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&); + + // Implementation + + namespace hash_detail + { + template <class T> + inline std::size_t hash_value_signed(T val) + { + const int size_t_bits = std::numeric_limits<std::size_t>::digits; + // ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1 + const int length = (std::numeric_limits<T>::digits - 1) + / size_t_bits; + + std::size_t seed = 0; + T positive = val < 0 ? -1 - val : val; + + // Hopefully, this loop can be unrolled. + for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) + { + seed ^= (std::size_t) (positive >> i) + (seed<<6) + (seed>>2); + } + seed ^= (std::size_t) val + (seed<<6) + (seed>>2); + + return seed; + } + + template <class T> + inline std::size_t hash_value_unsigned(T val) + { + const int size_t_bits = std::numeric_limits<std::size_t>::digits; + // ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1 + const int length = (std::numeric_limits<T>::digits - 1) + / size_t_bits; + + std::size_t seed = 0; + + // Hopefully, this loop can be unrolled. + for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) + { + seed ^= (std::size_t) (val >> i) + (seed<<6) + (seed>>2); + } + seed ^= (std::size_t) val + (seed<<6) + (seed>>2); + + return seed; + } + } + + inline std::size_t hash_value(bool v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(char v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(unsigned char v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(signed char v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(short v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(unsigned short v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(int v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(unsigned int v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(long v) + { + return static_cast<std::size_t>(v); + } + + inline std::size_t hash_value(unsigned long v) + { + return static_cast<std::size_t>(v); + } + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + inline std::size_t hash_value(wchar_t v) + { + return static_cast<std::size_t>(v); + } +#endif + +#if defined(BOOST_HAS_LONG_LONG) + inline std::size_t hash_value(boost::long_long_type v) + { + return hash_detail::hash_value_signed(v); + } + + inline std::size_t hash_value(boost::ulong_long_type v) + { + return hash_detail::hash_value_unsigned(v); + } +#endif + + // Implementation by Alberto Barbati and Dave Harris. +#if !BOOST_WORKAROUND(__DMC__, <= 0x848) + template <class T> std::size_t hash_value(T* const& v) +#else + template <class T> std::size_t hash_value(T* v) +#endif + { + std::size_t x = static_cast<std::size_t>( + reinterpret_cast<std::ptrdiff_t>(v)); + + return x + (x >> 3); + } + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template <class T> + inline void hash_combine(std::size_t& seed, T& v) +#else + template <class T> + inline void hash_combine(std::size_t& seed, T const& v) +#endif + { + boost::hash<T> hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + template <class It> + inline std::size_t hash_range(It first, It last) + { + std::size_t seed = 0; + + for(; first != last; ++first) + { + hash_combine(seed, *first); + } + + return seed; + } + + template <class It> + inline void hash_range(std::size_t& seed, It first, It last) + { + for(; first != last; ++first) + { + hash_combine(seed, *first); + } + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + template <class T> + inline std::size_t hash_range(T* first, T* last) + { + std::size_t seed = 0; + + for(; first != last; ++first) + { + boost::hash<T> hasher; + seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + return seed; + } + + template <class T> + inline void hash_range(std::size_t& seed, T* first, T* last) + { + for(; first != last; ++first) + { + boost::hash<T> hasher; + seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + } +#endif + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template< class T, unsigned N > + inline std::size_t hash_value(const T (&x)[N]) + { + return hash_range(x, x + N); + } + + template< class T, unsigned N > + inline std::size_t hash_value(T (&x)[N]) + { + return hash_range(x, x + N); + } +#endif + + template <class Ch, class A> + inline std::size_t hash_value(std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + inline std::size_t hash_value(float v) + { + return boost::hash_detail::float_hash_value(v); + } + + inline std::size_t hash_value(double v) + { + return boost::hash_detail::float_hash_value(v); + } + + inline std::size_t hash_value(long double v) + { + return boost::hash_detail::float_hash_value(v); + } + + // + // boost::hash + // + + // Define the specializations required by the standard. The general purpose + // boost::hash is defined later in extensions.hpp if BOOST_HASH_NO_EXTENSIONS + // is not defined. + + // BOOST_HASH_SPECIALIZE - define a specialization for a type which is + // passed by copy. + // + // BOOST_HASH_SPECIALIZE_REF - define a specialization for a type which is + // passed by copy. + // + // These are undefined later. + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +#define BOOST_HASH_SPECIALIZE(type) \ + template <> struct hash<type> \ + : public std::unary_function<type, std::size_t> \ + { \ + std::size_t operator()(type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; + +#define BOOST_HASH_SPECIALIZE_REF(type) \ + template <> struct hash<type> \ + : public std::unary_function<type, std::size_t> \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; +#else +#define BOOST_HASH_SPECIALIZE(type) \ + template <> struct hash<type> \ + : public std::unary_function<type, std::size_t> \ + { \ + std::size_t operator()(type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; \ + \ + template <> struct hash<const type> \ + : public std::unary_function<const type, std::size_t> \ + { \ + std::size_t operator()(const type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; + +#define BOOST_HASH_SPECIALIZE_REF(type) \ + template <> struct hash<type> \ + : public std::unary_function<type, std::size_t> \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; \ + \ + template <> struct hash<const type> \ + : public std::unary_function<const type, std::size_t> \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; +#endif + + BOOST_HASH_SPECIALIZE(bool) + BOOST_HASH_SPECIALIZE(char) + BOOST_HASH_SPECIALIZE(signed char) + BOOST_HASH_SPECIALIZE(unsigned char) +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + BOOST_HASH_SPECIALIZE(wchar_t) +#endif + BOOST_HASH_SPECIALIZE(short) + BOOST_HASH_SPECIALIZE(unsigned short) + BOOST_HASH_SPECIALIZE(int) + BOOST_HASH_SPECIALIZE(unsigned int) + BOOST_HASH_SPECIALIZE(long) + BOOST_HASH_SPECIALIZE(unsigned long) + + BOOST_HASH_SPECIALIZE(float) + BOOST_HASH_SPECIALIZE(double) + BOOST_HASH_SPECIALIZE(long double) + + BOOST_HASH_SPECIALIZE_REF(std::string) +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_HASH_SPECIALIZE_REF(std::wstring) +#endif + +#if defined(BOOST_HAS_LONG_LONG) + BOOST_HASH_SPECIALIZE(boost::long_long_type) + BOOST_HASH_SPECIALIZE(boost::ulong_long_type) +#endif + +#undef BOOST_HASH_SPECIALIZE +#undef BOOST_HASH_SPECIALIZE_REF + +// Specializing boost::hash for pointers. + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template <class T> + struct hash<T*> + : public std::unary_function<T*, std::size_t> + { + std::size_t operator()(T* v) const + { +#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) + return boost::hash_value(v); +#else + std::size_t x = static_cast<std::size_t>( + reinterpret_cast<std::ptrdiff_t>(v)); + + return x + (x >> 3); +#endif + } + }; + +#else + + // For compilers without partial specialization, we define a + // boost::hash for all remaining types. But hash_impl is only defined + // for pointers in 'extensions.hpp' - so when BOOST_HASH_NO_EXTENSIONS + // is defined there will still be a compile error for types not supported + // in the standard. + + namespace hash_detail + { + template <bool IsPointer> + struct hash_impl; + + template <> + struct hash_impl<true> + { + template <class T> + struct inner + : public std::unary_function<T, std::size_t> + { + std::size_t operator()(T val) const + { +#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590) + return boost::hash_value(val); +#else + std::size_t x = static_cast<std::size_t>( + reinterpret_cast<std::ptrdiff_t>(val)); + + return x + (x >> 3); +#endif + } + }; + }; + } + + template <class T> struct hash + : public boost::hash_detail::hash_impl<boost::is_pointer<T>::value> + ::BOOST_NESTED_TEMPLATE inner<T> + { + }; + +#endif +} + +#undef BOOST_HASH_CHAR_TRAITS + +#endif // BOOST_FUNCTIONAL_HASH_HASH_HPP + +// Include this outside of the include guards in case the file is included +// twice - once with BOOST_HASH_NO_EXTENSIONS defined, and then with it +// undefined. + +#if !defined(BOOST_HASH_NO_EXTENSIONS) \ + && !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) +#include <boost/functional/hash/extensions.hpp> +#endif diff --git a/ext/boost/functional/hash/hash_fwd.hpp b/ext/boost/functional/hash/hash_fwd.hpp new file mode 100644 index 0000000000..1d51b07f2d --- /dev/null +++ b/ext/boost/functional/hash/hash_fwd.hpp @@ -0,0 +1,40 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP) +#define BOOST_FUNCTIONAL_HASH_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/config.hpp> +#include <cstddef> +#include <boost/detail/workaround.hpp> + +namespace boost +{ + template <class T> struct hash; + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template <class T> void hash_combine(std::size_t& seed, T& v); +#else + template <class T> void hash_combine(std::size_t& seed, T const& v); +#endif + + template <class It> std::size_t hash_range(It, It); + template <class It> void hash_range(std::size_t&, It, It); + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + template <class T> inline std::size_t hash_range(T*, T*); + template <class T> inline void hash_range(std::size_t&, T*, T*); +#endif +} + +#endif diff --git a/ext/boost/functional/hash_fwd.hpp b/ext/boost/functional/hash_fwd.hpp new file mode 100644 index 0000000000..b640988618 --- /dev/null +++ b/ext/boost/functional/hash_fwd.hpp @@ -0,0 +1,7 @@ + +// Copyright 2005-2009 Daniel James. +// 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) + +#include <boost/functional/hash/hash_fwd.hpp> + diff --git a/ext/boost/integer/integer_mask.hpp b/ext/boost/integer/integer_mask.hpp new file mode 100644 index 0000000000..0a092d3850 --- /dev/null +++ b/ext/boost/integer/integer_mask.hpp @@ -0,0 +1,93 @@ +// Boost integer/integer_mask.hpp header file ------------------------------// + +// (C) Copyright Daryle Walker 2001. +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_INTEGER_INTEGER_MASK_HPP +#define BOOST_INTEGER_INTEGER_MASK_HPP + +#include <boost/integer_fwd.hpp> // self include + +#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT +#include <boost/integer.hpp> // for boost::uint_t + +#include <climits> // for UCHAR_MAX, etc. +#include <cstddef> // for std::size_t + +#include <boost/limits.hpp> // for std::numeric_limits + + +namespace boost +{ + + +// Specified single-bit mask class declaration -----------------------------// +// (Lowest bit starts counting at 0.) + +template < std::size_t Bit > +struct high_bit_mask_t +{ + typedef typename uint_t<(Bit + 1)>::least least; + typedef typename uint_t<(Bit + 1)>::fast fast; + + BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << Bit) ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << Bit) ); + + BOOST_STATIC_CONSTANT( std::size_t, bit_position = Bit ); + +}; // boost::high_bit_mask_t + + +// Specified bit-block mask class declaration ------------------------------// +// Makes masks for the lowest N bits +// (Specializations are needed when N fills up a type.) + +template < std::size_t Bits > +struct low_bits_mask_t +{ + typedef typename uint_t<Bits>::least least; + typedef typename uint_t<Bits>::fast fast; + + BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); + + BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); + +}; // boost::low_bits_mask_t + + +#define BOOST_LOW_BITS_MASK_SPECIALIZE( Type ) \ + template < > struct low_bits_mask_t< std::numeric_limits<Type>::digits > { \ + typedef std::numeric_limits<Type> limits_type; \ + typedef uint_t<limits_type::digits>::least least; \ + typedef uint_t<limits_type::digits>::fast fast; \ + BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); \ + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); \ + BOOST_STATIC_CONSTANT( std::size_t, bit_count = limits_type::digits ); \ + } + +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned char ); + +#if USHRT_MAX > UCHAR_MAX +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned short ); +#endif + +#if UINT_MAX > USHRT_MAX +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned int ); +#endif + +#if ULONG_MAX > UINT_MAX +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned long ); +#endif + +#undef BOOST_LOW_BITS_MASK_SPECIALIZE + + +} // namespace boost + + +#endif // BOOST_INTEGER_INTEGER_MASK_HPP diff --git a/ext/boost/integer/static_log2.hpp b/ext/boost/integer/static_log2.hpp new file mode 100644 index 0000000000..219a48e341 --- /dev/null +++ b/ext/boost/integer/static_log2.hpp @@ -0,0 +1,132 @@ +// -------------- Boost static_log2.hpp header file ----------------------- // +// +// Copyright (C) 2001 Daryle Walker. +// Copyright (C) 2003 Vesa Karvonen. +// Copyright (C) 2003 Gennaro Prota. +// +// 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) +// +// --------------------------------------------------- +// See http://www.boost.org/libs/integer for documentation. +// ------------------------------------------------------------------------- // + + +#ifndef BOOST_INTEGER_STATIC_LOG2_HPP +#define BOOST_INTEGER_STATIC_LOG2_HPP + +#include "boost/config.hpp" // for BOOST_STATIC_CONSTANT + +namespace boost { + + namespace detail { + + namespace static_log2_impl { + + // choose_initial_n<> + // + // Recursively doubles its integer argument, until it + // becomes >= of the "width" (C99, 6.2.6.2p4) of + // static_log2_argument_type. + // + // Used to get the maximum power of two less then the width. + // + // Example: if on your platform argument_type has 48 value + // bits it yields n=32. + // + // It's easy to prove that, starting from such a value + // of n, the core algorithm works correctly for any width + // of static_log2_argument_type and that recursion always + // terminates with x = 1 and n = 0 (see the algorithm's + // invariant). + + typedef unsigned long argument_type; + typedef int result_type; + + + template <result_type n> + struct choose_initial_n { + + BOOST_STATIC_CONSTANT(bool, c = (argument_type(1) << n << n) != 0); + BOOST_STATIC_CONSTANT( + result_type, + value = !c*n + choose_initial_n<2*c*n>::value + ); + + }; + + template <> + struct choose_initial_n<0> { + BOOST_STATIC_CONSTANT(result_type, value = 0); + }; + + + + // start computing from n_zero - must be a power of two + const result_type n_zero = 16; + const result_type initial_n = choose_initial_n<n_zero>::value; + + // static_log2_impl<> + // + // * Invariant: + // 2n + // 1 <= x && x < 2 at the start of each recursion + // (see also choose_initial_n<>) + // + // * Type requirements: + // + // argument_type maybe any unsigned type with at least n_zero + 1 + // value bits. (Note: If larger types will be standardized -e.g. + // unsigned long long- then the argument_type typedef can be + // changed without affecting the rest of the code.) + // + + template <argument_type x, result_type n = initial_n> + struct static_log2_impl { + + BOOST_STATIC_CONSTANT(bool, c = (x >> n) > 0); // x >= 2**n ? + BOOST_STATIC_CONSTANT( + result_type, + value = c*n + (static_log2_impl< (x>>c*n), n/2 >::value) + ); + + }; + + template <> + struct static_log2_impl<1, 0> { + BOOST_STATIC_CONSTANT(result_type, value = 0); + }; + + } + } // detail + + + + // -------------------------------------- + // static_log2<x> + // ---------------------------------------- + + typedef detail::static_log2_impl::argument_type static_log2_argument_type; + typedef detail::static_log2_impl::result_type static_log2_result_type; + + + template <static_log2_argument_type x> + struct static_log2 { + + BOOST_STATIC_CONSTANT( + static_log2_result_type, + value = detail::static_log2_impl::static_log2_impl<x>::value + ); + + }; + + + template <> + struct static_log2<0> { }; + +} + + + +#endif // include guard diff --git a/ext/boost/integer/static_min_max.hpp b/ext/boost/integer/static_min_max.hpp new file mode 100644 index 0000000000..264603727f --- /dev/null +++ b/ext/boost/integer/static_min_max.hpp @@ -0,0 +1,55 @@ +// Boost integer/static_min_max.hpp header file ----------------------------// + +// (C) Copyright Daryle Walker 2001. +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_INTEGER_STATIC_MIN_MAX_HPP +#define BOOST_INTEGER_STATIC_MIN_MAX_HPP + +#include <boost/integer_fwd.hpp> // self include + +#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT + + +namespace boost +{ + + +// Compile-time extrema class declarations ---------------------------------// +// Get the minimum or maximum of two values, signed or unsigned. + +template < long Value1, long Value2 > +struct static_signed_min +{ + BOOST_STATIC_CONSTANT( long, value = (Value1 > Value2) ? Value2 : Value1 ); +}; + +template < long Value1, long Value2 > +struct static_signed_max +{ + BOOST_STATIC_CONSTANT( long, value = (Value1 < Value2) ? Value2 : Value1 ); +}; + +template < unsigned long Value1, unsigned long Value2 > +struct static_unsigned_min +{ + BOOST_STATIC_CONSTANT( unsigned long, value + = (Value1 > Value2) ? Value2 : Value1 ); +}; + +template < unsigned long Value1, unsigned long Value2 > +struct static_unsigned_max +{ + BOOST_STATIC_CONSTANT( unsigned long, value + = (Value1 < Value2) ? Value2 : Value1 ); +}; + + +} // namespace boost + + +#endif // BOOST_INTEGER_STATIC_MIN_MAX_HPP diff --git a/ext/boost/optional/optional.hpp b/ext/boost/optional/optional.hpp new file mode 100644 index 0000000000..42277ba61e --- /dev/null +++ b/ext/boost/optional/optional.hpp @@ -0,0 +1,922 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP + +#include<new> +#include<algorithm> + +#include "boost/config.hpp" +#include "boost/assert.hpp" +#include "boost/type.hpp" +#include "boost/type_traits/alignment_of.hpp" +#include "boost/type_traits/type_with_alignment.hpp" +#include "boost/type_traits/remove_reference.hpp" +#include "boost/type_traits/is_reference.hpp" +#include "boost/mpl/if.hpp" +#include "boost/mpl/bool.hpp" +#include "boost/mpl/not.hpp" +#include "boost/detail/reference_content.hpp" +#include "boost/none.hpp" +#include "boost/utility/compare_pointees.hpp" + +#include "boost/optional/optional_fwd.hpp" + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) +// VC6.0 has the following bug: +// When a templated assignment operator exist, an implicit conversion +// constructing an optional<T> is used when assigment of the form: +// optional<T> opt ; opt = T(...); +// is compiled. +// However, optional's ctor is _explicit_ and the assignemt shouldn't compile. +// Therefore, for VC6.0 templated assignment is disabled. +// +#define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1300) +// VC7.0 has the following bug: +// When both a non-template and a template copy-ctor exist +// and the templated version is made 'explicit', the explicit is also +// given to the non-templated version, making the class non-implicitely-copyable. +// +#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700) +// AFAICT only VC7.1 correctly resolves the overload set +// that includes the in-place factory taking functions, +// so for the other VC versions, in-place factory support +// is disabled +#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#endif + +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551) +// BCB (5.5.1) cannot parse the nested template struct in an inplace factory. +#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#endif + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \ + && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) ) +// BCB (up to 5.64) has the following bug: +// If there is a member function/operator template of the form +// template<class Expr> mfunc( Expr expr ) ; +// some calls are resolved to this even if there are other better matches. +// The effect of this bug is that calls to converting ctors and assignments +// are incrorrectly sink to this general catch-all member function template as shown above. +#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION +#endif + +// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<> +// member template of a factory as used in the optional<> implementation. +// He proposed this simple fix which is to move the call to apply<> outside +// namespace boost. +namespace boost_optional_detail +{ + template <class T, class Factory> + void construct(Factory const& factory, void* address) + { + factory.BOOST_NESTED_TEMPLATE apply<T>(address); + } +} + + +namespace boost { + +class in_place_factory_base ; +class typed_in_place_factory_base ; + +namespace optional_detail { + +// This local class is used instead of that in "aligned_storage.hpp" +// because I've found the 'official' class to ICE BCB5.5 +// when some types are used with optional<> +// (due to sizeof() passed down as a non-type template parameter) +template <class T> +class aligned_storage +{ + // Borland ICEs if unnamed unions are used for this! + union dummy_u + { + char data[ sizeof(T) ]; + BOOST_DEDUCED_TYPENAME type_with_alignment< + ::boost::alignment_of<T>::value >::type aligner_; + } dummy_ ; + + public: + + void const* address() const { return &dummy_.data[0]; } + void * address() { return &dummy_.data[0]; } +} ; + +template<class T> +struct types_when_isnt_ref +{ + typedef T const& reference_const_type ; + typedef T & reference_type ; + typedef T const* pointer_const_type ; + typedef T * pointer_type ; + typedef T const& argument_type ; +} ; +template<class T> +struct types_when_is_ref +{ + typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ; + + typedef raw_type& reference_const_type ; + typedef raw_type& reference_type ; + typedef raw_type* pointer_const_type ; + typedef raw_type* pointer_type ; + typedef raw_type& argument_type ; +} ; + +struct optional_tag {} ; + +template<class T> +class optional_base : public optional_tag +{ + private : + + typedef +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + BOOST_DEDUCED_TYPENAME +#endif + ::boost::detail::make_reference_content<T>::type internal_type ; + + typedef aligned_storage<internal_type> storage_type ; + + typedef types_when_isnt_ref<T> types_when_not_ref ; + typedef types_when_is_ref<T> types_when_ref ; + + typedef optional_base<T> this_type ; + + protected : + + typedef T value_type ; + + typedef mpl::true_ is_reference_tag ; + typedef mpl::false_ is_not_reference_tag ; + + typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ; + + typedef bool (this_type::*unspecified_bool_type)() const; + + typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; + typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ; + + // Creates an optional<T> uninitialized. + // No-throw + optional_base() + : + m_initialized(false) {} + + // Creates an optional<T> uninitialized. + // No-throw + optional_base ( none_t ) + : + m_initialized(false) {} + + // Creates an optional<T> initialized with 'val'. + // Can throw if T::T(T const&) does + optional_base ( argument_type val ) + : + m_initialized(false) + { + construct(val); + } + + // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>. + // Can throw if T::T(T const&) does + optional_base ( bool cond, argument_type val ) + : + m_initialized(false) + { + if ( cond ) + construct(val); + } + + // Creates a deep copy of another optional<T> + // Can throw if T::T(T const&) does + optional_base ( optional_base const& rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + + + // This is used for both converting and in-place constructions. + // Derived classes use the 'tag' to select the appropriate + // implementation (the correct 'construct()' overload) + template<class Expr> + explicit optional_base ( Expr const& expr, Expr const* tag ) + : + m_initialized(false) + { + construct(expr,tag); + } + + + + // No-throw (assuming T::~T() doesn't) + ~optional_base() { destroy() ; } + + // Assigns from another optional<T> (deep-copies the rhs value) + void assign ( optional_base const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(rhs.get_impl(), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + } + + // Assigns from another _convertible_ optional<U> (deep-copies the rhs value) + template<class U> + void assign ( optional<U> const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(static_cast<value_type>(rhs.get())); + } + } + + // Assigns from a T (deep-copies the rhs value) + void assign ( argument_type val ) + { + if (is_initialized()) + assign_value(val, is_reference_predicate() ); + else construct(val); + } + + // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void assign ( none_t ) { destroy(); } + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + template<class Expr> + void assign_expr ( Expr const& expr, Expr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(expr,tag); + else construct(expr,tag); + } +#endif + + public : + + // Destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void reset() { destroy(); } + + // Replaces the current value -if any- with 'val' + void reset ( argument_type val ) { assign(val); } + + // Returns a pointer to the value if this is initialized, otherwise, + // returns NULL. + // No-throw + pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } + pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } + + bool is_initialized() const { return m_initialized ; } + + protected : + + void construct ( argument_type val ) + { + new (m_storage.address()) internal_type(val) ; + m_initialized = true ; + } + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + // Constructs in-place using the given factory + template<class Expr> + void construct ( Expr const& factory, in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ; + boost_optional_detail::construct<value_type>(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template<class Expr> + void construct ( Expr const& factory, typed_in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ; + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template<class Expr> + void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template<class Expr> + void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } +#endif + + // Constructs using any expression implicitely convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional<T> from optional<U> uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template<class Expr> + void construct ( Expr const& expr, void const* ) + { + new (m_storage.address()) internal_type(expr) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitely convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional<T> from optional<U> uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template<class Expr> + void assign_expr_to_initialized ( Expr const& expr, void const* ) + { + assign_value(expr, is_reference_predicate()); + } + +#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + // BCB5.64 (and probably lower versions) workaround. + // The in-place factories are supported by means of catch-all constructors + // and assignment operators (the functions are parameterized in terms of + // an arbitrary 'Expr' type) + // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U> + // to the 'Expr'-taking functions even though explicit overloads are present for them. + // Thus, the following overload is needed to properly handle the case when the 'lhs' + // is another optional. + // + // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error + // instead of choosing the wrong overload + // + // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>) + template<class Expr> + void construct ( Expr const& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) internal_type(expr.get()) ; + m_initialized = true ; + } + } +#endif + + void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } + void assign_value ( argument_type val, is_reference_tag ) { construct(val); } + + void destroy() + { + if ( m_initialized ) + destroy_impl(is_reference_predicate()) ; + } + + unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; } + + reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; } + reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; } + + pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; } + pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; } + + private : + + // internal_type can be either T or reference_content<T> + internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); } + internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); } + + // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference. + reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; } + reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; } + reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; } + reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; } +#else + void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; } +#endif + + void destroy_impl ( is_reference_tag ) { m_initialized = false ; } + + // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error. + // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case, + // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference. + pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; } + pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; } + pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; } + pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; } + + bool m_initialized ; + storage_type m_storage ; +} ; + +} // namespace optional_detail + +template<class T> +class optional : public optional_detail::optional_base<T> +{ + typedef optional_detail::optional_base<T> base ; + + typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ; + + public : + + typedef optional<T> this_type ; + + typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; + typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + + // Creates an optional<T> uninitialized. + // No-throw + optional() : base() {} + + // Creates an optional<T> uninitialized. + // No-throw + optional( none_t none_ ) : base(none_) {} + + // Creates an optional<T> initialized with 'val'. + // Can throw if T::T(T const&) does + optional ( argument_type val ) : base(val) {} + + // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional ( bool cond, argument_type val ) : base(cond,val) {} + +#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + // NOTE: MSVC needs templated versions first + + // Creates a deep copy of another convertible optional<U> + // Requires a valid conversion from U to T. + // Can throw if T::T(U const&) does + template<class U> + explicit optional ( optional<U> const& rhs ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct(rhs.get()); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + // Creates an optional<T> with an expression which can be either + // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n); + // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n); + // (c) Any expression implicitely convertible to the single type + // of a one-argument T's constructor. + // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U> + // even though explicit overloads are present for these. + // Depending on the above some T ctor is called. + // Can throw is the resolved T ctor throws. + template<class Expr> + explicit optional ( Expr const& expr ) : base(expr,&expr) {} +#endif + + // Creates a deep copy of another optional<T> + // Can throw if T::T(T const&) does + optional ( optional const& rhs ) : base(rhs) {} + + // No-throw (assuming T::~T() doesn't) + ~optional() {} + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + // Assigns from an expression. See corresponding constructor. + // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED + template<class Expr> + optional& operator= ( Expr expr ) + { + this->assign_expr(expr,&expr); + return *this ; + } +#endif + + +#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT + // Assigns from another convertible optional<U> (converts && deep-copies the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED + template<class U> + optional& operator= ( optional<U> const& rhs ) + { + this->assign(rhs); + return *this ; + } +#endif + + // Assigns from another optional<T> (deep-copies the rhs value) + // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED + // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) + optional& operator= ( optional const& rhs ) + { + this->assign( rhs ) ; + return *this ; + } + + // Assigns from a T (deep-copies the rhs value) + // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED + optional& operator= ( argument_type val ) + { + this->assign( val ) ; + return *this ; + } + + // Assigns from a "none" + // Which destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + optional& operator= ( none_t none_ ) + { + this->assign( none_ ) ; + return *this ; + } + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + + // Returns a copy of the value if this is initialized, 'v' otherwise + reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; } + reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; } + + // Returns a pointer to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + reference_const_type operator *() const { return this->get() ; } + reference_type operator *() { return this->get() ; } + + // implicit conversion to "bool" + // No-throw + operator unspecified_bool_type() const { return this->safe_bool() ; } + + // This is provided for those compilers which don't like the conversion to bool + // on some contexts. + bool operator!() const { return !this->is_initialized() ; } +} ; + +// Returns optional<T>(v) +template<class T> +inline +optional<T> make_optional ( T const& v ) +{ + return optional<T>(v); +} + +// Returns optional<T>(cond,v) +template<class T> +inline +optional<T> make_optional ( bool cond, T const& v ) +{ + return optional<T>(cond,v); +} + +// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. +// No-throw +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type +get ( optional<T> const& opt ) +{ + return opt.get() ; +} + +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::reference_type +get ( optional<T>& opt ) +{ + return opt.get() ; +} + +// Returns a pointer to the value if this is initialized, otherwise, returns NULL. +// No-throw +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type +get ( optional<T> const* opt ) +{ + return opt->get_ptr() ; +} + +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::pointer_type +get ( optional<T>* opt ) +{ + return opt->get_ptr() ; +} + +// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. +// No-throw +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type +get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v ) +{ + return opt.get_value_or(v) ; +} + +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::reference_type +get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v ) +{ + return opt.get_value_or(v) ; +} + +// Returns a pointer to the value if this is initialized, otherwise, returns NULL. +// No-throw +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type +get_pointer ( optional<T> const& opt ) +{ + return opt.get_ptr() ; +} + +template<class T> +inline +BOOST_DEDUCED_TYPENAME optional<T>::pointer_type +get_pointer ( optional<T>& opt ) +{ + return opt.get_ptr() ; +} + +// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). +// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead. + + +// +// optional<T> vs optional<T> cases +// + +template<class T> +inline +bool operator == ( optional<T> const& x, optional<T> const& y ) +{ return equal_pointees(x,y); } + +template<class T> +inline +bool operator < ( optional<T> const& x, optional<T> const& y ) +{ return less_pointees(x,y); } + +template<class T> +inline +bool operator != ( optional<T> const& x, optional<T> const& y ) +{ return !( x == y ) ; } + +template<class T> +inline +bool operator > ( optional<T> const& x, optional<T> const& y ) +{ return y < x ; } + +template<class T> +inline +bool operator <= ( optional<T> const& x, optional<T> const& y ) +{ return !( y < x ) ; } + +template<class T> +inline +bool operator >= ( optional<T> const& x, optional<T> const& y ) +{ return !( x < y ) ; } + + +// +// optional<T> vs T cases +// +template<class T> +inline +bool operator == ( optional<T> const& x, T const& y ) +{ return equal_pointees(x, optional<T>(y)); } + +template<class T> +inline +bool operator < ( optional<T> const& x, T const& y ) +{ return less_pointees(x, optional<T>(y)); } + +template<class T> +inline +bool operator != ( optional<T> const& x, T const& y ) +{ return !( x == y ) ; } + +template<class T> +inline +bool operator > ( optional<T> const& x, T const& y ) +{ return y < x ; } + +template<class T> +inline +bool operator <= ( optional<T> const& x, T const& y ) +{ return !( y < x ) ; } + +template<class T> +inline +bool operator >= ( optional<T> const& x, T const& y ) +{ return !( x < y ) ; } + +// +// T vs optional<T> cases +// + +template<class T> +inline +bool operator == ( T const& x, optional<T> const& y ) +{ return equal_pointees( optional<T>(x), y ); } + +template<class T> +inline +bool operator < ( T const& x, optional<T> const& y ) +{ return less_pointees( optional<T>(x), y ); } + +template<class T> +inline +bool operator != ( T const& x, optional<T> const& y ) +{ return !( x == y ) ; } + +template<class T> +inline +bool operator > ( T const& x, optional<T> const& y ) +{ return y < x ; } + +template<class T> +inline +bool operator <= ( T const& x, optional<T> const& y ) +{ return !( y < x ) ; } + +template<class T> +inline +bool operator >= ( T const& x, optional<T> const& y ) +{ return !( x < y ) ; } + + +// +// optional<T> vs none cases +// + +template<class T> +inline +bool operator == ( optional<T> const& x, none_t ) +{ return equal_pointees(x, optional<T>() ); } + +template<class T> +inline +bool operator < ( optional<T> const& x, none_t ) +{ return less_pointees(x,optional<T>() ); } + +template<class T> +inline +bool operator != ( optional<T> const& x, none_t y ) +{ return !( x == y ) ; } + +template<class T> +inline +bool operator > ( optional<T> const& x, none_t y ) +{ return y < x ; } + +template<class T> +inline +bool operator <= ( optional<T> const& x, none_t y ) +{ return !( y < x ) ; } + +template<class T> +inline +bool operator >= ( optional<T> const& x, none_t y ) +{ return !( x < y ) ; } + +// +// none vs optional<T> cases +// + +template<class T> +inline +bool operator == ( none_t x, optional<T> const& y ) +{ return equal_pointees(optional<T>() ,y); } + +template<class T> +inline +bool operator < ( none_t x, optional<T> const& y ) +{ return less_pointees(optional<T>() ,y); } + +template<class T> +inline +bool operator != ( none_t x, optional<T> const& y ) +{ return !( x == y ) ; } + +template<class T> +inline +bool operator > ( none_t x, optional<T> const& y ) +{ return y < x ; } + +template<class T> +inline +bool operator <= ( none_t x, optional<T> const& y ) +{ return !( y < x ) ; } + +template<class T> +inline +bool operator >= ( none_t x, optional<T> const& y ) +{ return !( x < y ) ; } + +// +// The following swap implementation follows the GCC workaround as found in +// "boost/detail/compressed_pair.hpp" +// +namespace optional_detail { + +// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA) +#if BOOST_WORKAROUND(__GNUC__, < 3) \ + || BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2 + using std::swap; +#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE +#endif + +// optional's swap: +// If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified. +// If only one is initialized, calls U.reset(*I), THEN I.reset(). +// If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset) +// If both are uninitialized, do nothing (no-throw) +template<class T> +inline +void optional_swap ( optional<T>& x, optional<T>& y ) +{ + if ( !x && !!y ) + { + x.reset(*y); + y.reset(); + } + else if ( !!x && !y ) + { + y.reset(*x); + x.reset(); + } + else if ( !!x && !!y ) + { +// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC) +#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE + // allow for Koenig lookup + using std::swap ; +#endif + swap(*x,*y); + } +} + +} // namespace optional_detail + +template<class T> inline void swap ( optional<T>& x, optional<T>& y ) +{ + optional_detail::optional_swap(x,y); +} + + +} // namespace boost + +#endif + diff --git a/ext/boost/optional/optional_fwd.hpp b/ext/boost/optional/optional_fwd.hpp new file mode 100644 index 0000000000..2cf4fa654c --- /dev/null +++ b/ext/boost/optional/optional_fwd.hpp @@ -0,0 +1,22 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP + +namespace boost { + +template<class T> class optional ; + +} // namespace boost + +#endif + diff --git a/ext/boost/optional/optional_io.hpp b/ext/boost/optional/optional_io.hpp new file mode 100644 index 0000000000..ef1ecaf3a0 --- /dev/null +++ b/ext/boost/optional/optional_io.hpp @@ -0,0 +1,84 @@ +// Copyright (C) 2005, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP + +#if defined __GNUC__ +# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97) +# define BOOST_OPTIONAL_NO_TEMPLATED_STREAMS +# endif +#endif // __GNUC__ + +#if defined BOOST_OPTIONAL_NO_TEMPLATED_STREAMS +# include <iostream> +#else +# include <istream> +# include <ostream> +#endif + + +#include "boost/optional/optional.hpp" +#include "boost/utility/value_init.hpp" + +namespace boost +{ + +#if defined (BOOST_NO_TEMPLATED_STREAMS) +template<class T> +inline std::ostream& operator<<(std::ostream& out, optional<T> const& v) +#else +template<class CharType, class CharTrait, class T> +inline +std::basic_ostream<CharType, CharTrait>& +operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v) +#endif +{ + if ( out.good() ) + { + if ( !v ) + out << "--" ; + else out << ' ' << *v ; + } + + return out; +} + +#if defined (BOOST_NO_TEMPLATED_STREAMS) +template<class T> +inline std::istream& operator>>(std::istream& in, optional<T>& v) +#else +template<class CharType, class CharTrait, class T> +inline +std::basic_istream<CharType, CharTrait>& +operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v) +#endif +{ + if ( in.good() ) + { + int d = in.get(); + if ( d == ' ' ) + { + T x ; + in >> x; + v = x ; + } + else + v = optional<T>() ; + } + + return in; +} + +} // namespace boost + +#endif + diff --git a/ext/boost/regex/concepts.hpp b/ext/boost/regex/concepts.hpp new file mode 100644 index 0000000000..98fd59413f --- /dev/null +++ b/ext/boost/regex/concepts.hpp @@ -0,0 +1,906 @@ +/* + * + * 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 concepts.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression concepts. + */ + +#ifndef BOOST_REGEX_CONCEPTS_HPP_INCLUDED +#define BOOST_REGEX_CONCEPTS_HPP_INCLUDED + +#include <boost/concept_archetype.hpp> +#include <boost/concept_check.hpp> +#include <boost/type_traits/is_enum.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/static_assert.hpp> +#ifndef BOOST_TEST_TR1_REGEX +#include <boost/regex.hpp> +#endif +#include <bitset> +#include <vector> +#include <iostream> + +namespace boost{ + +// +// bitmask_archetype: +// this can be either an integer type, an enum, or a std::bitset, +// we use the latter as the architype as it offers the "strictest" +// of the possible interfaces: +// +typedef std::bitset<512> bitmask_archetype; +// +// char_architype: +// A strict model for the character type interface. +// +struct char_architype +{ + // default constructable: + char_architype(); + // copy constructable / assignable: + char_architype(const char_architype&); + char_architype& operator=(const char_architype&); + // constructable from an integral value: + char_architype(unsigned long val); + // comparable: + bool operator==(const char_architype&)const; + bool operator!=(const char_architype&)const; + bool operator<(const char_architype&)const; + bool operator<=(const char_architype&)const; + bool operator>=(const char_architype&)const; + bool operator>(const char_architype&)const; + // conversion to integral type: + operator long()const; +}; +// +// char_architype can not be used with basic_string: +// +} // namespace boost +namespace std{ + template<> struct char_traits<boost::char_architype> + { + // The intent is that this template is not instantiated, + // but this typedef gives us a chance of compilation in + // case it is: + typedef boost::char_architype char_type; + }; +} +namespace boost{ +// +// regex_traits_architype: +// A strict interpretation of the regular expression traits class requirements. +// +template <class charT> +struct regex_traits_architype +{ +public: + regex_traits_architype(); + typedef charT char_type; + // typedef std::size_t size_type; + typedef std::vector<char_type> string_type; + typedef copy_constructible_archetype<assignable_archetype<> > locale_type; + typedef bitmask_archetype char_class_type; + + static std::size_t length(const char_type* ) { return 0; } + + charT translate(charT ) const { return charT(); } + charT translate_nocase(charT ) const { return static_object<charT>::get(); } + + template <class ForwardIterator> + string_type transform(ForwardIterator , ForwardIterator ) const + { return static_object<string_type>::get(); } + template <class ForwardIterator> + string_type transform_primary(ForwardIterator , ForwardIterator ) const + { return static_object<string_type>::get(); } + + template <class ForwardIterator> + char_class_type lookup_classname(ForwardIterator , ForwardIterator ) const + { return static_object<char_class_type>::get(); } + template <class ForwardIterator> + string_type lookup_collatename(ForwardIterator , ForwardIterator ) const + { return static_object<string_type>::get(); } + + bool isctype(charT, char_class_type) const + { return false; } + int value(charT, int) const + { return 0; } + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return static_object<locale_type>::get(); } + +private: + // this type is not copyable: + regex_traits_architype(const regex_traits_architype&); + regex_traits_architype& operator=(const regex_traits_architype&); +}; + +// +// alter this to std::tr1, to test a std implementation: +// +#ifndef BOOST_TEST_TR1_REGEX +namespace global_regex_namespace = ::boost; +#else +namespace global_regex_namespace = ::std::tr1; +#endif + +template <class Bitmask> +struct BitmaskConcept +{ + void constraints() + { + function_requires<CopyConstructibleConcept<Bitmask> >(); + function_requires<AssignableConcept<Bitmask> >(); + + m_mask1 = m_mask2 | m_mask3; + m_mask1 = m_mask2 & m_mask3; + m_mask1 = m_mask2 ^ m_mask3; + + m_mask1 = ~m_mask2; + + m_mask1 |= m_mask2; + m_mask1 &= m_mask2; + m_mask1 ^= m_mask2; + } + Bitmask m_mask1, m_mask2, m_mask3; +}; + +template <class traits> +struct RegexTraitsConcept +{ + RegexTraitsConcept(); + // required typedefs: + typedef typename traits::char_type char_type; + // typedef typename traits::size_type size_type; + typedef typename traits::string_type string_type; + typedef typename traits::locale_type locale_type; + typedef typename traits::char_class_type char_class_type; + + void constraints() + { + //function_requires<UnsignedIntegerConcept<size_type> >(); + function_requires<RandomAccessContainerConcept<string_type> >(); + function_requires<DefaultConstructibleConcept<locale_type> >(); + function_requires<CopyConstructibleConcept<locale_type> >(); + function_requires<AssignableConcept<locale_type> >(); + function_requires<BitmaskConcept<char_class_type> >(); + + std::size_t n = traits::length(m_pointer); + ignore_unused_variable_warning(n); + + char_type c = m_ctraits.translate(m_char); + ignore_unused_variable_warning(c); + c = m_ctraits.translate_nocase(m_char); + + //string_type::foobar bar; + string_type s1 = m_ctraits.transform(m_pointer, m_pointer); + ignore_unused_variable_warning(s1); + + string_type s2 = m_ctraits.transform_primary(m_pointer, m_pointer); + ignore_unused_variable_warning(s2); + + char_class_type cc = m_ctraits.lookup_classname(m_pointer, m_pointer); + ignore_unused_variable_warning(cc); + + string_type s3 = m_ctraits.lookup_collatename(m_pointer, m_pointer); + ignore_unused_variable_warning(s3); + + bool b = m_ctraits.isctype(m_char, cc); + ignore_unused_variable_warning(b); + + int v = m_ctraits.value(m_char, 16); + ignore_unused_variable_warning(v); + + locale_type l(m_ctraits.getloc()); + m_traits.imbue(l); + ignore_unused_variable_warning(l); + } + traits m_traits; + const traits m_ctraits; + const char_type* m_pointer; + char_type m_char; +private: + RegexTraitsConcept& operator=(RegexTraitsConcept&); +}; + +// +// helper class to compute what traits class a regular expression type is using: +// +template <class Regex> +struct regex_traits_computer; + +template <class charT, class traits> +struct regex_traits_computer< global_regex_namespace::basic_regex<charT, traits> > +{ + typedef traits type; +}; + +// +// BaseRegexConcept does not test anything dependent on basic_string, +// in case our charT does not have an associated char_traits: +// +template <class Regex> +struct BaseRegexConcept +{ + typedef typename Regex::value_type value_type; + //typedef typename Regex::size_type size_type; + typedef typename Regex::flag_type flag_type; + typedef typename Regex::locale_type locale_type; + typedef input_iterator_archetype<value_type> input_iterator_type; + + // derived test types: + typedef const value_type* pointer_type; + typedef bidirectional_iterator_archetype<value_type> BidiIterator; + typedef global_regex_namespace::sub_match<BidiIterator> sub_match_type; + typedef global_regex_namespace::match_results<BidiIterator> match_results_type; + typedef output_iterator_archetype<value_type> OutIterator; + typedef typename regex_traits_computer<Regex>::type traits_type; + typedef global_regex_namespace::regex_iterator<BidiIterator, value_type, traits_type> regex_iterator_type; + typedef global_regex_namespace::regex_token_iterator<BidiIterator, value_type, traits_type> regex_token_iterator_type; + + void global_constraints() + { + // + // test non-template components: + // + function_requires<BitmaskConcept<global_regex_namespace::regex_constants::syntax_option_type> >(); + global_regex_namespace::regex_constants::syntax_option_type opts + = global_regex_namespace::regex_constants::icase + | global_regex_namespace::regex_constants::nosubs + | global_regex_namespace::regex_constants::optimize + | global_regex_namespace::regex_constants::collate + | global_regex_namespace::regex_constants::ECMAScript + | global_regex_namespace::regex_constants::basic + | global_regex_namespace::regex_constants::extended + | global_regex_namespace::regex_constants::awk + | global_regex_namespace::regex_constants::grep + | global_regex_namespace::regex_constants::egrep; + ignore_unused_variable_warning(opts); + + function_requires<BitmaskConcept<global_regex_namespace::regex_constants::match_flag_type> >(); + global_regex_namespace::regex_constants::match_flag_type mopts + = global_regex_namespace::regex_constants::match_default + | global_regex_namespace::regex_constants::match_not_bol + | global_regex_namespace::regex_constants::match_not_eol + | global_regex_namespace::regex_constants::match_not_bow + | global_regex_namespace::regex_constants::match_not_eow + | global_regex_namespace::regex_constants::match_any + | global_regex_namespace::regex_constants::match_not_null + | global_regex_namespace::regex_constants::match_continuous + | global_regex_namespace::regex_constants::match_prev_avail + | global_regex_namespace::regex_constants::format_default + | global_regex_namespace::regex_constants::format_sed + | global_regex_namespace::regex_constants::format_no_copy + | global_regex_namespace::regex_constants::format_first_only; + ignore_unused_variable_warning(mopts); + + BOOST_STATIC_ASSERT((::boost::is_enum<global_regex_namespace::regex_constants::error_type>::value)); + global_regex_namespace::regex_constants::error_type e1 = global_regex_namespace::regex_constants::error_collate; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_ctype; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_escape; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_backref; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_brack; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_paren; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_brace; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_badbrace; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_range; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_space; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_badrepeat; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_complexity; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_stack; + ignore_unused_variable_warning(e1); + + BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::runtime_error, global_regex_namespace::regex_error>::value )); + const global_regex_namespace::regex_error except(e1); + e1 = except.code(); + + typedef typename Regex::value_type value_type; + function_requires< RegexTraitsConcept<global_regex_namespace::regex_traits<char> > >(); + function_requires< BaseRegexConcept<global_regex_namespace::basic_regex<char> > >(); + } + void constraints() + { + global_constraints(); + + BOOST_STATIC_ASSERT((::boost::is_same< flag_type, global_regex_namespace::regex_constants::syntax_option_type>::value)); + flag_type opts + = Regex::icase + | Regex::nosubs + | Regex::optimize + | Regex::collate + | Regex::ECMAScript + | Regex::basic + | Regex::extended + | Regex::awk + | Regex::grep + | Regex::egrep; + ignore_unused_variable_warning(opts); + + function_requires<DefaultConstructibleConcept<Regex> >(); + function_requires<CopyConstructibleConcept<Regex> >(); + + // Regex constructors: + Regex e1(m_pointer); + ignore_unused_variable_warning(e1); + Regex e2(m_pointer, m_flags); + ignore_unused_variable_warning(e2); + Regex e3(m_pointer, m_size, m_flags); + ignore_unused_variable_warning(e3); + Regex e4(in1, in2); + ignore_unused_variable_warning(e4); + Regex e5(in1, in2, m_flags); + ignore_unused_variable_warning(e5); + + // assign etc: + Regex e; + e = m_pointer; + e = e1; + e.assign(e1); + e.assign(m_pointer); + e.assign(m_pointer, m_flags); + e.assign(m_pointer, m_size, m_flags); + e.assign(in1, in2); + e.assign(in1, in2, m_flags); + + // access: + const Regex ce; + unsigned i = ce.mark_count(); + ignore_unused_variable_warning(i); + m_flags = ce.flags(); + e.imbue(ce.getloc()); + e.swap(e1); + + global_regex_namespace::swap(e, e1); + + // sub_match: + BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::pair<BidiIterator, BidiIterator>, sub_match_type>::value)); + typedef typename sub_match_type::value_type sub_value_type; + typedef typename sub_match_type::difference_type sub_diff_type; + typedef typename sub_match_type::iterator sub_iter_type; + BOOST_STATIC_ASSERT((::boost::is_same<sub_value_type, value_type>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<sub_iter_type, BidiIterator>::value)); + bool b = m_sub.matched; + ignore_unused_variable_warning(b); + BidiIterator bi = m_sub.first; + ignore_unused_variable_warning(bi); + bi = m_sub.second; + ignore_unused_variable_warning(bi); + sub_diff_type diff = m_sub.length(); + ignore_unused_variable_warning(diff); + // match_results tests: + typedef typename match_results_type::value_type mr_value_type; + typedef typename match_results_type::const_reference mr_const_reference; + typedef typename match_results_type::reference mr_reference; + typedef typename match_results_type::const_iterator mr_const_iterator; + typedef typename match_results_type::iterator mr_iterator; + typedef typename match_results_type::difference_type mr_difference_type; + typedef typename match_results_type::size_type mr_size_type; + typedef typename match_results_type::allocator_type mr_allocator_type; + typedef typename match_results_type::char_type mr_char_type; + typedef typename match_results_type::string_type mr_string_type; + + match_results_type m1; + mr_allocator_type at; + match_results_type m2(at); + match_results_type m3(m1); + m1 = m2; + + int ival = 0; + + mr_size_type mrs = m_cresults.size(); + ignore_unused_variable_warning(mrs); + mrs = m_cresults.max_size(); + ignore_unused_variable_warning(mrs); + b = m_cresults.empty(); + ignore_unused_variable_warning(b); + mr_difference_type mrd = m_cresults.length(); + ignore_unused_variable_warning(mrd); + mrd = m_cresults.length(ival); + ignore_unused_variable_warning(mrd); + mrd = m_cresults.position(); + ignore_unused_variable_warning(mrd); + mrd = m_cresults.position(mrs); + ignore_unused_variable_warning(mrd); + + mr_const_reference mrcr = m_cresults[ival]; + ignore_unused_variable_warning(mrcr); + mr_const_reference mrcr2 = m_cresults.prefix(); + ignore_unused_variable_warning(mrcr2); + mr_const_reference mrcr3 = m_cresults.suffix(); + ignore_unused_variable_warning(mrcr3); + mr_const_iterator mrci = m_cresults.begin(); + ignore_unused_variable_warning(mrci); + mrci = m_cresults.end(); + ignore_unused_variable_warning(mrci); + + mr_allocator_type at2 = m_cresults.get_allocator(); + m_results.swap(m_results); + global_regex_namespace::swap(m_results, m_results); + + // regex_match: + b = global_regex_namespace::regex_match(m_in, m_in, m_results, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_in, m_in, m_results, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_in, m_in, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_in, m_in, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, m_pmatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, m_pmatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, e, m_mft); + ignore_unused_variable_warning(b); + // regex_search: + b = global_regex_namespace::regex_search(m_in, m_in, m_results, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_in, m_in, m_results, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_in, m_in, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_in, m_in, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, m_pmatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, m_pmatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, e, m_mft); + ignore_unused_variable_warning(b); + + // regex_iterator: + typedef typename regex_iterator_type::regex_type rit_regex_type; + typedef typename regex_iterator_type::value_type rit_value_type; + typedef typename regex_iterator_type::difference_type rit_difference_type; + typedef typename regex_iterator_type::pointer rit_pointer; + typedef typename regex_iterator_type::reference rit_reference; + typedef typename regex_iterator_type::iterator_category rit_iterator_category; + BOOST_STATIC_ASSERT((::boost::is_same<rit_regex_type, Regex>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rit_value_type, match_results_type>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rit_difference_type, std::ptrdiff_t>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rit_pointer, const match_results_type*>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rit_reference, const match_results_type&>::value)); + BOOST_STATIC_ASSERT((::boost::is_convertible<rit_iterator_category*, std::forward_iterator_tag*>::value)); + // this takes care of most of the checks needed: + function_requires<ForwardIteratorConcept<regex_iterator_type> >(); + regex_iterator_type iter1(m_in, m_in, e); + ignore_unused_variable_warning(iter1); + regex_iterator_type iter2(m_in, m_in, e, m_mft); + ignore_unused_variable_warning(iter2); + + // regex_token_iterator: + typedef typename regex_token_iterator_type::regex_type rtit_regex_type; + typedef typename regex_token_iterator_type::value_type rtit_value_type; + typedef typename regex_token_iterator_type::difference_type rtit_difference_type; + typedef typename regex_token_iterator_type::pointer rtit_pointer; + typedef typename regex_token_iterator_type::reference rtit_reference; + typedef typename regex_token_iterator_type::iterator_category rtit_iterator_category; + BOOST_STATIC_ASSERT((::boost::is_same<rtit_regex_type, Regex>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rtit_value_type, sub_match_type>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rtit_difference_type, std::ptrdiff_t>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rtit_pointer, const sub_match_type*>::value)); + BOOST_STATIC_ASSERT((::boost::is_same<rtit_reference, const sub_match_type&>::value)); + BOOST_STATIC_ASSERT((::boost::is_convertible<rtit_iterator_category*, std::forward_iterator_tag*>::value)); + // this takes care of most of the checks needed: + function_requires<ForwardIteratorConcept<regex_token_iterator_type> >(); + regex_token_iterator_type ti1(m_in, m_in, e); + ignore_unused_variable_warning(ti1); + regex_token_iterator_type ti2(m_in, m_in, e, 0); + ignore_unused_variable_warning(ti2); + regex_token_iterator_type ti3(m_in, m_in, e, 0, m_mft); + ignore_unused_variable_warning(ti3); + std::vector<int> subs; + regex_token_iterator_type ti4(m_in, m_in, e, subs); + ignore_unused_variable_warning(ti4); + regex_token_iterator_type ti5(m_in, m_in, e, subs, m_mft); + ignore_unused_variable_warning(ti5); + static const int i_array[3] = { 1, 2, 3, }; + regex_token_iterator_type ti6(m_in, m_in, e, i_array); + ignore_unused_variable_warning(ti6); + regex_token_iterator_type ti7(m_in, m_in, e, i_array, m_mft); + ignore_unused_variable_warning(ti7); + } + + pointer_type m_pointer; + flag_type m_flags; + std::size_t m_size; + input_iterator_type in1, in2; + const sub_match_type m_sub; + const value_type m_char; + match_results_type m_results; + const match_results_type m_cresults; + OutIterator m_out; + BidiIterator m_in; + global_regex_namespace::regex_constants::match_flag_type m_mft; + global_regex_namespace::match_results<pointer_type> m_pmatch; + + BaseRegexConcept(); + BaseRegexConcept(const BaseRegexConcept&); + BaseRegexConcept& operator=(const BaseRegexConcept&); +}; + +// +// RegexConcept: +// Test every interface in the std: +// +template <class Regex> +struct RegexConcept +{ + typedef typename Regex::value_type value_type; + //typedef typename Regex::size_type size_type; + typedef typename Regex::flag_type flag_type; + typedef typename Regex::locale_type locale_type; + + // derived test types: + typedef const value_type* pointer_type; + typedef std::basic_string<value_type> string_type; + typedef boost::bidirectional_iterator_archetype<value_type> BidiIterator; + typedef global_regex_namespace::sub_match<BidiIterator> sub_match_type; + typedef global_regex_namespace::match_results<BidiIterator> match_results_type; + typedef output_iterator_archetype<value_type> OutIterator; + + + void constraints() + { + function_requires<BaseRegexConcept<Regex> >(); + // string based construct: + Regex e1(m_string); + ignore_unused_variable_warning(e1); + Regex e2(m_string, m_flags); + ignore_unused_variable_warning(e2); + + // assign etc: + Regex e; + e = m_string; + e.assign(m_string); + e.assign(m_string, m_flags); + + // sub_match: + string_type s(m_sub); + ignore_unused_variable_warning(s); + s = m_sub.str(); + ignore_unused_variable_warning(s); + int i = m_sub.compare(m_string); + ignore_unused_variable_warning(i); + + int i2 = m_sub.compare(m_sub); + ignore_unused_variable_warning(i2); + i2 = m_sub.compare(m_pointer); + ignore_unused_variable_warning(i2); + + bool b = m_sub == m_sub; + ignore_unused_variable_warning(b); + b = m_sub != m_sub; + ignore_unused_variable_warning(b); + b = m_sub <= m_sub; + ignore_unused_variable_warning(b); + b = m_sub <= m_sub; + ignore_unused_variable_warning(b); + b = m_sub > m_sub; + ignore_unused_variable_warning(b); + b = m_sub >= m_sub; + ignore_unused_variable_warning(b); + + b = m_sub == m_pointer; + ignore_unused_variable_warning(b); + b = m_sub != m_pointer; + ignore_unused_variable_warning(b); + b = m_sub <= m_pointer; + ignore_unused_variable_warning(b); + b = m_sub <= m_pointer; + ignore_unused_variable_warning(b); + b = m_sub > m_pointer; + ignore_unused_variable_warning(b); + b = m_sub >= m_pointer; + ignore_unused_variable_warning(b); + + b = m_pointer == m_sub; + ignore_unused_variable_warning(b); + b = m_pointer != m_sub; + ignore_unused_variable_warning(b); + b = m_pointer <= m_sub; + ignore_unused_variable_warning(b); + b = m_pointer <= m_sub; + ignore_unused_variable_warning(b); + b = m_pointer > m_sub; + ignore_unused_variable_warning(b); + b = m_pointer >= m_sub; + ignore_unused_variable_warning(b); + + b = m_sub == m_char; + ignore_unused_variable_warning(b); + b = m_sub != m_char; + ignore_unused_variable_warning(b); + b = m_sub <= m_char; + ignore_unused_variable_warning(b); + b = m_sub <= m_char; + ignore_unused_variable_warning(b); + b = m_sub > m_char; + ignore_unused_variable_warning(b); + b = m_sub >= m_char; + ignore_unused_variable_warning(b); + + b = m_char == m_sub; + ignore_unused_variable_warning(b); + b = m_char != m_sub; + ignore_unused_variable_warning(b); + b = m_char <= m_sub; + ignore_unused_variable_warning(b); + b = m_char <= m_sub; + ignore_unused_variable_warning(b); + b = m_char > m_sub; + ignore_unused_variable_warning(b); + b = m_char >= m_sub; + ignore_unused_variable_warning(b); + + b = m_sub == m_string; + ignore_unused_variable_warning(b); + b = m_sub != m_string; + ignore_unused_variable_warning(b); + b = m_sub <= m_string; + ignore_unused_variable_warning(b); + b = m_sub <= m_string; + ignore_unused_variable_warning(b); + b = m_sub > m_string; + ignore_unused_variable_warning(b); + b = m_sub >= m_string; + ignore_unused_variable_warning(b); + + b = m_string == m_sub; + ignore_unused_variable_warning(b); + b = m_string != m_sub; + ignore_unused_variable_warning(b); + b = m_string <= m_sub; + ignore_unused_variable_warning(b); + b = m_string <= m_sub; + ignore_unused_variable_warning(b); + b = m_string > m_sub; + ignore_unused_variable_warning(b); + b = m_string >= m_sub; + ignore_unused_variable_warning(b); + + // match results: + m_string = m_results.str(); + ignore_unused_variable_warning(m_string); + m_string = m_results.str(0); + ignore_unused_variable_warning(m_string); + m_out = m_cresults.format(m_out, m_string); + m_out = m_cresults.format(m_out, m_string, m_mft); + m_string = m_cresults.format(m_string); + ignore_unused_variable_warning(m_string); + m_string = m_cresults.format(m_string, m_mft); + ignore_unused_variable_warning(m_string); + + // regex_match: + b = global_regex_namespace::regex_match(m_string, m_smatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_string, m_smatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_string, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_string, e, m_mft); + ignore_unused_variable_warning(b); + + // regex_search: + b = global_regex_namespace::regex_search(m_string, m_smatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_string, m_smatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_string, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_string, e, m_mft); + ignore_unused_variable_warning(b); + + // regex_replace: + m_out = global_regex_namespace::regex_replace(m_out, m_in, m_in, e, m_string, m_mft); + m_out = global_regex_namespace::regex_replace(m_out, m_in, m_in, e, m_string); + m_string = global_regex_namespace::regex_replace(m_string, e, m_string, m_mft); + ignore_unused_variable_warning(m_string); + m_string = global_regex_namespace::regex_replace(m_string, e, m_string); + ignore_unused_variable_warning(m_string); + + } + + flag_type m_flags; + string_type m_string; + const sub_match_type m_sub; + match_results_type m_results; + pointer_type m_pointer; + value_type m_char; + const match_results_type m_cresults; + OutIterator m_out; + BidiIterator m_in; + global_regex_namespace::regex_constants::match_flag_type m_mft; + global_regex_namespace::match_results<typename string_type::const_iterator> m_smatch; + + RegexConcept(); + RegexConcept(const RegexConcept&); + RegexConcept& operator=(const RegexConcept&); +}; + +#ifndef BOOST_REGEX_TEST_STD +// +// BoostRegexConcept: +// Test every interface in the Boost implementation: +// +template <class Regex> +struct BoostRegexConcept +{ + typedef typename Regex::value_type value_type; + typedef typename Regex::size_type size_type; + typedef typename Regex::flag_type flag_type; + typedef typename Regex::locale_type locale_type; + + // derived test types: + typedef const value_type* pointer_type; + typedef std::basic_string<value_type> string_type; + typedef typename Regex::const_iterator const_iterator; + typedef bidirectional_iterator_archetype<value_type> BidiIterator; + typedef global_regex_namespace::sub_match<BidiIterator> sub_match_type; + typedef global_regex_namespace::match_results<BidiIterator> match_results_type; + + void constraints() + { + global_regex_namespace::regex_constants::match_flag_type mopts + = global_regex_namespace::regex_constants::match_default + | global_regex_namespace::regex_constants::match_not_bol + | global_regex_namespace::regex_constants::match_not_eol + | global_regex_namespace::regex_constants::match_not_bow + | global_regex_namespace::regex_constants::match_not_eow + | global_regex_namespace::regex_constants::match_any + | global_regex_namespace::regex_constants::match_not_null + | global_regex_namespace::regex_constants::match_continuous + | global_regex_namespace::regex_constants::match_partial + | global_regex_namespace::regex_constants::match_prev_avail + | global_regex_namespace::regex_constants::format_default + | global_regex_namespace::regex_constants::format_sed + | global_regex_namespace::regex_constants::format_perl + | global_regex_namespace::regex_constants::format_no_copy + | global_regex_namespace::regex_constants::format_first_only; + + (void)mopts; + + function_requires<RegexConcept<Regex> >(); + const global_regex_namespace::regex_error except(global_regex_namespace::regex_constants::error_collate); + std::ptrdiff_t pt = except.position(); + ignore_unused_variable_warning(pt); + const Regex ce, ce2; +#ifndef BOOST_NO_STD_LOCALE + m_stream << ce; +#endif + unsigned i = ce.error_code(); + ignore_unused_variable_warning(i); + pointer_type p = ce.expression(); + ignore_unused_variable_warning(p); + int i2 = ce.compare(ce2); + ignore_unused_variable_warning(i2); + bool b = ce == ce2; + ignore_unused_variable_warning(b); + b = ce.empty(); + ignore_unused_variable_warning(b); + b = ce != ce2; + ignore_unused_variable_warning(b); + b = ce < ce2; + ignore_unused_variable_warning(b); + b = ce > ce2; + ignore_unused_variable_warning(b); + b = ce <= ce2; + ignore_unused_variable_warning(b); + b = ce >= ce2; + ignore_unused_variable_warning(b); + i = ce.status(); + ignore_unused_variable_warning(i); + size_type s = ce.max_size(); + ignore_unused_variable_warning(s); + s = ce.size(); + ignore_unused_variable_warning(s); + const_iterator pi = ce.begin(); + ignore_unused_variable_warning(pi); + pi = ce.end(); + ignore_unused_variable_warning(pi); + string_type s2 = ce.str(); + ignore_unused_variable_warning(s2); + + m_string = m_sub + m_sub; + ignore_unused_variable_warning(m_string); + m_string = m_sub + m_pointer; + ignore_unused_variable_warning(m_string); + m_string = m_pointer + m_sub; + ignore_unused_variable_warning(m_string); + m_string = m_sub + m_string; + ignore_unused_variable_warning(m_string); + m_string = m_string + m_sub; + ignore_unused_variable_warning(m_string); + m_string = m_sub + m_char; + ignore_unused_variable_warning(m_string); + m_string = m_char + m_sub; + ignore_unused_variable_warning(m_string); + + // Named sub-expressions: + m_sub = m_cresults[&m_char]; + ignore_unused_variable_warning(m_sub); + m_sub = m_cresults[m_string]; + ignore_unused_variable_warning(m_sub); + m_sub = m_cresults[""]; + ignore_unused_variable_warning(m_sub); + m_sub = m_cresults[std::string("")]; + ignore_unused_variable_warning(m_sub); + m_string = m_cresults.str(&m_char); + ignore_unused_variable_warning(m_string); + m_string = m_cresults.str(m_string); + ignore_unused_variable_warning(m_string); + m_string = m_cresults.str(""); + ignore_unused_variable_warning(m_string); + m_string = m_cresults.str(std::string("")); + ignore_unused_variable_warning(m_string); + + typename match_results_type::difference_type diff; + diff = m_cresults.length(&m_char); + ignore_unused_variable_warning(diff); + diff = m_cresults.length(m_string); + ignore_unused_variable_warning(diff); + diff = m_cresults.length(""); + ignore_unused_variable_warning(diff); + diff = m_cresults.length(std::string("")); + ignore_unused_variable_warning(diff); + diff = m_cresults.position(&m_char); + ignore_unused_variable_warning(diff); + diff = m_cresults.position(m_string); + ignore_unused_variable_warning(diff); + diff = m_cresults.position(""); + ignore_unused_variable_warning(diff); + diff = m_cresults.position(std::string("")); + ignore_unused_variable_warning(diff); + +#ifndef BOOST_NO_STD_LOCALE + m_stream << m_sub; + m_stream << m_cresults; +#endif + } + + std::basic_ostream<value_type> m_stream; + sub_match_type m_sub; + pointer_type m_pointer; + string_type m_string; + const value_type m_char; + match_results_type m_results; + const match_results_type m_cresults; + + BoostRegexConcept(); + BoostRegexConcept(const BoostRegexConcept&); + BoostRegexConcept& operator=(const BoostRegexConcept&); +}; + +#endif // BOOST_REGEX_TEST_STD + +} + +#endif diff --git a/ext/boost/regex/config.hpp b/ext/boost/regex/config.hpp new file mode 100644 index 0000000000..8306f3ff9a --- /dev/null +++ b/ext/boost/regex/config.hpp @@ -0,0 +1,417 @@ +/* + * + * 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 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> + +#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 + +/* + * 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 + +/* + * 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(BOOST_HAS_DIRENT_H) && !(defined(_WIN32) && !defined(BOOST_REGEX_NO_W32)) +# define BOOST_REGEX_NO_FILEITER +#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. + */ +#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) +# define BOOST_REGEX_HAS_OTHER_WCHAR_T +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251 4231 4660) +# 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: + * + ****************************************************************************/ + +#if defined(BOOST_HAS_DECLSPEC) && (defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_REGEX_STATIC_LINK) +# if defined(BOOST_REGEX_SOURCE) +# define BOOST_REGEX_DECL __declspec(dllexport) +# define BOOST_REGEX_BUILD_DLL +# else +# define BOOST_REGEX_DECL __declspec(dllimport) +# endif +#endif + +#ifndef BOOST_REGEX_DECL +# 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) && (BOOST_MSVC >= 1200) && defined(_MSC_EXTENSIONS) +#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED) +# 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 + +/* 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) +# 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 re_detail{ + +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 re_detail{ + +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 + + + + diff --git a/ext/boost/regex/config/borland.hpp b/ext/boost/regex/config/borland.hpp new file mode 100644 index 0000000000..51c2126b8e --- /dev/null +++ b/ext/boost/regex/config/borland.hpp @@ -0,0 +1,72 @@ +/* + * + * 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 + + diff --git a/ext/boost/regex/config/cwchar.hpp b/ext/boost/regex/config/cwchar.hpp new file mode 100644 index 0000000000..a55089d0ab --- /dev/null +++ b/ext/boost/regex/config/cwchar.hpp @@ -0,0 +1,207 @@ +/* + * + * 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 + diff --git a/ext/boost/regex/icu.hpp b/ext/boost/regex/icu.hpp new file mode 100644 index 0000000000..247155724e --- /dev/null +++ b/ext/boost/regex/icu.hpp @@ -0,0 +1,1021 @@ +/* + * + * 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> + + +namespace boost{ + +namespace re_detail{ + +// +// 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(re_detail::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)) ? 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, + 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::re_detail::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 re_detail{ + +#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), conv_type(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), conv_type(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), b(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), b(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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 UnicodeString& s, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl) +{ + return re_detail::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 re_detail{ +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) + { + out.set_first(in[i].first.base(), i); + out.set_second(in[i].second.base(), i); + } + } +} + +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), conv_type(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), conv_type(last), what, e, flags); + // copy results across to m: + if(result) copy_results(m, what); + return result; +} +} // namespace re_detail + +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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 UnicodeString& s, + match_results<const UChar*>& m, + const u32regex& e, + match_flag_type flags = match_default) +{ + return re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 UnicodeString& s, + const u32regex& e, + match_flag_type flags = match_default) +{ + match_results<const UChar*> m; + return re_detail::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 re_detail{ +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), conv_type(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), conv_type(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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 UnicodeString& s, + match_results<const UChar*>& m, + const u32regex& e, + match_flag_type flags = match_default) +{ + return re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 re_detail::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 UnicodeString& s, + const u32regex& e, + match_flag_type flags = match_default) +{ + match_results<const UChar*> m; + return re_detail::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 re_detail{ +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), boost::u8_to_u32_iterator<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), boost::u16_to_u32_iterator<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*) +{ + 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), boost::u8_to_u32_iterator<const charT*>(p+std::strlen((const char*)p))); +} +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*) +{ + 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), boost::u16_to_u32_iterator<const charT*>(p+u_strlen((const UChar*)p))); +} +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 = re_detail::copy(in.first, in.second, out); + } + else + { + I1 last_m = in.first; + while(i != j) + { + if(!(flags & regex_constants::format_no_copy)) + out = re_detail::copy(i->prefix().first, i->prefix().second, out); + if(f.size()) + out = ::boost::re_detail::regex_format_imp(out, *i, &*f.begin(), &*f.begin() + f.size(), flags, e.get_traits()); + else + out = ::boost::re_detail::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 = re_detail::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(); +} +} // re_detail + +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 re_detail::extract_output_base +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + <OutputIterator> +#endif + ( + re_detail::do_regex_replace( + re_detail::make_utf32_out(out, static_cast<mpl::int_<sizeof(*first)> const*>(0)), + re_detail::make_utf32_seq(first, last, static_cast<mpl::int_<sizeof(*first)> const*>(0)), + e, + re_detail::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 re_detail::extract_output_base +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + <OutputIterator> +#endif + ( + re_detail::do_regex_replace( + re_detail::make_utf32_out(out, static_cast<mpl::int_<sizeof(*first)> const*>(0)), + re_detail::make_utf32_seq(first, last, static_cast<mpl::int_<sizeof(*first)> const*>(0)), + e, + re_detail::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 UnicodeString& fmt, + match_flag_type flags = match_default) +{ + return re_detail::extract_output_base +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + <OutputIterator> +#endif + ( + re_detail::do_regex_replace( + re_detail::make_utf32_out(out, static_cast<mpl::int_<sizeof(*first)> const*>(0)), + re_detail::make_utf32_seq(first, last, static_cast<mpl::int_<sizeof(*first)> const*>(0)), + e, + re_detail::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; + re_detail::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; + re_detail::string_out_iterator<std::basic_string<charT> > i(result); + u32regex_replace(i, s.begin(), s.end(), e, fmt.c_str(), flags); + return result; +} + +namespace re_detail{ + +class unicode_string_out_iterator +{ + UnicodeString* out; +public: + unicode_string_out_iterator(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 UnicodeString u32regex_replace(const UnicodeString& s, + const u32regex& e, + const UChar* fmt, + match_flag_type flags = match_default) +{ + UnicodeString result; + re_detail::unicode_string_out_iterator i(result); + u32regex_replace(i, s.getBuffer(), s.getBuffer()+s.length(), e, fmt, flags); + return result; +} + +inline UnicodeString u32regex_replace(const UnicodeString& s, + const u32regex& e, + const UnicodeString& fmt, + match_flag_type flags = match_default) +{ + UnicodeString result; + re_detail::unicode_string_out_iterator i(result); + re_detail::do_regex_replace( + re_detail::make_utf32_out(i, static_cast<mpl::int_<2> const*>(0)), + re_detail::make_utf32_seq(s.getBuffer(), s.getBuffer()+s.length(), static_cast<mpl::int_<2> const*>(0)), + e, + re_detail::make_utf32_seq(fmt.getBuffer(), fmt.getBuffer() + fmt.length(), static_cast<mpl::int_<2> const*>(0)), + flags); + return result; +} + +} // namespace boost. + +#include <boost/regex/v4/u32regex_iterator.hpp> +#include <boost/regex/v4/u32regex_token_iterator.hpp> + +#endif diff --git a/ext/boost/regex/mfc.hpp b/ext/boost/regex/mfc.hpp new file mode 100644 index 0000000000..02502f9504 --- /dev/null +++ b/ext/boost/regex/mfc.hpp @@ -0,0 +1,190 @@ +/* + * + * 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 mfc.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Overloads and helpers for using MFC/ATL string types with Boost.Regex. + */ + +#ifndef BOOST_REGEX_MFC_HPP +#define BOOST_REGEX_MFC_HPP + +#include <atlsimpstr.h> +#include <boost/regex.hpp> + +namespace boost{ + +// +// define the types used for TCHAR's: +typedef basic_regex<TCHAR> tregex; +typedef match_results<TCHAR const*> tmatch; +typedef regex_iterator<TCHAR const*> tregex_iterator; +typedef regex_token_iterator<TCHAR const*> tregex_token_iterator; + +#if _MSC_VER >= 1310 +#define SIMPLE_STRING_PARAM class B, bool b +#define SIMPLE_STRING_ARG_LIST B, b +#else +#define SIMPLE_STRING_PARAM class B +#define SIMPLE_STRING_ARG_LIST B +#endif + +// +// define regex creation functions: +// +template <SIMPLE_STRING_PARAM> +inline basic_regex<B> +make_regex(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, ::boost::regex_constants::syntax_option_type f = boost::regex_constants::normal) +{ + basic_regex<B> result(s.GetString(), s.GetString() + s.GetLength(), f); + return result; +} +// +// regex_match overloads: +// +template <SIMPLE_STRING_PARAM, class A, class T> +inline bool regex_match(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, + match_results<const B*, A>& what, + const basic_regex<B, T>& e, + boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + return ::boost::regex_match(s.GetString(), + s.GetString() + s.GetLength(), + what, + e, + f); +} + +template <SIMPLE_STRING_PARAM, class T> +inline bool regex_match(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, + const basic_regex<B, T>& e, + boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + return ::boost::regex_match(s.GetString(), + s.GetString() + s.GetLength(), + e, + f); +} +// +// regex_search overloads: +// +template <SIMPLE_STRING_PARAM, class A, class T> +inline bool regex_search(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, + match_results<const B*, A>& what, + const basic_regex<B, T>& e, + boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + return ::boost::regex_search(s.GetString(), + s.GetString() + s.GetLength(), + what, + e, + f); +} + +template <SIMPLE_STRING_PARAM, class T> +inline bool regex_search(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, + const basic_regex<B, T>& e, + boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + return ::boost::regex_search(s.GetString(), + s.GetString() + s.GetLength(), + e, + f); +} +// +// regex_iterator creation: +// +template <SIMPLE_STRING_PARAM> +inline regex_iterator<B const*> +make_regex_iterator(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, const basic_regex<B>& e, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + regex_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, f); + return result; +} + +template <SIMPLE_STRING_PARAM> +inline regex_token_iterator<B const*> + make_regex_token_iterator(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, const basic_regex<B>& e, int sub = 0, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, sub, f); + return result; +} + +template <SIMPLE_STRING_PARAM> +inline regex_token_iterator<B const*> +make_regex_token_iterator(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, const basic_regex<B>& e, const std::vector<int>& subs, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, subs, f); + return result; +} + +template <SIMPLE_STRING_PARAM, std::size_t N> +inline regex_token_iterator<B const*> +make_regex_token_iterator(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, const basic_regex<B>& e, const int (& subs)[N], ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default) +{ + regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, subs, f); + return result; +} + +template <class OutputIterator, class BidirectionalIterator, class traits, + SIMPLE_STRING_PARAM> +OutputIterator regex_replace(OutputIterator out, + BidirectionalIterator first, + BidirectionalIterator last, + const basic_regex<B, traits>& e, + const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& fmt, + match_flag_type flags = match_default) +{ + return ::boost::regex_replace(out, first, last, e, fmt.GetString(), flags); +} + +namespace re_detail{ + +template <SIMPLE_STRING_PARAM> +class mfc_string_out_iterator +{ + ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>* out; +public: + mfc_string_out_iterator(ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s) : out(&s) {} + mfc_string_out_iterator& operator++() { return *this; } + mfc_string_out_iterator& operator++(int) { return *this; } + mfc_string_out_iterator& operator*() { return *this; } + mfc_string_out_iterator& operator=(B v) + { + out->AppendChar(v); + return *this; + } + typedef std::ptrdiff_t difference_type; + typedef B value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::output_iterator_tag iterator_category; +}; + +} + +template <class traits, SIMPLE_STRING_PARAM> +ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST> regex_replace(const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& s, + const basic_regex<B, traits>& e, + const ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST>& fmt, + match_flag_type flags = match_default) +{ + ATL::CSimpleStringT<SIMPLE_STRING_ARG_LIST> result(s.GetManager()); + re_detail::mfc_string_out_iterator<SIMPLE_STRING_ARG_LIST> i(result); + regex_replace(i, s.GetString(), s.GetString() + s.GetLength(), e, fmt.GetString(), flags); + return result; +} + +} // namespace boost. + +#endif diff --git a/ext/boost/regex/pattern_except.hpp b/ext/boost/regex/pattern_except.hpp new file mode 100644 index 0000000000..57ea14c256 --- /dev/null +++ b/ext/boost/regex/pattern_except.hpp @@ -0,0 +1,100 @@ +/* + * + * 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 re_detail{ + +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::re_detail::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 + + + diff --git a/ext/boost/regex/pending/object_cache.hpp b/ext/boost/regex/pending/object_cache.hpp new file mode 100644 index 0000000000..2a7e00bc0a --- /dev/null +++ b/ext/boost/regex/pending/object_cache.hpp @@ -0,0 +1,163 @@ +/* + * + * 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 max_cache_size); + +private: + static boost::shared_ptr<Object const> do_get(const Key& k, size_type 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 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 const> 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 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 > 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 diff --git a/ext/boost/regex/pending/static_mutex.hpp b/ext/boost/regex/pending/static_mutex.hpp new file mode 100644 index 0000000000..218169c3c8 --- /dev/null +++ b/ext/boost/regex/pending/static_mutex.hpp @@ -0,0 +1,184 @@ +/* + * + * 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 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(); + 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; +}; + + +} // 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. +// +// Since this preprocessor path is almost never taken, we hide these header +// dependencies so that build tools don't find them. +// +#define B1 <boost/thread/once.hpp> +#define B2 <boost/thread/recursive_mutex.hpp> +#include B1 +#include B2 +#undef B1 +#undef B2 + +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 diff --git a/ext/boost/regex/pending/unicode_iterator.hpp b/ext/boost/regex/pending/unicode_iterator.hpp new file mode 100644 index 0000000000..657ca0a4cf --- /dev/null +++ b/ext/boost/regex/pending/unicode_iterator.hpp @@ -0,0 +1,692 @@ +/* + * + * 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 unicode_iterator.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Iterator adapters for converting between different Unicode encodings. + */ + +/**************************************************************************** + +Contents: +~~~~~~~~~ + +1) Read Only, Input Adapters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +template <class BaseIterator, class U8Type = ::boost::uint8_t> +class u32_to_u8_iterator; + +Adapts sequence of UTF-32 code points to "look like" a sequence of UTF-8. + +template <class BaseIterator, class U32Type = ::boost::uint32_t> +class u8_to_u32_iterator; + +Adapts sequence of UTF-8 code points to "look like" a sequence of UTF-32. + +template <class BaseIterator, class U16Type = ::boost::uint16_t> +class u32_to_u16_iterator; + +Adapts sequence of UTF-32 code points to "look like" a sequence of UTF-16. + +template <class BaseIterator, class U32Type = ::boost::uint32_t> +class u16_to_u32_iterator; + +Adapts sequence of UTF-16 code points to "look like" a sequence of UTF-32. + +2) Single pass output iterator adapters: + +template <class BaseIterator> +class utf8_output_iterator; + +Accepts UTF-32 code points and forwards them on as UTF-8 code points. + +template <class BaseIterator> +class utf16_output_iterator; + +Accepts UTF-32 code points and forwards them on as UTF-16 code points. + +****************************************************************************/ + +#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 <boost/throw_exception.hpp> +#include <stdexcept> +#ifndef BOOST_NO_STD_LOCALE +#include <sstream> +#include <ios> +#endif +#include <limits.h> // CHAR_BIT + +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; +} + +inline unsigned utf8_byte_count(boost::uint8_t c) +{ + // if the most significant bit with a zero in it is in position + // 8-N then there are N bytes in this UTF-8 sequence: + boost::uint8_t mask = 0x80u; + unsigned result = 0; + while(c & mask) + { + ++result; + mask >>= 1; + } + return (result == 0) ? 1 : ((result > 4) ? 4 : result); +} + +inline unsigned utf8_trailing_byte_count(boost::uint8_t c) +{ + return utf8_byte_count(c) - 1; +} + +inline void invalid_utf32_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); +} + + +} // namespace detail + +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>, U16Type, std::bidirectional_iterator_tag, const U16Type> base_type; + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + 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); +#endif + +public: + typename base_type::reference + dereference()const + { + if(m_current == 2) + extract_current(); + return m_values[m_current]; + } + bool equal(const u32_to_u16_iterator& that)const + { + if(m_position == that.m_position) + { + // Both m_currents must be equal, or both even + // this is the same as saying their sum must be even: + return (m_current + that.m_current) & 1u ? false : 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[0] = 0; + m_values[1] = 0; + m_values[2] = 0; + } + u32_to_u16_iterator(BaseIterator b) : m_position(b), m_current(2) + { + m_values[0] = 0; + m_values[1] = 0; + m_values[2] = 0; + } +private: + + void extract_current()const + { + // begin by checking for a code point out of range: + ::boost::uint32_t v = *m_position; + if(v >= 0x10000u) + { + if(v > 0x10FFFFu) + detail::invalid_utf32_code_point(*m_position); + // split into two surrogates: + 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])) + detail::invalid_utf32_code_point(*m_position); + } + } + BaseIterator m_position; + mutable U16Type m_values[3]; + mutable 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>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type; + // special values for pending iterator reads: + BOOST_STATIC_CONSTANT(U32Type, pending_read = 0xffffffffu); + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + 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); +#endif + +public: + typename base_type::reference + dereference()const + { + if(m_value == pending_read) + 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() + { + m_value = pending_read; + } + u16_to_u32_iterator(BaseIterator b) : m_position(b) + { + m_value = pending_read; + } +private: + static 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()const + { + 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: + BaseIterator next(m_position); + ::boost::uint16_t t = *++next; + if((t & 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); + } + // 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; + mutable U32Type m_value; +}; + +template <class BaseIterator, class U8Type = ::boost::uint8_t> +class u32_to_u8_iterator + : public boost::iterator_facade<u32_to_u8_iterator<BaseIterator, U8Type>, U8Type, std::bidirectional_iterator_tag, const U8Type> +{ + typedef boost::iterator_facade<u32_to_u8_iterator<BaseIterator, U8Type>, U8Type, std::bidirectional_iterator_tag, const U8Type> base_type; + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + 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(U8Type)*CHAR_BIT == 8); +#endif + +public: + typename base_type::reference + dereference()const + { + if(m_current == 4) + extract_current(); + return m_values[m_current]; + } + bool equal(const u32_to_u8_iterator& that)const + { + if(m_position == that.m_position) + { + // either the m_current's must be equal, or one must be 0 and + // the other 4: which means neither must have bits 1 or 2 set: + return (m_current == that.m_current) + || (((m_current | that.m_current) & 3) == 0); + } + 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 == 4) + { + // 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 = 4; + ++m_position; + } + } + void decrement() + { + if((m_current & 3) == 0) + { + --m_position; + extract_current(); + m_current = 3; + while(m_current && (m_values[m_current] == 0)) + --m_current; + } + else + --m_current; + } + BaseIterator base()const + { + return m_position; + } + // construct: + u32_to_u8_iterator() : m_position(), m_current(0) + { + m_values[0] = 0; + m_values[1] = 0; + m_values[2] = 0; + m_values[3] = 0; + m_values[4] = 0; + } + u32_to_u8_iterator(BaseIterator b) : m_position(b), m_current(4) + { + m_values[0] = 0; + m_values[1] = 0; + m_values[2] = 0; + m_values[3] = 0; + m_values[4] = 0; + } +private: + + void extract_current()const + { + boost::uint32_t c = *m_position; + if(c > 0x10FFFFu) + detail::invalid_utf32_code_point(c); + if(c < 0x80u) + { + m_values[0] = static_cast<unsigned char>(c); + m_values[1] = static_cast<unsigned char>(0u); + m_values[2] = static_cast<unsigned char>(0u); + m_values[3] = static_cast<unsigned char>(0u); + } + else if(c < 0x800u) + { + m_values[0] = static_cast<unsigned char>(0xC0u + (c >> 6)); + m_values[1] = static_cast<unsigned char>(0x80u + (c & 0x3Fu)); + m_values[2] = static_cast<unsigned char>(0u); + m_values[3] = static_cast<unsigned char>(0u); + } + else if(c < 0x10000u) + { + m_values[0] = static_cast<unsigned char>(0xE0u + (c >> 12)); + m_values[1] = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu)); + m_values[2] = static_cast<unsigned char>(0x80u + (c & 0x3Fu)); + m_values[3] = static_cast<unsigned char>(0u); + } + else + { + m_values[0] = static_cast<unsigned char>(0xF0u + (c >> 18)); + m_values[1] = static_cast<unsigned char>(0x80u + ((c >> 12) & 0x3Fu)); + m_values[2] = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu)); + m_values[3] = static_cast<unsigned char>(0x80u + (c & 0x3Fu)); + } + m_current= 0; + } + BaseIterator m_position; + mutable U8Type m_values[5]; + mutable unsigned m_current; +}; + +template <class BaseIterator, class U32Type = ::boost::uint32_t> +class u8_to_u32_iterator + : public boost::iterator_facade<u8_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type> +{ + typedef boost::iterator_facade<u8_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type; + // special values for pending iterator reads: + BOOST_STATIC_CONSTANT(U32Type, pending_read = 0xffffffffu); + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type; + + BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 8); + BOOST_STATIC_ASSERT(sizeof(U32Type)*CHAR_BIT == 32); +#endif + +public: + typename base_type::reference + dereference()const + { + if(m_value == pending_read) + extract_current(); + return m_value; + } + bool equal(const u8_to_u32_iterator& that)const + { + return m_position == that.m_position; + } + void increment() + { + // skip high surrogate first if there is one: + unsigned c = detail::utf8_byte_count(*m_position); + std::advance(m_position, c); + m_value = pending_read; + } + void decrement() + { + // Keep backtracking until we don't have a trailing character: + unsigned count = 0; + while((*--m_position & 0xC0u) == 0x80u) ++count; + // now check that the sequence was valid: + if(count != detail::utf8_trailing_byte_count(*m_position)) + invalid_sequnce(); + m_value = pending_read; + } + BaseIterator base()const + { + return m_position; + } + // construct: + u8_to_u32_iterator() : m_position() + { + m_value = pending_read; + } + u8_to_u32_iterator(BaseIterator b) : m_position(b) + { + m_value = pending_read; + } +private: + static void invalid_sequnce() + { + std::out_of_range e("Invalid UTF-8 sequence encountered while trying to encode UTF-32 character"); + boost::throw_exception(e); + } + void extract_current()const + { + m_value = static_cast<U32Type>(static_cast< ::boost::uint8_t>(*m_position)); + // we must not have a continuation character: + if((m_value & 0xC0u) == 0x80u) + invalid_sequnce(); + // see how many extra byts we have: + unsigned extra = detail::utf8_trailing_byte_count(*m_position); + // extract the extra bits, 6 from each extra byte: + BaseIterator next(m_position); + for(unsigned c = 0; c < extra; ++c) + { + ++next; + m_value <<= 6; + m_value += static_cast<boost::uint8_t>(*next) & 0x3Fu; + } + // we now need to remove a few of the leftmost bits, but how many depends + // upon how many extra bytes we've extracted: + static const boost::uint32_t masks[4] = + { + 0x7Fu, + 0x7FFu, + 0xFFFFu, + 0x1FFFFFu, + }; + m_value &= masks[extra]; + // check the result: + if(m_value > static_cast<U32Type>(0x10FFFFu)) + invalid_sequnce(); + } + BaseIterator m_position; + mutable U32Type m_value; +}; + +template <class BaseIterator> +class utf16_output_iterator +{ +public: + typedef void difference_type; + typedef void value_type; + typedef boost::uint32_t* pointer; + typedef boost::uint32_t& reference; + typedef std::output_iterator_tag iterator_category; + + utf16_output_iterator(const BaseIterator& b) + : m_position(b){} + utf16_output_iterator(const utf16_output_iterator& that) + : m_position(that.m_position){} + utf16_output_iterator& operator=(const utf16_output_iterator& that) + { + m_position = that.m_position; + return *this; + } + const utf16_output_iterator& operator*()const + { + return *this; + } + void operator=(boost::uint32_t val)const + { + push(val); + } + utf16_output_iterator& operator++() + { + return *this; + } + utf16_output_iterator& operator++(int) + { + return *this; + } + BaseIterator base()const + { + return m_position; + } +private: + void push(boost::uint32_t v)const + { + if(v >= 0x10000u) + { + // begin by checking for a code point out of range: + if(v > 0x10FFFFu) + detail::invalid_utf32_code_point(v); + // split into two surrogates: + *m_position++ = static_cast<boost::uint16_t>(v >> 10) + detail::high_surrogate_base; + *m_position++ = static_cast<boost::uint16_t>(v & detail::ten_bit_mask) + detail::low_surrogate_base; + } + else + { + // 16-bit code point: + // value must not be a surrogate: + if(detail::is_surrogate(v)) + detail::invalid_utf32_code_point(v); + *m_position++ = static_cast<boost::uint16_t>(v); + } + } + mutable BaseIterator m_position; +}; + +template <class BaseIterator> +class utf8_output_iterator +{ +public: + typedef void difference_type; + typedef void value_type; + typedef boost::uint32_t* pointer; + typedef boost::uint32_t& reference; + typedef std::output_iterator_tag iterator_category; + + utf8_output_iterator(const BaseIterator& b) + : m_position(b){} + utf8_output_iterator(const utf8_output_iterator& that) + : m_position(that.m_position){} + utf8_output_iterator& operator=(const utf8_output_iterator& that) + { + m_position = that.m_position; + return *this; + } + const utf8_output_iterator& operator*()const + { + return *this; + } + void operator=(boost::uint32_t val)const + { + push(val); + } + utf8_output_iterator& operator++() + { + return *this; + } + utf8_output_iterator& operator++(int) + { + return *this; + } + BaseIterator base()const + { + return m_position; + } +private: + void push(boost::uint32_t c)const + { + if(c > 0x10FFFFu) + detail::invalid_utf32_code_point(c); + if(c < 0x80u) + { + *m_position++ = static_cast<unsigned char>(c); + } + else if(c < 0x800u) + { + *m_position++ = static_cast<unsigned char>(0xC0u + (c >> 6)); + *m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu)); + } + else if(c < 0x10000u) + { + *m_position++ = static_cast<unsigned char>(0xE0u + (c >> 12)); + *m_position++ = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu)); + *m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu)); + } + else + { + *m_position++ = static_cast<unsigned char>(0xF0u + (c >> 18)); + *m_position++ = static_cast<unsigned char>(0x80u + ((c >> 12) & 0x3Fu)); + *m_position++ = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu)); + *m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu)); + } + } + mutable BaseIterator m_position; +}; + +} // namespace boost + +#endif // BOOST_REGEX_UNICODE_ITERATOR_HPP + diff --git a/ext/boost/regex/regex_traits.hpp b/ext/boost/regex/regex_traits.hpp new file mode 100644 index 0000000000..730ba6e0d8 --- /dev/null +++ b/ext/boost/regex/regex_traits.hpp @@ -0,0 +1,35 @@ +/* + * + * 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 regex_traits.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression traits classes. + */ + +#ifndef BOOST_REGEX_TRAITS_HPP +#define BOOST_REGEX_TRAITS_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +# include <boost/regex/config.hpp> +#endif + +# ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED +# include <boost/regex/v4/regex_traits.hpp> +# endif + +#endif // include + + + + + diff --git a/ext/boost/regex/user.hpp b/ext/boost/regex/user.hpp new file mode 100644 index 0000000000..95908173d7 --- /dev/null +++ b/ext/boost/regex/user.hpp @@ -0,0 +1,90 @@ +/* + * + * 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 user.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: User settable options. + */ + +// define if you want the regex library to use the C locale +// even on Win32: +// #define BOOST_REGEX_USE_C_LOCALE + +// define this is you want the regex library to use the C++ +// locale: +// #define BOOST_REGEX_USE_CPP_LOCALE + +// define this if the runtime library is a dll, and you +// want BOOST_REGEX_DYN_LINK to set up dll exports/imports +// with __declspec(dllexport)/__declspec(dllimport.) +// #define BOOST_REGEX_HAS_DLL_RUNTIME + +// define this if you want to dynamically link to regex, +// if the runtime library is also a dll (Probably Win32 specific, +// and has no effect unless BOOST_REGEX_HAS_DLL_RUNTIME is set): +// #define BOOST_REGEX_DYN_LINK + +// define this if you don't want the lib to automatically +// select its link libraries: +// #define BOOST_REGEX_NO_LIB + +// define this if templates with switch statements cause problems: +// #define BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE + +// define this to disable Win32 support when available: +// #define BOOST_REGEX_NO_W32 + +// define this if bool is not a real type: +// #define BOOST_REGEX_NO_BOOL + +// define this if no template instances are to be placed in +// the library rather than users object files: +// #define BOOST_REGEX_NO_EXTERNAL_TEMPLATES + +// define this if the forward declarations in regex_fwd.hpp +// cause more problems than they are worth: +// #define BOOST_REGEX_NO_FWD + +// define this if your compiler supports MS Windows structured +// exception handling. +// #define BOOST_REGEX_HAS_MS_STACK_GUARD + +// define this if you want to use the recursive algorithm +// even if BOOST_REGEX_HAS_MS_STACK_GUARD is not defined. +// #define BOOST_REGEX_RECURSIVE + +// define this if you want to use the non-recursive +// algorithm, even if the recursive version would be the default. +// #define BOOST_REGEX_NON_RECURSIVE + +// define this if you want to set the size of the memory blocks +// used by the non-recursive algorithm. +// #define BOOST_REGEX_BLOCKSIZE 4096 + +// define this if you want to set the maximum number of memory blocks +// used by the non-recursive algorithm. +// #define BOOST_REGEX_MAX_BLOCKS 1024 + +// define this if you want to set the maximum number of memory blocks +// cached by the non-recursive algorithm: Normally this is 16, but can be +// higher if you have multiple threads all using boost.regex, or lower +// if you don't want boost.regex to cache memory. +// #define BOOST_REGEX_MAX_CACHE_BLOCKS 16 + +// define this if you want to be able to access extended capture +// information in your sub_match's (caution this will slow things +// down quite a bit). +// #define BOOST_REGEX_MATCH_EXTRA + +// define this if you want to enable support for Unicode via ICU. +// #define BOOST_HAS_ICU diff --git a/ext/boost/regex/v4/basic_regex.hpp b/ext/boost/regex/v4/basic_regex.hpp new file mode 100644 index 0000000000..09b0467b40 --- /dev/null +++ b/ext/boost/regex/v4/basic_regex.hpp @@ -0,0 +1,825 @@ +/* + * + * Copyright (c) 1998-2004 + * John Maddock + * + * 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/ for most recent version. + * FILE basic_regex.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares template class basic_regex. + */ + +#ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP +#define BOOST_REGEX_V4_BASIC_REGEX_HPP + +#include <boost/type_traits/is_same.hpp> +#include <boost/functional/hash.hpp> + +#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 + +namespace boost{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4251 4231 4660 4800) +#endif + +namespace re_detail{ + +// +// forward declaration, we will need this one later: +// +template <class charT, class traits> +class basic_regex_parser; + +template <class I> +void bubble_down_one(I first, I last) +{ + if(first != last) + { + I next = last - 1; + while((next != first) && !(*(next-1) < *next)) + { + (next-1)->swap(*next); + --next; + } + } +} + +// +// Class named_subexpressions +// Contains information about named subexpressions within the regex. +// +template <class charT> +class named_subexpressions_base +{ +public: + virtual int get_id(const charT* i, const charT* j)const = 0; + virtual int get_id(std::size_t hash)const = 0; +#ifdef __GNUC__ + // warning supression: + virtual ~named_subexpressions_base(){} +#endif +}; + +template <class Iterator> +inline std::size_t hash_value_from_capture_name(Iterator i, Iterator j) +{ + std::size_t r = boost::hash_range(i, j); + r %= ((std::numeric_limits<int>::max)() - 10001); + r += 10000; + return r; +} + +template <class charT> +class named_subexpressions : public named_subexpressions_base<charT> +{ + struct name + { + name(const charT* i, const charT* j, int idx) + : /*n(i, j), */ index(idx) + { + hash = hash_value_from_capture_name(i, j); + } + name(std::size_t h, int idx) + : index(idx), hash(h) + { + } + //std::vector<charT> n; + int index; + std::size_t hash; + bool operator < (const name& other)const + { + return hash < other.hash; //std::lexicographical_compare(n.begin(), n.end(), other.n.begin(), other.n.end()); + } + bool operator == (const name& other)const + { + return hash == other.hash; //n == other.n; + } + void swap(name& other) + { + //n.swap(other.n); + std::swap(index, other.index); + std::swap(hash, other.hash); + } + }; +public: + named_subexpressions(){} + void set_name(const charT* i, const charT* j, int index) + { + m_sub_names.push_back(name(i, j, index)); + bubble_down_one(m_sub_names.begin(), m_sub_names.end()); + } + int get_id(const charT* i, const charT* j)const + { + name t(i, j, 0); + typename std::vector<name>::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t); + if((pos != m_sub_names.end()) && (*pos == t)) + { + return pos->index; + } + return -1; + } + int get_id(std::size_t h)const + { + name t(h, 0); + typename std::vector<name>::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t); + if((pos != m_sub_names.end()) && (*pos == t)) + { + return pos->index; + } + return -1; + } +private: + std::vector<name> m_sub_names; +}; + +template <class charT, class Other> +class named_subexpressions_converter : public named_subexpressions_base<charT> +{ + boost::shared_ptr<named_subexpressions<Other> > m_converter; +public: + named_subexpressions_converter(boost::shared_ptr<named_subexpressions<Other> > s) + : m_converter(s) {} + int get_id(const charT* i, const charT* j)const + { + if(i == j) + return -1; + std::vector<Other> v; + while(i != j) + { + v.push_back(*i); + ++i; + } + return m_converter->get_id(&v[0], &v[0] + v.size()); + } + int get_id(std::size_t h)const + { + return m_converter->get_id(h); + } +}; + +template <class To> +inline boost::shared_ptr<named_subexpressions_base<To> > convert_to_named_subs_imp( + boost::shared_ptr<named_subexpressions<To> > s, + boost::integral_constant<bool,true> const&) +{ + return s; +} +template <class To, class From> +inline boost::shared_ptr<named_subexpressions_base<To> > convert_to_named_subs_imp( + boost::shared_ptr<named_subexpressions<From> > s, + boost::integral_constant<bool,false> const&) +{ + return boost::shared_ptr<named_subexpressions_converter<To, From> >(new named_subexpressions_converter<To, From>(s)); +} +template <class To, class From> +inline boost::shared_ptr<named_subexpressions_base<To> > convert_to_named_subs( + boost::shared_ptr<named_subexpressions<From> > s) +{ + typedef typename boost::is_same<To, From>::type tag_type; + return convert_to_named_subs_imp<To>(s, tag_type()); +} +// +// class regex_data: +// represents the data we wish to expose to the matching algorithms. +// +template <class charT, class traits> +struct regex_data : public named_subexpressions<charT> +{ + typedef regex_constants::syntax_option_type flag_type; + typedef std::size_t size_type; + + regex_data(const ::boost::shared_ptr< + ::boost::regex_traits_wrapper<traits> >& t) + : m_ptraits(t), m_expression(0), m_expression_len(0) {} + regex_data() + : m_ptraits(new ::boost::regex_traits_wrapper<traits>()), m_expression(0), m_expression_len(0) {} + + ::boost::shared_ptr< + ::boost::regex_traits_wrapper<traits> + > m_ptraits; // traits class instance + flag_type m_flags; // flags with which we were compiled + int m_status; // error code (0 implies OK). + const charT* m_expression; // the original expression + std::ptrdiff_t m_expression_len; // the length of the original expression + size_type m_mark_count; // the number of marked sub-expressions + re_detail::re_syntax_base* m_first_state; // the first state of the machine + unsigned m_restart_type; // search optimisation type + unsigned char m_startmap[1 << CHAR_BIT]; // which characters can start a match + unsigned int m_can_be_null; // whether we can match a null string + re_detail::raw_storage m_data; // the buffer in which our states are constructed + typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character + std::vector< + std::pair< + std::size_t, std::size_t> > m_subs; // Position of sub-expressions within the *string*. + bool m_has_recursions; // whether we have recursive expressions; +}; +// +// class basic_regex_implementation +// pimpl implementation class for basic_regex. +// +template <class charT, class traits> +class basic_regex_implementation + : public regex_data<charT, traits> +{ +public: + typedef regex_constants::syntax_option_type flag_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef typename traits::locale_type locale_type; + typedef const charT* const_iterator; + + basic_regex_implementation(){} + basic_regex_implementation(const ::boost::shared_ptr< + ::boost::regex_traits_wrapper<traits> >& t) + : regex_data<charT, traits>(t) {} + void assign(const charT* arg_first, + const charT* arg_last, + flag_type f) + { + regex_data<charT, traits>* pdat = this; + basic_regex_parser<charT, traits> parser(pdat); + parser.parse(arg_first, arg_last, f); + } + + locale_type BOOST_REGEX_CALL imbue(locale_type l) + { + return this->m_ptraits->imbue(l); + } + locale_type BOOST_REGEX_CALL getloc()const + { + return this->m_ptraits->getloc(); + } + std::basic_string<charT> BOOST_REGEX_CALL str()const + { + std::basic_string<charT> result; + if(this->m_status == 0) + result = std::basic_string<charT>(this->m_expression, this->m_expression_len); + return result; + } + const_iterator BOOST_REGEX_CALL expression()const + { + return this->m_expression; + } + std::pair<const_iterator, const_iterator> BOOST_REGEX_CALL subexpression(std::size_t n)const + { + if(n == 0) + throw std::out_of_range("0 is not a valid subexpression index."); + const std::pair<std::size_t, std::size_t>& pi = this->m_subs.at(n - 1); + std::pair<const_iterator, const_iterator> p(expression() + pi.first, expression() + pi.second); + return p; + } + // + // begin, end: + const_iterator BOOST_REGEX_CALL begin()const + { + return (!this->m_status ? 0 : this->m_expression); + } + const_iterator BOOST_REGEX_CALL end()const + { + return (!this->m_status ? 0 : this->m_expression + this->m_expression_len); + } + flag_type BOOST_REGEX_CALL flags()const + { + return this->m_flags; + } + size_type BOOST_REGEX_CALL size()const + { + return this->m_expression_len; + } + int BOOST_REGEX_CALL status()const + { + return this->m_status; + } + size_type BOOST_REGEX_CALL mark_count()const + { + return this->m_mark_count; + } + const re_detail::re_syntax_base* get_first_state()const + { + return this->m_first_state; + } + unsigned get_restart_type()const + { + return this->m_restart_type; + } + const unsigned char* get_map()const + { + return this->m_startmap; + } + const ::boost::regex_traits_wrapper<traits>& get_traits()const + { + return *(this->m_ptraits); + } + bool can_be_null()const + { + return this->m_can_be_null; + } + const regex_data<charT, traits>& get_data()const + { + basic_regex_implementation<charT, traits> const* p = this; + return *static_cast<const regex_data<charT, traits>*>(p); + } +}; + +} // namespace re_detail +// +// class basic_regex: +// represents the compiled +// regular expression: +// + +#ifdef BOOST_REGEX_NO_FWD +template <class charT, class traits = regex_traits<charT> > +#else +template <class charT, class traits > +#endif +class basic_regex : public regbase +{ +public: + // typedefs: + typedef std::size_t traits_size_type; + typedef typename traits::string_type traits_string_type; + typedef charT char_type; + typedef traits traits_type; + + typedef charT value_type; + typedef charT& reference; + typedef const charT& const_reference; + typedef const charT* const_iterator; + typedef const_iterator iterator; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef regex_constants::syntax_option_type flag_type; + // locale_type + // placeholder for actual locale type used by the + // traits class to localise *this. + typedef typename traits::locale_type locale_type; + +public: + explicit basic_regex(){} + explicit basic_regex(const charT* p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + { + assign(p1, p2, f); + } + basic_regex(const charT* p, size_type len, flag_type f) + { + assign(p, len, f); + } + basic_regex(const basic_regex& that) + : m_pimpl(that.m_pimpl) {} + ~basic_regex(){} + basic_regex& BOOST_REGEX_CALL operator=(const basic_regex& that) + { + return assign(that); + } + basic_regex& BOOST_REGEX_CALL operator=(const charT* ptr) + { + return assign(ptr); + } + + // + // assign: + basic_regex& assign(const basic_regex& that) + { + m_pimpl = that.m_pimpl; + return *this; + } + basic_regex& assign(const charT* p, flag_type f = regex_constants::normal) + { + return assign(p, p + traits::length(p), f); + } + basic_regex& assign(const charT* p, size_type len, flag_type f) + { + return assign(p, p + len, f); + } +private: + basic_regex& do_assign(const charT* p1, + const charT* p2, + flag_type f); +public: + basic_regex& assign(const charT* p1, + const charT* p2, + flag_type f = regex_constants::normal) + { + return do_assign(p1, p2, f); + } +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + + template <class ST, class SA> + unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal) + { + return set_expression(p.data(), p.data() + p.size(), f); + } + + template <class ST, class SA> + explicit basic_regex(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + + template <class InputIterator> + basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) + { + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + if(a.size()) + assign(&*a.begin(), &*a.begin() + a.size(), f); + else + assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f); + } + + template <class ST, class SA> + basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p) + { + return assign(p.data(), p.data() + p.size(), regex_constants::normal); + } + + template <class string_traits, class A> + basic_regex& BOOST_REGEX_CALL assign( + const std::basic_string<charT, string_traits, A>& s, + flag_type f = regex_constants::normal) + { + return assign(s.data(), s.data() + s.size(), f); + } + + template <class InputIterator> + basic_regex& BOOST_REGEX_CALL assign(InputIterator arg_first, + InputIterator arg_last, + flag_type f = regex_constants::normal) + { + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + if(a.size()) + { + const charT* p1 = &*a.begin(); + const charT* p2 = &*a.begin() + a.size(); + return assign(p1, p2, f); + } + return assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f); + } +#else + unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal) + { + return set_expression(p.data(), p.data() + p.size(), f); + } + + basic_regex(const std::basic_string<charT>& p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + + basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p) + { + return assign(p.data(), p.data() + p.size(), regex_constants::normal); + } + + basic_regex& BOOST_REGEX_CALL assign( + const std::basic_string<charT>& s, + flag_type f = regex_constants::normal) + { + return assign(s.data(), s.data() + s.size(), f); + } + +#endif + + // + // locale: + locale_type BOOST_REGEX_CALL imbue(locale_type l); + locale_type BOOST_REGEX_CALL getloc()const + { + return m_pimpl.get() ? m_pimpl->getloc() : locale_type(); + } + // + // getflags: + // retained for backwards compatibility only, "flags" + // is now the preferred name: + flag_type BOOST_REGEX_CALL getflags()const + { + return flags(); + } + flag_type BOOST_REGEX_CALL flags()const + { + return m_pimpl.get() ? m_pimpl->flags() : 0; + } + // + // str: + std::basic_string<charT> BOOST_REGEX_CALL str()const + { + return m_pimpl.get() ? m_pimpl->str() : std::basic_string<charT>(); + } + // + // begin, end, subexpression: + std::pair<const_iterator, const_iterator> BOOST_REGEX_CALL subexpression(std::size_t n)const + { + if(!m_pimpl.get()) + throw std::logic_error("Can't access subexpressions in an invalid regex."); + return m_pimpl->subexpression(n); + } + const_iterator BOOST_REGEX_CALL begin()const + { + return (m_pimpl.get() ? m_pimpl->begin() : 0); + } + const_iterator BOOST_REGEX_CALL end()const + { + return (m_pimpl.get() ? m_pimpl->end() : 0); + } + // + // swap: + void BOOST_REGEX_CALL swap(basic_regex& that)throw() + { + m_pimpl.swap(that.m_pimpl); + } + // + // size: + size_type BOOST_REGEX_CALL size()const + { + return (m_pimpl.get() ? m_pimpl->size() : 0); + } + // + // max_size: + size_type BOOST_REGEX_CALL max_size()const + { + return UINT_MAX; + } + // + // empty: + bool BOOST_REGEX_CALL empty()const + { + return (m_pimpl.get() ? 0 != m_pimpl->status() : true); + } + + size_type BOOST_REGEX_CALL mark_count()const + { + return (m_pimpl.get() ? m_pimpl->mark_count() : 0); + } + + int status()const + { + return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty); + } + + int BOOST_REGEX_CALL compare(const basic_regex& that) const + { + if(m_pimpl.get() == that.m_pimpl.get()) + return 0; + if(!m_pimpl.get()) + return -1; + if(!that.m_pimpl.get()) + return 1; + if(status() != that.status()) + return status() - that.status(); + if(flags() != that.flags()) + return flags() - that.flags(); + return str().compare(that.str()); + } + bool BOOST_REGEX_CALL operator==(const basic_regex& e)const + { + return compare(e) == 0; + } + bool BOOST_REGEX_CALL operator != (const basic_regex& e)const + { + return compare(e) != 0; + } + bool BOOST_REGEX_CALL operator<(const basic_regex& e)const + { + return compare(e) < 0; + } + bool BOOST_REGEX_CALL operator>(const basic_regex& e)const + { + return compare(e) > 0; + } + bool BOOST_REGEX_CALL operator<=(const basic_regex& e)const + { + return compare(e) <= 0; + } + bool BOOST_REGEX_CALL operator>=(const basic_regex& e)const + { + return compare(e) >= 0; + } + + // + // The following are deprecated as public interfaces + // but are available for compatibility with earlier versions. + const charT* BOOST_REGEX_CALL expression()const + { + return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0); + } + unsigned int BOOST_REGEX_CALL set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + { + assign(p1, p2, f | regex_constants::no_except); + return status(); + } + unsigned int BOOST_REGEX_CALL set_expression(const charT* p, flag_type f = regex_constants::normal) + { + assign(p, f | regex_constants::no_except); + return status(); + } + unsigned int BOOST_REGEX_CALL error_code()const + { + return status(); + } + // + // private access methods: + // + const re_detail::re_syntax_base* get_first_state()const + { + BOOST_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_first_state(); + } + unsigned get_restart_type()const + { + BOOST_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_restart_type(); + } + const unsigned char* get_map()const + { + BOOST_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_map(); + } + const ::boost::regex_traits_wrapper<traits>& get_traits()const + { + BOOST_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_traits(); + } + bool can_be_null()const + { + BOOST_ASSERT(0 != m_pimpl.get()); + return m_pimpl->can_be_null(); + } + const re_detail::regex_data<charT, traits>& get_data()const + { + BOOST_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_data(); + } + boost::shared_ptr<re_detail::named_subexpressions<charT> > get_named_subs()const + { + return m_pimpl; + } + +private: + shared_ptr<re_detail::basic_regex_implementation<charT, traits> > m_pimpl; +}; + +// +// out of line members; +// these are the only members that mutate the basic_regex object, +// and are designed to provide the strong exception guarentee +// (in the event of a throw, the state of the object remains unchanged). +// +template <class charT, class traits> +basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1, + const charT* p2, + flag_type f) +{ + shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp; + if(!m_pimpl.get()) + { + temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>()); + } + else + { + temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits)); + } + temp->assign(p1, p2, f); + temp.swap(m_pimpl); + return *this; +} + +template <class charT, class traits> +typename basic_regex<charT, traits>::locale_type BOOST_REGEX_CALL basic_regex<charT, traits>::imbue(locale_type l) +{ + shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp(new re_detail::basic_regex_implementation<charT, traits>()); + locale_type result = temp->imbue(l); + temp.swap(m_pimpl); + return result; +} + +// +// non-members: +// +template <class charT, class traits> +void swap(basic_regex<charT, traits>& e1, basic_regex<charT, traits>& e2) +{ + e1.swap(e2); +} + +#ifndef BOOST_NO_STD_LOCALE +template <class charT, class traits, class traits2> +std::basic_ostream<charT, traits>& + operator << (std::basic_ostream<charT, traits>& os, + const basic_regex<charT, traits2>& e) +{ + return (os << e.str()); +} +#else +template <class traits> +std::ostream& operator << (std::ostream& os, const basic_regex<char, traits>& e) +{ + return (os << e.str()); +} +#endif + +// +// class reg_expression: +// this is provided for backwards compatibility only, +// it is deprecated, no not use! +// +#ifdef BOOST_REGEX_NO_FWD +template <class charT, class traits = regex_traits<charT> > +#else +template <class charT, class traits > +#endif +class reg_expression : public basic_regex<charT, traits> +{ +public: + typedef typename basic_regex<charT, traits>::flag_type flag_type; + typedef typename basic_regex<charT, traits>::size_type size_type; + explicit reg_expression(){} + explicit reg_expression(const charT* p, flag_type f = regex_constants::normal) + : basic_regex<charT, traits>(p, f){} + reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + : basic_regex<charT, traits>(p1, p2, f){} + reg_expression(const charT* p, size_type len, flag_type f) + : basic_regex<charT, traits>(p, len, f){} + reg_expression(const reg_expression& that) + : basic_regex<charT, traits>(that) {} + ~reg_expression(){} + reg_expression& BOOST_REGEX_CALL operator=(const reg_expression& that) + { + return this->assign(that); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + template <class ST, class SA> + explicit reg_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal) + : basic_regex<charT, traits>(p, f) + { + } + + template <class InputIterator> + reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) + : basic_regex<charT, traits>(arg_first, arg_last, f) + { + } + + template <class ST, class SA> + reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p) + { + this->assign(p); + return *this; + } +#else + explicit reg_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal) + : basic_regex<charT, traits>(p, f) + { + } + + reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p) + { + this->assign(p); + return *this; + } +#endif + +}; + +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + +} // namespace boost + +#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 + +#endif + diff --git a/ext/boost/regex/v4/basic_regex_creator.hpp b/ext/boost/regex/v4/basic_regex_creator.hpp new file mode 100644 index 0000000000..6f0050542d --- /dev/null +++ b/ext/boost/regex/v4/basic_regex_creator.hpp @@ -0,0 +1,1436 @@ +/* + * + * 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 basic_regex_creator.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares template class basic_regex_creator which fills in + * the data members of a regex_data object. + */ + +#ifndef BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP +#define BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP + +#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: 4800) +#endif + +namespace boost{ + +namespace re_detail{ + +template <class charT> +struct digraph : public std::pair<charT, charT> +{ + digraph() : std::pair<charT, charT>(0, 0){} + digraph(charT c1) : std::pair<charT, charT>(c1, 0){} + digraph(charT c1, charT c2) : std::pair<charT, charT>(c1, c2) + {} +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + digraph(const digraph<charT>& d) : std::pair<charT, charT>(d.first, d.second){} +#endif + template <class Seq> + digraph(const Seq& s) : std::pair<charT, charT>() + { + BOOST_ASSERT(s.size() <= 2); + BOOST_ASSERT(s.size()); + this->first = s[0]; + this->second = (s.size() > 1) ? s[1] : 0; + } +}; + +template <class charT, class traits> +class basic_char_set +{ +public: + typedef digraph<charT> digraph_type; + typedef typename traits::string_type string_type; + typedef typename traits::char_class_type mask_type; + + basic_char_set() + { + m_negate = false; + m_has_digraphs = false; + m_classes = 0; + m_negated_classes = 0; + m_empty = true; + } + + void add_single(const digraph_type& s) + { + m_singles.insert(m_singles.end(), s); + if(s.second) + m_has_digraphs = true; + m_empty = false; + } + void add_range(const digraph_type& first, const digraph_type& end) + { + m_ranges.insert(m_ranges.end(), first); + m_ranges.insert(m_ranges.end(), end); + if(first.second) + { + m_has_digraphs = true; + add_single(first); + } + if(end.second) + { + m_has_digraphs = true; + add_single(end); + } + m_empty = false; + } + void add_class(mask_type m) + { + m_classes |= m; + m_empty = false; + } + void add_negated_class(mask_type m) + { + m_negated_classes |= m; + m_empty = false; + } + void add_equivalent(const digraph_type& s) + { + m_equivalents.insert(m_equivalents.end(), s); + if(s.second) + { + m_has_digraphs = true; + add_single(s); + } + m_empty = false; + } + void negate() + { + m_negate = true; + //m_empty = false; + } + + // + // accessor functions: + // + bool has_digraphs()const + { + return m_has_digraphs; + } + bool is_negated()const + { + return m_negate; + } + typedef typename std::vector<digraph_type>::const_iterator list_iterator; + list_iterator singles_begin()const + { + return m_singles.begin(); + } + list_iterator singles_end()const + { + return m_singles.end(); + } + list_iterator ranges_begin()const + { + return m_ranges.begin(); + } + list_iterator ranges_end()const + { + return m_ranges.end(); + } + list_iterator equivalents_begin()const + { + return m_equivalents.begin(); + } + list_iterator equivalents_end()const + { + return m_equivalents.end(); + } + mask_type classes()const + { + return m_classes; + } + mask_type negated_classes()const + { + return m_negated_classes; + } + bool empty()const + { + return m_empty; + } +private: + std::vector<digraph_type> m_singles; // a list of single characters to match + std::vector<digraph_type> m_ranges; // a list of end points of our ranges + bool m_negate; // true if the set is to be negated + bool m_has_digraphs; // true if we have digraphs present + mask_type m_classes; // character classes to match + mask_type m_negated_classes; // negated character classes to match + bool m_empty; // whether we've added anything yet + std::vector<digraph_type> m_equivalents; // a list of equivalence classes +}; + +template <class charT, class traits> +class basic_regex_creator +{ +public: + basic_regex_creator(regex_data<charT, traits>* data); + std::ptrdiff_t getoffset(void* addr) + { + return getoffset(addr, m_pdata->m_data.data()); + } + std::ptrdiff_t getoffset(const void* addr, const void* base) + { + return static_cast<const char*>(addr) - static_cast<const char*>(base); + } + re_syntax_base* getaddress(std::ptrdiff_t off) + { + return getaddress(off, m_pdata->m_data.data()); + } + re_syntax_base* getaddress(std::ptrdiff_t off, void* base) + { + return static_cast<re_syntax_base*>(static_cast<void*>(static_cast<char*>(base) + off)); + } + void init(unsigned l_flags) + { + m_pdata->m_flags = l_flags; + m_icase = l_flags & regex_constants::icase; + } + regbase::flag_type flags() + { + return m_pdata->m_flags; + } + void flags(regbase::flag_type f) + { + m_pdata->m_flags = f; + if(m_icase != static_cast<bool>(f & regbase::icase)) + { + m_icase = static_cast<bool>(f & regbase::icase); + } + } + re_syntax_base* append_state(syntax_element_type t, std::size_t s = sizeof(re_syntax_base)); + re_syntax_base* insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s = sizeof(re_syntax_base)); + re_literal* append_literal(charT c); + re_syntax_base* append_set(const basic_char_set<charT, traits>& char_set); + re_syntax_base* append_set(const basic_char_set<charT, traits>& char_set, mpl::false_*); + re_syntax_base* append_set(const basic_char_set<charT, traits>& char_set, mpl::true_*); + void finalize(const charT* p1, const charT* p2); +protected: + regex_data<charT, traits>* m_pdata; // pointer to the basic_regex_data struct we are filling in + const ::boost::regex_traits_wrapper<traits>& + m_traits; // convenience reference to traits class + re_syntax_base* m_last_state; // the last state we added + bool m_icase; // true for case insensitive matches + unsigned m_repeater_id; // the state_id of the next repeater + bool m_has_backrefs; // true if there are actually any backrefs + unsigned m_backrefs; // bitmask of permitted backrefs + boost::uintmax_t m_bad_repeats; // bitmask of repeats we can't deduce a startmap for; + bool m_has_recursions; // set when we have recursive expresisons to fixup + typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character + typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character + typename traits::char_class_type m_lower_mask; // mask used to determine if a character is a lowercase character + typename traits::char_class_type m_upper_mask; // mask used to determine if a character is an uppercase character + typename traits::char_class_type m_alpha_mask; // mask used to determine if a character is an alphabetic character +private: + basic_regex_creator& operator=(const basic_regex_creator&); + basic_regex_creator(const basic_regex_creator&); + + void fixup_pointers(re_syntax_base* state); + void fixup_recursions(re_syntax_base* state); + void create_startmaps(re_syntax_base* state); + int calculate_backstep(re_syntax_base* state); + void create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask); + unsigned get_restart_type(re_syntax_base* state); + void set_all_masks(unsigned char* bits, unsigned char); + bool is_bad_repeat(re_syntax_base* pt); + void set_bad_repeat(re_syntax_base* pt); + syntax_element_type get_repeat_type(re_syntax_base* state); + void probe_leading_repeat(re_syntax_base* state); +}; + +template <class charT, class traits> +basic_regex_creator<charT, traits>::basic_regex_creator(regex_data<charT, traits>* data) + : m_pdata(data), m_traits(*(data->m_ptraits)), m_last_state(0), m_repeater_id(0), m_has_backrefs(false), m_backrefs(0), m_has_recursions(false) +{ + m_pdata->m_data.clear(); + m_pdata->m_status = ::boost::regex_constants::error_ok; + static const charT w = 'w'; + static const charT s = 's'; + static const charT l[5] = { 'l', 'o', 'w', 'e', 'r', }; + static const charT u[5] = { 'u', 'p', 'p', 'e', 'r', }; + static const charT a[5] = { 'a', 'l', 'p', 'h', 'a', }; + m_word_mask = m_traits.lookup_classname(&w, &w +1); + m_mask_space = m_traits.lookup_classname(&s, &s +1); + m_lower_mask = m_traits.lookup_classname(l, l + 5); + m_upper_mask = m_traits.lookup_classname(u, u + 5); + m_alpha_mask = m_traits.lookup_classname(a, a + 5); + m_pdata->m_word_mask = m_word_mask; + BOOST_ASSERT(m_word_mask != 0); + BOOST_ASSERT(m_mask_space != 0); + BOOST_ASSERT(m_lower_mask != 0); + BOOST_ASSERT(m_upper_mask != 0); + BOOST_ASSERT(m_alpha_mask != 0); +} + +template <class charT, class traits> +re_syntax_base* basic_regex_creator<charT, traits>::append_state(syntax_element_type t, std::size_t s) +{ + // if the state is a backref then make a note of it: + if(t == syntax_element_backref) + this->m_has_backrefs = true; + // append a new state, start by aligning our last one: + m_pdata->m_data.align(); + // set the offset to the next state in our last one: + if(m_last_state) + m_last_state->next.i = m_pdata->m_data.size() - getoffset(m_last_state); + // now actually extent our data: + m_last_state = static_cast<re_syntax_base*>(m_pdata->m_data.extend(s)); + // fill in boilerplate options in the new state: + m_last_state->next.i = 0; + m_last_state->type = t; + return m_last_state; +} + +template <class charT, class traits> +re_syntax_base* basic_regex_creator<charT, traits>::insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s) +{ + // append a new state, start by aligning our last one: + m_pdata->m_data.align(); + // set the offset to the next state in our last one: + if(m_last_state) + m_last_state->next.i = m_pdata->m_data.size() - getoffset(m_last_state); + // remember the last state position: + std::ptrdiff_t off = getoffset(m_last_state) + s; + // now actually insert our data: + re_syntax_base* new_state = static_cast<re_syntax_base*>(m_pdata->m_data.insert(pos, s)); + // fill in boilerplate options in the new state: + new_state->next.i = s; + new_state->type = t; + m_last_state = getaddress(off); + return new_state; +} + +template <class charT, class traits> +re_literal* basic_regex_creator<charT, traits>::append_literal(charT c) +{ + re_literal* result; + // start by seeing if we have an existing re_literal we can extend: + if((0 == m_last_state) || (m_last_state->type != syntax_element_literal)) + { + // no existing re_literal, create a new one: + result = static_cast<re_literal*>(append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT))); + result->length = 1; + *static_cast<charT*>(static_cast<void*>(result+1)) = m_traits.translate(c, m_icase); + } + else + { + // we have an existing re_literal, extend it: + std::ptrdiff_t off = getoffset(m_last_state); + m_pdata->m_data.extend(sizeof(charT)); + m_last_state = result = static_cast<re_literal*>(getaddress(off)); + charT* characters = static_cast<charT*>(static_cast<void*>(result+1)); + characters[result->length] = m_traits.translate(c, m_icase); + ++(result->length); + } + return result; +} + +template <class charT, class traits> +inline re_syntax_base* basic_regex_creator<charT, traits>::append_set( + const basic_char_set<charT, traits>& char_set) +{ + typedef mpl::bool_< (sizeof(charT) == 1) > truth_type; + return char_set.has_digraphs() + ? append_set(char_set, static_cast<mpl::false_*>(0)) + : append_set(char_set, static_cast<truth_type*>(0)); +} + +template <class charT, class traits> +re_syntax_base* basic_regex_creator<charT, traits>::append_set( + const basic_char_set<charT, traits>& char_set, mpl::false_*) +{ + typedef typename traits::string_type string_type; + typedef typename basic_char_set<charT, traits>::list_iterator item_iterator; + typedef typename traits::char_class_type mask_type; + + re_set_long<mask_type>* result = static_cast<re_set_long<mask_type>*>(append_state(syntax_element_long_set, sizeof(re_set_long<mask_type>))); + // + // fill in the basics: + // + result->csingles = static_cast<unsigned int>(::boost::re_detail::distance(char_set.singles_begin(), char_set.singles_end())); + result->cranges = static_cast<unsigned int>(::boost::re_detail::distance(char_set.ranges_begin(), char_set.ranges_end())) / 2; + result->cequivalents = static_cast<unsigned int>(::boost::re_detail::distance(char_set.equivalents_begin(), char_set.equivalents_end())); + result->cclasses = char_set.classes(); + result->cnclasses = char_set.negated_classes(); + if(flags() & regbase::icase) + { + // adjust classes as needed: + if(((result->cclasses & m_lower_mask) == m_lower_mask) || ((result->cclasses & m_upper_mask) == m_upper_mask)) + result->cclasses |= m_alpha_mask; + if(((result->cnclasses & m_lower_mask) == m_lower_mask) || ((result->cnclasses & m_upper_mask) == m_upper_mask)) + result->cnclasses |= m_alpha_mask; + } + + result->isnot = char_set.is_negated(); + result->singleton = !char_set.has_digraphs(); + // + // remember where the state is for later: + // + std::ptrdiff_t offset = getoffset(result); + // + // now extend with all the singles: + // + item_iterator first, last; + first = char_set.singles_begin(); + last = char_set.singles_end(); + while(first != last) + { + charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (first->second ? 3 : 2))); + p[0] = m_traits.translate(first->first, m_icase); + if(first->second) + { + p[1] = m_traits.translate(first->second, m_icase); + p[2] = 0; + } + else + p[1] = 0; + ++first; + } + // + // now extend with all the ranges: + // + first = char_set.ranges_begin(); + last = char_set.ranges_end(); + while(first != last) + { + // first grab the endpoints of the range: + digraph<charT> c1 = *first; + c1.first = this->m_traits.translate(c1.first, this->m_icase); + c1.second = this->m_traits.translate(c1.second, this->m_icase); + ++first; + digraph<charT> c2 = *first; + c2.first = this->m_traits.translate(c2.first, this->m_icase); + c2.second = this->m_traits.translate(c2.second, this->m_icase); + ++first; + string_type s1, s2; + // different actions now depending upon whether collation is turned on: + if(flags() & regex_constants::collate) + { + // we need to transform our range into sort keys: +#if BOOST_WORKAROUND(__GNUC__, < 3) + string_type in(3, charT(0)); + in[0] = c1.first; + in[1] = c1.second; + s1 = this->m_traits.transform(in.c_str(), (in[1] ? in.c_str()+2 : in.c_str()+1)); + in[0] = c2.first; + in[1] = c2.second; + s2 = this->m_traits.transform(in.c_str(), (in[1] ? in.c_str()+2 : in.c_str()+1)); +#else + charT a1[3] = { c1.first, c1.second, charT(0), }; + charT a2[3] = { c2.first, c2.second, charT(0), }; + s1 = this->m_traits.transform(a1, (a1[1] ? a1+2 : a1+1)); + s2 = this->m_traits.transform(a2, (a2[1] ? a2+2 : a2+1)); +#endif + if(s1.size() == 0) + s1 = string_type(1, charT(0)); + if(s2.size() == 0) + s2 = string_type(1, charT(0)); + } + else + { + if(c1.second) + { + s1.insert(s1.end(), c1.first); + s1.insert(s1.end(), c1.second); + } + else + s1 = string_type(1, c1.first); + if(c2.second) + { + s2.insert(s2.end(), c2.first); + s2.insert(s2.end(), c2.second); + } + else + s2.insert(s2.end(), c2.first); + } + if(s1 > s2) + { + // Oops error: + return 0; + } + charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) ); + re_detail::copy(s1.begin(), s1.end(), p); + p[s1.size()] = charT(0); + p += s1.size() + 1; + re_detail::copy(s2.begin(), s2.end(), p); + p[s2.size()] = charT(0); + } + // + // now process the equivalence classes: + // + first = char_set.equivalents_begin(); + last = char_set.equivalents_end(); + while(first != last) + { + string_type s; + if(first->second) + { +#if BOOST_WORKAROUND(__GNUC__, < 3) + string_type in(3, charT(0)); + in[0] = first->first; + in[1] = first->second; + s = m_traits.transform_primary(in.c_str(), in.c_str()+2); +#else + charT cs[3] = { first->first, first->second, charT(0), }; + s = m_traits.transform_primary(cs, cs+2); +#endif + } + else + s = m_traits.transform_primary(&first->first, &first->first+1); + if(s.empty()) + return 0; // invalid or unsupported equivalence class + charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) ); + re_detail::copy(s.begin(), s.end(), p); + p[s.size()] = charT(0); + ++first; + } + // + // finally reset the address of our last state: + // + m_last_state = result = static_cast<re_set_long<mask_type>*>(getaddress(offset)); + return result; +} + +namespace{ + +template<class T> +inline bool char_less(T t1, T t2) +{ + return t1 < t2; +} +template<> +inline bool char_less<char>(char t1, char t2) +{ + return static_cast<unsigned char>(t1) < static_cast<unsigned char>(t2); +} +template<> +inline bool char_less<signed char>(signed char t1, signed char t2) +{ + return static_cast<unsigned char>(t1) < static_cast<unsigned char>(t2); +} +} + +template <class charT, class traits> +re_syntax_base* basic_regex_creator<charT, traits>::append_set( + const basic_char_set<charT, traits>& char_set, mpl::true_*) +{ + typedef typename traits::string_type string_type; + typedef typename basic_char_set<charT, traits>::list_iterator item_iterator; + + re_set* result = static_cast<re_set*>(append_state(syntax_element_set, sizeof(re_set))); + bool negate = char_set.is_negated(); + std::memset(result->_map, 0, sizeof(result->_map)); + // + // handle singles first: + // + item_iterator first, last; + first = char_set.singles_begin(); + last = char_set.singles_end(); + while(first != last) + { + for(unsigned int i = 0; i < (1 << CHAR_BIT); ++i) + { + if(this->m_traits.translate(static_cast<charT>(i), this->m_icase) + == this->m_traits.translate(first->first, this->m_icase)) + result->_map[i] = true; + } + ++first; + } + // + // OK now handle ranges: + // + first = char_set.ranges_begin(); + last = char_set.ranges_end(); + while(first != last) + { + // first grab the endpoints of the range: + charT c1 = this->m_traits.translate(first->first, this->m_icase); + ++first; + charT c2 = this->m_traits.translate(first->first, this->m_icase); + ++first; + // different actions now depending upon whether collation is turned on: + if(flags() & regex_constants::collate) + { + // we need to transform our range into sort keys: + charT c3[2] = { c1, charT(0), }; + string_type s1 = this->m_traits.transform(c3, c3+1); + c3[0] = c2; + string_type s2 = this->m_traits.transform(c3, c3+1); + if(s1 > s2) + { + // Oops error: + return 0; + } + BOOST_ASSERT(c3[1] == charT(0)); + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + c3[0] = static_cast<charT>(i); + string_type s3 = this->m_traits.transform(c3, c3 +1); + if((s1 <= s3) && (s3 <= s2)) + result->_map[i] = true; + } + } + else + { + if(char_less<charT>(c2, c1)) + { + // Oops error: + return 0; + } + // everything in range matches: + std::memset(result->_map + static_cast<unsigned char>(c1), true, 1 + static_cast<unsigned char>(c2) - static_cast<unsigned char>(c1)); + } + } + // + // and now the classes: + // + typedef typename traits::char_class_type mask_type; + mask_type m = char_set.classes(); + if(flags() & regbase::icase) + { + // adjust m as needed: + if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask)) + m |= m_alpha_mask; + } + if(m != 0) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + if(this->m_traits.isctype(static_cast<charT>(i), m)) + result->_map[i] = true; + } + } + // + // and now the negated classes: + // + m = char_set.negated_classes(); + if(flags() & regbase::icase) + { + // adjust m as needed: + if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask)) + m |= m_alpha_mask; + } + if(m != 0) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + if(0 == this->m_traits.isctype(static_cast<charT>(i), m)) + result->_map[i] = true; + } + } + // + // now process the equivalence classes: + // + first = char_set.equivalents_begin(); + last = char_set.equivalents_end(); + while(first != last) + { + string_type s; + BOOST_ASSERT(static_cast<charT>(0) == first->second); + s = m_traits.transform_primary(&first->first, &first->first+1); + if(s.empty()) + return 0; // invalid or unsupported equivalence class + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + charT c[2] = { (static_cast<charT>(i)), charT(0), }; + string_type s2 = this->m_traits.transform_primary(c, c+1); + if(s == s2) + result->_map[i] = true; + } + ++first; + } + if(negate) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + result->_map[i] = !(result->_map[i]); + } + } + return result; +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::finalize(const charT* p1, const charT* p2) +{ + // we've added all the states we need, now finish things off. + // start by adding a terminating state: + append_state(syntax_element_match); + // extend storage to store original expression: + std::ptrdiff_t len = p2 - p1; + m_pdata->m_expression_len = len; + charT* ps = static_cast<charT*>(m_pdata->m_data.extend(sizeof(charT) * (1 + (p2 - p1)))); + m_pdata->m_expression = ps; + re_detail::copy(p1, p2, ps); + ps[p2 - p1] = 0; + // fill in our other data... + // successful parsing implies a zero status: + m_pdata->m_status = 0; + // get the first state of the machine: + m_pdata->m_first_state = static_cast<re_syntax_base*>(m_pdata->m_data.data()); + // fixup pointers in the machine: + fixup_pointers(m_pdata->m_first_state); + if(m_has_recursions) + { + m_pdata->m_has_recursions = true; + fixup_recursions(m_pdata->m_first_state); + } + else + m_pdata->m_has_recursions = false; + // create nested startmaps: + create_startmaps(m_pdata->m_first_state); + // create main startmap: + std::memset(m_pdata->m_startmap, 0, sizeof(m_pdata->m_startmap)); + m_pdata->m_can_be_null = 0; + + m_bad_repeats = 0; + create_startmap(m_pdata->m_first_state, m_pdata->m_startmap, &(m_pdata->m_can_be_null), mask_all); + // get the restart type: + m_pdata->m_restart_type = get_restart_type(m_pdata->m_first_state); + // optimise a leading repeat if there is one: + probe_leading_repeat(m_pdata->m_first_state); +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::fixup_pointers(re_syntax_base* state) +{ + while(state) + { + switch(state->type) + { + case syntax_element_recurse: + m_has_recursions = true; + if(state->next.i) + state->next.p = getaddress(state->next.i, state); + else + state->next.p = 0; + break; + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + // set the state_id of this repeat: + static_cast<re_repeat*>(state)->state_id = m_repeater_id++; + // fall through: + case syntax_element_alt: + std::memset(static_cast<re_alt*>(state)->_map, 0, sizeof(static_cast<re_alt*>(state)->_map)); + static_cast<re_alt*>(state)->can_be_null = 0; + // fall through: + case syntax_element_jump: + static_cast<re_jump*>(state)->alt.p = getaddress(static_cast<re_jump*>(state)->alt.i, state); + // fall through again: + default: + if(state->next.i) + state->next.p = getaddress(state->next.i, state); + else + state->next.p = 0; + } + state = state->next.p; + } +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::fixup_recursions(re_syntax_base* state) +{ + re_syntax_base* base = state; + while(state) + { + switch(state->type) + { + case syntax_element_assert_backref: + { + // just check that the index is valid: + int id = static_cast<const re_brace*>(state)->index; + if(id < 0) + { + id = -id-1; + if(id >= 10000) + { + id = m_pdata->get_id(id); + if(id <= 0) + { + // check of sub-expression that doesn't exist: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = this->m_pdata->m_ptraits->error_string(boost::regex_constants::error_bad_pattern); + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + } + } + } + break; + case syntax_element_recurse: + { + bool ok = false; + re_syntax_base* p = base; + int id = static_cast<re_jump*>(state)->alt.i; + if(id > 10000) + id = m_pdata->get_id(id); + while(p) + { + if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == id)) + { + static_cast<re_jump*>(state)->alt.p = p; + ok = true; + break; + } + p = p->next.p; + } + if(!ok) + { + // recursion to sub-expression that doesn't exist: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = this->m_pdata->m_ptraits->error_string(boost::regex_constants::error_bad_pattern); + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + } + default: + break; + } + state = state->next.p; + } +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state) +{ + // non-recursive implementation: + // create the last map in the machine first, so that earlier maps + // can make use of the result... + // + // This was originally a recursive implementation, but that caused stack + // overflows with complex expressions on small stacks (think COM+). + + // start by saving the case setting: + bool l_icase = m_icase; + std::vector<std::pair<bool, re_syntax_base*> > v; + + while(state) + { + switch(state->type) + { + case syntax_element_toggle_case: + // we need to track case changes here: + m_icase = static_cast<re_case*>(state)->icase; + state = state->next.p; + continue; + case syntax_element_alt: + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + // just push the state onto our stack for now: + v.push_back(std::pair<bool, re_syntax_base*>(m_icase, state)); + state = state->next.p; + break; + case syntax_element_backstep: + // we need to calculate how big the backstep is: + static_cast<re_brace*>(state)->index + = this->calculate_backstep(state->next.p); + if(static_cast<re_brace*>(state)->index < 0) + { + // Oops error: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = this->m_pdata->m_ptraits->error_string(boost::regex_constants::error_bad_pattern); + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + // fall through: + default: + state = state->next.p; + } + } + // now work through our list, building all the maps as we go: + while(v.size()) + { + const std::pair<bool, re_syntax_base*>& p = v.back(); + m_icase = p.first; + state = p.second; + v.pop_back(); + + // Build maps: + m_bad_repeats = 0; + create_startmap(state->next.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_take); + m_bad_repeats = 0; + create_startmap(static_cast<re_alt*>(state)->alt.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_skip); + // adjust the type of the state to allow for faster matching: + state->type = this->get_repeat_type(state); + } + // restore case sensitivity: + m_icase = l_icase; +} + +template <class charT, class traits> +int basic_regex_creator<charT, traits>::calculate_backstep(re_syntax_base* state) +{ + typedef typename traits::char_class_type mask_type; + int result = 0; + while(state) + { + switch(state->type) + { + case syntax_element_startmark: + if((static_cast<re_brace*>(state)->index == -1) + || (static_cast<re_brace*>(state)->index == -2)) + { + state = static_cast<re_jump*>(state->next.p)->alt.p->next.p; + continue; + } + else if(static_cast<re_brace*>(state)->index == -3) + { + state = state->next.p->next.p; + continue; + } + break; + case syntax_element_endmark: + if((static_cast<re_brace*>(state)->index == -1) + || (static_cast<re_brace*>(state)->index == -2)) + return result; + break; + case syntax_element_literal: + result += static_cast<re_literal*>(state)->length; + break; + case syntax_element_wild: + case syntax_element_set: + result += 1; + break; + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_backref: + case syntax_element_rep: + case syntax_element_combining: + case syntax_element_long_set_rep: + case syntax_element_backstep: + { + re_repeat* rep = static_cast<re_repeat *>(state); + // adjust the type of the state to allow for faster matching: + state->type = this->get_repeat_type(state); + if((state->type == syntax_element_dot_rep) + || (state->type == syntax_element_char_rep) + || (state->type == syntax_element_short_set_rep)) + { + if(rep->max != rep->min) + return -1; + result += static_cast<int>(rep->min); + state = rep->alt.p; + continue; + } + else if((state->type == syntax_element_long_set_rep)) + { + BOOST_ASSERT(rep->next.p->type == syntax_element_long_set); + if(static_cast<re_set_long<mask_type>*>(rep->next.p)->singleton == 0) + return -1; + if(rep->max != rep->min) + return -1; + result += static_cast<int>(rep->min); + state = rep->alt.p; + continue; + } + } + return -1; + case syntax_element_long_set: + if(static_cast<re_set_long<mask_type>*>(state)->singleton == 0) + return -1; + result += 1; + break; + case syntax_element_jump: + state = static_cast<re_jump*>(state)->alt.p; + continue; + default: + break; + } + state = state->next.p; + } + return -1; +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask) +{ + int not_last_jump = 1; + + // track case sensitivity: + bool l_icase = m_icase; + + while(state) + { + switch(state->type) + { + case syntax_element_toggle_case: + l_icase = static_cast<re_case*>(state)->icase; + state = state->next.p; + break; + case syntax_element_literal: + { + // don't set anything in *pnull, set each element in l_map + // that could match the first character in the literal: + if(l_map) + { + l_map[0] |= mask_init; + charT first_char = *static_cast<charT*>(static_cast<void*>(static_cast<re_literal*>(state) + 1)); + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(m_traits.translate(static_cast<charT>(i), l_icase) == first_char) + l_map[i] |= mask; + } + } + return; + } + case syntax_element_end_line: + { + // next character must be a line separator (if there is one): + if(l_map) + { + l_map[0] |= mask_init; + l_map['\n'] |= mask; + l_map['\r'] |= mask; + l_map['\f'] |= mask; + l_map[0x85] |= mask; + } + // now figure out if we can match a NULL string at this point: + if(pnull) + create_startmap(state->next.p, 0, pnull, mask); + return; + } + case syntax_element_recurse: + case syntax_element_backref: + // can be null, and any character can match: + if(pnull) + *pnull |= mask; + // fall through: + case syntax_element_wild: + { + // can't be null, any character can match: + set_all_masks(l_map, mask); + return; + } + case syntax_element_match: + { + // must be null, any character can match: + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + case syntax_element_word_start: + { + // recurse, then AND with all the word characters: + create_startmap(state->next.p, l_map, pnull, mask); + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(!m_traits.isctype(static_cast<charT>(i), m_word_mask)) + l_map[i] &= static_cast<unsigned char>(~mask); + } + } + return; + } + case syntax_element_word_end: + { + // recurse, then AND with all the word characters: + create_startmap(state->next.p, l_map, pnull, mask); + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(m_traits.isctype(static_cast<charT>(i), m_word_mask)) + l_map[i] &= static_cast<unsigned char>(~mask); + } + } + return; + } + case syntax_element_buffer_end: + { + // we *must be null* : + if(pnull) + *pnull |= mask; + return; + } + case syntax_element_long_set: + if(l_map) + { + typedef typename traits::char_class_type mask_type; + if(static_cast<re_set_long<mask_type>*>(state)->singleton) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + charT c = static_cast<charT>(i); + if(&c != re_is_set_member(&c, &c + 1, static_cast<re_set_long<mask_type>*>(state), *m_pdata, m_icase)) + l_map[i] |= mask; + } + } + else + set_all_masks(l_map, mask); + } + return; + case syntax_element_set: + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(static_cast<re_set*>(state)->_map[ + static_cast<unsigned char>(m_traits.translate(static_cast<charT>(i), l_icase))]) + l_map[i] |= mask; + } + } + return; + case syntax_element_jump: + // take the jump: + state = static_cast<re_alt*>(state)->alt.p; + not_last_jump = -1; + break; + case syntax_element_alt: + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + re_alt* rep = static_cast<re_alt*>(state); + if(rep->_map[0] & mask_init) + { + if(l_map) + { + // copy previous results: + l_map[0] |= mask_init; + for(unsigned int i = 0; i <= UCHAR_MAX; ++i) + { + if(rep->_map[i] & mask_any) + l_map[i] |= mask; + } + } + if(pnull) + { + if(rep->can_be_null & mask_any) + *pnull |= mask; + } + } + else + { + // we haven't created a startmap for this alternative yet + // so take the union of the two options: + if(is_bad_repeat(state)) + { + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + set_bad_repeat(state); + create_startmap(state->next.p, l_map, pnull, mask); + if((state->type == syntax_element_alt) + || (static_cast<re_repeat*>(state)->min == 0) + || (not_last_jump == 0)) + create_startmap(rep->alt.p, l_map, pnull, mask); + } + } + return; + case syntax_element_soft_buffer_end: + // match newline or null: + if(l_map) + { + l_map[0] |= mask_init; + l_map['\n'] |= mask; + l_map['\r'] |= mask; + } + if(pnull) + *pnull |= mask; + return; + case syntax_element_endmark: + // need to handle independent subs as a special case: + if(static_cast<re_brace*>(state)->index < 0) + { + // can be null, any character can match: + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + else + { + state = state->next.p; + break; + } + + case syntax_element_startmark: + // need to handle independent subs as a special case: + if(static_cast<re_brace*>(state)->index == -3) + { + state = state->next.p->next.p; + break; + } + // otherwise fall through: + default: + state = state->next.p; + } + ++not_last_jump; + } +} + +template <class charT, class traits> +unsigned basic_regex_creator<charT, traits>::get_restart_type(re_syntax_base* state) +{ + // + // find out how the machine starts, so we can optimise the search: + // + while(state) + { + switch(state->type) + { + case syntax_element_startmark: + case syntax_element_endmark: + state = state->next.p; + continue; + case syntax_element_start_line: + return regbase::restart_line; + case syntax_element_word_start: + return regbase::restart_word; + case syntax_element_buffer_start: + return regbase::restart_buf; + case syntax_element_restart_continue: + return regbase::restart_continue; + default: + state = 0; + continue; + } + } + return regbase::restart_any; +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::set_all_masks(unsigned char* bits, unsigned char mask) +{ + // + // set mask in all of bits elements, + // if bits[0] has mask_init not set then we can + // optimise this to a call to memset: + // + if(bits) + { + if(bits[0] == 0) + (std::memset)(bits, mask, 1u << CHAR_BIT); + else + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + bits[i] |= mask; + } + bits[0] |= mask_init; + } +} + +template <class charT, class traits> +bool basic_regex_creator<charT, traits>::is_bad_repeat(re_syntax_base* pt) +{ + switch(pt->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + unsigned state_id = static_cast<re_repeat*>(pt)->state_id; + if(state_id > sizeof(m_bad_repeats) * CHAR_BIT) + return true; // run out of bits, assume we can't traverse this one. + static const boost::uintmax_t one = 1uL; + return m_bad_repeats & (one << state_id); + } + default: + return false; + } +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::set_bad_repeat(re_syntax_base* pt) +{ + switch(pt->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + unsigned state_id = static_cast<re_repeat*>(pt)->state_id; + static const boost::uintmax_t one = 1uL; + if(state_id <= sizeof(m_bad_repeats) * CHAR_BIT) + m_bad_repeats |= (one << state_id); + } + default: + break; + } +} + +template <class charT, class traits> +syntax_element_type basic_regex_creator<charT, traits>::get_repeat_type(re_syntax_base* state) +{ + typedef typename traits::char_class_type mask_type; + if(state->type == syntax_element_rep) + { + // check to see if we are repeating a single state: + if(state->next.p->next.p->next.p == static_cast<re_alt*>(state)->alt.p) + { + switch(state->next.p->type) + { + case re_detail::syntax_element_wild: + return re_detail::syntax_element_dot_rep; + case re_detail::syntax_element_literal: + return re_detail::syntax_element_char_rep; + case re_detail::syntax_element_set: + return re_detail::syntax_element_short_set_rep; + case re_detail::syntax_element_long_set: + if(static_cast<re_detail::re_set_long<mask_type>*>(state->next.p)->singleton) + return re_detail::syntax_element_long_set_rep; + break; + default: + break; + } + } + } + return state->type; +} + +template <class charT, class traits> +void basic_regex_creator<charT, traits>::probe_leading_repeat(re_syntax_base* state) +{ + // enumerate our states, and see if we have a leading repeat + // for which failed search restarts can be optimised; + do + { + switch(state->type) + { + case syntax_element_startmark: + if(static_cast<re_brace*>(state)->index >= 0) + { + state = state->next.p; + continue; + } + if((static_cast<re_brace*>(state)->index == -1) + || (static_cast<re_brace*>(state)->index == -2)) + { + // skip past the zero width assertion: + state = static_cast<const re_jump*>(state->next.p)->alt.p->next.p; + continue; + } + if(static_cast<re_brace*>(state)->index == -3) + { + // Have to skip the leading jump state: + state = state->next.p->next.p; + continue; + } + return; + case syntax_element_endmark: + case syntax_element_start_line: + case syntax_element_end_line: + case syntax_element_word_boundary: + case syntax_element_within_word: + case syntax_element_word_start: + case syntax_element_word_end: + case syntax_element_buffer_start: + case syntax_element_buffer_end: + case syntax_element_restart_continue: + state = state->next.p; + break; + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + if(this->m_has_backrefs == 0) + static_cast<re_repeat*>(state)->leading = true; + // fall through: + default: + return; + } + }while(state); +} + + +} // namespace re_detail + +} // namespace boost + +#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 + +#endif diff --git a/ext/boost/regex/v4/basic_regex_parser.hpp b/ext/boost/regex/v4/basic_regex_parser.hpp new file mode 100644 index 0000000000..7d2f5543e2 --- /dev/null +++ b/ext/boost/regex/v4/basic_regex_parser.hpp @@ -0,0 +1,2571 @@ +/* + * + * 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 basic_regex_parser.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares template class basic_regex_parser. + */ + +#ifndef BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP +#define BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP + +#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 + +namespace boost{ +namespace re_detail{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4244 4800) +#endif + +template <class charT, class traits> +class basic_regex_parser : public basic_regex_creator<charT, traits> +{ +public: + basic_regex_parser(regex_data<charT, traits>* data); + void parse(const charT* p1, const charT* p2, unsigned flags); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position); + + bool parse_all(); + bool parse_basic(); + bool parse_extended(); + bool parse_literal(); + bool parse_open_paren(); + bool parse_basic_escape(); + bool parse_extended_escape(); + bool parse_match_any(); + bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits<std::size_t>::max)()); + bool parse_repeat_range(bool isbasic); + bool parse_alt(); + bool parse_set(); + bool parse_backref(); + void parse_set_literal(basic_char_set<charT, traits>& char_set); + bool parse_inner_set(basic_char_set<charT, traits>& char_set); + bool parse_QE(); + bool parse_perl_extension(); + bool add_emacs_code(bool negate); + bool unwind_alts(std::ptrdiff_t last_paren_start); + digraph<charT> get_next_set_literal(basic_char_set<charT, traits>& char_set); + charT unescape_character(); + regex_constants::syntax_option_type parse_options(); + +private: + typedef bool (basic_regex_parser::*parser_proc_type)(); + typedef typename traits::string_type string_type; + typedef typename traits::char_class_type char_class_type; + parser_proc_type m_parser_proc; // the main parser to use + const charT* m_base; // the start of the string being parsed + const charT* m_end; // the end of the string being parsed + const charT* m_position; // our current parser position + unsigned m_mark_count; // how many sub-expressions we have + int m_mark_reset; // used to indicate that we're inside a (?|...) block. + unsigned m_max_mark; // largest mark count seen inside a (?|...) block. + std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted). + std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative + bool m_has_case_change; // true if somewhere in the current block the case has changed +#if defined(BOOST_MSVC) && defined(_M_IX86) + // This is an ugly warning suppression workaround (for warnings *inside* std::vector + // that can not otherwise be suppressed)... + BOOST_STATIC_ASSERT(sizeof(long) >= sizeof(void*)); + std::vector<long> m_alt_jumps; // list of alternative in the current scope. +#else + std::vector<std::ptrdiff_t> m_alt_jumps; // list of alternative in the current scope. +#endif + + basic_regex_parser& operator=(const basic_regex_parser&); + basic_regex_parser(const basic_regex_parser&); +}; + +template <class charT, class traits> +basic_regex_parser<charT, traits>::basic_regex_parser(regex_data<charT, traits>* data) + : basic_regex_creator<charT, traits>(data), m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false) +{ +} + +template <class charT, class traits> +void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2, unsigned l_flags) +{ + // pass l_flags on to base class: + this->init(l_flags); + // set up pointers: + m_position = m_base = p1; + m_end = p2; + // empty strings are errors: + if((p1 == p2) && + ( + ((l_flags & regbase::main_option_type) != regbase::perl_syntax_group) + || (l_flags & regbase::no_empty_expressions) + ) + ) + { + fail(regex_constants::error_empty, 0); + return; + } + // select which parser to use: + switch(l_flags & regbase::main_option_type) + { + case regbase::perl_syntax_group: + { + m_parser_proc = &basic_regex_parser<charT, traits>::parse_extended; + // + // Add a leading paren with index zero to give recursions a target: + // + re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace))); + br->index = 0; + br->icase = this->flags() & regbase::icase; + break; + } + case regbase::basic_syntax_group: + m_parser_proc = &basic_regex_parser<charT, traits>::parse_basic; + break; + case regbase::literal: + m_parser_proc = &basic_regex_parser<charT, traits>::parse_literal; + break; + } + + // parse all our characters: + bool result = parse_all(); + // + // Unwind our alternatives: + // + unwind_alts(-1); + // reset l_flags as a global scope (?imsx) may have altered them: + this->flags(l_flags); + // if we haven't gobbled up all the characters then we must + // have had an unexpected ')' : + if(!result) + { + fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_position)); + return; + } + // if an error has been set then give up now: + if(this->m_pdata->m_status) + return; + // fill in our sub-expression count: + this->m_pdata->m_mark_count = 1 + m_mark_count; + this->finalize(p1, p2); +} + +template <class charT, class traits> +void basic_regex_parser<charT, traits>::fail(regex_constants::error_type error_code, std::ptrdiff_t position) +{ + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = error_code; + m_position = m_end; // don't bother parsing anything else + // get the error message: + std::string message = this->m_pdata->m_ptraits->error_string(error_code); + // and raise the exception, this will do nothing if exceptions are disabled: +#ifndef BOOST_NO_EXCEPTIONS + if(0 == (this->flags() & regex_constants::no_except)) + { + boost::regex_error e(message, error_code, position); + e.raise(); + } +#else + (void)position; // suppress warnings. +#endif +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_all() +{ + bool result = true; + while(result && (m_position != m_end)) + { + result = (this->*m_parser_proc)(); + } + return result; +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4702) +#endif +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_basic() +{ + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_escape: + return parse_basic_escape(); + case regex_constants::syntax_dot: + return parse_match_any(); + case regex_constants::syntax_caret: + ++m_position; + this->append_state(syntax_element_start_line); + break; + case regex_constants::syntax_dollar: + ++m_position; + this->append_state(syntax_element_end_line); + break; + case regex_constants::syntax_star: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(); + } + case regex_constants::syntax_plus: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(1); + } + case regex_constants::syntax_question: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(0, 1); + } + case regex_constants::syntax_open_set: + return parse_set(); + case regex_constants::syntax_newline: + if(this->flags() & regbase::newline_alt) + return parse_alt(); + else + return parse_literal(); + default: + return parse_literal(); + } + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_extended() +{ + bool result = true; + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_open_mark: + return parse_open_paren(); + case regex_constants::syntax_close_mark: + return false; + case regex_constants::syntax_escape: + return parse_extended_escape(); + case regex_constants::syntax_dot: + return parse_match_any(); + case regex_constants::syntax_caret: + ++m_position; + this->append_state( + (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_start : syntax_element_start_line)); + break; + case regex_constants::syntax_dollar: + ++m_position; + this->append_state( + (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_end : syntax_element_end_line)); + break; + case regex_constants::syntax_star: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0); + return false; + } + ++m_position; + return parse_repeat(); + case regex_constants::syntax_question: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0); + return false; + } + ++m_position; + return parse_repeat(0,1); + case regex_constants::syntax_plus: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0); + return false; + } + ++m_position; + return parse_repeat(1); + case regex_constants::syntax_open_brace: + ++m_position; + return parse_repeat_range(false); + case regex_constants::syntax_close_brace: + fail(regex_constants::error_brace, this->m_position - this->m_end); + return false; + case regex_constants::syntax_or: + return parse_alt(); + case regex_constants::syntax_open_set: + return parse_set(); + case regex_constants::syntax_newline: + if(this->flags() & regbase::newline_alt) + return parse_alt(); + else + return parse_literal(); + case regex_constants::syntax_hash: + // + // If we have a mod_x flag set, then skip until + // we get to a newline character: + // + if((this->flags() + & (regbase::no_perl_ex|regbase::mod_x)) + == regbase::mod_x) + { + while((m_position != m_end) && !is_separator(*m_position++)){} + return true; + } + // Otherwise fall through: + default: + result = parse_literal(); + break; + } + return result; +} +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_literal() +{ + // append this as a literal provided it's not a space character + // or the perl option regbase::mod_x is not set: + if( + ((this->flags() + & (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex)) + != regbase::mod_x) + || !this->m_traits.isctype(*m_position, this->m_mask_space)) + this->append_literal(*m_position); + ++m_position; + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_open_paren() +{ + // + // skip the '(' and error check: + // + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + // + // begin by checking for a perl-style (?...) extension: + // + if( + ((this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) == 0) + || ((this->flags() & (regbase::main_option_type | regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex)) + ) + { + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question) + return parse_perl_extension(); + } + // + // update our mark count, and append the required state: + // + unsigned markid = 0; + if(0 == (this->flags() & regbase::nosubs)) + { + markid = ++m_mark_count; +#ifndef BOOST_NO_STD_DISTANCE + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair<std::size_t, std::size_t>(std::distance(m_base, m_position) - 1, 0)); +#else + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair<std::size_t, std::size_t>((m_position - m_base) - 1, 0)); +#endif + } + re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + std::ptrdiff_t last_paren_start = this->getoffset(pb); + // back up insertion point for alternations, and set new point: + std::ptrdiff_t last_alt_point = m_alt_insert_point; + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + // + // back up the current flags in case we have a nested (?imsx) group: + // + regex_constants::syntax_option_type opts = this->flags(); + bool old_case_change = m_has_case_change; + m_has_case_change = false; // no changes to this scope as yet... + // + // Back up branch reset data in case we have a nested (?|...) + // + int mark_reset = m_mark_reset; + m_mark_reset = -1; + // + // now recursively add more states, this will terminate when we get to a + // matching ')' : + // + parse_all(); + // + // Unwind pushed alternatives: + // + if(0 == unwind_alts(last_paren_start)) + return false; + // + // restore flags: + // + if(m_has_case_change) + { + // the case has changed in one or more of the alternatives + // within the scoped (...) block: we have to add a state + // to reset the case sensitivity: + static_cast<re_case*>( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = opts & regbase::icase; + } + this->flags(opts); + m_has_case_change = old_case_change; + // + // restore branch reset: + // + m_mark_reset = mark_reset; + // + // we either have a ')' or we have run out of characters prematurely: + // + if(m_position == m_end) + { + this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end)); + return false; + } + BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark); +#ifndef BOOST_NO_STD_DISTANCE + if(markid && (this->flags() & regbase::save_subexpression_location)) + this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position); +#else + if(markid && (this->flags() & regbase::save_subexpression_location)) + this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base); +#endif + ++m_position; + // + // append closing parenthesis state: + // + pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + this->m_paren_start = last_paren_start; + // + // restore the alternate insertion point: + // + this->m_alt_insert_point = last_alt_point; + // + // allow backrefs to this mark: + // + if((markid > 0) && (markid < sizeof(unsigned) * CHAR_BIT)) + this->m_backrefs |= 1u << (markid - 1); + + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_basic_escape() +{ + ++m_position; + bool result = true; + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::syntax_open_mark: + return parse_open_paren(); + case regex_constants::syntax_close_mark: + return false; + case regex_constants::syntax_plus: + if(this->flags() & regex_constants::bk_plus_qm) + { + ++m_position; + return parse_repeat(1); + } + else + return parse_literal(); + case regex_constants::syntax_question: + if(this->flags() & regex_constants::bk_plus_qm) + { + ++m_position; + return parse_repeat(0, 1); + } + else + return parse_literal(); + case regex_constants::syntax_open_brace: + if(this->flags() & regbase::no_intervals) + return parse_literal(); + ++m_position; + return parse_repeat_range(true); + case regex_constants::syntax_close_brace: + if(this->flags() & regbase::no_intervals) + return parse_literal(); + fail(regex_constants::error_brace, this->m_position - this->m_base); + return false; + case regex_constants::syntax_or: + if(this->flags() & regbase::bk_vbar) + return parse_alt(); + else + result = parse_literal(); + break; + case regex_constants::syntax_digit: + return parse_backref(); + case regex_constants::escape_type_start_buffer: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_buffer_start); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_end_buffer: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_buffer_end); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_word_assert: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_boundary); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_not_word_assert: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_within_word); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_left_word: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_start); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_right_word: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_end); + } + else + result = parse_literal(); + break; + default: + if(this->flags() & regbase::emacs_ex) + { + bool negate = true; + switch(*m_position) + { + case 'w': + negate = false; + // fall through: + case 'W': + { + basic_char_set<charT, traits> char_set; + if(negate) + char_set.negate(); + char_set.add_class(this->m_word_mask); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; + } + case 's': + negate = false; + // fall through: + case 'S': + return add_emacs_code(negate); + case 'c': + case 'C': + // not supported yet: + fail(regex_constants::error_escape, m_position - m_base); + return false; + default: + break; + } + } + result = parse_literal(); + break; + } + return result; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_extended_escape() +{ + ++m_position; + bool negate = false; // in case this is a character class escape: \w \d etc + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::escape_type_not_class: + negate = true; + // fall through: + case regex_constants::escape_type_class: + { +escape_type_class_jump: + typedef typename traits::char_class_type mask_type; + mask_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + basic_char_set<charT, traits> char_set; + if(negate) + char_set.negate(); + char_set.add_class(m); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; + } + // + // not a class, just a regular unknown escape: + // + this->append_literal(unescape_character()); + break; + } + case regex_constants::syntax_digit: + return parse_backref(); + case regex_constants::escape_type_left_word: + ++m_position; + this->append_state(syntax_element_word_start); + break; + case regex_constants::escape_type_right_word: + ++m_position; + this->append_state(syntax_element_word_end); + break; + case regex_constants::escape_type_start_buffer: + ++m_position; + this->append_state(syntax_element_buffer_start); + break; + case regex_constants::escape_type_end_buffer: + ++m_position; + this->append_state(syntax_element_buffer_end); + break; + case regex_constants::escape_type_word_assert: + ++m_position; + this->append_state(syntax_element_word_boundary); + break; + case regex_constants::escape_type_not_word_assert: + ++m_position; + this->append_state(syntax_element_within_word); + break; + case regex_constants::escape_type_Z: + ++m_position; + this->append_state(syntax_element_soft_buffer_end); + break; + case regex_constants::escape_type_Q: + return parse_QE(); + case regex_constants::escape_type_C: + return parse_match_any(); + case regex_constants::escape_type_X: + ++m_position; + this->append_state(syntax_element_combining); + break; + case regex_constants::escape_type_G: + ++m_position; + this->append_state(syntax_element_restart_continue); + break; + case regex_constants::escape_type_not_property: + negate = true; + // fall through: + case regex_constants::escape_type_property: + { + ++m_position; + char_class_type m; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + // maybe have \p{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + const charT* base = m_position; + // skip forward until we find enclosing brace: + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + m = this->m_traits.lookup_classname(++base, m_position++); + } + else + { + m = this->m_traits.lookup_classname(m_position, m_position+1); + ++m_position; + } + if(m != 0) + { + basic_char_set<charT, traits> char_set; + if(negate) + char_set.negate(); + char_set.add_class(m); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + return true; + } + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + case regex_constants::escape_type_reset_start_mark: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->index = -5; + pb->icase = this->flags() & regbase::icase; + this->m_pdata->m_data.align(); + ++m_position; + return true; + } + goto escape_type_class_jump; + case regex_constants::escape_type_line_ending: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + const charT* e = get_escape_R_string<charT>(); + const charT* old_position = m_position; + const charT* old_end = m_end; + const charT* old_base = m_base; + m_position = e; + m_base = e; + m_end = e + traits::length(e); + bool r = parse_all(); + m_position = ++old_position; + m_end = old_end; + m_base = old_base; + return r; + } + goto escape_type_class_jump; + case regex_constants::escape_type_extended_backref: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + bool have_brace = false; + bool negative = false; + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + // maybe have \g{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + have_brace = true; + } + negative = (*m_position == static_cast<charT>('-')); + if((negative) && (++m_position == m_end)) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + const charT* pc = m_position; + int i = this->m_traits.toi(pc, m_end, 10); + if(i < 0) + { + // Check for a named capture: + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + i = this->m_pdata->get_id(base, m_position); + pc = m_position; + } + if(negative) + i = 1 + m_mark_count - i; + if((i > 0) && (this->m_backrefs & (1u << (i-1)))) + { + m_position = pc; + re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = i; + pb->icase = this->flags() & regbase::icase; + } + else + { + fail(regex_constants::error_backref, m_position - m_end); + return false; + } + m_position = pc; + if(have_brace) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + ++m_position; + } + return true; + } + goto escape_type_class_jump; + case regex_constants::escape_type_control_v: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + goto escape_type_class_jump; + // fallthrough: + default: + this->append_literal(unescape_character()); + break; + } + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_match_any() +{ + // + // we have a '.' that can match any character: + // + ++m_position; + static_cast<re_dot*>( + this->append_state(syntax_element_wild, sizeof(re_dot)) + )->mask = static_cast<unsigned char>(this->flags() & regbase::no_mod_s + ? re_detail::force_not_newline + : this->flags() & regbase::mod_s ? + re_detail::force_newline : re_detail::dont_care); + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_t high) +{ + bool greedy = true; + bool pocessive = false; + std::size_t insert_point; + // + // when we get to here we may have a non-greedy ? mark still to come: + // + if((m_position != m_end) + && ( + (0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + || ((regbase::basic_syntax_group|regbase::emacs_ex) == (this->flags() & (regbase::main_option_type | regbase::emacs_ex))) + ) + ) + { + // OK we have a perl or emacs regex, check for a '?': + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question) + { + greedy = false; + ++m_position; + } + // for perl regexes only check for pocessive ++ repeats. + if((0 == (this->flags() & regbase::main_option_type)) + && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_plus)) + { + pocessive = true; + ++m_position; + } + } + if(0 == this->m_last_state) + { + fail(regex_constants::error_badrepeat, ::boost::re_detail::distance(m_base, m_position)); + return false; + } + if(this->m_last_state->type == syntax_element_endmark) + { + // insert a repeat before the '(' matching the last ')': + insert_point = this->m_paren_start; + } + else if((this->m_last_state->type == syntax_element_literal) && (static_cast<re_literal*>(this->m_last_state)->length > 1)) + { + // the last state was a literal with more than one character, split it in two: + re_literal* lit = static_cast<re_literal*>(this->m_last_state); + charT c = (static_cast<charT*>(static_cast<void*>(lit+1)))[lit->length - 1]; + --(lit->length); + // now append new state: + lit = static_cast<re_literal*>(this->append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT))); + lit->length = 1; + (static_cast<charT*>(static_cast<void*>(lit+1)))[0] = c; + insert_point = this->getoffset(this->m_last_state); + } + else + { + // repeat the last state whatever it was, need to add some error checking here: + switch(this->m_last_state->type) + { + case syntax_element_start_line: + case syntax_element_end_line: + case syntax_element_word_boundary: + case syntax_element_within_word: + case syntax_element_word_start: + case syntax_element_word_end: + case syntax_element_buffer_start: + case syntax_element_buffer_end: + case syntax_element_alt: + case syntax_element_soft_buffer_end: + case syntax_element_restart_continue: + case syntax_element_jump: + case syntax_element_startmark: + case syntax_element_backstep: + // can't legally repeat any of the above: + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + default: + // do nothing... + break; + } + insert_point = this->getoffset(this->m_last_state); + } + // + // OK we now know what to repeat, so insert the repeat around it: + // + re_repeat* rep = static_cast<re_repeat*>(this->insert_state(insert_point, syntax_element_rep, re_repeater_size)); + rep->min = low; + rep->max = high; + rep->greedy = greedy; + rep->leading = false; + // store our repeater position for later: + std::ptrdiff_t rep_off = this->getoffset(rep); + // and append a back jump to the repeat: + re_jump* jmp = static_cast<re_jump*>(this->append_state(syntax_element_jump, sizeof(re_jump))); + jmp->alt.i = rep_off - this->getoffset(jmp); + this->m_pdata->m_data.align(); + // now fill in the alt jump for the repeat: + rep = static_cast<re_repeat*>(this->getaddress(rep_off)); + rep->alt.i = this->m_pdata->m_data.size() - rep_off; + // + // If the repeat is pocessive then bracket the repeat with a (?>...) + // independent sub-expression construct: + // + if(pocessive) + { + re_brace* pb = static_cast<re_brace*>(this->insert_state(insert_point, syntax_element_startmark, sizeof(re_brace))); + pb->index = -3; + pb->icase = this->flags() & regbase::icase; + re_jump* jmp = static_cast<re_jump*>(this->insert_state(insert_point + sizeof(re_brace), syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp); + pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = -3; + pb->icase = this->flags() & regbase::icase; + } + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic) +{ + // + // parse a repeat-range: + // + std::size_t min, max; + int v; + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + // fail if at end: + if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base); + return false; + } + // get min: + v = this->m_traits.toi(m_position, m_end, 10); + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(v < 0) + { + fail(regex_constants::error_badbrace, this->m_position - this->m_base); + return false; + } + else if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base); + return false; + } + min = v; + // see if we have a comma: + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma) + { + // move on and error check: + ++m_position; + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base); + return false; + } + // get the value if any: + v = this->m_traits.toi(m_position, m_end, 10); + max = (v >= 0) ? v : (std::numeric_limits<std::size_t>::max)(); + } + else + { + // no comma, max = min: + max = min; + } + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + // OK now check trailing }: + if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base); + return false; + } + if(isbasic) + { + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_escape) + { + ++m_position; + if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base); + return false; + } + } + else + { + fail(regex_constants::error_badbrace, this->m_position - this->m_base); + return false; + } + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_brace) + ++m_position; + else + { + fail(regex_constants::error_badbrace, this->m_position - this->m_base); + return false; + } + // + // finally go and add the repeat, unless error: + // + if(min > max) + { + fail(regex_constants::error_badbrace, this->m_position - this->m_base); + return false; + } + return parse_repeat(min, max); +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_alt() +{ + // + // error check: if there have been no previous states, + // or if the last state was a '(' then error: + // + if( + ((this->m_last_state == 0) || (this->m_last_state->type == syntax_element_startmark)) + && + !( + ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) + && + ((this->flags() & regbase::no_empty_expressions) == 0) + ) + ) + { + fail(regex_constants::error_empty, this->m_position - this->m_base); + return false; + } + // + // Reset mark count if required: + // + if(m_max_mark < m_mark_count) + m_max_mark = m_mark_count; + if(m_mark_reset >= 0) + m_mark_count = m_mark_reset; + + ++m_position; + // + // we need to append a trailing jump: + // + re_syntax_base* pj = this->append_state(re_detail::syntax_element_jump, sizeof(re_jump)); + std::ptrdiff_t jump_offset = this->getoffset(pj); + // + // now insert the alternative: + // + re_alt* palt = static_cast<re_alt*>(this->insert_state(this->m_alt_insert_point, syntax_element_alt, re_alt_size)); + jump_offset += re_alt_size; + this->m_pdata->m_data.align(); + palt->alt.i = this->m_pdata->m_data.size() - this->getoffset(palt); + // + // update m_alt_insert_point so that the next alternate gets + // inserted at the start of the second of the two we've just created: + // + this->m_alt_insert_point = this->m_pdata->m_data.size(); + // + // the start of this alternative must have a case changes state + // if the current block has messed around with case changes: + // + if(m_has_case_change) + { + static_cast<re_case*>( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = this->m_icase; + } + // + // push the alternative onto our stack, a recursive + // implementation here is easier to understand (and faster + // as it happens), but causes all kinds of stack overflow problems + // on programs with small stacks (COM+). + // + m_alt_jumps.push_back(jump_offset); + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_set() +{ + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + basic_char_set<charT, traits> char_set; + + const charT* base = m_position; // where the '[' was + const charT* item_base = m_position; // where the '[' or '^' was + + while(m_position != m_end) + { + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_caret: + if(m_position == base) + { + char_set.negate(); + ++m_position; + item_base = m_position; + } + else + parse_set_literal(char_set); + break; + case regex_constants::syntax_close_set: + if(m_position == item_base) + { + parse_set_literal(char_set); + break; + } + else + { + ++m_position; + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_range, m_position - m_base); + return false; + } + } + return true; + case regex_constants::syntax_open_set: + if(parse_inner_set(char_set)) + break; + return true; + case regex_constants::syntax_escape: + { + // + // look ahead and see if this is a character class shortcut + // \d \w \s etc... + // + ++m_position; + if(this->m_traits.escape_syntax_type(*m_position) + == regex_constants::escape_type_class) + { + char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + char_set.add_class(m); + ++m_position; + break; + } + } + else if(this->m_traits.escape_syntax_type(*m_position) + == regex_constants::escape_type_not_class) + { + // negated character class: + char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + char_set.add_negated_class(m); + ++m_position; + break; + } + } + // not a character class, just a regular escape: + --m_position; + parse_set_literal(char_set); + break; + } + default: + parse_set_literal(char_set); + break; + } + } + return m_position != m_end; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, traits>& char_set) +{ + // + // we have either a character class [:name:] + // a collating element [.name.] + // or an equivalence class [=name=] + // + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_dot: + // + // a collating element is treated as a literal: + // + --m_position; + parse_set_literal(char_set); + return true; + case regex_constants::syntax_colon: + { + // check that character classes are actually enabled: + if((this->flags() & (regbase::main_option_type | regbase::no_char_classes)) + == (regbase::basic_syntax_group | regbase::no_char_classes)) + { + --m_position; + parse_set_literal(char_set); + return true; + } + // skip the ':' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching ':]' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_colon)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + // + // check for negated class: + // + bool negated = false; + if(this->m_traits.syntax_type(*name_first) == regex_constants::syntax_caret) + { + ++name_first; + negated = true; + } + typedef typename traits::char_class_type mask_type; + mask_type m = this->m_traits.lookup_classname(name_first, name_last); + if(m == 0) + { + if(char_set.empty() && (name_last - name_first == 1)) + { + // maybe a special case: + ++m_position; + if( (m_position != m_end) + && (this->m_traits.syntax_type(*m_position) + == regex_constants::syntax_close_set)) + { + if(this->m_traits.escape_syntax_type(*name_first) + == regex_constants::escape_type_left_word) + { + ++m_position; + this->append_state(syntax_element_word_start); + return false; + } + if(this->m_traits.escape_syntax_type(*name_first) + == regex_constants::escape_type_right_word) + { + ++m_position; + this->append_state(syntax_element_word_end); + return false; + } + } + } + fail(regex_constants::error_ctype, name_first - m_base); + return false; + } + if(negated == false) + char_set.add_class(m); + else + char_set.add_negated_class(m); + ++m_position; + break; + } + case regex_constants::syntax_equal: + { + // skip the '=' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching '=]' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_brack, m_position - m_base); + return false; + } + string_type m = this->m_traits.lookup_collatename(name_first, name_last); + if((0 == m.size()) || (m.size() > 2)) + { + fail(regex_constants::error_collate, name_first - m_base); + return false; + } + digraph<charT> d; + d.first = m[0]; + if(m.size() > 1) + d.second = m[1]; + else + d.second = 0; + char_set.add_equivalent(d); + ++m_position; + break; + } + default: + --m_position; + parse_set_literal(char_set); + break; + } + return true; +} + +template <class charT, class traits> +void basic_regex_parser<charT, traits>::parse_set_literal(basic_char_set<charT, traits>& char_set) +{ + digraph<charT> start_range(get_next_set_literal(char_set)); + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) + { + // we have a range: + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set) + { + digraph<charT> end_range = get_next_set_literal(char_set); + char_set.add_range(start_range, end_range); + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) + { + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_set) + { + // trailing - : + --m_position; + return; + } + fail(regex_constants::error_range, m_position - m_base); + return; + } + return; + } + --m_position; + } + char_set.add_single(start_range); +} + +template <class charT, class traits> +digraph<charT> basic_regex_parser<charT, traits>::get_next_set_literal(basic_char_set<charT, traits>& char_set) +{ + digraph<charT> result; + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_dash: + if(!char_set.empty()) + { + // see if we are at the end of the set: + if((++m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_range, m_position - m_base); + return result; + } + --m_position; + } + result.first = *m_position++; + return result; + case regex_constants::syntax_escape: + // check to see if escapes are supported first: + if(this->flags() & regex_constants::no_escape_in_lists) + { + result = *m_position++; + break; + } + ++m_position; + result = unescape_character(); + break; + case regex_constants::syntax_open_set: + { + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, m_position - m_base); + return result; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot) + { + --m_position; + result.first = *m_position; + ++m_position; + return result; + } + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, m_position - m_base); + return result; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching ':]' + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + ++m_position; + string_type s = this->m_traits.lookup_collatename(name_first, name_last); + if(s.empty() || (s.size() > 2)) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + result.first = s[0]; + if(s.size() > 1) + result.second = s[1]; + else + result.second = 0; + return result; + } + default: + result = *m_position++; + } + return result; +} + +// +// does a value fit in the specified charT type? +// +template <class charT> +bool valid_value(charT, int v, const mpl::true_&) +{ + return (v >> (sizeof(charT) * CHAR_BIT)) == 0; +} +template <class charT> +bool valid_value(charT, int, const mpl::false_&) +{ + return true; // v will alsways fit in a charT +} +template <class charT> +bool valid_value(charT c, int v) +{ + return valid_value(c, v, mpl::bool_<(sizeof(charT) < sizeof(int))>()); +} + +template <class charT, class traits> +charT basic_regex_parser<charT, traits>::unescape_character() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + charT result(0); + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::escape_type_control_a: + result = charT('\a'); + break; + case regex_constants::escape_type_e: + result = charT(27); + break; + case regex_constants::escape_type_control_f: + result = charT('\f'); + break; + case regex_constants::escape_type_control_n: + result = charT('\n'); + break; + case regex_constants::escape_type_control_r: + result = charT('\r'); + break; + case regex_constants::escape_type_control_t: + result = charT('\t'); + break; + case regex_constants::escape_type_control_v: + result = charT('\v'); + break; + case regex_constants::escape_type_word_assert: + result = charT('\b'); + break; + case regex_constants::escape_type_ascii_control: + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + /* + if((*m_position < charT('@')) + || (*m_position > charT(125)) ) + { + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + */ + result = static_cast<charT>(*m_position % 32); + break; + case regex_constants::escape_type_hex: + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + // maybe have \x{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + int i = this->m_traits.toi(m_position, m_end, 16); + if((m_position == m_end) + || (i < 0) + || ((std::numeric_limits<charT>::is_specialized) && (i > (int)(std::numeric_limits<charT>::max)())) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + { + fail(regex_constants::error_badbrace, m_position - m_base); + return result; + } + ++m_position; + result = charT(i); + } + else + { + std::ptrdiff_t len = (std::min)(static_cast<std::ptrdiff_t>(2), m_end - m_position); + int i = this->m_traits.toi(m_position, m_position + len, 16); + if((i < 0) + || !valid_value(charT(0), i)) + { + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + result = charT(i); + } + return result; + case regex_constants::syntax_digit: + { + // an octal escape sequence, the first character must be a zero + // followed by up to 3 octal digits: + std::ptrdiff_t len = (std::min)(::boost::re_detail::distance(m_position, m_end), static_cast<std::ptrdiff_t>(4)); + const charT* bp = m_position; + int val = this->m_traits.toi(bp, bp + 1, 8); + if(val != 0) + { + // Oops not an octal escape after all: + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + val = this->m_traits.toi(m_position, m_position + len, 8); + if(val < 0) + { + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + return static_cast<charT>(val); + } + case regex_constants::escape_type_named_char: + { + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + // maybe have \N{name} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + const charT* base = m_position; + // skip forward until we find enclosing brace: + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + string_type s = this->m_traits.lookup_collatename(++base, m_position++); + if(s.empty()) + { + fail(regex_constants::error_collate, m_position - m_base); + return false; + } + if(s.size() == 1) + { + return s[0]; + } + } + // fall through is a failure: + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + default: + result = *m_position; + break; + } + ++m_position; + return result; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_backref() +{ + BOOST_ASSERT(m_position != m_end); + const charT* pc = m_position; + int i = this->m_traits.toi(pc, pc + 1, 10); + if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs))) + { + // not a backref at all but an octal escape sequence: + charT c = unescape_character(); + this->append_literal(c); + } + else if((i > 0) && (this->m_backrefs & (1u << (i-1)))) + { + m_position = pc; + re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = i; + pb->icase = this->flags() & regbase::icase; + } + else + { + fail(regex_constants::error_backref, m_position - m_end); + return false; + } + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_QE() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // + // parse a \Q...\E sequence: + // + ++m_position; // skip the Q + const charT* start = m_position; + const charT* end; + do + { + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape)) + ++m_position; + if(m_position == m_end) + { + // a \Q...\E sequence may terminate with the end of the expression: + end = m_position; + break; + } + if(++m_position == m_end) // skip the escape + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + // check to see if it's a \E: + if(this->m_traits.escape_syntax_type(*m_position) == regex_constants::escape_type_E) + { + ++m_position; + end = m_position - 2; + break; + } + // otherwise go round again: + }while(true); + // + // now add all the character between the two escapes as literals: + // + while(start != end) + { + this->append_literal(*start); + ++start; + } + return true; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::parse_perl_extension() +{ + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + // + // treat comments as a special case, as these + // are the only ones that don't start with a leading + // startmark state: + // + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_hash) + { + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) + {} + return true; + } + // + // backup some state, and prepare the way: + // + int markid = 0; + std::ptrdiff_t jump_offset = 0; + re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->icase = this->flags() & regbase::icase; + std::ptrdiff_t last_paren_start = this->getoffset(pb); + // back up insertion point for alternations, and set new point: + std::ptrdiff_t last_alt_point = m_alt_insert_point; + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + std::ptrdiff_t expected_alt_point = m_alt_insert_point; + bool restore_flags = true; + regex_constants::syntax_option_type old_flags = this->flags(); + bool old_case_change = m_has_case_change; + m_has_case_change = false; + charT name_delim; + int mark_reset = m_mark_reset; + m_mark_reset = -1; + int v; + // + // select the actual extension used: + // + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_or: + m_mark_reset = m_mark_count; + // fall through: + case regex_constants::syntax_colon: + // + // a non-capturing mark: + // + pb->index = markid = 0; + ++m_position; + break; + case regex_constants::syntax_digit: + { + // + // a recursive subexpression: + // + v = this->m_traits.toi(m_position, m_end, 10); + if((v < 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } +insert_recursion: + pb->index = markid = 0; + static_cast<re_jump*>(this->append_state(syntax_element_recurse, sizeof(re_jump)))->alt.i = v; + static_cast<re_case*>( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = this->flags() & regbase::icase; + break; + } + case regex_constants::syntax_plus: + // + // A forward-relative recursive subexpression: + // + ++m_position; + v = this->m_traits.toi(m_position, m_end, 10); + if((v <= 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + v += m_mark_count; + goto insert_recursion; + case regex_constants::syntax_dash: + // + // Possibly a backward-relative recursive subexpression: + // + ++m_position; + v = this->m_traits.toi(m_position, m_end, 10); + if(v <= 0) + { + --m_position; + // Oops not a relative recursion at all, but a (?-imsx) group: + goto option_group_jump; + } + v = m_mark_count + 1 - v; + if(v <= 0) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + goto insert_recursion; + case regex_constants::syntax_equal: + pb->index = markid = -1; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::syntax_not: + pb->index = markid = -2; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::escape_type_left_word: + { + // a lookbehind assertion: + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + regex_constants::syntax_type t = this->m_traits.syntax_type(*m_position); + if(t == regex_constants::syntax_not) + pb->index = markid = -2; + else if(t == regex_constants::syntax_equal) + pb->index = markid = -1; + else + { + // Probably a named capture which also starts (?< : + name_delim = '>'; + --m_position; + goto named_capture_jump; + } + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->append_state(syntax_element_backstep, sizeof(re_brace)); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + } + case regex_constants::escape_type_right_word: + // + // an independent sub-expression: + // + pb->index = markid = -3; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::syntax_open_mark: + { + // a conditional expression: + pb->index = markid = -4; + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + int v = this->m_traits.toi(m_position, m_end, 10); + if(*m_position == charT('R')) + { + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(*m_position == charT('&')) + { + const charT* base = ++m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + v = -static_cast<int>(hash_value_from_capture_name(base, m_position)); + } + else + { + v = -this->m_traits.toi(m_position, m_end, 10); + } + re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v < 0 ? (v - 1) : 0; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + } + else if((*m_position == charT('\'')) || (*m_position == charT('<'))) + { + const charT* base = ++m_position; + while((m_position != m_end) && (*m_position != charT('>')) && (*m_position != charT('\''))) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + v = static_cast<int>(hash_value_from_capture_name(base, m_position)); + re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v; + if((*m_position != charT('>')) && (*m_position != charT('\'')) || (++m_position == m_end)) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + } + else if(*m_position == charT('D')) + { + const char* def = "DEFINE"; + while(*def && (m_position != m_end) && (*m_position == charT(*def))) + ++m_position, ++def; + if((m_position == m_end) || *def) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = 9999; // special magic value! + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + } + else if(v > 0) + { + re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + } + else + { + // verify that we have a lookahead or lookbehind assert: + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word) + { + if(++m_position == m_end) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not)) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + m_position -= 3; + } + else + { + if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not)) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + m_position -= 2; + } + } + break; + } + case regex_constants::syntax_close_mark: + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + case regex_constants::escape_type_end_buffer: + { + name_delim = *m_position; +named_capture_jump: + markid = 0; + if(0 == (this->flags() & regbase::nosubs)) + { + markid = ++m_mark_count; + #ifndef BOOST_NO_STD_DISTANCE + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair<std::size_t, std::size_t>(std::distance(m_base, m_position) - 2, 0)); + #else + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair<std::size_t, std::size_t>((m_position - m_base) - 2, 0)); + #endif + } + pb->index = markid; + const charT* base = ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + while((m_position != m_end) && (*m_position != name_delim)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + this->m_pdata->set_name(base, m_position, markid); + ++m_position; + break; + } + default: + if(*m_position == charT('R')) + { + ++m_position; + v = 0; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + goto insert_recursion; + } + if(*m_position == charT('&')) + { + ++m_position; + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + v = static_cast<int>(hash_value_from_capture_name(base, m_position)); + goto insert_recursion; + } + if(*m_position == charT('P')) + { + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + if(*m_position == charT('>')) + { + ++m_position; + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + v = static_cast<int>(hash_value_from_capture_name(base, m_position)); + goto insert_recursion; + } + } + // + // lets assume that we have a (?imsx) group and try and parse it: + // +option_group_jump: + regex_constants::syntax_option_type opts = parse_options(); + if(m_position == m_end) + return false; + // make a note of whether we have a case change: + m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase)); + pb->index = markid = 0; + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark) + { + // update flags and carry on as normal: + this->flags(opts); + restore_flags = false; + old_case_change |= m_has_case_change; // defer end of scope by one ')' + } + else if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_colon) + { + // update flags and carry on until the matching ')' is found: + this->flags(opts); + ++m_position; + } + else + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + + // finally append a case change state if we need it: + if(m_has_case_change) + { + static_cast<re_case*>( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = opts & regbase::icase; + } + + } + // + // now recursively add more states, this will terminate when we get to a + // matching ')' : + // + parse_all(); + // + // Unwind alternatives: + // + if(0 == unwind_alts(last_paren_start)) + return false; + // + // we either have a ')' or we have run out of characters prematurely: + // + if(m_position == m_end) + { + this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end)); + return false; + } + BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark); + ++m_position; + // + // restore the flags: + // + if(restore_flags) + { + // append a case change state if we need it: + if(m_has_case_change) + { + static_cast<re_case*>( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = old_flags & regbase::icase; + } + this->flags(old_flags); + } + // + // set up the jump pointer if we have one: + // + if(jump_offset) + { + this->m_pdata->m_data.align(); + re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset)); + jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp); + if(this->m_last_state == jmp) + { + // Oops... we didn't have anything inside the assertion: + fail(regex_constants::error_empty, m_position - m_base); + return false; + } + } + // + // verify that if this is conditional expression, that we do have + // an alternative, if not add one: + // + if(markid == -4) + { + re_syntax_base* b = this->getaddress(expected_alt_point); + // Make sure we have exactly one alternative following this state: + if(b->type != syntax_element_alt) + { + re_alt* alt = static_cast<re_alt*>(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt))); + alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt); + } + else if(this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt) + { + // Can't have seen more than one alternative: + fail(regex_constants::error_bad_pattern, m_position - m_base); + return false; + } + else + { + // We must *not* have seen an alternative inside a (DEFINE) block: + b = this->getaddress(b->next.i, b); + if((b->type == syntax_element_assert_backref) && (static_cast<re_brace*>(b)->index == 9999)) + { + fail(regex_constants::error_bad_pattern, m_position - m_base); + return false; + } + } + // check for invalid repetition of next state: + b = this->getaddress(expected_alt_point); + b = this->getaddress(static_cast<re_alt*>(b)->next.i, b); + if((b->type != syntax_element_assert_backref) + && (b->type != syntax_element_startmark)) + { + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + } + } + // + // append closing parenthesis state: + // + pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + this->m_paren_start = last_paren_start; + // + // restore the alternate insertion point: + // + this->m_alt_insert_point = last_alt_point; + // + // and the case change data: + // + m_has_case_change = old_case_change; + // + // And the mark_reset data: + // + if(m_max_mark > m_mark_count) + { + m_mark_count = m_max_mark; + } + m_mark_reset = mark_reset; + + + if(markid > 0) + { +#ifndef BOOST_NO_STD_DISTANCE + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position) - 1; +#else + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base) - 1; +#endif + // + // allow backrefs to this mark: + // + if((markid > 0) && (markid < (int)(sizeof(unsigned) * CHAR_BIT))) + this->m_backrefs |= 1u << (markid - 1); + } + return true; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::add_emacs_code(bool negate) +{ + // + // parses an emacs style \sx or \Sx construct. + // + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + basic_char_set<charT, traits> char_set; + if(negate) + char_set.negate(); + + static const charT s_punct[5] = { 'p', 'u', 'n', 'c', 't', }; + + switch(*m_position) + { + case 's': + case ' ': + char_set.add_class(this->m_mask_space); + break; + case 'w': + char_set.add_class(this->m_word_mask); + break; + case '_': + char_set.add_single(digraph<charT>(charT('$'))); + char_set.add_single(digraph<charT>(charT('&'))); + char_set.add_single(digraph<charT>(charT('*'))); + char_set.add_single(digraph<charT>(charT('+'))); + char_set.add_single(digraph<charT>(charT('-'))); + char_set.add_single(digraph<charT>(charT('_'))); + char_set.add_single(digraph<charT>(charT('<'))); + char_set.add_single(digraph<charT>(charT('>'))); + break; + case '.': + char_set.add_class(this->m_traits.lookup_classname(s_punct, s_punct+5)); + break; + case '(': + char_set.add_single(digraph<charT>(charT('('))); + char_set.add_single(digraph<charT>(charT('['))); + char_set.add_single(digraph<charT>(charT('{'))); + break; + case ')': + char_set.add_single(digraph<charT>(charT(')'))); + char_set.add_single(digraph<charT>(charT(']'))); + char_set.add_single(digraph<charT>(charT('}'))); + break; + case '"': + char_set.add_single(digraph<charT>(charT('"'))); + char_set.add_single(digraph<charT>(charT('\''))); + char_set.add_single(digraph<charT>(charT('`'))); + break; + case '\'': + char_set.add_single(digraph<charT>(charT('\''))); + char_set.add_single(digraph<charT>(charT(','))); + char_set.add_single(digraph<charT>(charT('#'))); + break; + case '<': + char_set.add_single(digraph<charT>(charT(';'))); + break; + case '>': + char_set.add_single(digraph<charT>(charT('\n'))); + char_set.add_single(digraph<charT>(charT('\f'))); + break; + default: + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; +} + +template <class charT, class traits> +regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_options() +{ + // we have a (?imsx-imsx) group, convert it into a set of flags: + regex_constants::syntax_option_type f = this->flags(); + bool breakout = false; + do + { + switch(*m_position) + { + case 's': + f |= regex_constants::mod_s; + f &= ~regex_constants::no_mod_s; + break; + case 'm': + f &= ~regex_constants::no_mod_m; + break; + case 'i': + f |= regex_constants::icase; + break; + case 'x': + f |= regex_constants::mod_x; + break; + default: + breakout = true; + continue; + } + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + } + while(!breakout); + + if(*m_position == static_cast<charT>('-')) + { + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + do + { + switch(*m_position) + { + case 's': + f &= ~regex_constants::mod_s; + f |= regex_constants::no_mod_s; + break; + case 'm': + f |= regex_constants::no_mod_m; + break; + case 'i': + f &= ~regex_constants::icase; + break; + case 'x': + f &= ~regex_constants::mod_x; + break; + default: + breakout = true; + continue; + } + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + } + while(!breakout); + } + return f; +} + +template <class charT, class traits> +bool basic_regex_parser<charT, traits>::unwind_alts(std::ptrdiff_t last_paren_start) +{ + // + // If we didn't actually add any states after the last + // alternative then that's an error: + // + if((this->m_alt_insert_point == static_cast<std::ptrdiff_t>(this->m_pdata->m_data.size())) + && m_alt_jumps.size() && (m_alt_jumps.back() > last_paren_start) + && + !( + ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) + && + ((this->flags() & regbase::no_empty_expressions) == 0) + ) + ) + { + fail(regex_constants::error_empty, this->m_position - this->m_base); + return false; + } + // + // Fix up our alternatives: + // + while(m_alt_jumps.size() && (m_alt_jumps.back() > last_paren_start)) + { + // + // fix up the jump to point to the end of the states + // that we've just added: + // + std::ptrdiff_t jump_offset = m_alt_jumps.back(); + m_alt_jumps.pop_back(); + this->m_pdata->m_data.align(); + re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset)); + BOOST_ASSERT(jmp->type == syntax_element_jump); + jmp->alt.i = this->m_pdata->m_data.size() - jump_offset; + } + return true; +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace re_detail +} // namespace boost + +#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 + +#endif diff --git a/ext/boost/regex/v4/c_regex_traits.hpp b/ext/boost/regex/v4/c_regex_traits.hpp new file mode 100644 index 0000000000..d99b0f341b --- /dev/null +++ b/ext/boost/regex/v4/c_regex_traits.hpp @@ -0,0 +1,211 @@ +/* + * + * 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 c_regex_traits.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression traits class that wraps the global C locale. + */ + +#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_C_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include <boost/regex/v4/regex_workaround.hpp> +#endif + +#include <cctype> + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strlen; using ::tolower; +} +#endif + +#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 + +namespace boost{ + +template <class charT> +struct c_regex_traits; + +template<> +struct BOOST_REGEX_DECL c_regex_traits<char> +{ + c_regex_traits(){} + typedef char char_type; + typedef std::size_t size_type; + typedef std::string string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::strlen)(p); + } + + char translate(char c) const + { + return c; + } + char translate_nocase(char c) const + { + return static_cast<char>((std::tolower)(static_cast<unsigned char>(c))); + } + + static string_type BOOST_REGEX_CALL transform(const char* p1, const char* p2); + static string_type BOOST_REGEX_CALL transform_primary(const char* p1, const char* p2); + + static char_class_type BOOST_REGEX_CALL lookup_classname(const char* p1, const char* p2); + static string_type BOOST_REGEX_CALL lookup_collatename(const char* p1, const char* p2); + + static bool BOOST_REGEX_CALL isctype(char, char_class_type); + static int BOOST_REGEX_CALL value(char, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#ifndef BOOST_NO_WREGEX +template<> +struct BOOST_REGEX_DECL c_regex_traits<wchar_t> +{ + c_regex_traits(){} + typedef wchar_t char_type; + typedef std::size_t size_type; + typedef std::wstring string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::wcslen)(p); + } + + wchar_t translate(wchar_t c) const + { + return c; + } + wchar_t translate_nocase(wchar_t c) const + { + return (std::towlower)(c); + } + + static string_type BOOST_REGEX_CALL transform(const wchar_t* p1, const wchar_t* p2); + static string_type BOOST_REGEX_CALL transform_primary(const wchar_t* p1, const wchar_t* p2); + + static char_class_type BOOST_REGEX_CALL lookup_classname(const wchar_t* p1, const wchar_t* p2); + static string_type BOOST_REGEX_CALL lookup_collatename(const wchar_t* p1, const wchar_t* p2); + + static bool BOOST_REGEX_CALL isctype(wchar_t, char_class_type); + static int BOOST_REGEX_CALL value(wchar_t, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +// +// Provide an unsigned short version as well, so the user can link to this +// no matter whether they build with /Zc:wchar_t or not (MSVC specific). +// +template<> +struct BOOST_REGEX_DECL c_regex_traits<unsigned short> +{ + c_regex_traits(){} + typedef unsigned short char_type; + typedef std::size_t size_type; + typedef std::basic_string<unsigned short> string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::wcslen)((const wchar_t*)p); + } + + unsigned short translate(unsigned short c) const + { + return c; + } + unsigned short translate_nocase(unsigned short c) const + { + return (std::towlower)((wchar_t)c); + } + + static string_type BOOST_REGEX_CALL transform(const unsigned short* p1, const unsigned short* p2); + static string_type BOOST_REGEX_CALL transform_primary(const unsigned short* p1, const unsigned short* p2); + + static char_class_type BOOST_REGEX_CALL lookup_classname(const unsigned short* p1, const unsigned short* p2); + static string_type BOOST_REGEX_CALL lookup_collatename(const unsigned short* p1, const unsigned short* p2); + + static bool BOOST_REGEX_CALL isctype(unsigned short, char_class_type); + static int BOOST_REGEX_CALL value(unsigned short, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#endif + +#endif // BOOST_NO_WREGEX + +} + +#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 + +#endif + + + diff --git a/ext/boost/regex/v4/char_regex_traits.hpp b/ext/boost/regex/v4/char_regex_traits.hpp new file mode 100644 index 0000000000..e8a501ca00 --- /dev/null +++ b/ext/boost/regex/v4/char_regex_traits.hpp @@ -0,0 +1,81 @@ +/* + * + * Copyright (c) 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 char_regex_traits.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares deprecated traits classes char_regex_traits<>. + */ + + +#ifndef BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP +#define BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP + +#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 + +namespace boost{ + +namespace deprecated{ +// +// class char_regex_traits_i +// provides case insensitive traits classes (deprecated): +template <class charT> +class char_regex_traits_i : public regex_traits<charT> {}; + +template<> +class char_regex_traits_i<char> : public regex_traits<char> +{ +public: + typedef char char_type; + typedef unsigned char uchar_type; + typedef unsigned int size_type; + typedef regex_traits<char> base_type; + +}; + +#ifndef BOOST_NO_WREGEX +template<> +class char_regex_traits_i<wchar_t> : public regex_traits<wchar_t> +{ +public: + typedef wchar_t char_type; + typedef unsigned short uchar_type; + typedef unsigned int size_type; + typedef regex_traits<wchar_t> base_type; + +}; +#endif +} // namespace deprecated +} // namespace boost + +#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 + +#endif // include + diff --git a/ext/boost/regex/v4/cpp_regex_traits.hpp b/ext/boost/regex/v4/cpp_regex_traits.hpp new file mode 100644 index 0000000000..7ce3ed300e --- /dev/null +++ b/ext/boost/regex/v4/cpp_regex_traits.hpp @@ -0,0 +1,1086 @@ +/* + * + * 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 cpp_regex_traits.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression traits class cpp_regex_traits. + */ + +#ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED + +#include <boost/config.hpp> + +#ifndef BOOST_NO_STD_LOCALE + +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include <boost/regex/pattern_except.hpp> +#endif +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include <boost/regex/v4/regex_traits_defaults.hpp> +#endif +#ifdef BOOST_HAS_THREADS +#include <boost/regex/pending/static_mutex.hpp> +#endif +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#include <boost/regex/v4/primary_transform.hpp> +#endif +#ifndef BOOST_REGEX_OBJECT_CACHE_HPP +#include <boost/regex/pending/object_cache.hpp> +#endif + +#include <istream> +#include <ios> +#include <climits> + +#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:4786) +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template <class charT> +class cpp_regex_traits; + +namespace re_detail{ + +// +// class parser_buf: +// acts as a stream buffer which wraps around a pair of pointers: +// +template <class charT, + class traits = ::std::char_traits<charT> > +class parser_buf : public ::std::basic_streambuf<charT, traits> +{ + typedef ::std::basic_streambuf<charT, traits> base_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::char_type char_type; + typedef typename base_type::pos_type pos_type; + typedef ::std::streamsize streamsize; + typedef typename base_type::off_type off_type; +public: + parser_buf() : base_type() { setbuf(0, 0); } + const charT* getnext() { return this->gptr(); } +protected: + std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n); + typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which); + typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which); +private: + parser_buf& operator=(const parser_buf&); + parser_buf(const parser_buf&); +}; + +template<class charT, class traits> +std::basic_streambuf<charT, traits>* +parser_buf<charT, traits>::setbuf(char_type* s, streamsize n) +{ + this->setg(s, s, s + n); + return this; +} + +template<class charT, class traits> +typename parser_buf<charT, traits>::pos_type +parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) +{ + if(which & ::std::ios_base::out) + return pos_type(off_type(-1)); + std::ptrdiff_t size = this->egptr() - this->eback(); + std::ptrdiff_t pos = this->gptr() - this->eback(); + charT* g = this->eback(); + switch(way) + { + case ::std::ios_base::beg: + if((off < 0) || (off > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + off, g + size); + break; + case ::std::ios_base::end: + if((off < 0) || (off > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + size - off, g + size); + break; + case ::std::ios_base::cur: + { + std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off); + if((newpos < 0) || (newpos > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + newpos, g + size); + break; + } + default: ; + } +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4244) +#endif + return static_cast<pos_type>(this->gptr() - this->eback()); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template<class charT, class traits> +typename parser_buf<charT, traits>::pos_type +parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which) +{ + if(which & ::std::ios_base::out) + return pos_type(off_type(-1)); + off_type size = static_cast<off_type>(this->egptr() - this->eback()); + charT* g = this->eback(); + if(off_type(sp) <= size) + { + this->setg(g, g + off_type(sp), g + size); + } + return pos_type(off_type(-1)); +} + +// +// class cpp_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template <class charT> +struct cpp_regex_traits_base +{ + cpp_regex_traits_base(const std::locale& l) + { imbue(l); } + std::locale imbue(const std::locale& l); + + std::locale m_locale; + std::ctype<charT> const* m_pctype; +#ifndef BOOST_NO_STD_MESSAGES + std::messages<charT> const* m_pmessages; +#endif + std::collate<charT> const* m_pcollate; + + bool operator<(const cpp_regex_traits_base& b)const + { + if(m_pctype == b.m_pctype) + { +#ifndef BOOST_NO_STD_MESSAGES + if(m_pmessages == b.m_pmessages) + { + } + return m_pmessages < b.m_pmessages; +#else + return m_pcollate < b.m_pcollate; +#endif + } + return m_pctype < b.m_pctype; + } + bool operator==(const cpp_regex_traits_base& b)const + { + return (m_pctype == b.m_pctype) +#ifndef BOOST_NO_STD_MESSAGES + && (m_pmessages == b.m_pmessages) +#endif + && (m_pcollate == b.m_pcollate); + } +}; + +template <class charT> +std::locale cpp_regex_traits_base<charT>::imbue(const std::locale& l) +{ + std::locale result(m_locale); + m_locale = l; + m_pctype = &BOOST_USE_FACET(std::ctype<charT>, l); +#ifndef BOOST_NO_STD_MESSAGES + m_pmessages = &BOOST_USE_FACET(std::messages<charT>, l); +#endif + m_pcollate = &BOOST_USE_FACET(std::collate<charT>, l); + return result; +} + +// +// class cpp_regex_traits_char_layer: +// implements methods that require specialisation for narrow characters: +// +template <class charT> +class cpp_regex_traits_char_layer : public cpp_regex_traits_base<charT> +{ + typedef std::basic_string<charT> string_type; + typedef std::map<charT, regex_constants::syntax_type> map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + cpp_regex_traits_char_layer(const std::locale& l) + : cpp_regex_traits_base<charT>(l) + { + init(); + } + cpp_regex_traits_char_layer(const cpp_regex_traits_base<charT>& b) + : cpp_regex_traits_base<charT>(b) + { + init(); + } + void init(); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class; + if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template <class charT> +void cpp_regex_traits_char_layer<charT>::init() +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: +#ifndef BOOST_NO_STD_MESSAGES +#ifndef __IBMCPP__ + typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1); +#else + typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits<charT>::get_catalog_name()); + if(cat_name.size()) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::re_detail::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if((int)cat >= 0) + { +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[mss[j]] = i; + } + } + this->m_pmessages->close(cat); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(...) + { + this->m_pmessages->close(cat); + throw; + } +#endif + } + else + { +#endif + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + m_char_map[this->m_pctype->widen(*ptr)] = i; + ++ptr; + } + } +#ifndef BOOST_NO_STD_MESSAGES + } +#endif +} + +template <class charT> +typename cpp_regex_traits_char_layer<charT>::string_type + cpp_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, this->m_pctype->widen(*ptr)); + ++ptr; + } + return result; +} + +// +// specialised version for narrow characters: +// +template <> +class BOOST_REGEX_DECL cpp_regex_traits_char_layer<char> : public cpp_regex_traits_base<char> +{ + typedef std::string string_type; +public: + cpp_regex_traits_char_layer(const std::locale& l) + : cpp_regex_traits_base<char>(l) + { + init(); + } + cpp_regex_traits_char_layer(const cpp_regex_traits_base<char>& l) + : cpp_regex_traits_base<char>(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast<unsigned char>(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast<unsigned char>(c)]; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + void init(); +}; + +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +enum +{ + char_class_space=1<<0, + char_class_print=1<<1, + char_class_cntrl=1<<2, + char_class_upper=1<<3, + char_class_lower=1<<4, + char_class_alpha=1<<5, + char_class_digit=1<<6, + char_class_punct=1<<7, + char_class_xdigit=1<<8, + char_class_alnum=char_class_alpha|char_class_digit, + char_class_graph=char_class_alnum|char_class_punct, + char_class_blank=1<<9, + char_class_word=1<<10, + char_class_unicode=1<<11, + char_class_horizontal_space=1<<12, + char_class_vertical_space=1<<13 +}; + +#endif + +// +// class cpp_regex_traits_implementation: +// provides pimpl implementation for cpp_regex_traits. +// +template <class charT> +class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT> +{ +public: + typedef typename cpp_regex_traits<charT>::char_class_type char_class_type; + typedef typename std::ctype<charT>::mask native_mask_type; +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 24); + BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 25); + BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 26); + BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 1u << 27); + BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 1u << 28); +#endif + + typedef std::basic_string<charT> string_type; + typedef charT char_type; + //cpp_regex_traits_implementation(); + cpp_regex_traits_implementation(const std::locale& l) + : cpp_regex_traits_char_layer<charT>(l) + { + init(); + } + cpp_regex_traits_implementation(const cpp_regex_traits_base<charT>& l) + : cpp_regex_traits_char_layer<charT>(l) + { + init(); + } + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map<int, std::string>::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + string_type temp(p1, p2); + this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size()); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const; +private: + std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID + std::map<string_type, char_class_type> m_custom_class_names; // character class names + std::map<string_type, string_type> m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; + void init(); +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +public: + bool isctype(charT c, char_class_type m)const; +#endif +}; + +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET +#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) + +template <class charT> +typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_blank; +template <class charT> +typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_word; +template <class charT> +typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_unicode; +template <class charT> +typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_vertical; +template <class charT> +typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_horizontal; + +#endif +#endif + +template <class charT> +typename cpp_regex_traits_implementation<charT>::string_type + cpp_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const +{ + // + // PRECONDITIONS: + // + // A bug in gcc 3.2 (and maybe other versions as well) treats + // p1 as a null terminated string, for efficiency reasons + // we work around this elsewhere, but just assert here that + // we adhere to gcc's (buggy) preconditions... + // + BOOST_ASSERT(*p2 == 0); + + string_type result; + // + // swallowing all exceptions here is a bad idea + // however at least one std lib will always throw + // std::bad_alloc for certain arguments... + // + try{ + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size()); + result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->m_pcollate->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->m_pcollate->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } + }catch(...){} + while(result.size() && (charT(0) == *result.rbegin())) + result.erase(result.size() - 1); + if(result.empty()) + { + // character is ignorable at the primary level: + result = string_type(1, charT(0)); + } + return result; +} + +template <class charT> +typename cpp_regex_traits_implementation<charT>::string_type + cpp_regex_traits_implementation<charT>::transform(const charT* p1, const charT* p2) const +{ + // + // PRECONDITIONS: + // + // A bug in gcc 3.2 (and maybe other versions as well) treats + // p1 as a null terminated string, for efficiency reasons + // we work around this elsewhere, but just assert here that + // we adhere to gcc's (buggy) preconditions... + // + BOOST_ASSERT(*p2 == 0); + // + // swallowing all exceptions here is a bad idea + // however at least one std lib will always throw + // std::bad_alloc for certain arguments... + // + string_type result; + try{ + result = this->m_pcollate->transform(p1, p2); + // + // Borland's STLPort version returns a NULL-terminated + // string that has garbage at the end - each call to + // std::collate<wchar_t>::transform returns a different string! + // So as a workaround, we'll truncate the string at the first NULL + // which _seems_ to work.... +#if BOOST_WORKAROUND(__BORLANDC__, < 0x580) + result.erase(result.find(charT(0))); +#else + // + // some implementations (Dinkumware) append unnecessary trailing \0's: + while(result.size() && (charT(0) == *result.rbegin())) + result.erase(result.size() - 1); +#endif + BOOST_ASSERT(std::find(result.begin(), result.end(), charT(0)) == result.end()); + } + catch(...) + { + } + return result; +} + + +template <class charT> +typename cpp_regex_traits_implementation<charT>::string_type + cpp_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map<string_type, string_type>::const_iterator iter_type; + if(m_custom_collate_names.size()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\ + && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551) + std::string name(p1, p2); +#else + std::string name; + const charT* p0 = p1; + while(p0 != p2) + name.append(1, char(*p0++)); +#endif + name = lookup_default_collate_name(name); +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\ + && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551) + if(name.size()) + return string_type(name.begin(), name.end()); +#else + if(name.size()) + { + string_type result; + typedef std::string::const_iterator iter; + iter b = name.begin(); + iter e = name.end(); + while(b != e) + result.append(1, charT(*b++)); + return result; + } +#endif + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +template <class charT> +void cpp_regex_traits_implementation<charT>::init() +{ +#ifndef BOOST_NO_STD_MESSAGES +#ifndef __IBMCPP__ + typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1); +#else + typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits<charT>::get_catalog_name()); + if(cat_name.size()) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::re_detail::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if((int)cat >= 0) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0); + i <= boost::regex_constants::error_unknown; + i = static_cast<boost::regex_constants::error_type>(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, this->m_pctype->widen(*p)); + ++p; + } + string_type s = this->m_pmessages->get(cat, 0, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, this->m_pctype->narrow(s[j], 0)); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + static const char_class_type masks[16] = + { + std::ctype<charT>::alnum, + std::ctype<charT>::alpha, + std::ctype<charT>::cntrl, + std::ctype<charT>::digit, + std::ctype<charT>::graph, + cpp_regex_traits_implementation<charT>::mask_horizontal, + std::ctype<charT>::lower, + std::ctype<charT>::print, + std::ctype<charT>::punct, + std::ctype<charT>::space, + std::ctype<charT>::upper, + cpp_regex_traits_implementation<charT>::mask_vertical, + std::ctype<charT>::xdigit, + cpp_regex_traits_implementation<charT>::mask_blank, + cpp_regex_traits_implementation<charT>::mask_word, + cpp_regex_traits_implementation<charT>::mask_unicode, + }; +#else + static const char_class_type masks[14] = + { + ::boost::re_detail::char_class_alnum, + ::boost::re_detail::char_class_alpha, + ::boost::re_detail::char_class_cntrl, + ::boost::re_detail::char_class_digit, + ::boost::re_detail::char_class_graph, + ::boost::re_detail::char_class_horizontal_space, + ::boost::re_detail::char_class_lower, + ::boost::re_detail::char_class_print, + ::boost::re_detail::char_class_punct, + ::boost::re_detail::char_class_space, + ::boost::re_detail::char_class_upper, + ::boost::re_detail::char_class_vertical_space, + ::boost::re_detail::char_class_xdigit, + ::boost::re_detail::char_class_blank, + ::boost::re_detail::char_class_word, + ::boost::re_detail::char_class_unicode, + }; +#endif + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(this->m_pmessages->get(cat, 0, j+300, null_string)); + if(s.size()) + this->m_custom_class_names[s] = masks[j]; + } + } +#endif + // + // get the collation format used by m_pcollate: + // + m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim); +} + +template <class charT> +typename cpp_regex_traits_implementation<charT>::char_class_type + cpp_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const +{ +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + static const char_class_type masks[22] = + { + 0, + std::ctype<char>::alnum, + std::ctype<char>::alpha, + cpp_regex_traits_implementation<charT>::mask_blank, + std::ctype<char>::cntrl, + std::ctype<char>::digit, + std::ctype<char>::digit, + std::ctype<char>::graph, + cpp_regex_traits_implementation<charT>::mask_horizontal, + std::ctype<char>::lower, + std::ctype<char>::lower, + std::ctype<char>::print, + std::ctype<char>::punct, + std::ctype<char>::space, + std::ctype<char>::space, + std::ctype<char>::upper, + cpp_regex_traits_implementation<charT>::mask_unicode, + std::ctype<char>::upper, + cpp_regex_traits_implementation<charT>::mask_vertical, + std::ctype<char>::alnum | cpp_regex_traits_implementation<charT>::mask_word, + std::ctype<char>::alnum | cpp_regex_traits_implementation<charT>::mask_word, + std::ctype<char>::xdigit, + }; +#else + static const char_class_type masks[22] = + { + 0, + ::boost::re_detail::char_class_alnum, + ::boost::re_detail::char_class_alpha, + ::boost::re_detail::char_class_blank, + ::boost::re_detail::char_class_cntrl, + ::boost::re_detail::char_class_digit, + ::boost::re_detail::char_class_digit, + ::boost::re_detail::char_class_graph, + ::boost::re_detail::char_class_horizontal_space, + ::boost::re_detail::char_class_lower, + ::boost::re_detail::char_class_lower, + ::boost::re_detail::char_class_print, + ::boost::re_detail::char_class_punct, + ::boost::re_detail::char_class_space, + ::boost::re_detail::char_class_space, + ::boost::re_detail::char_class_upper, + ::boost::re_detail::char_class_unicode, + ::boost::re_detail::char_class_upper, + ::boost::re_detail::char_class_vertical_space, + ::boost::re_detail::char_class_alnum | ::boost::re_detail::char_class_word, + ::boost::re_detail::char_class_alnum | ::boost::re_detail::char_class_word, + ::boost::re_detail::char_class_xdigit, + }; +#endif + if(m_custom_class_names.size()) + { + typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t state_id = 1 + re_detail::get_default_class_id(p1, p2); + BOOST_ASSERT(state_id < sizeof(masks) / sizeof(masks[0])); + return masks[state_id]; +} + +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +template <class charT> +bool cpp_regex_traits_implementation<charT>::isctype(const charT c, char_class_type mask) const +{ + return + ((mask & ::boost::re_detail::char_class_space) && (m_pctype->is(std::ctype<charT>::space, c))) + || ((mask & ::boost::re_detail::char_class_print) && (m_pctype->is(std::ctype<charT>::print, c))) + || ((mask & ::boost::re_detail::char_class_cntrl) && (m_pctype->is(std::ctype<charT>::cntrl, c))) + || ((mask & ::boost::re_detail::char_class_upper) && (m_pctype->is(std::ctype<charT>::upper, c))) + || ((mask & ::boost::re_detail::char_class_lower) && (m_pctype->is(std::ctype<charT>::lower, c))) + || ((mask & ::boost::re_detail::char_class_alpha) && (m_pctype->is(std::ctype<charT>::alpha, c))) + || ((mask & ::boost::re_detail::char_class_digit) && (m_pctype->is(std::ctype<charT>::digit, c))) + || ((mask & ::boost::re_detail::char_class_punct) && (m_pctype->is(std::ctype<charT>::punct, c))) + || ((mask & ::boost::re_detail::char_class_xdigit) && (m_pctype->is(std::ctype<charT>::xdigit, c))) + || ((mask & ::boost::re_detail::char_class_blank) && (m_pctype->is(std::ctype<charT>::space, c)) && !::boost::re_detail::is_separator(c)) + || ((mask & ::boost::re_detail::char_class_word) && (c == '_')) + || ((mask & ::boost::re_detail::char_class_unicode) && ::boost::re_detail::is_extended(c)) + || ((mask & ::boost::re_detail::char_class_vertical) && (is_separator(c) || (c == '\v'))) + || ((mask & ::boost::re_detail::char_class_horizontal) && m_pctype->is(std::ctype<charT>::space, c) && !(is_separator(c) || (c == '\v'))); +} +#endif + + +template <class charT> +inline boost::shared_ptr<const cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT)) +{ + cpp_regex_traits_base<charT> key(l); + return ::boost::object_cache<cpp_regex_traits_base<charT>, cpp_regex_traits_implementation<charT> >::get(key, 5); +} + +} // re_detail + +template <class charT> +class cpp_regex_traits +{ +private: + typedef std::ctype<charT> ctype_type; +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string<char_type> string_type; + typedef std::locale locale_type; + typedef boost::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + cpp_regex_traits() + : m_pimpl(re_detail::create_cpp_regex_traits<charT>(std::locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits<charT>::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT translate(charT c, bool icase) const + { + return icase ? m_pimpl->m_pctype->tolower(c) : c; + } + charT tolower(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT toupper(charT c) const + { + return m_pimpl->m_pctype->toupper(c); + } + string_type transform(const charT* p1, const charT* p2) const + { + return m_pimpl->transform(p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + typedef typename std::ctype<charT>::mask ctype_mask; + + static const ctype_mask mask_base = + static_cast<ctype_mask>( + std::ctype<charT>::alnum + | std::ctype<charT>::alpha + | std::ctype<charT>::cntrl + | std::ctype<charT>::digit + | std::ctype<charT>::graph + | std::ctype<charT>::lower + | std::ctype<charT>::print + | std::ctype<charT>::punct + | std::ctype<charT>::space + | std::ctype<charT>::upper + | std::ctype<charT>::xdigit); + + if((f & mask_base) + && (m_pimpl->m_pctype->is( + static_cast<ctype_mask>(f & mask_base), c))) + return true; + else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c)) + return true; + else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_word) && (c == '_')) + return true; + else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_blank) + && m_pimpl->m_pctype->is(std::ctype<charT>::space, c) + && !re_detail::is_separator(c)) + return true; + else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_vertical) + && (::boost::re_detail::is_separator(c) || (c == '\v'))) + return true; + else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_horizontal) + && this->isctype(c, std::ctype<charT>::space) && !this->isctype(c, re_detail::cpp_regex_traits_implementation<charT>::mask_vertical)) + return true; + return false; +#else + return m_pimpl->isctype(c, f); +#endif + } + int toi(const charT*& p1, const charT* p2, int radix)const; + int value(charT c, int radix)const + { + const charT* pc = &c; + return toi(pc, pc + 1, radix); + } + locale_type imbue(locale_type l) + { + std::locale result(getloc()); + m_pimpl = re_detail::create_cpp_regex_traits<charT>(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + boost::shared_ptr<const re_detail::cpp_regex_traits_implementation<charT> > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static static_mutex& get_mutex_inst(); +#endif +}; + + +template <class charT> +int cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const +{ + re_detail::parser_buf<charT> sbuf; // buffer for parsing numbers. + std::basic_istream<charT> is(&sbuf); // stream for parsing numbers. + + // we do NOT want to parse any thousands separators inside the stream: + last = std::find(first, last, BOOST_USE_FACET(std::numpunct<charT>, is.getloc()).thousands_sep()); + + sbuf.pubsetbuf(const_cast<charT*>(static_cast<const charT*>(first)), static_cast<std::streamsize>(last-first)); + is.clear(); + if(std::abs(radix) == 16) is >> std::hex; + else if(std::abs(radix) == 8) is >> std::oct; + else is >> std::dec; + int val; + if(is >> val) + { + first = first + ((last - first) - sbuf.in_avail()); + return val; + } + else + return -1; +} + +template <class charT> +std::string cpp_regex_traits<charT>::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template <class charT> +std::string& cpp_regex_traits<charT>::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template <class charT> +std::string cpp_regex_traits<charT>::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template <class charT> +static_mutex& cpp_regex_traits<charT>::get_mutex_inst() +{ + static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT; + return s_mutex; +} +#endif + + +} // boost + +#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 + +#endif + +#endif + + diff --git a/ext/boost/regex/v4/cregex.hpp b/ext/boost/regex/v4/cregex.hpp new file mode 100644 index 0000000000..cafe396cd9 --- /dev/null +++ b/ext/boost/regex/v4/cregex.hpp @@ -0,0 +1,329 @@ +/* + * + * 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 cregex.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares POSIX API functions + * + boost::RegEx high level wrapper. + */ + +#ifndef BOOST_RE_CREGEX_HPP_INCLUDED +#define BOOST_RE_CREGEX_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif +#include <boost/regex/v4/match_flags.hpp> +#include <boost/regex/v4/error_type.hpp> + +#ifdef __cplusplus +#include <cstddef> +#else +#include <stddef.h> +#endif + +#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 + +/* include these defs only for POSIX compatablity */ +#ifdef __cplusplus +namespace boost{ +extern "C" { +#endif + +#if defined(__cplusplus) && !defined(BOOST_NO_STDC_NAMESPACE) +typedef std::ptrdiff_t regoff_t; +typedef std::size_t regsize_t; +#else +typedef ptrdiff_t regoff_t; +typedef size_t regsize_t; +#endif + +typedef struct +{ + unsigned int re_magic; +#ifdef __cplusplus + std::size_t re_nsub; /* number of parenthesized subexpressions */ +#else + size_t re_nsub; +#endif + const char* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + match_flag_type eflags; /* none of your business :-) */ +} regex_tA; + +#ifndef BOOST_NO_WREGEX +typedef struct +{ + unsigned int re_magic; +#ifdef __cplusplus + std::size_t re_nsub; /* number of parenthesized subexpressions */ +#else + size_t re_nsub; +#endif + const wchar_t* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + match_flag_type eflags; /* none of your business :-) */ +} regex_tW; +#endif + +typedef struct +{ + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + +/* regcomp() flags */ +typedef enum{ + REG_BASIC = 0000, + REG_EXTENDED = 0001, + REG_ICASE = 0002, + REG_NOSUB = 0004, + REG_NEWLINE = 0010, + REG_NOSPEC = 0020, + REG_PEND = 0040, + REG_DUMP = 0200, + REG_NOCOLLATE = 0400, + REG_ESCAPE_IN_LISTS = 01000, + REG_NEWLINE_ALT = 02000, + REG_PERLEX = 04000, + + REG_PERL = REG_EXTENDED | REG_NOCOLLATE | REG_ESCAPE_IN_LISTS | REG_PERLEX, + REG_AWK = REG_EXTENDED | REG_ESCAPE_IN_LISTS, + REG_GREP = REG_BASIC | REG_NEWLINE_ALT, + REG_EGREP = REG_EXTENDED | REG_NEWLINE_ALT, + + REG_ASSERT = 15, + REG_INVARG = 16, + REG_ATOI = 255, /* convert name to number (!) */ + REG_ITOA = 0400 /* convert number to name (!) */ +} reg_comp_flags; + +/* regexec() flags */ +typedef enum{ + REG_NOTBOL = 00001, + REG_NOTEOL = 00002, + REG_STARTEND = 00004 +} reg_exec_flags; + +// +// POSIX error codes: +// +typedef unsigned reg_error_t; +typedef reg_error_t reg_errcode_t; // backwards compatibility + +static const reg_error_t REG_NOERROR = 0; /* Success. */ +static const reg_error_t REG_NOMATCH = 1; /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ +static const reg_error_t REG_BADPAT = 2; /* Invalid pattern. */ +static const reg_error_t REG_ECOLLATE = 3; /* Undefined collating element. */ +static const reg_error_t REG_ECTYPE = 4; /* Invalid character class name. */ +static const reg_error_t REG_EESCAPE = 5; /* Trailing backslash. */ +static const reg_error_t REG_ESUBREG = 6; /* Invalid back reference. */ +static const reg_error_t REG_EBRACK = 7; /* Unmatched left bracket. */ +static const reg_error_t REG_EPAREN = 8; /* Parenthesis imbalance. */ +static const reg_error_t REG_EBRACE = 9; /* Unmatched \{. */ +static const reg_error_t REG_BADBR = 10; /* Invalid contents of \{\}. */ +static const reg_error_t REG_ERANGE = 11; /* Invalid range end. */ +static const reg_error_t REG_ESPACE = 12; /* Ran out of memory. */ +static const reg_error_t REG_BADRPT = 13; /* No preceding re for repetition op. */ +static const reg_error_t REG_EEND = 14; /* unexpected end of expression */ +static const reg_error_t REG_ESIZE = 15; /* expression too big */ +static const reg_error_t REG_ERPAREN = 8; /* = REG_EPAREN : unmatched right parenthesis */ +static const reg_error_t REG_EMPTY = 17; /* empty expression */ +static const reg_error_t REG_E_MEMORY = 15; /* = REG_ESIZE : out of memory */ +static const reg_error_t REG_ECOMPLEXITY = 18; /* complexity too high */ +static const reg_error_t REG_ESTACK = 19; /* out of stack space */ +static const reg_error_t REG_E_UNKNOWN = 20; /* unknown error */ +static const reg_error_t REG_ENOSYS = 20; /* = REG_E_UNKNOWN : Reserved. */ + +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA*, const char*, int); +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int, const regex_tA*, char*, regsize_t); +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA*, const char*, regsize_t, regmatch_t*, int); +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA*); + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW*, const wchar_t*, int); +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int, const regex_tW*, wchar_t*, regsize_t); +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW*, const wchar_t*, regsize_t, regmatch_t*, int); +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW*); +#endif + +#ifdef UNICODE +#define regcomp regcompW +#define regerror regerrorW +#define regexec regexecW +#define regfree regfreeW +#define regex_t regex_tW +#else +#define regcomp regcompA +#define regerror regerrorA +#define regexec regexecA +#define regfree regfreeA +#define regex_t regex_tA +#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 + +#ifdef __cplusplus +} // extern "C" +} // namespace +#endif + +// +// C++ high level wrapper goes here: +// +#if defined(__cplusplus) +#include <string> +#include <vector> +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 + +class RegEx; + +namespace re_detail{ + +class RegExData; +struct pred1; +struct pred2; +struct pred3; +struct pred4; + +} // namespace re_detail + +#if (defined(BOOST_MSVC) || defined(__BORLANDC__)) && !defined(BOOST_DISABLE_WIN32) +typedef bool (__cdecl *GrepCallback)(const RegEx& expression); +typedef bool (__cdecl *GrepFileCallback)(const char* file, const RegEx& expression); +typedef bool (__cdecl *FindFilesCallback)(const char* file); +#else +typedef bool (*GrepCallback)(const RegEx& expression); +typedef bool (*GrepFileCallback)(const char* file, const RegEx& expression); +typedef bool (*FindFilesCallback)(const char* file); +#endif + +class BOOST_REGEX_DECL RegEx +{ +private: + re_detail::RegExData* pdata; +public: + RegEx(); + RegEx(const RegEx& o); + ~RegEx(); + explicit RegEx(const char* c, bool icase = false); + explicit RegEx(const std::string& s, bool icase = false); + RegEx& operator=(const RegEx& o); + RegEx& operator=(const char* p); + RegEx& operator=(const std::string& s){ return this->operator=(s.c_str()); } + unsigned int SetExpression(const char* p, bool icase = false); + unsigned int SetExpression(const std::string& s, bool icase = false){ return SetExpression(s.c_str(), icase); } + std::string Expression()const; + unsigned int error_code()const; + // + // now matching operators: + // + bool Match(const char* p, match_flag_type flags = match_default); + bool Match(const std::string& s, match_flag_type flags = match_default) { return Match(s.c_str(), flags); } + bool Search(const char* p, match_flag_type flags = match_default); + bool Search(const std::string& s, match_flag_type flags = match_default) { return Search(s.c_str(), flags); } + unsigned int Grep(GrepCallback cb, const char* p, match_flag_type flags = match_default); + unsigned int Grep(GrepCallback cb, const std::string& s, match_flag_type flags = match_default) { return Grep(cb, s.c_str(), flags); } + unsigned int Grep(std::vector<std::string>& v, const char* p, match_flag_type flags = match_default); + unsigned int Grep(std::vector<std::string>& v, const std::string& s, match_flag_type flags = match_default) { return Grep(v, s.c_str(), flags); } + unsigned int Grep(std::vector<std::size_t>& v, const char* p, match_flag_type flags = match_default); + unsigned int Grep(std::vector<std::size_t>& v, const std::string& s, match_flag_type flags = match_default) { return Grep(v, s.c_str(), flags); } +#ifndef BOOST_REGEX_NO_FILEITER + unsigned int GrepFiles(GrepFileCallback cb, const char* files, bool recurse = false, match_flag_type flags = match_default); + unsigned int GrepFiles(GrepFileCallback cb, const std::string& files, bool recurse = false, match_flag_type flags = match_default) { return GrepFiles(cb, files.c_str(), recurse, flags); } + unsigned int FindFiles(FindFilesCallback cb, const char* files, bool recurse = false, match_flag_type flags = match_default); + unsigned int FindFiles(FindFilesCallback cb, const std::string& files, bool recurse = false, match_flag_type flags = match_default) { return FindFiles(cb, files.c_str(), recurse, flags); } +#endif + + std::string Merge(const std::string& in, const std::string& fmt, + bool copy = true, match_flag_type flags = match_default); + std::string Merge(const char* in, const char* fmt, + bool copy = true, match_flag_type flags = match_default); + + std::size_t Split(std::vector<std::string>& v, std::string& s, match_flag_type flags = match_default, unsigned max_count = ~0); + // + // now operators for returning what matched in more detail: + // + std::size_t Position(int i = 0)const; + std::size_t Length(int i = 0)const; + bool Matched(int i = 0)const; + std::size_t Marks()const; + std::string What(int i = 0)const; + std::string operator[](int i)const { return What(i); } + + static const std::size_t npos; + + friend struct re_detail::pred1; + friend struct re_detail::pred2; + friend struct re_detail::pred3; + friend struct re_detail::pred4; +}; + +#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 + +#endif // include guard + + + + + + + + + + diff --git a/ext/boost/regex/v4/error_type.hpp b/ext/boost/regex/v4/error_type.hpp new file mode 100644 index 0000000000..b6633a0092 --- /dev/null +++ b/ext/boost/regex/v4/error_type.hpp @@ -0,0 +1,58 @@ +/* + * + * Copyright (c) 2003-2005 + * 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 error_type.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression error type enumerator. + */ + +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#define BOOST_REGEX_ERROR_TYPE_HPP + +#ifdef __cplusplus +namespace boost{ +#endif + +#ifdef __cplusplus +namespace regex_constants{ + +enum error_type{ + + error_ok = 0, // not used + error_no_match = 1, // not used + error_bad_pattern = 2, + error_collate = 3, + error_ctype = 4, + error_escape = 5, + error_backref = 6, + error_brack = 7, + error_paren = 8, + error_brace = 9, + error_badbrace = 10, + error_range = 11, + error_space = 12, + error_badrepeat = 13, + error_end = 14, // not used + error_size = 15, + error_right_paren = 16, // not used + error_empty = 17, + error_complexity = 18, + error_stack = 19, + error_unknown = 20 +}; + +} +} +#endif // __cplusplus + +#endif diff --git a/ext/boost/regex/v4/fileiter.hpp b/ext/boost/regex/v4/fileiter.hpp new file mode 100644 index 0000000000..f13c4b2fb7 --- /dev/null +++ b/ext/boost/regex/v4/fileiter.hpp @@ -0,0 +1,455 @@ +/* + * + * 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 fileiter.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares various platform independent file and + * directory iterators, plus binary file input in + * the form of class map_file. + */ + +#ifndef BOOST_RE_FILEITER_HPP_INCLUDED +#define BOOST_RE_FILEITER_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif +#include <boost/assert.hpp> + +#ifndef BOOST_REGEX_NO_FILEITER + +#if (defined(__CYGWIN__) || defined(__CYGWIN32__)) && !defined(BOOST_REGEX_NO_W32) +#error "Sorry, can't mix <windows.h> with STL code and gcc compiler: if you ran configure, try again with configure --disable-ms-windows" +#define BOOST_REGEX_FI_WIN32_MAP +#define BOOST_REGEX_FI_POSIX_DIR +#elif (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) && !defined(BOOST_REGEX_NO_W32) +#define BOOST_REGEX_FI_WIN32_MAP +#define BOOST_REGEX_FI_WIN32_DIR +#else +#define BOOST_REGEX_FI_POSIX_MAP +#define BOOST_REGEX_FI_POSIX_DIR +#endif + +#if defined(BOOST_REGEX_FI_WIN32_MAP)||defined(BOOST_REGEX_FI_WIN32_DIR) +#include <windows.h> +#endif + +#if defined(BOOST_REGEX_FI_WIN32_DIR) + +#include <cstddef> + +namespace boost{ + namespace re_detail{ + +#ifndef BOOST_NO_ANSI_APIS +typedef WIN32_FIND_DATAA _fi_find_data; +#else +typedef WIN32_FIND_DATAW _fi_find_data; +#endif +typedef HANDLE _fi_find_handle; + + } // namespace re_detail + +} // namespace boost + +#define _fi_invalid_handle INVALID_HANDLE_VALUE +#define _fi_dir FILE_ATTRIBUTE_DIRECTORY + +#elif defined(BOOST_REGEX_FI_POSIX_DIR) + +#include <cstddef> +#include <cstdio> +#include <cctype> +#include <iterator> +#include <list> +#include <cassert> +#include <dirent.h> + +#if defined(__SUNPRO_CC) +using std::list; +#endif + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +namespace boost{ + namespace re_detail{ + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +struct _fi_find_data +{ + unsigned dwFileAttributes; + char cFileName[MAX_PATH]; +}; + +struct _fi_priv_data; + +typedef _fi_priv_data* _fi_find_handle; +#define _fi_invalid_handle 0 +#define _fi_dir 1 + +_fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData); +bool _fi_FindNextFile(_fi_find_handle hFindFile, _fi_find_data* lpFindFileData); +bool _fi_FindClose(_fi_find_handle hFindFile); + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + + } // namespace re_detail +} // namespace boost + +#ifdef FindFirstFile + #undef FindFirstFile +#endif +#ifdef FindNextFile + #undef FindNextFile +#endif +#ifdef FindClose + #undef FindClose +#endif + +#define FindFirstFileA _fi_FindFirstFile +#define FindNextFileA _fi_FindNextFile +#define FindClose _fi_FindClose + +#endif + +namespace boost{ + namespace re_detail{ + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +#ifdef BOOST_REGEX_FI_WIN32_MAP // win32 mapfile + +class BOOST_REGEX_DECL mapfile +{ + HANDLE hfile; + HANDLE hmap; + const char* _first; + const char* _last; +public: + + typedef const char* iterator; + + mapfile(){ hfile = hmap = 0; _first = _last = 0; } + mapfile(const char* file){ hfile = hmap = 0; _first = _last = 0; open(file); } + ~mapfile(){ close(); } + void open(const char* file); + void close(); + const char* begin(){ return _first; } + const char* end(){ return _last; } + size_t size(){ return _last - _first; } + bool valid(){ return (hfile != 0) && (hfile != INVALID_HANDLE_VALUE); } +}; + + +#else + +class BOOST_REGEX_DECL mapfile_iterator; + +class BOOST_REGEX_DECL mapfile +{ + typedef char* pointer; + std::FILE* hfile; + long int _size; + pointer* _first; + pointer* _last; + mutable std::list<pointer*> condemed; + enum sizes + { + buf_size = 4096 + }; + void lock(pointer* node)const; + void unlock(pointer* node)const; +public: + + typedef mapfile_iterator iterator; + + mapfile(){ hfile = 0; _size = 0; _first = _last = 0; } + mapfile(const char* file){ hfile = 0; _size = 0; _first = _last = 0; open(file); } + ~mapfile(){ close(); } + void open(const char* file); + void close(); + iterator begin()const; + iterator end()const; + unsigned long size()const{ return _size; } + bool valid()const{ return hfile != 0; } + friend class mapfile_iterator; +}; + +class BOOST_REGEX_DECL mapfile_iterator +#if !defined(BOOST_NO_STD_ITERATOR) || defined(BOOST_MSVC_STD_ITERATOR) +: public std::iterator<std::random_access_iterator_tag, char> +#endif +{ + typedef mapfile::pointer internal_pointer; + internal_pointer* node; + const mapfile* file; + unsigned long offset; + long position()const + { + return file ? ((node - file->_first) * mapfile::buf_size + offset) : 0; + } + void position(long pos) + { + if(file) + { + node = file->_first + (pos / mapfile::buf_size); + offset = pos % mapfile::buf_size; + } + } +public: + typedef std::ptrdiff_t difference_type; + typedef char value_type; + typedef const char* pointer; + typedef const char& reference; + typedef std::random_access_iterator_tag iterator_category; + + mapfile_iterator() { node = 0; file = 0; offset = 0; } + mapfile_iterator(const mapfile* f, long arg_position) + { + file = f; + node = f->_first + arg_position / mapfile::buf_size; + offset = arg_position % mapfile::buf_size; + if(file) + file->lock(node); + } + mapfile_iterator(const mapfile_iterator& i) + { + file = i.file; + node = i.node; + offset = i.offset; + if(file) + file->lock(node); + } + ~mapfile_iterator() + { + if(file && node) + file->unlock(node); + } + mapfile_iterator& operator = (const mapfile_iterator& i); + char operator* ()const + { + BOOST_ASSERT(node >= file->_first); + BOOST_ASSERT(node < file->_last); + return file ? *(*node + sizeof(int) + offset) : char(0); + } + char operator[] (long off)const + { + mapfile_iterator tmp(*this); + tmp += off; + return *tmp; + } + mapfile_iterator& operator++ (); + mapfile_iterator operator++ (int); + mapfile_iterator& operator-- (); + mapfile_iterator operator-- (int); + + mapfile_iterator& operator += (long off) + { + position(position() + off); + return *this; + } + mapfile_iterator& operator -= (long off) + { + position(position() - off); + return *this; + } + + friend inline bool operator==(const mapfile_iterator& i, const mapfile_iterator& j) + { + return (i.file == j.file) && (i.node == j.node) && (i.offset == j.offset); + } + + friend inline bool operator!=(const mapfile_iterator& i, const mapfile_iterator& j) + { + return !(i == j); + } + + friend inline bool operator<(const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() < j.position(); + } + friend inline bool operator>(const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() > j.position(); + } + friend inline bool operator<=(const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() <= j.position(); + } + friend inline bool operator>=(const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() >= j.position(); + } + + friend mapfile_iterator operator + (const mapfile_iterator& i, long off); + friend mapfile_iterator operator + (long off, const mapfile_iterator& i) + { + mapfile_iterator tmp(i); + return tmp += off; + } + friend mapfile_iterator operator - (const mapfile_iterator& i, long off); + friend inline long operator - (const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() - j.position(); + } +}; + +#endif + +// _fi_sep determines the directory separator, either '\\' or '/' +BOOST_REGEX_DECL extern const char* _fi_sep; + +struct file_iterator_ref +{ + _fi_find_handle hf; + _fi_find_data _data; + long count; +}; + + +class BOOST_REGEX_DECL file_iterator +{ + char* _root; + char* _path; + char* ptr; + file_iterator_ref* ref; + +public: + typedef std::ptrdiff_t difference_type; + typedef const char* value_type; + typedef const char** pointer; + typedef const char*& reference; + typedef std::input_iterator_tag iterator_category; + + file_iterator(); + file_iterator(const char* wild); + ~file_iterator(); + file_iterator(const file_iterator&); + file_iterator& operator=(const file_iterator&); + const char* root()const { return _root; } + const char* path()const { return _path; } + const char* name()const { return ptr; } + _fi_find_data* data() { return &(ref->_data); } + void next(); + file_iterator& operator++() { next(); return *this; } + file_iterator operator++(int); + const char* operator*() { return path(); } + + friend inline bool operator == (const file_iterator& f1, const file_iterator& f2) + { + return ((f1.ref->hf == _fi_invalid_handle) && (f2.ref->hf == _fi_invalid_handle)); + } + + friend inline bool operator != (const file_iterator& f1, const file_iterator& f2) + { + return !(f1 == f2); + } + +}; + +// dwa 9/13/00 - suppress unused parameter warning +inline bool operator < (const file_iterator&, const file_iterator&) +{ + return false; +} + + +class BOOST_REGEX_DECL directory_iterator +{ + char* _root; + char* _path; + char* ptr; + file_iterator_ref* ref; + +public: + typedef std::ptrdiff_t difference_type; + typedef const char* value_type; + typedef const char** pointer; + typedef const char*& reference; + typedef std::input_iterator_tag iterator_category; + + directory_iterator(); + directory_iterator(const char* wild); + ~directory_iterator(); + directory_iterator(const directory_iterator& other); + directory_iterator& operator=(const directory_iterator& other); + + const char* root()const { return _root; } + const char* path()const { return _path; } + const char* name()const { return ptr; } + _fi_find_data* data() { return &(ref->_data); } + void next(); + directory_iterator& operator++() { next(); return *this; } + directory_iterator operator++(int); + const char* operator*() { return path(); } + + static const char* separator() { return _fi_sep; } + + friend inline bool operator == (const directory_iterator& f1, const directory_iterator& f2) + { + return ((f1.ref->hf == _fi_invalid_handle) && (f2.ref->hf == _fi_invalid_handle)); + } + + + friend inline bool operator != (const directory_iterator& f1, const directory_iterator& f2) + { + return !(f1 == f2); + } + + }; + +inline bool operator < (const directory_iterator&, const directory_iterator&) +{ + return false; +} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + + +} // namespace re_detail +using boost::re_detail::directory_iterator; +using boost::re_detail::file_iterator; +using boost::re_detail::mapfile; +} // namespace boost + +#endif // BOOST_REGEX_NO_FILEITER +#endif // BOOST_RE_FILEITER_HPP + + + + + + + + + + + + + + + + + + diff --git a/ext/boost/regex/v4/instances.hpp b/ext/boost/regex/v4/instances.hpp new file mode 100644 index 0000000000..d12dc6b270 --- /dev/null +++ b/ext/boost/regex/v4/instances.hpp @@ -0,0 +1,215 @@ +/* + * + * 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 instances.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Defines those template instances that are placed in the + * library rather than in the users object files. + */ + +// +// note no include guard, we may include this multiple times: +// +#ifndef BOOST_REGEX_NO_EXTERNAL_TEMPLATES + +namespace boost{ + +// +// this header can be included multiple times, each time with +// a different character type, BOOST_REGEX_CHAR_T must be defined +// first: +// +#ifndef BOOST_REGEX_CHAR_T +# error "BOOST_REGEX_CHAR_T not defined" +#endif + +#ifndef BOOST_REGEX_TRAITS_T +# define BOOST_REGEX_TRAITS_T , boost::regex_traits<BOOST_REGEX_CHAR_T > +#endif + +// +// what follows is compiler specific: +// + +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x600) + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +# ifndef BOOST_REGEX_INSTANTIATE +# pragma option push -Jgx +# endif + +template class BOOST_REGEX_DECL basic_regex< BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >; +template class BOOST_REGEX_DECL match_results< const BOOST_REGEX_CHAR_T* >; +#ifndef BOOST_NO_STD_ALLOCATOR +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_T >; +#endif + +# ifndef BOOST_REGEX_INSTANTIATE +# pragma option pop +# endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#elif defined(BOOST_MSVC) || defined(__ICL) + +# ifndef BOOST_REGEX_INSTANTIATE +# ifdef __GNUC__ +# define template __extension__ extern template +# else +# if BOOST_MSVC > 1310 +# define BOOST_REGEX_TEMPLATE_DECL +# endif +# define template extern template +# endif +# endif + +#ifndef BOOST_REGEX_TEMPLATE_DECL +# define BOOST_REGEX_TEMPLATE_DECL BOOST_REGEX_DECL +#endif + +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251 4231 4660) +# endif + +template class BOOST_REGEX_TEMPLATE_DECL basic_regex< BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >; + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +template class BOOST_REGEX_TEMPLATE_DECL match_results< const BOOST_REGEX_CHAR_T* >; +#endif +#ifndef BOOST_NO_STD_ALLOCATOR +template class BOOST_REGEX_TEMPLATE_DECL ::boost::re_detail::perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >; +#endif +#if !(defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB <= 1))\ + && !(defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION <= 800))\ + && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))\ + && !defined(BOOST_REGEX_ICU_INSTANCES) +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +template class BOOST_REGEX_TEMPLATE_DECL match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >; +#endif +#ifndef BOOST_NO_STD_ALLOCATOR +template class BOOST_REGEX_TEMPLATE_DECL ::boost::re_detail::perl_matcher< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >; +#endif +#endif + + +# ifdef BOOST_MSVC +# pragma warning(pop) +# endif + +# ifdef template +# undef template +# endif + +#undef BOOST_REGEX_TEMPLATE_DECL + +#elif (defined(__GNUC__) && (__GNUC__ >= 3)) + +# ifndef BOOST_REGEX_INSTANTIATE +# define template __extension__ extern template +# endif + +#if !defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_REGEX_ICU_INSTANCES) +namespace re_detail{ +template BOOST_REGEX_DECL +std::locale cpp_regex_traits_base<BOOST_REGEX_CHAR_T>::imbue(const std::locale& l); + +template BOOST_REGEX_DECL +cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type + cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::transform_primary(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const; +template BOOST_REGEX_DECL +cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type + cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::transform(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const; +template BOOST_REGEX_DECL +cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::string_type + cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::lookup_collatename(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const; +template BOOST_REGEX_DECL +void cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::init(); +template BOOST_REGEX_DECL +cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::char_class_type + cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::lookup_classname_imp(const BOOST_REGEX_CHAR_T* p1, const BOOST_REGEX_CHAR_T* p2) const; +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +template BOOST_REGEX_DECL +bool cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::isctype(const BOOST_REGEX_CHAR_T c, char_class_type mask) const; +#endif +} // namespace +template BOOST_REGEX_DECL +int cpp_regex_traits<BOOST_REGEX_CHAR_T>::toi(const BOOST_REGEX_CHAR_T*& first, const BOOST_REGEX_CHAR_T* last, int radix)const; +template BOOST_REGEX_DECL +std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::catalog_name(const std::string& name); +template BOOST_REGEX_DECL +std::string& cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_catalog_name_inst(); +template BOOST_REGEX_DECL +std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_catalog_name(); +#ifdef BOOST_HAS_THREADS +template BOOST_REGEX_DECL +static_mutex& cpp_regex_traits<BOOST_REGEX_CHAR_T>::get_mutex_inst(); +#endif +#endif + +template BOOST_REGEX_DECL basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >& + basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::do_assign( + const BOOST_REGEX_CHAR_T* p1, + const BOOST_REGEX_CHAR_T* p2, + flag_type f); +template BOOST_REGEX_DECL basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::locale_type BOOST_REGEX_CALL + basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >::imbue(locale_type l); + +template BOOST_REGEX_DECL void BOOST_REGEX_CALL + match_results<const BOOST_REGEX_CHAR_T*>::maybe_assign( + const match_results<const BOOST_REGEX_CHAR_T*>& m); + +namespace re_detail{ +template BOOST_REGEX_DECL void perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::construct_init( + const basic_regex<BOOST_REGEX_CHAR_T BOOST_REGEX_TRAITS_T >& e, match_flag_type f); +template BOOST_REGEX_DECL bool perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::match(); +template BOOST_REGEX_DECL bool perl_matcher<BOOST_REGEX_CHAR_T const *, match_results< const BOOST_REGEX_CHAR_T* >::allocator_type BOOST_REGEX_TRAITS_T >::find(); +} // namespace + +#if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) \ + && !defined(BOOST_REGEX_ICU_INSTANCES)\ + && !defined(__SGI_STL_PORT)\ + && !defined(_STLPORT_VERSION) +// std:basic_string<>::const_iterator instances as well: +template BOOST_REGEX_DECL void BOOST_REGEX_CALL + match_results<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator>::maybe_assign( + const match_results<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator>& m); + +namespace re_detail{ +template BOOST_REGEX_DECL void perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::construct_init( + const basic_regex<BOOST_REGEX_CHAR_T>& e, match_flag_type f); +template BOOST_REGEX_DECL bool perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::match(); +template BOOST_REGEX_DECL bool perl_matcher<std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator, match_results< std::basic_string<BOOST_REGEX_CHAR_T>::const_iterator >::allocator_type, boost::regex_traits<BOOST_REGEX_CHAR_T > >::find(); +} // namespace +#endif + +# ifdef template +# undef template +# endif + + +#endif + +} // namespace boost + +#endif // BOOST_REGEX_NO_EXTERNAL_TEMPLATES + + + + + diff --git a/ext/boost/regex/v4/iterator_category.hpp b/ext/boost/regex/v4/iterator_category.hpp new file mode 100644 index 0000000000..9e40142378 --- /dev/null +++ b/ext/boost/regex/v4/iterator_category.hpp @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 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 regex_match.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Iterator traits for selecting an iterator type as + * an integral constant expression. + */ + + +#ifndef BOOST_REGEX_ITERATOR_CATEGORY_HPP +#define BOOST_REGEX_ITERATOR_CATEGORY_HPP + +#include <iterator> +#include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/is_pointer.hpp> + +namespace boost{ +namespace detail{ + +template <class I> +struct is_random_imp +{ +#ifndef BOOST_NO_STD_ITERATOR_TRAITS +private: + typedef typename std::iterator_traits<I>::iterator_category cat; +public: + BOOST_STATIC_CONSTANT(bool, value = (::boost::is_convertible<cat*, std::random_access_iterator_tag*>::value)); +#else + BOOST_STATIC_CONSTANT(bool, value = false); +#endif +}; + +template <class I> +struct is_random_pointer_imp +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template <bool is_pointer_type> +struct is_random_imp_selector +{ + template <class I> + struct rebind + { + typedef is_random_imp<I> type; + }; +}; + +template <> +struct is_random_imp_selector<true> +{ + template <class I> + struct rebind + { + typedef is_random_pointer_imp<I> type; + }; +}; + +} + +template <class I> +struct is_random_access_iterator +{ +private: + typedef detail::is_random_imp_selector< ::boost::is_pointer<I>::value> selector; + typedef typename selector::template rebind<I> bound_type; + typedef typename bound_type::type answer; +public: + BOOST_STATIC_CONSTANT(bool, value = answer::value); +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +template <class I> +const bool is_random_access_iterator<I>::value; +#endif + +} + +#endif + diff --git a/ext/boost/regex/v4/iterator_traits.hpp b/ext/boost/regex/v4/iterator_traits.hpp new file mode 100644 index 0000000000..f7afacb17b --- /dev/null +++ b/ext/boost/regex/v4/iterator_traits.hpp @@ -0,0 +1,135 @@ +/* + * + * 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 iterator_traits.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares iterator traits workarounds. + */ + +#ifndef BOOST_REGEX_V4_ITERATOR_TRAITS_HPP +#define BOOST_REGEX_V4_ITERATOR_TRAITS_HPP + +#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 + +namespace boost{ +namespace re_detail{ + +#if defined(BOOST_NO_STD_ITERATOR_TRAITS) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template <class T> +struct regex_iterator_traits +{ + typedef typename T::iterator_category iterator_category; + typedef typename T::value_type value_type; +#if !defined(BOOST_NO_STD_ITERATOR) + typedef typename T::difference_type difference_type; + typedef typename T::pointer pointer; + typedef typename T::reference reference; +#else + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; +#endif +}; + +template <class T> +struct pointer_iterator_traits +{ + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; +}; +template <class T> +struct const_pointer_iterator_traits +{ + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef const T* pointer; + typedef const T& reference; + typedef std::random_access_iterator_tag iterator_category; +}; + +template<> +struct regex_iterator_traits<char*> : pointer_iterator_traits<char>{}; +template<> +struct regex_iterator_traits<const char*> : const_pointer_iterator_traits<char>{}; +template<> +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>{}; +// +// the follwoing are needed for ICU support: +// +template<> +struct regex_iterator_traits<unsigned char*> : pointer_iterator_traits<char>{}; +template<> +struct regex_iterator_traits<const unsigned char*> : const_pointer_iterator_traits<char>{}; +template<> +struct regex_iterator_traits<int*> : pointer_iterator_traits<int>{}; +template<> +struct regex_iterator_traits<const int*> : const_pointer_iterator_traits<int>{}; + +#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>{}; +template<> +struct regex_iterator_traits<std::string::const_iterator> : const_pointer_iterator_traits<char>{}; +#ifndef BOOST_NO_STD_WSTRING +template<> +struct regex_iterator_traits<std::wstring::iterator> : pointer_iterator_traits<wchar_t>{}; +template<> +struct regex_iterator_traits<std::wstring::const_iterator> : const_pointer_iterator_traits<wchar_t>{}; +#endif // BOOST_NO_WSTRING +#endif // stport + +#else + +template <class T> +struct regex_iterator_traits : public std::iterator_traits<T> {}; + +#endif + +} // namespace re_detail +} // namespace boost + +#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 + +#endif + diff --git a/ext/boost/regex/v4/match_flags.hpp b/ext/boost/regex/v4/match_flags.hpp new file mode 100644 index 0000000000..9585aca8b2 --- /dev/null +++ b/ext/boost/regex/v4/match_flags.hpp @@ -0,0 +1,138 @@ +/* + * + * 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 match_flags.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares match_flags type. + */ + +#ifndef BOOST_REGEX_V4_MATCH_FLAGS +#define BOOST_REGEX_V4_MATCH_FLAGS + +#ifdef __cplusplus +# include <boost/cstdint.hpp> +#endif + +#ifdef __cplusplus +namespace boost{ + namespace regex_constants{ +#endif + +typedef enum _match_flags +{ + match_default = 0, + match_not_bol = 1, // first is not start of line + match_not_eol = match_not_bol << 1, // last is not end of line + match_not_bob = match_not_eol << 1, // first is not start of buffer + match_not_eob = match_not_bob << 1, // last is not end of buffer + match_not_bow = match_not_eob << 1, // first is not start of word + match_not_eow = match_not_bow << 1, // last is not end of word + match_not_dot_newline = match_not_eow << 1, // \n is not matched by '.' + match_not_dot_null = match_not_dot_newline << 1, // '\0' is not matched by '.' + match_prev_avail = match_not_dot_null << 1, // *--first is a valid expression + match_init = match_prev_avail << 1, // internal use + match_any = match_init << 1, // don't care what we match + match_not_null = match_any << 1, // string can't be null + match_continuous = match_not_null << 1, // each grep match must continue from + // uninterupted from the previous one + match_partial = match_continuous << 1, // find partial matches + + match_stop = match_partial << 1, // stop after first match (grep) V3 only + match_not_initial_null = match_stop, // don't match initial null, V4 only + match_all = match_stop << 1, // must find the whole of input even if match_any is set + match_perl = match_all << 1, // Use perl matching rules + match_posix = match_perl << 1, // Use POSIX matching rules + match_nosubs = match_posix << 1, // don't trap marked subs + match_extra = match_nosubs << 1, // include full capture information for repeated captures + match_single_line = match_extra << 1, // treat text as single line and ignor any \n's when matching ^ and $. + match_unused1 = match_single_line << 1, // unused + match_unused2 = match_unused1 << 1, // unused + match_unused3 = match_unused2 << 1, // unused + match_max = match_unused3, + + format_perl = 0, // perl style replacement + format_default = 0, // ditto. + format_sed = match_max << 1, // sed style replacement. + format_all = format_sed << 1, // enable all extentions to sytax. + format_no_copy = format_all << 1, // don't copy non-matching segments. + format_first_only = format_no_copy << 1, // Only replace first occurance. + format_is_if = format_first_only << 1, // internal use only. + format_literal = format_is_if << 1 // treat string as a literal + +} match_flags; + +#if (defined(_MSC_VER) && (_MSC_VER < 1300)) || defined(__BORLANDC__) +typedef unsigned long match_flag_type; +#else +typedef match_flags match_flag_type; + + +#ifdef __cplusplus +inline match_flags operator&(match_flags m1, match_flags m2) +{ return static_cast<match_flags>(static_cast<boost::int32_t>(m1) & static_cast<boost::int32_t>(m2)); } +inline match_flags operator|(match_flags m1, match_flags m2) +{ return static_cast<match_flags>(static_cast<boost::int32_t>(m1) | static_cast<boost::int32_t>(m2)); } +inline match_flags operator^(match_flags m1, match_flags m2) +{ return static_cast<match_flags>(static_cast<boost::int32_t>(m1) ^ static_cast<boost::int32_t>(m2)); } +inline match_flags operator~(match_flags m1) +{ return static_cast<match_flags>(~static_cast<boost::int32_t>(m1)); } +inline match_flags& operator&=(match_flags& m1, match_flags m2) +{ m1 = m1&m2; return m1; } +inline match_flags& operator|=(match_flags& m1, match_flags m2) +{ m1 = m1|m2; return m1; } +inline match_flags& operator^=(match_flags& m1, match_flags m2) +{ m1 = m1^m2; return m1; } +#endif +#endif + +#ifdef __cplusplus +} // namespace regex_constants +// +// import names into boost for backwards compatiblity: +// +using regex_constants::match_flag_type; +using regex_constants::match_default; +using regex_constants::match_not_bol; +using regex_constants::match_not_eol; +using regex_constants::match_not_bob; +using regex_constants::match_not_eob; +using regex_constants::match_not_bow; +using regex_constants::match_not_eow; +using regex_constants::match_not_dot_newline; +using regex_constants::match_not_dot_null; +using regex_constants::match_prev_avail; +//using regex_constants::match_init; +using regex_constants::match_any; +using regex_constants::match_not_null; +using regex_constants::match_continuous; +using regex_constants::match_partial; +//using regex_constants::match_stop; +using regex_constants::match_all; +using regex_constants::match_perl; +using regex_constants::match_posix; +using regex_constants::match_nosubs; +using regex_constants::match_extra; +using regex_constants::match_single_line; +//using regex_constants::match_max; +using regex_constants::format_all; +using regex_constants::format_sed; +using regex_constants::format_perl; +using regex_constants::format_default; +using regex_constants::format_no_copy; +using regex_constants::format_first_only; +//using regex_constants::format_is_if; + +} // namespace boost +#endif // __cplusplus +#endif // include guard + diff --git a/ext/boost/regex/v4/match_results.hpp b/ext/boost/regex/v4/match_results.hpp new file mode 100644 index 0000000000..09dd31f009 --- /dev/null +++ b/ext/boost/regex/v4/match_results.hpp @@ -0,0 +1,579 @@ +/* + * + * 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 match_results.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares template class match_results. + */ + +#ifndef BOOST_REGEX_V4_MATCH_RESULTS_HPP +#define BOOST_REGEX_V4_MATCH_RESULTS_HPP + +#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 + +namespace boost{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4251 4231 4660) +#endif + +namespace re_detail{ + +template <class charT> +class named_subexpressions; + +} + +template <class BidiIterator, class Allocator> +class match_results +{ +private: +#ifndef BOOST_NO_STD_ALLOCATOR + typedef std::vector<sub_match<BidiIterator>, Allocator> vector_type; +#else + typedef std::vector<sub_match<BidiIterator> > vector_type; +#endif +public: + typedef sub_match<BidiIterator> value_type; +#if !defined(BOOST_NO_STD_ALLOCATOR) && !(defined(BOOST_MSVC) && defined(_STLPORT_VERSION)) + typedef typename Allocator::const_reference const_reference; +#else + typedef const value_type& const_reference; +#endif + typedef const_reference reference; + typedef typename vector_type::const_iterator const_iterator; + typedef const_iterator iterator; + typedef typename re_detail::regex_iterator_traits< + BidiIterator>::difference_type difference_type; + typedef typename Allocator::size_type size_type; + typedef Allocator allocator_type; + typedef typename re_detail::regex_iterator_traits< + BidiIterator>::value_type char_type; + typedef std::basic_string<char_type> string_type; + typedef re_detail::named_subexpressions_base<char_type> named_sub_type; + + // construct/copy/destroy: + explicit match_results(const Allocator& a = Allocator()) +#ifndef BOOST_NO_STD_ALLOCATOR + : m_subs(a), m_base(), m_last_closed_paren(0) {} +#else + : m_subs(), m_base(), m_last_closed_paren(0) { (void)a; } +#endif + match_results(const match_results& m) + : m_subs(m.m_subs), m_base(m.m_base) {} + match_results& operator=(const match_results& m) + { + m_subs = m.m_subs; + m_base = m.m_base; + return *this; + } + ~match_results(){} + + // size: + size_type size() const + { return empty() ? 0 : m_subs.size() - 2; } + size_type max_size() const + { return m_subs.max_size(); } + bool empty() const + { return m_subs.size() < 2; } + // element access: + difference_type length(int sub = 0) const + { + sub += 2; + if((sub < (int)m_subs.size()) && (sub > 0)) + return m_subs[sub].length(); + return 0; + } + difference_type length(const char_type* sub) const + { + const char_type* end = sub; + while(*end) ++end; + return length(named_subexpression_index(sub, end)); + } + template <class charT> + difference_type length(const charT* sub) const + { + const charT* end = sub; + while(*end) ++end; + return length(named_subexpression_index(sub, end)); + } + template <class charT, class Traits, class A> + difference_type length(const std::basic_string<charT, Traits, A>& sub) const + { + return length(sub.c_str()); + } + difference_type position(size_type sub = 0) const + { + sub += 2; + if(sub < m_subs.size()) + { + const sub_match<BidiIterator>& s = m_subs[sub]; + if(s.matched || (sub == 2)) + { + return ::boost::re_detail::distance((BidiIterator)(m_base), (BidiIterator)(s.first)); + } + } + return ~static_cast<difference_type>(0); + } + difference_type position(const char_type* sub) const + { + const char_type* end = sub; + while(*end) ++end; + return position(named_subexpression_index(sub, end)); + } + template <class charT> + difference_type position(const charT* sub) const + { + const charT* end = sub; + while(*end) ++end; + return position(named_subexpression_index(sub, end)); + } + template <class charT, class Traits, class A> + difference_type position(const std::basic_string<charT, Traits, A>& sub) const + { + return position(sub.c_str()); + } + string_type str(int sub = 0) const + { + sub += 2; + string_type result; + if(sub < (int)m_subs.size() && (sub > 0)) + { + const sub_match<BidiIterator>& s = m_subs[sub]; + if(s.matched) + { + result = s.str(); + } + } + return result; + } + string_type str(const char_type* sub) const + { + return (*this)[sub].str(); + } + template <class Traits, class A> + string_type str(const std::basic_string<char_type, Traits, A>& sub) const + { + return (*this)[sub].str(); + } + template <class charT> + string_type str(const charT* sub) const + { + return (*this)[sub].str(); + } + template <class charT, class Traits, class A> + string_type str(const std::basic_string<charT, Traits, A>& sub) const + { + return (*this)[sub].str(); + } + const_reference operator[](int sub) const + { + sub += 2; + if(sub < (int)m_subs.size() && (sub >= 0)) + { + return m_subs[sub]; + } + return m_null; + } + // + // Named sub-expressions: + // + const_reference named_subexpression(const char_type* i, const char_type* j) const + { + int index = m_named_subs->get_id(i, j); + return index > 0 ? (*this)[index] : m_null; + } + template <class charT> + const_reference named_subexpression(const charT* i, const charT* j) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(i == j) + return m_null; + std::vector<char_type> s; + while(i != j) + s.insert(s.end(), *i++); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + int named_subexpression_index(const char_type* i, const char_type* j) const + { + int index = m_named_subs->get_id(i, j); + return index > 0 ? index : -20; + } + template <class charT> + int named_subexpression_index(const charT* i, const charT* j) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(i == j) + return -20; + std::vector<char_type> s; + while(i != j) + s.insert(s.end(), *i++); + return named_subexpression_index(&*s.begin(), &*s.begin() + s.size()); + } + template <class Traits, class A> + const_reference operator[](const std::basic_string<char_type, Traits, A>& s) const + { + return named_subexpression(s.c_str(), s.c_str() + s.size()); + } + const_reference operator[](const char_type* p) const + { + const char_type* e = p; + while(*e) ++e; + return named_subexpression(p, e); + } + + template <class charT> + const_reference operator[](const charT* p) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(*p == 0) + return m_null; + std::vector<char_type> s; + while(*p) + s.insert(s.end(), *p++); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + template <class charT, class Traits, class A> + const_reference operator[](const std::basic_string<charT, Traits, A>& ns) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(ns.empty()) + return m_null; + std::vector<char_type> s; + for(unsigned i = 0; i < ns.size(); ++i) + s.insert(s.end(), ns[i]); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + + const_reference prefix() const + { + return (*this)[-1]; + } + + const_reference suffix() const + { + return (*this)[-2]; + } + const_iterator begin() const + { + return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end(); + } + const_iterator end() const + { + return m_subs.end(); + } + // format: + template <class OutputIterator> + OutputIterator format(OutputIterator out, + const string_type& fmt, + match_flag_type flags = format_default) const + { + re_detail::trivial_format_traits<char_type> traits; + return re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, traits); + } + string_type format(const string_type& fmt, + match_flag_type flags = format_default) const + { + string_type result; + re_detail::string_out_iterator<string_type> i(result); + re_detail::trivial_format_traits<char_type> traits; + re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, traits); + return result; + } + // format with locale: + template <class OutputIterator, class RegexT> + OutputIterator format(OutputIterator out, + const string_type& fmt, + match_flag_type flags, + const RegexT& re) const + { + return ::boost::re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits()); + } + template <class RegexT> + string_type format(const string_type& fmt, + match_flag_type flags, + const RegexT& re) const + { + string_type result; + re_detail::string_out_iterator<string_type> i(result); + ::boost::re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits()); + return result; + } + const_reference get_last_closed_paren()const + { + return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren]; + } + + allocator_type get_allocator() const + { +#ifndef BOOST_NO_STD_ALLOCATOR + return m_subs.get_allocator(); +#else + return allocator_type(); +#endif + } + void swap(match_results& that) + { + std::swap(m_subs, that.m_subs); + std::swap(m_base, that.m_base); + } + bool operator==(const match_results& that)const + { + return (m_subs == that.m_subs) && (m_base == that.m_base); + } + bool operator!=(const match_results& that)const + { return !(*this == that); } + +#ifdef BOOST_REGEX_MATCH_EXTRA + typedef typename sub_match<BidiIterator>::capture_sequence_type capture_sequence_type; + + const capture_sequence_type& captures(int i)const + { + return (*this)[i].captures(); + } +#endif + + // + // private access functions: + void BOOST_REGEX_CALL set_second(BidiIterator i) + { + BOOST_ASSERT(m_subs.size() > 2); + m_subs[2].second = i; + m_subs[2].matched = true; + m_subs[0].first = i; + m_subs[0].matched = (m_subs[0].first != m_subs[0].second); + m_null.first = i; + m_null.second = i; + m_null.matched = false; + } + + void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false) + { + if(pos) + m_last_closed_paren = pos; + pos += 2; + BOOST_ASSERT(m_subs.size() > pos); + m_subs[pos].second = i; + m_subs[pos].matched = m; + if((pos == 2) && !escape_k) + { + m_subs[0].first = i; + m_subs[0].matched = (m_subs[0].first != m_subs[0].second); + m_null.first = i; + m_null.second = i; + m_null.matched = false; + } + } + void BOOST_REGEX_CALL set_size(size_type n, BidiIterator i, BidiIterator j) + { + value_type v(j); + size_type len = m_subs.size(); + if(len > n + 2) + { + m_subs.erase(m_subs.begin()+n+2, m_subs.end()); + std::fill(m_subs.begin(), m_subs.end(), v); + } + else + { + std::fill(m_subs.begin(), m_subs.end(), v); + if(n+2 != len) + m_subs.insert(m_subs.end(), n+2-len, v); + } + m_subs[1].first = i; + m_last_closed_paren = 0; + } + void BOOST_REGEX_CALL set_base(BidiIterator pos) + { + m_base = pos; + } + BidiIterator base()const + { + return m_base; + } + void BOOST_REGEX_CALL set_first(BidiIterator i) + { + // set up prefix: + m_subs[1].second = i; + m_subs[1].matched = (m_subs[1].first != i); + // set up $0: + m_subs[2].first = i; + // zero out everything else: + for(size_type n = 3; n < m_subs.size(); ++n) + { + m_subs[n].first = m_subs[n].second = m_subs[0].second; + m_subs[n].matched = false; + } + } + void BOOST_REGEX_CALL set_first(BidiIterator i, size_type pos, bool escape_k = false) + { + BOOST_ASSERT(pos+2 < m_subs.size()); + if(pos || escape_k) + { + m_subs[pos+2].first = i; + if(escape_k) + { + m_subs[1].second = i; + m_subs[1].matched = (m_subs[1].first != m_subs[1].second); + } + } + else + set_first(i); + } + void BOOST_REGEX_CALL maybe_assign(const match_results<BidiIterator, Allocator>& m); + + void BOOST_REGEX_CALL set_named_subs(boost::shared_ptr<named_sub_type> subs) + { + m_named_subs = subs; + } + +private: + vector_type m_subs; // subexpressions + BidiIterator m_base; // where the search started from + sub_match<BidiIterator> m_null; // a null match + boost::shared_ptr<named_sub_type> m_named_subs; + int m_last_closed_paren; +}; + +template <class BidiIterator, class Allocator> +void BOOST_REGEX_CALL match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m) +{ + const_iterator p1, p2; + p1 = begin(); + p2 = m.begin(); + // + // Distances are measured from the start of *this* match, unless this isn't + // a valid match in which case we use the start of the whole sequence. Note that + // no subsequent match-candidate can ever be to the left of the first match found. + // This ensures that when we are using bidirectional iterators, that distances + // measured are as short as possible, and therefore as efficient as possible + // to compute. Finally note that we don't use the "matched" data member to test + // whether a sub-expression is a valid match, because partial matches set this + // to false for sub-expression 0. + // + BidiIterator l_end = this->suffix().second; + BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first; + difference_type len1 = 0; + difference_type len2 = 0; + difference_type base1 = 0; + difference_type base2 = 0; + std::size_t i; + for(i = 0; i < size(); ++i, ++p1, ++p2) + { + // + // Leftmost takes priority over longest; handle special cases + // where distances need not be computed first (an optimisation + // for bidirectional iterators: ensure that we don't accidently + // compute the length of the whole sequence, as this can be really + // expensive). + // + if(p1->first == l_end) + { + if(p2->first != l_end) + { + // p2 must be better than p1, and no need to calculate + // actual distances: + base1 = 1; + base2 = 0; + break; + } + else + { + // *p1 and *p2 are either unmatched or match end-of sequence, + // either way no need to calculate distances: + if((p1->matched == false) && (p2->matched == true)) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + continue; + } + } + else if(p2->first == l_end) + { + // p1 better than p2, and no need to calculate distances: + return; + } + base1 = ::boost::re_detail::distance(l_base, p1->first); + base2 = ::boost::re_detail::distance(l_base, p2->first); + BOOST_ASSERT(base1 >= 0); + BOOST_ASSERT(base2 >= 0); + if(base1 < base2) return; + if(base2 < base1) break; + + len1 = ::boost::re_detail::distance((BidiIterator)p1->first, (BidiIterator)p1->second); + len2 = ::boost::re_detail::distance((BidiIterator)p2->first, (BidiIterator)p2->second); + BOOST_ASSERT(len1 >= 0); + BOOST_ASSERT(len2 >= 0); + if((len1 != len2) || ((p1->matched == false) && (p2->matched == true))) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + } + if(i == size()) + return; + if(base2 < base1) + *this = m; + else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) ) + *this = m; +} + +template <class BidiIterator, class Allocator> +void swap(match_results<BidiIterator, Allocator>& a, match_results<BidiIterator, Allocator>& b) +{ + a.swap(b); +} + +#ifndef BOOST_NO_STD_LOCALE +template <class charT, class traits, class BidiIterator, class Allocator> +std::basic_ostream<charT, traits>& + operator << (std::basic_ostream<charT, traits>& os, + const match_results<BidiIterator, Allocator>& s) +{ + return (os << s.str()); +} +#else +template <class BidiIterator, class Allocator> +std::ostream& operator << (std::ostream& os, + const match_results<BidiIterator, Allocator>& s) +{ + return (os << s.str()); +} +#endif + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} // namespace boost + +#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 + +#endif + + diff --git a/ext/boost/regex/v4/mem_block_cache.hpp b/ext/boost/regex/v4/mem_block_cache.hpp new file mode 100644 index 0000000000..222142dd69 --- /dev/null +++ b/ext/boost/regex/v4/mem_block_cache.hpp @@ -0,0 +1,99 @@ + /* + * Copyright (c) 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 mem_block_cache.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: memory block cache used by the non-recursive matcher. + */ + +#ifndef BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP +#define BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP + +#include <new> +#ifdef BOOST_HAS_THREADS +#include <boost/regex/pending/static_mutex.hpp> +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost{ +namespace re_detail{ + +struct mem_block_node +{ + mem_block_node* next; +}; + +struct mem_block_cache +{ + // this member has to be statically initialsed: + mem_block_node* next; + unsigned cached_blocks; +#ifdef BOOST_HAS_THREADS + boost::static_mutex mut; +#endif + + ~mem_block_cache() + { + while(next) + { + mem_block_node* old = next; + next = next->next; + ::operator delete(old); + } + } + void* get() + { +#ifdef BOOST_HAS_THREADS + boost::static_mutex::scoped_lock g(mut); +#endif + if(next) + { + mem_block_node* result = next; + next = next->next; + --cached_blocks; + return result; + } + return ::operator new(BOOST_REGEX_BLOCKSIZE); + } + void put(void* p) + { +#ifdef BOOST_HAS_THREADS + boost::static_mutex::scoped_lock g(mut); +#endif + if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS) + { + ::operator delete(p); + } + else + { + mem_block_node* old = static_cast<mem_block_node*>(p); + old->next = next; + next = old; + ++cached_blocks; + } + } +}; + +extern mem_block_cache block_cache; + +} +} // namespace boost + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif + diff --git a/ext/boost/regex/v4/perl_matcher.hpp b/ext/boost/regex/v4/perl_matcher.hpp new file mode 100644 index 0000000000..726c2881e5 --- /dev/null +++ b/ext/boost/regex/v4/perl_matcher.hpp @@ -0,0 +1,580 @@ +/* + * + * Copyright (c) 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) + * + */ + +#ifndef BOOST_REGEX_MATCHER_HPP +#define BOOST_REGEX_MATCHER_HPP + +#include <boost/regex/v4/iterator_category.hpp> + +#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: 4800) +#endif + +namespace boost{ +namespace re_detail{ + +// +// error checking API: +// +BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex_constants::syntax_option_type ef, match_flag_type mf); +// +// function can_start: +// +template <class charT> +inline bool can_start(charT c, const unsigned char* map, unsigned char mask) +{ + return ((c < static_cast<charT>(0)) ? true : ((c >= static_cast<charT>(1 << CHAR_BIT)) ? true : map[c] & mask)); +} +inline bool can_start(char c, const unsigned char* map, unsigned char mask) +{ + return map[(unsigned char)c] & mask; +} +inline bool can_start(signed char c, const unsigned char* map, unsigned char mask) +{ + return map[(unsigned char)c] & mask; +} +inline bool can_start(unsigned char c, const unsigned char* map, unsigned char mask) +{ + return map[c] & mask; +} +inline bool can_start(unsigned short c, const unsigned char* map, unsigned char mask) +{ + return ((c >= (1 << CHAR_BIT)) ? true : map[c] & mask); +} +#if !defined(__hpux) // WCHAR_MIN not usable in pp-directives. +#if defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +inline bool can_start(wchar_t c, const unsigned char* map, unsigned char mask) +{ + return ((c >= static_cast<wchar_t>(1u << CHAR_BIT)) ? true : map[c] & mask); +} +#endif +#endif +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +inline bool can_start(unsigned int c, const unsigned char* map, unsigned char mask) +{ + return (((c >= static_cast<unsigned int>(1u << CHAR_BIT)) ? true : map[c] & mask)); +} +#endif + + +// +// Unfortunately Rogue Waves standard library appears to have a bug +// in std::basic_string::compare that results in eroneous answers +// in some cases (tested with Borland C++ 5.1, Rogue Wave lib version +// 0x020101) the test case was: +// {39135,0} < {0xff,0} +// which succeeds when it should not. +// +#ifndef _RWSTD_VER +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) +template <class C, class T, class A> +inline int string_compare(const std::basic_string<C,T,A>& s, const C* p) +{ + if(0 == *p) + { + if(s.empty() || ((s.size() == 1) && (s[0] == 0))) + return 0; + } + return s.compare(p); +} +#endif +#else +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) +template <class C, class T, class A> +inline int string_compare(const std::basic_string<C,T,A>& s, const C* p) +{ + if(0 == *p) + { + if(s.empty() || ((s.size() == 1) && (s[0] == 0))) + return 0; + } + return s.compare(p); +} +#endif +inline int string_compare(const std::string& s, const char* p) +{ return std::strcmp(s.c_str(), p); } +# ifndef BOOST_NO_WREGEX +inline int string_compare(const std::wstring& s, const wchar_t* p) +{ return std::wcscmp(s.c_str(), p); } +#endif +#endif +template <class Seq, class C> +inline int string_compare(const Seq& s, const C* p) +{ + std::size_t i = 0; + while((i < s.size()) && (p[i] == s[i])) + { + ++i; + } + return (i == s.size()) ? -p[i] : s[i] - p[i]; +} +# define STR_COMP(s,p) string_compare(s,p) + +template<class charT> +inline const charT* re_skip_past_null(const charT* p) +{ + while (*p != static_cast<charT>(0)) ++p; + return ++p; +} + +template <class iterator, class charT, class traits_type, class char_classT> +iterator BOOST_REGEX_CALL re_is_set_member(iterator next, + iterator last, + const re_set_long<char_classT>* set_, + const regex_data<charT, traits_type>& e, bool icase) +{ + const charT* p = reinterpret_cast<const charT*>(set_+1); + iterator ptr; + unsigned int i; + //bool icase = e.m_flags & regex_constants::icase; + + if(next == last) return next; + + typedef typename traits_type::string_type traits_string_type; + const ::boost::regex_traits_wrapper<traits_type>& traits_inst = *(e.m_ptraits); + + // dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never + // referenced + (void)traits_inst; + + // try and match a single character, could be a multi-character + // collating element... + for(i = 0; i < set_->csingles; ++i) + { + ptr = next; + if(*p == static_cast<charT>(0)) + { + // treat null string as special case: + if(traits_inst.translate(*ptr, icase) != *p) + { + while(*p == static_cast<charT>(0))++p; + continue; + } + return set_->isnot ? next : (ptr == next) ? ++next : ptr; + } + else + { + while(*p && (ptr != last)) + { + if(traits_inst.translate(*ptr, icase) != *p) + break; + ++p; + ++ptr; + } + + if(*p == static_cast<charT>(0)) // if null we've matched + return set_->isnot ? next : (ptr == next) ? ++next : ptr; + + p = re_skip_past_null(p); // skip null + } + } + + charT col = traits_inst.translate(*next, icase); + + + if(set_->cranges || set_->cequivalents) + { + traits_string_type s1; + // + // try and match a range, NB only a single character can match + if(set_->cranges) + { + if((e.m_flags & regex_constants::collate) == 0) + s1.assign(1, col); + else + { + charT a[2] = { col, charT(0), }; + s1 = traits_inst.transform(a, a + 1); + } + for(i = 0; i < set_->cranges; ++i) + { + if(STR_COMP(s1, p) >= 0) + { + do{ ++p; }while(*p); + ++p; + if(STR_COMP(s1, p) <= 0) + return set_->isnot ? next : ++next; + } + else + { + // skip first string + do{ ++p; }while(*p); + ++p; + } + // skip second string + do{ ++p; }while(*p); + ++p; + } + } + // + // try and match an equivalence class, NB only a single character can match + if(set_->cequivalents) + { + charT a[2] = { col, charT(0), }; + s1 = traits_inst.transform_primary(a, a +1); + for(i = 0; i < set_->cequivalents; ++i) + { + if(STR_COMP(s1, p) == 0) + return set_->isnot ? next : ++next; + // skip string + do{ ++p; }while(*p); + ++p; + } + } + } + if(traits_inst.isctype(col, set_->cclasses) == true) + return set_->isnot ? next : ++next; + if((set_->cnclasses != 0) && (traits_inst.isctype(col, set_->cnclasses) == false)) + return set_->isnot ? next : ++next; + return set_->isnot ? ++next : next; +} + +template <class BidiIterator> +class repeater_count +{ + repeater_count** stack; + repeater_count* next; + int state_id; + std::size_t count; // the number of iterations so far + BidiIterator start_pos; // where the last repeat started +public: + repeater_count(repeater_count** s) + { + stack = s; + next = 0; + state_id = -1; + count = 0; + } + repeater_count(int i, repeater_count** s, BidiIterator start) + : start_pos(start) + { + state_id = i; + stack = s; + next = *stack; + *stack = this; + if(state_id > next->state_id) + count = 0; + else + { + repeater_count* p = next; + while(p->state_id != state_id) + p = p->next; + count = p->count; + start_pos = p->start_pos; + } + } + ~repeater_count() + { + if(next) + *stack = next; + } + std::size_t get_count() { return count; } + int get_id() { return state_id; } + std::size_t operator++() { return ++count; } + bool check_null_repeat(const BidiIterator& pos, std::size_t max) + { + // this is called when we are about to start a new repeat, + // if the last one was NULL move our count to max, + // otherwise save the current position. + bool result = (count == 0) ? false : (pos == start_pos); + if(result) + count = max; + else + start_pos = pos; + return result; + } +}; + +struct saved_state; + +enum saved_state_type +{ + saved_type_end = 0, + saved_type_paren = 1, + saved_type_recurse = 2, + saved_type_assertion = 3, + saved_state_alt = 4, + saved_state_repeater_count = 5, + saved_state_extra_block = 6, + saved_state_greedy_single_repeat = 7, + saved_state_rep_slow_dot = 8, + saved_state_rep_fast_dot = 9, + saved_state_rep_char = 10, + saved_state_rep_short_set = 11, + saved_state_rep_long_set = 12, + saved_state_non_greedy_long_repeat = 13, + saved_state_count = 14 +}; + +template <class Results> +struct recursion_info +{ + typedef typename Results::value_type value_type; + typedef typename value_type::iterator iterator; + int id; + const re_syntax_base* preturn_address; + Results results; + repeater_count<iterator>* repeater_stack; +}; + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4251 4231 4660) +#endif + +template <class BidiIterator, class Allocator, class traits> +class perl_matcher +{ +public: + typedef typename traits::char_type char_type; + typedef perl_matcher<BidiIterator, Allocator, traits> self_type; + typedef bool (self_type::*matcher_proc_type)(void); + typedef std::size_t traits_size_type; + typedef typename is_byte<char_type>::width_type width_type; + typedef typename regex_iterator_traits<BidiIterator>::difference_type difference_type; + typedef match_results<BidiIterator, Allocator> results_type; + + perl_matcher(BidiIterator first, BidiIterator end, + match_results<BidiIterator, Allocator>& what, + const basic_regex<char_type, traits>& e, + match_flag_type f, + BidiIterator l_base) + : m_result(what), base(first), last(end), + position(first), backstop(l_base), re(e), traits_inst(e.get_traits()), + m_independent(false), next_count(&rep_obj), rep_obj(&next_count), recursion_stack_position(0) + { + construct_init(e, f); + } + + bool match(); + bool find(); + + void setf(match_flag_type f) + { m_match_flags |= f; } + void unsetf(match_flag_type f) + { m_match_flags &= ~f; } + +private: + void construct_init(const basic_regex<char_type, traits>& e, match_flag_type f); + + bool find_imp(); + bool match_imp(); +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + typedef bool (perl_matcher::*protected_proc_type)(); + bool protected_call(protected_proc_type); +#endif + void estimate_max_state_count(std::random_access_iterator_tag*); + void estimate_max_state_count(void*); + bool match_prefix(); + bool match_all_states(); + + // match procs, stored in s_match_vtable: + bool match_startmark(); + bool match_endmark(); + bool match_literal(); + bool match_start_line(); + bool match_end_line(); + bool match_wild(); + bool match_match(); + bool match_word_boundary(); + bool match_within_word(); + bool match_word_start(); + bool match_word_end(); + bool match_buffer_start(); + bool match_buffer_end(); + bool match_backref(); + bool match_long_set(); + bool match_set(); + bool match_jump(); + bool match_alt(); + bool match_rep(); + bool match_combining(); + bool match_soft_buffer_end(); + bool match_restart_continue(); + bool match_long_set_repeat(); + bool match_set_repeat(); + bool match_char_repeat(); + bool match_dot_repeat_fast(); + bool match_dot_repeat_slow(); + bool match_dot_repeat_dispatch() + { + return ::boost::is_random_access_iterator<BidiIterator>::value ? match_dot_repeat_fast() : match_dot_repeat_slow(); + } + bool match_backstep(); + bool match_assert_backref(); + bool match_toggle_case(); +#ifdef BOOST_REGEX_RECURSIVE + bool backtrack_till_match(std::size_t count); +#endif + bool match_recursion(); + + // find procs stored in s_find_vtable: + bool find_restart_any(); + bool find_restart_word(); + bool find_restart_line(); + bool find_restart_buf(); + bool find_restart_lit(); + +private: + // final result structure to be filled in: + match_results<BidiIterator, Allocator>& m_result; + // temporary result for POSIX matches: + scoped_ptr<match_results<BidiIterator, Allocator> > m_temp_match; + // pointer to actual result structure to fill in: + match_results<BidiIterator, Allocator>* m_presult; + // start of sequence being searched: + BidiIterator base; + // end of sequence being searched: + BidiIterator last; + // current character being examined: + BidiIterator position; + // where to restart next search after failed match attempt: + BidiIterator restart; + // where the current search started from, acts as base for $` during grep: + BidiIterator search_base; + // how far we can go back when matching lookbehind: + BidiIterator backstop; + // the expression being examined: + const basic_regex<char_type, traits>& re; + // the expression's traits class: + const ::boost::regex_traits_wrapper<traits>& traits_inst; + // the next state in the machine being matched: + const re_syntax_base* pstate; + // matching flags in use: + match_flag_type m_match_flags; + // how many states we have examined so far: + boost::uintmax_t state_count; + // max number of states to examine before giving up: + boost::uintmax_t max_state_count; + // whether we should ignore case or not: + bool icase; + // set to true when (position == last), indicates that we may have a partial match: + bool m_has_partial_match; + // set to true whenever we get a match: + bool m_has_found_match; + // set to true whenever we're inside an independent sub-expression: + bool m_independent; + // the current repeat being examined: + repeater_count<BidiIterator>* next_count; + // the first repeat being examined (top of linked list): + repeater_count<BidiIterator> rep_obj; + // the mask to pass when matching word boundaries: + typename traits::char_class_type m_word_mask; + // the bitmask to use when determining whether a match_any matches a newline or not: + unsigned char match_any_mask; + // recursion information: + recursion_info<results_type> recursion_stack[50]; + unsigned recursion_stack_position; + +#ifdef BOOST_REGEX_NON_RECURSIVE + // + // additional members for non-recursive version: + // + typedef bool (self_type::*unwind_proc_type)(bool); + + void extend_stack(); + bool unwind(bool); + bool unwind_end(bool); + bool unwind_paren(bool); + bool unwind_recursion_stopper(bool); + bool unwind_assertion(bool); + bool unwind_alt(bool); + bool unwind_repeater_counter(bool); + bool unwind_extra_block(bool); + bool unwind_greedy_single_repeat(bool); + bool unwind_slow_dot_repeat(bool); + bool unwind_fast_dot_repeat(bool); + bool unwind_char_repeat(bool); + bool unwind_short_set_repeat(bool); + bool unwind_long_set_repeat(bool); + bool unwind_non_greedy_repeat(bool); + bool unwind_recursion(bool); + bool unwind_recursion_pop(bool); + void destroy_single_repeat(); + void push_matched_paren(int index, const sub_match<BidiIterator>& sub); + void push_recursion_stopper(); + void push_assertion(const re_syntax_base* ps, bool positive); + void push_alt(const re_syntax_base* ps); + void push_repeater_count(int i, repeater_count<BidiIterator>** s); + void push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id); + void push_non_greedy_repeat(const re_syntax_base* ps); + void push_recursion(int id, const re_syntax_base* p, results_type* presults); + void push_recursion_pop(); + + // pointer to base of stack: + saved_state* m_stack_base; + // pointer to current stack position: + saved_state* m_backup_state; + // determines what value to return when unwinding from recursion, + // allows for mixed recursive/non-recursive algorithm: + bool m_recursive_result; + // how many memory blocks have we used up?: + unsigned used_block_count; +#endif + + // 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) {} +}; + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace re_detail + +#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 + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +// +// include the implementation of perl_matcher: +// +#ifdef BOOST_REGEX_RECURSIVE +#include <boost/regex/v4/perl_matcher_recursive.hpp> +#else +#include <boost/regex/v4/perl_matcher_non_recursive.hpp> +#endif +// this one has to be last: +#include <boost/regex/v4/perl_matcher_common.hpp> + +#endif + diff --git a/ext/boost/regex/v4/perl_matcher_common.hpp b/ext/boost/regex/v4/perl_matcher_common.hpp new file mode 100644 index 0000000000..fd439f84b6 --- /dev/null +++ b/ext/boost/regex/v4/perl_matcher_common.hpp @@ -0,0 +1,949 @@ +/* + * + * Copyright (c) 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 perl_matcher_common.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Definitions of perl_matcher member functions that are + * common to both the recursive and non-recursive versions. + */ + +#ifndef BOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP +#define BOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP + +#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 __BORLANDC__ +# pragma option push -w-8008 -w-8066 +#endif +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4800) +#endif + +namespace boost{ +namespace re_detail{ + +template <class BidiIterator, class Allocator, class traits> +void perl_matcher<BidiIterator, Allocator, traits>::construct_init(const basic_regex<char_type, traits>& e, match_flag_type f) +{ + typedef typename regex_iterator_traits<BidiIterator>::iterator_category category; + typedef typename basic_regex<char_type, traits>::flag_type expression_flag_type; + + if(e.empty()) + { + // precondition failure: e is not a valid regex. + std::invalid_argument ex("Invalid regular expression object"); + boost::throw_exception(ex); + } + pstate = 0; + m_match_flags = f; + estimate_max_state_count(static_cast<category*>(0)); + expression_flag_type re_f = re.flags(); + icase = re_f & regex_constants::icase; + if(!(m_match_flags & (match_perl|match_posix))) + { + if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0) + m_match_flags |= match_perl; + else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex)) + m_match_flags |= match_perl; + else + m_match_flags |= match_posix; + } + if(m_match_flags & match_posix) + { + m_temp_match.reset(new match_results<BidiIterator, Allocator>()); + m_presult = m_temp_match.get(); + } + else + m_presult = &m_result; +#ifdef BOOST_REGEX_NON_RECURSIVE + m_stack_base = 0; + m_backup_state = 0; +#endif + // find the value to use for matching word boundaries: + m_word_mask = re.get_data().m_word_mask; + // find bitmask to use for matching '.': + match_any_mask = static_cast<unsigned char>((f & match_not_dot_newline) ? re_detail::test_not_newline : re_detail::test_newline); +} + +template <class BidiIterator, class Allocator, class traits> +void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std::random_access_iterator_tag*) +{ + // + // How many states should we allow our machine to visit before giving up? + // This is a heuristic: it takes the greater of O(N^2) and O(NS^2) + // where N is the length of the string, and S is the number of states + // in the machine. It's tempting to up this to O(N^2S) or even O(N^2S^2) + // but these take unreasonably amounts of time to bale out in pathological + // cases. + // + // Calculate NS^2 first: + // + static const boost::uintmax_t k = 100000; + boost::uintmax_t dist = boost::re_detail::distance(base, last); + if(dist == 0) + dist = 1; + boost::uintmax_t states = re.size(); + if(states == 0) + states = 1; + states *= states; + if((std::numeric_limits<boost::uintmax_t>::max)() / dist < states) + { + max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2; + return; + } + states *= dist; + if((std::numeric_limits<boost::uintmax_t>::max)() - k < states) + { + max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2; + return; + } + states += k; + + max_state_count = states; + + // + // Now calculate N^2: + // + states = dist; + if((std::numeric_limits<boost::uintmax_t>::max)() / dist < states) + { + max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2; + return; + } + states *= dist; + if((std::numeric_limits<boost::uintmax_t>::max)() - k < states) + { + max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2; + return; + } + states += k; + // + // N^2 can be a very large number indeed, to prevent things getting out + // of control, cap the max states: + // + if(states > BOOST_REGEX_MAX_STATE_COUNT) + states = BOOST_REGEX_MAX_STATE_COUNT; + // + // If (the possibly capped) N^2 is larger than our first estimate, + // use this instead: + // + if(states > max_state_count) + max_state_count = states; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(void*) +{ + // we don't know how long the sequence is: + max_state_count = BOOST_REGEX_MAX_STATE_COUNT; +} + +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD +template <class BidiIterator, class Allocator, class traits> +inline bool perl_matcher<BidiIterator, Allocator, traits>::protected_call( + protected_proc_type proc) +{ + ::boost::re_detail::concrete_protected_call + <perl_matcher<BidiIterator, Allocator, traits> > + obj(this, proc); + return obj.execute(); + +} +#endif + +template <class BidiIterator, class Allocator, class traits> +inline bool perl_matcher<BidiIterator, Allocator, traits>::match() +{ +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + return protected_call(&perl_matcher<BidiIterator, Allocator, traits>::match_imp); +#else + return match_imp(); +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_imp() +{ + // initialise our stack if we are non-recursive: +#ifdef BOOST_REGEX_NON_RECURSIVE + save_state_init init(&m_stack_base, &m_backup_state); + used_block_count = BOOST_REGEX_MAX_BLOCKS; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif +#endif + + // reset our state machine: + position = base; + search_base = base; + state_count = 0; + m_match_flags |= regex_constants::match_all; + m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), search_base, last); + m_presult->set_base(base); + m_presult->set_named_subs(re_detail::convert_to_named_subs<typename match_results<BidiIterator>::char_type>(this->re.get_named_subs())); + if(m_match_flags & match_posix) + m_result = *m_presult; + verify_options(re.flags(), m_match_flags); + if(0 == match_prefix()) + return false; + return (m_result[0].second == last) && (m_result[0].first == base); + +#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif +} + +template <class BidiIterator, class Allocator, class traits> +inline bool perl_matcher<BidiIterator, Allocator, traits>::find() +{ +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + return protected_call(&perl_matcher<BidiIterator, Allocator, traits>::find_imp); +#else + return find_imp(); +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::find_imp() +{ + static matcher_proc_type const s_find_vtable[7] = + { + &perl_matcher<BidiIterator, Allocator, traits>::find_restart_any, + &perl_matcher<BidiIterator, Allocator, traits>::find_restart_word, + &perl_matcher<BidiIterator, Allocator, traits>::find_restart_line, + &perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf, + &perl_matcher<BidiIterator, Allocator, traits>::match_prefix, + &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit, + &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit, + }; + + // initialise our stack if we are non-recursive: +#ifdef BOOST_REGEX_NON_RECURSIVE + save_state_init init(&m_stack_base, &m_backup_state); + used_block_count = BOOST_REGEX_MAX_BLOCKS; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif +#endif + + state_count = 0; + if((m_match_flags & regex_constants::match_init) == 0) + { + // reset our state machine: + search_base = position = base; + pstate = re.get_first_state(); + m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), base, last); + m_presult->set_base(base); + m_presult->set_named_subs(re_detail::convert_to_named_subs<typename match_results<BidiIterator>::char_type>(this->re.get_named_subs())); + m_match_flags |= regex_constants::match_init; + } + else + { + // start again: + search_base = position = m_result[0].second; + // If last match was null and match_not_null was not set then increment + // our start position, otherwise we go into an infinite loop: + if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0)) + { + if(position == last) + return false; + else + ++position; + } + // reset $` start: + m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), search_base, last); + //if((base != search_base) && (base == backstop)) + // m_match_flags |= match_prev_avail; + } + if(m_match_flags & match_posix) + { + m_result.set_size(re.mark_count(), base, last); + m_result.set_base(base); + } + + verify_options(re.flags(), m_match_flags); + // find out what kind of expression we have: + unsigned type = (m_match_flags & match_continuous) ? + static_cast<unsigned int>(regbase::restart_continue) + : static_cast<unsigned int>(re.get_restart_type()); + + // call the appropriate search routine: + matcher_proc_type proc = s_find_vtable[type]; + return (this->*proc)(); + +#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_prefix() +{ + m_has_partial_match = false; + m_has_found_match = false; + pstate = re.get_first_state(); + m_presult->set_first(position); + restart = position; + match_all_states(); + if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial)) + { + m_has_found_match = true; + m_presult->set_second(last, 0, false); + position = last; + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(m_has_found_match && (match_extra & m_match_flags)) + { + // + // we have a match, reverse the capture information: + // + for(unsigned i = 0; i < m_presult->size(); ++i) + { + typename sub_match<BidiIterator>::capture_sequence_type & seq = ((*m_presult)[i]).get_captures(); + std::reverse(seq.begin(), seq.end()); + } + } +#endif + if(!m_has_found_match) + position = restart; // reset search postion + return m_has_found_match; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_literal() +{ + unsigned int len = static_cast<const re_literal*>(pstate)->length; + const char_type* what = reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1); + // + // compare string with what we stored in + // our records: + for(unsigned int i = 0; i < len; ++i, ++position) + { + if((position == last) || (traits_inst.translate(*position, icase) != what[i])) + return false; + } + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_start_line() +{ + if(position == backstop) + { + if((m_match_flags & match_prev_avail) == 0) + { + if((m_match_flags & match_not_bol) == 0) + { + pstate = pstate->next.p; + return true; + } + return false; + } + } + else if(m_match_flags & match_single_line) + return false; + + // check the previous value character: + BidiIterator t(position); + --t; + if(position != last) + { + if(is_separator(*t) && !((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n'))) ) + { + pstate = pstate->next.p; + return true; + } + } + else if(is_separator(*t)) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_end_line() +{ + if(position != last) + { + if(m_match_flags & match_single_line) + return false; + // we're not yet at the end so *first is always valid: + if(is_separator(*position)) + { + if((position != backstop) || (m_match_flags & match_prev_avail)) + { + // check that we're not in the middle of \r\n sequence + BidiIterator t(position); + --t; + if((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n'))) + { + return false; + } + } + pstate = pstate->next.p; + return true; + } + } + else if((m_match_flags & match_not_eol) == 0) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_wild() +{ + if(position == last) + return false; + if(is_separator(*position) && ((match_any_mask & static_cast<const re_dot*>(pstate)->mask) == 0)) + return false; + if((*position == char_type(0)) && (m_match_flags & match_not_dot_null)) + return false; + pstate = pstate->next.p; + ++position; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary() +{ + bool b; // indcates whether next character is a word character + if(position != last) + { + // prev and this character must be opposites: + #if defined(BOOST_REGEX_USE_C_LOCALE) && defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95) + b = traits::isctype(*position, m_word_mask); + #else + b = traits_inst.isctype(*position, m_word_mask); + #endif + } + else + { + b = (m_match_flags & match_not_eow) ? true : false; + } + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + { + if(m_match_flags & match_not_bow) + b ^= true; + else + b ^= false; + } + else + { + --position; + b ^= traits_inst.isctype(*position, m_word_mask); + ++position; + } + if(b) + { + pstate = pstate->next.p; + return true; + } + return false; // no match if we get to here... +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_within_word() +{ + if(position == last) + return false; + // both prev and this character must be m_word_mask: + bool prev = traits_inst.isctype(*position, m_word_mask); + { + bool b; + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + return false; + else + { + --position; + b = traits_inst.isctype(*position, m_word_mask); + ++position; + } + if(b == prev) + { + pstate = pstate->next.p; + return true; + } + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_word_start() +{ + if(position == last) + return false; // can't be starting a word if we're already at the end of input + if(!traits_inst.isctype(*position, m_word_mask)) + return false; // next character isn't a word character + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + { + if(m_match_flags & match_not_bow) + return false; // no previous input + } + else + { + // otherwise inside buffer: + BidiIterator t(position); + --t; + if(traits_inst.isctype(*t, m_word_mask)) + return false; // previous character not non-word + } + // OK we have a match: + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_word_end() +{ + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + return false; // start of buffer can't be end of word + BidiIterator t(position); + --t; + if(traits_inst.isctype(*t, m_word_mask) == false) + return false; // previous character wasn't a word character + + if(position == last) + { + if(m_match_flags & match_not_eow) + return false; // end of buffer but not end of word + } + else + { + // otherwise inside buffer: + if(traits_inst.isctype(*position, m_word_mask)) + return false; // next character is a word character + } + pstate = pstate->next.p; + return true; // if we fall through to here then we've succeeded +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start() +{ + if((position != backstop) || (m_match_flags & match_not_bob)) + return false; + // OK match: + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end() +{ + if((position != last) || (m_match_flags & match_not_eob)) + return false; + // OK match: + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_backref() +{ + // + // Compare with what we previously matched. + // Note that this succeeds if the backref did not partisipate + // in the match, this is in line with ECMAScript, but not Perl + // or PCRE. + // + BidiIterator i = (*m_presult)[static_cast<const re_brace*>(pstate)->index].first; + BidiIterator j = (*m_presult)[static_cast<const re_brace*>(pstate)->index].second; + while(i != j) + { + if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase))) + return false; + ++i; + ++position; + } + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set() +{ + typedef typename traits::char_class_type char_class_type; + // let the traits class do the work: + if(position == last) + return false; + BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data(), icase); + if(t != position) + { + pstate = pstate->next.p; + position = t; + return true; + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_set() +{ + if(position == last) + return false; + if(static_cast<const re_set*>(pstate)->_map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + pstate = pstate->next.p; + ++position; + return true; + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_jump() +{ + pstate = static_cast<const re_jump*>(pstate)->alt.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_combining() +{ + if(position == last) + return false; + if(is_combining(traits_inst.translate(*position, icase))) + return false; + ++position; + while((position != last) && is_combining(traits_inst.translate(*position, icase))) + ++position; + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end() +{ + if(m_match_flags & match_not_eob) + return false; + BidiIterator p(position); + while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p; + if(p != last) + return false; + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue() +{ + if(position == search_base) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_backstep() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if( ::boost::is_random_access_iterator<BidiIterator>::value) + { + std::ptrdiff_t maxlen = ::boost::re_detail::distance(backstop, position); + if(maxlen < static_cast<const re_brace*>(pstate)->index) + return false; + std::advance(position, -static_cast<const re_brace*>(pstate)->index); + } + else + { + int c = static_cast<const re_brace*>(pstate)->index; + while(c--) + { + if(position == backstop) + return false; + --position; + } + } + pstate = pstate->next.p; + return true; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref() +{ + // return true if marked sub-expression N has been matched: + int index = static_cast<const re_brace*>(pstate)->index; + bool result; + if(index == 9999) + { + // Magic value for a (DEFINE) block: + return false; + } + else if(index > 0) + { + // Check if index is a hash value: + if(index >= 10000) + index = re.get_data().get_id(index); + // Have we matched subexpression "index"? + result = (*m_presult)[index].matched; + pstate = pstate->next.p; + } + else + { + // Have we recursed into subexpression "index"? + // If index == 0 then check for any recursion at all, otherwise for recursion to -index-1. + int id = -index-1; + if(id >= 10000) + id = re.get_data().get_id(id); + result = recursion_stack_position && ((recursion_stack[recursion_stack_position-1].id == id) || (index == 0)); + pstate = pstate->next.p; + } + return result; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case() +{ + // change our case sensitivity: + this->icase = static_cast<const re_case*>(pstate)->icase; + pstate = pstate->next.p; + return true; +} + + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + const unsigned char* _map = re.get_map(); + while(true) + { + // skip everything we can't match: + while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) ) + ++position; + if(position == last) + { + // run out of characters, try a null match if possible: + if(re.can_be_null()) + return match_prefix(); + break; + } + // now try and obtain a match: + if(match_prefix()) + return true; + if(position == last) + return false; + ++position; + } + return false; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_word() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // do search optimised for word starts: + const unsigned char* _map = re.get_map(); + if((m_match_flags & match_prev_avail) || (position != base)) + --position; + else if(match_prefix()) + return true; + do + { + while((position != last) && traits_inst.isctype(*position, m_word_mask)) + ++position; + while((position != last) && !traits_inst.isctype(*position, m_word_mask)) + ++position; + if(position == last) + break; + + if(can_start(*position, _map, (unsigned char)mask_any) ) + { + if(match_prefix()) + return true; + } + if(position == last) + break; + } while(true); + return false; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_line() +{ + // do search optimised for line starts: + const unsigned char* _map = re.get_map(); + if(match_prefix()) + return true; + while(position != last) + { + while((position != last) && !is_separator(*position)) + ++position; + if(position == last) + return false; + ++position; + if(position == last) + { + if(re.can_be_null() && match_prefix()) + return true; + return false; + } + + if( can_start(*position, _map, (unsigned char)mask_any) ) + { + if(match_prefix()) + return true; + } + if(position == last) + return false; + //++position; + } + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf() +{ + if((position == base) && ((m_match_flags & match_not_bob) == 0)) + return match_prefix(); + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit() +{ +#if 0 + if(position == last) + return false; // can't possibly match if we're at the end already + + unsigned type = (m_match_flags & match_continuous) ? + static_cast<unsigned int>(regbase::restart_continue) + : static_cast<unsigned int>(re.get_restart_type()); + + const kmp_info<char_type>* info = access::get_kmp(re); + int len = info->len; + const char_type* x = info->pstr; + int j = 0; + while (position != last) + { + while((j > -1) && (x[j] != traits_inst.translate(*position, icase))) + j = info->kmp_next[j]; + ++position; + ++j; + if(j >= len) + { + if(type == regbase::restart_fixed_lit) + { + std::advance(position, -j); + restart = position; + std::advance(restart, len); + m_result.set_first(position); + m_result.set_second(restart); + position = restart; + return true; + } + else + { + restart = position; + std::advance(position, -j); + if(match_prefix()) + return true; + else + { + for(int k = 0; (restart != position) && (k < j); ++k, --restart) + {} // dwa 10/20/2000 - warning suppression for MWCW + if(restart != last) + ++restart; + position = restart; + j = 0; //we could do better than this... + } + } + } + } + if((m_match_flags & match_partial) && (position == last) && j) + { + // we need to check for a partial match: + restart = position; + std::advance(position, -j); + return match_prefix(); + } +#endif + return false; +} + +} // namespace re_detail + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#ifdef __BORLANDC__ +# pragma option 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 + +#endif + diff --git a/ext/boost/regex/v4/perl_matcher_non_recursive.hpp b/ext/boost/regex/v4/perl_matcher_non_recursive.hpp new file mode 100644 index 0000000000..2ce7ebe034 --- /dev/null +++ b/ext/boost/regex/v4/perl_matcher_non_recursive.hpp @@ -0,0 +1,1635 @@ +/* + * + * Copyright (c) 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 perl_matcher_common.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Definitions of perl_matcher member functions that are + * specific to the non-recursive implementation. + */ + +#ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP +#define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP + +#include <new> + +#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: 4800) +#endif + +namespace boost{ +namespace re_detail{ + +template <class T> +inline void inplace_destroy(T* p) +{ + (void)p; // warning suppression + p->~T(); +} + +struct saved_state +{ + union{ + unsigned int state_id; + // this padding ensures correct alignment on 64-bit platforms: + std::size_t padding1; + std::ptrdiff_t padding2; + void* padding3; + }; + saved_state(unsigned i) : state_id(i) {} +}; + +template <class BidiIterator> +struct saved_matched_paren : public saved_state +{ + int index; + sub_match<BidiIterator> sub; + saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){}; +}; + +template <class BidiIterator> +struct saved_position : public saved_state +{ + const re_syntax_base* pstate; + BidiIterator position; + saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){}; +}; + +template <class BidiIterator> +struct saved_assertion : public saved_position<BidiIterator> +{ + bool positive; + saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos) + : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){}; +}; + +template <class BidiIterator> +struct saved_repeater : public saved_state +{ + repeater_count<BidiIterator> count; + saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start) + : saved_state(saved_state_repeater_count), count(i,s,start){} +}; + +struct saved_extra_block : public saved_state +{ + saved_state *base, *end; + saved_extra_block(saved_state* b, saved_state* e) + : saved_state(saved_state_extra_block), base(b), end(e) {} +}; + +struct save_state_init +{ + saved_state** stack; + save_state_init(saved_state** base, saved_state** end) + : stack(base) + { + *base = static_cast<saved_state*>(get_mem_block()); + *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE); + --(*end); + (void) new (*end)saved_state(0); + BOOST_ASSERT(*end > *base); + } + ~save_state_init() + { + put_mem_block(*stack); + *stack = 0; + } +}; + +template <class BidiIterator> +struct saved_single_repeat : public saved_state +{ + std::size_t count; + const re_repeat* rep; + BidiIterator last_position; + saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id) + : saved_state(arg_id), count(c), rep(r), last_position(lp){} +}; + +template <class Results> +struct saved_recursion : public saved_state +{ + saved_recursion(int id, const re_syntax_base* p, Results* pr) + : saved_state(14), recursion_id(id), preturn_address(p), results(*pr) + {} + int recursion_id; + const re_syntax_base* preturn_address; + Results results; +}; + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states() +{ + static matcher_proc_type const s_match_vtable[30] = + { + (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark), + &perl_matcher<BidiIterator, Allocator, traits>::match_endmark, + &perl_matcher<BidiIterator, Allocator, traits>::match_literal, + &perl_matcher<BidiIterator, Allocator, traits>::match_start_line, + &perl_matcher<BidiIterator, Allocator, traits>::match_end_line, + &perl_matcher<BidiIterator, Allocator, traits>::match_wild, + &perl_matcher<BidiIterator, Allocator, traits>::match_match, + &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary, + &perl_matcher<BidiIterator, Allocator, traits>::match_within_word, + &perl_matcher<BidiIterator, Allocator, traits>::match_word_start, + &perl_matcher<BidiIterator, Allocator, traits>::match_word_end, + &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start, + &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end, + &perl_matcher<BidiIterator, Allocator, traits>::match_backref, + &perl_matcher<BidiIterator, Allocator, traits>::match_long_set, + &perl_matcher<BidiIterator, Allocator, traits>::match_set, + &perl_matcher<BidiIterator, Allocator, traits>::match_jump, + &perl_matcher<BidiIterator, Allocator, traits>::match_alt, + &perl_matcher<BidiIterator, Allocator, traits>::match_rep, + &perl_matcher<BidiIterator, Allocator, traits>::match_combining, + &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end, + &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue, + // Although this next line *should* be evaluated at compile time, in practice + // some compilers (VC++) emit run-time initialisation which breaks thread + // safety, so use a dispatch function instead: + //(::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow), + &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch, + &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::match_backstep, + &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref, + &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case, + &perl_matcher<BidiIterator, Allocator, traits>::match_recursion, + }; + + push_recursion_stopper(); + do{ + while(pstate) + { + matcher_proc_type proc = s_match_vtable[pstate->type]; + ++state_count; + if(!(this->*proc)()) + { + if(state_count > max_state_count) + raise_error(traits_inst, regex_constants::error_space); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + bool successful_unwind = unwind(false); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(false == successful_unwind) + return m_recursive_result; + } + } + }while(unwind(true)); + return m_recursive_result; +} + +template <class BidiIterator, class Allocator, class traits> +void perl_matcher<BidiIterator, Allocator, traits>::extend_stack() +{ + if(used_block_count) + { + --used_block_count; + saved_state* stack_base; + saved_state* backup_state; + stack_base = static_cast<saved_state*>(get_mem_block()); + backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE); + saved_extra_block* block = static_cast<saved_extra_block*>(backup_state); + --block; + (void) new (block) saved_extra_block(m_stack_base, m_backup_state); + m_stack_base = stack_base; + m_backup_state = block; + } + else + raise_error(traits_inst, regex_constants::error_size); +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub) +{ + //BOOST_ASSERT(index); + saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper() +{ + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(saved_type_recurse); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive) +{ + saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps) +{ + saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps) +{ + saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s) +{ + saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_repeater<BidiIterator>(i, s, position); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id) +{ + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int id, const re_syntax_base* p, results_type* presults) +{ + saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_recursion<results_type>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_recursion<results_type>(id, p, presults); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark() +{ + int index = static_cast<const re_brace*>(pstate)->index; + icase = static_cast<const re_brace*>(pstate)->icase; + switch(index) + { + case 0: + pstate = pstate->next.p; + break; + case -1: + case -2: + { + // forward lookahead assert: + const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + push_assertion(next_pstate, index == -1); + break; + } + case -3: + { + // independent sub-expression, currently this is always recursive: + bool old_independent = m_independent; + m_independent = true; + const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool r = match_all_states(); + pstate = next_pstate; + m_independent = old_independent; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(r && (m_match_flags & match_extra)) + { + // + // our captures have been stored in *m_presult + // we need to unpack them, and insert them + // back in the right order when we unwind the stack: + // + match_results<BidiIterator, Allocator> temp_match(*m_presult); + unsigned i; + for(i = 0; i < temp_match.size(); ++i) + (*m_presult)[i].get_captures().clear(); + // match everything else: + r = match_all_states(); + // now place the stored captures back: + for(i = 0; i < temp_match.size(); ++i) + { + typedef typename sub_match<BidiIterator>::capture_sequence_type seq; + seq& s1 = (*m_presult)[i].get_captures(); + const seq& s2 = temp_match[i].captures(); + s1.insert( + s1.end(), + s2.begin(), + s2.end()); + } + } +#endif + return r; + } + case -4: + { + // conditional expression: + const re_alt* alt = static_cast<const re_alt*>(pstate->next.p); + BOOST_ASSERT(alt->type == syntax_element_alt); + pstate = alt->next.p; + if(pstate->type == syntax_element_assert_backref) + { + if(!match_assert_backref()) + pstate = alt->alt.p; + break; + } + else + { + // zero width assertion, have to match this recursively: + BOOST_ASSERT(pstate->type == syntax_element_startmark); + bool negated = static_cast<const re_brace*>(pstate)->index == -2; + BidiIterator saved_position = position; + const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool r = match_all_states(); + position = saved_position; + if(negated) + r = !r; + if(r) + pstate = next_pstate; + else + pstate = alt->alt.p; + break; + } + } + case -5: + { + push_matched_paren(0, (*m_presult)[0]); + m_presult->set_first(position, 0, true); + pstate = pstate->next.p; + break; + } + default: + { + BOOST_ASSERT(index > 0); + if((m_match_flags & match_nosubs) == 0) + { + push_matched_paren(index, (*m_presult)[index]); + m_presult->set_first(position, index); + } + pstate = pstate->next.p; + break; + } + } + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_alt() +{ + bool take_first, take_second; + const re_alt* jmp = static_cast<const re_alt*>(pstate); + + // find out which of these two alternatives we need to take: + if(position == last) + { + take_first = jmp->can_be_null & mask_take; + take_second = jmp->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, jmp->_map, (unsigned char)mask_take); + take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip); + } + + if(take_first) + { + // we can take the first alternative, + // see if we need to push next alternative: + if(take_second) + { + push_alt(jmp->alt.p); + } + pstate = pstate->next.p; + return true; + } + if(take_second) + { + pstate = jmp->alt.p; + return true; + } + return false; // neither option is possible +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_rep() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127 4244) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + + // find out which of these two alternatives we need to take: + bool take_first, take_second; + if(position == last) + { + take_first = rep->can_be_null & mask_take; + take_second = rep->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, rep->_map, (unsigned char)mask_take); + take_second = can_start(*position, rep->_map, (unsigned char)mask_skip); + } + + if((m_backup_state->state_id != saved_state_repeater_count) + || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id) + || (next_count->get_id() != rep->state_id)) + { + // we're moving to a different repeat from the last + // one, so set up a counter object: + push_repeater_count(rep->state_id, &next_count); + } + // + // If we've had at least one repeat already, and the last one + // matched the NULL string then set the repeat count to + // maximum: + // + next_count->check_null_repeat(position, rep->max); + + if(next_count->get_count() < rep->min) + { + // we must take the repeat: + if(take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + return false; + } + + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // try and take the repeat if we can: + if((next_count->get_count() < rep->max) && take_first) + { + if(take_second) + { + // store position in case we fail: + push_alt(rep->alt.p); + } + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + else if(take_second) + { + pstate = rep->alt.p; + return true; + } + return false; // can't take anything, fail... + } + else // non-greedy + { + // try and skip the repeat if we can: + if(take_second) + { + if((next_count->get_count() < rep->max) && take_first) + { + // store position in case we fail: + push_non_greedy_repeat(rep->next.p); + } + pstate = rep->alt.p; + return true; + } + if((next_count->get_count() < rep->max) && take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + } + return false; +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow() +{ + unsigned count = 0; + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + re_syntax_base* psingle = rep->next.p; + // match compulsary repeats first: + while(count < rep->min) + { + pstate = psingle; + if(!match_wild()) + return false; + ++count; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // repeat for as long as we can: + while(count < rep->max) + { + pstate = psingle; + if(!match_wild()) + break; + ++count; + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_slow_dot); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast() +{ + if(m_match_flags & match_not_dot_null) + return match_dot_repeat_slow(); + if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0) + return match_dot_repeat_slow(); + + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + unsigned count = static_cast<unsigned>((std::min)(static_cast<unsigned>(::boost::re_detail::distance(position, last)), static_cast<unsigned>(greedy ? rep->max : rep->min))); + if(rep->min > count) + { + position = last; + return false; // not enough text left to match + } + std::advance(position, count); + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_fast_dot); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length); + const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator<BidiIterator>::value) + { + BidiIterator end = position; + std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired)); + BidiIterator origin(position); + while((position != end) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + } + count = (unsigned)::boost::re_detail::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_char); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map; + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator<BidiIterator>::value) + { + BidiIterator end = position; + std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired)); + BidiIterator origin(position); + while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + ++position; + } + count = (unsigned)::boost::re_detail::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_short_set); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + typedef typename traits::char_class_type mask_type; + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + const re_set_long<mask_type>* set = static_cast<const re_set_long<mask_type>*>(pstate->next.p); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator<BidiIterator>::value) + { + BidiIterator end = position; + std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired)); + BidiIterator origin(position); + while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + } + count = (unsigned)::boost::re_detail::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_long_set); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion() +{ + BOOST_ASSERT(pstate->type == syntax_element_recurse); + // + // Backup call stack: + // + push_recursion_pop(); + // + // Set new call stack: + // + if(recursion_stack_position >= static_cast<int>(sizeof(recursion_stack)/sizeof(recursion_stack[0]))) + { + return false; + } + recursion_stack[recursion_stack_position].preturn_address = pstate->next.p; + recursion_stack[recursion_stack_position].results = *m_presult; + pstate = static_cast<const re_jump*>(pstate)->alt.p; + recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index; + ++recursion_stack_position; + //BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id); + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark() +{ + int index = static_cast<const re_brace*>(pstate)->index; + icase = static_cast<const re_brace*>(pstate)->icase; + if(index > 0) + { + if((m_match_flags & match_nosubs) == 0) + { + m_presult->set_second(position, index); + } + if(recursion_stack_position) + { + if(index == recursion_stack[recursion_stack_position-1].id) + { + --recursion_stack_position; + pstate = recursion_stack[recursion_stack_position].preturn_address; + *m_presult = recursion_stack[recursion_stack_position].results; + push_recursion(recursion_stack[recursion_stack_position].id, recursion_stack[recursion_stack_position].preturn_address, &recursion_stack[recursion_stack_position].results); + } + } + } + else if((index < 0) && (index != -4)) + { + // matched forward lookahead: + pstate = 0; + return true; + } + pstate = pstate->next.p; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_match() +{ + if(recursion_stack_position) + { + BOOST_ASSERT(0 == recursion_stack[recursion_stack_position-1].id); + --recursion_stack_position; + pstate = recursion_stack[recursion_stack_position].preturn_address; + *m_presult = recursion_stack[recursion_stack_position].results; + push_recursion(recursion_stack[recursion_stack_position].id, recursion_stack[recursion_stack_position].preturn_address, &recursion_stack[recursion_stack_position].results); + return true; + } + if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first)) + return false; + if((m_match_flags & match_all) && (position != last)) + return false; + if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base)) + return false; + m_presult->set_second(position); + pstate = 0; + m_has_found_match = true; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + if((m_match_flags & match_any) == 0) + return false; + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(match_extra & m_match_flags) + { + for(unsigned i = 0; i < m_presult->size(); ++i) + if((*m_presult)[i].matched) + ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]); + } +#endif + return true; +} + +/**************************************************************************** + +Unwind and associated proceedures follow, these perform what normal stack +unwinding does in the recursive implementation. + +****************************************************************************/ + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match) +{ + static unwind_proc_type const s_unwind_table[18] = + { + &perl_matcher<BidiIterator, Allocator, traits>::unwind_end, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_paren, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_alt, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion, + &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop, + }; + + m_recursive_result = have_match; + unwind_proc_type unwinder; + bool cont; + // + // keep unwinding our stack until we have something to do: + // + do + { + unwinder = s_unwind_table[m_backup_state->state_id]; + cont = (this->*unwinder)(m_recursive_result); + }while(cont); + // + // return true if we have more states to try: + // + return pstate ? true : false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool) +{ + pstate = 0; // nothing left to search + return false; // end of stack nothing more to search +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match) +{ + saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state); + // restore previous values if no match was found: + if(have_match == false) + { + m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0); + m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0); + } +#ifdef BOOST_REGEX_MATCH_EXTRA + // + // we have a match, push the capture information onto the stack: + // + else if(pmp->sub.matched && (match_extra & m_match_flags)) + ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub); +#endif + // unwind stack: + m_backup_state = pmp+1; + boost::re_detail::inplace_destroy(pmp); + return true; // keep looking +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool) +{ + boost::re_detail::inplace_destroy(m_backup_state++); + pstate = 0; // nothing left to search + return false; // end of stack nothing more to search +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r) +{ + saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state); + pstate = pmp->pstate; + position = pmp->position; + bool result = (r == pmp->positive); + m_recursive_result = pmp->positive ? r : !r; + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return !result; // return false if the assertion was matched to stop search. +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r) +{ + saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + if(!r) + { + pstate = pmp->pstate; + position = pmp->position; + } + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return r; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool) +{ + saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state); + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; // keep looking +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool) +{ + saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state); + void* condemmed = m_stack_base; + m_stack_base = pmp->base; + m_backup_state = pmp->end; + boost::re_detail::inplace_destroy(pmp); + put_mem_block(condemmed); + return true; // keep looking +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat() +{ + saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + boost::re_detail::inplace_destroy(p++); + m_backup_state = p; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r) +{ + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + BOOST_ASSERT(rep->next.p != 0); + BOOST_ASSERT(rep->alt.p != 0); + + count -= rep->min; + + if((m_match_flags & match_partial) && (position == last)) + m_has_partial_match = true; + + BOOST_ASSERT(count); + position = pmp->last_position; + + // backtrack till we can skip out: + do + { + --position; + --count; + ++state_count; + }while(count && !can_start(*position, rep->_map, mask_skip)); + + // if we've hit base, destroy this state: + if(count == 0) + { + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count + rep->min; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r) +{ + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + BOOST_ASSERT(rep->type == syntax_element_dot_rep); + BOOST_ASSERT(rep->next.p != 0); + BOOST_ASSERT(rep->alt.p != 0); + BOOST_ASSERT(rep->next.p->type == syntax_element_wild); + + BOOST_ASSERT(count < rep->max); + pstate = rep->next.p; + position = pmp->last_position; + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(!match_wild()) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r) +{ + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + + BOOST_ASSERT(count < rep->max); + position = pmp->last_position; + if(position != last) + { + + // wind forward until we can skip out of the repeat: + do + { + ++position; + ++count; + ++state_count; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r) +{ + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1); + position = pmp->last_position; + + BOOST_ASSERT(rep->type == syntax_element_char_rep); + BOOST_ASSERT(rep->next.p != 0); + BOOST_ASSERT(rep->alt.p != 0); + BOOST_ASSERT(rep->next.p->type == syntax_element_literal); + BOOST_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(traits_inst.translate(*position, icase) != what) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++ position; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r) +{ + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map; + position = pmp->last_position; + + BOOST_ASSERT(rep->type == syntax_element_short_set_rep); + BOOST_ASSERT(rep->next.p != 0); + BOOST_ASSERT(rep->alt.p != 0); + BOOST_ASSERT(rep->next.p->type == syntax_element_set); + BOOST_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++ position; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r) +{ + typedef typename traits::char_class_type mask_type; + saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const re_set_long<mask_type>* set = static_cast<const re_set_long<mask_type>*>(pstate); + position = pmp->last_position; + + BOOST_ASSERT(rep->type == syntax_element_long_set_rep); + BOOST_ASSERT(rep->next.p != 0); + BOOST_ASSERT(rep->alt.p != 0); + BOOST_ASSERT(rep->next.p->type == syntax_element_long_set); + BOOST_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(position == re_is_set_member(position, last, set, re.get_data(), icase)) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++position; + ++count; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r) +{ + saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + if(!r) + { + position = pmp->position; + pstate = pmp->pstate; + ++(*next_count); + } + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return r; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r) +{ + saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state); + if(!r) + { + recursion_stack[recursion_stack_position].id = pmp->recursion_id; + recursion_stack[recursion_stack_position].preturn_address = pmp->preturn_address; + recursion_stack[recursion_stack_position].results = pmp->results; + ++recursion_stack_position; + } + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r) +{ + saved_state* pmp = static_cast<saved_state*>(m_backup_state); + if(!r) + { + --recursion_stack_position; + } + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop() +{ + saved_state* pmp = static_cast<saved_state*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_state*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_state(15); + m_backup_state = pmp; +} +/* +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r) +{ + saved_state* pmp = static_cast<saved_state*>(m_backup_state); + if(!r) + { + --parenthesis_stack_position; + } + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop() +{ + saved_state* pmp = static_cast<saved_state*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_state*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_state(16); + m_backup_state = pmp; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r) +{ + saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + if(!r) + { + parenthesis_stack[parenthesis_stack_position++] = pmp->position; + } + boost::re_detail::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p) +{ + saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position<BidiIterator>(0, p, 17); + m_backup_state = pmp; +} +*/ +} // namespace re_detail +} // namespace boost + +#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 + +#endif + + diff --git a/ext/boost/regex/v4/perl_matcher_recursive.hpp b/ext/boost/regex/v4/perl_matcher_recursive.hpp new file mode 100644 index 0000000000..48f08b7b8d --- /dev/null +++ b/ext/boost/regex/v4/perl_matcher_recursive.hpp @@ -0,0 +1,992 @@ +/* + * + * Copyright (c) 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 perl_matcher_common.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Definitions of perl_matcher member functions that are + * specific to the recursive implementation. + */ + +#ifndef BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP +#define BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP + +#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: 4800) +#endif + +namespace boost{ +namespace re_detail{ + +template <class BidiIterator> +class backup_subex +{ + int index; + sub_match<BidiIterator> sub; +public: + template <class A> + backup_subex(const match_results<BidiIterator, A>& w, int i) + : index(i), sub(w[i], false) {} + template <class A> + void restore(match_results<BidiIterator, A>& w) + { + w.set_first(sub.first, index, index == 0); + w.set_second(sub.second, index, sub.matched, index == 0); + } + const sub_match<BidiIterator>& get() { return sub; } +}; + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states() +{ + static matcher_proc_type const s_match_vtable[30] = + { + (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark), + &perl_matcher<BidiIterator, Allocator, traits>::match_endmark, + &perl_matcher<BidiIterator, Allocator, traits>::match_literal, + &perl_matcher<BidiIterator, Allocator, traits>::match_start_line, + &perl_matcher<BidiIterator, Allocator, traits>::match_end_line, + &perl_matcher<BidiIterator, Allocator, traits>::match_wild, + &perl_matcher<BidiIterator, Allocator, traits>::match_match, + &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary, + &perl_matcher<BidiIterator, Allocator, traits>::match_within_word, + &perl_matcher<BidiIterator, Allocator, traits>::match_word_start, + &perl_matcher<BidiIterator, Allocator, traits>::match_word_end, + &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start, + &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end, + &perl_matcher<BidiIterator, Allocator, traits>::match_backref, + &perl_matcher<BidiIterator, Allocator, traits>::match_long_set, + &perl_matcher<BidiIterator, Allocator, traits>::match_set, + &perl_matcher<BidiIterator, Allocator, traits>::match_jump, + &perl_matcher<BidiIterator, Allocator, traits>::match_alt, + &perl_matcher<BidiIterator, Allocator, traits>::match_rep, + &perl_matcher<BidiIterator, Allocator, traits>::match_combining, + &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end, + &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue, + // Although this next line *should* be evaluated at compile time, in practice + // some compilers (VC++) emit run-time initialisation which breaks thread + // safety, so use a dispatch function instead: + //(::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow), + &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch, + &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat, + &perl_matcher<BidiIterator, Allocator, traits>::match_backstep, + &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref, + &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case, + &perl_matcher<BidiIterator, Allocator, traits>::match_recursion, + }; + + if(state_count > max_state_count) + raise_error(traits_inst, regex_constants::error_space); + while(pstate) + { + matcher_proc_type proc = s_match_vtable[pstate->type]; + ++state_count; + if(!(this->*proc)()) + { + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + return 0; + } + } + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark() +{ + int index = static_cast<const re_brace*>(pstate)->index; + icase = static_cast<const re_brace*>(pstate)->icase; + bool r = true; + switch(index) + { + case 0: + pstate = pstate->next.p; + break; + case -1: + case -2: + { + // forward lookahead assert: + BidiIterator old_position(position); + const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + r = match_all_states(); + pstate = next_pstate; + position = old_position; + if((r && (index != -1)) || (!r && (index != -2))) + r = false; + else + r = true; + break; + } + case -3: + { + // independent sub-expression: + bool old_independent = m_independent; + m_independent = true; + const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + r = match_all_states(); + pstate = next_pstate; + m_independent = old_independent; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(r && (m_match_flags & match_extra)) + { + // + // our captures have been stored in *m_presult + // we need to unpack them, and insert them + // back in the right order when we unwind the stack: + // + unsigned i; + match_results<BidiIterator, Allocator> tm(*m_presult); + for(i = 0; i < tm.size(); ++i) + (*m_presult)[i].get_captures().clear(); + // match everything else: + r = match_all_states(); + // now place the stored captures back: + for(i = 0; i < tm.size(); ++i) + { + typedef typename sub_match<BidiIterator>::capture_sequence_type seq; + seq& s1 = (*m_presult)[i].get_captures(); + const seq& s2 = tm[i].captures(); + s1.insert( + s1.end(), + s2.begin(), + s2.end()); + } + } +#endif + break; + } + case -4: + { + // conditional expression: + const re_alt* alt = static_cast<const re_alt*>(pstate->next.p); + BOOST_ASSERT(alt->type == syntax_element_alt); + pstate = alt->next.p; + if(pstate->type == syntax_element_assert_backref) + { + if(!match_assert_backref()) + pstate = alt->alt.p; + break; + } + else + { + // zero width assertion, have to match this recursively: + BOOST_ASSERT(pstate->type == syntax_element_startmark); + bool negated = static_cast<const re_brace*>(pstate)->index == -2; + BidiIterator saved_position = position; + const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool r = match_all_states(); + position = saved_position; + if(negated) + r = !r; + if(r) + pstate = next_pstate; + else + pstate = alt->alt.p; + break; + } + } + case -5: + { + // Reset start of $0, since we have a \K escape + backup_subex<BidiIterator> sub(*m_presult, 0); + m_presult->set_first(position, 0, true); + pstate = pstate->next.p; + r = match_all_states(); + if(r == false) + sub.restore(*m_presult); + break; + } + default: + { + BOOST_ASSERT(index > 0); + if((m_match_flags & match_nosubs) == 0) + { + backup_subex<BidiIterator> sub(*m_presult, index); + m_presult->set_first(position, index); + pstate = pstate->next.p; + r = match_all_states(); + if(r == false) + sub.restore(*m_presult); +#ifdef BOOST_REGEX_MATCH_EXTRA + // + // we have a match, push the capture information onto the stack: + // + else if(sub.get().matched && (match_extra & m_match_flags)) + ((*m_presult)[index]).get_captures().push_back(sub.get()); +#endif + } + else + { + pstate = pstate->next.p; + } + break; + } + } + return r; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_alt() +{ + bool take_first, take_second; + const re_alt* jmp = static_cast<const re_alt*>(pstate); + + // find out which of these two alternatives we need to take: + if(position == last) + { + take_first = jmp->can_be_null & mask_take; + take_second = jmp->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, jmp->_map, (unsigned char)mask_take); + take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip); + } + + if(take_first) + { + // we can take the first alternative, + // see if we need to push next alternative: + if(take_second) + { + BidiIterator oldposition(position); + const re_syntax_base* old_pstate = jmp->alt.p; + pstate = pstate->next.p; + if(!match_all_states()) + { + pstate = old_pstate; + position = oldposition; + } + return true; + } + pstate = pstate->next.p; + return true; + } + if(take_second) + { + pstate = jmp->alt.p; + return true; + } + return false; // neither option is possible +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_rep() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127 4244) +#endif + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + // + // Always copy the repeat count, so that the state is restored + // when we exit this scope: + // + repeater_count<BidiIterator> r(rep->state_id, &next_count, position); + // + // If we've had at least one repeat already, and the last one + // matched the NULL string then set the repeat count to + // maximum: + // + next_count->check_null_repeat(position, rep->max); + + // find out which of these two alternatives we need to take: + bool take_first, take_second; + if(position == last) + { + take_first = rep->can_be_null & mask_take; + take_second = rep->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, rep->_map, (unsigned char)mask_take); + take_second = can_start(*position, rep->_map, (unsigned char)mask_skip); + } + + if(next_count->get_count() < rep->min) + { + // we must take the repeat: + if(take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return match_all_states(); + } + return false; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // try and take the repeat if we can: + if((next_count->get_count() < rep->max) && take_first) + { + // store position in case we fail: + BidiIterator pos = position; + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + if(match_all_states()) + return true; + // failed repeat, reset posistion and fall through for alternative: + position = pos; + } + if(take_second) + { + pstate = rep->alt.p; + return true; + } + return false; // can't take anything, fail... + } + else // non-greedy + { + // try and skip the repeat if we can: + if(take_second) + { + // store position in case we fail: + BidiIterator pos = position; + pstate = rep->alt.p; + if(match_all_states()) + return true; + // failed alternative, reset posistion and fall through for repeat: + position = pos; + } + if((next_count->get_count() < rep->max) && take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return match_all_states(); + } + } + return false; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + unsigned count = 0; + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + re_syntax_base* psingle = rep->next.p; + // match compulsary repeats first: + while(count < rep->min) + { + pstate = psingle; + if(!match_wild()) + return false; + ++count; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // normal repeat: + while(count < rep->max) + { + pstate = psingle; + if(!match_wild()) + break; + ++count; + } + if((rep->leading) && (count < rep->max)) + restart = position; + pstate = rep; + return backtrack_till_match(count - rep->min); + } + else + { + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if(count >= rep->max) + return false; + ++count; + pstate = psingle; + position = save_pos; + if(!match_wild()) + return false; + }while(true); + } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if(m_match_flags & match_not_dot_null) + return match_dot_repeat_slow(); + if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0) + return match_dot_repeat_slow(); + // + // start by working out how much we can skip: + // + const re_repeat* rep = static_cast<const re_repeat*>(pstate); +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4267) +#endif + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t count = (std::min)(static_cast<std::size_t>(::boost::re_detail::distance(position, last)), static_cast<std::size_t>(greedy ? rep->max : rep->min)); + if(rep->min > count) + { + position = last; + return false; // not enough text left to match + } + std::advance(position, count); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + ++position; + ++count; + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if(count >= rep->max) + return false; + if(save_pos == last) + return false; + position = ++save_pos; + ++count; + }while(true); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#pragma warning(disable:4267) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length); + const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1); + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t count, desired; + if(::boost::is_random_access_iterator<BidiIterator>::value) + { + desired = + (std::min)( + (std::size_t)(greedy ? rep->max : rep->min), + (std::size_t)::boost::re_detail::distance(position, last)); + count = desired; + ++desired; + if(icase) + { + while(--desired && (traits_inst.translate_nocase(*position) == what)) + { + ++position; + } + } + else + { + while(--desired && (traits_inst.translate(*position) == what)) + { + ++position; + } + } + count = count - desired; + } + else + { + count = 0; + desired = greedy ? rep->max : rep->min; + while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + } + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(count < rep->min) + return false; + + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + if((traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + else + return false; // counldn't repeat even though it was the only option + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if(count >= rep->max) + return false; + position = save_pos; + if(position == last) + return false; + if(traits_inst.translate(*position, icase) == what) + { + ++position; + ++count; + } + else + { + return false; + } + }while(true); +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map; + unsigned count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator<BidiIterator>::value) + { + BidiIterator end = position; + std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired)); + BidiIterator origin(position); + while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + ++position; + } + count = (unsigned)::boost::re_detail::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + } + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(count < rep->min) + return false; + + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + else + return false; // counldn't repeat even though it was the only option + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if(count >= rep->max) + return false; + position = save_pos; + if(position == last) + return false; + if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + else + { + return false; + } + }while(true); +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef __BORLANDC__ +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + typedef typename traits::char_class_type char_class_type; + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + const re_set_long<char_class_type>* set = static_cast<const re_set_long<char_class_type>*>(pstate->next.p); + unsigned count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator<BidiIterator>::value) + { + BidiIterator end = position; + std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired)); + BidiIterator origin(position); + while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + } + count = (unsigned)::boost::re_detail::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + ++count; + } + } + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(count < rep->min) + return false; + + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + if(position != re_is_set_member(position, last, set, re.get_data(), icase)) + { + ++position; + ++count; + } + else + return false; // counldn't repeat even though it was the only option + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if(count >= rep->max) + return false; + position = save_pos; + if(position == last) + return false; + if(position != re_is_set_member(position, last, set, re.get_data(), icase)) + { + ++position; + ++count; + } + else + { + return false; + } + }while(true); +#ifdef __BORLANDC__ +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::backtrack_till_match(std::size_t count) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if((m_match_flags & match_partial) && (position == last)) + m_has_partial_match = true; + + const re_repeat* rep = static_cast<const re_repeat*>(pstate); + BidiIterator backtrack = position; + if(position == last) + { + if(rep->can_be_null & mask_skip) + { + pstate = rep->alt.p; + if(match_all_states()) + return true; + } + if(count) + { + position = --backtrack; + --count; + } + else + return false; + } + do + { + while(count && !can_start(*position, rep->_map, mask_skip)) + { + --position; + --count; + ++state_count; + } + pstate = rep->alt.p; + backtrack = position; + if(match_all_states()) + return true; + if(count == 0) + return false; + position = --backtrack; + ++state_count; + --count; + }while(true); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion() +{ + BOOST_ASSERT(pstate->type == syntax_element_recurse); + // + // Set new call stack: + // + if(recursion_stack_position >= static_cast<int>(sizeof(recursion_stack)/sizeof(recursion_stack[0]))) + { + return false; + } + recursion_stack[recursion_stack_position].preturn_address = pstate->next.p; + recursion_stack[recursion_stack_position].results = *m_presult; + recursion_stack[recursion_stack_position].repeater_stack = next_count; + pstate = static_cast<const re_jump*>(pstate)->alt.p; + recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index; + ++recursion_stack_position; + + repeater_count<BidiIterator>* saved = next_count; + repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those + next_count = &r; + bool result = match_all_states(); + next_count = saved; + + if(!result) + { + --recursion_stack_position; + next_count = recursion_stack[recursion_stack_position].repeater_stack; + *m_presult = recursion_stack[recursion_stack_position].results; + return false; + } + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark() +{ + int index = static_cast<const re_brace*>(pstate)->index; + icase = static_cast<const re_brace*>(pstate)->icase; + if(index > 0) + { + if((m_match_flags & match_nosubs) == 0) + { + m_presult->set_second(position, index); + } + if(recursion_stack_position) + { + if(index == recursion_stack[recursion_stack_position-1].id) + { + --recursion_stack_position; + recursion_info<results_type> saved = recursion_stack[recursion_stack_position]; + const re_syntax_base* saved_state = pstate = saved.preturn_address; + repeater_count<BidiIterator>* saved_count = next_count; + next_count = saved.repeater_stack; + *m_presult = saved.results; + if(!match_all_states()) + { + recursion_stack[recursion_stack_position] = saved; + ++recursion_stack_position; + next_count = saved_count; + return false; + } + } + } + } + else if((index < 0) && (index != -4)) + { + // matched forward lookahead: + pstate = 0; + return true; + } + pstate = pstate ? pstate->next.p : 0; + return true; +} + +template <class BidiIterator, class Allocator, class traits> +bool perl_matcher<BidiIterator, Allocator, traits>::match_match() +{ + if(recursion_stack_position) + { + BOOST_ASSERT(0 == recursion_stack[recursion_stack_position-1].id); + --recursion_stack_position; + const re_syntax_base* saved_state = pstate = recursion_stack[recursion_stack_position].preturn_address; + *m_presult = recursion_stack[recursion_stack_position].results; + if(!match_all_states()) + { + recursion_stack[recursion_stack_position].preturn_address = saved_state; + recursion_stack[recursion_stack_position].results = *m_presult; + ++recursion_stack_position; + return false; + } + return true; + } + if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first)) + return false; + if((m_match_flags & match_all) && (position != last)) + return false; + if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base)) + return false; + m_presult->set_second(position); + pstate = 0; + m_has_found_match = true; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + if((m_match_flags & match_any) == 0) + return false; + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(match_extra & m_match_flags) + { + for(unsigned i = 0; i < m_presult->size(); ++i) + if((*m_presult)[i].matched) + ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]); + } +#endif + return true; +} + + + +} // namespace re_detail +} // namespace boost +#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 + +#endif + diff --git a/ext/boost/regex/v4/primary_transform.hpp b/ext/boost/regex/v4/primary_transform.hpp new file mode 100644 index 0000000000..989f500c1d --- /dev/null +++ b/ext/boost/regex/v4/primary_transform.hpp @@ -0,0 +1,146 @@ +/* + * + * 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: primary_transform.hpp + * VERSION: see <boost/version.hpp> + * DESCRIPTION: Heuristically determines the sort string format in use + * by the current locale. + */ + +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#define BOOST_REGEX_PRIMARY_TRANSFORM + +#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 + +namespace boost{ + namespace re_detail{ + + +enum{ + sort_C, + sort_fixed, + sort_delim, + sort_unknown +}; + +template <class S, class charT> +unsigned count_chars(const S& s, charT c) +{ + // + // Count how many occurances of character c occur + // in string s: if c is a delimeter between collation + // fields, then this should be the same value for all + // sort keys: + // + unsigned int count = 0; + for(unsigned pos = 0; pos < s.size(); ++pos) + { + if(s[pos] == c) ++count; + } + return count; +} + + +template <class traits, class charT> +unsigned find_sort_syntax(const traits* pt, charT* delim) +{ + // + // compare 'a' with 'A' to see how similar they are, + // should really use a-accute but we can't portably do that, + // + typedef typename traits::string_type string_type; + typedef typename traits::char_type char_type; + + // Suppress incorrect warning for MSVC + (void)pt; + + char_type a[2] = {'a', '\0', }; + string_type sa(pt->transform(a, a+1)); + if(sa == a) + { + *delim = 0; + return sort_C; + } + char_type A[2] = { 'A', '\0', }; + string_type sA(pt->transform(A, A+1)); + char_type c[2] = { ';', '\0', }; + string_type sc(pt->transform(c, c+1)); + + int pos = 0; + while((pos <= static_cast<int>(sa.size())) && (pos <= static_cast<int>(sA.size())) && (sa[pos] == sA[pos])) ++pos; + --pos; + if(pos < 0) + { + *delim = 0; + return sort_unknown; + } + // + // at this point sa[pos] is either the end of a fixed width field + // or the character that acts as a delimiter: + // + charT maybe_delim = sa[pos]; + if((pos != 0) && (count_chars(sa, maybe_delim) == count_chars(sA, maybe_delim)) && (count_chars(sa, maybe_delim) == count_chars(sc, maybe_delim))) + { + *delim = maybe_delim; + return sort_delim; + } + // + // OK doen't look like a delimiter, try for fixed width field: + // + if((sa.size() == sA.size()) && (sa.size() == sc.size())) + { + // note assumes that the fixed width field is less than + // (numeric_limits<charT>::max)(), should be true for all types + // I can't imagine 127 character fields... + *delim = static_cast<charT>(++pos); + return sort_fixed; + } + // + // don't know what it is: + // + *delim = 0; + return sort_unknown; +} + + + } // namespace re_detail +} // namespace boost + +#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 + +#endif + + + + + + + diff --git a/ext/boost/regex/v4/protected_call.hpp b/ext/boost/regex/v4/protected_call.hpp new file mode 100644 index 0000000000..ebf15ba370 --- /dev/null +++ b/ext/boost/regex/v4/protected_call.hpp @@ -0,0 +1,81 @@ +/* + * + * 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 basic_regex_creator.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares template class basic_regex_creator which fills in + * the data members of a regex_data object. + */ + +#ifndef BOOST_REGEX_V4_PROTECTED_CALL_HPP +#define BOOST_REGEX_V4_PROTECTED_CALL_HPP + +#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 + +namespace boost{ +namespace re_detail{ + +class BOOST_REGEX_DECL abstract_protected_call +{ +public: + bool BOOST_REGEX_CALL execute()const; + // this stops gcc-4 from complaining: + virtual ~abstract_protected_call(){} +private: + virtual bool call()const = 0; +}; + +template <class T> +class concrete_protected_call + : public abstract_protected_call +{ +public: + typedef bool (T::*proc_type)(); + concrete_protected_call(T* o, proc_type p) + : obj(o), proc(p) {} +private: + virtual bool call()const; + T* obj; + proc_type proc; +}; + +template <class T> +bool concrete_protected_call<T>::call()const +{ + return (obj->*proc)(); +} + +} +} // namespace boost + +#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 + +#endif diff --git a/ext/boost/regex/v4/regbase.hpp b/ext/boost/regex/v4/regbase.hpp new file mode 100644 index 0000000000..2b737d5aba --- /dev/null +++ b/ext/boost/regex/v4/regbase.hpp @@ -0,0 +1,180 @@ +/* + * + * 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 regbase.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares class regbase. + */ + +#ifndef BOOST_REGEX_V4_REGBASE_HPP +#define BOOST_REGEX_V4_REGBASE_HPP + +#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 + +namespace boost{ +// +// class regbase +// handles error codes and flags +// +class BOOST_REGEX_DECL regbase +{ +public: + enum flag_type_ + { + // + // Divide the flags up into logical groups: + // bits 0-7 indicate main synatx type. + // bits 8-15 indicate syntax subtype. + // bits 16-31 indicate options that are common to all + // regex syntaxes. + // In all cases the default is 0. + // + // Main synatx group: + // + perl_syntax_group = 0, // default + basic_syntax_group = 1, // POSIX basic + literal = 2, // all characters are literals + main_option_type = literal | basic_syntax_group | perl_syntax_group, // everything! + // + // options specific to perl group: + // + no_bk_refs = 1 << 8, // \d not allowed + no_perl_ex = 1 << 9, // disable perl extensions + no_mod_m = 1 << 10, // disable Perl m modifier + mod_x = 1 << 11, // Perl x modifier + mod_s = 1 << 12, // force s modifier on (overrides match_not_dot_newline) + no_mod_s = 1 << 13, // force s modifier off (overrides match_not_dot_newline) + + // + // options specific to basic group: + // + no_char_classes = 1 << 8, // [[:CLASS:]] not allowed + no_intervals = 1 << 9, // {x,y} not allowed + bk_plus_qm = 1 << 10, // uses \+ and \? + bk_vbar = 1 << 11, // use \| for alternatives + emacs_ex = 1 << 12, // enables emacs extensions + + // + // options common to all groups: + // + no_escape_in_lists = 1 << 16, // '\' not special inside [...] + newline_alt = 1 << 17, // \n is the same as | + no_except = 1 << 18, // no exception on error + failbit = 1 << 19, // error flag + icase = 1 << 20, // characters are matched regardless of case + nocollate = 0, // don't use locale specific collation (deprecated) + collate = 1 << 21, // use locale specific collation + nosubs = 1 << 22, // don't mark sub-expressions + save_subexpression_location = 1 << 23, // save subexpression locations + no_empty_expressions = 1 << 24, // no empty expressions allowed + optimize = 0, // not really supported + + + + basic = basic_syntax_group | collate | no_escape_in_lists, + extended = no_bk_refs | collate | no_perl_ex | no_escape_in_lists, + normal = 0, + emacs = basic_syntax_group | collate | emacs_ex | bk_vbar, + awk = no_bk_refs | collate | no_perl_ex, + grep = basic | newline_alt, + egrep = extended | newline_alt, + sed = basic, + perl = normal, + ECMAScript = normal, + JavaScript = normal, + JScript = normal + }; + typedef unsigned int flag_type; + + enum restart_info + { + restart_any = 0, + restart_word = 1, + restart_line = 2, + restart_buf = 3, + restart_continue = 4, + restart_lit = 5, + restart_fixed_lit = 6, + restart_count = 7 + }; +}; + +// +// provide std lib proposal compatible constants: +// +namespace regex_constants{ + + enum flag_type_ + { + + no_except = ::boost::regbase::no_except, + failbit = ::boost::regbase::failbit, + literal = ::boost::regbase::literal, + icase = ::boost::regbase::icase, + nocollate = ::boost::regbase::nocollate, + collate = ::boost::regbase::collate, + nosubs = ::boost::regbase::nosubs, + optimize = ::boost::regbase::optimize, + bk_plus_qm = ::boost::regbase::bk_plus_qm, + bk_vbar = ::boost::regbase::bk_vbar, + no_intervals = ::boost::regbase::no_intervals, + no_char_classes = ::boost::regbase::no_char_classes, + no_escape_in_lists = ::boost::regbase::no_escape_in_lists, + no_mod_m = ::boost::regbase::no_mod_m, + mod_x = ::boost::regbase::mod_x, + mod_s = ::boost::regbase::mod_s, + no_mod_s = ::boost::regbase::no_mod_s, + save_subexpression_location = ::boost::regbase::save_subexpression_location, + no_empty_expressions = ::boost::regbase::no_empty_expressions, + + basic = ::boost::regbase::basic, + extended = ::boost::regbase::extended, + normal = ::boost::regbase::normal, + emacs = ::boost::regbase::emacs, + awk = ::boost::regbase::awk, + grep = ::boost::regbase::grep, + egrep = ::boost::regbase::egrep, + sed = basic, + perl = normal, + ECMAScript = normal, + JavaScript = normal, + JScript = normal + }; + typedef ::boost::regbase::flag_type syntax_option_type; + +} // namespace regex_constants + +} // namespace boost + +#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 + +#endif + diff --git a/ext/boost/regex/v4/regex.hpp b/ext/boost/regex/v4/regex.hpp new file mode 100644 index 0000000000..7cc260a3ac --- /dev/null +++ b/ext/boost/regex/v4/regex.hpp @@ -0,0 +1,202 @@ +/* + * + * 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 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. + */ + +#ifndef BOOST_RE_REGEX_HPP_INCLUDED +#define BOOST_RE_REGEX_HPP_INCLUDED + +#ifdef __cplusplus + +// what follows is all C++ don't include in C builds!! + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include <boost/regex/v4/regex_workaround.hpp> +#endif + +#ifndef BOOST_REGEX_FWD_HPP +#include <boost/regex_fwd.hpp> +#endif +#ifndef BOOST_REGEX_TRAITS_HPP +#include <boost/regex/regex_traits.hpp> +#endif +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#include <boost/regex/v4/error_type.hpp> +#endif +#ifndef BOOST_REGEX_V4_MATCH_FLAGS +#include <boost/regex/v4/match_flags.hpp> +#endif +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#include <boost/regex/v4/regex_raw_buffer.hpp> +#endif +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include <boost/regex/pattern_except.hpp> +#endif + +#ifndef BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP +#include <boost/regex/v4/char_regex_traits.hpp> +#endif +#ifndef BOOST_REGEX_V4_STATES_HPP +#include <boost/regex/v4/states.hpp> +#endif +#ifndef BOOST_REGEX_V4_REGBASE_HPP +#include <boost/regex/v4/regbase.hpp> +#endif +#ifndef BOOST_REGEX_V4_ITERATOR_TRAITS_HPP +#include <boost/regex/v4/iterator_traits.hpp> +#endif +#ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP +#include <boost/regex/v4/basic_regex.hpp> +#endif +#ifndef BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP +#include <boost/regex/v4/basic_regex_creator.hpp> +#endif +#ifndef BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP +#include <boost/regex/v4/basic_regex_parser.hpp> +#endif +#ifndef BOOST_REGEX_V4_SUB_MATCH_HPP +#include <boost/regex/v4/sub_match.hpp> +#endif +#ifndef BOOST_REGEX_FORMAT_HPP +#include <boost/regex/v4/regex_format.hpp> +#endif +#ifndef BOOST_REGEX_V4_MATCH_RESULTS_HPP +#include <boost/regex/v4/match_results.hpp> +#endif +#ifndef BOOST_REGEX_V4_PROTECTED_CALL_HPP +#include <boost/regex/v4/protected_call.hpp> +#endif +#ifndef BOOST_REGEX_MATCHER_HPP +#include <boost/regex/v4/perl_matcher.hpp> +#endif +// +// template instances: +// +#define BOOST_REGEX_CHAR_T char +#ifdef BOOST_REGEX_NARROW_INSTANTIATE +# define BOOST_REGEX_INSTANTIATE +#endif +#include <boost/regex/v4/instances.hpp> +#undef BOOST_REGEX_CHAR_T +#ifdef BOOST_REGEX_INSTANTIATE +# undef BOOST_REGEX_INSTANTIATE +#endif + +#ifndef BOOST_NO_WREGEX +#define BOOST_REGEX_CHAR_T wchar_t +#ifdef BOOST_REGEX_WIDE_INSTANTIATE +# define BOOST_REGEX_INSTANTIATE +#endif +#include <boost/regex/v4/instances.hpp> +#undef BOOST_REGEX_CHAR_T +#ifdef BOOST_REGEX_INSTANTIATE +# undef BOOST_REGEX_INSTANTIATE +#endif +#endif + +#if !defined(BOOST_NO_WREGEX) && defined(BOOST_REGEX_HAS_OTHER_WCHAR_T) +#define BOOST_REGEX_CHAR_T unsigned short +#ifdef BOOST_REGEX_US_INSTANTIATE +# define BOOST_REGEX_INSTANTIATE +#endif +#include <boost/regex/v4/instances.hpp> +#undef BOOST_REGEX_CHAR_T +#ifdef BOOST_REGEX_INSTANTIATE +# undef BOOST_REGEX_INSTANTIATE +#endif +#endif + + +namespace boost{ +#ifdef BOOST_REGEX_NO_FWD +typedef basic_regex<char, regex_traits<char> > regex; +#ifndef BOOST_NO_WREGEX +typedef basic_regex<wchar_t, regex_traits<wchar_t> > wregex; +#endif +#endif + +typedef match_results<const char*> cmatch; +typedef match_results<std::string::const_iterator> smatch; +#ifndef BOOST_NO_WREGEX +typedef match_results<const wchar_t*> wcmatch; +typedef match_results<std::wstring::const_iterator> wsmatch; +#endif + +} // namespace boost +#ifndef BOOST_REGEX_MATCH_HPP +#include <boost/regex/v4/regex_match.hpp> +#endif +#ifndef BOOST_REGEX_V4_REGEX_SEARCH_HPP +#include <boost/regex/v4/regex_search.hpp> +#endif +#ifndef BOOST_REGEX_ITERATOR_HPP +#include <boost/regex/v4/regex_iterator.hpp> +#endif +#ifndef BOOST_REGEX_TOKEN_ITERATOR_HPP +#include <boost/regex/v4/regex_token_iterator.hpp> +#endif +#ifndef BOOST_REGEX_V4_REGEX_GREP_HPP +#include <boost/regex/v4/regex_grep.hpp> +#endif +#ifndef BOOST_REGEX_V4_REGEX_REPLACE_HPP +#include <boost/regex/v4/regex_replace.hpp> +#endif +#ifndef BOOST_REGEX_V4_REGEX_MERGE_HPP +#include <boost/regex/v4/regex_merge.hpp> +#endif +#ifndef BOOST_REGEX_SPLIT_HPP +#include <boost/regex/v4/regex_split.hpp> +#endif + +#endif // __cplusplus + +#endif // include + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/boost/regex/v4/regex_format.hpp b/ext/boost/regex/v4/regex_format.hpp new file mode 100644 index 0000000000..4e95112f90 --- /dev/null +++ b/ext/boost/regex/v4/regex_format.hpp @@ -0,0 +1,829 @@ +/* + * + * 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 regex_format.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_FORMAT_HPP +#define BOOST_REGEX_FORMAT_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 + +// +// Forward declaration: +// + template <class BidiIterator, class Allocator = BOOST_DEDUCED_TYPENAME std::vector<sub_match<BidiIterator> >::allocator_type > +class match_results; + +namespace re_detail{ + +// +// struct trivial_format_traits: +// defines minimum localisation support for formatting +// in the case that the actual regex traits is unavailable. +// +template <class charT> +struct trivial_format_traits +{ + typedef charT char_type; + + static std::ptrdiff_t length(const charT* p) + { + return global_length(p); + } + static charT tolower(charT c) + { + return ::boost::re_detail::global_lower(c); + } + static charT toupper(charT c) + { + return ::boost::re_detail::global_upper(c); + } + static int value(const charT c, int radix) + { + int result = global_value(c); + return result >= radix ? -1 : result; + } + int toi(const charT*& p1, const charT* p2, int radix)const + { + return global_toi(p1, p2, radix, *this); + } +}; + +template <class OutputIterator, class Results, class traits> +class basic_regex_formatter +{ +public: + typedef typename traits::char_type char_type; + basic_regex_formatter(OutputIterator o, const Results& r, const traits& t) + : m_traits(t), m_results(r), m_out(o), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {} + OutputIterator format(const char_type* p1, const char_type* p2, match_flag_type f); + OutputIterator format(const char_type* p1, match_flag_type f) + { + return format(p1, p1 + m_traits.length(p1), f); + } +private: + typedef typename Results::value_type sub_match_type; + enum output_state + { + output_copy, + output_next_lower, + output_next_upper, + output_lower, + output_upper, + output_none + }; + + void put(char_type c); + void put(const sub_match_type& sub); + void format_all(); + void format_perl(); + void format_escape(); + void format_conditional(); + void format_until_scope_end(); + bool handle_perl_verb(bool have_brace); + + const traits& m_traits; // the traits class for localised formatting operations + const Results& m_results; // the match_results being used. + OutputIterator m_out; // where to send output. + const char_type* m_position; // format string, current position + const char_type* m_end; // format string end + match_flag_type m_flags; // format flags to use + output_state m_state; // what to do with the next character + output_state m_restore_state; // what state to restore to. + bool m_have_conditional; // we are parsing a conditional +private: + basic_regex_formatter(const basic_regex_formatter&); + basic_regex_formatter& operator=(const basic_regex_formatter&); +}; + +template <class OutputIterator, class Results, class traits> +OutputIterator basic_regex_formatter<OutputIterator, Results, traits>::format(const char_type* p1, const char_type* p2, match_flag_type f) +{ + m_position = p1; + m_end = p2; + m_flags = f; + format_all(); + return m_out; +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::format_all() +{ + // over and over: + while(m_position != m_end) + { + switch(*m_position) + { + case '&': + if(m_flags & ::boost::regex_constants::format_sed) + { + ++m_position; + put(m_results[0]); + break; + } + put(*m_position++); + break; + case '\\': + format_escape(); + break; + case '(': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + bool have_conditional = m_have_conditional; + m_have_conditional = false; + format_until_scope_end(); + m_have_conditional = have_conditional; + if(m_position == m_end) + return; + BOOST_ASSERT(*m_position == static_cast<char_type>(')')); + ++m_position; // skip the closing ')' + break; + } + put(*m_position); + ++m_position; + break; + case ')': + if(m_flags & boost::regex_constants::format_all) + { + return; + } + put(*m_position); + ++m_position; + break; + case ':': + if((m_flags & boost::regex_constants::format_all) && m_have_conditional) + { + return; + } + put(*m_position); + ++m_position; + break; + case '?': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + format_conditional(); + break; + } + put(*m_position); + ++m_position; + break; + case '$': + if((m_flags & format_sed) == 0) + { + format_perl(); + break; + } + // fall through, not a special character: + default: + put(*m_position); + ++m_position; + break; + } + } +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::format_perl() +{ + // + // On entry *m_position points to a '$' character + // output the information that goes with it: + // + BOOST_ASSERT(*m_position == '$'); + // + // see if this is a trailing '$': + // + if(++m_position == m_end) + { + --m_position; + put(*m_position); + ++m_position; + return; + } + // + // OK find out what kind it is: + // + bool have_brace = false; + const char_type* save_position = m_position; + switch(*m_position) + { + case '&': + ++m_position; + put(this->m_results[0]); + break; + case '`': + ++m_position; + put(this->m_results.prefix()); + break; + case '\'': + ++m_position; + put(this->m_results.suffix()); + break; + case '$': + put(*m_position++); + break; + case '+': + if((++m_position != m_end) && (*m_position == '{')) + { + const char_type* base = ++m_position; + while((m_position != m_end) && (*m_position != '}')) ++m_position; + if(m_position != m_end) + { + // Named sub-expression: + put(this->m_results.named_subexpression(base, m_position)); + ++m_position; + break; + } + else + { + m_position = --base; + } + } + put((this->m_results)[this->m_results.size() > 1 ? this->m_results.size() - 1 : 1]); + break; + case '{': + have_brace = true; + ++m_position; + // fall through.... + default: + // see if we have a number: + { + std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end); + //len = (std::min)(static_cast<std::ptrdiff_t>(2), len); + int v = m_traits.toi(m_position, m_position + len, 10); + if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}')))) + { + // Look for a Perl-5.10 verb: + if(!handle_perl_verb(have_brace)) + { + // leave the $ as is, and carry on: + m_position = --save_position; + put(*m_position); + ++m_position; + } + break; + } + // otherwise output sub v: + put(this->m_results[v]); + if(have_brace) + ++m_position; + } + } +} + +template <class OutputIterator, class Results, class traits> +bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bool have_brace) +{ + // + // We may have a capitalised string containing a Perl action: + // + static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' }; + static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' }; + static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' }; + static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' }; + static const char_type LAST_SUBMATCH_RESULT[] = { 'L', 'A', 'S', 'T', '_', 'S', 'U', 'B', 'M', 'A', 'T', 'C', 'H', '_', 'R', 'E', 'S', 'U', 'L', 'T' }; + static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' }; + + if(have_brace && (*m_position == '^')) + ++m_position; + + int max_len = m_end - m_position; + + if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH)) + { + m_position += 5; + if(have_brace) + { + if(*m_position == '}') + ++m_position; + else + { + m_position -= 5; + return false; + } + } + put(this->m_results[0]); + return true; + } + if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH)) + { + m_position += 8; + if(have_brace) + { + if(*m_position == '}') + ++m_position; + else + { + m_position -= 8; + return false; + } + } + put(this->m_results.prefix()); + return true; + } + if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH)) + { + m_position += 9; + if(have_brace) + { + if(*m_position == '}') + ++m_position; + else + { + m_position -= 9; + return false; + } + } + put(this->m_results.suffix()); + return true; + } + if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH)) + { + m_position += 16; + if(have_brace) + { + if(*m_position == '}') + ++m_position; + else + { + m_position -= 16; + return false; + } + } + put((this->m_results)[this->m_results.size() > 1 ? this->m_results.size() - 1 : 1]); + return true; + } + if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT)) + { + m_position += 20; + if(have_brace) + { + if(*m_position == '}') + ++m_position; + else + { + m_position -= 20; + return false; + } + } + put(this->m_results.get_last_closed_paren()); + return true; + } + if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT)) + { + m_position += 2; + if(have_brace) + { + if(*m_position == '}') + ++m_position; + else + { + m_position -= 2; + return false; + } + } + put(this->m_results.get_last_closed_paren()); + return true; + } + return false; +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::format_escape() +{ + // skip the escape and check for trailing escape: + if(++m_position == m_end) + { + put(static_cast<char_type>('\\')); + return; + } + // now switch on the escape type: + switch(*m_position) + { + case 'a': + put(static_cast<char_type>('\a')); + ++m_position; + break; + case 'f': + put(static_cast<char_type>('\f')); + ++m_position; + break; + case 'n': + put(static_cast<char_type>('\n')); + ++m_position; + break; + case 'r': + put(static_cast<char_type>('\r')); + ++m_position; + break; + case 't': + put(static_cast<char_type>('\t')); + ++m_position; + break; + case 'v': + put(static_cast<char_type>('\v')); + ++m_position; + break; + case 'x': + if(++m_position == m_end) + { + put(static_cast<char_type>('x')); + return; + } + // maybe have \x{ddd} + if(*m_position == static_cast<char_type>('{')) + { + ++m_position; + int val = m_traits.toi(m_position, m_end, 16); + if(val < 0) + { + // invalid value treat everything as literals: + put(static_cast<char_type>('x')); + put(static_cast<char_type>('{')); + return; + } + if(*m_position != static_cast<char_type>('}')) + { + while(*m_position != static_cast<char_type>('\\')) + --m_position; + ++m_position; + put(*m_position++); + return; + } + ++m_position; + put(static_cast<char_type>(val)); + return; + } + else + { + std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end); + len = (std::min)(static_cast<std::ptrdiff_t>(2), len); + int val = m_traits.toi(m_position, m_position + len, 16); + if(val < 0) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast<char_type>(val)); + } + break; + case 'c': + if(++m_position == m_end) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast<char_type>(*m_position++ % 32)); + break; + case 'e': + put(static_cast<char_type>(27)); + ++m_position; + break; + default: + // see if we have a perl specific escape: + if((m_flags & boost::regex_constants::format_sed) == 0) + { + bool breakout = false; + switch(*m_position) + { + case 'l': + ++m_position; + m_restore_state = m_state; + m_state = output_next_lower; + breakout = true; + break; + case 'L': + ++m_position; + m_state = output_lower; + breakout = true; + break; + case 'u': + ++m_position; + m_restore_state = m_state; + m_state = output_next_upper; + breakout = true; + break; + case 'U': + ++m_position; + m_state = output_upper; + breakout = true; + break; + case 'E': + ++m_position; + m_state = output_copy; + breakout = true; + break; + } + if(breakout) + break; + } + // see if we have a \n sed style backreference: + int v = m_traits.toi(m_position, m_position+1, 10); + if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed))) + { + put(m_results[v]); + break; + } + else if(v == 0) + { + // octal ecape sequence: + --m_position; + std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end); + len = (std::min)(static_cast<std::ptrdiff_t>(4), len); + v = m_traits.toi(m_position, m_position + len, 8); + BOOST_ASSERT(v >= 0); + put(static_cast<char_type>(v)); + break; + } + // Otherwise output the character "as is": + put(*m_position++); + break; + } +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::format_conditional() +{ + if(m_position == m_end) + { + // oops trailing '?': + put(static_cast<char_type>('?')); + return; + } + int v; + if(*m_position == '{') + { + const char_type* base = m_position; + ++m_position; + v = m_traits.toi(m_position, m_end, 10); + if(v < 0) + { + // Try a named subexpression: + while((m_position != m_end) && (*m_position != '}')) + ++m_position; + v = m_results.named_subexpression_index(base + 1, m_position); + } + if((v < 0) || (*m_position != '}')) + { + m_position = base; + // oops trailing '?': + put(static_cast<char_type>('?')); + return; + } + // Skip trailing '}': + ++m_position; + } + else + { + std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end); + len = (std::min)(static_cast<std::ptrdiff_t>(2), len); + v = m_traits.toi(m_position, m_position + len, 10); + } + if(v < 0) + { + // oops not a number: + put(static_cast<char_type>('?')); + return; + } + + // output varies depending upon whether sub-expression v matched or not: + if(m_results[v].matched) + { + m_have_conditional = true; + format_all(); + m_have_conditional = false; + if((m_position != m_end) && (*m_position == static_cast<char_type>(':'))) + { + // skip the ':': + ++m_position; + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format the rest of this scope: + format_until_scope_end(); + // restore output state: + m_state = saved_state; + } + } + else + { + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format until ':' or ')': + m_have_conditional = true; + format_all(); + m_have_conditional = false; + // restore state: + m_state = saved_state; + if((m_position != m_end) && (*m_position == static_cast<char_type>(':'))) + { + // skip the ':': + ++m_position; + // format the rest of this scope: + format_until_scope_end(); + } + } +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::format_until_scope_end() +{ + do + { + format_all(); + if((m_position == m_end) || (*m_position == static_cast<char_type>(')'))) + return; + put(*m_position++); + }while(m_position != m_end); +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::put(char_type c) +{ + // write a single character to output + // according to which case translation mode we are in: + switch(this->m_state) + { + case output_none: + return; + case output_next_lower: + c = m_traits.tolower(c); + this->m_state = m_restore_state; + break; + case output_next_upper: + c = m_traits.toupper(c); + this->m_state = m_restore_state; + break; + case output_lower: + c = m_traits.tolower(c); + break; + case output_upper: + c = m_traits.toupper(c); + break; + default: + break; + } + *m_out = c; + ++m_out; +} + +template <class OutputIterator, class Results, class traits> +void basic_regex_formatter<OutputIterator, Results, traits>::put(const sub_match_type& sub) +{ + typedef typename sub_match_type::iterator iterator_type; + iterator_type i = sub.first; + while(i != sub.second) + { + put(*i); + ++i; + } +} + +template <class S> +class string_out_iterator +#ifndef BOOST_NO_STD_ITERATOR + : public std::iterator<std::output_iterator_tag, typename S::value_type> +#endif +{ + S* out; +public: + string_out_iterator(S& s) : out(&s) {} + string_out_iterator& operator++() { return *this; } + string_out_iterator& operator++(int) { return *this; } + string_out_iterator& operator*() { return *this; } + string_out_iterator& operator=(typename S::value_type v) + { + out->append(1, v); + return *this; + } + +#ifdef BOOST_NO_STD_ITERATOR + typedef std::ptrdiff_t difference_type; + typedef typename S::value_type value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::output_iterator_tag iterator_category; +#endif +}; + +template <class OutputIterator, class Iterator, class Alloc, class charT, class traits> +OutputIterator regex_format_imp(OutputIterator out, + const match_results<Iterator, Alloc>& m, + const charT* p1, const charT* p2, + match_flag_type flags, + const traits& t + ) +{ + if(flags & regex_constants::format_literal) + { + return re_detail::copy(p1, p2, out); + } + + re_detail::basic_regex_formatter< + OutputIterator, + match_results<Iterator, Alloc>, + traits > f(out, m, t); + return f.format(p1, p2, flags); +} + + +} // namespace re_detail + +template <class OutputIterator, class Iterator, class charT> +OutputIterator regex_format(OutputIterator out, + const match_results<Iterator>& m, + const charT* fmt, + match_flag_type flags = format_all + ) +{ + re_detail::trivial_format_traits<charT> traits; + return re_detail::regex_format_imp(out, m, fmt, fmt + traits.length(fmt), flags, traits); +} + +template <class OutputIterator, class Iterator, class charT> +OutputIterator regex_format(OutputIterator out, + const match_results<Iterator>& m, + const std::basic_string<charT>& fmt, + match_flag_type flags = format_all + ) +{ + re_detail::trivial_format_traits<charT> traits; + return re_detail::regex_format_imp(out, m, fmt.data(), fmt.data() + fmt.size(), flags, traits); +} + +template <class Iterator, class charT> +std::basic_string<charT> regex_format(const match_results<Iterator>& m, + const charT* fmt, + match_flag_type flags = format_all) +{ + std::basic_string<charT> result; + re_detail::string_out_iterator<std::basic_string<charT> > i(result); + re_detail::trivial_format_traits<charT> traits; + re_detail::regex_format_imp(i, m, fmt, fmt + traits.length(fmt), flags, traits); + return result; +} + +template <class Iterator, class charT> +std::basic_string<charT> regex_format(const match_results<Iterator>& m, + const std::basic_string<charT>& fmt, + match_flag_type flags = format_all) +{ + std::basic_string<charT> result; + re_detail::string_out_iterator<std::basic_string<charT> > i(result); + re_detail::trivial_format_traits<charT> traits; + re_detail::regex_format_imp(i, m, fmt.data(), fmt.data() + fmt.size(), flags, traits); + return result; +} + +#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 // BOOST_REGEX_FORMAT_HPP + + + + + + diff --git a/ext/boost/regex/v4/regex_fwd.hpp b/ext/boost/regex/v4/regex_fwd.hpp new file mode 100644 index 0000000000..3076b069ac --- /dev/null +++ b/ext/boost/regex/v4/regex_fwd.hpp @@ -0,0 +1,73 @@ +/* + * + * 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 regex_fwd.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Forward declares boost::basic_regex<> and + * associated typedefs. + */ + +#ifndef BOOST_REGEX_FWD_HPP_INCLUDED +#define BOOST_REGEX_FWD_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif + +// +// define BOOST_REGEX_NO_FWD if this +// header doesn't work! +// +#ifdef BOOST_REGEX_NO_FWD +# ifndef BOOST_RE_REGEX_HPP +# include <boost/regex.hpp> +# endif +#else + +namespace boost{ + +template <class charT> +class cpp_regex_traits; +template <class charT> +struct c_regex_traits; +template <class charT> +class w32_regex_traits; + +#ifdef BOOST_REGEX_USE_WIN32_LOCALE +template <class charT, class implementationT = w32_regex_traits<charT> > +struct regex_traits; +#elif defined(BOOST_REGEX_USE_CPP_LOCALE) +template <class charT, class implementationT = cpp_regex_traits<charT> > +struct regex_traits; +#else +template <class charT, class implementationT = c_regex_traits<charT> > +struct regex_traits; +#endif + +template <class charT, class traits = regex_traits<charT> > +class basic_regex; + +typedef basic_regex<char, regex_traits<char> > regex; +#ifndef BOOST_NO_WREGEX +typedef basic_regex<wchar_t, regex_traits<wchar_t> > wregex; +#endif + +} // namespace boost + +#endif // BOOST_REGEX_NO_FWD + +#endif + + + + diff --git a/ext/boost/regex/v4/regex_grep.hpp b/ext/boost/regex/v4/regex_grep.hpp new file mode 100644 index 0000000000..3a3d906ecb --- /dev/null +++ b/ext/boost/regex/v4/regex_grep.hpp @@ -0,0 +1,155 @@ +/* + * + * 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 regex_grep.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides regex_grep implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_GREP_HPP +#define BOOST_REGEX_V4_REGEX_GREP_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 + +// +// regex_grep: +// find all non-overlapping matches within the sequence first last: +// +template <class Predicate, class BidiIterator, class charT, class traits> +inline unsigned int regex_grep(Predicate foo, + BidiIterator first, + BidiIterator last, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + if(e.flags() & regex_constants::failbit) + return false; + + typedef typename match_results<BidiIterator>::allocator_type match_allocator_type; + + match_results<BidiIterator> m; + re_detail::perl_matcher<BidiIterator, match_allocator_type, traits> matcher(first, last, m, e, flags, first); + unsigned int count = 0; + while(matcher.find()) + { + ++count; + if(0 == foo(m)) + return count; // caller doesn't want to go on + if(m[0].second == last) + return count; // we've reached the end, don't try and find an extra null match. + if(m.length() == 0) + { + if(m[0].second == last) + return count; + // we found a NULL-match, now try to find + // a non-NULL one at the same position: + match_results<BidiIterator, match_allocator_type> m2(m); + matcher.setf(match_not_null | match_continuous); + if(matcher.find()) + { + ++count; + if(0 == foo(m)) + return count; + } + else + { + // reset match back to where it was: + m = m2; + } + matcher.unsetf((match_not_null | match_continuous) & ~flags); + } + } + return count; +} + +// +// regex_grep convenience interfaces: +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template <class Predicate, class charT, class traits> +inline unsigned int regex_grep(Predicate foo, const charT* str, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + traits::length(str), e, flags); +} + +template <class Predicate, class ST, class SA, class charT, class traits> +inline unsigned int regex_grep(Predicate foo, const std::basic_string<charT, ST, SA>& s, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} +#else // partial specialisation +inline unsigned int regex_grep(bool (*foo)(const cmatch&), const char* str, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + regex::traits_type::length(str), e, flags); +} +#ifndef BOOST_NO_WREGEX +inline unsigned int regex_grep(bool (*foo)(const wcmatch&), const wchar_t* str, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + wregex::traits_type::length(str), e, flags); +} +#endif +inline unsigned int regex_grep(bool (*foo)(const match_results<std::string::const_iterator>&), const std::string& s, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} +#if !defined(BOOST_NO_WREGEX) +inline unsigned int regex_grep(bool (*foo)(const match_results<std::basic_string<wchar_t>::const_iterator>&), + const std::basic_string<wchar_t>& s, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} +#endif +#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 // BOOST_REGEX_V4_REGEX_GREP_HPP + diff --git a/ext/boost/regex/v4/regex_iterator.hpp b/ext/boost/regex/v4/regex_iterator.hpp new file mode 100644 index 0000000000..c2f2c49f2e --- /dev/null +++ b/ext/boost/regex/v4/regex_iterator.hpp @@ -0,0 +1,201 @@ +/* + * + * Copyright (c) 2003 + * 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 regex_iterator.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides regex_iterator implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_ITERATOR_HPP +#define BOOST_REGEX_V4_REGEX_ITERATOR_HPP + +#include <boost/shared_ptr.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 + +template <class BidirectionalIterator, + class charT, + class traits> +class regex_iterator_implementation +{ + typedef basic_regex<charT, traits> regex_type; + + match_results<BidirectionalIterator> what; // current match + BidirectionalIterator base; // start of sequence + BidirectionalIterator end; // end of sequence + const regex_type re; // the expression + match_flag_type flags; // flags for matching + +public: + regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f) + : base(), end(last), re(*p), flags(f){} + bool init(BidirectionalIterator first) + { + base = first; + return regex_search(first, end, what, re, flags); + } + bool compare(const regex_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); + } + const match_results<BidirectionalIterator>& get() + { return what; } + bool next() + { + //if(what.prefix().first != what[0].second) + // flags |= match_prev_avail; + BidirectionalIterator next_start = what[0].second; + match_flag_type f(flags); + if(!what.length()) + f |= regex_constants::match_not_initial_null; + //if(base != next_start) + // f |= regex_constants::match_not_bob; + bool result = regex_search(next_start, end, what, re, f, base); + if(result) + what.set_base(base); + return result; + } +private: + regex_iterator_implementation& operator=(const regex_iterator_implementation&); +}; + +template <class BidirectionalIterator, + class charT = BOOST_DEDUCED_TYPENAME re_detail::regex_iterator_traits<BidirectionalIterator>::value_type, + class traits = regex_traits<charT> > +class regex_iterator +#ifndef BOOST_NO_STD_ITERATOR + : public std::iterator< + std::forward_iterator_tag, + match_results<BidirectionalIterator>, + typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type, + const match_results<BidirectionalIterator>*, + const match_results<BidirectionalIterator>& > +#endif +{ +private: + typedef regex_iterator_implementation<BidirectionalIterator, charT, traits> impl; + typedef shared_ptr<impl> pimpl; +public: + typedef basic_regex<charT, traits> regex_type; + typedef match_results<BidirectionalIterator> value_type; + typedef typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + regex_iterator(){} + regex_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + match_flag_type m = match_default) + : pdata(new impl(&re, b, m)) + { + if(!pdata->init(a)) + { + pdata.reset(); + } + } + regex_iterator(const regex_iterator& that) + : pdata(that.pdata) {} + regex_iterator& operator=(const regex_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const regex_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const regex_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + regex_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + regex_iterator operator++(int) + { + regex_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && !pdata.unique()) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef regex_iterator<const char*> cregex_iterator; +typedef regex_iterator<std::string::const_iterator> sregex_iterator; +#ifndef BOOST_NO_WREGEX +typedef regex_iterator<const wchar_t*> wcregex_iterator; +typedef regex_iterator<std::wstring::const_iterator> wsregex_iterator; +#endif + +// make_regex_iterator: +template <class charT, class traits> +inline regex_iterator<const charT*, charT, traits> make_regex_iterator(const charT* p, const basic_regex<charT, traits>& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, m); +} +template <class charT, class traits, class ST, class SA> +inline regex_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, m); +} + +#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 // BOOST_REGEX_V4_REGEX_ITERATOR_HPP + diff --git a/ext/boost/regex/v4/regex_match.hpp b/ext/boost/regex/v4/regex_match.hpp new file mode 100644 index 0000000000..e947a15225 --- /dev/null +++ b/ext/boost/regex/v4/regex_match.hpp @@ -0,0 +1,382 @@ +/* + * + * 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 regex_match.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Regular expression matching algorithms. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + + +#ifndef BOOST_REGEX_MATCH_HPP +#define BOOST_REGEX_MATCH_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 + +// +// proc regex_match +// returns true if the specified regular expression matches +// the whole of the input. Fills in what matched in m. +// +template <class BidiIterator, class Allocator, class charT, class traits> +bool regex_match(BidiIterator first, BidiIterator last, + match_results<BidiIterator, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + re_detail::perl_matcher<BidiIterator, Allocator, traits> matcher(first, last, m, e, flags, first); + return matcher.match(); +} +template <class iterator, class charT, class traits> +bool regex_match(iterator first, iterator last, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + match_results<iterator> m; + return regex_match(first, last, m, e, flags | regex_constants::match_any); +} +// +// query_match convenience interfaces: +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template <class charT, class Allocator, class traits> +inline bool regex_match(const charT* str, + match_results<const charT*, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + traits::length(str), m, e, flags); +} + +template <class ST, class SA, class Allocator, class charT, class traits> +inline bool regex_match(const std::basic_string<charT, ST, SA>& s, + match_results<typename std::basic_string<charT, ST, SA>::const_iterator, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +template <class charT, class traits> +inline bool regex_match(const charT* str, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + match_results<const charT*> m; + return regex_match(str, str + traits::length(str), m, e, flags | regex_constants::match_any); +} + +template <class ST, class SA, class charT, class traits> +inline bool regex_match(const std::basic_string<charT, ST, SA>& s, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + typedef typename std::basic_string<charT, ST, SA>::const_iterator iterator; + match_results<iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#else // partial ordering +inline bool regex_match(const char* str, + cmatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const regex& e, + match_flag_type flags = match_default) +{ + match_results<const char*> m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex<char, cpp_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex<char, cpp_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + match_results<const char*> m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex<char, c_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex<char, c_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + match_results<const char*> m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex<char, w32_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex<char, w32_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + match_results<const char*> m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +#ifndef BOOST_NO_WREGEX +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const wregex& e, + match_flag_type flags = match_default) +{ + match_results<const wchar_t*> m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex<wchar_t, cpp_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex<wchar_t, cpp_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + match_results<const wchar_t*> m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex<wchar_t, c_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex<wchar_t, c_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + match_results<const wchar_t*> m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex<wchar_t, w32_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex<wchar_t, w32_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + match_results<const wchar_t*> m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +#endif +inline bool regex_match(const std::string& s, + smatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const regex& e, + match_flag_type flags = match_default) +{ + match_results<std::string::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex<char, cpp_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex<char, cpp_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + match_results<std::string::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex<char, c_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex<char, c_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + match_results<std::string::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex<char, w32_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex<char, w32_regex_traits<char> >& e, + match_flag_type flags = match_default) +{ + match_results<std::string::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +#if !defined(BOOST_NO_WREGEX) +inline bool regex_match(const std::basic_string<wchar_t>& s, + match_results<std::basic_string<wchar_t>::const_iterator>& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string<wchar_t>& s, + const wregex& e, + match_flag_type flags = match_default) +{ + match_results<std::basic_string<wchar_t>::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const std::basic_string<wchar_t>& s, + match_results<std::basic_string<wchar_t>::const_iterator>& m, + const basic_regex<wchar_t, cpp_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string<wchar_t>& s, + const basic_regex<wchar_t, cpp_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + match_results<std::basic_string<wchar_t>::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const std::basic_string<wchar_t>& s, + match_results<std::basic_string<wchar_t>::const_iterator>& m, + const basic_regex<wchar_t, c_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string<wchar_t>& s, + const basic_regex<wchar_t, c_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + match_results<std::basic_string<wchar_t>::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const std::basic_string<wchar_t>& s, + match_results<std::basic_string<wchar_t>::const_iterator>& m, + const basic_regex<wchar_t, w32_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string<wchar_t>& s, + const basic_regex<wchar_t, w32_regex_traits<wchar_t> >& e, + match_flag_type flags = match_default) +{ + match_results<std::basic_string<wchar_t>::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +#endif + +#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 // BOOST_REGEX_MATCH_HPP + + + + + + + + + + + + + + + + + + diff --git a/ext/boost/regex/v4/regex_merge.hpp b/ext/boost/regex/v4/regex_merge.hpp new file mode 100644 index 0000000000..404ca77501 --- /dev/null +++ b/ext/boost/regex/v4/regex_merge.hpp @@ -0,0 +1,93 @@ +/* + * + * 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 regex_format.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_V4_REGEX_MERGE_HPP +#define BOOST_REGEX_V4_REGEX_MERGE_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 + +template <class OutputIterator, class Iterator, class traits, class charT> +inline OutputIterator regex_merge(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex<charT, traits>& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + return regex_replace(out, first, last, e, fmt, flags); +} + +template <class OutputIterator, class Iterator, class traits, class charT> +inline OutputIterator regex_merge(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex<charT, traits>& e, + const std::basic_string<charT>& fmt, + match_flag_type flags = match_default) +{ + return regex_merge(out, first, last, e, fmt.c_str(), flags); +} + +template <class traits, class charT> +inline std::basic_string<charT> regex_merge(const std::basic_string<charT>& s, + const basic_regex<charT, traits>& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + return regex_replace(s, e, fmt, flags); +} + +template <class traits, class charT> +inline std::basic_string<charT> regex_merge(const std::basic_string<charT>& s, + const basic_regex<charT, traits>& e, + const std::basic_string<charT>& fmt, + match_flag_type flags = match_default) +{ + return regex_replace(s, e, fmt, flags); +} + +#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 // BOOST_REGEX_V4_REGEX_MERGE_HPP + + diff --git a/ext/boost/regex/v4/regex_raw_buffer.hpp b/ext/boost/regex/v4/regex_raw_buffer.hpp new file mode 100644 index 0000000000..52d45a250b --- /dev/null +++ b/ext/boost/regex/v4/regex_raw_buffer.hpp @@ -0,0 +1,210 @@ +/* + * + * 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 regex_raw_buffer.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Raw character buffer for regex code. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#define BOOST_REGEX_RAW_BUFFER_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif + +#include <algorithm> +#include <cstddef> + +namespace boost{ + namespace re_detail{ + +#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 + +struct empty_padding{}; + +union padding +{ + void* p; + unsigned int i; +}; + +template <int N> +struct padding3 +{ + enum{ + padding_size = 8, + padding_mask = 7 + }; +}; + +template<> +struct padding3<2> +{ + enum{ + padding_size = 2, + padding_mask = 1 + }; +}; + +template<> +struct padding3<4> +{ + enum{ + padding_size = 4, + padding_mask = 3 + }; +}; + +template<> +struct padding3<8> +{ + enum{ + padding_size = 8, + padding_mask = 7 + }; +}; + +template<> +struct padding3<16> +{ + enum{ + padding_size = 16, + padding_mask = 15 + }; +}; + +enum{ + padding_size = padding3<sizeof(padding)>::padding_size, + padding_mask = padding3<sizeof(padding)>::padding_mask +}; + +// +// class raw_storage +// basically this is a simplified vector<unsigned char> +// this is used by basic_regex for expression storage +// + +class BOOST_REGEX_DECL raw_storage +{ +public: + typedef std::size_t size_type; + typedef unsigned char* pointer; +private: + pointer last, start, end; +public: + + raw_storage(); + raw_storage(size_type n); + + ~raw_storage() + { + ::operator delete(start); + } + + void BOOST_REGEX_CALL resize(size_type n); + + void* BOOST_REGEX_CALL extend(size_type n) + { + if(size_type(last - end) < n) + resize(n + (end - start)); + register pointer result = end; + end += n; + return result; + } + + void* BOOST_REGEX_CALL insert(size_type pos, size_type n); + + size_type BOOST_REGEX_CALL size() + { + return end - start; + } + + size_type BOOST_REGEX_CALL capacity() + { + return last - start; + } + + void* BOOST_REGEX_CALL data()const + { + return start; + } + + size_type BOOST_REGEX_CALL index(void* ptr) + { + return static_cast<pointer>(ptr) - static_cast<pointer>(data()); + } + + void BOOST_REGEX_CALL clear() + { + end = start; + } + + void BOOST_REGEX_CALL align() + { + // move end up to a boundary: + end = start + (((end - start) + padding_mask) & ~padding_mask); + } + void swap(raw_storage& that) + { + std::swap(start, that.start); + std::swap(end, that.end); + std::swap(last, that.last); + } +}; + +inline raw_storage::raw_storage() +{ + last = start = end = 0; +} + +inline raw_storage::raw_storage(size_type n) +{ + start = end = static_cast<pointer>(::operator new(n)); + BOOST_REGEX_NOEH_ASSERT(start) + last = start + n; +} + + +#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 re_detail +} // namespace boost + +#endif + + + + + + diff --git a/ext/boost/regex/v4/regex_replace.hpp b/ext/boost/regex/v4/regex_replace.hpp new file mode 100644 index 0000000000..c4544c05b9 --- /dev/null +++ b/ext/boost/regex/v4/regex_replace.hpp @@ -0,0 +1,122 @@ +/* + * + * 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 regex_format.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_V4_REGEX_REPLACE_HPP +#define BOOST_REGEX_V4_REGEX_REPLACE_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 + +template <class OutputIterator, class BidirectionalIterator, class traits, class charT> +OutputIterator regex_replace(OutputIterator out, + BidirectionalIterator first, + BidirectionalIterator last, + const basic_regex<charT, traits>& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + regex_iterator<BidirectionalIterator, charT, traits> i(first, last, e, flags); + regex_iterator<BidirectionalIterator, charT, traits> j; + if(i == j) + { + if(!(flags & regex_constants::format_no_copy)) + out = re_detail::copy(first, last, out); + } + else + { + BidirectionalIterator last_m(first); + while(i != j) + { + if(!(flags & regex_constants::format_no_copy)) + out = re_detail::copy(i->prefix().first, i->prefix().second, out); + out = i->format(out, fmt, flags, e); + last_m = (*i)[0].second; + if(flags & regex_constants::format_first_only) + break; + ++i; + } + if(!(flags & regex_constants::format_no_copy)) + out = re_detail::copy(last_m, last, out); + } + return out; +} + +template <class OutputIterator, class Iterator, class traits, class charT> +inline OutputIterator regex_replace(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex<charT, traits>& e, + const std::basic_string<charT>& fmt, + match_flag_type flags = match_default) +{ + return regex_replace(out, first, last, e, fmt.c_str(), flags); +} + +template <class traits, class charT> +std::basic_string<charT> regex_replace(const std::basic_string<charT>& s, + const basic_regex<charT, traits>& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + std::basic_string<charT> result; + re_detail::string_out_iterator<std::basic_string<charT> > i(result); + regex_replace(i, s.begin(), s.end(), e, fmt, flags); + return result; +} + +template <class traits, class charT> +std::basic_string<charT> regex_replace(const std::basic_string<charT>& s, + const basic_regex<charT, traits>& e, + const std::basic_string<charT>& fmt, + match_flag_type flags = match_default) +{ + std::basic_string<charT> result; + re_detail::string_out_iterator<std::basic_string<charT> > i(result); + regex_replace(i, s.begin(), s.end(), e, fmt.c_str(), flags); + return result; +} + +#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 // BOOST_REGEX_V4_REGEX_REPLACE_HPP + + diff --git a/ext/boost/regex/v4/regex_search.hpp b/ext/boost/regex/v4/regex_search.hpp new file mode 100644 index 0000000000..cf5579d2c7 --- /dev/null +++ b/ext/boost/regex/v4/regex_search.hpp @@ -0,0 +1,217 @@ +/* + * + * 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 regex_search.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides regex_search implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_SEARCH_HPP +#define BOOST_REGEX_V4_REGEX_SEARCH_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 + +template <class BidiIterator, class Allocator, class charT, class traits> +bool regex_search(BidiIterator first, BidiIterator last, + match_results<BidiIterator, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_search(first, last, m, e, flags, first); +} + +template <class BidiIterator, class Allocator, class charT, class traits> +bool regex_search(BidiIterator first, BidiIterator last, + match_results<BidiIterator, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags, + BidiIterator base) +{ + if(e.flags() & regex_constants::failbit) + return false; + + re_detail::perl_matcher<BidiIterator, Allocator, traits> matcher(first, last, m, e, flags, base); + return matcher.find(); +} + +// +// regex_search convenience interfaces: +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template <class charT, class Allocator, class traits> +inline bool regex_search(const charT* str, + match_results<const charT*, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + traits::length(str), m, e, flags); +} + +template <class ST, class SA, class Allocator, class charT, class traits> +inline bool regex_search(const std::basic_string<charT, ST, SA>& s, + match_results<typename std::basic_string<charT, ST, SA>::const_iterator, Allocator>& m, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} +#else // partial overloads: +inline bool regex_search(const char* str, + cmatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_search(const char* first, const char* last, + const regex& e, + match_flag_type flags = match_default) +{ + cmatch m; + return regex_search(first, last, m, e, flags | regex_constants::match_any); +} + +#ifndef BOOST_NO_WREGEX +inline bool regex_search(const wchar_t* str, + wcmatch& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_search(const wchar_t* first, const wchar_t* last, + const wregex& e, + match_flag_type flags = match_default) +{ + wcmatch m; + return regex_search(first, last, m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_search(const std::string& s, + smatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} +#if !defined(BOOST_NO_WREGEX) +inline bool regex_search(const std::basic_string<wchar_t>& s, + wsmatch& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} +#endif + +#endif + +template <class BidiIterator, class charT, class traits> +bool regex_search(BidiIterator first, BidiIterator last, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + if(e.flags() & regex_constants::failbit) + return false; + + match_results<BidiIterator> m; + typedef typename match_results<BidiIterator>::allocator_type match_alloc_type; + re_detail::perl_matcher<BidiIterator, match_alloc_type, traits> matcher(first, last, m, e, flags | regex_constants::match_any, first); + return matcher.find(); +} + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +template <class charT, class traits> +inline bool regex_search(const charT* str, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + traits::length(str), e, flags); +} + +template <class ST, class SA, class charT, class traits> +inline bool regex_search(const std::basic_string<charT, ST, SA>& s, + const basic_regex<charT, traits>& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), e, flags); +} +#else // non-template function overloads +inline bool regex_search(const char* str, + const regex& e, + match_flag_type flags = match_default) +{ + cmatch m; + return regex_search(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_WREGEX +inline bool regex_search(const wchar_t* str, + const wregex& e, + match_flag_type flags = match_default) +{ + wcmatch m; + return regex_search(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_search(const std::string& s, + const regex& e, + match_flag_type flags = match_default) +{ + smatch m; + return regex_search(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#if !defined(BOOST_NO_WREGEX) +inline bool regex_search(const std::basic_string<wchar_t>& s, + const wregex& e, + match_flag_type flags = match_default) +{ + wsmatch m; + return regex_search(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} + +#endif // BOOST_NO_WREGEX + +#endif // partial overload + +#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 // BOOST_REGEX_V4_REGEX_SEARCH_HPP + + diff --git a/ext/boost/regex/v4/regex_split.hpp b/ext/boost/regex/v4/regex_split.hpp new file mode 100644 index 0000000000..a7ae350f4a --- /dev/null +++ b/ext/boost/regex/v4/regex_split.hpp @@ -0,0 +1,172 @@ +/* + * + * 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 regex_split.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Implements regex_split and associated functions. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_SPLIT_HPP +#define BOOST_REGEX_SPLIT_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: 4800) +#endif + +namespace re_detail{ + +template <class charT> +const basic_regex<charT>& get_default_expression(charT) +{ + static const charT expression_text[4] = { '\\', 's', '+', '\00', }; + static const basic_regex<charT> e(expression_text); + return e; +} + +template <class OutputIterator, class charT, class Traits1, class Alloc1> +class split_pred +{ + typedef std::basic_string<charT, Traits1, Alloc1> string_type; + typedef typename string_type::const_iterator iterator_type; + iterator_type* p_last; + OutputIterator* p_out; + std::size_t* p_max; + std::size_t initial_max; +public: + split_pred(iterator_type* a, OutputIterator* b, std::size_t* c) + : p_last(a), p_out(b), p_max(c), initial_max(*c) {} + + bool operator()(const match_results<iterator_type>& what); +}; + +template <class OutputIterator, class charT, class Traits1, class Alloc1> +bool split_pred<OutputIterator, charT, Traits1, Alloc1>::operator() + (const match_results<iterator_type>& what) +{ + *p_last = what[0].second; + if(what.size() > 1) + { + // output sub-expressions only: + for(unsigned i = 1; i < what.size(); ++i) + { + *(*p_out) = what.str(i); + ++(*p_out); + if(0 == --*p_max) return false; + } + return *p_max != 0; + } + else + { + // output $` only if it's not-null or not at the start of the input: + const sub_match<iterator_type>& sub = what[-1]; + if((sub.first != sub.second) || (*p_max != initial_max)) + { + *(*p_out) = sub.str(); + ++(*p_out); + return --*p_max; + } + } + // + // initial null, do nothing: + return true; +} + +} // namespace re_detail + +template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2> +std::size_t regex_split(OutputIterator out, + std::basic_string<charT, Traits1, Alloc1>& s, + const basic_regex<charT, Traits2>& e, + match_flag_type flags, + std::size_t max_split) +{ + typedef typename std::basic_string<charT, Traits1, Alloc1>::const_iterator ci_t; + typedef typename match_results<ci_t>::allocator_type match_allocator; + ci_t last = s.begin(); + std::size_t init_size = max_split; + re_detail::split_pred<OutputIterator, charT, Traits1, Alloc1> pred(&last, &out, &max_split); + ci_t i, j; + i = s.begin(); + j = s.end(); + regex_grep(pred, i, j, e, flags); + // + // if there is still input left, do a final push as long as max_split + // is not exhausted, and we're not splitting sub-expressions rather + // than whitespace: + if(max_split && (last != s.end()) && (e.mark_count() == 1)) + { + *out = std::basic_string<charT, Traits1, Alloc1>((ci_t)last, (ci_t)s.end()); + ++out; + last = s.end(); + --max_split; + } + // + // delete from the string everything that has been processed so far: + s.erase(0, last - s.begin()); + // + // return the number of new records pushed: + return init_size - max_split; +} + +template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2> +inline std::size_t regex_split(OutputIterator out, + std::basic_string<charT, Traits1, Alloc1>& s, + const basic_regex<charT, Traits2>& e, + match_flag_type flags = match_default) +{ + return regex_split(out, s, e, flags, UINT_MAX); +} + +template <class OutputIterator, class charT, class Traits1, class Alloc1> +inline std::size_t regex_split(OutputIterator out, + std::basic_string<charT, Traits1, Alloc1>& s) +{ + return regex_split(out, s, re_detail::get_default_expression(charT(0)), match_default, UINT_MAX); +} + +#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 + + diff --git a/ext/boost/regex/v4/regex_token_iterator.hpp b/ext/boost/regex/v4/regex_token_iterator.hpp new file mode 100644 index 0000000000..4e8bc36fef --- /dev/null +++ b/ext/boost/regex/v4/regex_token_iterator.hpp @@ -0,0 +1,342 @@ +/* + * + * Copyright (c) 2003 + * 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 regex_token_iterator.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides regex_token_iterator implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP +#define BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP + +#include <boost/shared_ptr.hpp> +#include <boost/detail/workaround.hpp> +#if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +// +// Borland C++ Builder 6, and Visual C++ 6, +// can't cope with the array template constructor +// so we have a template member that will accept any type as +// argument, and then assert that is really is an array: +// +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_array.hpp> +#endif + +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 +#if BOOST_WORKAROUND(BOOST_MSVC, > 1300) +# pragma warning(push) +# pragma warning(disable:4700) +#endif + +template <class BidirectionalIterator, + class charT, + class traits> +class regex_token_iterator_implementation +{ + typedef basic_regex<charT, traits> regex_type; + typedef sub_match<BidirectionalIterator> value_type; + + match_results<BidirectionalIterator> what; // current match + BidirectionalIterator base; // start of search area + BidirectionalIterator end; // end of search area + const regex_type re; // the expression + match_flag_type flags; // match flags + value_type result; // the current string result + int N; // the current sub-expression being enumerated + std::vector<int> subs; // the sub-expressions to enumerate + +public: + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) + : end(last), re(*p), flags(f){ subs.push_back(sub); } + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector<int>& v, match_flag_type f) + : end(last), re(*p), flags(f), subs(v){} +#if !BOOST_WORKAROUND(__HP_aCC, < 60700) +#if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ + || BOOST_WORKAROUND(__HP_aCC, < 60700) + template <class T> + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const T& submatches, match_flag_type f) + : end(last), re(*p), flags(f) + { + // assert that T really is an array: + BOOST_STATIC_ASSERT(::boost::is_array<T>::value); + const std::size_t array_size = sizeof(T) / sizeof(submatches[0]); + for(std::size_t i = 0; i < array_size; ++i) + { + subs.push_back(submatches[i]); + } + } +#else + template <std::size_t CN> + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) + : end(last), re(*p), flags(f) + { + for(std::size_t i = 0; i < CN; ++i) + { + subs.push_back(submatches[i]); + } + } +#endif +#endif + bool init(BidirectionalIterator first) + { + N = 0; + base = first; + if(regex_search(first, end, what, re, flags, base) == true) + { + N = 0; + result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]); + return true; + } + else if((subs[N] == -1) && (first != end)) + { + result.first = first; + result.second = end; + result.matched = (first != end); + N = -1; + return true; + } + return false; + } + bool compare(const regex_token_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) + && (end == that.end) + && (flags == that.flags) + && (N == that.N) + && (what[0].first == that.what[0].first) + && (what[0].second == that.what[0].second); + } + const value_type& get() + { return result; } + bool next() + { + if(N == -1) + return false; + if(N+1 < (int)subs.size()) + { + ++N; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + //if(what.prefix().first != what[0].second) + // flags |= /*match_prev_avail |*/ regex_constants::match_not_bob; + BidirectionalIterator last_end(what[0].second); + if(regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags), base)) + { + N =0; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + else if((last_end != end) && (subs[0] == -1)) + { + N =-1; + result.first = last_end; + result.second = end; + result.matched = (last_end != end); + return true; + } + return false; + } +private: + regex_token_iterator_implementation& operator=(const regex_token_iterator_implementation&); +}; + +template <class BidirectionalIterator, + class charT = BOOST_DEDUCED_TYPENAME re_detail::regex_iterator_traits<BidirectionalIterator>::value_type, + class traits = regex_traits<charT> > +class regex_token_iterator +#ifndef BOOST_NO_STD_ITERATOR + : public std::iterator< + std::forward_iterator_tag, + sub_match<BidirectionalIterator>, + typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type, + const sub_match<BidirectionalIterator>*, + const sub_match<BidirectionalIterator>& > +#endif +{ +private: + typedef regex_token_iterator_implementation<BidirectionalIterator, charT, traits> impl; + typedef shared_ptr<impl> pimpl; +public: + typedef basic_regex<charT, traits> regex_type; + typedef sub_match<BidirectionalIterator> value_type; + typedef typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + regex_token_iterator(){} + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + int submatch = 0, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatch, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const std::vector<int>& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#if !BOOST_WORKAROUND(__HP_aCC, < 60700) +#if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ + || BOOST_WORKAROUND(__HP_aCC, < 60700) + template <class T> + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const T& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#else + template <std::size_t N> + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const int (&submatches)[N], match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#endif +#endif + regex_token_iterator(const regex_token_iterator& that) + : pdata(that.pdata) {} + regex_token_iterator& operator=(const regex_token_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const regex_token_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const regex_token_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + regex_token_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + regex_token_iterator operator++(int) + { + regex_token_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && !pdata.unique()) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef regex_token_iterator<const char*> cregex_token_iterator; +typedef regex_token_iterator<std::string::const_iterator> sregex_token_iterator; +#ifndef BOOST_NO_WREGEX +typedef regex_token_iterator<const wchar_t*> wcregex_token_iterator; +typedef regex_token_iterator<std::wstring::const_iterator> wsregex_token_iterator; +#endif + +template <class charT, class traits> +inline regex_token_iterator<const charT*, charT, traits> make_regex_token_iterator(const charT* p, const basic_regex<charT, traits>& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, submatch, m); +} +template <class charT, class traits, class ST, class SA> +inline regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +template <class charT, class traits, std::size_t N> +inline regex_token_iterator<const charT*, charT, traits> make_regex_token_iterator(const charT* p, const basic_regex<charT, traits>& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, submatch, m); +} +template <class charT, class traits, class ST, class SA, std::size_t N> +inline regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} +#endif +template <class charT, class traits> +inline regex_token_iterator<const charT*, charT, traits> make_regex_token_iterator(const charT* p, const basic_regex<charT, traits>& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, submatch, m); +} +template <class charT, class traits, class ST, class SA> +inline regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} + +#if BOOST_WORKAROUND(BOOST_MSVC, > 1300) +# 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 // BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP + + + + diff --git a/ext/boost/regex/v4/regex_traits.hpp b/ext/boost/regex/v4/regex_traits.hpp new file mode 100644 index 0000000000..f5f0402cab --- /dev/null +++ b/ext/boost/regex/v4/regex_traits.hpp @@ -0,0 +1,189 @@ +/* + * + * Copyright (c) 2003 + * 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 regex_traits.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression traits classes. + */ + +#ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include <boost/regex/config.hpp> +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include <boost/regex/v4/regex_workaround.hpp> +#endif +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#include <boost/regex/v4/syntax_type.hpp> +#endif +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#include <boost/regex/v4/error_type.hpp> +#endif +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include <boost/regex/v4/regex_traits_defaults.hpp> +#endif +#ifndef BOOST_NO_STD_LOCALE +# ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +# include <boost/regex/v4/cpp_regex_traits.hpp> +# endif +#endif +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x560) +# ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +# include <boost/regex/v4/c_regex_traits.hpp> +# endif +#endif +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +# ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +# include <boost/regex/v4/w32_regex_traits.hpp> +# endif +#endif +#ifndef BOOST_REGEX_FWD_HPP_INCLUDED +#include <boost/regex_fwd.hpp> +#endif + +#include "boost/mpl/has_xxx.hpp" +#include <boost/static_assert.hpp> + +#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 + +namespace boost{ + +template <class charT, class implementationT > +struct regex_traits : public implementationT +{ + regex_traits() : implementationT() {} +}; + +// +// class regex_traits_wrapper. +// this is what our implementation will actually store; +// it provides default implementations of the "optional" +// interfaces that we support, in addition to the +// required "standard" ones: +// +namespace re_detail{ +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !BOOST_WORKAROUND(__HP_aCC, < 60000) +BOOST_MPL_HAS_XXX_TRAIT_DEF(boost_extensions_tag) +#else +template<class T> +struct has_boost_extensions_tag +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; +#endif + +template <class BaseT> +struct default_wrapper : public BaseT +{ + typedef typename BaseT::char_type char_type; + std::string error_string(::boost::regex_constants::error_type e)const + { + return ::boost::re_detail::get_default_error_string(e); + } + ::boost::regex_constants::syntax_type syntax_type(char_type c)const + { + return ((c & 0x7f) == c) ? get_default_syntax_type(static_cast<char>(c)) : ::boost::regex_constants::syntax_char; + } + ::boost::regex_constants::escape_syntax_type escape_syntax_type(char_type c)const + { + return ((c & 0x7f) == c) ? get_default_escape_syntax_type(static_cast<char>(c)) : ::boost::regex_constants::escape_type_identity; + } + int toi(const char_type*& p1, const char_type* p2, int radix)const + { + return ::boost::re_detail::global_toi(p1, p2, radix, *this); + } + char_type translate(char_type c, bool icase)const + { + return (icase ? this->translate_nocase(c) : this->translate(c)); + } + char_type translate(char_type c)const + { + return BaseT::translate(c); + } + char_type tolower(char_type c)const + { + return ::boost::re_detail::global_lower(c); + } + char_type toupper(char_type c)const + { + return ::boost::re_detail::global_upper(c); + } +}; + +template <class BaseT, bool has_extensions> +struct compute_wrapper_base +{ + typedef BaseT type; +}; +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !BOOST_WORKAROUND(__HP_aCC, < 60000) +template <class BaseT> +struct compute_wrapper_base<BaseT, false> +{ + typedef default_wrapper<BaseT> type; +}; +#else +template <> +struct compute_wrapper_base<c_regex_traits<char>, false> +{ + typedef default_wrapper<c_regex_traits<char> > type; +}; +#ifndef BOOST_NO_WREGEX +template <> +struct compute_wrapper_base<c_regex_traits<wchar_t>, false> +{ + typedef default_wrapper<c_regex_traits<wchar_t> > type; +}; +#endif +#endif + +} // namespace re_detail + +template <class BaseT> +struct regex_traits_wrapper + : public ::boost::re_detail::compute_wrapper_base< + BaseT, + ::boost::re_detail::has_boost_extensions_tag<BaseT>::value + >::type +{ + regex_traits_wrapper(){} +private: + regex_traits_wrapper(const regex_traits_wrapper&); + regex_traits_wrapper& operator=(const regex_traits_wrapper&); +}; + +} // namespace boost + +#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 + +#endif // include + diff --git a/ext/boost/regex/v4/regex_traits_defaults.hpp b/ext/boost/regex/v4/regex_traits_defaults.hpp new file mode 100644 index 0000000000..5b2c6bc338 --- /dev/null +++ b/ext/boost/regex/v4/regex_traits_defaults.hpp @@ -0,0 +1,371 @@ +/* + * + * 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 regex_traits_defaults.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares API's for access to regex_traits default properties. + */ + +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#define BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED + +#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 + +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#include <boost/regex/v4/syntax_type.hpp> +#endif +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#include <boost/regex/v4/error_type.hpp> +#endif + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strlen; +} +#endif + +namespace boost{ namespace re_detail{ + + +// +// helpers to suppress warnings: +// +template <class charT> +inline bool is_extended(charT c) +{ return c > 256; } +inline bool is_extended(char) +{ return false; } + + +BOOST_REGEX_DECL const char* BOOST_REGEX_CALL get_default_syntax(regex_constants::syntax_type n); +BOOST_REGEX_DECL const char* BOOST_REGEX_CALL get_default_error_string(regex_constants::error_type n); +BOOST_REGEX_DECL regex_constants::syntax_type BOOST_REGEX_CALL get_default_syntax_type(char c); +BOOST_REGEX_DECL regex_constants::escape_syntax_type BOOST_REGEX_CALL get_default_escape_syntax_type(char c); + +// is charT c a combining character? +BOOST_REGEX_DECL bool BOOST_REGEX_CALL is_combining_implementation(uint_least16_t s); + +template <class charT> +inline bool is_combining(charT c) +{ + return (c <= static_cast<charT>(0)) ? false : ((c >= static_cast<charT>((std::numeric_limits<uint_least16_t>::max)())) ? false : is_combining_implementation(static_cast<unsigned short>(c))); +} +template <> +inline bool is_combining<char>(char) +{ + return false; +} +template <> +inline bool is_combining<signed char>(signed char) +{ + return false; +} +template <> +inline bool is_combining<unsigned char>(unsigned char) +{ + return false; +} +#ifndef __hpux // can't use WCHAR_MAX/MIN in pp-directives +#ifdef _MSC_VER +template<> +inline bool is_combining<wchar_t>(wchar_t c) +{ + return is_combining_implementation(static_cast<unsigned short>(c)); +} +#elif !defined(__DECCXX) && !defined(__osf__) && !defined(__OSF__) && defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if defined(WCHAR_MAX) && (WCHAR_MAX <= USHRT_MAX) +template<> +inline bool is_combining<wchar_t>(wchar_t c) +{ + return is_combining_implementation(static_cast<unsigned short>(c)); +} +#else +template<> +inline bool is_combining<wchar_t>(wchar_t c) +{ + return (c >= (std::numeric_limits<uint_least16_t>::max)()) ? false : is_combining_implementation(static_cast<unsigned short>(c)); +} +#endif +#endif +#endif + +// +// is a charT c a line separator? +// +template <class charT> +inline bool is_separator(charT c) +{ + return BOOST_REGEX_MAKE_BOOL( + (c == static_cast<charT>('\n')) + || (c == static_cast<charT>('\r')) + || (c == static_cast<charT>('\f')) + || (static_cast<boost::uint16_t>(c) == 0x2028u) + || (static_cast<boost::uint16_t>(c) == 0x2029u) + || (static_cast<boost::uint16_t>(c) == 0x85u)); +} +template <> +inline bool is_separator<char>(char c) +{ + return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r') || (c == '\f')); +} + +// +// get a default collating element: +// +BOOST_REGEX_DECL std::string BOOST_REGEX_CALL lookup_default_collate_name(const std::string& name); + +// +// get the state_id of a character clasification, the individual +// traits classes then transform that state_id into a bitmask: +// +template <class charT> +struct character_pointer_range +{ + const charT* p1; + const charT* p2; + + bool operator < (const character_pointer_range& r)const + { + return std::lexicographical_compare(p1, p2, r.p1, r.p2); + } + bool operator == (const character_pointer_range& r)const + { + // Not only do we check that the ranges are of equal size before + // calling std::equal, but there is no other algorithm available: + // not even a non-standard MS one. So forward to unchecked_equal + // in the MS case. + return ((p2 - p1) == (r.p2 - r.p1)) && re_detail::equal(p1, p2, r.p1); + } +}; +template <class charT> +int get_default_class_id(const charT* p1, const charT* p2) +{ + static const charT data[73] = { + 'a', 'l', 'n', 'u', 'm', + 'a', 'l', 'p', 'h', 'a', + 'b', 'l', 'a', 'n', 'k', + 'c', 'n', 't', 'r', 'l', + 'd', 'i', 'g', 'i', 't', + 'g', 'r', 'a', 'p', 'h', + 'l', 'o', 'w', 'e', 'r', + 'p', 'r', 'i', 'n', 't', + 'p', 'u', 'n', 'c', 't', + 's', 'p', 'a', 'c', 'e', + 'u', 'n', 'i', 'c', 'o', 'd', 'e', + 'u', 'p', 'p', 'e', 'r', + 'v', + 'w', 'o', 'r', 'd', + 'x', 'd', 'i', 'g', 'i', 't', + }; + + static const character_pointer_range<charT> ranges[21] = + { + {data+0, data+5,}, // alnum + {data+5, data+10,}, // alpha + {data+10, data+15,}, // blank + {data+15, data+20,}, // cntrl + {data+20, data+21,}, // d + {data+20, data+25,}, // digit + {data+25, data+30,}, // graph + {data+29, data+30,}, // h + {data+30, data+31,}, // l + {data+30, data+35,}, // lower + {data+35, data+40,}, // print + {data+40, data+45,}, // punct + {data+45, data+46,}, // s + {data+45, data+50,}, // space + {data+57, data+58,}, // u + {data+50, data+57,}, // unicode + {data+57, data+62,}, // upper + {data+62, data+63,}, // v + {data+63, data+64,}, // w + {data+63, data+67,}, // word + {data+67, data+73,}, // xdigit + }; + static const character_pointer_range<charT>* ranges_begin = ranges; + static const character_pointer_range<charT>* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0])); + + character_pointer_range<charT> t = { p1, p2, }; + const character_pointer_range<charT>* p = std::lower_bound(ranges_begin, ranges_end, t); + if((p != ranges_end) && (t == *p)) + return static_cast<int>(p - ranges); + return -1; +} + +// +// helper functions: +// +template <class charT> +std::ptrdiff_t global_length(const charT* p) +{ + std::ptrdiff_t n = 0; + while(*p) + { + ++p; + ++n; + } + return n; +} +template<> +inline std::ptrdiff_t global_length<char>(const char* p) +{ + return (std::strlen)(p); +} +#ifndef BOOST_NO_WREGEX +template<> +inline std::ptrdiff_t global_length<wchar_t>(const wchar_t* p) +{ + return (std::wcslen)(p); +} +#endif +template <class charT> +inline charT BOOST_REGEX_CALL global_lower(charT c) +{ + return c; +} +template <class charT> +inline charT BOOST_REGEX_CALL global_upper(charT c) +{ + return c; +} + +BOOST_REGEX_DECL char BOOST_REGEX_CALL do_global_lower(char c); +BOOST_REGEX_DECL char BOOST_REGEX_CALL do_global_upper(char c); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL do_global_lower(wchar_t c); +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL do_global_upper(wchar_t c); +#endif +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL do_global_lower(unsigned short c); +BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL do_global_upper(unsigned short c); +#endif +// +// This sucks: declare template specialisations of global_lower/global_upper +// that just forward to the non-template implementation functions. We do +// this because there is one compiler (Compaq Tru64 C++) that doesn't seem +// to differentiate between templates and non-template overloads.... +// what's more, the primary template, plus all overloads have to be +// defined in the same translation unit (if one is inline they all must be) +// otherwise the "local template instantiation" compiler option can pick +// the wrong instantiation when linking: +// +template<> inline char BOOST_REGEX_CALL global_lower<char>(char c){ return do_global_lower(c); } +template<> inline char BOOST_REGEX_CALL global_upper<char>(char c){ return do_global_upper(c); } +#ifndef BOOST_NO_WREGEX +template<> inline wchar_t BOOST_REGEX_CALL global_lower<wchar_t>(wchar_t c){ return do_global_lower(c); } +template<> inline wchar_t BOOST_REGEX_CALL global_upper<wchar_t>(wchar_t c){ return do_global_upper(c); } +#endif +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +template<> inline unsigned short BOOST_REGEX_CALL global_lower<unsigned short>(unsigned short c){ return do_global_lower(c); } +template<> inline unsigned short BOOST_REGEX_CALL global_upper<unsigned short>(unsigned short c){ return do_global_upper(c); } +#endif + +template <class charT> +int global_value(charT c) +{ + static const charT zero = '0'; + static const charT nine = '9'; + static const charT a = 'a'; + static const charT f = 'f'; + static const charT A = 'A'; + static const charT F = 'F'; + + if(c > f) return -1; + if(c >= a) return 10 + (c - a); + if(c > F) return -1; + if(c >= A) return 10 + (c - A); + if(c > nine) return -1; + if(c >= zero) return c - zero; + return -1; +} +template <class charT, class traits> +int global_toi(const charT*& p1, const charT* p2, int radix, const traits& t) +{ + (void)t; // warning suppression + int next_value = t.value(*p1, radix); + if((p1 == p2) || (next_value < 0) || (next_value >= radix)) + return -1; + int result = 0; + while(p1 != p2) + { + next_value = t.value(*p1, radix); + if((next_value < 0) || (next_value >= radix)) + break; + result *= radix; + result += next_value; + ++p1; + } + return result; +} + +template <class charT> +inline const charT* get_escape_R_string() +{ +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4309) +#endif + static const charT e1[] = { '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', '\x85', '\\', 'x', '{', '2', '0', '2', '8', '}', + '\\', 'x', '{', '2', '0', '2', '9', '}', ']', ')', '\0' }; + static const charT e2[] = { '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', '\x85', ']', ')', '\0' }; + + charT c = static_cast<charT>(0x2029u); + bool b = (static_cast<unsigned>(c) == 0x2029u); + + return (b ? e1 : e2); +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +} + +template <> +inline const char* get_escape_R_string<char>() +{ +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4309) +#endif + static const char e2[] = { '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', '\x85', ']', ')', '\0' }; + return e2; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +} + +} // re_detail +} // boost + +#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 + +#endif diff --git a/ext/boost/regex/v4/regex_workaround.hpp b/ext/boost/regex/v4/regex_workaround.hpp new file mode 100644 index 0000000000..06527f1a1f --- /dev/null +++ b/ext/boost/regex/v4/regex_workaround.hpp @@ -0,0 +1,202 @@ +/* + * + * Copyright (c) 1998-2005 + * 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 regex_workarounds.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares Misc workarounds. + */ + +#ifndef BOOST_REGEX_WORKAROUND_HPP +#define BOOST_REGEX_WORKAROUND_HPP + + +#include <new> +#include <cstring> +#include <cstdlib> +#include <cstddef> +#include <cassert> +#include <cstdio> +#include <climits> +#include <string> +#include <stdexcept> +#include <iterator> +#include <algorithm> +#include <iosfwd> +#include <vector> +#include <map> +#include <boost/limits.hpp> +#include <boost/assert.hpp> +#include <boost/cstdint.hpp> +#include <boost/throw_exception.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/scoped_array.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/mpl/bool_fwd.hpp> +#ifndef BOOST_NO_STD_LOCALE +# include <locale> +#endif + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::sprintf; using ::strcpy; using ::strcat; using ::strlen; +} +#endif + +namespace boost{ namespace re_detail{ +#ifdef BOOST_NO_STD_DISTANCE +template <class T> +std::ptrdiff_t distance(const T& x, const T& y) +{ return y - x; } +#else +using std::distance; +#endif +}} + + +#ifdef BOOST_REGEX_NO_BOOL +# define BOOST_REGEX_MAKE_BOOL(x) static_cast<bool>((x) ? true : false) +#else +# define BOOST_REGEX_MAKE_BOOL(x) static_cast<bool>(x) +#endif + +/***************************************************************************** + * + * Fix broken broken namespace support: + * + ****************************************************************************/ + +#if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus) + +namespace std{ + using ::ptrdiff_t; + using ::size_t; + using ::abs; + using ::memset; + using ::memcpy; +} + +#endif + +/***************************************************************************** + * + * helper functions pointer_construct/pointer_destroy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace re_detail{ + +#ifdef BOOST_MSVC +#pragma warning (push) +#pragma warning (disable : 4100) +#endif + +template <class T> +inline void pointer_destroy(T* p) +{ p->~T(); (void)p; } + +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + +template <class T> +inline void pointer_construct(T* p, const T& t) +{ new (p) T(t); } + +}} // namespaces +#endif + +/***************************************************************************** + * + * helper function copy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace re_detail{ +#if BOOST_WORKAROUND(BOOST_MSVC,>=1400) && BOOST_WORKAROUND(BOOST_MSVC, <1600) && defined(_CPPLIB_VER) && defined(BOOST_DINKUMWARE_STDLIB) && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) + // + // MSVC 8 will either emit warnings or else refuse to compile + // code that makes perfectly legitimate use of std::copy, when + // the OutputIterator type is a user-defined class (apparently all user + // defined iterators are "unsafe"). This code works around that: + // + template<class InputIterator, class OutputIterator> + inline OutputIterator copy( + InputIterator first, + InputIterator last, + OutputIterator dest + ) + { + return stdext::unchecked_copy(first, last, dest); + } + template<class InputIterator1, class InputIterator2> + inline bool equal( + InputIterator1 first, + InputIterator1 last, + InputIterator2 with + ) + { + return stdext::unchecked_equal(first, last, with); + } + +#else + using std::copy; + using std::equal; +#endif +#if BOOST_WORKAROUND(BOOST_MSVC,>=1400) && defined(__STDC_WANT_SECURE_LIB__) && __STDC_WANT_SECURE_LIB__ + + // use safe versions of strcpy etc: + using ::strcpy_s; + using ::strcat_s; +#else + inline std::size_t strcpy_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + if(std::strlen(strSource)+1 > sizeInBytes) + return 1; + std::strcpy(strDestination, strSource); + return 0; + } + inline std::size_t strcat_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + if(std::strlen(strSource) + std::strlen(strDestination) + 1 > sizeInBytes) + return 1; + std::strcat(strDestination, strSource); + return 0; + } + +#endif + + inline void overflow_error_if_not_zero(std::size_t i) + { + if(i) + { + std::overflow_error e("String buffer too small"); + boost::throw_exception(e); + } + } + +}} // namespaces + +#endif // __cplusplus + +#endif // include guard + diff --git a/ext/boost/regex/v4/states.hpp b/ext/boost/regex/v4/states.hpp new file mode 100644 index 0000000000..efdebbe59f --- /dev/null +++ b/ext/boost/regex/v4/states.hpp @@ -0,0 +1,293 @@ +/* + * + * 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 states.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares internal state machine structures. + */ + +#ifndef BOOST_REGEX_V4_STATES_HPP +#define BOOST_REGEX_V4_STATES_HPP + +#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 + +namespace boost{ +namespace re_detail{ + +/*** mask_type ******************************************************* +Whenever we have a choice of two alternatives, we use an array of bytes +to indicate which of the two alternatives it is possible to take for any +given input character. If mask_take is set, then we can take the next +state, and if mask_skip is set then we can take the alternative. +***********************************************************************/ +enum mask_type +{ + mask_take = 1, + mask_skip = 2, + mask_init = 4, + mask_any = mask_skip | mask_take, + mask_all = mask_any +}; + +/*** helpers ********************************************************** +These helpers let us use function overload resolution to detect whether +we have narrow or wide character strings: +***********************************************************************/ +struct _narrow_type{}; +struct _wide_type{}; +template <class charT> struct is_byte; +template<> struct is_byte<char> { typedef _narrow_type width_type; }; +template<> struct is_byte<unsigned char>{ typedef _narrow_type width_type; }; +template<> struct is_byte<signed char> { typedef _narrow_type width_type; }; +template <class charT> struct is_byte { typedef _wide_type width_type; }; + +/*** enum syntax_element_type ****************************************** +Every record in the state machine falls into one of the following types: +***********************************************************************/ +enum syntax_element_type +{ + // start of a marked sub-expression, or perl-style (?...) extension + syntax_element_startmark = 0, + // end of a marked sub-expression, or perl-style (?...) extension + syntax_element_endmark = syntax_element_startmark + 1, + // any sequence of literal characters + syntax_element_literal = syntax_element_endmark + 1, + // start of line assertion: ^ + syntax_element_start_line = syntax_element_literal + 1, + // end of line assertion $ + syntax_element_end_line = syntax_element_start_line + 1, + // match any character: . + syntax_element_wild = syntax_element_end_line + 1, + // end of expression: we have a match when we get here + syntax_element_match = syntax_element_wild + 1, + // perl style word boundary: \b + syntax_element_word_boundary = syntax_element_match + 1, + // perl style within word boundary: \B + syntax_element_within_word = syntax_element_word_boundary + 1, + // start of word assertion: \< + syntax_element_word_start = syntax_element_within_word + 1, + // end of word assertion: \> + syntax_element_word_end = syntax_element_word_start + 1, + // start of buffer assertion: \` + syntax_element_buffer_start = syntax_element_word_end + 1, + // end of buffer assertion: \' + syntax_element_buffer_end = syntax_element_buffer_start + 1, + // backreference to previously matched sub-expression + syntax_element_backref = syntax_element_buffer_end + 1, + // either a wide character set [..] or one with multicharacter collating elements: + syntax_element_long_set = syntax_element_backref + 1, + // narrow character set: [...] + syntax_element_set = syntax_element_long_set + 1, + // jump to a new state in the machine: + syntax_element_jump = syntax_element_set + 1, + // choose between two production states: + syntax_element_alt = syntax_element_jump + 1, + // a repeat + syntax_element_rep = syntax_element_alt + 1, + // match a combining character sequence + syntax_element_combining = syntax_element_rep + 1, + // perl style soft buffer end: \z + syntax_element_soft_buffer_end = syntax_element_combining + 1, + // perl style continuation: \G + syntax_element_restart_continue = syntax_element_soft_buffer_end + 1, + // single character repeats: + syntax_element_dot_rep = syntax_element_restart_continue + 1, + syntax_element_char_rep = syntax_element_dot_rep + 1, + syntax_element_short_set_rep = syntax_element_char_rep + 1, + syntax_element_long_set_rep = syntax_element_short_set_rep + 1, + // a backstep for lookbehind repeats: + syntax_element_backstep = syntax_element_long_set_rep + 1, + // an assertion that a mark was matched: + syntax_element_assert_backref = syntax_element_backstep + 1, + syntax_element_toggle_case = syntax_element_assert_backref + 1, + // a recursive expression: + syntax_element_recurse = syntax_element_toggle_case + 1 +}; + +#ifdef BOOST_REGEX_DEBUG +// dwa 09/26/00 - This is needed to suppress warnings about an ambiguous conversion +std::ostream& operator<<(std::ostream&, syntax_element_type); +#endif + +struct re_syntax_base; + +/*** union offset_type ************************************************ +Points to another state in the machine. During machine construction +we use integral offsets, but these are converted to pointers before +execution of the machine. +***********************************************************************/ +union offset_type +{ + re_syntax_base* p; + std::ptrdiff_t i; +}; + +/*** struct re_syntax_base ******************************************** +Base class for all states in the machine. +***********************************************************************/ +struct re_syntax_base +{ + syntax_element_type type; // what kind of state this is + offset_type next; // next state in the machine +}; + +/*** struct re_brace ************************************************** +A marked parenthesis. +***********************************************************************/ +struct re_brace : public re_syntax_base +{ + // The index to match, can be zero (don't mark the sub-expression) + // or negative (for perl style (?...) extentions): + int index; + bool icase; +}; + +/*** struct re_dot ************************************************** +Match anything. +***********************************************************************/ +enum +{ + dont_care = 1, + force_not_newline = 0, + force_newline = 2, + + test_not_newline = 2, + test_newline = 3 +}; +struct re_dot : public re_syntax_base +{ + unsigned char mask; +}; + +/*** struct re_literal ************************************************ +A string of literals, following this structure will be an +array of characters: charT[length] +***********************************************************************/ +struct re_literal : public re_syntax_base +{ + unsigned int length; +}; + +/*** struct re_case ************************************************ +Indicates whether we are moving to a case insensive block or not +***********************************************************************/ +struct re_case : public re_syntax_base +{ + bool icase; +}; + +/*** struct re_set_long *********************************************** +A wide character set of characters, following this structure will be +an array of type charT: +First csingles null-terminated strings +Then 2 * cranges NULL terminated strings +Then cequivalents NULL terminated strings +***********************************************************************/ +template <class mask_type> +struct re_set_long : public re_syntax_base +{ + unsigned int csingles, cranges, cequivalents; + mask_type cclasses; + mask_type cnclasses; + bool isnot; + bool singleton; +}; + +/*** struct re_set **************************************************** +A set of narrow-characters, matches any of _map which is none-zero +***********************************************************************/ +struct re_set : public re_syntax_base +{ + unsigned char _map[1 << CHAR_BIT]; +}; + +/*** struct re_jump *************************************************** +Jump to a new location in the machine (not next). +***********************************************************************/ +struct re_jump : public re_syntax_base +{ + offset_type alt; // location to jump to +}; + +/*** struct re_alt *************************************************** +Jump to a new location in the machine (possibly next). +***********************************************************************/ +struct re_alt : public re_jump +{ + unsigned char _map[1 << CHAR_BIT]; // which characters can take the jump + unsigned int can_be_null; // true if we match a NULL string +}; + +/*** struct re_repeat ************************************************* +Repeat a section of the machine +***********************************************************************/ +struct re_repeat : public re_alt +{ + std::size_t min, max; // min and max allowable repeats + int state_id; // Unique identifier for this repeat + bool leading; // True if this repeat is at the start of the machine (lets us optimize some searches) + bool greedy; // True if this is a greedy repeat +}; + +/*** enum re_jump_size_type ******************************************* +Provides compiled size of re_jump structure (allowing for trailing alignment). +We provide this so we know how manybytes to insert when constructing the machine +(The value of padding_mask is defined in regex_raw_buffer.hpp). +***********************************************************************/ +enum re_jump_size_type +{ + re_jump_size = (sizeof(re_jump) + padding_mask) & ~(padding_mask), + re_repeater_size = (sizeof(re_repeat) + padding_mask) & ~(padding_mask), + re_alt_size = (sizeof(re_alt) + padding_mask) & ~(padding_mask) +}; + +/*** proc re_is_set_member ********************************************* +Forward declaration: we'll need this one later... +***********************************************************************/ + +template<class charT, class traits> +struct regex_data; + +template <class iterator, class charT, class traits_type, class char_classT> +iterator BOOST_REGEX_CALL re_is_set_member(iterator next, + iterator last, + const re_set_long<char_classT>* set_, + const regex_data<charT, traits_type>& e, bool icase); + +} // namespace re_detail + +} // namespace boost + +#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 + +#endif + + diff --git a/ext/boost/regex/v4/sub_match.hpp b/ext/boost/regex/v4/sub_match.hpp new file mode 100644 index 0000000000..1c79e39a9a --- /dev/null +++ b/ext/boost/regex/v4/sub_match.hpp @@ -0,0 +1,509 @@ +/* + * + * 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 sub_match.cpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares template class sub_match. + */ + +#ifndef BOOST_REGEX_V4_SUB_MATCH_HPP +#define BOOST_REGEX_V4_SUB_MATCH_HPP + +#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 + +namespace boost{ + +template <class BidiIterator> +struct sub_match : public std::pair<BidiIterator, BidiIterator> +{ + typedef typename re_detail::regex_iterator_traits<BidiIterator>::value_type value_type; +#if defined(BOOST_NO_STD_ITERATOR_TRAITS) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + typedef std::ptrdiff_t difference_type; +#else + typedef typename re_detail::regex_iterator_traits<BidiIterator>::difference_type difference_type; +#endif + typedef BidiIterator iterator_type; + typedef BidiIterator iterator; + typedef BidiIterator const_iterator; + + bool matched; + + sub_match() : std::pair<BidiIterator, BidiIterator>(), matched(false) {} + sub_match(BidiIterator i) : std::pair<BidiIterator, BidiIterator>(i, i), matched(false) {} +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_MSVC, < 1310)\ + && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)\ + && !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + template <class T, class A> + operator std::basic_string<value_type, T, A> ()const + { + return std::basic_string<value_type, T, A>(this->first, this->second); + } +#else + operator std::basic_string<value_type> ()const + { + return str(); + } +#endif + difference_type BOOST_REGEX_CALL length()const + { + difference_type n = ::boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); + return n; + } + std::basic_string<value_type> str()const + { + std::basic_string<value_type> result; + std::size_t len = ::boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); + result.reserve(len); + BidiIterator i = this->first; + while(i != this->second) + { + result.append(1, *i); + ++i; + } + return result; + } + int compare(const sub_match& s)const + { + if(matched != s.matched) + return static_cast<int>(matched) - static_cast<int>(s.matched); + return str().compare(s.str()); + } + int compare(const std::basic_string<value_type>& s)const + { + return str().compare(s); + } + int compare(const value_type* p)const + { + return str().compare(p); + } + + bool operator==(const sub_match& that)const + { return compare(that) == 0; } + bool BOOST_REGEX_CALL operator !=(const sub_match& that)const + { return compare(that) != 0; } + bool operator<(const sub_match& that)const + { return compare(that) < 0; } + bool operator>(const sub_match& that)const + { return compare(that) > 0; } + bool operator<=(const sub_match& that)const + { return compare(that) <= 0; } + bool operator>=(const sub_match& that)const + { return compare(that) >= 0; } + +#ifdef BOOST_REGEX_MATCH_EXTRA + typedef std::vector<sub_match<BidiIterator> > capture_sequence_type; + + const capture_sequence_type& captures()const + { + if(!m_captures) + m_captures.reset(new capture_sequence_type()); + return *m_captures; + } + // + // Private implementation API: DO NOT USE! + // + capture_sequence_type& get_captures()const + { + if(!m_captures) + m_captures.reset(new capture_sequence_type()); + return *m_captures; + } + +private: + mutable boost::scoped_ptr<capture_sequence_type> m_captures; +public: + +#endif + sub_match(const sub_match& that, bool +#ifdef BOOST_REGEX_MATCH_EXTRA + deep_copy +#endif + = true + ) + : std::pair<BidiIterator, BidiIterator>(that), + matched(that.matched) + { +#ifdef BOOST_REGEX_MATCH_EXTRA + if(that.m_captures) + if(deep_copy) + m_captures.reset(new capture_sequence_type(*(that.m_captures))); +#endif + } + sub_match& operator=(const sub_match& that) + { + this->first = that.first; + this->second = that.second; + matched = that.matched; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(that.m_captures) + get_captures() = *(that.m_captures); +#endif + return *this; + } + + +#ifdef BOOST_OLD_REGEX_H + // + // the following are deprecated, do not use!! + // + operator int()const; + operator unsigned int()const; + operator short()const + { + return (short)(int)(*this); + } + operator unsigned short()const + { + return (unsigned short)(unsigned int)(*this); + } +#endif +}; + +typedef sub_match<const char*> csub_match; +typedef sub_match<std::string::const_iterator> ssub_match; +#ifndef BOOST_NO_WREGEX +typedef sub_match<const wchar_t*> wcsub_match; +typedef sub_match<std::wstring::const_iterator> wssub_match; +#endif + +// comparison to std::basic_string<> part 1: +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator == (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ return s.compare(m.str()) == 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator != (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ return s.compare(m.str()) != 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator < (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ return s.compare(m.str()) < 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator <= (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ return s.compare(m.str()) <= 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator >= (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ return s.compare(m.str()) >= 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator > (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ return s.compare(m.str()) > 0; } +// comparison to std::basic_string<> part 2: +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator == (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ return m.str().compare(s) == 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator != (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ return m.str().compare(s) != 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator < (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ return m.str().compare(s) < 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator > (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ return m.str().compare(s) > 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator <= (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ return m.str().compare(s) <= 0; } +template <class RandomAccessIterator, class traits, class Allocator> +inline bool operator >= (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ return m.str().compare(s) >= 0; } +// comparison to const charT* part 1: +template <class RandomAccessIterator> +inline bool operator == (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s) +{ return m.str().compare(s) == 0; } +template <class RandomAccessIterator> +inline bool operator != (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s) +{ return m.str().compare(s) != 0; } +template <class RandomAccessIterator> +inline bool operator > (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s) +{ return m.str().compare(s) > 0; } +template <class RandomAccessIterator> +inline bool operator < (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s) +{ return m.str().compare(s) < 0; } +template <class RandomAccessIterator> +inline bool operator >= (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s) +{ return m.str().compare(s) >= 0; } +template <class RandomAccessIterator> +inline bool operator <= (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s) +{ return m.str().compare(s) <= 0; } +// comparison to const charT* part 2: +template <class RandomAccessIterator> +inline bool operator == (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(s) == 0; } +template <class RandomAccessIterator> +inline bool operator != (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(s) != 0; } +template <class RandomAccessIterator> +inline bool operator < (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(s) > 0; } +template <class RandomAccessIterator> +inline bool operator > (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(s) < 0; } +template <class RandomAccessIterator> +inline bool operator <= (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(s) >= 0; } +template <class RandomAccessIterator> +inline bool operator >= (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(s) <= 0; } + +// comparison to const charT& part 1: +template <class RandomAccessIterator> +inline bool operator == (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) == 0; } +template <class RandomAccessIterator> +inline bool operator != (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) != 0; } +template <class RandomAccessIterator> +inline bool operator > (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) > 0; } +template <class RandomAccessIterator> +inline bool operator < (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) < 0; } +template <class RandomAccessIterator> +inline bool operator >= (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) >= 0; } +template <class RandomAccessIterator> +inline bool operator <= (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) <= 0; } +// comparison to const charT* part 2: +template <class RandomAccessIterator> +inline bool operator == (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(0, m.length(), &s, 1) == 0; } +template <class RandomAccessIterator> +inline bool operator != (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(0, m.length(), &s, 1) != 0; } +template <class RandomAccessIterator> +inline bool operator < (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(0, m.length(), &s, 1) > 0; } +template <class RandomAccessIterator> +inline bool operator > (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(0, m.length(), &s, 1) < 0; } +template <class RandomAccessIterator> +inline bool operator <= (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(0, m.length(), &s, 1) >= 0; } +template <class RandomAccessIterator> +inline bool operator >= (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ return m.str().compare(0, m.length(), &s, 1) <= 0; } + +// addition operators: +template <class RandomAccessIterator, class traits, class Allocator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator> +operator + (const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s, + const sub_match<RandomAccessIterator>& m) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator> result; + result.reserve(s.size() + m.length() + 1); + return result.append(s).append(m.first, m.second); +} +template <class RandomAccessIterator, class traits, class Allocator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator> +operator + (const sub_match<RandomAccessIterator>& m, + const std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type, traits, Allocator> result; + result.reserve(s.size() + m.length() + 1); + return result.append(m.first, m.second).append(s); +} +#if !(defined(__GNUC__) && defined(BOOST_NO_STD_LOCALE)) +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> result; + result.reserve(std::char_traits<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type>::length(s) + m.length() + 1); + return result.append(s).append(m.first, m.second); +} +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const * s) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> result; + result.reserve(std::char_traits<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type>::length(s) + m.length() + 1); + return result.append(m.first, m.second).append(s); +} +#else +// worwaround versions: +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const* s, + const sub_match<RandomAccessIterator>& m) +{ + return s + m.str(); +} +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const * s) +{ + return m.str() + s; +} +#endif +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s, + const sub_match<RandomAccessIterator>& m) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> result; + result.reserve(m.length() + 2); + return result.append(1, s).append(m.first, m.second); +} +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (const sub_match<RandomAccessIterator>& m, + typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type const& s) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> result; + result.reserve(m.length() + 2); + return result.append(m.first, m.second).append(1, s); +} +template <class RandomAccessIterator> +inline std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> +operator + (const sub_match<RandomAccessIterator>& m1, + const sub_match<RandomAccessIterator>& m2) +{ + std::basic_string<typename re_detail::regex_iterator_traits<RandomAccessIterator>::value_type> result; + result.reserve(m1.length() + m2.length() + 1); + return result.append(m1.first, m1.second).append(m2.first, m2.second); +} +#ifndef BOOST_NO_STD_LOCALE +template <class charT, class traits, class RandomAccessIterator> +std::basic_ostream<charT, traits>& + operator << (std::basic_ostream<charT, traits>& os, + const sub_match<RandomAccessIterator>& s) +{ + return (os << s.str()); +} +#else +template <class RandomAccessIterator> +std::ostream& operator << (std::ostream& os, + const sub_match<RandomAccessIterator>& s) +{ + return (os << s.str()); +} +#endif + +#ifdef BOOST_OLD_REGEX_H +namespace re_detail{ +template <class BidiIterator, class charT> +int do_toi(BidiIterator i, BidiIterator j, char c, int radix) +{ + std::string s(i, j); + char* p; + int result = std::strtol(s.c_str(), &p, radix); + if(*p)raise_regex_exception("Bad sub-expression"); + return result; +} + +// +// helper: +template <class I, class charT> +int do_toi(I& i, I j, charT c) +{ + int result = 0; + while((i != j) && (isdigit(*i))) + { + result = result*10 + (*i - '0'); + ++i; + } + return result; +} +} + + +template <class BidiIterator> +sub_match<BidiIterator>::operator int()const +{ + BidiIterator i = first; + BidiIterator j = second; + if(i == j)raise_regex_exception("Bad sub-expression"); + int neg = 1; + if((i != j) && (*i == '-')) + { + neg = -1; + ++i; + } + neg *= re_detail::do_toi(i, j, *i); + if(i != j)raise_regex_exception("Bad sub-expression"); + return neg; +} +template <class BidiIterator> +sub_match<BidiIterator>::operator unsigned int()const +{ + BidiIterator i = first; + BidiIterator j = second; + if(i == j) + raise_regex_exception("Bad sub-expression"); + return re_detail::do_toi(i, j, *first); +} +#endif + +} // namespace boost + +#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 + +#endif + diff --git a/ext/boost/regex/v4/syntax_type.hpp b/ext/boost/regex/v4/syntax_type.hpp new file mode 100644 index 0000000000..3efdf0b0f9 --- /dev/null +++ b/ext/boost/regex/v4/syntax_type.hpp @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2003 + * 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 syntax_type.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression synatx type enumerator. + */ + +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#define BOOST_REGEX_SYNTAX_TYPE_HPP + +namespace boost{ +namespace regex_constants{ + +typedef unsigned char syntax_type; + +// +// values chosen are binary compatible with previous version: +// +static const syntax_type syntax_char = 0; +static const syntax_type syntax_open_mark = 1; +static const syntax_type syntax_close_mark = 2; +static const syntax_type syntax_dollar = 3; +static const syntax_type syntax_caret = 4; +static const syntax_type syntax_dot = 5; +static const syntax_type syntax_star = 6; +static const syntax_type syntax_plus = 7; +static const syntax_type syntax_question = 8; +static const syntax_type syntax_open_set = 9; +static const syntax_type syntax_close_set = 10; +static const syntax_type syntax_or = 11; +static const syntax_type syntax_escape = 12; +static const syntax_type syntax_dash = 14; +static const syntax_type syntax_open_brace = 15; +static const syntax_type syntax_close_brace = 16; +static const syntax_type syntax_digit = 17; +static const syntax_type syntax_comma = 27; +static const syntax_type syntax_equal = 37; +static const syntax_type syntax_colon = 36; +static const syntax_type syntax_not = 53; + +// extensions: + +static const syntax_type syntax_hash = 13; +static const syntax_type syntax_newline = 26; + +// escapes: + +typedef syntax_type escape_syntax_type; + +static const escape_syntax_type escape_type_word_assert = 18; +static const escape_syntax_type escape_type_not_word_assert = 19; +static const escape_syntax_type escape_type_control_f = 29; +static const escape_syntax_type escape_type_control_n = 30; +static const escape_syntax_type escape_type_control_r = 31; +static const escape_syntax_type escape_type_control_t = 32; +static const escape_syntax_type escape_type_control_v = 33; +static const escape_syntax_type escape_type_ascii_control = 35; +static const escape_syntax_type escape_type_hex = 34; +static const escape_syntax_type escape_type_unicode = 0; // not used +static const escape_syntax_type escape_type_identity = 0; // not used +static const escape_syntax_type escape_type_backref = syntax_digit; +static const escape_syntax_type escape_type_decimal = syntax_digit; // not used +static const escape_syntax_type escape_type_class = 22; +static const escape_syntax_type escape_type_not_class = 23; + +// extensions: + +static const escape_syntax_type escape_type_left_word = 20; +static const escape_syntax_type escape_type_right_word = 21; +static const escape_syntax_type escape_type_start_buffer = 24; // for \` +static const escape_syntax_type escape_type_end_buffer = 25; // for \' +static const escape_syntax_type escape_type_control_a = 28; // for \a +static const escape_syntax_type escape_type_e = 38; // for \e +static const escape_syntax_type escape_type_E = 47; // for \Q\E +static const escape_syntax_type escape_type_Q = 48; // for \Q\E +static const escape_syntax_type escape_type_X = 49; // for \X +static const escape_syntax_type escape_type_C = 50; // for \C +static const escape_syntax_type escape_type_Z = 51; // for \Z +static const escape_syntax_type escape_type_G = 52; // for \G + +static const escape_syntax_type escape_type_property = 54; // for \p +static const escape_syntax_type escape_type_not_property = 55; // for \P +static const escape_syntax_type escape_type_named_char = 56; // for \N +static const escape_syntax_type escape_type_extended_backref = 57; // for \g +static const escape_syntax_type escape_type_reset_start_mark = 58; // for \K +static const escape_syntax_type escape_type_line_ending = 59; // for \R + +static const escape_syntax_type syntax_max = 60; + +} +} + + +#endif diff --git a/ext/boost/regex/v4/u32regex_iterator.hpp b/ext/boost/regex/v4/u32regex_iterator.hpp new file mode 100644 index 0000000000..7e893e6951 --- /dev/null +++ b/ext/boost/regex/v4/u32regex_iterator.hpp @@ -0,0 +1,193 @@ +/* + * + * Copyright (c) 2003 + * 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 u32regex_iterator.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides u32regex_iterator implementation. + */ + +#ifndef BOOST_REGEX_V4_U32REGEX_ITERATOR_HPP +#define BOOST_REGEX_V4_U32REGEX_ITERATOR_HPP + +namespace boost{ + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +template <class BidirectionalIterator> +class u32regex_iterator_implementation +{ + typedef u32regex regex_type; + + match_results<BidirectionalIterator> what; // current match + BidirectionalIterator base; // start of sequence + BidirectionalIterator end; // end of sequence + const regex_type re; // the expression + match_flag_type flags; // flags for matching + +public: + u32regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f) + : base(), end(last), re(*p), flags(f){} + bool init(BidirectionalIterator first) + { + base = first; + return u32regex_search(first, end, what, re, flags, base); + } + bool compare(const u32regex_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); + } + const match_results<BidirectionalIterator>& get() + { return what; } + bool next() + { + //if(what.prefix().first != what[0].second) + // flags |= match_prev_avail; + BidirectionalIterator next_start = what[0].second; + match_flag_type f(flags); + if(!what.length()) + f |= regex_constants::match_not_initial_null; + //if(base != next_start) + // f |= regex_constants::match_not_bob; + bool result = u32regex_search(next_start, end, what, re, f, base); + if(result) + what.set_base(base); + return result; + } +private: + u32regex_iterator_implementation& operator=(const u32regex_iterator_implementation&); +}; + +template <class BidirectionalIterator> +class u32regex_iterator +#ifndef BOOST_NO_STD_ITERATOR + : public std::iterator< + std::forward_iterator_tag, + match_results<BidirectionalIterator>, + typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type, + const match_results<BidirectionalIterator>*, + const match_results<BidirectionalIterator>& > +#endif +{ +private: + typedef u32regex_iterator_implementation<BidirectionalIterator> impl; + typedef shared_ptr<impl> pimpl; +public: + typedef u32regex regex_type; + typedef match_results<BidirectionalIterator> value_type; + typedef typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + u32regex_iterator(){} + u32regex_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + match_flag_type m = match_default) + : pdata(new impl(&re, b, m)) + { + if(!pdata->init(a)) + { + pdata.reset(); + } + } + u32regex_iterator(const u32regex_iterator& that) + : pdata(that.pdata) {} + u32regex_iterator& operator=(const u32regex_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const u32regex_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const u32regex_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + u32regex_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + u32regex_iterator operator++(int) + { + u32regex_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && !pdata.unique()) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef u32regex_iterator<const char*> utf8regex_iterator; +typedef u32regex_iterator<const UChar*> utf16regex_iterator; +typedef u32regex_iterator<const UChar32*> utf32regex_iterator; + +inline u32regex_iterator<const char*> make_u32regex_iterator(const char* p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_iterator<const char*>(p, p+std::strlen(p), e, m); +} +#ifndef BOOST_NO_WREGEX +inline u32regex_iterator<const wchar_t*> make_u32regex_iterator(const wchar_t* p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_iterator<const wchar_t*>(p, p+std::wcslen(p), e, m); +} +#endif +#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) +inline u32regex_iterator<const UChar*> make_u32regex_iterator(const UChar* p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_iterator<const UChar*>(p, p+u_strlen(p), e, m); +} +#endif +template <class charT, class Traits, class Alloc> +inline u32regex_iterator<typename std::basic_string<charT, Traits, Alloc>::const_iterator> make_u32regex_iterator(const std::basic_string<charT, Traits, Alloc>& p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type; + return u32regex_iterator<iter_type>(p.begin(), p.end(), e, m); +} +inline u32regex_iterator<const UChar*> make_u32regex_iterator(const UnicodeString& s, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, m); +} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_ITERATOR_HPP + diff --git a/ext/boost/regex/v4/u32regex_token_iterator.hpp b/ext/boost/regex/v4/u32regex_token_iterator.hpp new file mode 100644 index 0000000000..2726d486fd --- /dev/null +++ b/ext/boost/regex/v4/u32regex_token_iterator.hpp @@ -0,0 +1,377 @@ +/* + * + * Copyright (c) 2003 + * 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 u32regex_token_iterator.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Provides u32regex_token_iterator implementation. + */ + +#ifndef BOOST_REGEX_V4_U32REGEX_TOKEN_ITERATOR_HPP +#define BOOST_REGEX_V4_U32REGEX_TOKEN_ITERATOR_HPP + +#if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +// +// Borland C++ Builder 6, and Visual C++ 6, +// can't cope with the array template constructor +// so we have a template member that will accept any type as +// argument, and then assert that is really is an array: +// +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_array.hpp> +#endif + +namespace boost{ + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#if BOOST_WORKAROUND(BOOST_MSVC, > 1300) +# pragma warning(push) +# pragma warning(disable:4700) +#endif + +template <class BidirectionalIterator> +class u32regex_token_iterator_implementation +{ + typedef u32regex regex_type; + typedef sub_match<BidirectionalIterator> value_type; + + match_results<BidirectionalIterator> what; // current match + BidirectionalIterator end; // end of search area + BidirectionalIterator base; // start of search area + const regex_type re; // the expression + match_flag_type flags; // match flags + value_type result; // the current string result + int N; // the current sub-expression being enumerated + std::vector<int> subs; // the sub-expressions to enumerate + +public: + u32regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) + : end(last), re(*p), flags(f){ subs.push_back(sub); } + u32regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector<int>& v, match_flag_type f) + : end(last), re(*p), flags(f), subs(v){} +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // can't reliably get this to work.... +#elif (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ + || BOOST_WORKAROUND(__HP_aCC, < 60700) + template <class T> + u32regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const T& submatches, match_flag_type f) + : end(last), re(*p), flags(f) + { + // assert that T really is an array: + BOOST_STATIC_ASSERT(::boost::is_array<T>::value); + const std::size_t array_size = sizeof(T) / sizeof(submatches[0]); + for(std::size_t i = 0; i < array_size; ++i) + { + subs.push_back(submatches[i]); + } + } +#else + template <std::size_t CN> + u32regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) + : end(last), re(*p), flags(f) + { + for(std::size_t i = 0; i < CN; ++i) + { + subs.push_back(submatches[i]); + } + } +#endif + + bool init(BidirectionalIterator first) + { + base = first; + N = 0; + if(u32regex_search(first, end, what, re, flags, base) == true) + { + N = 0; + result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]); + return true; + } + else if((subs[N] == -1) && (first != end)) + { + result.first = first; + result.second = end; + result.matched = (first != end); + N = -1; + return true; + } + return false; + } + bool compare(const u32regex_token_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) + && (end == that.end) + && (flags == that.flags) + && (N == that.N) + && (what[0].first == that.what[0].first) + && (what[0].second == that.what[0].second); + } + const value_type& get() + { return result; } + bool next() + { + if(N == -1) + return false; + if(N+1 < (int)subs.size()) + { + ++N; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + //if(what.prefix().first != what[0].second) + // flags |= match_prev_avail | regex_constants::match_not_bob; + BidirectionalIterator last_end(what[0].second); + if(u32regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags), base)) + { + N =0; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + else if((last_end != end) && (subs[0] == -1)) + { + N =-1; + result.first = last_end; + result.second = end; + result.matched = (last_end != end); + return true; + } + return false; + } +private: + u32regex_token_iterator_implementation& operator=(const u32regex_token_iterator_implementation&); +}; + +template <class BidirectionalIterator> +class u32regex_token_iterator +#ifndef BOOST_NO_STD_ITERATOR + : public std::iterator< + std::forward_iterator_tag, + sub_match<BidirectionalIterator>, + typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type, + const sub_match<BidirectionalIterator>*, + const sub_match<BidirectionalIterator>& > +#endif +{ +private: + typedef u32regex_token_iterator_implementation<BidirectionalIterator> impl; + typedef shared_ptr<impl> pimpl; +public: + typedef u32regex regex_type; + typedef sub_match<BidirectionalIterator> value_type; + typedef typename re_detail::regex_iterator_traits<BidirectionalIterator>::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + u32regex_token_iterator(){} + u32regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + int submatch = 0, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatch, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } + u32regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const std::vector<int>& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // can't reliably get this to work.... +#elif (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ + || BOOST_WORKAROUND(__HP_aCC, < 60700) + template <class T> + u32regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const T& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#else + template <std::size_t N> + u32regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const int (&submatches)[N], match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#endif + u32regex_token_iterator(const u32regex_token_iterator& that) + : pdata(that.pdata) {} + u32regex_token_iterator& operator=(const u32regex_token_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const u32regex_token_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const u32regex_token_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + u32regex_token_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + u32regex_token_iterator operator++(int) + { + u32regex_token_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && !pdata.unique()) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef u32regex_token_iterator<const char*> utf8regex_token_iterator; +typedef u32regex_token_iterator<const UChar*> utf16regex_token_iterator; +typedef u32regex_token_iterator<const UChar32*> utf32regex_token_iterator; + +// construction from an integral sub_match state_id: +inline u32regex_token_iterator<const char*> make_u32regex_token_iterator(const char* p, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const char*>(p, p+std::strlen(p), e, submatch, m); +} +#ifndef BOOST_NO_WREGEX +inline u32regex_token_iterator<const wchar_t*> make_u32regex_token_iterator(const wchar_t* p, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const wchar_t*>(p, p+std::wcslen(p), e, submatch, m); +} +#endif +#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) +inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UChar* p, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const UChar*>(p, p+u_strlen(p), e, submatch, m); +} +#endif +template <class charT, class Traits, class Alloc> +inline u32regex_token_iterator<typename std::basic_string<charT, Traits, Alloc>::const_iterator> make_u32regex_token_iterator(const std::basic_string<charT, Traits, Alloc>& p, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type; + return u32regex_token_iterator<iter_type>(p.begin(), p.end(), e, m); +} +inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UnicodeString& s, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, submatch, m); +} + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// construction from a reference to an array: +template <std::size_t N> +inline u32regex_token_iterator<const char*> make_u32regex_token_iterator(const char* p, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const char*>(p, p+std::strlen(p), e, submatch, m); +} +#ifndef BOOST_NO_WREGEX +template <std::size_t N> +inline u32regex_token_iterator<const wchar_t*> make_u32regex_token_iterator(const wchar_t* p, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const wchar_t*>(p, p+std::wcslen(p), e, submatch, m); +} +#endif +#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) +template <std::size_t N> +inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UChar* p, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const UChar*>(p, p+u_strlen(p), e, m); +} +#endif +template <class charT, class Traits, class Alloc, std::size_t N> +inline u32regex_token_iterator<typename std::basic_string<charT, Traits, Alloc>::const_iterator> make_u32regex_token_iterator(const std::basic_string<charT, Traits, Alloc>& p, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type; + return u32regex_token_iterator<iter_type>(p.begin(), p.end(), e, m); +} +template <std::size_t N> +inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UnicodeString& s, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, submatch, m); +} +#endif // BOOST_MSVC < 1300 + +// construction from a vector of sub_match state_id's: +inline u32regex_token_iterator<const char*> make_u32regex_token_iterator(const char* p, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const char*>(p, p+std::strlen(p), e, submatch, m); +} +#ifndef BOOST_NO_WREGEX +inline u32regex_token_iterator<const wchar_t*> make_u32regex_token_iterator(const wchar_t* p, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const wchar_t*>(p, p+std::wcslen(p), e, submatch, m); +} +#endif +#if !defined(U_WCHAR_IS_UTF16) && (U_SIZEOF_WCHAR_T != 2) +inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UChar* p, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const UChar*>(p, p+u_strlen(p), e, submatch, m); +} +#endif +template <class charT, class Traits, class Alloc> +inline u32regex_token_iterator<typename std::basic_string<charT, Traits, Alloc>::const_iterator> make_u32regex_token_iterator(const std::basic_string<charT, Traits, Alloc>& p, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type; + return u32regex_token_iterator<iter_type>(p.begin(), p.end(), e, m); +} +inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UnicodeString& s, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return u32regex_token_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, submatch, m); +} + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1310) +# pragma warning(pop) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP + + + + diff --git a/ext/boost/regex/v4/w32_regex_traits.hpp b/ext/boost/regex/v4/w32_regex_traits.hpp new file mode 100644 index 0000000000..d55620726d --- /dev/null +++ b/ext/boost/regex/v4/w32_regex_traits.hpp @@ -0,0 +1,741 @@ +/* + * + * 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 w32_regex_traits.hpp + * VERSION see <boost/version.hpp> + * DESCRIPTION: Declares regular expression traits class w32_regex_traits. + */ + +#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include <boost/regex/pattern_except.hpp> +#endif +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include <boost/regex/v4/regex_traits_defaults.hpp> +#endif +#ifdef BOOST_HAS_THREADS +#include <boost/regex/pending/static_mutex.hpp> +#endif +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#include <boost/regex/v4/primary_transform.hpp> +#endif +#ifndef BOOST_REGEX_OBJECT_CACHE_HPP +#include <boost/regex/pending/object_cache.hpp> +#endif + +#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:4786) +#pragma warning(disable:4800) +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template <class charT> +class w32_regex_traits; + +namespace re_detail{ + +// +// start by typedeffing the types we'll need: +// +typedef ::boost::uint32_t lcid_type; // placeholder for LCID. +typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE. + +// +// then add wrappers around the actual Win32 API's (ie implementation hiding): +// +BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale(); +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type); +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(unsigned short ca, lcid_type state_id); +#endif +#endif +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type); +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(unsigned short ca, lcid_type state_id); +#endif +#endif +BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name); +BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def); +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::basic_string<unsigned short>& def); +#endif +#endif +BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2); +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transform(lcid_type state_id, const unsigned short* p1, const unsigned short* p2); +#endif +#endif +BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type); +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_tolower(unsigned short c, lcid_type state_id); +#endif +#endif +BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type); +#endif +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c); +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type state_id, boost::uint32_t m, unsigned short c); +#endif +#endif +// +// class w32_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template <class charT> +struct w32_regex_traits_base +{ + w32_regex_traits_base(lcid_type l) + { imbue(l); } + lcid_type imbue(lcid_type l); + + lcid_type m_locale; +}; + +template <class charT> +inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l) +{ + lcid_type result(m_locale); + m_locale = l; + return result; +} + +// +// class w32_regex_traits_char_layer: +// implements methods that require specialisation for narrow characters: +// +template <class charT> +class w32_regex_traits_char_layer : public w32_regex_traits_base<charT> +{ + typedef std::basic_string<charT> string_type; + typedef std::map<charT, regex_constants::syntax_type> map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + w32_regex_traits_char_layer(const lcid_type l); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(::boost::re_detail::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class; + if(::boost::re_detail::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + charT tolower(charT c)const + { + return ::boost::re_detail::w32_tolower(c, this->m_locale); + } + bool isctype(boost::uint32_t mask, charT c)const + { + return ::boost::re_detail::w32_is(this->m_locale, mask, c); + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template <class charT> +w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::re_detail::lcid_type l) + : w32_regex_traits_base<charT>(l) +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + cat_type cat; + std::string cat_name(w32_regex_traits<charT>::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::re_detail::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::re_detail::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + this->m_char_map[mss[j]] = i; + } + } + } + else + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + this->m_char_map[static_cast<charT>(*ptr)] = i; + ++ptr; + } + } + } +} + +template <class charT> +typename w32_regex_traits_char_layer<charT>::string_type + w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, static_cast<charT>(*ptr)); + ++ptr; + } + return result; +} + +// +// specialised version for narrow characters: +// +template <> +class BOOST_REGEX_DECL w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char> +{ + typedef std::string string_type; +public: + w32_regex_traits_char_layer(::boost::re_detail::lcid_type l) + : w32_regex_traits_base<char>(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast<unsigned char>(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast<unsigned char>(c)]; + } + char tolower(char c)const + { + return m_lower_map[static_cast<unsigned char>(c)]; + } + bool isctype(boost::uint32_t mask, char c)const + { + return m_type_map[static_cast<unsigned char>(c)] & mask; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + char m_lower_map[1u << CHAR_BIT]; + boost::uint16_t m_type_map[1u << CHAR_BIT]; + void init(); +}; + +// +// class w32_regex_traits_implementation: +// provides pimpl implementation for w32_regex_traits. +// +template <class charT> +class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT> +{ +public: + typedef typename w32_regex_traits<charT>::char_class_type char_class_type; + BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1 + BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2 + BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3 + BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4 + BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff); // all the masks used by the CT_CTYPE1 group + + typedef std::basic_string<charT> string_type; + typedef charT char_type; + w32_regex_traits_implementation(::boost::re_detail::lcid_type l); + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map<int, std::string>::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + typedef typename string_type::size_type size_type; + string_type temp(p1, p2); + for(size_type i = 0; i < temp.size(); ++i) + temp[i] = this->tolower(temp[i]); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::re_detail::w32_transform(this->m_locale, p1, p2); + } +private: + std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID + std::map<string_type, char_class_type> m_custom_class_names; // character class names + std::map<string_type, string_type> m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; +}; + +template <class charT> +typename w32_regex_traits_implementation<charT>::string_type + w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const +{ + string_type result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + typedef typename string_type::size_type size_type; + for(size_type i = 0; i < result.size(); ++i) + result[i] = this->tolower(result[i]); + result = this->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } + if(result.empty()) + result = string_type(1, charT(0)); + return result; +} + +template <class charT> +typename w32_regex_traits_implementation<charT>::string_type + w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map<string_type, string_type>::const_iterator iter_type; + if(m_custom_collate_names.size()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\ + && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551) + std::string name(p1, p2); +#else + std::string name; + const charT* p0 = p1; + while(p0 != p2) + name.append(1, char(*p0++)); +#endif + name = lookup_default_collate_name(name); +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\ + && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551) + if(name.size()) + return string_type(name.begin(), name.end()); +#else + if(name.size()) + { + string_type result; + typedef std::string::const_iterator iter; + iter b = name.begin(); + iter e = name.end(); + while(b != e) + result.append(1, charT(*b++)); + return result; + } +#endif + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +template <class charT> +w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::re_detail::lcid_type l) +: w32_regex_traits_char_layer<charT>(l) +{ + cat_type cat; + std::string cat_name(w32_regex_traits<charT>::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::re_detail::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::re_detail::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0); + i <= boost::regex_constants::error_unknown; + i = static_cast<boost::regex_constants::error_type>(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, static_cast<charT>(*p)); + ++p; + } + string_type s = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, static_cast<char>(s[j])); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // + static const char_class_type masks[14] = + { + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + 0x0080u, // C1_XDIGIT + 0x0040u, // C1_BLANK + w32_regex_traits_implementation<charT>::mask_word, + w32_regex_traits_implementation<charT>::mask_unicode, + }; + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(::boost::re_detail::w32_cat_get(cat, this->m_locale, j+300, null_string)); + if(s.size()) + this->m_custom_class_names[s] = masks[j]; + } + } + // + // get the collation format used by m_pcollate: + // + m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim); +} + +template <class charT> +typename w32_regex_traits_implementation<charT>::char_class_type + w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const +{ + static const char_class_type masks[22] = + { + 0, + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0040u, // C1_BLANK + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK + w32_regex_traits_implementation<charT>::mask_horizontal, + 0x0002u, // C1_LOWER + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + w32_regex_traits_implementation<charT>::mask_unicode, + 0x0001u, // C1_UPPER + w32_regex_traits_implementation<charT>::mask_vertical, + 0x0104u | w32_regex_traits_implementation<charT>::mask_word, + 0x0104u | w32_regex_traits_implementation<charT>::mask_word, + 0x0080u, // C1_XDIGIT + }; + if(m_custom_class_names.size()) + { + typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t state_id = 1 + re_detail::get_default_class_id(p1, p2); + if(state_id < sizeof(masks) / sizeof(masks[0])) + return masks[state_id]; + return masks[0]; +} + + +template <class charT> +boost::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::re_detail::lcid_type l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT)) +{ + // TODO: create a cache for previously constructed objects. + return boost::object_cache< ::boost::re_detail::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5); +} + +} // re_detail + +template <class charT> +class w32_regex_traits +{ +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string<char_type> string_type; + typedef ::boost::re_detail::lcid_type locale_type; + typedef boost::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + w32_regex_traits() + : m_pimpl(re_detail::create_w32_regex_traits<charT>(::boost::re_detail::w32_get_default_locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits<charT>::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return this->m_pimpl->tolower(c); + } + charT translate(charT c, bool icase) const + { + return icase ? this->m_pimpl->tolower(c) : c; + } + charT tolower(charT c) const + { + return this->m_pimpl->tolower(c); + } + charT toupper(charT c) const + { + return ::boost::re_detail::w32_toupper(c, this->m_pimpl->m_locale); + } + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::re_detail::w32_transform(this->m_pimpl->m_locale, p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { + if((f & re_detail::w32_regex_traits_implementation<charT>::mask_base) + && (this->m_pimpl->isctype(f & re_detail::w32_regex_traits_implementation<charT>::mask_base, c))) + return true; + else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c)) + return true; + else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_word) && (c == '_')) + return true; + else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_vertical) + && (::boost::re_detail::is_separator(c) || (c == '\v'))) + return true; + else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_horizontal) + && this->isctype(c, 0x0008u) && !this->isctype(c, re_detail::w32_regex_traits_implementation<charT>::mask_vertical)) + return true; + return false; + } + int toi(const charT*& p1, const charT* p2, int radix)const + { + return ::boost::re_detail::global_toi(p1, p2, radix, *this); + } + int value(charT c, int radix)const + { + int result = ::boost::re_detail::global_value(c); + return result < radix ? result : -1; + } + locale_type imbue(locale_type l) + { + ::boost::re_detail::lcid_type result(getloc()); + m_pimpl = re_detail::create_w32_regex_traits<charT>(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + boost::shared_ptr<const re_detail::w32_regex_traits_implementation<charT> > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static static_mutex& get_mutex_inst(); +#endif +}; + +template <class charT> +std::string w32_regex_traits<charT>::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template <class charT> +std::string& w32_regex_traits<charT>::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template <class charT> +std::string w32_regex_traits<charT>::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template <class charT> +static_mutex& w32_regex_traits<charT>::get_mutex_inst() +{ + static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT; + return s_mutex; +} +#endif + + +} // boost + +#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 + +#endif |