mirror of https://github.com/vitalif/openscad
experimental workaround for boost linker problems w random_device
parent
f40b6a672a
commit
84c6d45eaa
|
@ -0,0 +1,217 @@
|
|||
/* boost random_device.cpp implementation
|
||||
*
|
||||
* Copyright Jens Maurer 2000
|
||||
* Copyright Steven Watanabe 2010-2011
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* $Id: random_device.cpp 71018 2011-04-05 21:27:52Z steven_watanabe $
|
||||
*
|
||||
*/
|
||||
|
||||
#define BOOST_RANDOM_SOURCE
|
||||
|
||||
#include <boost/random/random_device.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <string>
|
||||
|
||||
#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) && !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
||||
// A definition is required even for integral static constants
|
||||
const bool boost::random::random_device::has_fixed_range;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <stdexcept> // std::invalid_argument
|
||||
|
||||
#define BOOST_AUTO_LINK_NOMANGLE
|
||||
#define BOOST_LIB_NAME "Advapi32"
|
||||
#include <boost/config/auto_link.hpp>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
extern "C" {
|
||||
|
||||
// mingw's wincrypt.h appears to be missing some things
|
||||
WINADVAPI
|
||||
BOOL
|
||||
WINAPI
|
||||
CryptEnumProvidersA(
|
||||
DWORD dwIndex,
|
||||
DWORD *pdwReserved,
|
||||
DWORD dwFlags,
|
||||
DWORD *pdwProvType,
|
||||
LPSTR szProvName,
|
||||
DWORD *pcbProvName
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
const char * const default_token = MS_DEF_PROV_A;
|
||||
|
||||
}
|
||||
|
||||
class boost::random::random_device::impl
|
||||
{
|
||||
public:
|
||||
impl(const std::string & token) : provider(token) {
|
||||
char buffer[80];
|
||||
DWORD type;
|
||||
DWORD len;
|
||||
|
||||
// Find the type of the provider
|
||||
for(DWORD i = 0; ; ++i) {
|
||||
len = sizeof(buffer);
|
||||
if(!CryptEnumProvidersA(i, NULL, 0, &type, buffer, &len)) {
|
||||
error("Could not find provider name");
|
||||
}
|
||||
if(buffer == provider) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!CryptAcquireContextA(&hProv, NULL, provider.c_str(), type,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
error("Could not acquire CSP context");
|
||||
}
|
||||
}
|
||||
|
||||
~impl() {
|
||||
if(!CryptReleaseContext(hProv, 0)) error("Could not release CSP context");
|
||||
}
|
||||
|
||||
unsigned int next() {
|
||||
unsigned int result;
|
||||
|
||||
if(!CryptGenRandom(hProv, sizeof(result),
|
||||
static_cast<BYTE*>(static_cast<void*>(&result)))) {
|
||||
error("error while reading");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void error(const std::string & msg) {
|
||||
char buf[80];
|
||||
DWORD num = FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
0,
|
||||
buf,
|
||||
sizeof(buf),
|
||||
NULL);
|
||||
|
||||
throw std::invalid_argument("boost::random_device: " + msg +
|
||||
" Cryptopraphic Service Provider " + provider +
|
||||
": " + std::string(&buf[0], &buf[0] + num));
|
||||
}
|
||||
const std::string provider;
|
||||
HCRYPTPROV hProv;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
namespace {
|
||||
// the default is the unlimited capacity device, using some secure hash
|
||||
// try "/dev/random" for blocking when the entropy pool has drained
|
||||
const char * const default_token = "/dev/urandom";
|
||||
}
|
||||
|
||||
/*
|
||||
* This uses the POSIX interface for unbuffered reading.
|
||||
* Using buffered std::istream would consume entropy which may
|
||||
* not actually be used. Entropy is a precious good we avoid
|
||||
* wasting.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__) && defined(_CXXRT_STD_NAME)
|
||||
// I have severe difficulty to get the POSIX includes to work with
|
||||
// -fhonor-std and Dietmar Kuhl's standard C++ library. Hack around that
|
||||
// problem for now.
|
||||
extern "C" {
|
||||
static const int O_RDONLY = 0;
|
||||
extern int open(const char *__file, int __oflag, ...);
|
||||
extern int read(int __fd, __ptr_t __buf, size_t __nbytes);
|
||||
extern int close(int __fd);
|
||||
}
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> // open
|
||||
#include <unistd.h> // read, close
|
||||
#endif
|
||||
|
||||
#include <errno.h> // errno
|
||||
#include <string.h> // strerror
|
||||
#include <stdexcept> // std::invalid_argument
|
||||
|
||||
|
||||
class boost::random::random_device::impl
|
||||
{
|
||||
public:
|
||||
impl(const std::string & token) : path(token) {
|
||||
fd = open(token.c_str(), O_RDONLY);
|
||||
if(fd < 0)
|
||||
error("cannot open");
|
||||
}
|
||||
|
||||
~impl() { if(close(fd) < 0) error("could not close"); }
|
||||
|
||||
unsigned int next() {
|
||||
unsigned int result;
|
||||
long sz = read(fd, reinterpret_cast<char *>(&result), sizeof(result));
|
||||
if(sz == -1)
|
||||
error("error while reading");
|
||||
else if(sz != sizeof(result)) {
|
||||
errno = 0;
|
||||
error("EOF while reading");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void error(const std::string & msg) {
|
||||
throw std::invalid_argument("boost::random_device: " + msg +
|
||||
" random-number pseudo-device " + path +
|
||||
": " + strerror(errno));
|
||||
}
|
||||
const std::string path;
|
||||
int fd;
|
||||
};
|
||||
|
||||
#endif // BOOST_WINDOWS
|
||||
|
||||
BOOST_RANDOM_DECL boost::random::random_device::random_device()
|
||||
: pimpl(new impl(default_token))
|
||||
{}
|
||||
|
||||
BOOST_RANDOM_DECL boost::random::random_device::random_device(const std::string& token)
|
||||
: pimpl(new impl(token))
|
||||
{}
|
||||
|
||||
BOOST_RANDOM_DECL boost::random_device::~random_device()
|
||||
{
|
||||
delete pimpl;
|
||||
}
|
||||
|
||||
BOOST_RANDOM_DECL double boost::random_device::entropy() const
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
BOOST_RANDOM_DECL unsigned int boost::random_device::operator()()
|
||||
{
|
||||
return pimpl->next();
|
||||
}
|
Loading…
Reference in New Issue