mirror of
https://git.wownero.com/wownero/onion-wownero-blockchain-explorer.git
synced 2024-08-15 00:33:12 +00:00
Merge branch 'date_lib_added'
This commit is contained in:
commit
735de00f96
20 changed files with 17071 additions and 3429 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
||||||
*.*~
|
*.*~
|
||||||
*.user
|
*.user
|
||||||
.idea/
|
.idea/
|
||||||
|
cmake-build-debug/
|
||||||
|
|
|
@ -172,4 +172,5 @@ target_link_libraries(${PROJECT_NAME}
|
||||||
pthread
|
pthread
|
||||||
unbound
|
unbound
|
||||||
unwind
|
unwind
|
||||||
|
curl
|
||||||
dl)
|
dl)
|
||||||
|
|
19
README.md
19
README.md
|
@ -8,7 +8,8 @@ Curently available Monero blockchain explorer websites have several limitations
|
||||||
- are closed sourced,
|
- are closed sourced,
|
||||||
- are not available as hidden services,
|
- are not available as hidden services,
|
||||||
- provide only basic search capabilities,
|
- provide only basic search capabilities,
|
||||||
- can't identify users outputs based on provided Monero address and viewkey.
|
- can't identify users outputs based on provided Monero address and viewkey, or private tx key,
|
||||||
|
- do not support Monero testnet, i.e., they dont work with RingCT transactions
|
||||||
|
|
||||||
|
|
||||||
In this example, these limitations are addressed by development of
|
In this example, these limitations are addressed by development of
|
||||||
|
@ -18,7 +19,8 @@ an Onion Monero Blockchain Explorer. The example not only shows how to use Moner
|
||||||
- [lmdb++](https://github.com/bendiken/lmdbxx) - C++ wrapper for the LMDB
|
- [lmdb++](https://github.com/bendiken/lmdbxx) - C++ wrapper for the LMDB
|
||||||
- [mstch](https://github.com/no1msd/mstch) - C++ {{mustache}} templates
|
- [mstch](https://github.com/no1msd/mstch) - C++ {{mustache}} templates
|
||||||
- [rapidjson](https://github.com/miloyip/rapidjson) - C++ JSON parser/generator
|
- [rapidjson](https://github.com/miloyip/rapidjson) - C++ JSON parser/generator
|
||||||
|
- [date](https://github.com/HowardHinnant/date) - C++ date and time library
|
||||||
|
- [fmt](https://github.com/fmtlib/fmt) - Small, safe and fast string formatting library
|
||||||
|
|
||||||
## Address
|
## Address
|
||||||
|
|
||||||
|
@ -45,7 +47,8 @@ The key features of the Onion Monero Blockchain Explorer are
|
||||||
- made fully in C++,
|
- made fully in C++,
|
||||||
- the only explorer showing encrypted payments ID,
|
- the only explorer showing encrypted payments ID,
|
||||||
- the only explorer with the ability to search by encrypted payments ID, tx public
|
- the only explorer with the ability to search by encrypted payments ID, tx public
|
||||||
and private keys, stealth addresses, input key images,
|
and private keys, stealth addresses, input key images, block timestamps
|
||||||
|
(UTC time, e.g., 2016-11-23 14:03:05)
|
||||||
- the only explorer showing ring signatures,
|
- the only explorer showing ring signatures,
|
||||||
- the only explorer showing transaction extra field,
|
- the only explorer showing transaction extra field,
|
||||||
- the only explorer showing public components of Monero addresses,
|
- the only explorer showing public components of Monero addresses,
|
||||||
|
@ -53,13 +56,14 @@ The key features of the Onion Monero Blockchain Explorer are
|
||||||
- the only explorer that can be used to prove that you send Monero to someone,
|
- the only explorer that can be used to prove that you send Monero to someone,
|
||||||
- the only explorer showing detailed information about mixins, such as, mixins'
|
- the only explorer showing detailed information about mixins, such as, mixins'
|
||||||
age, timescale, mixin of mixins,
|
age, timescale, mixin of mixins,
|
||||||
- the only explorer showing number of amount output indices.
|
- the only explorer showing number of amount output indices,
|
||||||
|
- the only explorer supporting Monero testnet network and RingCT.
|
||||||
|
|
||||||
## Prerequisite
|
## Prerequisite
|
||||||
|
|
||||||
Everything here was done and tested using Monero 0.9.4 on Ubuntu 16.04 x86_64.
|
Everything here was done and tested using Monero 0.9.4 on Ubuntu 16.04 x86_64.
|
||||||
|
|
||||||
Instruction for Monero 0.9 compilation and Monero headers and libraries setup are
|
Instruction for Monero 0.10 compilation and Monero headers and libraries setup are
|
||||||
as shown here:
|
as shown here:
|
||||||
- [Compile Monero 0.9 on Ubuntu 16.04 x64](https://github.com/moneroexamples/compile-monero-09-on-ubuntu-16-04)
|
- [Compile Monero 0.9 on Ubuntu 16.04 x64](https://github.com/moneroexamples/compile-monero-09-on-ubuntu-16-04)
|
||||||
- [lmdbcpp-monero](https://github.com/moneroexamples/lmdbcpp-monero.git)
|
- [lmdbcpp-monero](https://github.com/moneroexamples/lmdbcpp-monero.git)
|
||||||
|
@ -230,8 +234,11 @@ git clone https://github.com/moneroexamples/onion-monero-blockchain-explorer.git
|
||||||
# enter the downloaded sourced code folder
|
# enter the downloaded sourced code folder
|
||||||
cd onion-monero-blockchain-explorer
|
cd onion-monero-blockchain-explorer
|
||||||
|
|
||||||
|
# make a build folder and enter it
|
||||||
|
mkdir build && cd build
|
||||||
|
|
||||||
# create the makefile
|
# create the makefile
|
||||||
cmake .
|
cmake ..
|
||||||
|
|
||||||
# compile
|
# compile
|
||||||
make
|
make
|
||||||
|
|
|
@ -8,11 +8,11 @@ project(myext)
|
||||||
set(SOURCE_HEADERS
|
set(SOURCE_HEADERS
|
||||||
minicsv.h
|
minicsv.h
|
||||||
format.h
|
format.h
|
||||||
dateparser.h)
|
)
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
format.cc
|
format.cc
|
||||||
dateparser.cpp)
|
date/tz.cpp)
|
||||||
|
|
||||||
# make static library called libmyxrm
|
# make static library called libmyxrm
|
||||||
# that we are going to link to
|
# that we are going to link to
|
||||||
|
|
668
ext/date/chrono_io.h
Normal file
668
ext/date/chrono_io.h
Normal file
|
@ -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
|
4823
ext/date/date.h
Normal file
4823
ext/date/date.h
Normal file
File diff suppressed because it is too large
Load diff
49
ext/date/ios.h
Normal file
49
ext/date/ios.h
Normal file
|
@ -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
|
405
ext/date/ios.mm
Normal file
405
ext/date/ios.mm
Normal file
|
@ -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
|
3046
ext/date/julian.h
Normal file
3046
ext/date/julian.h
Normal file
File diff suppressed because it is too large
Load diff
3120
ext/date/tz.cpp
Normal file
3120
ext/date/tz.cpp
Normal file
File diff suppressed because it is too large
Load diff
1345
ext/date/tz.h
Normal file
1345
ext/date/tz.h
Normal file
File diff suppressed because it is too large
Load diff
265
ext/date/tz_private.h
Normal file
265
ext/date/tz_private.h
Normal file
|
@ -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
|
|
12
main.cpp
12
main.cpp
|
@ -223,12 +223,12 @@ int main(int ac, const char* av[]) {
|
||||||
return xmrblocks.search(string(req.url_params.get("value")));
|
return xmrblocks.search(string(req.url_params.get("value")));
|
||||||
});
|
});
|
||||||
|
|
||||||
// CROW_ROUTE(app, "/robots.txt")
|
CROW_ROUTE(app, "/robots.txt")
|
||||||
// ([&]() {
|
([&]() {
|
||||||
// string text = "User-agent: *\n"
|
string text = "User-agent: *\n"
|
||||||
// "Disallow: ";
|
"Disallow: ";
|
||||||
// return text;
|
return text;
|
||||||
// });
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/autorefresh")
|
CROW_ROUTE(app, "/autorefresh")
|
||||||
([&]() {
|
([&]() {
|
||||||
|
|
|
@ -451,7 +451,7 @@ namespace xmreg
|
||||||
|
|
||||||
|
|
||||||
// set cursor the the first item
|
// set cursor the the first item
|
||||||
if (cr.get(key_to_find, info_val, MDB_SET))
|
if (cr.get(key_to_find, info_val, MDB_SET_RANGE))
|
||||||
{
|
{
|
||||||
out_infos.push_back(*(info_val.data<output_info>()));
|
out_infos.push_back(*(info_val.data<output_info>()));
|
||||||
|
|
||||||
|
|
130
src/page.h
130
src/page.h
|
@ -48,26 +48,26 @@
|
||||||
namespace xmreg {
|
namespace xmreg {
|
||||||
|
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// define a checker to test if a structure has "tx_blob"
|
// define a checker to test if a structure has "tx_blob"
|
||||||
// member variable. I use modified daemon with few extra
|
// member variable. I use modified daemon with few extra
|
||||||
// bits and pieces here and there. One of them is
|
// bits and pieces here and there. One of them is
|
||||||
// tx_blob in cryptonote::tx_info structure
|
// tx_blob in cryptonote::tx_info structure
|
||||||
// thus I check if I run my version, or just
|
// thus I check if I run my version, or just
|
||||||
// generic one
|
// generic one
|
||||||
DEFINE_MEMBER_CHECKER(tx_blob)
|
DEFINE_MEMBER_CHECKER(tx_blob)
|
||||||
|
|
||||||
// define getter to get tx_blob, i.e., get_tx_blob function
|
// define getter to get tx_blob, i.e., get_tx_blob function
|
||||||
// as string if exists. the getter return empty string if
|
// as string if exists. the getter return empty string if
|
||||||
// tx_blob does not exist
|
// tx_blob does not exist
|
||||||
DEFINE_MEMBER_GETTER(tx_blob, string)
|
DEFINE_MEMBER_GETTER(tx_blob, string)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a given header filed contains value string
|
* Check if a given header filed contains value string
|
||||||
*
|
*
|
||||||
* @param req
|
* @param req
|
||||||
|
@ -75,11 +75,11 @@ namespace xmreg {
|
||||||
* @param value
|
* @param value
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
string
|
string
|
||||||
does_header_has(const crow::request& req,
|
does_header_has(const crow::request& req,
|
||||||
const string& field = "Accept",
|
const string& field = "Accept",
|
||||||
const string& value = "q=.2, */*; q=.2")
|
const string& value = "q=.2, */*; q=.2")
|
||||||
{
|
{
|
||||||
string accept = req.get_header_value(field);
|
string accept = req.get_header_value(field);
|
||||||
|
|
||||||
if (!accept.empty())
|
if (!accept.empty())
|
||||||
|
@ -91,18 +91,18 @@ namespace xmreg {
|
||||||
}
|
}
|
||||||
|
|
||||||
return string {};
|
return string {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The tx_details struct
|
* @brief The tx_details struct
|
||||||
*
|
*
|
||||||
* Basic information about tx
|
* Basic information about tx
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct tx_details
|
struct tx_details
|
||||||
{
|
{
|
||||||
crypto::hash hash;
|
crypto::hash hash;
|
||||||
crypto::public_key pk;
|
crypto::public_key pk;
|
||||||
uint64_t xmr_inputs;
|
uint64_t xmr_inputs;
|
||||||
|
@ -229,9 +229,9 @@ namespace xmreg {
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class page {
|
class page {
|
||||||
|
|
||||||
// check if we have tx_blob member in tx_info structure
|
// check if we have tx_blob member in tx_info structure
|
||||||
static const bool HAVE_TX_BLOB {
|
static const bool HAVE_TX_BLOB {
|
||||||
|
@ -252,7 +252,7 @@ namespace xmreg {
|
||||||
bool testnet;
|
bool testnet;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
page(MicroCore* _mcore, Blockchain* _core_storage,
|
page(MicroCore* _mcore, Blockchain* _core_storage,
|
||||||
string _deamon_url, string _lmdb2_path, bool _testnet)
|
string _deamon_url, string _lmdb2_path, bool _testnet)
|
||||||
|
@ -2203,37 +2203,6 @@ namespace xmreg {
|
||||||
// such search start with "aoi_", e.g., "aoi_444-23.00"
|
// such search start with "aoi_", e.g., "aoi_444-23.00"
|
||||||
bool search_for_amount_output_idx = (search_text.substr(0, 4) == "aoi_");
|
bool search_for_amount_output_idx = (search_text.substr(0, 4) == "aoi_");
|
||||||
|
|
||||||
// check if date given in format: 2005-04-55
|
|
||||||
// this is 10 characters
|
|
||||||
if (search_text.length() == 19)
|
|
||||||
{
|
|
||||||
uint64_t estimated_blk_height {0};
|
|
||||||
|
|
||||||
// first parse the string date into boost's ptime object
|
|
||||||
dateparser parser {"%Y-%m-%d %H:%M:%S"};
|
|
||||||
|
|
||||||
if (parser(search_text))
|
|
||||||
{
|
|
||||||
// seems we have a correct date!
|
|
||||||
// so try to estimate block height from it.
|
|
||||||
|
|
||||||
cout << "timestamp: " << xmreg::ptime_to_time_t(parser.pt) << endl;
|
|
||||||
|
|
||||||
// estimate blockchain height from the start date provided
|
|
||||||
estimated_blk_height = xmreg::estimate_bc_height(search_text);
|
|
||||||
|
|
||||||
result_html = show_block(estimated_blk_height);
|
|
||||||
|
|
||||||
// nasty check if output is "Cant get" as a sign of
|
|
||||||
// a not found tx. Later need to think of something better.
|
|
||||||
if (result_html.find("Cant get") == string::npos)
|
|
||||||
{
|
|
||||||
return result_html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// first check if searching for block of given height
|
// first check if searching for block of given height
|
||||||
if (search_text.size() < 12 &&
|
if (search_text.size() < 12 &&
|
||||||
(search_for_global_output_idx == false
|
(search_for_global_output_idx == false
|
||||||
|
@ -2365,6 +2334,39 @@ namespace xmreg {
|
||||||
|
|
||||||
mylmdb = make_unique<xmreg::MyLMDB>(lmdb2_path);
|
mylmdb = make_unique<xmreg::MyLMDB>(lmdb2_path);
|
||||||
|
|
||||||
|
// check if date given in format: 2015-04-15 12:02:33
|
||||||
|
// this is 19 characters
|
||||||
|
if (search_text.length() == 19)
|
||||||
|
{
|
||||||
|
uint64_t estimated_blk_height {0};
|
||||||
|
|
||||||
|
// first parse the string to date::sys_seconds and then to timestamp
|
||||||
|
// since epoch
|
||||||
|
uint64_t blk_timestamp_utc = parse(search_text).time_since_epoch().count();
|
||||||
|
|
||||||
|
if (blk_timestamp_utc)
|
||||||
|
{
|
||||||
|
// seems we have a correct date!
|
||||||
|
// so try to estimate block height from it.
|
||||||
|
//
|
||||||
|
// to find block we can use our lmdb outputs_info table
|
||||||
|
// its indexes are timestamps.
|
||||||
|
|
||||||
|
vector<xmreg::output_info> out_infos;
|
||||||
|
|
||||||
|
if (mylmdb->get_output_info(blk_timestamp_utc, out_infos))
|
||||||
|
{
|
||||||
|
// since many outputs can be in a single block
|
||||||
|
// just get the first one to obtained its block
|
||||||
|
|
||||||
|
uint64_t found_blk_height = core_storage->get_db()
|
||||||
|
.get_tx_block_height(out_infos.at(0).tx_hash);
|
||||||
|
|
||||||
|
return show_block(found_blk_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mylmdb->search(search_text,
|
mylmdb->search(search_text,
|
||||||
tx_search_results["key_images"],
|
tx_search_results["key_images"],
|
||||||
|
@ -2894,7 +2896,7 @@ namespace xmreg {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3617,10 +3619,10 @@ namespace xmreg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mixin_no;
|
return mixin_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string
|
string
|
||||||
get_full_page(string& middle)
|
get_full_page(string& middle)
|
||||||
{
|
{
|
||||||
|
@ -3638,6 +3640,15 @@ namespace xmreg {
|
||||||
+ footer_html;
|
+ footer_html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string
|
||||||
|
get_full_page(string& middle)
|
||||||
|
{
|
||||||
|
return xmreg::read(TMPL_HEADER)
|
||||||
|
+ middle
|
||||||
|
+ xmreg::read(TMPL_FOOTER);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_css_style(mstch::map& context)
|
add_css_style(mstch::map& context)
|
||||||
{
|
{
|
||||||
|
@ -3646,8 +3657,7 @@ namespace xmreg {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
{{^testnet}}
|
{{^testnet}}
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<form action="/search" method="get" style="width:100%; margin-top:15px" class="style-1">
|
<form action="/search" method="get" style="width:100%; margin-top:15px" class="style-1">
|
||||||
<input type="text" name="value" size="100"
|
<input type="text" name="value" size="120"
|
||||||
placeholder="blk height, blk hash, tx hash, tx payment id, encrypted payment id, tx public key, input key image, and stealth address">
|
placeholder="blk height, blk hash, tx hash, tx payment id, encrypted payment id, tx public key, input key image, stealth address, and datetime">
|
||||||
<input type="submit" value="Search">
|
<input type="submit" value="Search">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -143,23 +143,14 @@ namespace xmreg
|
||||||
return bf::path(remove_trailing_path_separator(path_str));
|
return bf::path(remove_trailing_path_separator(path_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string
|
string
|
||||||
timestamp_to_str(time_t timestamp, const char* format)
|
timestamp_to_str(time_t timestamp, const char* format)
|
||||||
{
|
{
|
||||||
|
auto a_time_point = chrono::system_clock::from_time_t(timestamp);
|
||||||
|
auto utc = date::to_utc_time(chrono::system_clock::from_time_t(timestamp));
|
||||||
|
auto sys_time = date::to_sys_time(utc);
|
||||||
|
|
||||||
const int TIME_LENGTH = 60;
|
return date::format(format, date::floor<chrono::seconds>(sys_time));
|
||||||
|
|
||||||
char str_buff[TIME_LENGTH];
|
|
||||||
|
|
||||||
tm *tm_ptr;
|
|
||||||
tm_ptr = localtime(×tamp);
|
|
||||||
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = std::strftime(str_buff, TIME_LENGTH, format, tm_ptr);
|
|
||||||
|
|
||||||
return string(str_buff, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -516,36 +507,6 @@ namespace xmreg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rough estimate of block height from the time provided
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint64_t
|
|
||||||
estimate_bc_height(const string& date, const char* format)
|
|
||||||
{
|
|
||||||
const pt::ptime MONERO_START {gt::date(2014,04,18)};
|
|
||||||
const uint64_t MONERO_BLOCK_TIME {60}; // seconds
|
|
||||||
|
|
||||||
dateparser parser {format};
|
|
||||||
|
|
||||||
if (!parser(date))
|
|
||||||
{
|
|
||||||
throw runtime_error(string("Date format is incorrect: ") + date);
|
|
||||||
}
|
|
||||||
|
|
||||||
pt::ptime requested_date = parser.pt;
|
|
||||||
|
|
||||||
if (requested_date < MONERO_START)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pt::time_duration td = requested_date - MONERO_START;
|
|
||||||
|
|
||||||
return static_cast<uint64_t>(td.total_seconds()) / MONERO_BLOCK_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
array<size_t, 5>
|
array<size_t, 5>
|
||||||
timestamp_difference(uint64_t t1, uint64_t t2)
|
timestamp_difference(uint64_t t1, uint64_t t2)
|
||||||
{
|
{
|
||||||
|
@ -890,5 +851,21 @@ namespace xmreg
|
||||||
return null_pkey;
|
return null_pkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
date::sys_seconds
|
||||||
|
parse(const std::string& str, string format)
|
||||||
|
{
|
||||||
|
std::istringstream in(str);
|
||||||
|
date::sys_seconds tp;
|
||||||
|
in >> date::parse(format, tp);
|
||||||
|
if (in.fail())
|
||||||
|
{
|
||||||
|
in.clear();
|
||||||
|
in.str(str);
|
||||||
|
in >> date::parse(format, tp);
|
||||||
|
}
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
215
src/tools.h
215
src/tools.h
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Created by marcin on 5/11/15.
|
// Created by mwo on 5/11/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef XMREG01_TOOLS_H
|
#ifndef XMREG01_TOOLS_H
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
#include "monero_headers.h"
|
#include "monero_headers.h"
|
||||||
#include "tx_details.h"
|
#include "tx_details.h"
|
||||||
|
|
||||||
#include "../ext/dateparser.h"
|
|
||||||
#include "../ext/infix_iterator.h"
|
#include "../ext/infix_iterator.h"
|
||||||
|
#include "../ext/date/tz.h"
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
@ -36,18 +36,19 @@
|
||||||
*/
|
*/
|
||||||
namespace xmreg
|
namespace xmreg
|
||||||
{
|
{
|
||||||
using namespace cryptonote;
|
|
||||||
using namespace crypto;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace bf = boost::filesystem;
|
using namespace cryptonote;
|
||||||
namespace pt = boost::posix_time;
|
using namespace crypto;
|
||||||
namespace gt = boost::gregorian;
|
using namespace std;
|
||||||
namespace lt = boost::local_time;
|
|
||||||
|
namespace bf = boost::filesystem;
|
||||||
|
namespace pt = boost::posix_time;
|
||||||
|
namespace gt = boost::gregorian;
|
||||||
|
namespace lt = boost::local_time;
|
||||||
|
|
||||||
|
|
||||||
struct outputs_visitor
|
struct outputs_visitor
|
||||||
{
|
{
|
||||||
std::vector<crypto::public_key >& m_output_keys;
|
std::vector<crypto::public_key >& m_output_keys;
|
||||||
|
|
||||||
const Blockchain& m_bch;
|
const Blockchain& m_bch;
|
||||||
|
@ -59,152 +60,135 @@ namespace xmreg
|
||||||
|
|
||||||
bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey)
|
bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey)
|
||||||
{
|
{
|
||||||
//check tx unlock time
|
|
||||||
// if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
|
|
||||||
// {
|
|
||||||
// LOG_PRINT_L1("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
m_output_keys.push_back(pubkey);
|
m_output_keys.push_back(pubkey);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool
|
||||||
|
parse_str_secret_key(const string& key_str, T& secret_key);
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_tx_pub_key_from_str_hash(Blockchain& core_storage,
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool
|
|
||||||
parse_str_secret_key(const string& key_str, T& secret_key);
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
get_tx_pub_key_from_str_hash(Blockchain& core_storage,
|
|
||||||
const string& hash_str,
|
const string& hash_str,
|
||||||
transaction& tx);
|
transaction& tx);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
parse_str_address(const string& address_str,
|
parse_str_address(const string& address_str,
|
||||||
account_public_address& address,
|
account_public_address& address,
|
||||||
bool testnet = false);
|
bool testnet = false);
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
is_separator(char c);
|
is_separator(char c);
|
||||||
|
|
||||||
string
|
string
|
||||||
print_address(const account_public_address& address,
|
print_address(const account_public_address& address,
|
||||||
bool testnet = false);
|
bool testnet = false);
|
||||||
|
|
||||||
string
|
string
|
||||||
print_sig (const signature& sig);
|
print_sig (const signature& sig);
|
||||||
|
|
||||||
string
|
string
|
||||||
remove_trailing_path_separator(const string& in_path);
|
remove_trailing_path_separator(const string& in_path);
|
||||||
|
|
||||||
bf::path
|
bf::path
|
||||||
remove_trailing_path_separator(const bf::path& in_path);
|
remove_trailing_path_separator(const bf::path& in_path);
|
||||||
|
|
||||||
string
|
string
|
||||||
timestamp_to_str(time_t timestamp, const char* format = "%F %T");
|
timestamp_to_str(time_t timestamp, const char* format = "%F %T");
|
||||||
|
|
||||||
|
|
||||||
ostream&
|
ostream&
|
||||||
operator<< (ostream& os, const account_public_address& addr);
|
operator<< (ostream& os, const account_public_address& addr);
|
||||||
|
|
||||||
|
|
||||||
string
|
string
|
||||||
get_default_lmdb_folder(bool testnet = false);
|
get_default_lmdb_folder(bool testnet = false);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
generate_key_image(const crypto::key_derivation& derivation,
|
generate_key_image(const crypto::key_derivation& derivation,
|
||||||
const std::size_t output_index,
|
const std::size_t output_index,
|
||||||
const crypto::secret_key& sec_key,
|
const crypto::secret_key& sec_key,
|
||||||
const crypto::public_key& pub_key,
|
const crypto::public_key& pub_key,
|
||||||
crypto::key_image& key_img);
|
crypto::key_image& key_img);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
get_blockchain_path(const boost::optional<string>& bc_path,
|
get_blockchain_path(const boost::optional<string>& bc_path,
|
||||||
bf::path& blockchain_path,
|
bf::path& blockchain_path,
|
||||||
bool testnet = false);
|
bool testnet = false);
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
sum_money_in_outputs(const transaction& tx);
|
sum_money_in_outputs(const transaction& tx);
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
sum_money_in_inputs(const transaction& tx);
|
sum_money_in_inputs(const transaction& tx);
|
||||||
|
|
||||||
array<uint64_t, 2>
|
array<uint64_t, 2>
|
||||||
sum_money_in_tx(const transaction& tx);
|
sum_money_in_tx(const transaction& tx);
|
||||||
|
|
||||||
array<uint64_t, 2>
|
array<uint64_t, 2>
|
||||||
sum_money_in_txs(const vector<transaction>& txs);
|
sum_money_in_txs(const vector<transaction>& txs);
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
sum_fees_in_txs(const vector<transaction>& txs);
|
sum_fees_in_txs(const vector<transaction>& txs);
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
get_mixin_no(const transaction& tx);
|
get_mixin_no(const transaction& tx);
|
||||||
|
|
||||||
vector<uint64_t>
|
vector<uint64_t>
|
||||||
get_mixin_no_in_txs(const vector<transaction>& txs);
|
get_mixin_no_in_txs(const vector<transaction>& txs);
|
||||||
|
|
||||||
vector<pair<txout_to_key, uint64_t>>
|
vector<pair<txout_to_key, uint64_t>>
|
||||||
get_ouputs(const transaction& tx);
|
get_ouputs(const transaction& tx);
|
||||||
|
|
||||||
vector<tuple<txout_to_key, uint64_t, uint64_t>>
|
vector<tuple<txout_to_key, uint64_t, uint64_t>>
|
||||||
get_ouputs_tuple(const transaction& tx);
|
get_ouputs_tuple(const transaction& tx);
|
||||||
|
|
||||||
vector<txin_to_key>
|
vector<txin_to_key>
|
||||||
get_key_images(const transaction& tx);
|
get_key_images(const transaction& tx);
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
get_payment_id(const vector<uint8_t>& extra,
|
get_payment_id(const vector<uint8_t>& extra,
|
||||||
crypto::hash& payment_id,
|
crypto::hash& payment_id,
|
||||||
crypto::hash8& payment_id8);
|
crypto::hash8& payment_id8);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
get_payment_id(const transaction& tx,
|
get_payment_id(const transaction& tx,
|
||||||
crypto::hash& payment_id,
|
crypto::hash& payment_id,
|
||||||
crypto::hash8& payment_id8);
|
crypto::hash8& payment_id8);
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
enable_monero_log() {
|
enable_monero_log() {
|
||||||
uint32_t log_level = 0;
|
uint32_t log_level = 0;
|
||||||
epee::log_space::get_set_log_detalisation_level(true, log_level);
|
epee::log_space::get_set_log_detalisation_level(true, log_level);
|
||||||
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
|
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t
|
inline double
|
||||||
estimate_bc_height(const string& date, const char* format = "%Y-%m-%d");
|
get_xmr(uint64_t core_amount)
|
||||||
|
{
|
||||||
|
|
||||||
inline double
|
|
||||||
get_xmr(uint64_t core_amount)
|
|
||||||
{
|
|
||||||
return static_cast<double>(core_amount) / 1e12;
|
return static_cast<double>(core_amount) / 1e12;
|
||||||
}
|
}
|
||||||
|
|
||||||
array<size_t, 5>
|
array<size_t, 5>
|
||||||
timestamp_difference(uint64_t t1, uint64_t t2);
|
timestamp_difference(uint64_t t1, uint64_t t2);
|
||||||
|
|
||||||
string
|
string
|
||||||
read(string filename);
|
read(string filename);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prints an iterable such as vector
|
* prints an iterable such as vector
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void print_iterable(const T & elems) {
|
void print_iterable(const T & elems) {
|
||||||
|
|
||||||
infix_ostream_iterator<typename T::value_type>
|
infix_ostream_iterator<typename T::value_type>
|
||||||
oiter(std::cout, ",");
|
oiter(std::cout, ",");
|
||||||
|
@ -212,45 +196,48 @@ namespace xmreg
|
||||||
std::cout << "[";
|
std::cout << "[";
|
||||||
std::copy(elems.begin(), elems.end(),oiter);
|
std::copy(elems.begin(), elems.end(),oiter);
|
||||||
std::cout << "]" << std::endl;
|
std::cout << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, double>
|
pair<string, double>
|
||||||
timestamps_time_scale(const vector<uint64_t>& timestamps,
|
timestamps_time_scale(const vector<uint64_t>& timestamps,
|
||||||
uint64_t timeN, uint64_t resolution = 80,
|
uint64_t timeN, uint64_t resolution = 80,
|
||||||
uint64_t time0 = 1397818193 /* timestamp of the second block */);
|
uint64_t time0 = 1397818193 /* timestamp of the second block */);
|
||||||
|
|
||||||
|
|
||||||
time_t
|
time_t
|
||||||
ptime_to_time_t(const pt::ptime& in_ptime);
|
ptime_to_time_t(const pt::ptime& in_ptime);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
decode_ringct(const rct::rctSig & rv,
|
decode_ringct(const rct::rctSig & rv,
|
||||||
const crypto::public_key pub,
|
const crypto::public_key pub,
|
||||||
const crypto::secret_key &sec,
|
const crypto::secret_key &sec,
|
||||||
unsigned int i,
|
unsigned int i,
|
||||||
rct::key & mask,
|
rct::key & mask,
|
||||||
uint64_t & amount);
|
uint64_t & amount);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
url_decode(const std::string& in, std::string& out);
|
url_decode(const std::string& in, std::string& out);
|
||||||
|
|
||||||
map<std::string, std::string>
|
map<std::string, std::string>
|
||||||
parse_crow_post_data(const string& req_body);
|
parse_crow_post_data(const string& req_body);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
get_dummy_account_keys(account_keys& dummy_keys, bool testnet = false);
|
get_dummy_account_keys(account_keys& dummy_keys, bool testnet = false);
|
||||||
|
|
||||||
|
|
||||||
// from wallet2::decrypt
|
// from wallet2::decrypt
|
||||||
string
|
string
|
||||||
decrypt(const std::string &ciphertext,
|
decrypt(const std::string &ciphertext,
|
||||||
const crypto::secret_key &skey,
|
const crypto::secret_key &skey,
|
||||||
bool authenticated = true);
|
bool authenticated = true);
|
||||||
|
|
||||||
// based on
|
// based on
|
||||||
// crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const
|
// crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const
|
||||||
public_key
|
public_key
|
||||||
get_tx_pub_key_from_received_outs(const transaction &tx);
|
get_tx_pub_key_from_received_outs(const transaction &tx);
|
||||||
|
|
||||||
|
date::sys_seconds
|
||||||
|
parse(const std::string& str, string format="%Y-%m-%d %H:%M:%S");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue