Merge branch 'date_lib_added'
commit
735de00f96
@ -0,0 +1,668 @@
|
||||
#ifndef CHRONO_IO_H
|
||||
#define CHRONO_IO_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that woud involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <ratio>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
|
||||
template <class CharT, std::size_t N>
|
||||
class string_literal
|
||||
{
|
||||
CharT p_[N];
|
||||
|
||||
public:
|
||||
using const_iterator = const CharT*;
|
||||
|
||||
string_literal(string_literal const&) = default;
|
||||
string_literal& operator=(string_literal const&) = delete;
|
||||
|
||||
template <std::size_t N1 = 2,
|
||||
class = std::enable_if_t<N1 == N>>
|
||||
constexpr string_literal(CharT c) noexcept
|
||||
: p_{c}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr string_literal(const CharT(&a)[N]) noexcept
|
||||
: p_{}
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
p_[i] = a[i];
|
||||
}
|
||||
|
||||
template <class U = CharT, class = std::enable_if_t<1 < sizeof(U)>>
|
||||
constexpr string_literal(const char(&a)[N]) noexcept
|
||||
: p_{}
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
p_[i] = a[i];
|
||||
}
|
||||
|
||||
template <class CharT2, class = std::enable_if_t<!std::is_same<CharT2, CharT>{}>>
|
||||
constexpr string_literal(string_literal<CharT2, N> const& a) noexcept
|
||||
: p_{}
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
p_[i] = a[i];
|
||||
}
|
||||
|
||||
template <std::size_t N1, std::size_t N2,
|
||||
class = std::enable_if_t<N1 + N2 - 1 == N>>
|
||||
constexpr string_literal(const string_literal<CharT, N1>& x,
|
||||
const string_literal<CharT, N2>& y) noexcept
|
||||
: p_{}
|
||||
{
|
||||
std::size_t i = 0;
|
||||
for (; i < N1-1; ++i)
|
||||
p_[i] = x[i];
|
||||
for (std::size_t j = 0; j < N2; ++j, ++i)
|
||||
p_[i] = y[j];
|
||||
}
|
||||
|
||||
constexpr const CharT* data() const noexcept {return p_;}
|
||||
constexpr std::size_t size() const noexcept {return N-1;}
|
||||
|
||||
constexpr const_iterator begin() const noexcept {return p_;}
|
||||
constexpr const_iterator end() const noexcept {return p_ + N-1;}
|
||||
|
||||
constexpr CharT const& operator[](std::size_t n) const noexcept
|
||||
{
|
||||
return p_[n];
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
friend
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
|
||||
{
|
||||
return os << s.p_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
|
||||
constexpr
|
||||
inline
|
||||
string_literal<std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>,
|
||||
N1 + N2 - 1>
|
||||
operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) noexcept
|
||||
{
|
||||
using CharT = std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>;
|
||||
return string_literal<CharT, N1 + N2 - 1>{string_literal<CharT, N1>{x},
|
||||
string_literal<CharT, N2>{y}};
|
||||
}
|
||||
|
||||
template <class CharT, std::size_t N>
|
||||
constexpr
|
||||
inline
|
||||
string_literal<CharT, N>
|
||||
msl(const CharT(&a)[N]) noexcept
|
||||
{
|
||||
return string_literal<CharT, N>{a};
|
||||
}
|
||||
|
||||
template <class CharT,
|
||||
class = std::enable_if_t<std::is_same<CharT, char>{} ||
|
||||
std::is_same<CharT, wchar_t>{} ||
|
||||
std::is_same<CharT, char16_t>{} ||
|
||||
std::is_same<CharT, char32_t>{}>>
|
||||
constexpr
|
||||
inline
|
||||
string_literal<CharT, 2>
|
||||
msl(CharT c) noexcept
|
||||
{
|
||||
return string_literal<CharT, 2>{c};
|
||||
}
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
to_string_len(std::intmax_t i)
|
||||
{
|
||||
std::size_t r = 0;
|
||||
do
|
||||
{
|
||||
i /= 10;
|
||||
++r;
|
||||
} while (i > 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <std::intmax_t N>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
N < 10,
|
||||
string_literal<char, to_string_len(N)+1>
|
||||
>
|
||||
msl() noexcept
|
||||
{
|
||||
return msl(char(N % 10 + '0'));
|
||||
}
|
||||
|
||||
template <std::intmax_t N>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
10 <= N,
|
||||
string_literal<char, to_string_len(N)+1>
|
||||
>
|
||||
msl() noexcept
|
||||
{
|
||||
return msl<N/10>() + msl(char(N % 10 + '0'));
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
std::ratio<N, D>::type::den != 1,
|
||||
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
|
||||
to_string_len(std::ratio<N, D>::type::den) + 4>
|
||||
>
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
|
||||
msl<R::den>() + msl(CharT{']'});
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
std::ratio<N, D>::type::den == 1,
|
||||
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
|
||||
>
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::atto) noexcept
|
||||
{
|
||||
return msl(CharT{'a'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::femto) noexcept
|
||||
{
|
||||
return msl(CharT{'f'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::pico) noexcept
|
||||
{
|
||||
return msl(CharT{'p'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::nano) noexcept
|
||||
{
|
||||
return msl(CharT{'n'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
std::is_same<CharT, char>{},
|
||||
string_literal<char, 3>
|
||||
>
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return string_literal<char, 3>{"\xC2\xB5"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
!std::is_same<CharT, char>{},
|
||||
string_literal<CharT, 2>
|
||||
>
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::milli) noexcept
|
||||
{
|
||||
return msl(CharT{'m'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::centi) noexcept
|
||||
{
|
||||
return msl(CharT{'c'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::deci) noexcept
|
||||
{
|
||||
return msl(CharT{'d'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::deca) noexcept
|
||||
{
|
||||
return string_literal<CharT, 3>{"da"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::hecto) noexcept
|
||||
{
|
||||
return msl(CharT{'h'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::kilo) noexcept
|
||||
{
|
||||
return msl(CharT{'k'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::mega) noexcept
|
||||
{
|
||||
return msl(CharT{'M'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::giga) noexcept
|
||||
{
|
||||
return msl(CharT{'G'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::tera) noexcept
|
||||
{
|
||||
return msl(CharT{'T'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::peta) noexcept
|
||||
{
|
||||
return msl(CharT{'P'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::exa) noexcept
|
||||
{
|
||||
return msl(CharT{'E'});
|
||||
}
|
||||
|
||||
template <class CharT, class Period>
|
||||
constexpr
|
||||
auto
|
||||
get_units(Period p)
|
||||
{
|
||||
return msl<CharT>(p) + string_literal<CharT, 2>{"s"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
auto
|
||||
get_units(std::ratio<1>)
|
||||
{
|
||||
return string_literal<CharT, 2>{"s"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
auto
|
||||
get_units(std::ratio<60>)
|
||||
{
|
||||
return string_literal<CharT, 4>{"min"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
auto
|
||||
get_units(std::ratio<3600>)
|
||||
{
|
||||
return string_literal<CharT, 2>{"h"};
|
||||
}
|
||||
|
||||
#else // __cplusplus < 201402
|
||||
|
||||
inline
|
||||
std::string
|
||||
to_string(std::uint64_t x)
|
||||
{
|
||||
return std::to_string(x);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
to_string(std::uint64_t x)
|
||||
{
|
||||
auto y = std::to_string(x);
|
||||
return std::basic_string<CharT>(y.begin(), y.end());
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::ratio<N, D>::type::den != 1,
|
||||
std::basic_string<CharT>
|
||||
>::type
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
|
||||
to_string<CharT>(R::den) + CharT{']'};
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::ratio<N, D>::type::den == 1,
|
||||
std::basic_string<CharT>
|
||||
>::type
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::atto) noexcept
|
||||
{
|
||||
return {'a'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::femto) noexcept
|
||||
{
|
||||
return {'f'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::pico) noexcept
|
||||
{
|
||||
return {'p'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::nano) noexcept
|
||||
{
|
||||
return {'n'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::is_same<CharT, char>::value,
|
||||
std::string
|
||||
>::type
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return "\xC2\xB5";
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
!std::is_same<CharT, char>::value,
|
||||
std::basic_string<CharT>
|
||||
>::type
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return {CharT(static_cast<unsigned char>('\xB5'))};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::milli) noexcept
|
||||
{
|
||||
return {'m'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::centi) noexcept
|
||||
{
|
||||
return {'c'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::deci) noexcept
|
||||
{
|
||||
return {'d'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::deca) noexcept
|
||||
{
|
||||
return {'d', 'a'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::hecto) noexcept
|
||||
{
|
||||
return {'h'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::kilo) noexcept
|
||||
{
|
||||
return {'k'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::mega) noexcept
|
||||
{
|
||||
return {'M'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::giga) noexcept
|
||||
{
|
||||
return {'G'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::tera) noexcept
|
||||
{
|
||||
return {'T'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::peta) noexcept
|
||||
{
|
||||
return {'P'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::exa) noexcept
|
||||
{
|
||||
return {'E'};
|
||||
}
|
||||
|
||||
template <class CharT, class Period>
|
||||
std::basic_string<CharT>
|
||||
get_units(Period p)
|
||||
{
|
||||
return msl<CharT>(p) + CharT{'s'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
get_units(std::ratio<1>)
|
||||
{
|
||||
return {'s'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
get_units(std::ratio<60>)
|
||||
{
|
||||
return {'m', 'i', 'n'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
get_units(std::ratio<3600>)
|
||||
{
|
||||
return {'h'};
|
||||
}
|
||||
|
||||
#endif // __cplusplus >= 201402
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class CharT, class Traits, class Rep, class Period>
|
||||
inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const std::chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
return os << d.count()
|
||||
<< detail::get_units<CharT>(typename Period::type{});
|
||||
}
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // CHRONO_IO_H
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@
|
||||
//
|
||||
// ios.h
|
||||
// DateTimeLib
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Alexander Kormanovsky
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef ios_hpp
|
||||
#define ios_hpp
|
||||
|
||||
#if __APPLE__
|
||||
# include <TargetConditionals.h>
|
||||
# if TARGET_OS_IPHONE
|
||||
# include <string>
|
||||
|
||||
namespace date
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
std::string get_tzdata_path();
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
||||
# endif // TARGET_OS_IPHONE
|
||||
#else // !__APPLE__
|
||||
# define TARGET_OS_IPHONE 0
|
||||
#endif // !__APPLE__
|
||||
#endif // ios_hpp
|
@ -0,0 +1,405 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Alexander Kormanovsky
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#include "ios.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <zlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef TAR_DEBUG
|
||||
# define TAR_DEBUG 0
|
||||
#endif
|
||||
|
||||
#define INTERNAL_DIR "Library/tzdata"
|
||||
#define TARGZ_EXTENSION "tar.gz"
|
||||
|
||||
#define TAR_BLOCK_SIZE 512
|
||||
#define TAR_TYPE_POSITION 156
|
||||
#define TAR_NAME_POSITION 0
|
||||
#define TAR_NAME_SIZE 100
|
||||
#define TAR_SIZE_POSITION 124
|
||||
#define TAR_SIZE_SIZE 12
|
||||
|
||||
namespace date
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
struct TarInfo
|
||||
{
|
||||
char objType;
|
||||
std::string objName;
|
||||
int64_t realContentSize; // writable size without padding zeroes
|
||||
int64_t blocksContentSize; // adjusted size to 512 bytes blocks
|
||||
bool success;
|
||||
};
|
||||
|
||||
char* convertCFStringRefPathToCStringPath(CFStringRef ref);
|
||||
bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath);
|
||||
TarInfo getTarObjectInfo(CFReadStreamRef readStream, int64_t location);
|
||||
std::string getTarObject(CFReadStreamRef readStream, int64_t size);
|
||||
bool writeFile(CFURLRef tzdataUrl, std::string fileName, std::string data,
|
||||
int64_t realContentSize);
|
||||
|
||||
std::string
|
||||
date::iOSUtils::get_tzdata_path()
|
||||
{
|
||||
CFURLRef ref = CFCopyHomeDirectoryURL();
|
||||
CFStringRef homePath = CFURLCopyPath(CFCopyHomeDirectoryURL());
|
||||
std::string tzdata_path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
|
||||
INTERNAL_DIR);
|
||||
|
||||
if (access(tzdata_path.c_str(), F_OK) == 0)
|
||||
{
|
||||
#if TAR_DEBUG
|
||||
printf("tzdata exists\n");
|
||||
#endif
|
||||
return tzdata_path;
|
||||
}
|
||||
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||
CFArrayRef paths = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR(TARGZ_EXTENSION),
|
||||
NULL);
|
||||
|
||||
if (CFArrayGetCount(paths) != 0)
|
||||
{
|
||||
// get archive path, assume there is no other tar.gz in bundle
|
||||
CFURLRef archiveUrl = static_cast<CFURLRef>(CFArrayGetValueAtIndex(paths, 0));
|
||||
CFStringRef archiveName= CFURLCopyPath(archiveUrl);
|
||||
archiveUrl = CFBundleCopyResourceURL(mainBundle, archiveName, NULL, NULL);
|
||||
|
||||
extractTzdata(CFCopyHomeDirectoryURL(), archiveUrl, tzdata_path);
|
||||
}
|
||||
|
||||
return tzdata_path;
|
||||
}
|
||||
|
||||
char*
|
||||
convertCFStringRefPathToCStringPath(CFStringRef ref)
|
||||
{
|
||||
CFIndex bufferSize = CFStringGetMaximumSizeOfFileSystemRepresentation(ref);
|
||||
char *buffer = new char[bufferSize];
|
||||
CFStringGetFileSystemRepresentation(ref, buffer, bufferSize);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath)
|
||||
{
|
||||
const char *TAR_TMP_PATH = "/tmp.tar";
|
||||
|
||||
// create Library path
|
||||
CFStringRef libraryStr = CFStringCreateWithCString(NULL, "Library",
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef libraryUrl = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
|
||||
homeUrl, libraryStr,
|
||||
false);
|
||||
|
||||
// create tzdata path
|
||||
CFStringRef tzdataPathRef = CFStringCreateWithCString(NULL, INTERNAL_DIR,
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef tzdataPathUrl = CFURLCreateCopyAppendingPathComponent(NULL, homeUrl,
|
||||
tzdataPathRef, false);
|
||||
|
||||
// create src archive path
|
||||
CFStringRef archivePath = CFURLCopyPath(archiveUrl);
|
||||
gzFile tarFile = gzopen(convertCFStringRefPathToCStringPath(archivePath), "rb");
|
||||
|
||||
// create tar unpacking path
|
||||
CFStringRef tarName = CFStringCreateWithCString(NULL, TAR_TMP_PATH,
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef tarUrl = CFURLCreateCopyAppendingPathComponent(NULL, libraryUrl, tarName,
|
||||
false);
|
||||
const char *tarPath = convertCFStringRefPathToCStringPath(CFURLCopyPath(tarUrl));
|
||||
|
||||
// create tzdata directory
|
||||
mkdir(destPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
|
||||
// create stream
|
||||
CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(NULL, tarUrl);
|
||||
bool success = true;
|
||||
|
||||
if (!CFWriteStreamOpen(writeStream))
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
|
||||
if (err.domain == kCFStreamErrorDomainPOSIX)
|
||||
{
|
||||
printf("kCFStreamErrorDomainPOSIX %i\n", err.error);
|
||||
}
|
||||
else if(err.domain == kCFStreamErrorDomainMacOSStatus)
|
||||
{
|
||||
printf("kCFStreamErrorDomainMacOSStatus %i\n", err.error);
|
||||
}
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ======= extract tar ========
|
||||
|
||||
unsigned int bufferLength = 1024 * 256; // 256Kb
|
||||
void *buffer = malloc(bufferLength);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int readBytes = gzread(tarFile, buffer, bufferLength);
|
||||
|
||||
if (readBytes > 0)
|
||||
{
|
||||
CFIndex writtenBytes = CFWriteStreamWrite(writeStream, (unsigned char*)buffer,
|
||||
readBytes);
|
||||
|
||||
if (writtenBytes < 0)
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
printf("write stream error %i\n", err.error);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (readBytes == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (readBytes == -1)
|
||||
{
|
||||
printf("decompression failed\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unexpected zlib state\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CFWriteStreamClose(writeStream);
|
||||
CFRelease(writeStream);
|
||||
free(buffer);
|
||||
gzclose(tarFile);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ======== extract files =========
|
||||
|
||||
uint64_t location = 0; // Position in the file
|
||||
|
||||
// get file size
|
||||
struct stat stat_buf;
|
||||
int res = stat(tarPath, &stat_buf);
|
||||
if (res != 0)
|
||||
{
|
||||
printf("error file size\n");
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
int64_t tarSize = stat_buf.st_size;
|
||||
|
||||
// create read stream
|
||||
CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, tarUrl);
|
||||
|
||||
if (!CFReadStreamOpen(readStream))
|
||||
{
|
||||
CFStreamError err = CFReadStreamGetError(readStream);
|
||||
|
||||
if (err.domain == kCFStreamErrorDomainPOSIX)
|
||||
{
|
||||
printf("kCFStreamErrorDomainPOSIX %i", err.error);
|
||||
}
|
||||
else if(err.domain == kCFStreamErrorDomainMacOSStatus)
|
||||
{
|
||||
printf("kCFStreamErrorDomainMacOSStatus %i", err.error);
|
||||
}
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
CFRelease(readStream);
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
long size = 0;
|
||||
|
||||
// process files
|
||||
while (location < tarSize)
|
||||
{
|
||||
TarInfo info = getTarObjectInfo(readStream, location);
|
||||
|
||||
if (!info.success || info.realContentSize == 0)
|
||||
{
|
||||
break; // something wrong or all files are read
|
||||
}
|
||||
|
||||
switch (info.objType)
|
||||
{
|
||||
case '0': // file
|
||||
case '\0': //
|
||||
{
|
||||
std::string obj = getTarObject(readStream, info.blocksContentSize);
|
||||
#if TAR_DEBUG
|
||||
size += info.realContentSize;
|
||||
printf("#%i %s file size %lld written total %ld from %lld\n", ++count,
|
||||
info.objName.c_str(), info.realContentSize, size, tarSize);
|
||||
#endif
|
||||
writeFile(tzdataPathUrl, info.objName, obj, info.realContentSize);
|
||||
location += info.blocksContentSize;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFReadStreamClose(readStream);
|
||||
CFRelease(readStream);
|
||||
|
||||
remove(tarPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TarInfo
|
||||
getTarObjectInfo(CFReadStreamRef readStream, int64_t location)
|
||||
{
|
||||
int64_t length = TAR_BLOCK_SIZE;
|
||||
uint8_t buffer[length];
|
||||
|
||||
char type;
|
||||
char name[TAR_NAME_SIZE + 1];
|
||||
char sizeBuf[TAR_SIZE_SIZE + 1];
|
||||
CFIndex bytesRead;
|
||||
|
||||
bool avail = CFReadStreamHasBytesAvailable(readStream);
|
||||
|
||||
bytesRead = CFReadStreamRead(readStream, buffer, length);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
CFStreamError err = CFReadStreamGetError(readStream);
|
||||
printf("error reading tar object info %i", err.error);
|
||||
return {false};
|
||||
}
|
||||
|
||||
memcpy(&type, &buffer[TAR_TYPE_POSITION], 1);
|
||||
|
||||
memset(&name, '\0', TAR_NAME_SIZE + 1);
|
||||
memcpy(&name, &buffer[TAR_NAME_POSITION], TAR_NAME_SIZE);
|
||||
|
||||
memset(&sizeBuf, '\0', TAR_SIZE_SIZE + 1);
|
||||
memcpy(&sizeBuf, &buffer[TAR_SIZE_POSITION], TAR_SIZE_SIZE);
|
||||
int64_t realSize = strtol(sizeBuf, NULL, 8);
|
||||
int64_t blocksSize = realSize + (TAR_BLOCK_SIZE - (realSize % TAR_BLOCK_SIZE));
|
||||
|
||||
return {type, std::string(name), realSize, blocksSize, true};
|
||||
}
|
||||
|
||||
std::string
|
||||
getTarObject(CFReadStreamRef readStream, int64_t size)
|
||||
{
|
||||
uint8_t buffer[size];
|
||||
|
||||
CFIndex bytesRead = CFReadStreamRead(readStream, buffer, size);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
CFStreamError err = CFReadStreamGetError(readStream);
|
||||
printf("error reading tar object info %i", err.error);
|
||||
}
|
||||
|
||||
return std::string((char *)buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
writeFile(CFURLRef tzdataUrl, std::string fileName, std::string data,
|
||||
int64_t realContentSize)
|
||||
{
|
||||
// create stream
|
||||
CFStringRef fileNameRef = CFStringCreateWithCString(NULL, fileName.c_str(),
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef url = CFURLCreateCopyAppendingPathComponent(NULL, tzdataUrl, fileNameRef,
|
||||
false);
|
||||
CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(NULL, url);
|
||||
|
||||
// open stream
|
||||
if (!CFWriteStreamOpen(writeStream))
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
|
||||
if (err.domain == kCFStreamErrorDomainPOSIX)
|
||||
{
|
||||
printf("kCFStreamErrorDomainPOSIX %i\n", err.error);
|
||||
}
|
||||
else if(err.domain == kCFStreamErrorDomainMacOSStatus)
|
||||
{
|
||||
printf("kCFStreamErrorDomainMacOSStatus %i\n", err.error);
|
||||
}
|
||||
|
||||
CFRelease(writeStream);
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim empty space
|
||||
uint8_t trimmedData[realContentSize + 1];
|
||||
memset(&trimmedData, '\0', realContentSize);
|
||||
memcpy(&trimmedData, data.c_str(), realContentSize);
|
||||
|
||||
// write
|
||||
CFIndex writtenBytes = CFWriteStreamWrite(writeStream, trimmedData, realContentSize);
|
||||
|
||||
if (writtenBytes < 0)
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
printf("write stream error %i\n", err.error);
|
||||
}
|
||||
|
||||
CFWriteStreamClose(writeStream);
|
||||
CFRelease(writeStream);
|
||||
writeStream = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
||||
#endif // TARGET_OS_IPHONE
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,265 @@
|
||||
#ifndef TZ_PRIVATE_H
|
||||
#define TZ_PRIVATE_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015, 2016 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that woud involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
#include "tz.h"
|
||||
#else
|
||||
#include "date.h"
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
enum class tz {utc, local, standard};
|
||||
|
||||
//forward declare to avoid warnings in gcc 6.2
|
||||
class MonthDayTime;
|
||||
std::istream& operator>>(std::istream& is, MonthDayTime& x);
|
||||
std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
|
||||
|
||||
|
||||
class MonthDayTime
|
||||
{
|
||||
private:
|
||||
struct pair
|
||||
{
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
pair() : month_day_(date::jan / 1), weekday_(0U) {}
|
||||
|
||||
pair(const date::month_day& month_day, const date::weekday& weekday)
|
||||
: month_day_(month_day), weekday_(weekday) {}
|
||||
#endif
|
||||
|
||||
date::month_day month_day_;
|
||||
date::weekday weekday_;
|
||||
};
|
||||
|
||||
enum Type {month_day, month_last_dow, lteq, gteq};
|
||||
|
||||
Type type_{month_day};
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
union U
|
||||
#else
|
||||
struct U
|
||||
#endif
|
||||
{
|
||||
date::month_day month_day_;
|
||||
date::month_weekday_last month_weekday_last_;
|
||||
pair month_day_weekday_;
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
U() : month_day_{date::jan/1} {}
|
||||
#else
|
||||
U() :
|
||||
month_day_(date::jan/1),
|
||||
month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U)))
|
||||
{}
|
||||
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
|
||||
U& operator=(const date::month_day& x);
|
||||
U& operator=(const date::month_weekday_last& x);
|
||||
U& operator=(const pair& x);
|
||||
} u;
|
||||
|
||||
std::chrono::hours h_{0};
|
||||
std::chrono::minutes m_{0};
|
||||
std::chrono::seconds s_{0};
|
||||
tz zone_{tz::local};
|
||||
|
||||
public:
|
||||
MonthDayTime() = default;
|
||||
MonthDayTime(local_seconds tp, tz timezone);
|
||||
MonthDayTime(const date::month_day& md, tz timezone);
|
||||
|
||||
date::day day() const;
|
||||
date::month month() const;
|
||||
tz zone() const {return zone_;}
|
||||
|
||||
void canonicalize(date::year y);
|
||||
|
||||
sys_seconds
|
||||
to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const;
|
||||
sys_days to_sys_days(date::year y) const;
|
||||
|
||||
sys_seconds to_time_point(date::year y) const;
|
||||
int compare(date::year y, const MonthDayTime& x, date::year yx,
|
||||
std::chrono::seconds offset, std::chrono::minutes prev_save) const;
|
||||
|
||||
friend std::istream& operator>>(std::istream& is, MonthDayTime& x);
|
||||
friend std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
|
||||
};
|
||||
|
||||
// A Rule specifies one or more set of datetimes without using an offset.
|
||||
// Multiple dates are specified with multiple years. The years in effect
|
||||
// go from starting_year_ to ending_year_, inclusive. starting_year_ <=
|
||||
// ending_year_. save_ is ineffect for times from the specified time
|
||||
// onward, including the specified time. When the specified time is
|
||||
// local, it uses the save_ from the chronologically previous Rule, or if
|
||||
// there is none, 0.
|
||||
|
||||
//forward declare to avoid warnings in gcc 6.2
|
||||
class Rule;
|
||||
bool operator==(const Rule& x, const Rule& y);
|
||||
bool operator<(const Rule& x, const Rule& y);
|
||||
bool operator==(const Rule& x, const date::year& y);
|
||||
bool operator<(const Rule& x, const date::year& y);
|
||||
bool operator==(const date::year& x, const Rule& y);
|
||||
bool operator<(const date::year& x, const Rule& y);
|
||||
bool operator==(const Rule& x, const std::string& y);
|
||||
bool operator<(const Rule& x, const std::string& y);
|
||||
bool operator==(const std::string& x, const Rule& y);
|
||||
bool operator<(const std::string& x, const Rule& y);
|
||||
std::ostream& operator<<(std::ostream& os, const Rule& r);
|
||||
|
||||
class Rule
|
||||
{
|
||||
private:
|
||||
std::string name_;
|
||||
date::year starting_year_{0};
|
||||
date::year ending_year_{0};
|
||||
MonthDayTime starting_at_;
|
||||
std::chrono::minutes save_{0};
|
||||
std::string abbrev_;
|
||||
|
||||
public:
|
||||
Rule() = default;
|
||||
explicit Rule(const std::string& s);
|
||||
Rule(const Rule& r, date::year starting_year, date::year ending_year);
|
||||
|
||||
const std::string& name() const {return name_;}
|
||||
const std::string& abbrev() const {return abbrev_;}
|
||||
|
||||
const MonthDayTime& mdt() const {return starting_at_;}
|
||||
const date::year& starting_year() const {return starting_year_;}
|
||||
const date::year& ending_year() const {return ending_year_;}
|
||||
const std::chrono::minutes& save() const {return save_;}
|
||||
|
||||
static void split_overlaps(std::vector<Rule>& rules);
|
||||
|
||||
friend bool operator==(const Rule& x, const Rule& y);
|
||||
friend bool operator<(const Rule& x, const Rule& y);
|
||||
friend bool operator==(const Rule& x, const date::year& y);
|
||||
friend bool operator<(const Rule& x, const date::year& y);
|
||||
friend bool operator==(const date::year& x, const Rule& y);
|
||||
friend bool operator<(const date::year& x, const Rule& y);
|
||||
friend bool operator==(const Rule& x, const std::string& y);
|
||||
friend bool operator<(const Rule& x, const std::string& y);
|
||||
friend bool operator==(const std::string& x, const Rule& y);
|
||||
friend bool operator<(const std::string& x, const Rule& y);
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Rule& r);
|
||||
|
||||
private:
|
||||
date::day day() const;
|
||||
date::month month() const;
|
||||
static void split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e);
|
||||
static bool overlaps(const Rule& x, const Rule& y);
|
||||
static void split(std::vector<Rule>& rules, std::size_t i, std::size_t k,
|
||||
std::size_t& e);
|
||||
};
|
||||
|
||||
inline bool operator!=(const Rule& x, const Rule& y) {return !(x == y);}
|
||||
inline bool operator> (const Rule& x, const Rule& y) {return y < x;}
|
||||
inline bool operator<=(const Rule& x, const Rule& y) {return !(y < x);}
|
||||
inline bool operator>=(const Rule& x, const Rule& y) {return !(x < y);}
|
||||
|
||||
inline bool operator!=(const Rule& x, const date::year& y) {return !(x == y);}
|
||||
inline bool operator> (const Rule& x, const date::year& y) {return y < x;}
|
||||
inline bool operator<=(const Rule& x, const date::year& y) {return !(y < x);}
|
||||
inline bool operator>=(const Rule& x, const date::year& y) {return !(x < y);}
|
||||
|
||||
inline bool operator!=(const date::year& x, const Rule& y) {return !(x == y);}
|
||||
inline bool operator> (const date::year& x, const Rule& y) {return y < x;}
|
||||
inline bool operator<=(const date::year& x, const Rule& y) {return !(y < x);}
|
||||
inline bool operator>=(const date::year& x, const Rule& y) {return !(x < y);}
|
||||
|
||||
inline bool operator!=(const Rule& x, const std::string& y) {return !(x == y);}
|
||||
inline bool operator> (const Rule& x, const std::string& y) {return y < x;}
|
||||
inline bool operator<=(const Rule& x, const std::string& y) {return !(y < x);}
|
||||
inline bool operator>=(const Rule& x, const std::string& y) {return !(x < y);}
|
||||
|
||||
inline bool operator!=(const std::string& x, const Rule& y) {return !(x == y);}
|
||||
inline bool operator> (const std::string& x, const Rule& y) {return y < x;}
|
||||
inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);}
|
||||
inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);}
|
||||
|
||||
struct zonelet
|
||||
{
|
||||
enum tag {has_rule, has_save, is_empty};
|
||||
|
||||
std::chrono::seconds gmtoff_;
|
||||
tag tag_ = has_rule;
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
union U
|
||||
#else
|
||||
struct U
|
||||
#endif
|
||||
{
|
||||
std::string rule_;
|
||||
std::chrono::minutes save_;
|
||||
|
||||
~U() {}
|
||||
U() {}
|
||||
U(const U&) {}
|
||||
U& operator=(const U&) = delete;
|
||||
} u;
|
||||
|
||||
std::string format_;
|
||||
date::year until_year_{0};
|
||||
MonthDayTime until_date_;
|
||||
sys_seconds until_utc_;
|
||||
local_seconds until_std_;
|
||||
local_seconds until_loc_;
|
||||
std::chrono::minutes initial_save_{};
|
||||
std::string initial_abbrev_;
|
||||
std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()};
|
||||
std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()};
|
||||
|
||||
~zonelet();
|
||||
zonelet();
|
||||
zonelet(const zonelet& i);
|
||||
zonelet& operator=(const zonelet&) = delete;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace date
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
#include "tz.h"
|
||||
#endif
|
||||
|
||||
#endif // TZ_PRIVATE_H
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// Created by marcin on 22/11/15.
|
||||
//
|
||||
|
||||
#include "dateparser.h"
|
||||
|
||||
|
||||
dateparser::dateparser(std::string fmt)
|
||||
{
|
||||
// set format
|
||||
using namespace boost::local_time;
|
||||
local_time_input_facet* input_facet = new local_time_input_facet();
|
||||
input_facet->format(fmt.c_str());
|
||||
ss.imbue(std::locale(ss.getloc(), input_facet));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
dateparser::operator()(std::string const& text)
|
||||
{
|
||||
ss.clear();
|
||||
ss.str(text);
|
||||
|
||||
bool ok = bool(ss >> pt);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
auto tm = to_tm(pt);
|
||||
year = tm.tm_year;
|
||||
month = tm.tm_mon + 1; // for 1-based (1:jan, .. 12:dec)
|
||||
day = tm.tm_mday;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Created by marcin on 22/11/15.
|
||||
//
|
||||
|
||||
#ifndef XMR2CSV_DATEPARSER_H
|
||||
#define XMR2CSV_DATEPARSER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
|
||||
|
||||
// taken from: http://stackoverflow.com/a/19482908/248823
|
||||
struct dateparser
|
||||
{
|
||||
boost::posix_time::ptime pt;
|
||||
unsigned year, month, day;
|
||||
|
||||
dateparser(std::string fmt);
|
||||
|
||||
bool
|
||||
operator()(std::string const& text);
|
||||
|
||||
private:
|
||||
std::stringstream ss;
|
||||
};
|
||||
|
||||
#endif //XMR2CSV_DATEPARSER_H
|
Loading…
Reference in New Issue