diff options
Diffstat (limited to '3rdParty/Boost/libs')
28 files changed, 5627 insertions, 0 deletions
diff --git a/3rdParty/Boost/libs/date_time/src/gregorian/date_generators.cpp b/3rdParty/Boost/libs/date_time/src/gregorian/date_generators.cpp new file mode 100644 index 0000000..bbef7f6 --- /dev/null +++ b/3rdParty/Boost/libs/date_time/src/gregorian/date_generators.cpp @@ -0,0 +1,38 @@ +/* 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) $ + */ + + + +#ifndef BOOST_DATE_TIME_SOURCE +#define BOOST_DATE_TIME_SOURCE +#endif +#include "boost/date_time/date_generators.hpp" + +namespace boost { +namespace date_time { + + const char* const _nth_as_str[] = {"out of range", "first", "second", + "third", "fourth", "fifth"}; + + //! Returns nth arg as string. 1 -> "first", 2 -> "second", max is 5. + BOOST_DATE_TIME_DECL const char* nth_as_str(int ele) + { + if(ele >= 1 || ele <= 5) { + return _nth_as_str[ele]; + } + else { + return _nth_as_str[0]; + } + } + +} } //namespace date_time + + + + + diff --git a/3rdParty/Boost/libs/date_time/src/gregorian/greg_month.cpp b/3rdParty/Boost/libs/date_time/src/gregorian/greg_month.cpp new file mode 100644 index 0000000..efca973 --- /dev/null +++ b/3rdParty/Boost/libs/date_time/src/gregorian/greg_month.cpp @@ -0,0 +1,173 @@ +/* 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-11-23 06:13:35 -0500 (Sun, 23 Nov 2008) $ + */ + + + +#ifndef BOOST_DATE_TIME_SOURCE +#define BOOST_DATE_TIME_SOURCE +#endif +#include "boost/date_time/gregorian/greg_month.hpp" +#include "boost/date_time/gregorian/greg_facet.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/compiler_config.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 +#include "boost/date_time/date_parsing.hpp" +#include "boost/date_time/gregorian/parsers.hpp" + +#include "greg_names.hpp" +namespace boost { +namespace gregorian { + + /*! Returns a shared pointer to a map of Month strings & numbers. + * Strings are both full names and abbreviations. + * Ex. ("jan",1), ("february",2), etc... + * Note: All characters are lowercase - for case insensitivity + */ + greg_month::month_map_ptr_type greg_month::get_month_map_ptr() + { + static month_map_ptr_type month_map_ptr(new greg_month::month_map_type()); + + if(month_map_ptr->empty()) { + std::string s(""); + for(unsigned short i = 1; i <= 12; ++i) { + greg_month m(static_cast<month_enum>(i)); + s = m.as_long_string(); + s = date_time::convert_to_lower(s); + month_map_ptr->insert(std::make_pair(s, i)); + s = m.as_short_string(); + s = date_time::convert_to_lower(s); + month_map_ptr->insert(std::make_pair(s, i)); + } + } + return month_map_ptr; + } + + + //! Returns 3 char english string for the month ex: Jan, Feb, Mar, Apr + const char* + greg_month::as_short_string() const + { + return short_month_names[value_-1]; + } + + //! Returns full name of month as string in english ex: January, February + const char* + greg_month::as_long_string() const + { + return long_month_names[value_-1]; + } + + //! Return special_value from string argument + /*! Return special_value from string argument. If argument is + * not one of the special value names (defined in names.hpp), + * return 'not_special' */ + special_values special_value_from_string(const std::string& s) { + short i = date_time::find_match(special_value_names, + special_value_names, + date_time::NumSpecialValues, + s); + if(i >= date_time::NumSpecialValues) { // match not found + return not_special; + } + else { + return static_cast<special_values>(i); + } + } + + +#ifndef BOOST_NO_STD_WSTRING + //! Returns 3 wchar_t english string for the month ex: Jan, Feb, Mar, Apr + const wchar_t* + greg_month::as_short_wstring() const + { + return w_short_month_names[value_-1]; + } + + //! Returns full name of month as wchar_t string in english ex: January, February + const wchar_t* + greg_month::as_long_wstring() const + { + return w_long_month_names[value_-1]; + } +#endif // BOOST_NO_STD_WSTRING + +#ifndef BOOST_DATE_TIME_NO_LOCALE + /*! creates an all_date_names_put object with the correct set of names. + * This function is only called in the event of an exception where + * the imbued locale containing the needed facet is for some reason + * unreachable. + */ + BOOST_DATE_TIME_DECL + boost::date_time::all_date_names_put<greg_facet_config, char>* + create_facet_def(char type) + { + typedef + boost::date_time::all_date_names_put<greg_facet_config, char> facet_def; + + return new facet_def(short_month_names, + long_month_names, + special_value_names, + short_weekday_names, + long_weekday_names); + } + + //! 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){ + typedef boost::date_time::all_date_names_put<greg_facet_config, char> facet_def; + return std::locale(loc, new facet_def(short_month_names, + long_month_names, + special_value_names, + short_weekday_names, + long_weekday_names) + ); + } + +#ifndef BOOST_NO_STD_WSTRING + /*! creates an all_date_names_put object with the correct set of names. + * This function is only called in the event of an exception where + * the imbued locale containing the needed facet is for some reason + * unreachable. + */ + BOOST_DATE_TIME_DECL + boost::date_time::all_date_names_put<greg_facet_config, wchar_t>* + create_facet_def(wchar_t type) + { + typedef + boost::date_time::all_date_names_put<greg_facet_config,wchar_t> facet_def; + + return new facet_def(w_short_month_names, + w_long_month_names, + w_special_value_names, + w_short_weekday_names, + w_long_weekday_names); + } + + //! 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){ + typedef boost::date_time::all_date_names_put<greg_facet_config, wchar_t> facet_def; + return std::locale(loc, new facet_def(w_short_month_names, + w_long_month_names, + w_special_value_names, + w_short_weekday_names, + w_long_weekday_names) + ); + } +#endif // BOOST_NO_STD_WSTRING +#endif // BOOST_DATE_TIME_NO_LOCALE + +} } //namespace gregorian + + + + + + diff --git a/3rdParty/Boost/libs/date_time/src/gregorian/greg_names.hpp b/3rdParty/Boost/libs/date_time/src/gregorian/greg_names.hpp new file mode 100644 index 0000000..76a1a24 --- /dev/null +++ b/3rdParty/Boost/libs/date_time/src/gregorian/greg_names.hpp @@ -0,0 +1,43 @@ +/* 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) $ + */ + + + +#ifndef DATE_TIME_SRC_GREG_NAMES_HPP___ +#define DATE_TIME_SRC_GREG_NAMES_HPP___ + +#include "boost/date_time/gregorian/greg_month.hpp" +#include "boost/date_time/special_defs.hpp" +namespace boost { +namespace gregorian { + + + const char* const short_month_names[NumMonths]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec", "NAM"}; + const char* const long_month_names[NumMonths]={"January","February","March","April","May","June","July","August","September","October","November","December","NotAMonth"}; + const char* const special_value_names[date_time::NumSpecialValues]={"not-a-date-time","-infinity","+infinity","min_date_time","max_date_time","not_special"}; + + + const char* const short_weekday_names[]={"Sun", "Mon", "Tue", + "Wed", "Thu", "Fri", "Sat"}; + const char* const long_weekday_names[]= {"Sunday","Monday","Tuesday", + "Wednesday", "Thursday", + "Friday", "Saturday"}; + +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* const w_short_month_names[NumMonths]={L"Jan",L"Feb",L"Mar",L"Apr",L"May",L"Jun",L"Jul",L"Aug",L"Sep",L"Oct",L"Nov",L"Dec",L"NAM"}; + const wchar_t* const w_long_month_names[NumMonths]={L"January",L"February",L"March",L"April",L"May",L"June",L"July",L"August",L"September",L"October",L"November",L"December",L"NotAMonth"}; + const wchar_t* const w_special_value_names[date_time::NumSpecialValues]={L"not-a-date-time",L"-infinity",L"+infinity",L"min_date_time",L"max_date_time",L"not_special"}; + + const wchar_t* const w_short_weekday_names[]={L"Sun", L"Mon", L"Tue", + L"Wed", L"Thu", L"Fri", L"Sat"}; + const wchar_t* const w_long_weekday_names[]= {L"Sunday",L"Monday",L"Tuesday", + L"Wednesday", L"Thursday", + L"Friday", L"Saturday"}; +#endif // BOOST_NO_STD_WSTRING +} } // boost::gregorian +#endif // DATE_TIME_SRC_GREG_NAMES_HPP___ diff --git a/3rdParty/Boost/libs/date_time/src/gregorian/greg_weekday.cpp b/3rdParty/Boost/libs/date_time/src/gregorian/greg_weekday.cpp new file mode 100644 index 0000000..4057d29 --- /dev/null +++ b/3rdParty/Boost/libs/date_time/src/gregorian/greg_weekday.cpp @@ -0,0 +1,50 @@ +/* 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) $ + */ + + + +#ifndef BOOST_DATE_TIME_SOURCE +#define BOOST_DATE_TIME_SOURCE +#endif +#include "boost/date_time/gregorian/greg_weekday.hpp" + +#include "greg_names.hpp" + +namespace boost { +namespace gregorian { + + //! Return a 3 digit english string of the day of week (eg: Sun) + const char* + greg_weekday::as_short_string() const + { + return short_weekday_names[value_]; + } + //! Return a point to a long english string representing day of week + const char* + greg_weekday::as_long_string() const + { + return long_weekday_names[value_]; + } + +#ifndef BOOST_NO_STD_WSTRING + //! Return a 3 digit english wchar_t string of the day of week (eg: Sun) + const wchar_t* + greg_weekday::as_short_wstring() const + { + return w_short_weekday_names[value_]; + } + //! Return a point to a long english wchar_t string representing day of week + const wchar_t* + greg_weekday::as_long_wstring() const + { + return w_long_weekday_names[value_]; + } +#endif // BOOST_NO_STD_WSTRING + +} } //namespace gregorian + diff --git a/3rdParty/Boost/libs/date_time/src/gregorian/gregorian_types.cpp b/3rdParty/Boost/libs/date_time/src/gregorian/gregorian_types.cpp new file mode 100644 index 0000000..a856e79 --- /dev/null +++ b/3rdParty/Boost/libs/date_time/src/gregorian/gregorian_types.cpp @@ -0,0 +1,62 @@ +/* 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) $ + */ + + +/** @defgroup date_basics Date Basics + This page summarizes some of the key user types and functions needed + to write programs using the gregorian date system. This is not a + comprehensive list, but rather some key types to start exploring. + + +**/ + +/** @defgroup date_alg Date Algorithms / Generators + Date algorithms or generators are tools for generating other dates or + schedules of dates. A generator function starts with some part of a + date such as a month and day and is supplied another part to then + generate a final date. + +**/ + +/** @defgroup date_format Date Formatting + The functions on these page are some of the key formatting functions + for dates. +**/ + + +//File doesn't have a current purpose except to generate docs +//and keep it changeable without recompiles +/*! @example days_alive.cpp + Calculate the number of days you have been living using durations and dates. +*/ +/*! @example days_till_new_year.cpp + Calculate the number of days till new years +*/ +/*! @example print_month.cpp + Simple utility to print out days of the month with the days of a month. Demontstrates date iteration (date_time::date_itr). +*/ +/*! @example localization.cpp + An example showing localized stream-based I/O. +*/ +/*! @example dates_as_strings.cpp + Various parsing and output of strings (mostly supported for + compilers that do not support localized streams). +*/ +/*! @example period_calc.cpp + Calculates if a date is in an 'irregular' collection of periods using + period calculation functions. +*/ +/*! @example print_holidays.cpp + This is an example of using functors to define a holiday schedule + */ +/*! @example localization.cpp + Demonstrates the use of facets to localize date output for Gregorian dates. + */ + + + diff --git a/3rdParty/Boost/libs/date_time/src/posix_time/posix_time_types.cpp b/3rdParty/Boost/libs/date_time/src/posix_time/posix_time_types.cpp new file mode 100644 index 0000000..06ef563 --- /dev/null +++ b/3rdParty/Boost/libs/date_time/src/posix_time/posix_time_types.cpp @@ -0,0 +1,35 @@ + +/* 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 + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +//File doesn't have a current purpose except to generate docs +//and keep it changeable without recompiles + +/** @defgroup time_basics Time Basics + +**/ + +/** @defgroup time_format Time Formatting + +**/ + + + +/*! @example local_utc_conversion.cpp + Demonstrate utc to local and local to utc calculations including dst. +*/ +/*! @example time_periods.cpp Demonstrate some simple uses of time periods. +*/ +/*! @example print_hours.cpp Demonstrate time iteration, clock retrieval, and simple calculation. + */ +/*! @example time_math.cpp Various types of calculations with times and time durations. + */ + + + diff --git a/3rdParty/Boost/libs/detail/utf8_codecvt_facet.cpp b/3rdParty/Boost/libs/detail/utf8_codecvt_facet.cpp new file mode 100644 index 0000000..658ab6a --- /dev/null +++ b/3rdParty/Boost/libs/detail/utf8_codecvt_facet.cpp @@ -0,0 +1,269 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// utf8_codecvt_facet.cpp + +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// 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) + +// Please see the comments in <boost/detail/utf8_codecvt_facet.hpp> to +// learn how this file should be used. + +#include <boost/detail/utf8_codecvt_facet.hpp> + +#include <cstdlib> // for multi-byte converson routines +#include <cassert> + +#include <boost/limits.hpp> +#include <boost/config.hpp> + +// If we don't have wstring, then Unicode support +// is not available anyway, so we don't need to even +// compiler this file. This also fixes the problem +// with mingw, which can compile this file, but will +// generate link error when building DLL. +#ifndef BOOST_NO_STD_WSTRING + +BOOST_UTF8_BEGIN_NAMESPACE + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation for wchar_t + +// Translate incoming UTF-8 into UCS-4 +std::codecvt_base::result utf8_codecvt_facet::do_in( + std::mbstate_t& /*state*/, + const char * from, + const char * from_end, + const char * & from_next, + wchar_t * to, + wchar_t * to_end, + wchar_t * & to_next +) const { + // Basic algorithm: The first octet determines how many + // octets total make up the UCS-4 character. The remaining + // "continuing octets" all begin with "10". To convert, subtract + // the amount that specifies the number of octets from the first + // octet. Subtract 0x80 (1000 0000) from each continuing octet, + // then mash the whole lot together. Note that each continuing + // octet only uses 6 bits as unique values, so only shift by + // multiples of 6 to combine. + while (from != from_end && to != to_end) { + + // Error checking on the first octet + if (invalid_leading_octet(*from)){ + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + // The first octet is adjusted by a value dependent upon + // the number of "continuing octets" encoding the character + const int cont_octet_count = get_cont_octet_count(*from); + const wchar_t octet1_modifier_table[] = { + 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc + }; + + // The unsigned char conversion is necessary in case char is + // signed (I learned this the hard way) + wchar_t ucs_result = + (unsigned char)(*from++) - octet1_modifier_table[cont_octet_count]; + + // Invariants : + // 1) At the start of the loop, 'i' continuing characters have been + // processed + // 2) *from points to the next continuing character to be processed. + int i = 0; + while(i != cont_octet_count && from != from_end) { + + // Error checking on continuing characters + if (invalid_continuing_octet(*from)) { + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + ucs_result *= (1 << 6); + + // each continuing character has an extra (10xxxxxx)b attached to + // it that must be removed. + ucs_result += (unsigned char)(*from++) - 0x80; + ++i; + } + + // If the buffer ends with an incomplete unicode character... + if (from == from_end && i != cont_octet_count) { + // rewind "from" to before the current character translation + from_next = from - (i+1); + to_next = to; + return std::codecvt_base::partial; + } + *to++ = ucs_result; + } + from_next = from; + to_next = to; + + // Were we done converting or did we run out of destination space? + if(from == from_end) return std::codecvt_base::ok; + else return std::codecvt_base::partial; +} + +std::codecvt_base::result utf8_codecvt_facet::do_out( + std::mbstate_t& /*state*/, + const wchar_t * from, + const wchar_t * from_end, + const wchar_t * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + // RG - consider merging this table with the other one + const wchar_t octet1_modifier_table[] = { + 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc + }; + + wchar_t max_wchar = (std::numeric_limits<wchar_t>::max)(); + while (from != from_end && to != to_end) { + + // Check for invalid UCS-4 character + if (*from > max_wchar) { + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + int cont_octet_count = get_cont_octet_out_count(*from); + + // RG - comment this formula better + int shift_exponent = (cont_octet_count) * 6; + + // Process the first character + *to++ = static_cast<char>(octet1_modifier_table[cont_octet_count] + + (unsigned char)(*from / (1 << shift_exponent))); + + // Process the continuation characters + // Invariants: At the start of the loop: + // 1) 'i' continuing octets have been generated + // 2) '*to' points to the next location to place an octet + // 3) shift_exponent is 6 more than needed for the next octet + int i = 0; + while (i != cont_octet_count && to != to_end) { + shift_exponent -= 6; + *to++ = static_cast<char>(0x80 + ((*from / (1 << shift_exponent)) % (1 << 6))); + ++i; + } + // If we filled up the out buffer before encoding the character + if(to == to_end && i != cont_octet_count) { + from_next = from; + to_next = to - (i+1); + return std::codecvt_base::partial; + } + *from++; + } + from_next = from; + to_next = to; + // Were we done or did we run out of destination space + if(from == from_end) return std::codecvt_base::ok; + else return std::codecvt_base::partial; +} + +// How many char objects can I process to get <= max_limit +// wchar_t objects? +int utf8_codecvt_facet::do_length( + BOOST_CODECVT_DO_LENGTH_CONST std::mbstate_t &, + const char * from, + const char * from_end, + std::size_t max_limit +#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) +) const throw() +#else +) const +#endif +{ + // RG - this code is confusing! I need a better way to express it. + // and test cases. + + // Invariants: + // 1) last_octet_count has the size of the last measured character + // 2) char_count holds the number of characters shown to fit + // within the bounds so far (no greater than max_limit) + // 3) from_next points to the octet 'last_octet_count' before the + // last measured character. + int last_octet_count=0; + std::size_t char_count = 0; + const char* from_next = from; + // Use "<" because the buffer may represent incomplete characters + while (from_next+last_octet_count <= from_end && char_count <= max_limit) { + from_next += last_octet_count; + last_octet_count = (get_octet_count(*from_next)); + ++char_count; + } + return static_cast<int>(from_next-from_end); +} + +unsigned int utf8_codecvt_facet::get_octet_count( + unsigned char lead_octet +){ + // if the 0-bit (MSB) is 0, then 1 character + if (lead_octet <= 0x7f) return 1; + + // Otherwise the count number of consecutive 1 bits starting at MSB +// assert(0xc0 <= lead_octet && lead_octet <= 0xfd); + + if (0xc0 <= lead_octet && lead_octet <= 0xdf) return 2; + else if (0xe0 <= lead_octet && lead_octet <= 0xef) return 3; + else if (0xf0 <= lead_octet && lead_octet <= 0xf7) return 4; + else if (0xf8 <= lead_octet && lead_octet <= 0xfb) return 5; + else return 6; +} +BOOST_UTF8_END_NAMESPACE + +namespace { +template<std::size_t s> +int get_cont_octet_out_count_impl(wchar_t word){ + if (word < 0x80) { + return 0; + } + if (word < 0x800) { + return 1; + } + return 2; +} + +// note the following code will generate on some platforms where +// wchar_t is defined as UCS2. The warnings are superfluous as +// the specialization is never instantitiated with such compilers. +template<> +int get_cont_octet_out_count_impl<4>(wchar_t word){ + if (word < 0x80) { + return 0; + } + if (word < 0x800) { + return 1; + } + if (word < 0x10000) { + return 2; + } + if (word < 0x200000) { + return 3; + } + if (word < 0x4000000) { + return 4; + } + return 5; +} + +} // namespace anonymous + +BOOST_UTF8_BEGIN_NAMESPACE +// How many "continuing octets" will be needed for this word +// == total octets - 1. +int utf8_codecvt_facet::get_cont_octet_out_count( + wchar_t word +) const { + return get_cont_octet_out_count_impl<sizeof(wchar_t)>(word); +} +BOOST_UTF8_END_NAMESPACE + +#endif diff --git a/3rdParty/Boost/libs/filesystem/src/operations.cpp b/3rdParty/Boost/libs/filesystem/src/operations.cpp new file mode 100644 index 0000000..0c74504 --- /dev/null +++ b/3rdParty/Boost/libs/filesystem/src/operations.cpp @@ -0,0 +1,1367 @@ +// operations.cpp ----------------------------------------------------------// + +// Copyright 2002-2005 Beman Dawes +// Copyright 2001 Dietmar Kuehl +// 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 library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_FILESYSTEM_SOURCE + +#define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r() needs this + +// enable the XPG-compliant version of readdir_r() on AIX +#if defined(_AIX) +# define _LINUX_SOURCE_COMPAT +#endif + +#if !(defined(__HP_aCC) && defined(_ILP32) && \ + !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) +#define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, +#endif +#define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX + // 64-bit systems or on 32-bit systems which don't have files larger + // than can be represented by a traditional POSIX/UNIX off_t type. + // OTOH, defining them should kick in 64-bit off_t's (and thus + // st_size) on 32-bit systems that provide the Large File + // Support (LFS) interface, such as Linux, Solaris, and IRIX. + // The defines are given before any headers are included to + // ensure that they are available to all included headers. + // That is required at least on Solaris, and possibly on other + // systems as well. + +// for some compilers (CodeWarrior, for example), windows.h +// is getting included by some other boost header, so do this early: +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0500 // Default to Windows 2K or later +#endif + + +#include <boost/filesystem/operations.hpp> +#include <boost/scoped_array.hpp> +#include <boost/throw_exception.hpp> +#include <boost/detail/workaround.hpp> + +namespace fs = boost::filesystem; +using boost::system::error_code; +using boost::system::system_category; + +# if defined(BOOST_WINDOWS_API) +# include <windows.h> +# if defined(__BORLANDC__) || defined(__MWERKS__) +# if defined(__BORLANDC__) + using std::time_t; +# endif +# include <utime.h> +# else +# include <sys/utime.h> +# endif + +# else // BOOST_POSIX_API +# include <sys/types.h> +# if !defined(__APPLE__) && !defined(__OpenBSD__) +# include <sys/statvfs.h> +# define BOOST_STATVFS statvfs +# define BOOST_STATVFS_F_FRSIZE vfs.f_frsize +# else +#ifdef __OpenBSD__ +# include <sys/param.h> +#endif +# include <sys/mount.h> +# define BOOST_STATVFS statfs +# define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>( vfs.f_bsize ) +# endif +# include <dirent.h> +# include <unistd.h> +# include <fcntl.h> +# include <utime.h> +# include "limits.h" +# endif + +// BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in +// dir_itr_increment. The config tests are placed here because some of the +// macros being tested come from dirent.h. +// +// TODO: find out what macros indicate dirent::d_type present in more libraries +# if defined(BOOST_WINDOWS_API) \ + || (defined(_DIRENT_HAVE_D_TYPE) /* defined by GNU C library if d_type present */ \ + && !(defined(__SUNPRO_CC) && !defined(__sun))) // _DIRENT_HAVE_D_TYPE wrong for Sun compiler on Linux +# define BOOST_FILESYSTEM_STATUS_CACHE +# endif + +#include <sys/stat.h> // even on Windows some functions use stat() +#include <string> +#include <cstring> +#include <cstdio> // for remove, rename +#include <cerrno> +#include <cassert> +// #include <iostream> // for debugging only; comment out when not in use + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::strcmp; using ::remove; using ::rename; } +#endif + +// helpers -----------------------------------------------------------------// + +namespace +{ + const error_code ok; + + bool is_empty_directory( const std::string & dir_path ) + { + static const fs::directory_iterator end_itr; + return fs::directory_iterator(fs::path(dir_path)) == end_itr; + } + +#ifdef BOOST_WINDOWS_API + +// For Windows, the xxxA form of various function names is used to avoid +// inadvertently getting wide forms of the functions. (The undecorated +// forms are actually macros, so can misfire if the user has various +// other macros defined. There was a bug report of this happening.) + + inline DWORD get_file_attributes( const char * ph ) + { return ::GetFileAttributesA( ph ); } + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + inline DWORD get_file_attributes( const wchar_t * ph ) + { return ::GetFileAttributesW( ph ); } + + bool is_empty_directory( const std::wstring & dir_path ) + { + static const fs::wdirectory_iterator wend_itr; + return fs::wdirectory_iterator(fs::wpath(dir_path)) == wend_itr; + } + + inline BOOL get_file_attributes_ex( const wchar_t * ph, + WIN32_FILE_ATTRIBUTE_DATA & fad ) + { return ::GetFileAttributesExW( ph, ::GetFileExInfoStandard, &fad ); } + + HANDLE create_file( const wchar_t * ph, DWORD dwDesiredAccess, + DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile ) + { + return ::CreateFileW( ph, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile ); + } + + inline DWORD get_current_directory( DWORD sz, wchar_t * buf ) + { return ::GetCurrentDirectoryW( sz, buf ); } + + inline bool set_current_directory( const wchar_t * buf ) + { return ::SetCurrentDirectoryW( buf ) != 0 ; } + + inline bool get_free_disk_space( const std::wstring & ph, + PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free ) + { return ::GetDiskFreeSpaceExW( ph.c_str(), avail, total, free ) != 0; } + + inline std::size_t get_full_path_name( + const std::wstring & ph, std::size_t len, wchar_t * buf, wchar_t ** p ) + { + return static_cast<std::size_t>( + ::GetFullPathNameW( ph.c_str(), + static_cast<DWORD>(len), buf, p )); + } + + inline bool remove_directory( const std::wstring & ph ) + { return ::RemoveDirectoryW( ph.c_str() ) != 0; } + + inline bool delete_file( const std::wstring & ph ) + { return ::DeleteFileW( ph.c_str() ) != 0; } + + inline bool create_directory( const std::wstring & dir ) + { return ::CreateDirectoryW( dir.c_str(), 0 ) != 0; } + +#if _WIN32_WINNT >= 0x500 + inline bool create_hard_link( const std::wstring & to_ph, + const std::wstring & from_ph ) + { return ::CreateHardLinkW( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; } +#endif + +# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY + + template< class String > + fs::file_status status_template( const String & ph, error_code & ec ) + { + DWORD attr( get_file_attributes( ph.c_str() ) ); + if ( attr == 0xFFFFFFFF ) + { + ec = error_code( ::GetLastError(), system_category ); + if ((ec.value() == ERROR_FILE_NOT_FOUND) + || (ec.value() == ERROR_PATH_NOT_FOUND) + || (ec.value() == ERROR_INVALID_NAME) // "tools/jam/src/:sys:stat.h", "//foo" + || (ec.value() == ERROR_INVALID_DRIVE) // USB card reader with no card inserted + || (ec.value() == ERROR_INVALID_PARAMETER) // ":sys:stat.h" + || (ec.value() == ERROR_BAD_PATHNAME) // "//nosuch" on Win64 + || (ec.value() == ERROR_BAD_NETPATH)) // "//nosuch" on Win32 + { + ec = ok; // these are not considered errors; + // the status is considered not found + return fs::file_status( fs::file_not_found ); + } + else if ((ec.value() == ERROR_SHARING_VIOLATION)) + { + ec = ok; // these are not considered errors; + // the file exists but the type is not known + return fs::file_status( fs::type_unknown ); + } + return fs::file_status( fs::status_unknown ); + } + ec = ok;; + return (attr & FILE_ATTRIBUTE_DIRECTORY) + ? fs::file_status( fs::directory_file ) + : fs::file_status( fs::regular_file ); + } + + BOOL get_file_attributes_ex( const char * ph, + WIN32_FILE_ATTRIBUTE_DATA & fad ) + { return ::GetFileAttributesExA( ph, ::GetFileExInfoStandard, &fad ); } + + template< class String > + boost::filesystem::detail::query_pair + is_empty_template( const String & ph ) + { + WIN32_FILE_ATTRIBUTE_DATA fad; + if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) + return std::make_pair( error_code( ::GetLastError(), system_category ), false ); + return std::make_pair( ok, + ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + ? is_empty_directory( ph ) + :( !fad.nFileSizeHigh && !fad.nFileSizeLow ) ); + } + + HANDLE create_file( const char * ph, DWORD dwDesiredAccess, + DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile ) + { + return ::CreateFileA( ph, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile ); + } + + // Thanks to Jeremy Maitin-Shepard for much help and for permission to + // base the equivalent() implementation on portions of his + // file-equivalence-win32.cpp experimental code. + struct handle_wrapper + { + HANDLE handle; + handle_wrapper( HANDLE h ) + : handle(h) {} + ~handle_wrapper() + { + if ( handle != INVALID_HANDLE_VALUE ) + ::CloseHandle(handle); + } + }; + + template< class String > + boost::filesystem::detail::query_pair + equivalent_template( const String & ph1, const String & ph2 ) + { + // Note well: Physical location on external media is part of the + // equivalence criteria. If there are no open handles, physical location + // can change due to defragmentation or other relocations. Thus handles + // must be held open until location information for both paths has + // been retrieved. + handle_wrapper p1( + create_file( + ph1.c_str(), + 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0 ) ); + int error1(0); // save error code in case we have to throw + if ( p1.handle == INVALID_HANDLE_VALUE ) + error1 = ::GetLastError(); + handle_wrapper p2( + create_file( + ph2.c_str(), + 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0 ) ); + if ( p1.handle == INVALID_HANDLE_VALUE + || p2.handle == INVALID_HANDLE_VALUE ) + { + if ( p1.handle != INVALID_HANDLE_VALUE + || p2.handle != INVALID_HANDLE_VALUE ) + { return std::make_pair( ok, false ); } + assert( p1.handle == INVALID_HANDLE_VALUE + && p2.handle == INVALID_HANDLE_VALUE ); + { return std::make_pair( error_code( error1, system_category), false ); } + } + // at this point, both handles are known to be valid + BY_HANDLE_FILE_INFORMATION info1, info2; + if ( !::GetFileInformationByHandle( p1.handle, &info1 ) ) + { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } + if ( !::GetFileInformationByHandle( p2.handle, &info2 ) ) + { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } + // In theory, volume serial numbers are sufficient to distinguish between + // devices, but in practice VSN's are sometimes duplicated, so last write + // time and file size are also checked. + return std::make_pair( ok, + info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow + && info1.nFileSizeHigh == info2.nFileSizeHigh + && info1.nFileSizeLow == info2.nFileSizeLow + && info1.ftLastWriteTime.dwLowDateTime + == info2.ftLastWriteTime.dwLowDateTime + && info1.ftLastWriteTime.dwHighDateTime + == info2.ftLastWriteTime.dwHighDateTime ); + } + + template< class String > + boost::filesystem::detail::uintmax_pair + file_size_template( const String & ph ) + { + WIN32_FILE_ATTRIBUTE_DATA fad; + // by now, intmax_t is 64-bits on all Windows compilers + if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) + return std::make_pair( error_code( ::GetLastError(), system_category ), 0 ); + if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) + return std::make_pair( error_code( ERROR_FILE_NOT_FOUND, system_category), 0 ); + return std::make_pair( ok, + (static_cast<boost::uintmax_t>(fad.nFileSizeHigh) + << (sizeof(fad.nFileSizeLow)*8)) + + fad.nFileSizeLow ); + } + + inline bool get_free_disk_space( const std::string & ph, + PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free ) + { return ::GetDiskFreeSpaceExA( ph.c_str(), avail, total, free ) != 0; } + + template< class String > + boost::filesystem::detail::space_pair + space_template( String & ph ) + { + ULARGE_INTEGER avail, total, free; + boost::filesystem::detail::space_pair result; + if ( get_free_disk_space( ph, &avail, &total, &free ) ) + { + result.first = ok; + result.second.capacity + = (static_cast<boost::uintmax_t>(total.HighPart) << 32) + + total.LowPart; + result.second.free + = (static_cast<boost::uintmax_t>(free.HighPart) << 32) + + free.LowPart; + result.second.available + = (static_cast<boost::uintmax_t>(avail.HighPart) << 32) + + avail.LowPart; + } + else + { + result.first = error_code( ::GetLastError(), system_category ); + result.second.capacity = result.second.free + = result.second.available = 0; + } + return result; + } + + inline DWORD get_current_directory( DWORD sz, char * buf ) + { return ::GetCurrentDirectoryA( sz, buf ); } + + template< class String > + error_code + get_current_path_template( String & ph ) + { + DWORD sz; + if ( (sz = get_current_directory( 0, + static_cast<typename String::value_type*>(0) )) == 0 ) + { sz = 1; } + typedef typename String::value_type value_type; + boost::scoped_array<value_type> buf( new value_type[sz] ); + if ( get_current_directory( sz, buf.get() ) == 0 ) + return error_code( ::GetLastError(), system_category ); + ph = buf.get(); + return ok; + } + + inline bool set_current_directory( const char * buf ) + { return ::SetCurrentDirectoryA( buf ) != 0; } + + template< class String > + error_code + set_current_path_template( const String & ph ) + { + return error_code( set_current_directory( ph.c_str() ) + ? 0 : ::GetLastError(), system_category ); + } + + inline std::size_t get_full_path_name( + const std::string & ph, std::size_t len, char * buf, char ** p ) + { + return static_cast<std::size_t>( + ::GetFullPathNameA( ph.c_str(), + static_cast<DWORD>(len), buf, p )); + } + + const std::size_t buf_size( 128 ); + + template<class String> + error_code + get_full_path_name_template( const String & ph, String & target ) + { + typename String::value_type buf[buf_size]; + typename String::value_type * pfn; + std::size_t len = get_full_path_name( ph, + buf_size , buf, &pfn ); + if ( len == 0 ) return error_code( ::GetLastError(), system_category ); + if ( len > buf_size ) + { + typedef typename String::value_type value_type; + boost::scoped_array<value_type> big_buf( new value_type[len] ); + if ( (len=get_full_path_name( ph, len , big_buf.get(), &pfn )) + == 0 ) return error_code( ::GetLastError(), system_category ); + big_buf[len] = '\0'; + target = big_buf.get(); + return ok; + } + buf[len] = '\0'; + target = buf; + return ok; + } + + template<class String> + error_code + get_file_write_time( const String & ph, FILETIME & last_write_time ) + { + handle_wrapper hw( + create_file( ph.c_str(), 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) ); + if ( hw.handle == INVALID_HANDLE_VALUE ) + return error_code( ::GetLastError(), system_category ); + return error_code( ::GetFileTime( hw.handle, 0, 0, &last_write_time ) != 0 + ? 0 : ::GetLastError(), system_category ); + } + + template<class String> + error_code + set_file_write_time( const String & ph, const FILETIME & last_write_time ) + { + handle_wrapper hw( + create_file( ph.c_str(), FILE_WRITE_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) ); + if ( hw.handle == INVALID_HANDLE_VALUE ) + return error_code( ::GetLastError(), system_category ); + return error_code( ::SetFileTime( hw.handle, 0, 0, &last_write_time ) != 0 + ? 0 : ::GetLastError(), system_category ); + } + + // these constants come from inspecting some Microsoft sample code + std::time_t to_time_t( const FILETIME & ft ) + { + __int64 t = (static_cast<__int64>( ft.dwHighDateTime ) << 32) + + ft.dwLowDateTime; +# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0 + t -= 116444736000000000LL; +# else + t -= 116444736000000000; +# endif + t /= 10000000; + return static_cast<std::time_t>( t ); + } + + void to_FILETIME( std::time_t t, FILETIME & ft ) + { + __int64 temp = t; + temp *= 10000000; +# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0 + temp += 116444736000000000LL; +# else + temp += 116444736000000000; +# endif + ft.dwLowDateTime = static_cast<DWORD>( temp ); + ft.dwHighDateTime = static_cast<DWORD>( temp >> 32 ); + } + + template<class String> + boost::filesystem::detail::time_pair + last_write_time_template( const String & ph ) + { + FILETIME lwt; + error_code ec( + get_file_write_time( ph, lwt ) ); + return std::make_pair( ec, to_time_t( lwt ) ); + } + + template<class String> + error_code + last_write_time_template( const String & ph, const std::time_t new_time ) + { + FILETIME lwt; + to_FILETIME( new_time, lwt ); + return set_file_write_time( ph, lwt ); + } + + bool remove_directory( const std::string & ph ) + { return ::RemoveDirectoryA( ph.c_str() ) != 0; } + + bool delete_file( const std::string & ph ) + { return ::DeleteFileA( ph.c_str() ) != 0; } + + template<class String> + error_code + remove_template( const String & ph ) + { + // TODO: test this code in the presence of Vista symlinks, + // including dangling, self-referal, and cyclic symlinks + error_code ec; + fs::file_status sf( fs::detail::status_api( ph, ec ) ); + if ( ec ) + return ec; + if ( sf.type() == fs::file_not_found ) + return ok; + if ( fs::is_directory( sf ) ) + { + if ( !remove_directory( ph ) ) + return error_code(::GetLastError(), system_category); + } + else + { + if ( !delete_file( ph ) ) return error_code(::GetLastError(), system_category); + } + return ok; + } + + inline bool create_directory( const std::string & dir ) + { return ::CreateDirectoryA( dir.c_str(), 0 ) != 0; } + + template<class String> + boost::filesystem::detail::query_pair + create_directory_template( const String & dir_ph ) + { + error_code error, dummy; + if ( create_directory( dir_ph ) ) return std::make_pair( error, true ); + error = error_code( ::GetLastError(), system_category ); + // an error here may simply mean the postcondition is already met + if ( error.value() == ERROR_ALREADY_EXISTS + && fs::is_directory( fs::detail::status_api( dir_ph, dummy ) ) ) + return std::make_pair( ok, false ); + return std::make_pair( error, false ); + } + +#if _WIN32_WINNT >= 0x500 + inline bool create_hard_link( const std::string & to_ph, + const std::string & from_ph ) + { return ::CreateHardLinkA( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; } +#endif + +#if _WIN32_WINNT >= 0x500 + template<class String> + error_code + create_hard_link_template( const String & to_ph, + const String & from_ph ) + { + return error_code( create_hard_link( to_ph.c_str(), from_ph.c_str() ) + ? 0 : ::GetLastError(), system_category ); + } +#endif + +#else // BOOST_POSIX_API + + int posix_remove( const char * p ) + { +# if defined(__QNXNTO__) || (defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))) + // Some Metrowerks C library versions fail on directories because of a + // known Metrowerks coding error in ::remove. Workaround is to call + // rmdir() or unlink() as indicated. + // Same bug also reported for QNX, with the same fix. + int err = ::unlink( p ); + if ( err == 0 || errno != EPERM ) + return err; + return ::rmdir( p ); +# else + return std::remove( p ); +# endif + } + +#endif +} // unnamed namespace + +namespace boost +{ + namespace filesystem + { + namespace detail + { + BOOST_FILESYSTEM_DECL system::error_code throws; + +// free functions ----------------------------------------------------------// + + BOOST_FILESYSTEM_DECL error_code not_found_error() + { +# ifdef BOOST_WINDOWS_API + return error_code(ERROR_PATH_NOT_FOUND, system_category); +# else + return error_code(ENOENT, system_category); +# endif + } + + BOOST_FILESYSTEM_DECL bool possible_large_file_size_support() + { +# ifdef BOOST_POSIX_API + struct stat lcl_stat; + return sizeof( lcl_stat.st_size ) > 4; +# else + return true; +# endif + } + +# ifdef BOOST_WINDOWS_API + + BOOST_FILESYSTEM_DECL fs::file_status + status_api( const std::string & ph, error_code & ec ) + { return status_template( ph, ec ); } + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + BOOST_FILESYSTEM_DECL fs::file_status + status_api( const std::wstring & ph, error_code & ec ) + { return status_template( ph, ec ); } + + BOOST_FILESYSTEM_DECL bool symbolic_link_exists_api( const std::wstring & ) + { return false; } + + BOOST_FILESYSTEM_DECL + fs::detail::query_pair is_empty_api( const std::wstring & ph ) + { return is_empty_template( ph ); } + + BOOST_FILESYSTEM_DECL + fs::detail::query_pair + equivalent_api( const std::wstring & ph1, const std::wstring & ph2 ) + { return equivalent_template( ph1, ph2 ); } + + BOOST_FILESYSTEM_DECL + fs::detail::uintmax_pair file_size_api( const std::wstring & ph ) + { return file_size_template( ph ); } + + BOOST_FILESYSTEM_DECL + fs::detail::space_pair space_api( const std::wstring & ph ) + { return space_template( ph ); } + + BOOST_FILESYSTEM_DECL + error_code + get_current_path_api( std::wstring & ph ) + { return get_current_path_template( ph ); } + + BOOST_FILESYSTEM_DECL + error_code + set_current_path_api( const std::wstring & ph ) + { return set_current_path_template( ph ); } + + BOOST_FILESYSTEM_DECL error_code + get_full_path_name_api( const std::wstring & ph, std::wstring & target ) + { return get_full_path_name_template( ph, target ); } + + BOOST_FILESYSTEM_DECL time_pair + last_write_time_api( const std::wstring & ph ) + { return last_write_time_template( ph ); } + + BOOST_FILESYSTEM_DECL error_code + last_write_time_api( const std::wstring & ph, std::time_t new_value ) + { return last_write_time_template( ph, new_value ); } + + BOOST_FILESYSTEM_DECL fs::detail::query_pair + create_directory_api( const std::wstring & ph ) + { return create_directory_template( ph ); } + +#if _WIN32_WINNT >= 0x500 + BOOST_FILESYSTEM_DECL error_code + create_hard_link_api( const std::wstring & to_ph, + const std::wstring & from_ph ) + { return create_hard_link_template( to_ph, from_ph ); } +#endif + + BOOST_FILESYSTEM_DECL error_code + create_symlink_api( const std::wstring & /*to_ph*/, + const std::wstring & /*from_ph*/ ) + { return error_code( ERROR_NOT_SUPPORTED, system_category ); } + + BOOST_FILESYSTEM_DECL error_code + remove_api( const std::wstring & ph ) { return remove_template( ph ); } + + BOOST_FILESYSTEM_DECL error_code + rename_api( const std::wstring & from, const std::wstring & to ) + { + return error_code( ::MoveFileW( from.c_str(), to.c_str() ) + ? 0 : ::GetLastError(), system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + copy_file_api( const std::wstring & from, const std::wstring & to ) + { + return error_code( ::CopyFileW( from.c_str(), to.c_str(), /*fail_if_exists=*/true ) + ? 0 : ::GetLastError(), system_category ); + } + + BOOST_FILESYSTEM_DECL bool create_file_api( const std::wstring & ph, + std::ios_base::openmode mode ) // true if succeeds + { + DWORD access( + ((mode & std::ios_base::in) == 0 ? 0 : GENERIC_READ) + | ((mode & std::ios_base::out) == 0 ? 0 : GENERIC_WRITE) ); + + DWORD disposition(0); // see 27.8.1.3 Table 92 + if ( (mode&~std::ios_base::binary) + == (std::ios_base::out|std::ios_base::app) ) + disposition = OPEN_ALWAYS; + else if ( (mode&~(std::ios_base::binary|std::ios_base::out)) + == std::ios_base::in ) disposition = OPEN_EXISTING; + else if ( ((mode&~(std::ios_base::binary|std::ios_base::trunc)) + == std::ios_base::out ) + || ((mode&~std::ios_base::binary) + == (std::ios_base::in|std::ios_base::out|std::ios_base::trunc)) ) + disposition = CREATE_ALWAYS; + else assert( 0 && "invalid mode argument" ); + + HANDLE handle ( ::CreateFileW( ph.c_str(), access, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + disposition, (mode &std::ios_base::out) != 0 + ? FILE_ATTRIBUTE_ARCHIVE : FILE_ATTRIBUTE_NORMAL, 0 ) ); + if ( handle == INVALID_HANDLE_VALUE ) return false; + ::CloseHandle( handle ); + return true; + } + + BOOST_FILESYSTEM_DECL std::string narrow_path_api( + const std::wstring & ph ) // return is empty if fails + { + std::string narrow_short_form; + std::wstring short_form; + for ( DWORD buf_sz( static_cast<DWORD>( ph.size()+1 ));; ) + { + boost::scoped_array<wchar_t> buf( new wchar_t[buf_sz] ); + DWORD sz( ::GetShortPathNameW( ph.c_str(), buf.get(), buf_sz ) ); + if ( sz == 0 ) return narrow_short_form; + if ( sz <= buf_sz ) + { + short_form += buf.get(); + break; + } + buf_sz = sz + 1; + } + // contributed by Takeshi Mouri: + int narrow_sz( ::WideCharToMultiByte( CP_ACP, 0, + short_form.c_str(), static_cast<int>(short_form.size()), 0, 0, 0, 0 ) ); + boost::scoped_array<char> narrow_buf( new char[narrow_sz] ); + ::WideCharToMultiByte( CP_ACP, 0, + short_form.c_str(), static_cast<int>(short_form.size()), + narrow_buf.get(), narrow_sz, 0, 0 ); + narrow_short_form.assign(narrow_buf.get(), narrow_sz); + + return narrow_short_form; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_first( void *& handle, const std::wstring & dir, + std::wstring & target, file_status & sf, file_status & symlink_sf ) + { + // use a form of search Sebastian Martel reports will work with Win98 + std::wstring dirpath( dir ); + dirpath += (dirpath.empty() + || dirpath[dirpath.size()-1] != L'\\') ? L"\\*" : L"*"; + + WIN32_FIND_DATAW data; + if ( (handle = ::FindFirstFileW( dirpath.c_str(), &data )) + == INVALID_HANDLE_VALUE ) + { + handle = 0; + return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND + ? 0 : ::GetLastError(), system_category ); + } + target = data.cFileName; + if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + { sf.type( directory_file ); symlink_sf.type( directory_file ); } + else { sf.type( regular_file ); symlink_sf.type( regular_file ); } + return ok; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_increment( void *& handle, std::wstring & target, + file_status & sf, file_status & symlink_sf ) + { + WIN32_FIND_DATAW data; + if ( ::FindNextFileW( handle, &data ) == 0 ) // fails + { + int error = ::GetLastError(); + dir_itr_close( handle ); + return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, system_category ); + } + target = data.cFileName; + if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + { sf.type( directory_file ); symlink_sf.type( directory_file ); } + else { sf.type( regular_file ); symlink_sf.type( regular_file ); } + return ok; + } + +# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY + + // suggested by Walter Landry + BOOST_FILESYSTEM_DECL bool symbolic_link_exists_api( const std::string & ) + { return false; } + + BOOST_FILESYSTEM_DECL + fs::detail::query_pair is_empty_api( const std::string & ph ) + { return is_empty_template( ph ); } + + BOOST_FILESYSTEM_DECL + fs::detail::query_pair + equivalent_api( const std::string & ph1, const std::string & ph2 ) + { return equivalent_template( ph1, ph2 ); } + + BOOST_FILESYSTEM_DECL + fs::detail::uintmax_pair file_size_api( const std::string & ph ) + { return file_size_template( ph ); } + + BOOST_FILESYSTEM_DECL + fs::detail::space_pair space_api( const std::string & ph ) + { return space_template( ph ); } + + BOOST_FILESYSTEM_DECL + error_code + get_current_path_api( std::string & ph ) + { return get_current_path_template( ph ); } + + BOOST_FILESYSTEM_DECL + error_code + set_current_path_api( const std::string & ph ) + { return set_current_path_template( ph ); } + + BOOST_FILESYSTEM_DECL error_code + get_full_path_name_api( const std::string & ph, std::string & target ) + { return get_full_path_name_template( ph, target ); } + + BOOST_FILESYSTEM_DECL time_pair + last_write_time_api( const std::string & ph ) + { return last_write_time_template( ph ); } + + BOOST_FILESYSTEM_DECL error_code + last_write_time_api( const std::string & ph, std::time_t new_value ) + { return last_write_time_template( ph, new_value ); } + + BOOST_FILESYSTEM_DECL fs::detail::query_pair + create_directory_api( const std::string & ph ) + { return create_directory_template( ph ); } + +#if _WIN32_WINNT >= 0x500 + BOOST_FILESYSTEM_DECL error_code + create_hard_link_api( const std::string & to_ph, + const std::string & from_ph ) + { + return create_hard_link_template( to_ph, from_ph ); + } +#endif + + BOOST_FILESYSTEM_DECL error_code + create_symlink_api( const std::string & /*to_ph*/, + const std::string & /*from_ph*/ ) + { return error_code( ERROR_NOT_SUPPORTED, system_category ); } + + BOOST_FILESYSTEM_DECL error_code + remove_api( const std::string & ph ) { return remove_template( ph ); } + + BOOST_FILESYSTEM_DECL error_code + rename_api( const std::string & from, const std::string & to ) + { + return error_code( ::MoveFileA( from.c_str(), to.c_str() ) + ? 0 : ::GetLastError(), system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + copy_file_api( const std::string & from, const std::string & to ) + { + return error_code( ::CopyFileA( from.c_str(), to.c_str(), /*fail_if_exists=*/true ) + ? 0 : ::GetLastError(), system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_first( void *& handle, const std::string & dir, + std::string & target, file_status & sf, file_status & symlink_sf ) + // Note: an empty root directory has no "." or ".." entries, so this + // causes a ERROR_FILE_NOT_FOUND error which we do not considered an + // error. It is treated as eof instead. + { + // use a form of search Sebastian Martel reports will work with Win98 + std::string dirpath( dir ); + dirpath += (dirpath.empty() + || (dirpath[dirpath.size()-1] != '\\' + && dirpath[dirpath.size()-1] != ':')) ? "\\*" : "*"; + + WIN32_FIND_DATAA data; + if ( (handle = ::FindFirstFileA( dirpath.c_str(), &data )) + == INVALID_HANDLE_VALUE ) + { + handle = 0; + return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND + ? 0 : ::GetLastError(), system_category ); + } + target = data.cFileName; + if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + { sf.type( directory_file ); symlink_sf.type( directory_file ); } + else { sf.type( regular_file ); symlink_sf.type( regular_file ); } + return ok; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_close( void *& handle ) + { + if ( handle != 0 ) + { + bool ok = ::FindClose( handle ) != 0; + handle = 0; + return error_code( ok ? 0 : ::GetLastError(), system_category ); + } + return ok; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_increment( void *& handle, std::string & target, + file_status & sf, file_status & symlink_sf ) + { + WIN32_FIND_DATAA data; + if ( ::FindNextFileA( handle, &data ) == 0 ) // fails + { + int error = ::GetLastError(); + dir_itr_close( handle ); + return error_code( error == ERROR_NO_MORE_FILES ? 0 : error, system_category ); + } + target = data.cFileName; + if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + { sf.type( directory_file ); symlink_sf.type( directory_file ); } + else { sf.type( regular_file ); symlink_sf.type( regular_file ); } + return ok; + } + +# else // BOOST_POSIX_API + + BOOST_FILESYSTEM_DECL fs::file_status + status_api( const std::string & ph, error_code & ec ) + { + struct stat path_stat; + if ( ::stat( ph.c_str(), &path_stat ) != 0 ) + { + if ( errno == ENOENT || errno == ENOTDIR ) + { + ec = ok; + return fs::file_status( fs::file_not_found ); + } + ec = error_code( errno, system_category ); + return fs::file_status( fs::status_unknown ); + } + ec = ok; + if ( S_ISDIR( path_stat.st_mode ) ) + return fs::file_status( fs::directory_file ); + if ( S_ISREG( path_stat.st_mode ) ) + return fs::file_status( fs::regular_file ); + if ( S_ISBLK( path_stat.st_mode ) ) + return fs::file_status( fs::block_file ); + if ( S_ISCHR( path_stat.st_mode ) ) + return fs::file_status( fs::character_file ); + if ( S_ISFIFO( path_stat.st_mode ) ) + return fs::file_status( fs::fifo_file ); + if ( S_ISSOCK( path_stat.st_mode ) ) + return fs::file_status( fs::socket_file ); + return fs::file_status( fs::type_unknown ); + } + + BOOST_FILESYSTEM_DECL fs::file_status + symlink_status_api( const std::string & ph, error_code & ec ) + { + struct stat path_stat; + if ( ::lstat( ph.c_str(), &path_stat ) != 0 ) + { + if ( errno == ENOENT || errno == ENOTDIR ) + { + ec = ok; + return fs::file_status( fs::file_not_found ); + } + ec = error_code( errno, system_category ); + return fs::file_status( fs::status_unknown ); + } + ec = ok; + if ( S_ISREG( path_stat.st_mode ) ) + return fs::file_status( fs::regular_file ); + if ( S_ISDIR( path_stat.st_mode ) ) + return fs::file_status( fs::directory_file ); + if ( S_ISLNK( path_stat.st_mode ) ) + return fs::file_status( fs::symlink_file ); + if ( S_ISBLK( path_stat.st_mode ) ) + return fs::file_status( fs::block_file ); + if ( S_ISCHR( path_stat.st_mode ) ) + return fs::file_status( fs::character_file ); + if ( S_ISFIFO( path_stat.st_mode ) ) + return fs::file_status( fs::fifo_file ); + if ( S_ISSOCK( path_stat.st_mode ) ) + return fs::file_status( fs::socket_file ); + return fs::file_status( fs::type_unknown ); + } + + // suggested by Walter Landry + BOOST_FILESYSTEM_DECL bool + symbolic_link_exists_api( const std::string & ph ) + { + struct stat path_stat; + return ::lstat( ph.c_str(), &path_stat ) == 0 + && S_ISLNK( path_stat.st_mode ); + } + + BOOST_FILESYSTEM_DECL query_pair + is_empty_api( const std::string & ph ) + { + struct stat path_stat; + if ( (::stat( ph.c_str(), &path_stat )) != 0 ) + return std::make_pair( error_code( errno, system_category ), false ); + return std::make_pair( ok, S_ISDIR( path_stat.st_mode ) + ? is_empty_directory( ph ) + : path_stat.st_size == 0 ); + } + + BOOST_FILESYSTEM_DECL query_pair + equivalent_api( const std::string & ph1, const std::string & ph2 ) + { + struct stat s2; + int e2( ::stat( ph2.c_str(), &s2 ) ); + struct stat s1; + int e1( ::stat( ph1.c_str(), &s1 ) ); + if ( e1 != 0 || e2 != 0 ) + return std::make_pair( error_code( e1 != 0 && e2 != 0 ? errno : 0, system_category ), false ); + // at this point, both stats are known to be valid + return std::make_pair( ok, + s1.st_dev == s2.st_dev + && s1.st_ino == s2.st_ino + // According to the POSIX stat specs, "The st_ino and st_dev fields + // taken together uniquely identify the file within the system." + // Just to be sure, size and mod time are also checked. + && s1.st_size == s2.st_size + && s1.st_mtime == s2.st_mtime ); + } + + BOOST_FILESYSTEM_DECL uintmax_pair + file_size_api( const std::string & ph ) + { + struct stat path_stat; + if ( ::stat( ph.c_str(), &path_stat ) != 0 ) + return std::make_pair( error_code( errno, system_category ), 0 ); + if ( !S_ISREG( path_stat.st_mode ) ) + return std::make_pair( error_code( EPERM, system_category ), 0 ); + return std::make_pair( ok, + static_cast<boost::uintmax_t>(path_stat.st_size) ); + } + + BOOST_FILESYSTEM_DECL space_pair + space_api( const std::string & ph ) + { + struct BOOST_STATVFS vfs; + space_pair result; + if ( ::BOOST_STATVFS( ph.c_str(), &vfs ) != 0 ) + { + result.first = error_code( errno, system_category ); + result.second.capacity = result.second.free + = result.second.available = 0; + } + else + { + result.first = ok; + result.second.capacity + = static_cast<boost::uintmax_t>(vfs.f_blocks) * BOOST_STATVFS_F_FRSIZE; + result.second.free + = static_cast<boost::uintmax_t>(vfs.f_bfree) * BOOST_STATVFS_F_FRSIZE; + result.second.available + = static_cast<boost::uintmax_t>(vfs.f_bavail) * BOOST_STATVFS_F_FRSIZE; + } + return result; + } + + BOOST_FILESYSTEM_DECL time_pair + last_write_time_api( const std::string & ph ) + { + struct stat path_stat; + if ( ::stat( ph.c_str(), &path_stat ) != 0 ) + return std::make_pair( error_code( errno, system_category ), 0 ); + return std::make_pair( ok, path_stat.st_mtime ); + } + + BOOST_FILESYSTEM_DECL error_code + last_write_time_api( const std::string & ph, std::time_t new_value ) + { + struct stat path_stat; + if ( ::stat( ph.c_str(), &path_stat ) != 0 ) + return error_code( errno, system_category ); + ::utimbuf buf; + buf.actime = path_stat.st_atime; // utime() updates access time too:-( + buf.modtime = new_value; + return error_code( ::utime( ph.c_str(), &buf ) != 0 ? errno : 0, system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + get_current_path_api( std::string & ph ) + { + for ( long path_max = 32;; path_max *=2 ) // loop 'til buffer large enough + { + boost::scoped_array<char> + buf( new char[static_cast<std::size_t>(path_max)] ); + if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 ) + { + if ( errno != ERANGE + // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set +# if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) + && errno != 0 +# endif + ) return error_code( errno, system_category ); + } + else + { + ph = buf.get(); + break; + } + } + return ok; + } + + BOOST_FILESYSTEM_DECL error_code + set_current_path_api( const std::string & ph ) + { + return error_code( ::chdir( ph.c_str() ) + ? errno : 0, system_category ); + } + + BOOST_FILESYSTEM_DECL fs::detail::query_pair + create_directory_api( const std::string & ph ) + { + if ( ::mkdir( ph.c_str(), S_IRWXU|S_IRWXG|S_IRWXO ) == 0 ) + { return std::make_pair( ok, true ); } + int ec=errno; + error_code dummy; + if ( ec != EEXIST + || !fs::is_directory( status_api( ph, dummy ) ) ) + { return std::make_pair( error_code( ec, system_category ), false ); } + return std::make_pair( ok, false ); + } + + BOOST_FILESYSTEM_DECL error_code + create_hard_link_api( const std::string & to_ph, + const std::string & from_ph ) + { + return error_code( ::link( to_ph.c_str(), from_ph.c_str() ) == 0 + ? 0 : errno, system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + create_symlink_api( const std::string & to_ph, + const std::string & from_ph ) + { + return error_code( ::symlink( to_ph.c_str(), from_ph.c_str() ) == 0 + ? 0 : errno, system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + remove_api( const std::string & ph ) + { + if ( posix_remove( ph.c_str() ) == 0 ) + return ok; + int error = errno; + // POSIX says "If the directory is not an empty directory, rmdir() + // shall fail and set errno to EEXIST or ENOTEMPTY." + // Linux uses ENOTEMPTY, Solaris uses EEXIST. + if ( error == EEXIST ) error = ENOTEMPTY; + + error_code ec; + + // ignore errors if post-condition satisfied + return status_api(ph, ec).type() == file_not_found + ? ok : error_code( error, system_category ) ; + } + + BOOST_FILESYSTEM_DECL error_code + rename_api( const std::string & from, const std::string & to ) + { + // POSIX is too permissive so must check + error_code dummy; + if ( fs::exists( status_api( to, dummy ) ) ) + return error_code( EEXIST, system_category ); + return error_code( std::rename( from.c_str(), to.c_str() ) != 0 + ? errno : 0, system_category ); + } + + BOOST_FILESYSTEM_DECL error_code + copy_file_api( const std::string & from_file_ph, + const std::string & to_file_ph ) + { + const std::size_t buf_sz = 32768; + boost::scoped_array<char> buf( new char [buf_sz] ); + int infile=-1, outfile=-1; // -1 means not open + struct stat from_stat; + + if ( ::stat( from_file_ph.c_str(), &from_stat ) != 0 + || (infile = ::open( from_file_ph.c_str(), + O_RDONLY )) < 0 + || (outfile = ::open( to_file_ph.c_str(), + O_WRONLY | O_CREAT | O_EXCL, + from_stat.st_mode )) < 0 ) + { + if ( infile >= 0 ) ::close( infile ); + return error_code( errno, system_category ); + } + + ssize_t sz, sz_read=1, sz_write; + while ( sz_read > 0 + && (sz_read = ::read( infile, buf.get(), buf_sz )) > 0 ) + { + // Allow for partial writes - see Advanced Unix Programming (2nd Ed.), + // Marc Rochkind, Addison-Wesley, 2004, page 94 + sz_write = 0; + do + { + if ( (sz = ::write( outfile, buf.get() + sz_write, + sz_read - sz_write )) < 0 ) + { + sz_read = sz; // cause read loop termination + break; // and error to be thrown after closes + } + sz_write += sz; + } while ( sz_write < sz_read ); + } + + if ( ::close( infile) < 0 ) sz_read = -1; + if ( ::close( outfile) < 0 ) sz_read = -1; + + return error_code( sz_read < 0 ? errno : 0, system_category ); + } + + // this code is based on Stevens and Rago, Advanced Programming in the + // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49 + error_code path_max( std::size_t & result ) + { +# ifdef PATH_MAX + static std::size_t max = PATH_MAX; +# else + static std::size_t max = 0; +# endif + if ( max == 0 ) + { + errno = 0; + long tmp = ::pathconf( "/", _PC_NAME_MAX ); + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate + max = 4096; // guess + else return error_code( errno, system_category ); + } + else max = static_cast<std::size_t>( tmp + 1 ); // relative root + } + result = max; + return ok; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_first( void *& handle, void *& buffer, + const std::string & dir, std::string & target, + file_status &, file_status & ) + { + if ( (handle = ::opendir( dir.c_str() )) == 0 ) + return error_code( errno, system_category ); + target = std::string( "." ); // string was static but caused trouble + // when iteration called from dtor, after + // static had already been destroyed + std::size_t path_size; + error_code ec = path_max( path_size ); + if ( ec ) return ec; + dirent de; + buffer = std::malloc( (sizeof(dirent) - sizeof(de.d_name)) + + path_size + 1 ); // + 1 for "/0" + return ok; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_close( void *& handle, void*& buffer ) + { + std::free( buffer ); + buffer = 0; + if ( handle == 0 ) return ok; + DIR * h( static_cast<DIR*>(handle) ); + handle = 0; + return error_code( ::closedir( h ) == 0 ? 0 : errno, system_category ); + } + + // warning: the only dirent member updated is d_name + inline int readdir_r_simulator( DIR * dirp, struct dirent * entry, + struct dirent ** result ) // *result set to 0 on end of directory + { + errno = 0; + + # if !defined(__CYGWIN__) \ + && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \ + && defined(_SC_THREAD_SAFE_FUNCTIONS) \ + && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0) \ + && (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT))) + if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) >= 0 ) + { return ::readdir_r( dirp, entry, result ); } + # endif + + struct dirent * p; + *result = 0; + if ( (p = ::readdir( dirp )) == 0 ) + return errno; + std::strcpy( entry->d_name, p->d_name ); + *result = entry; + return 0; + } + + BOOST_FILESYSTEM_DECL error_code + dir_itr_increment( void *& handle, void *& buffer, + std::string & target, file_status & sf, file_status & symlink_sf ) + { + BOOST_ASSERT( buffer != 0 ); + dirent * entry( static_cast<dirent *>(buffer) ); + dirent * result; + int return_code; + if ( (return_code = readdir_r_simulator( static_cast<DIR*>(handle), + entry, &result )) != 0 ) return error_code( errno, system_category ); + if ( result == 0 ) return dir_itr_close( handle, buffer ); + target = entry->d_name; +# ifdef BOOST_FILESYSTEM_STATUS_CACHE + if ( entry->d_type == DT_UNKNOWN ) // filesystem does not supply d_type value + { + sf = symlink_sf = fs::file_status(fs::status_unknown); + } + else // filesystem supplies d_type value + { + if ( entry->d_type == DT_DIR ) + sf = symlink_sf = fs::file_status( fs::directory_file ); + else if ( entry->d_type == DT_REG ) + sf = symlink_sf = fs::file_status( fs::regular_file ); + else if ( entry->d_type == DT_LNK ) + { + sf = fs::file_status( fs::status_unknown ); + symlink_sf = fs::file_status( fs::symlink_file ); + } + else sf = symlink_sf = fs::file_status( fs::status_unknown ); + } +# else + sf = symlink_sf = fs::file_status( fs::status_unknown ); +# endif + return ok; + } + +# endif + } // namespace detail + } // namespace filesystem +} // namespace boost diff --git a/3rdParty/Boost/libs/filesystem/src/path.cpp b/3rdParty/Boost/libs/filesystem/src/path.cpp new file mode 100644 index 0000000..6d7d40c --- /dev/null +++ b/3rdParty/Boost/libs/filesystem/src/path.cpp @@ -0,0 +1,163 @@ +// path.cpp ----------------------------------------------------------------// + +// Copyright 2005 Beman Dawes + +// 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 library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_FILESYSTEM_SOURCE + +#include <boost/filesystem/config.hpp> + +#ifndef BOOST_FILESYSTEM_NARROW_ONLY + +#include <boost/filesystem/path.hpp> +#include <boost/scoped_array.hpp> + +#include <locale> +#include <boost/cerrno.hpp> +#include <boost/system/error_code.hpp> + +#include <cwchar> // for std::mbstate_t + +namespace +{ + // std::locale construction can throw (if LC_MESSAGES is wrong, for example), + // so a static at function scope is used to ensure that exceptions can be + // caught. (A previous version was at namespace scope, so initialization + // occurred before main(), preventing exceptions from being caught.) + std::locale & loc() + { +#if !defined(macintosh) && !defined(__APPLE__) && !defined(__APPLE_CC__) + // ISO C calls this "the locale-specific native environment": + static std::locale lc(""); +#else + static std::locale lc = std::locale(); // Mac OS doesn't support locale("") +#endif + return lc; + } + + const std::codecvt<wchar_t, char, std::mbstate_t> *& + converter() + { + static const std::codecvt<wchar_t, char, std::mbstate_t> * + cvtr( + &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> > + ( loc() ) ); + return cvtr; + } + + bool locked(false); +} // unnamed namespace + +namespace boost +{ + namespace filesystem + { + bool wpath_traits::imbue( const std::locale & new_loc, const std::nothrow_t & ) + { + if ( locked ) return false; + locked = true; + loc() = new_loc; + converter() = &std::use_facet + <std::codecvt<wchar_t, char, std::mbstate_t> >( loc() ); + return true; + } + + void wpath_traits::imbue( const std::locale & new_loc ) + { + if ( locked ) boost::throw_exception( + wfilesystem_error( + "boost::filesystem::wpath_traits::imbue() after lockdown", + make_error_code( system::posix::not_supported ) ) ); + imbue( new_loc, std::nothrow ); + } + + //namespace detail + //{ + // BOOST_FILESYSTEM_DECL + // const char * what( const char * sys_err_what, + // const path & path1, const path & path2, std::string & target) + // { + // try + // { + // if ( target.empty() ) + // { + // target = sys_err_what; + // if ( !path1.empty() ) + // { + // target += ": \""; + // target += path1.file_string(); + // target += "\""; + // } + // if ( !path2.empty() ) + // { + // target += ", \""; + // target += path2.file_string(); + // target += "\""; + // } + // } + // return target.c_str(); + // } + // catch (...) + // { + // return sys_err_what; + // } + // } + //} + +# ifdef BOOST_POSIX_API + +// Because this is POSIX only code, we don't have to worry about ABI issues +// described in http://www.boost.org/more/separate_compilation.html + + wpath_traits::external_string_type + wpath_traits::to_external( const wpath & ph, + const internal_string_type & src ) + { + locked = true; + std::size_t work_size( converter()->max_length() * (src.size()+1) ); + boost::scoped_array<char> work( new char[ work_size ] ); + std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports + const internal_string_type::value_type * from_next; + external_string_type::value_type * to_next; + if ( converter()->out( + state, src.c_str(), src.c_str()+src.size(), from_next, work.get(), + work.get()+work_size, to_next ) != std::codecvt_base::ok ) + boost::throw_exception( boost::filesystem::wfilesystem_error( + "boost::filesystem::wpath::to_external conversion error", + ph, system::error_code( system::posix::invalid_argument, system::system_category ) ) ); + *to_next = '\0'; + return external_string_type( work.get() ); + } + + wpath_traits::internal_string_type + wpath_traits::to_internal( const external_string_type & src ) + { + locked = true; + std::size_t work_size( src.size()+1 ); + boost::scoped_array<wchar_t> work( new wchar_t[ work_size ] ); + std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports + const external_string_type::value_type * from_next; + internal_string_type::value_type * to_next; + if ( converter()->in( + state, src.c_str(), src.c_str()+src.size(), from_next, work.get(), + work.get()+work_size, to_next ) != std::codecvt_base::ok ) + boost::throw_exception( boost::filesystem::wfilesystem_error( + "boost::filesystem::wpath::to_internal conversion error", + system::error_code( system::posix::invalid_argument, system::system_category ) ) ); + *to_next = L'\0'; + return internal_string_type( work.get() ); + } +# endif // BOOST_POSIX_API + + } // namespace filesystem +} // namespace boost + +#endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY diff --git a/3rdParty/Boost/libs/filesystem/src/portability.cpp b/3rdParty/Boost/libs/filesystem/src/portability.cpp new file mode 100644 index 0000000..347180a --- /dev/null +++ b/3rdParty/Boost/libs/filesystem/src/portability.cpp @@ -0,0 +1,115 @@ +// portability.cpp ---------------------------------------------------------// + +// Copyright 2002-2005 Beman Dawes +// 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 library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_FILESYSTEM_SOURCE + +#include <boost/filesystem/config.hpp> +#include <boost/filesystem/path.hpp> + +namespace fs = boost::filesystem; + +#include <cstring> // SGI MIPSpro compilers need this + +# ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::strerror; } +# endif + +//----------------------------------------------------------------------------// + +namespace +{ + const char invalid_chars[] = + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + "<>:\"/\\|"; + // note that the terminating '\0' is part of the string - thus the size below + // is sizeof(invalid_chars) rather than sizeof(invalid_chars)-1. I + const std::string windows_invalid_chars( invalid_chars, sizeof(invalid_chars) ); + + const std::string valid_posix( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-" ); + +} // unnamed namespace + +namespace boost +{ + namespace filesystem + { + + // name_check functions ----------------------------------------------// + +# ifdef BOOST_WINDOWS + BOOST_FILESYSTEM_DECL bool native( const std::string & name ) + { + return windows_name( name ); + } +# else + BOOST_FILESYSTEM_DECL bool native( const std::string & name ) + { + return name.size() != 0 + && name[0] != ' ' + && name.find('/') == std::string::npos; + } +# endif + + BOOST_FILESYSTEM_DECL bool portable_posix_name( const std::string & name ) + { + return name.size() != 0 + && name.find_first_not_of( valid_posix ) == std::string::npos; + } + + BOOST_FILESYSTEM_DECL bool windows_name( const std::string & name ) + { + return name.size() != 0 + && name[0] != ' ' + && name.find_first_of( windows_invalid_chars ) == std::string::npos + && *(name.end()-1) != ' ' + && (*(name.end()-1) != '.' + || name.length() == 1 || name == ".."); + } + + BOOST_FILESYSTEM_DECL bool portable_name( const std::string & name ) + { + return + name.size() != 0 + && ( name == "." + || name == ".." + || (windows_name( name ) + && portable_posix_name( name ) + && name[0] != '.' && name[0] != '-')); + } + + BOOST_FILESYSTEM_DECL bool portable_directory_name( const std::string & name ) + { + return + name == "." + || name == ".." + || (portable_name( name ) + && name.find('.') == std::string::npos); + } + + BOOST_FILESYSTEM_DECL bool portable_file_name( const std::string & name ) + { + std::string::size_type pos; + return + portable_name( name ) + && name != "." + && name != ".." + && ( (pos = name.find( '.' )) == std::string::npos + || (name.find( '.', pos+1 ) == std::string::npos + && (pos + 5) > name.length() )) + ; + } + + } // namespace filesystem +} // namespace boost diff --git a/3rdParty/Boost/libs/filesystem/src/utf8_codecvt_facet.cpp b/3rdParty/Boost/libs/filesystem/src/utf8_codecvt_facet.cpp new file mode 100644 index 0000000..3fe3e95 --- /dev/null +++ b/3rdParty/Boost/libs/filesystem/src/utf8_codecvt_facet.cpp @@ -0,0 +1,20 @@ +// Copyright Vladimir Prus 2004. +// 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) + +#define BOOST_FILESYSTEM_SOURCE +#include <boost/filesystem/config.hpp> + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace filesystem { namespace detail { + +#define BOOST_UTF8_END_NAMESPACE }}} +#define BOOST_UTF8_DECL BOOST_FILESYSTEM_DECL + +#include "libs/detail/utf8_codecvt_facet.cpp" + + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL diff --git a/3rdParty/Boost/libs/filesystem/src/utf8_codecvt_facet.hpp b/3rdParty/Boost/libs/filesystem/src/utf8_codecvt_facet.hpp new file mode 100644 index 0000000..3b78fb1 --- /dev/null +++ b/3rdParty/Boost/libs/filesystem/src/utf8_codecvt_facet.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). + +// Distributed under the Boost Software License, Version 1.0. +// (See http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_FILESYSTEM_UTF8_CODECVT_FACET_HPP +#define BOOST_FILESYSTEM_UTF8_CODECVT_FACET_HPP + +#include <boost/filesystem/config.hpp> + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace filesystem { namespace detail { + +#define BOOST_UTF8_END_NAMESPACE }}} +#define BOOST_UTF8_DECL BOOST_FILESYSTEM_DECL + +#include <boost/detail/utf8_codecvt_facet.hpp> + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + +#endif diff --git a/3rdParty/Boost/libs/signals/src/connection.cpp b/3rdParty/Boost/libs/signals/src/connection.cpp new file mode 100644 index 0000000..b4ed8b4 --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/connection.cpp @@ -0,0 +1,155 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. 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) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/connection.hpp> +#include <cassert> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + + connection::connection(const connection& other) : + con(other.con), controlling_connection(other.controlling_connection) + { + } + + connection::~connection() + { + if (controlling_connection) { + disconnect(); + } + } + + void + connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con) + { + con.reset(new_con); + } + + bool connection::operator==(const connection& other) const + { + return con.get() == other.con.get(); + } + + bool connection::operator<(const connection& other) const + { + return con.get() < other.con.get(); + } + + connection& connection::operator=(const connection& other) + { + connection(other).swap(*this); + return *this; + } + + void connection::swap(connection& other) + { + this->con.swap(other.con); + std::swap(this->controlling_connection, other.controlling_connection); + } + + void swap(connection& c1, connection& c2) + { + c1.swap(c2); + } + + scoped_connection::scoped_connection(const connection& other) : + connection(other), + released(false) + { + } + + scoped_connection::scoped_connection(const scoped_connection& other) : + connection(other), + released(other.released) + { + } + + scoped_connection::~scoped_connection() + { + if (!released) { + this->disconnect(); + } + } + + connection scoped_connection::release() + { + released = true; + return *this; + } + + void scoped_connection::swap(scoped_connection& other) + { + this->connection::swap(other); + bool other_released = other.released; + other.released = this->released; + this->released = other_released; + } + + void swap(scoped_connection& c1, scoped_connection& c2) + { + c1.swap(c2); + } + + scoped_connection& + scoped_connection::operator=(const connection& other) + { + scoped_connection(other).swap(*this); + return *this; + } + + scoped_connection& + scoped_connection::operator=(const scoped_connection& other) + { + scoped_connection(other).swap(*this); + return *this; + } + + void + connection::add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b) + { + assert(con.get() != 0); + con->bound_objects.push_back(b); + } + + + void connection::disconnect() const + { + if (this->connected()) { + // Make sure we have a reference to the basic_connection object, + // because 'this' may disappear + shared_ptr<detail::basic_connection> local_con = con; + + void (*signal_disconnect)(void*, void*) = local_con->signal_disconnect; + + // Note that this connection no longer exists + // Order is important here: we could get into an infinite loop if this + // isn't cleared before we try the disconnect. + local_con->signal_disconnect = 0; + + // Disconnect signal + signal_disconnect(local_con->signal, local_con->signal_data); + + // Disconnect all bound objects + typedef std::list<BOOST_SIGNALS_NAMESPACE::detail::bound_object>::iterator iterator; + for (iterator i = local_con->bound_objects.begin(); + i != local_con->bound_objects.end(); ++i) { + assert(i->disconnect != 0); + i->disconnect(i->obj, i->data); + } + } + } + } // end namespace boost +} // end namespace boost + +#ifndef BOOST_MSVC +// Explicit instantiations to keep everything in the library +template class std::list<boost::BOOST_SIGNALS_NAMESPACE::detail::bound_object>; +#endif diff --git a/3rdParty/Boost/libs/signals/src/named_slot_map.cpp b/3rdParty/Boost/libs/signals/src/named_slot_map.cpp new file mode 100644 index 0000000..85a4bda --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/named_slot_map.cpp @@ -0,0 +1,134 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. 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) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/detail/named_slot_map.hpp> +#include <cassert> +#include <map> +#include <list> +#include <typeinfo> + +namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail { + +typedef std::list<connection_slot_pair> group_list; +typedef group_list::iterator slot_pair_iterator; +typedef std::map<stored_group, group_list, compare_type> slot_container_type; +typedef slot_container_type::iterator group_iterator; +typedef slot_container_type::const_iterator const_group_iterator; + + +#if BOOST_WORKAROUND(_MSC_VER, <= 1500) +void named_slot_map_iterator::decrement() { assert(false); } +void named_slot_map_iterator::advance(difference_type) { assert(false); } +#endif + +named_slot_map::named_slot_map(const compare_type& compare) : groups(compare) +{ + clear(); +} + +void named_slot_map::clear() +{ + groups.clear(); + groups[stored_group(stored_group::sk_front)]; + groups[stored_group(stored_group::sk_back)]; + back = groups.end(); + --back; +} + +named_slot_map::iterator named_slot_map::begin() +{ + return named_slot_map::iterator(groups.begin(), groups.end()); +} + +named_slot_map::iterator named_slot_map::end() +{ + return named_slot_map::iterator(groups.end(), groups.end()); +} + +named_slot_map::iterator +named_slot_map::insert(const stored_group& name, const connection& con, + const any& slot, connect_position at) +{ + group_iterator group; + if (name.empty()) { + switch (at) { + case at_front: group = groups.begin(); break; + case at_back: group = back; break; + } + } else { + group = groups.find(name); + if (group == groups.end()) { + slot_container_type::value_type v(name, group_list()); + group = groups.insert(v).first; + } + } + iterator it; + it.group = group; + it.last_group = groups.end(); + + switch (at) { + case at_back: + group->second.push_back(connection_slot_pair(con, slot)); + it.slot_ = group->second.end(); + it.slot_assigned = true; + --(it.slot_); + break; + + case at_front: + group->second.push_front(connection_slot_pair(con, slot)); + it.slot_ = group->second.begin(); + it.slot_assigned = true; + break; + } + return it; +} + +void named_slot_map::disconnect(const stored_group& name) +{ + group_iterator group = groups.find(name); + if (group != groups.end()) { + slot_pair_iterator i = group->second.begin(); + while (i != group->second.end()) { + slot_pair_iterator next = i; + ++next; + i->first.disconnect(); + i = next; + } + groups.erase(group); + } +} + +void named_slot_map::erase(iterator pos) +{ + // Erase the slot + pos.slot_->first.disconnect(); + pos.group->second.erase(pos.slot_); +} + +void named_slot_map::remove_disconnected_slots() +{ + // Remove any disconnected slots + group_iterator g = groups.begin(); + while (g != groups.end()) { + slot_pair_iterator s = g->second.begin(); + while (s != g->second.end()) { + if (s->first.connected()) ++s; + else g->second.erase(s++); + } + + // Clear out empty groups + if (empty(g)) groups.erase(g++); + else ++g; + } +} + + +} } } diff --git a/3rdParty/Boost/libs/signals/src/signal_base.cpp b/3rdParty/Boost/libs/signals/src/signal_base.cpp new file mode 100644 index 0000000..759672d --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/signal_base.cpp @@ -0,0 +1,189 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. 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) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/detail/signal_base.hpp> +#include <cassert> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + namespace detail { + signal_base_impl::signal_base_impl(const compare_type& comp, + const any& combiner) + : call_depth(0), + slots_(comp), + combiner_(combiner) + { + flags.delayed_disconnect = false; + flags.clearing = false; + } + + signal_base_impl::~signal_base_impl() + { + // Set the "clearing" flag to ignore extraneous disconnect requests, + // because all slots will be disconnected on destruction anyway. + flags.clearing = true; + } + + void signal_base_impl::disconnect_all_slots() + { + // Do nothing if we're already clearing the slot list + if (flags.clearing) + return; + + if (call_depth == 0) { + // Clearing the slot list will disconnect all slots automatically + temporarily_set_clearing set_clearing(this); + slots_.clear(); + } + else { + // We can't actually remove elements from the slot list because there + // are still iterators into the slot list that must not be + // invalidated by this operation. So just disconnect each slot + // without removing it from the slot list. When the call depth does + // reach zero, the call list will be cleared. + flags.delayed_disconnect = true; + temporarily_set_clearing set_clearing(this); + for (iterator i = slots_.begin(); i != slots_.end(); ++i) { + i->first.disconnect(); + } + } + } + + connection + signal_base_impl:: + connect_slot(const any& slot_, + const stored_group& name, + shared_ptr<slot_base::data_t> data, + connect_position at) + { + // Transfer the burden of ownership to a local, scoped + // connection. + data->watch_bound_objects.set_controlling(false); + scoped_connection safe_connection(data->watch_bound_objects); + + // Allocate storage for an iterator that will hold the point of + // insertion of the slot into the list. This is used to later remove + // the slot when it is disconnected. + std::auto_ptr<iterator> saved_iter(new iterator); + + // Add the slot to the list. + iterator pos = + slots_.insert(name, data->watch_bound_objects, slot_, at); + + // The assignment operation here absolutely must not throw, which + // intuitively makes sense (because any container's insert method + // becomes impossible to use in an exception-safe manner without this + // assumption), but doesn't appear to be mentioned in the standard. + *saved_iter = pos; + + // Fill out the connection object appropriately. None of these + // operations can throw + data->watch_bound_objects.get_connection()->signal = this; + data->watch_bound_objects.get_connection()->signal_data = + saved_iter.release(); + data->watch_bound_objects.get_connection()->signal_disconnect = + &signal_base_impl::slot_disconnected; + + // Make the copy of the connection in the list disconnect when it is + // destroyed. The local, scoped connection is then released + // because ownership has been transferred. + pos->first.set_controlling(); + return safe_connection.release(); + } + + bool signal_base_impl::empty() const + { + // Disconnected slots may still be in the list of slots if + // a) this is called while slots are being invoked (call_depth > 0) + // b) an exception was thrown in remove_disconnected_slots + for (iterator i = slots_.begin(); i != slots_.end(); ++i) { + if (i->first.connected()) + return false; + } + + return true; + } + + std::size_t signal_base_impl::num_slots() const + { + // Disconnected slots may still be in the list of slots if + // a) this is called while slots are being invoked (call_depth > 0) + // b) an exception was thrown in remove_disconnected_slots + std::size_t count = 0; + for (iterator i = slots_.begin(); i != slots_.end(); ++i) { + if (i->first.connected()) + ++count; + } + return count; + } + + void signal_base_impl::disconnect(const stored_group& group) + { slots_.disconnect(group); } + + void signal_base_impl::slot_disconnected(void* obj, void* data) + { + signal_base_impl* self = reinterpret_cast<signal_base_impl*>(obj); + + // We won't need the slot iterator after this + std::auto_ptr<iterator> slot(reinterpret_cast<iterator*>(data)); + + // If we're flags.clearing, we don't bother updating the list of slots + if (!self->flags.clearing) { + // If we're in a call, note the fact that a slot has been deleted so + // we can come back later to remove the iterator + if (self->call_depth > 0) { + self->flags.delayed_disconnect = true; + } + else { + // Just remove the slot now, it's safe + self->slots_.erase(*slot); + } + } + } + + void signal_base_impl::remove_disconnected_slots() const + { slots_.remove_disconnected_slots(); } + + call_notification:: + call_notification(const shared_ptr<signal_base_impl>& b) : + impl(b) + { + // A call will be made, so increment the call depth as a notification + impl->call_depth++; + } + + call_notification::~call_notification() + { + impl->call_depth--; + + // If the call depth is zero and we have some slots that have been + // disconnected during the calls, remove those slots from the list + if (impl->call_depth == 0 && + impl->flags.delayed_disconnect) { + impl->remove_disconnected_slots(); + impl->flags.delayed_disconnect = false; + } + } + + signal_base::signal_base(const compare_type& comp, const any& combiner) + : impl() + { + impl.reset(new signal_base_impl(comp, combiner)); + } + + signal_base::~signal_base() + { + } + + } // namespace detail + } // namespace BOOST_SIGNALS_NAMESPACE +} // namespace boost + diff --git a/3rdParty/Boost/libs/signals/src/slot.cpp b/3rdParty/Boost/libs/signals/src/slot.cpp new file mode 100644 index 0000000..7c296d6 --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/slot.cpp @@ -0,0 +1,71 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. 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) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/slot.hpp> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + namespace detail { + void slot_base::create_connection() + { + // Create a new connection object + basic_connection* con = new basic_connection(); + + /* nothrow */ { + // The signal portion isn't really necessary, except that we need a + // signal for the connection to be connected. + con->signal = static_cast<void*>(this); + con->signal_data = 0; + con->blocked_ = false ; + con->signal_disconnect = &bound_object_destructed; + } + + // This connection watches for destruction of bound objects. Note + // that the reset routine will delete con if an allocation throws + data->watch_bound_objects.reset(con); + + // We create a scoped connection, so that exceptions thrown while + // adding bound objects will cause a cleanup of the bound objects + // already connected. + scoped_connection safe_connection(data->watch_bound_objects); + + // Now notify each of the bound objects that they are connected to this + // slot. + for(std::vector<const trackable*>::iterator i = + data->bound_objects.begin(); + i != data->bound_objects.end(); ++i) { + // Notify the object that the slot is connecting to it + BOOST_SIGNALS_NAMESPACE::detail::bound_object binding; + (*i)->signal_connected(data->watch_bound_objects, binding); + + // This will notify the bound object that the connection just made + // should be disconnected if an exception is thrown before the + // end of this iteration + BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object + disconnector(binding); + + // Add the binding to the list of bindings for the connection + con->bound_objects.push_back(binding); + + // The connection object now knows about the bound object, so if an + // exception is thrown later the connection object will notify the + // bound object of the disconnection automatically + disconnector.release(); + } + + // No exceptions will be thrown past this point. + safe_connection.release(); + + data->watch_bound_objects.set_controlling(true); + } + } // end namespace detail + } // end namespace BOOST_SIGNALS_NAMESPACE +} // end namespace boost diff --git a/3rdParty/Boost/libs/signals/src/trackable.cpp b/3rdParty/Boost/libs/signals/src/trackable.cpp new file mode 100644 index 0000000..4f63586 --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/trackable.cpp @@ -0,0 +1,59 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. 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) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/trackable.hpp> +#include <algorithm> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + void trackable::signal_disconnected(void* obj, void* data) + { + trackable* self = reinterpret_cast<trackable*>(obj); + connection_iterator* signal = + reinterpret_cast<connection_iterator*>(data); + + // If we're dying, don't bother erasing the connection from the list; + // it'll be gone anyway + if (!self->dying) { + self->connected_signals.erase(*signal); + } + + // This iterator pointer won't ever be used again + delete signal; + } + + void + trackable::signal_connected(connection c, + BOOST_SIGNALS_NAMESPACE::detail::bound_object& binding) const + { + // Insert the connection + connection_iterator pos = + connected_signals.insert(connected_signals.end(), c); + + // Make this copy of the object disconnect when destroyed + pos->set_controlling(); + + binding.obj = const_cast<void*>(reinterpret_cast<const void*>(this)); + binding.data = reinterpret_cast<void*>(new connection_iterator(pos)); + binding.disconnect = &signal_disconnected; + } + + trackable::~trackable() + { + dying = true; + } + } // end namespace BOOST_SIGNALS_NAMESPACE +} + +#ifndef BOOST_MSVC +// Explicit instantiations to keep in the library +template class std::list<boost::BOOST_SIGNALS_NAMESPACE::connection>; +#endif diff --git a/3rdParty/Boost/libs/system/src/error_code.cpp b/3rdParty/Boost/libs/system/src/error_code.cpp new file mode 100644 index 0000000..030ab70 --- /dev/null +++ b/3rdParty/Boost/libs/system/src/error_code.cpp @@ -0,0 +1,433 @@ +// error_code support implementation file ----------------------------------// + +// Copyright Beman Dawes 2002, 2006 + +// 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 library home page at http://www.boost.org/libs/system + +//----------------------------------------------------------------------------// + +#include <boost/config/warning_disable.hpp> + +// define BOOST_SYSTEM_SOURCE so that <boost/system/config.hpp> knows +// the library is being built (possibly exporting rather than importing code) +#define BOOST_SYSTEM_SOURCE + +#include <boost/system/config.hpp> +#include <boost/system/error_code.hpp> +#include <boost/cerrno.hpp> +#include <vector> +#include <cstdlib> +#include <cassert> + +using namespace boost::system; +using namespace boost::system::posix_error; + +#include <cstring> // for strerror/strerror_r + +# if defined( BOOST_WINDOWS_API ) +# include <windows.h> +# ifndef ERROR_INCORRECT_SIZE +# define ERROR_INCORRECT_SIZE ERROR_BAD_ARGUMENTS +# endif +# endif + +//----------------------------------------------------------------------------// + +namespace +{ + // standard error categories ---------------------------------------------// + + class generic_error_category : public error_category + { + public: + generic_error_category(){} + const char * name() const; + std::string message( int ev ) const; + }; + + class system_error_category : public error_category + { + public: + system_error_category(){} + const char * name() const; + std::string message( int ev ) const; + error_condition default_error_condition( int ev ) const; + }; + + // generic_error_category implementation ---------------------------------// + + const char * generic_error_category::name() const + { + return "generic"; + } + + std::string generic_error_category::message( int ev ) const + { + static std::string unknown_err( "Unknown error" ); + // strerror_r is preferred because it is always thread safe, + // however, we fallback to strerror in certain cases because: + // -- Windows doesn't provide strerror_r. + // -- HP and Sundo provide strerror_r on newer systems, but there is + // no way to tell if is available at runtime and in any case their + // versions of strerror are thread safe anyhow. + // -- Linux only sometimes provides strerror_r. + // -- Tru64 provides strerror_r only when compiled -pthread. + // -- VMS doesn't provide strerror_r, but on this platform, strerror is + // thread safe. + # if defined(BOOST_WINDOWS_API) || defined(__hpux) || defined(__sun)\ + || (defined(__linux) && (!defined(__USE_XOPEN2K) || defined(BOOST_SYSTEM_USE_STRERROR)))\ + || (defined(__osf__) && !defined(_REENTRANT))\ + || (defined(__vms))\ + || (defined(__QNXNTO__)) + const char * c_str = std::strerror( ev ); + return c_str + ? std::string( c_str ) + : unknown_err; + # else // use strerror_r + char buf[64]; + char * bp = buf; + std::size_t sz = sizeof(buf); + # if defined(__CYGWIN__) || defined(__USE_GNU) + // Oddball version of strerror_r + const char * c_str = strerror_r( ev, bp, sz ); + return c_str + ? std::string( c_str ) + : unknown_err; + # else + // POSIX version of strerror_r + int result; + for (;;) + { + // strerror_r returns 0 on success, otherwise ERANGE if buffer too small, + // invalid_argument if ev not a valid error number + # if defined (__sgi) + const char * c_str = strerror( ev ); + result = 0; + return c_str + ? std::string( c_str ) + : unknown_err; + # else + result = strerror_r( ev, bp, sz ); + # endif + if (result == 0 ) + break; + else + { + # if defined(__linux) + // Linux strerror_r returns -1 on error, with error number in errno + result = errno; + # endif + if ( result != ERANGE ) break; + if ( sz > sizeof(buf) ) std::free( bp ); + sz *= 2; + if ( (bp = static_cast<char*>(std::malloc( sz ))) == 0 ) + return std::string( "ENOMEM" ); + } + } + std::string msg; + try + { + msg = ( ( result == invalid_argument ) ? "Unknown error" : bp ); + } + +# ifndef BOOST_NO_EXCEPTIONS + // See ticket #2098 + catch(...) + { + // just eat the exception + } +# endif + + if ( sz > sizeof(buf) ) std::free( bp ); + sz = 0; + return msg; + # endif // else POSIX version of strerror_r + # endif // else use strerror_r + } + // system_error_category implementation --------------------------------// + + const char * system_error_category::name() const + { + return "system"; + } + + error_condition system_error_category::default_error_condition( int ev ) const + { + switch ( ev ) + { + case 0: return make_error_condition( success ); + # if defined(BOOST_POSIX_API) + // POSIX-like O/S -> posix_errno decode table ---------------------------// + case E2BIG: return make_error_condition( argument_list_too_long ); + case EACCES: return make_error_condition( permission_denied ); + case EADDRINUSE: return make_error_condition( address_in_use ); + case EADDRNOTAVAIL: return make_error_condition( address_not_available ); + case EAFNOSUPPORT: return make_error_condition( address_family_not_supported ); + case EAGAIN: return make_error_condition( resource_unavailable_try_again ); +# if EALREADY != EBUSY // EALREADY and EBUSY are the same on QNX Neutrino + case EALREADY: return make_error_condition( connection_already_in_progress ); +# endif + case EBADF: return make_error_condition( bad_file_descriptor ); + case EBADMSG: return make_error_condition( bad_message ); + case EBUSY: return make_error_condition( device_or_resource_busy ); + case ECANCELED: return make_error_condition( operation_canceled ); + case ECHILD: return make_error_condition( no_child_process ); + case ECONNABORTED: return make_error_condition( connection_aborted ); + case ECONNREFUSED: return make_error_condition( connection_refused ); + case ECONNRESET: return make_error_condition( connection_reset ); + case EDEADLK: return make_error_condition( resource_deadlock_would_occur ); + case EDESTADDRREQ: return make_error_condition( destination_address_required ); + case EDOM: return make_error_condition( argument_out_of_domain ); + case EEXIST: return make_error_condition( file_exists ); + case EFAULT: return make_error_condition( bad_address ); + case EFBIG: return make_error_condition( file_too_large ); + case EHOSTUNREACH: return make_error_condition( host_unreachable ); + case EIDRM: return make_error_condition( identifier_removed ); + case EILSEQ: return make_error_condition( illegal_byte_sequence ); + case EINPROGRESS: return make_error_condition( operation_in_progress ); + case EINTR: return make_error_condition( interrupted ); + case EINVAL: return make_error_condition( invalid_argument ); + case EIO: return make_error_condition( io_error ); + case EISCONN: return make_error_condition( already_connected ); + case EISDIR: return make_error_condition( is_a_directory ); + case ELOOP: return make_error_condition( too_many_synbolic_link_levels ); + case EMFILE: return make_error_condition( too_many_files_open ); + case EMLINK: return make_error_condition( too_many_links ); + case EMSGSIZE: return make_error_condition( message_size ); + case ENAMETOOLONG: return make_error_condition( filename_too_long ); + case ENETDOWN: return make_error_condition( network_down ); + case ENETRESET: return make_error_condition( network_reset ); + case ENETUNREACH: return make_error_condition( network_unreachable ); + case ENFILE: return make_error_condition( too_many_files_open_in_system ); + case ENOBUFS: return make_error_condition( no_buffer_space ); + case ENODATA: return make_error_condition( no_message_available ); + case ENODEV: return make_error_condition( no_such_device ); + case ENOENT: return make_error_condition( no_such_file_or_directory ); + case ENOEXEC: return make_error_condition( executable_format_error ); + case ENOLCK: return make_error_condition( no_lock_available ); + case ENOLINK: return make_error_condition( no_link ); + case ENOMEM: return make_error_condition( not_enough_memory ); + case ENOMSG: return make_error_condition( no_message ); + case ENOPROTOOPT: return make_error_condition( no_protocol_option ); + case ENOSPC: return make_error_condition( no_space_on_device ); + case ENOSR: return make_error_condition( no_stream_resources ); + case ENOSTR: return make_error_condition( not_a_stream ); + case ENOSYS: return make_error_condition( function_not_supported ); + case ENOTCONN: return make_error_condition( not_connected ); + case ENOTDIR: return make_error_condition( not_a_directory ); + # if ENOTEMPTY != EEXIST // AIX treats ENOTEMPTY and EEXIST as the same value + case ENOTEMPTY: return make_error_condition( directory_not_empty ); + # endif // ENOTEMPTY != EEXIST + case ENOTRECOVERABLE: return make_error_condition( state_not_recoverable ); + case ENOTSOCK: return make_error_condition( not_a_socket ); + case ENOTSUP: return make_error_condition( not_supported ); + case ENOTTY: return make_error_condition( inappropriate_io_control_operation ); + case ENXIO: return make_error_condition( no_such_device_or_address ); + # if EOPNOTSUPP != ENOTSUP + case EOPNOTSUPP: return make_error_condition( operation_not_supported ); + # endif // EOPNOTSUPP != ENOTSUP + case EOVERFLOW: return make_error_condition( value_too_large ); + case EOWNERDEAD: return make_error_condition( owner_dead ); + case EPERM: return make_error_condition( operation_not_permitted ); + case EPIPE: return make_error_condition( broken_pipe ); + case EPROTO: return make_error_condition( protocol_error ); + case EPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); + case EPROTOTYPE: return make_error_condition( wrong_protocol_type ); + case ERANGE: return make_error_condition( result_out_of_range ); + case EROFS: return make_error_condition( read_only_file_system ); + case ESPIPE: return make_error_condition( invalid_seek ); + case ESRCH: return make_error_condition( no_such_process ); + case ETIME: return make_error_condition( stream_timeout ); + case ETIMEDOUT: return make_error_condition( timed_out ); + case ETXTBSY: return make_error_condition( text_file_busy ); + # if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: return make_error_condition( operation_would_block ); + # endif // EAGAIN != EWOULDBLOCK + case EXDEV: return make_error_condition( cross_device_link ); + #else + // Windows system -> posix_errno decode table ---------------------------// + // see WinError.h comments for descriptions of errors + case ERROR_ACCESS_DENIED: return make_error_condition( permission_denied ); + case ERROR_ALREADY_EXISTS: return make_error_condition( file_exists ); + case ERROR_BAD_UNIT: return make_error_condition( no_such_device ); + case ERROR_BUFFER_OVERFLOW: return make_error_condition( filename_too_long ); + case ERROR_BUSY: return make_error_condition( device_or_resource_busy ); + case ERROR_BUSY_DRIVE: return make_error_condition( device_or_resource_busy ); + case ERROR_CANNOT_MAKE: return make_error_condition( permission_denied ); + case ERROR_CANTOPEN: return make_error_condition( io_error ); + case ERROR_CANTREAD: return make_error_condition( io_error ); + case ERROR_CANTWRITE: return make_error_condition( io_error ); + case ERROR_CURRENT_DIRECTORY: return make_error_condition( permission_denied ); + case ERROR_DEV_NOT_EXIST: return make_error_condition( no_such_device ); + case ERROR_DEVICE_IN_USE: return make_error_condition( device_or_resource_busy ); + case ERROR_DIR_NOT_EMPTY: return make_error_condition( directory_not_empty ); + case ERROR_DIRECTORY: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid" + case ERROR_DISK_FULL: return make_error_condition( no_space_on_device ); + case ERROR_FILE_EXISTS: return make_error_condition( file_exists ); + case ERROR_FILE_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); + case ERROR_HANDLE_DISK_FULL: return make_error_condition( no_space_on_device ); + case ERROR_INVALID_ACCESS: return make_error_condition( permission_denied ); + case ERROR_INVALID_DRIVE: return make_error_condition( no_such_device ); + case ERROR_INVALID_FUNCTION: return make_error_condition( function_not_supported ); + case ERROR_INVALID_HANDLE: return make_error_condition( invalid_argument ); + case ERROR_INVALID_NAME: return make_error_condition( invalid_argument ); + case ERROR_LOCK_VIOLATION: return make_error_condition( no_lock_available ); + case ERROR_LOCKED: return make_error_condition( no_lock_available ); + case ERROR_NEGATIVE_SEEK: return make_error_condition( invalid_argument ); + case ERROR_NOACCESS: return make_error_condition( permission_denied ); + case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition( not_enough_memory ); + case ERROR_NOT_READY: return make_error_condition( resource_unavailable_try_again ); + case ERROR_NOT_SAME_DEVICE: return make_error_condition( cross_device_link ); + case ERROR_OPEN_FAILED: return make_error_condition( io_error ); + case ERROR_OPEN_FILES: return make_error_condition( device_or_resource_busy ); + case ERROR_OPERATION_ABORTED: return make_error_condition( operation_canceled ); + case ERROR_OUTOFMEMORY: return make_error_condition( not_enough_memory ); + case ERROR_PATH_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); + case ERROR_READ_FAULT: return make_error_condition( io_error ); + case ERROR_RETRY: return make_error_condition( resource_unavailable_try_again ); + case ERROR_SEEK: return make_error_condition( io_error ); + case ERROR_SHARING_VIOLATION: return make_error_condition( permission_denied ); + case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition( too_many_files_open ); + case ERROR_WRITE_FAULT: return make_error_condition( io_error ); + case ERROR_WRITE_PROTECT: return make_error_condition( permission_denied ); + case WSAEACCES: return make_error_condition( permission_denied ); + case WSAEADDRINUSE: return make_error_condition( address_in_use ); + case WSAEADDRNOTAVAIL: return make_error_condition( address_not_available ); + case WSAEAFNOSUPPORT: return make_error_condition( address_family_not_supported ); + case WSAEALREADY: return make_error_condition( connection_already_in_progress ); + case WSAEBADF: return make_error_condition( bad_file_descriptor ); + case WSAECONNABORTED: return make_error_condition( connection_aborted ); + case WSAECONNREFUSED: return make_error_condition( connection_refused ); + case WSAECONNRESET: return make_error_condition( connection_reset ); + case WSAEDESTADDRREQ: return make_error_condition( destination_address_required ); + case WSAEFAULT: return make_error_condition( bad_address ); + case WSAEHOSTUNREACH: return make_error_condition( host_unreachable ); + case WSAEINPROGRESS: return make_error_condition( operation_in_progress ); + case WSAEINTR: return make_error_condition( interrupted ); + case WSAEINVAL: return make_error_condition( invalid_argument ); + case WSAEISCONN: return make_error_condition( already_connected ); + case WSAEMFILE: return make_error_condition( too_many_files_open ); + case WSAEMSGSIZE: return make_error_condition( message_size ); + case WSAENAMETOOLONG: return make_error_condition( filename_too_long ); + case WSAENETDOWN: return make_error_condition( network_down ); + case WSAENETRESET: return make_error_condition( network_reset ); + case WSAENETUNREACH: return make_error_condition( network_unreachable ); + case WSAENOBUFS: return make_error_condition( no_buffer_space ); + case WSAENOPROTOOPT: return make_error_condition( no_protocol_option ); + case WSAENOTCONN: return make_error_condition( not_connected ); + case WSAENOTSOCK: return make_error_condition( not_a_socket ); + case WSAEOPNOTSUPP: return make_error_condition( operation_not_supported ); + case WSAEPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); + case WSAEPROTOTYPE: return make_error_condition( wrong_protocol_type ); + case WSAETIMEDOUT: return make_error_condition( timed_out ); + case WSAEWOULDBLOCK: return make_error_condition( operation_would_block ); + #endif + default: return error_condition( ev, system_category ); + } + } + +# if !defined( BOOST_WINDOWS_API ) + + std::string system_error_category::message( int ev ) const + { + return generic_category.message( ev ); + } +# else +// TODO: + +//Some quick notes on the implementation (sorry for the noise if +//someone has already mentioned them): +// +//- The ::LocalFree() usage isn't exception safe. +// +//See: +// +//<http://boost.cvs.sourceforge.net/boost/boost/boost/asio/system_exception.hpp?revision=1.1&view=markup> +// +//in the implementation of what() for an example. +// +//Cheers, +//Chris + std::string system_error_category::message( int ev ) const + { +# ifndef BOOST_NO_ANSI_APIS + LPVOID lpMsgBuf; + DWORD retval = ::FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + ev, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPSTR) &lpMsgBuf, + 0, + NULL + ); + if (retval == 0) + return std::string("Unknown error"); + + std::string str( static_cast<LPCSTR>(lpMsgBuf) ); + ::LocalFree( lpMsgBuf ); // free the buffer +# else // WinCE workaround + LPVOID lpMsgBuf; + DWORD retval = ::FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + ev, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPWSTR) &lpMsgBuf, + 0, + NULL + ); + if (retval == 0) + return std::string("Unknown error"); + + int num_chars = (wcslen( static_cast<LPCWSTR>(lpMsgBuf) ) + 1) * 2; + LPSTR narrow_buffer = (LPSTR)_alloca( num_chars ); + if (::WideCharToMultiByte(CP_ACP, 0, static_cast<LPCWSTR>(lpMsgBuf), -1, narrow_buffer, num_chars, NULL, NULL) == 0) + return std::string("Unknown error"); + + std::string str( narrow_buffer ); + ::LocalFree( lpMsgBuf ); // free the buffer +# endif + while ( str.size() + && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') ) + str.erase( str.size()-1 ); + if ( str.size() && str[str.size()-1] == '.' ) + { str.erase( str.size()-1 ); } + return str; + } +# endif + +} // unnamed namespace + +namespace boost +{ + namespace system + { + + BOOST_SYSTEM_DECL error_code throws; // "throw on error" special error_code; + // note that it doesn't matter if this + // isn't initialized before use since + // the only use is to take its + // address for comparison purposes + + BOOST_SYSTEM_DECL const error_category & get_system_category() + { + static const system_error_category system_category_const; + return system_category_const; + } + + BOOST_SYSTEM_DECL const error_category & get_generic_category() + { + static const generic_error_category generic_category_const; + return generic_category_const; + } + + } // namespace system +} // namespace boost diff --git a/3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp b/3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp new file mode 100644 index 0000000..8881303 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/exceptions.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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/thread/detail/config.hpp> + +#include <boost/thread/exceptions.hpp> +#include <cstring> +#include <string> + +namespace boost { + +thread_exception::thread_exception() + : m_sys_err(0) +{ +} + +thread_exception::thread_exception(int sys_err_code) + : m_sys_err(sys_err_code) +{ +} + +thread_exception::~thread_exception() throw() +{ +} + +int thread_exception::native_error() const +{ + return m_sys_err; +} + +lock_error::lock_error() +{ +} + +lock_error::lock_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +lock_error::~lock_error() throw() +{ +} + +const char* lock_error::what() const throw() +{ + return "boost::lock_error"; +} + +thread_resource_error::thread_resource_error() +{ +} + +thread_resource_error::thread_resource_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +thread_resource_error::~thread_resource_error() throw() +{ +} + +const char* thread_resource_error::what() const throw() +{ + return "boost::thread_resource_error"; +} + +unsupported_thread_option::unsupported_thread_option() +{ +} + +unsupported_thread_option::unsupported_thread_option(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +unsupported_thread_option::~unsupported_thread_option() throw() +{ +} + +const char* unsupported_thread_option::what() const throw() +{ + return "boost::unsupported_thread_option"; +} + +invalid_thread_argument::invalid_thread_argument() +{ +} + +invalid_thread_argument::invalid_thread_argument(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +invalid_thread_argument::~invalid_thread_argument() throw() +{ +} + +const char* invalid_thread_argument::what() const throw() +{ + return "boost::invalid_thread_argument"; +} + +thread_permission_error::thread_permission_error() +{ +} + +thread_permission_error::thread_permission_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +thread_permission_error::~thread_permission_error() throw() +{ +} + +const char* thread_permission_error::what() const throw() +{ + return "boost::thread_permission_error"; +} + +} // namespace boost diff --git a/3rdParty/Boost/libs/thread/src/pthread/once.cpp b/3rdParty/Boost/libs/thread/src/pthread/once.cpp new file mode 100644 index 0000000..6e3722a --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/once.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2007 Anthony Williams +// +// 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) + +#define __STDC_CONSTANT_MACROS +#include <boost/thread/once.hpp> +#include <boost/assert.hpp> +#include <pthread.h> +#include <stdlib.h> + +namespace boost +{ + namespace detail + { + BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0); + BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; + BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; + + namespace + { + pthread_key_t epoch_tss_key; + pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT; + + extern "C" void delete_epoch_tss_data(void* data) + { + free(data); + } + + extern "C" void create_epoch_tss_key() + { + BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data)); + } + + } + + boost::uintmax_t& get_once_per_thread_epoch() + { + BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); + void* data=pthread_getspecific(epoch_tss_key); + if(!data) + { + data=malloc(sizeof(boost::uintmax_t)); + BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); + *static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0); + } + return *static_cast<boost::uintmax_t*>(data); + } + } + +} diff --git a/3rdParty/Boost/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/libs/thread/src/pthread/thread.cpp new file mode 100644 index 0000000..cc71d97 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/thread.cpp @@ -0,0 +1,678 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// +// 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/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/tss.hpp> +#ifdef __linux__ +#include <sys/sysinfo.h> +#elif defined(__APPLE__) || defined(__FreeBSD__) +#include <sys/types.h> +#include <sys/sysctl.h> +#elif defined BOOST_HAS_UNISTD_H +#include <unistd.h> +#endif + +#include "timeconv.inl" + +namespace boost +{ + namespace detail + { + thread_data_base::~thread_data_base() + {} + + struct thread_exit_callback_node + { + boost::detail::thread_exit_function_base* func; + thread_exit_callback_node* next; + + thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, + thread_exit_callback_node* next_): + func(func_),next(next_) + {} + }; + + struct tss_data_node + { + void const* key; + boost::shared_ptr<boost::detail::tss_cleanup_function> func; + void* value; + tss_data_node* next; + + tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_, + tss_data_node* next_): + key(key_),func(func_),value(value_),next(next_) + {} + }; + + namespace + { + boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; + pthread_key_t current_thread_tls_key; + + extern "C" + { + void tls_destructor(void* data) + { + boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data); + if(thread_info) + { + while(thread_info->tss_data || thread_info->thread_exit_callbacks) + { + while(thread_info->thread_exit_callbacks) + { + detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks; + thread_info->thread_exit_callbacks=current_node->next; + if(current_node->func) + { + (*current_node->func)(); + delete current_node->func; + } + delete current_node; + } + while(thread_info->tss_data) + { + detail::tss_data_node* const current_node=thread_info->tss_data; + thread_info->tss_data=current_node->next; + if(current_node->func) + { + (*current_node->func)(current_node->value); + } + delete current_node; + } + } + thread_info->self.reset(); + } + } + } + + + void create_current_thread_tls_key() + { + BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); + } + } + + boost::detail::thread_data_base* get_current_thread_data() + { + boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); + return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key); + } + + void set_current_thread_data(detail::thread_data_base* new_data) + { + boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); + BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); + } + } + + namespace + { + extern "C" + { + void* thread_proxy(void* param) + { + boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; + thread_info->self.reset(); + detail::set_current_thread_data(thread_info.get()); + try + { + thread_info->run(); + } + catch(thread_interrupted const&) + { + } +// Removed as it stops the debugger identifying the cause of the exception +// Unhandled exceptions still cause the application to terminate +// catch(...) +// { +// std::terminate(); +// } + + detail::tls_destructor(thread_info.get()); + detail::set_current_thread_data(0); + boost::lock_guard<boost::mutex> lock(thread_info->data_mutex); + thread_info->done=true; + thread_info->done_condition.notify_all(); + return 0; + } + } + + struct externally_launched_thread: + detail::thread_data_base + { + externally_launched_thread() + { + interrupt_enabled=false; + } + + void run() + {} + + private: + externally_launched_thread(externally_launched_thread&); + void operator=(externally_launched_thread&); + }; + + detail::thread_data_base* make_external_thread_data() + { + detail::thread_data_base* const me(new externally_launched_thread()); + me->self.reset(me); + set_current_thread_data(me); + return me; + } + + + detail::thread_data_base* get_or_make_current_thread_data() + { + detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + if(!current_thread_data) + { + current_thread_data=make_external_thread_data(); + } + return current_thread_data; + } + + } + + + thread::thread() + {} + + void thread::start_thread() + { + thread_info->self=thread_info; + int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get()); + if (res != 0) + { + thread_info->self.reset(); + throw thread_resource_error(); + } + } + + thread::~thread() + { + detach(); + } + + detail::thread_data_ptr thread::get_thread_info() const + { + lock_guard<mutex> l(thread_info_mutex); + return thread_info; + } + + void thread::join() + { + detail::thread_data_ptr const local_thread_info=get_thread_info(); + if(local_thread_info) + { + bool do_join=false; + + { + unique_lock<mutex> lock(local_thread_info->data_mutex); + while(!local_thread_info->done) + { + local_thread_info->done_condition.wait(lock); + } + do_join=!local_thread_info->join_started; + + if(do_join) + { + local_thread_info->join_started=true; + } + else + { + while(!local_thread_info->joined) + { + local_thread_info->done_condition.wait(lock); + } + } + } + if(do_join) + { + void* result=0; + BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); + lock_guard<mutex> lock(local_thread_info->data_mutex); + local_thread_info->joined=true; + local_thread_info->done_condition.notify_all(); + } + + lock_guard<mutex> l1(thread_info_mutex); + if(thread_info==local_thread_info) + { + thread_info.reset(); + } + } + } + + bool thread::timed_join(system_time const& wait_until) + { + detail::thread_data_ptr const local_thread_info=get_thread_info(); + if(local_thread_info) + { + bool do_join=false; + + { + unique_lock<mutex> lock(local_thread_info->data_mutex); + while(!local_thread_info->done) + { + if(!local_thread_info->done_condition.timed_wait(lock,wait_until)) + { + return false; + } + } + do_join=!local_thread_info->join_started; + + if(do_join) + { + local_thread_info->join_started=true; + } + else + { + while(!local_thread_info->joined) + { + local_thread_info->done_condition.wait(lock); + } + } + } + if(do_join) + { + void* result=0; + BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); + lock_guard<mutex> lock(local_thread_info->data_mutex); + local_thread_info->joined=true; + local_thread_info->done_condition.notify_all(); + } + + lock_guard<mutex> l1(thread_info_mutex); + if(thread_info==local_thread_info) + { + thread_info.reset(); + } + } + return true; + } + + bool thread::joinable() const + { + return get_thread_info(); + } + + + void thread::detach() + { + detail::thread_data_ptr local_thread_info; + { + lock_guard<mutex> l1(thread_info_mutex); + thread_info.swap(local_thread_info); + } + + if(local_thread_info) + { + lock_guard<mutex> lock(local_thread_info->data_mutex); + if(!local_thread_info->join_started) + { + BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle)); + local_thread_info->join_started=true; + local_thread_info->joined=true; + } + } + } + + namespace this_thread + { + + void sleep(const system_time& st) + { + detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + + if(thread_info) + { + unique_lock<mutex> lk(thread_info->sleep_mutex); + while(thread_info->sleep_condition.timed_wait(lk,st)); + } + else + { + xtime const xt=get_xtime(st); + + for (int foo=0; foo < 5; ++foo) + { +# if defined(BOOST_HAS_PTHREAD_DELAY_NP) + timespec ts; + to_timespec_duration(xt, ts); + BOOST_VERIFY(!pthread_delay_np(&ts)); +# elif defined(BOOST_HAS_NANOSLEEP) + timespec ts; + to_timespec_duration(xt, ts); + + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); +# else + mutex mx; + mutex::scoped_lock lock(mx); + condition cond; + cond.timed_wait(lock, xt); +# endif + xtime cur; + xtime_get(&cur, TIME_UTC); + if (xtime_cmp(xt, cur) <= 0) + return; + } + } + } + + void yield() + { +# if defined(BOOST_HAS_SCHED_YIELD) + BOOST_VERIFY(!sched_yield()); +# elif defined(BOOST_HAS_PTHREAD_YIELD) + BOOST_VERIFY(!pthread_yield()); +# else + xtime xt; + xtime_get(&xt, TIME_UTC); + sleep(xt); +# endif + } + } + + unsigned thread::hardware_concurrency() + { +#if defined(PTW32_VERSION) || defined(__hpux) + return pthread_num_processors_np(); +#elif defined(__linux__) + return get_nprocs(); +#elif defined(__APPLE__) || defined(__FreeBSD__) + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count; +#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) + int const count=sysconf(_SC_NPROCESSORS_ONLN); + return (count>0)?count:0; +#else + return 0; +#endif + } + + thread::id thread::get_id() const + { + detail::thread_data_ptr const local_thread_info=get_thread_info(); + if(local_thread_info) + { + return id(local_thread_info); + } + else + { + return id(); + } + } + + void thread::interrupt() + { + detail::thread_data_ptr const local_thread_info=get_thread_info(); + if(local_thread_info) + { + lock_guard<mutex> lk(local_thread_info->data_mutex); + local_thread_info->interrupt_requested=true; + if(local_thread_info->current_cond) + { + BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond)); + } + } + } + + bool thread::interruption_requested() const + { + detail::thread_data_ptr const local_thread_info=get_thread_info(); + if(local_thread_info) + { + lock_guard<mutex> lk(local_thread_info->data_mutex); + return local_thread_info->interrupt_requested; + } + else + { + return false; + } + } + + thread::native_handle_type thread::native_handle() + { + detail::thread_data_ptr const local_thread_info=get_thread_info(); + if(local_thread_info) + { + lock_guard<mutex> lk(local_thread_info->data_mutex); + return local_thread_info->thread_handle; + } + else + { + return pthread_t(); + } + } + + + + namespace this_thread + { + thread::id get_id() + { + boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); + return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr()); + } + + void interruption_point() + { + boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + if(thread_info && thread_info->interrupt_enabled) + { + lock_guard<mutex> lg(thread_info->data_mutex); + if(thread_info->interrupt_requested) + { + thread_info->interrupt_requested=false; + throw thread_interrupted(); + } + } + } + + bool interruption_enabled() + { + boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + return thread_info && thread_info->interrupt_enabled; + } + + bool interruption_requested() + { + boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + if(!thread_info) + { + return false; + } + else + { + lock_guard<mutex> lg(thread_info->data_mutex); + return thread_info->interrupt_requested; + } + } + + disable_interruption::disable_interruption(): + interruption_was_enabled(interruption_enabled()) + { + if(interruption_was_enabled) + { + detail::get_current_thread_data()->interrupt_enabled=false; + } + } + + disable_interruption::~disable_interruption() + { + if(detail::get_current_thread_data()) + { + detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled; + } + } + + restore_interruption::restore_interruption(disable_interruption& d) + { + if(d.interruption_was_enabled) + { + detail::get_current_thread_data()->interrupt_enabled=true; + } + } + + restore_interruption::~restore_interruption() + { + if(detail::get_current_thread_data()) + { + detail::get_current_thread_data()->interrupt_enabled=false; + } + } + } + + namespace detail + { + void add_thread_exit_function(thread_exit_function_base* func) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + thread_exit_callback_node* const new_node= + new thread_exit_callback_node(func,current_thread_data->thread_exit_callbacks); + current_thread_data->thread_exit_callbacks=new_node; + } + + tss_data_node* find_tss_data(void const* key) + { + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + detail::tss_data_node* current_node=current_thread_data->tss_data; + while(current_node) + { + if(current_node->key==key) + { + return current_node; + } + current_node=current_node->next; + } + } + return NULL; + } + + void* get_tss_data(void const* key) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + return current_node->value; + } + return NULL; + } + + void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + if(cleanup_existing && current_node->func) + { + (*current_node->func)(current_node->value); + } + current_node->func=func; + current_node->value=tss_data; + } + else + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + tss_data_node* const new_node=new tss_data_node(key,func,tss_data,current_thread_data->tss_data); + current_thread_data->tss_data=new_node; + } + } + } + +// thread_group::thread_group() +// { +// } + +// thread_group::~thread_group() +// { +// // We shouldn't have to scoped_lock here, since referencing this object +// // from another thread while we're deleting it in the current thread is +// // going to lead to undefined behavior any way. +// for (std::list<thread*>::iterator it = m_threads.begin(); +// it != m_threads.end(); ++it) +// { +// delete (*it); +// } +// } + +// thread* thread_group::create_thread(const function0<void>& threadfunc) +// { +// // No scoped_lock required here since the only "shared data" that's +// // modified here occurs inside add_thread which does scoped_lock. +// std::auto_ptr<thread> thrd(new thread(threadfunc)); +// add_thread(thrd.get()); +// return thrd.release(); +// } + +// void thread_group::add_thread(thread* thrd) +// { +// mutex::scoped_lock scoped_lock(m_mutex); + +// // For now we'll simply ignore requests to add a thread object multiple +// // times. Should we consider this an error and either throw or return an +// // error value? +// std::list<thread*>::iterator it = std::find(m_threads.begin(), +// m_threads.end(), thrd); +// BOOST_ASSERT(it == m_threads.end()); +// if (it == m_threads.end()) +// m_threads.push_back(thrd); +// } + +// void thread_group::remove_thread(thread* thrd) +// { +// mutex::scoped_lock scoped_lock(m_mutex); + +// // For now we'll simply ignore requests to remove a thread object that's +// // not in the group. Should we consider this an error and either throw or +// // return an error value? +// std::list<thread*>::iterator it = std::find(m_threads.begin(), +// m_threads.end(), thrd); +// BOOST_ASSERT(it != m_threads.end()); +// if (it != m_threads.end()) +// m_threads.erase(it); +// } + +// void thread_group::join_all() +// { +// mutex::scoped_lock scoped_lock(m_mutex); +// for (std::list<thread*>::iterator it = m_threads.begin(); +// it != m_threads.end(); ++it) +// { +// (*it)->join(); +// } +// } + +// void thread_group::interrupt_all() +// { +// boost::lock_guard<mutex> guard(m_mutex); + +// for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end(); +// it!=end; +// ++it) +// { +// (*it)->interrupt(); +// } +// } + + +// size_t thread_group::size() const +// { +// return m_threads.size(); +// } + +} diff --git a/3rdParty/Boost/libs/thread/src/pthread/timeconv.inl b/3rdParty/Boost/libs/thread/src/pthread/timeconv.inl new file mode 100644 index 0000000..5ec3b17 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/pthread/timeconv.inl @@ -0,0 +1,130 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +// boostinspect:nounnamed + +namespace { +const int MILLISECONDS_PER_SECOND = 1000; +const int NANOSECONDS_PER_SECOND = 1000000000; +const int NANOSECONDS_PER_MILLISECOND = 1000000; + +const int MICROSECONDS_PER_SECOND = 1000000; +const int NANOSECONDS_PER_MICROSECOND = 1000; + +inline void to_time(int milliseconds, boost::xtime& xt) +{ + int res = 0; + res = boost::xtime_get(&xt, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); + xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND); + + if (xt.nsec >= NANOSECONDS_PER_SECOND) + { + ++xt.sec; + xt.nsec -= NANOSECONDS_PER_SECOND; + } +} + +#if defined(BOOST_HAS_PTHREADS) +inline void to_timespec(const boost::xtime& xt, timespec& ts) +{ + ts.tv_sec = static_cast<int>(xt.sec); + ts.tv_nsec = static_cast<int>(xt.nsec); + if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) + { + ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; + ts.tv_nsec %= NANOSECONDS_PER_SECOND; + } +} + +inline void to_time(int milliseconds, timespec& ts) +{ + boost::xtime xt; + to_time(milliseconds, xt); + to_timespec(xt, ts); +} + +inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) +{ + boost::xtime cur; + int res = 0; + res = boost::xtime_get(&cur, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + if (boost::xtime_cmp(xt, cur) <= 0) + { + ts.tv_sec = 0; + ts.tv_nsec = 0; + } + else + { + ts.tv_sec = xt.sec - cur.sec; + ts.tv_nsec = xt.nsec - cur.nsec; + + if( ts.tv_nsec < 0 ) + { + ts.tv_sec -= 1; + ts.tv_nsec += NANOSECONDS_PER_SECOND; + } + if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) + { + ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; + ts.tv_nsec %= NANOSECONDS_PER_SECOND; + } + } +} +#endif + +inline void to_duration(boost::xtime xt, int& milliseconds) +{ + boost::xtime cur; + int res = 0; + res = boost::xtime_get(&cur, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + if (boost::xtime_cmp(xt, cur) <= 0) + milliseconds = 0; + else + { + if (cur.nsec > xt.nsec) + { + xt.nsec += NANOSECONDS_PER_SECOND; + --xt.sec; + } + milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) + + (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) / + NANOSECONDS_PER_MILLISECOND); + } +} + +inline void to_microduration(boost::xtime xt, int& microseconds) +{ + boost::xtime cur; + int res = 0; + res = boost::xtime_get(&cur, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + if (boost::xtime_cmp(xt, cur) <= 0) + microseconds = 0; + else + { + if (cur.nsec > xt.nsec) + { + xt.nsec += NANOSECONDS_PER_SECOND; + --xt.sec; + } + microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) + + (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) / + NANOSECONDS_PER_MICROSECOND); + } +} +} + +// Change Log: +// 1 Jun 01 Initial creation. diff --git a/3rdParty/Boost/libs/thread/src/tss_null.cpp b/3rdParty/Boost/libs/thread/src/tss_null.cpp new file mode 100644 index 0000000..ff13b30 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/tss_null.cpp @@ -0,0 +1,34 @@ +// (C) Copyright Michael Glassford 2004. +// (C) Copyright 2007 Anthony Williams +// 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) + +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE)) + + /* + This file is a "null" implementation of tss cleanup; it's + purpose is to to eliminate link errors in cases + where it is known that tss cleanup is not needed. + */ + + extern "C" void tss_cleanup_implemented(void) + { + /* + This function's sole purpose is to cause a link error in cases where + automatic tss cleanup is not implemented by Boost.Threads as a + reminder that user code is responsible for calling the necessary + functions at the appropriate times (and for implementing an a + tss_cleanup_implemented() function to eliminate the linker's + missing symbol error). + + If Boost.Threads later implements automatic tss cleanup in cases + where it currently doesn't (which is the plan), the duplicate + symbol error will warn the user that their custom solution is no + longer needed and can be removed. + */ + } + +#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER) diff --git a/3rdParty/Boost/libs/thread/src/win32/exceptions.cpp b/3rdParty/Boost/libs/thread/src/win32/exceptions.cpp new file mode 100644 index 0000000..8881303 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/exceptions.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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/thread/detail/config.hpp> + +#include <boost/thread/exceptions.hpp> +#include <cstring> +#include <string> + +namespace boost { + +thread_exception::thread_exception() + : m_sys_err(0) +{ +} + +thread_exception::thread_exception(int sys_err_code) + : m_sys_err(sys_err_code) +{ +} + +thread_exception::~thread_exception() throw() +{ +} + +int thread_exception::native_error() const +{ + return m_sys_err; +} + +lock_error::lock_error() +{ +} + +lock_error::lock_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +lock_error::~lock_error() throw() +{ +} + +const char* lock_error::what() const throw() +{ + return "boost::lock_error"; +} + +thread_resource_error::thread_resource_error() +{ +} + +thread_resource_error::thread_resource_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +thread_resource_error::~thread_resource_error() throw() +{ +} + +const char* thread_resource_error::what() const throw() +{ + return "boost::thread_resource_error"; +} + +unsupported_thread_option::unsupported_thread_option() +{ +} + +unsupported_thread_option::unsupported_thread_option(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +unsupported_thread_option::~unsupported_thread_option() throw() +{ +} + +const char* unsupported_thread_option::what() const throw() +{ + return "boost::unsupported_thread_option"; +} + +invalid_thread_argument::invalid_thread_argument() +{ +} + +invalid_thread_argument::invalid_thread_argument(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +invalid_thread_argument::~invalid_thread_argument() throw() +{ +} + +const char* invalid_thread_argument::what() const throw() +{ + return "boost::invalid_thread_argument"; +} + +thread_permission_error::thread_permission_error() +{ +} + +thread_permission_error::thread_permission_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +thread_permission_error::~thread_permission_error() throw() +{ +} + +const char* thread_permission_error::what() const throw() +{ + return "boost::thread_permission_error"; +} + +} // namespace boost diff --git a/3rdParty/Boost/libs/thread/src/win32/thread.cpp b/3rdParty/Boost/libs/thread/src/win32/thread.cpp new file mode 100644 index 0000000..a72f053 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/thread.cpp @@ -0,0 +1,597 @@ +// 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) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins + +#define _WIN32_WINNT 0x400 +#define WINVER 0x400 + +#include <boost/thread/thread.hpp> +#include <algorithm> +#include <windows.h> +#ifndef UNDER_CE +#include <process.h> +#endif +#include <stdio.h> +#include <boost/thread/once.hpp> +#include <boost/thread/tss.hpp> +#include <boost/assert.hpp> +#include <boost/thread/detail/tss_hooks.hpp> +#include <boost/date_time/posix_time/conversion.hpp> + +namespace boost +{ + namespace + { + boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; + DWORD current_thread_tls_key=0; + + void create_current_thread_tls_key() + { + tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in + current_thread_tls_key=TlsAlloc(); + BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES); + } + + void cleanup_tls_key() + { + if(current_thread_tls_key) + { + TlsFree(current_thread_tls_key); + current_thread_tls_key=0; + } + } + + detail::thread_data_base* get_current_thread_data() + { + if(!current_thread_tls_key) + { + return 0; + } + return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); + } + + void set_current_thread_data(detail::thread_data_base* new_data) + { + boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); + BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); + } + +#ifdef BOOST_NO_THREADEX +// Windows CE doesn't define _beginthreadex + + struct ThreadProxyData + { + typedef unsigned (__stdcall* func)(void*); + func start_address_; + void* arglist_; + ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {} + }; + + DWORD WINAPI ThreadProxy(LPVOID args) + { + ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args); + DWORD ret=data->start_address_(data->arglist_); + delete data; + return ret; + } + + typedef void* uintptr_t; + + inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), + void* arglist, unsigned initflag, unsigned* thrdaddr) + { + DWORD threadID; + HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy, + new ThreadProxyData(start_address,arglist),initflag,&threadID); + if (hthread!=0) + *thrdaddr=threadID; + return reinterpret_cast<uintptr_t const>(hthread); + } + +#endif + + } + + namespace detail + { + struct thread_exit_callback_node + { + boost::detail::thread_exit_function_base* func; + thread_exit_callback_node* next; + + thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, + thread_exit_callback_node* next_): + func(func_),next(next_) + {} + }; + + struct tss_data_node + { + void const* key; + boost::shared_ptr<boost::detail::tss_cleanup_function> func; + void* value; + tss_data_node* next; + + tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_, + tss_data_node* next_): + key(key_),func(func_),value(value_),next(next_) + {} + }; + + } + + namespace + { + void run_thread_exit_callbacks() + { + detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); + if(current_thread_data) + { + while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) + { + while(current_thread_data->thread_exit_callbacks) + { + detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks; + current_thread_data->thread_exit_callbacks=current_node->next; + if(current_node->func) + { + (*current_node->func)(); + boost::detail::heap_delete(current_node->func); + } + boost::detail::heap_delete(current_node); + } + while(current_thread_data->tss_data) + { + detail::tss_data_node* const current_node=current_thread_data->tss_data; + current_thread_data->tss_data=current_node->next; + if(current_node->func) + { + (*current_node->func)(current_node->value); + } + boost::detail::heap_delete(current_node); + } + } + + set_current_thread_data(0); + } + } + + unsigned __stdcall thread_start_function(void* param) + { + detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); + set_current_thread_data(thread_info); + try + { + thread_info->run(); + } + catch(thread_interrupted const&) + { + } +// Removed as it stops the debugger identifying the cause of the exception +// Unhandled exceptions still cause the application to terminate +// catch(...) +// { +// std::terminate(); +// } + run_thread_exit_callbacks(); + return 0; + } + } + + thread::thread() + {} + + void thread::start_thread() + { + uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); + if(!new_thread) + { + throw thread_resource_error(); + } + intrusive_ptr_add_ref(thread_info.get()); + thread_info->thread_handle=(detail::win32::handle)(new_thread); + ResumeThread(thread_info->thread_handle); + } + + thread::thread(detail::thread_data_ptr data): + thread_info(data) + {} + + namespace + { + struct externally_launched_thread: + detail::thread_data_base + { + externally_launched_thread() + { + ++count; + interruption_enabled=false; + } + + void run() + {} + private: + externally_launched_thread(externally_launched_thread&); + void operator=(externally_launched_thread&); + }; + + void make_external_thread_data() + { + externally_launched_thread* me=detail::heap_new<externally_launched_thread>(); + set_current_thread_data(me); + } + + detail::thread_data_base* get_or_make_current_thread_data() + { + detail::thread_data_base* current_thread_data(get_current_thread_data()); + if(!current_thread_data) + { + make_external_thread_data(); + current_thread_data=get_current_thread_data(); + } + return current_thread_data; + } + + } + + thread::~thread() + { + detach(); + } + + thread::id thread::get_id() const + { + return thread::id(get_thread_info()); + } + + bool thread::joinable() const + { + return get_thread_info(); + } + + void thread::join() + { + detail::thread_data_ptr local_thread_info=get_thread_info(); + if(local_thread_info) + { + this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel()); + release_handle(); + } + } + + bool thread::timed_join(boost::system_time const& wait_until) + { + detail::thread_data_ptr local_thread_info=get_thread_info(); + if(local_thread_info) + { + if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until))) + { + return false; + } + release_handle(); + } + return true; + } + + void thread::detach() + { + release_handle(); + } + + void thread::release_handle() + { + lock_guard<mutex> l1(thread_info_mutex); + thread_info=0; + } + + void thread::interrupt() + { + detail::thread_data_ptr local_thread_info=get_thread_info(); + if(local_thread_info) + { + local_thread_info->interrupt(); + } + } + + bool thread::interruption_requested() const + { + detail::thread_data_ptr local_thread_info=get_thread_info(); + return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); + } + + unsigned thread::hardware_concurrency() + { + SYSTEM_INFO info={0}; + GetSystemInfo(&info); + return info.dwNumberOfProcessors; + } + + thread::native_handle_type thread::native_handle() + { + detail::thread_data_ptr local_thread_info=get_thread_info(); + return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value; + } + + detail::thread_data_ptr thread::get_thread_info() const + { + boost::mutex::scoped_lock l(thread_info_mutex); + return thread_info; + } + + namespace this_thread + { + namespace + { + LARGE_INTEGER get_due_time(detail::timeout const& target_time) + { + LARGE_INTEGER due_time={0}; + if(target_time.relative) + { + unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start; + LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds); + LONGLONG const hundred_nanoseconds_in_one_millisecond=10000; + + if(remaining_milliseconds>0) + { + due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond); + } + } + else + { + SYSTEMTIME target_system_time={0}; + target_system_time.wYear=target_time.abs_time.date().year(); + target_system_time.wMonth=target_time.abs_time.date().month(); + target_system_time.wDay=target_time.abs_time.date().day(); + target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours(); + target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes(); + target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds(); + + if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time))) + { + due_time.QuadPart=0; + } + else + { + long const hundred_nanoseconds_in_one_second=10000000; + due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second()); + } + } + return due_time; + } + } + + + bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) + { + detail::win32::handle handles[3]={0}; + unsigned handle_count=0; + unsigned wait_handle_index=~0U; + unsigned interruption_index=~0U; + unsigned timeout_index=~0U; + if(handle_to_wait_for!=detail::win32::invalid_handle_value) + { + wait_handle_index=handle_count; + handles[handle_count++]=handle_to_wait_for; + } + if(get_current_thread_data() && get_current_thread_data()->interruption_enabled) + { + interruption_index=handle_count; + handles[handle_count++]=get_current_thread_data()->interruption_handle; + } + + detail::win32::handle_manager timer_handle; + +#ifndef UNDER_CE + unsigned const min_timer_wait_period=20; + + if(!target_time.is_sentinel()) + { + detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); + if(time_left.milliseconds > min_timer_wait_period) + { + // for a long-enough timeout, use a waitable timer (which tracks clock changes) + timer_handle=CreateWaitableTimer(NULL,false,NULL); + if(timer_handle!=0) + { + LARGE_INTEGER due_time=get_due_time(target_time); + + bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; + if(set_time_succeeded) + { + timeout_index=handle_count; + handles[handle_count++]=timer_handle; + } + } + } + else if(!target_time.relative) + { + // convert short absolute-time timeouts into relative ones, so we don't race against clock changes + target_time=detail::timeout(time_left.milliseconds); + } + } +#endif + + bool const using_timer=timeout_index!=~0u; + detail::timeout::remaining_time time_left(0); + + do + { + if(!using_timer) + { + time_left=target_time.remaining_milliseconds(); + } + + if(handle_count) + { + unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds); + if(notified_index<handle_count) + { + if(notified_index==wait_handle_index) + { + return true; + } + else if(notified_index==interruption_index) + { + detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); + throw thread_interrupted(); + } + else if(notified_index==timeout_index) + { + return false; + } + } + } + else + { + detail::win32::Sleep(time_left.milliseconds); + } + if(target_time.relative) + { + target_time.milliseconds-=detail::timeout::max_non_infinite_wait; + } + } + while(time_left.more); + return false; + } + + thread::id get_id() + { + return thread::id(get_or_make_current_thread_data()); + } + + void interruption_point() + { + if(interruption_enabled() && interruption_requested()) + { + detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); + throw thread_interrupted(); + } + } + + bool interruption_enabled() + { + return get_current_thread_data() && get_current_thread_data()->interruption_enabled; + } + + bool interruption_requested() + { + return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); + } + + void yield() + { + detail::win32::Sleep(0); + } + + disable_interruption::disable_interruption(): + interruption_was_enabled(interruption_enabled()) + { + if(interruption_was_enabled) + { + get_current_thread_data()->interruption_enabled=false; + } + } + + disable_interruption::~disable_interruption() + { + if(get_current_thread_data()) + { + get_current_thread_data()->interruption_enabled=interruption_was_enabled; + } + } + + restore_interruption::restore_interruption(disable_interruption& d) + { + if(d.interruption_was_enabled) + { + get_current_thread_data()->interruption_enabled=true; + } + } + + restore_interruption::~restore_interruption() + { + if(get_current_thread_data()) + { + get_current_thread_data()->interruption_enabled=false; + } + } + } + + namespace detail + { + void add_thread_exit_function(thread_exit_function_base* func) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + thread_exit_callback_node* const new_node= + heap_new<thread_exit_callback_node>(func, + current_thread_data->thread_exit_callbacks); + current_thread_data->thread_exit_callbacks=new_node; + } + + tss_data_node* find_tss_data(void const* key) + { + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + detail::tss_data_node* current_node=current_thread_data->tss_data; + while(current_node) + { + if(current_node->key==key) + { + return current_node; + } + current_node=current_node->next; + } + } + return NULL; + } + + void* get_tss_data(void const* key) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + return current_node->value; + } + return NULL; + } + + void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + if(cleanup_existing && current_node->func.get()) + { + (*current_node->func)(current_node->value); + } + current_node->func=func; + current_node->value=tss_data; + } + else + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data); + current_thread_data->tss_data=new_node; + } + } + } +} + + +extern "C" BOOST_THREAD_DECL void on_process_enter() +{} + +extern "C" BOOST_THREAD_DECL void on_thread_enter() +{} + +extern "C" BOOST_THREAD_DECL void on_process_exit() +{ + boost::cleanup_tls_key(); +} + +extern "C" BOOST_THREAD_DECL void on_thread_exit() +{ + boost::run_thread_exit_callbacks(); +} + diff --git a/3rdParty/Boost/libs/thread/src/win32/timeconv.inl b/3rdParty/Boost/libs/thread/src/win32/timeconv.inl new file mode 100644 index 0000000..5ec3b17 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/timeconv.inl @@ -0,0 +1,130 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +// boostinspect:nounnamed + +namespace { +const int MILLISECONDS_PER_SECOND = 1000; +const int NANOSECONDS_PER_SECOND = 1000000000; +const int NANOSECONDS_PER_MILLISECOND = 1000000; + +const int MICROSECONDS_PER_SECOND = 1000000; +const int NANOSECONDS_PER_MICROSECOND = 1000; + +inline void to_time(int milliseconds, boost::xtime& xt) +{ + int res = 0; + res = boost::xtime_get(&xt, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); + xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND); + + if (xt.nsec >= NANOSECONDS_PER_SECOND) + { + ++xt.sec; + xt.nsec -= NANOSECONDS_PER_SECOND; + } +} + +#if defined(BOOST_HAS_PTHREADS) +inline void to_timespec(const boost::xtime& xt, timespec& ts) +{ + ts.tv_sec = static_cast<int>(xt.sec); + ts.tv_nsec = static_cast<int>(xt.nsec); + if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) + { + ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; + ts.tv_nsec %= NANOSECONDS_PER_SECOND; + } +} + +inline void to_time(int milliseconds, timespec& ts) +{ + boost::xtime xt; + to_time(milliseconds, xt); + to_timespec(xt, ts); +} + +inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) +{ + boost::xtime cur; + int res = 0; + res = boost::xtime_get(&cur, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + if (boost::xtime_cmp(xt, cur) <= 0) + { + ts.tv_sec = 0; + ts.tv_nsec = 0; + } + else + { + ts.tv_sec = xt.sec - cur.sec; + ts.tv_nsec = xt.nsec - cur.nsec; + + if( ts.tv_nsec < 0 ) + { + ts.tv_sec -= 1; + ts.tv_nsec += NANOSECONDS_PER_SECOND; + } + if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) + { + ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; + ts.tv_nsec %= NANOSECONDS_PER_SECOND; + } + } +} +#endif + +inline void to_duration(boost::xtime xt, int& milliseconds) +{ + boost::xtime cur; + int res = 0; + res = boost::xtime_get(&cur, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + if (boost::xtime_cmp(xt, cur) <= 0) + milliseconds = 0; + else + { + if (cur.nsec > xt.nsec) + { + xt.nsec += NANOSECONDS_PER_SECOND; + --xt.sec; + } + milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) + + (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) / + NANOSECONDS_PER_MILLISECOND); + } +} + +inline void to_microduration(boost::xtime xt, int& microseconds) +{ + boost::xtime cur; + int res = 0; + res = boost::xtime_get(&cur, boost::TIME_UTC); + assert(res == boost::TIME_UTC); + + if (boost::xtime_cmp(xt, cur) <= 0) + microseconds = 0; + else + { + if (cur.nsec > xt.nsec) + { + xt.nsec += NANOSECONDS_PER_SECOND; + --xt.sec; + } + microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) + + (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) / + NANOSECONDS_PER_MICROSECOND); + } +} +} + +// Change Log: +// 1 Jun 01 Initial creation. diff --git a/3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp b/3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp new file mode 100644 index 0000000..0522a12 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/tss_dll.cpp @@ -0,0 +1,72 @@ +// (C) Copyright Michael Glassford 2004. +// 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) + +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL) + + #include <boost/thread/detail/tss_hooks.hpp> + + #define WIN32_LEAN_AND_MEAN + #include <windows.h> + + #if defined(__BORLANDC__) + extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) + #elif defined(_WIN32_WCE) + extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) + #else + extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) + #endif + { + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + { + on_process_enter(); + on_thread_enter(); + break; + } + + case DLL_THREAD_ATTACH: + { + on_thread_enter(); + break; + } + + case DLL_THREAD_DETACH: + { + on_thread_exit(); + break; + } + + case DLL_PROCESS_DETACH: + { + on_thread_exit(); + on_process_exit(); + break; + } + } + + return TRUE; + } + + extern "C" void tss_cleanup_implemented(void) + { + /* + This function's sole purpose is to cause a link error in cases where + automatic tss cleanup is not implemented by Boost.Threads as a + reminder that user code is responsible for calling the necessary + functions at the appropriate times (and for implementing an a + tss_cleanup_implemented() function to eliminate the linker's + missing symbol error). + + If Boost.Threads later implements automatic tss cleanup in cases + where it currently doesn't (which is the plan), the duplicate + symbol error will warn the user that their custom solution is no + longer needed and can be removed. + */ + } + +#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL) diff --git a/3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp b/3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp new file mode 100644 index 0000000..ae89bc4 --- /dev/null +++ b/3rdParty/Boost/libs/thread/src/win32/tss_pe.cpp @@ -0,0 +1,287 @@ +// $Id: tss_pe.cpp 49324 2008-10-13 20:30:13Z anthonyw $ +// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. +// (C) Copyright 2007 Roland Schwarz +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins +// 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) + +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) + +#if defined(__MINGW32__) && !defined(_WIN64) + +#include <boost/thread/detail/tss_hooks.hpp> + +#include <windows.h> + +#include <cstdlib> + +extern "C" void tss_cleanup_implemented(void) {} + +namespace { + void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv) + { + switch (dwReason) + { + case DLL_THREAD_DETACH: + { + on_thread_exit(); + break; + } + } + } + + void on_after_ctors(void) + { + on_process_enter(); + } + + void on_before_dtors(void) + { + on_thread_exit(); + } + + void on_after_dtors(void) + { + on_process_exit(); + } +} + +extern "C" { + + void (* after_ctors )(void) __attribute__((section(".ctors"))) = on_after_ctors; + void (* before_dtors)(void) __attribute__((section(".dtors"))) = on_before_dtors; + void (* after_dtors )(void) __attribute__((section(".dtors.zzz"))) = on_after_dtors; + + ULONG __tls_index__ = 0; + char __tls_end__ __attribute__((section(".tls$zzz"))) = 0; + char __tls_start__ __attribute__((section(".tls"))) = 0; + + + PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0; + PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback; + PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0; +} + +extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) = +{ + (DWORD) &__tls_start__, + (DWORD) &__tls_end__, + (DWORD) &__tls_index__, + (DWORD) (&__crt_xl_start__+1), + (DWORD) 0, + (DWORD) 0 +}; + + +#elif defined(_MSC_VER) && !defined(UNDER_CE) + + #include <boost/thread/detail/tss_hooks.hpp> + + #include <stdlib.h> + + #define WIN32_LEAN_AND_MEAN + #include <windows.h> + + //Definitions required by implementation + + #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 + typedef void (__cdecl *_PVFV)(void); + #define INIRETSUCCESS + #define PVAPI void + #else + typedef int (__cdecl *_PVFV)(void); + #define INIRETSUCCESS 0 + #define PVAPI int + #endif + + typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); + + //Symbols for connection to the runtime environment + + extern "C" + { + extern DWORD _tls_used; //the tls directory (located in .rdata segment) + extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */ + } + + namespace + { + //Forward declarations + + static PVAPI on_tls_prepare(void); + static PVAPI on_process_init(void); + static PVAPI on_process_term(void); + static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID); + + //The .CRT$Xxx information is taken from Codeguru: + //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ + +#if (_MSC_VER >= 1400) +#pragma section(".CRT$XIU",long,read) +#pragma section(".CRT$XCU",long,read) +#pragma section(".CRT$XTU",long,read) +#pragma section(".CRT$XLC",long,read) + __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; + __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare; + __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init; + __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term; +#else + #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 + # pragma data_seg(push, old_seg) + #endif + //Callback to run tls glue code first. + //I don't think it is necessary to run it + //at .CRT$XIB level, since we are only + //interested in thread detachement. But + //this could be changed easily if required. + + #pragma data_seg(".CRT$XIU") + static _PVFV p_tls_prepare = on_tls_prepare; + #pragma data_seg() + + //Callback after all global ctors. + + #pragma data_seg(".CRT$XCU") + static _PVFV p_process_init = on_process_init; + #pragma data_seg() + + //Callback for tls notifications. + + #pragma data_seg(".CRT$XLB") + _TLSCB p_thread_callback = on_tls_callback; + #pragma data_seg() + //Callback for termination. + + #pragma data_seg(".CRT$XTU") + static _PVFV p_process_term = on_process_term; + #pragma data_seg() + #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 + # pragma data_seg(pop, old_seg) + #endif +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4189) +#endif + + PVAPI on_tls_prepare(void) + { + //The following line has an important side effect: + //if the TLS directory is not already there, it will + //be created by the linker. In other words, it forces a tls + //directory to be generated by the linker even when static tls + //(i.e. __declspec(thread)) is not used. + //The volatile should prevent the optimizer + //from removing the reference. + + DWORD volatile dw = _tls_used; + + #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 + _TLSCB* pfbegin = __xl_a; + _TLSCB* pfend = __xl_z; + _TLSCB* pfdst = pfbegin; + //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; + + //The following loop will merge the address pointers + //into a contiguous area, since the tlssup code seems + //to require this (at least on MSVC 6) + + while (pfbegin < pfend) + { + if (*pfbegin != 0) + { + *pfdst = *pfbegin; + ++pfdst; + } + ++pfbegin; + } + + *pfdst = 0; + #endif + + return INIRETSUCCESS; + } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + PVAPI on_process_init(void) + { + //Schedule on_thread_exit() to be called for the main + //thread before destructors of global objects have been + //called. + + //It will not be run when 'quick' exiting the + //library; however, this is the standard behaviour + //for destructors of global objects, so that + //shouldn't be a problem. + + atexit(on_thread_exit); + + //Call Boost process entry callback here + + on_process_enter(); + + return INIRETSUCCESS; + } + + PVAPI on_process_term(void) + { + on_process_exit(); + return INIRETSUCCESS; + } + + void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/) + { + switch (dwReason) + { + case DLL_THREAD_DETACH: + on_thread_exit(); + break; + } + } + + BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID) + { + switch (dwReason) + { + case DLL_THREAD_DETACH: + on_thread_exit(); + break; + case DLL_PROCESS_DETACH: + on_process_exit(); + break; + } + return true; + } + } //namespace + +extern "C" +{ + extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback; +} + + extern "C" void tss_cleanup_implemented(void) + { + /* + This function's sole purpose is to cause a link error in cases where + automatic tss cleanup is not implemented by Boost.Threads as a + reminder that user code is responsible for calling the necessary + functions at the appropriate times (and for implementing an a + tss_cleanup_implemented() function to eliminate the linker's + missing symbol error). + + If Boost.Threads later implements automatic tss cleanup in cases + where it currently doesn't (which is the plan), the duplicate + symbol error will warn the user that their custom solution is no + longer needed and can be removed. + */ + } +#endif //defined(_MSC_VER) && !defined(UNDER_CE) + +#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) |