Reduce Beast public interface and eliminate unused code:

Beast includes a lot of code for encapsulating cross-platform differences
which are not used or needed by rippled. Additionally, a lot of that code
implements functionality that is available from the standard library.

This moves away from custom implementations of features that the standard
library provides and reduces the number of platform-specific interfaces
andfeatures that Beast makes available.

Highlights include:
* Use std:: instead of beast implementations when possible
* Reduce the use of beast::String in public interfaces
* Remove Windows-specific COM and Registry code
* Reduce the public interface of beast::File
* Reduce the public interface of beast::SystemStats
* Remove unused sysctl/getsysinfo functions
* Remove beast::Logger
This commit is contained in:
Nik Bougalis
2014-10-13 14:20:54 -07:00
committed by Vinnie Falco
parent fefdb32d08
commit 186ca9c235
82 changed files with 361 additions and 7762 deletions

View File

@@ -55,18 +55,6 @@
//#define BEAST_FORCE_DEBUG 1 //#define BEAST_FORCE_DEBUG 1
#endif #endif
/** Config: BEAST_LOG_ASSERTIONS
If this flag is enabled, the the bassert and bassertfalse macros will always
use Logger::writeToLog() to write a message when an assertion happens.
Enabling it will also leave this turned on in release builds. When it's
disabled, however, the bassert and bassertfalse macros will not be compiled
in a release build.
@see bassert, bassertfalse, Logger
*/
#ifndef BEAST_LOG_ASSERTIONS
//#define BEAST_LOG_ASSERTIONS 1
#endif
/** Config: BEAST_CHECK_MEMORY_LEAKS /** Config: BEAST_CHECK_MEMORY_LEAKS
Enables a memory-leak check for certain objects when the app terminates. Enables a memory-leak check for certain objects when the app terminates.
See the LeakChecked class for more details about enabling leak checking for See the LeakChecked class for more details about enabling leak checking for

View File

@@ -34,101 +34,6 @@
namespace beast { namespace beast {
// Some indispensible min/max functions
/** Returns the larger of two values. */
template <typename Type>
inline Type bmax (const Type a, const Type b)
{ return (a < b) ? b : a; }
/** Returns the larger of three values. */
template <typename Type>
inline Type bmax (const Type a, const Type b, const Type c)
{ return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }
/** Returns the larger of four values. */
template <typename Type>
inline Type bmax (const Type a, const Type b, const Type c, const Type d)
{ return bmax (a, bmax (b, c, d)); }
/** Returns the smaller of two values. */
template <typename Type>
inline Type bmin (const Type a, const Type b)
{ return (b < a) ? b : a; }
/** Returns the smaller of three values. */
template <typename Type>
inline Type bmin (const Type a, const Type b, const Type c)
{ return (b < a) ? ((c < b) ? c : b) : ((c < a) ? c : a); }
/** Returns the smaller of four values. */
template <typename Type>
inline Type bmin (const Type a, const Type b, const Type c, const Type d)
{ return bmin (a, bmin (b, c, d)); }
/** Scans an array of values, returning the minimum value that it contains. */
template <typename Type>
const Type findMinimum (const Type* data, int numValues)
{
if (numValues <= 0)
return Type();
Type result (*data++);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const Type& v = *data++;
if (v < result) result = v;
}
return result;
}
/** Scans an array of values, returning the maximum value that it contains. */
template <typename Type>
const Type findMaximum (const Type* values, int numValues)
{
if (numValues <= 0)
return Type();
Type result (*values++);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const Type& v = *values++;
if (result < v) result = v;
}
return result;
}
/** Scans an array of values, returning the minimum and maximum values that it contains. */
template <typename Type>
void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highest)
{
if (numValues <= 0)
{
lowest = Type();
highest = Type();
}
else
{
Type mn (*values++);
Type mx (mn);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const Type& v = *values++;
if (mx < v) mx = v;
if (v < mn) mn = v;
}
lowest = mn;
highest = mx;
}
}
//============================================================================== //==============================================================================
/** Constrains a value to keep it within a given range. /** Constrains a value to keep it within a given range.
@@ -151,7 +56,8 @@ inline Type blimit (const Type lowerLimit,
const Type upperLimit, const Type upperLimit,
const Type valueToConstrain) noexcept const Type valueToConstrain) noexcept
{ {
bassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable.. // if these are in the wrong order, results are unpredictable.
bassert (lowerLimit <= upperLimit);
return (valueToConstrain < lowerLimit) ? lowerLimit return (valueToConstrain < lowerLimit) ? lowerLimit
: ((upperLimit < valueToConstrain) ? upperLimit : ((upperLimit < valueToConstrain) ? upperLimit
@@ -177,24 +83,6 @@ inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) noe
return static_cast <unsigned int> (valueToTest) < static_cast <unsigned int> (upperLimit); return static_cast <unsigned int> (valueToTest) < static_cast <unsigned int> (upperLimit);
} }
/** Returns true if a value is at least zero, and also less than or equal to a specified upper limit.
This is basically a quicker way to write:
@code valueToTest >= 0 && valueToTest <= upperLimit
@endcode
*/
template <typename Type>
inline bool isPositiveAndNotGreaterThan (Type valueToTest, Type upperLimit) noexcept
{
bassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero..
return Type() <= valueToTest && valueToTest <= upperLimit;
}
template <>
inline bool isPositiveAndNotGreaterThan (const int valueToTest, const int upperLimit) noexcept
{
bassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
return static_cast <unsigned int> (valueToTest) <= static_cast <unsigned int> (upperLimit);
}
//============================================================================== //==============================================================================
@@ -214,55 +102,6 @@ int numElementsInArray (Type (&array)[N])
return N; return N;
} }
/** 64-bit abs function. */
inline std::int64_t abs64 (const std::int64_t n) noexcept
{
return (n >= 0) ? n : -n;
}
//==============================================================================
#if BEAST_MSVC
#pragma optimize ("t", off)
#ifndef __INTEL_COMPILER
#pragma float_control (precise, on, push)
#endif
#endif
/** Fast floating-point-to-integer conversion.
This is faster than using the normal c++ cast to convert a float to an int, and
it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently.
*/
template <typename FloatType>
inline int roundToInt (const FloatType value) noexcept
{
#ifdef __INTEL_COMPILER
#pragma float_control (precise, on, push)
#endif
union { int asInt[2]; double asDouble; } n;
n.asDouble = ((double) value) + 6755399441055744.0;
#if BEAST_BIG_ENDIAN
return n.asInt [1];
#else
return n.asInt [0];
#endif
}
#if BEAST_MSVC
#ifndef __INTEL_COMPILER
#pragma float_control (pop)
#endif
#pragma optimize ("", on) // resets optimisations to the project defaults
#endif
} }
#endif #endif

View File

@@ -25,7 +25,6 @@
#define BEAST_ATOMIC_H_INCLUDED #define BEAST_ATOMIC_H_INCLUDED
#include <beast/Config.h> #include <beast/Config.h>
#include <beast/StaticAssert.h>
#include <beast/utility/noexcept.h> #include <beast/utility/noexcept.h>
@@ -43,6 +42,10 @@ namespace beast {
template <typename Type> template <typename Type>
class Atomic class Atomic
{ {
// This class can only be used for types which are 32 or 64 bits in size.
static_assert (sizeof (Type) == 4 || sizeof (Type) == 8,
"Atomic arguments must be 32- or 64-bit long primitive types.");
public: public:
/** Creates a new value, initialised to zero. */ /** Creates a new value, initialised to zero. */
inline Atomic() noexcept inline Atomic() noexcept
@@ -65,8 +68,6 @@ public:
/** Destructor. */ /** Destructor. */
inline ~Atomic() noexcept inline ~Atomic() noexcept
{ {
// This class can only be used for types which are 32 or 64 bits in size.
static_bassert (sizeof (Type) == 4 || sizeof (Type) == 8);
} }
/** Atomically reads and returns the current value. */ /** Atomically reads and returns the current value. */

View File

@@ -20,11 +20,8 @@
#ifndef BEAST_CRYPTO_H_INCLUDED #ifndef BEAST_CRYPTO_H_INCLUDED
#define BEAST_CRYPTO_H_INCLUDED #define BEAST_CRYPTO_H_INCLUDED
#include <beast/crypto/BinaryEncoding.h>
#include <beast/crypto/MurmurHash.h> #include <beast/crypto/MurmurHash.h>
#include <beast/crypto/Sha256.h> #include <beast/crypto/Sha256.h>
#include <beast/crypto/UnsignedInteger.h>
#include <beast/crypto/UnsignedIntegerCalc.h>
#endif #endif

View File

@@ -1,45 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_STATICASSERT_H_INCLUDED
#define BEAST_STATICASSERT_H_INCLUDED
#ifndef DOXYGEN
namespace beast
{
template <bool b>
struct BeastStaticAssert;
template <>
struct BeastStaticAssert <true>
{
static void dummy() {}
};
}
#endif
/** A compile-time assertion macro.
If the expression parameter is false, the macro will cause a compile error.
(The actual error message that the compiler generates may be completely
bizarre and seem to have no relation to the place where you put the
static_assert though!)
*/
#define static_bassert(expression) beast::BeastStaticAssert<expression>::dummy();
#endif

View File

@@ -109,9 +109,12 @@ extern void beast_reportFatalError (char const* message, char const* fileName, i
/** Writes a string to the standard error stream. /** Writes a string to the standard error stream.
This is only compiled in a debug build. This is only compiled in a debug build.
@see Logger::outputDebugString
*/ */
#define BDBG(dbgtext) { beast::String tempDbgBuf; tempDbgBuf << dbgtext; beast::Logger::outputDebugString (tempDbgBuf); } #define BDBG(dbgtext) { \
beast::String tempDbgBuf; \
tempDbgBuf << dbgtext; \
beast::outputDebugString (tempDbgBuf.toStdString ()); \
}
#if 0 #if 0
/** This will always cause an assertion failure. /** This will always cause an assertion failure.

View File

@@ -1,23 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_CRYPTO_BINARYENCODING_H_INCLUDED
#define BEAST_CRYPTO_BINARYENCODING_H_INCLUDED
#endif

View File

@@ -23,9 +23,5 @@
#include <beast/crypto/impl/MurmurHash.cpp> #include <beast/crypto/impl/MurmurHash.cpp>
#include <beast/crypto/impl/Sha256.cpp> #include <beast/crypto/impl/Sha256.cpp>
#include <beast/crypto/impl/UnsignedInteger.cpp>
#include <beast/crypto/tests/BinaryEncoding.cpp>
#include <beast/crypto/tests/base64.test.cpp> #include <beast/crypto/tests/base64.test.cpp>
#include <beast/crypto/tests/UnsignedInteger.test.cpp>

View File

@@ -1,294 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_CRYPTO_UNSIGNEDINTEGER_H_INCLUDED
#define BEAST_CRYPTO_UNSIGNEDINTEGER_H_INCLUDED
#include <beast/crypto/UnsignedIntegerCalc.h>
#include <beast/crypto/MurmurHash.h>
#include <beast/ByteOrder.h>
#include <beast/container/hardened_hash.h>
#include <beast/utility/noexcept.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
namespace beast {
/** Represents a set of bits of fixed size.
The data is stored in "canonical" format which is network (big endian)
byte order, most significant byte first.
In this implementation the pointer to the beginning of the canonical format
may not be aligned.
*/
template <std::size_t Bytes>
class UnsignedInteger
{
public:
/** Constant for determining the number of bytes. */
static std::size_t const size = Bytes;
// The underlying integer type we use when converting to calculation format.
typedef std::uint32_t IntCalcType;
// The type of object resulting from a conversion to calculation format.
typedef UnsignedIntegerCalc <IntCalcType> CalcType;
// Standard container compatibility
typedef std::uint8_t value_type;
typedef value_type* iterator;
typedef value_type const* const_iterator;
/** Hardened hash function for use with hash based containers.
The seed is used to make the hash unpredictable. This prevents
attackers from exploiting crafted inputs to produce degenerate
containers.
*/
typedef hardened_hash <> hasher;
/** Determins if two UnsignedInteger objects are equal. */
class equal
{
public:
bool operator() (UnsignedInteger const& lhs, UnsignedInteger const& rhs) const
{
return lhs.compare (rhs) == 0;
}
};
//--------------------------------------------------------------------------
/** Construct the object.
The values are uninitialized.
*/
UnsignedInteger ()
{
}
/** Construct a copy. */
UnsignedInteger (UnsignedInteger const& other)
{
this->operator= (other);
}
/** Construct from a raw memory.
The area pointed to by buffer must be at least Bytes in size,
or else undefined behavior will result.
*/
/** @{ */
explicit UnsignedInteger (void const* buf)
{
m_values [0] = 0; // clear any pad bytes
std::memcpy (begin(), buf, Bytes);
}
template <typename InputIt>
UnsignedInteger (InputIt first, InputIt last)
{
m_values [0] = 0; // clear any pad bytes
assert (std::distance (first, last) == size);
std::copy (first, last, begin());
}
/** @} */
/** Assign from another UnsignedInteger. */
UnsignedInteger& operator= (UnsignedInteger const& other)
{
// Perform an aligned, all inclusive copy that includes padding.
std::copy (other.m_values, other.m_values + CalcCount, m_values);
return *this;
}
/** Create from an integer type.
@invariant IntegerType must be an unsigned integer type.
*/
template <class UnsignedIntegralType>
static UnsignedInteger createFromInteger (UnsignedIntegralType value)
{
static_assert (Bytes >= sizeof (UnsignedIntegralType),
"Bytes is too small.");
UnsignedInteger <Bytes> result;
value = toNetworkByteOrder <UnsignedIntegralType> (value);
result.clear ();
std::memcpy (result.end () - sizeof (value), &value,
std::min (Bytes, sizeof (value)));
return result;
}
/** Construct with a filled value. */
static UnsignedInteger createFilled (value_type value)
{
UnsignedInteger result;
result.fill (value);
return result;
}
/** Fill with a particular byte value. */
void fill (value_type value)
{
IntCalcType c;
memset (&c, value, sizeof (c));
std::fill (m_values, m_values + CalcCount, c);
}
/** Clear the contents to zero. */
void clear ()
{
std::fill (m_values, m_values + CalcCount, 0);
}
/** Convert to calculation format. */
CalcType toCalcType (bool convert = true)
{
return CalcType::fromCanonical (m_values, Bytes, convert);
}
/** Determine if all bits are zero. */
bool isZero () const
{
for (int i = 0; i < CalcCount; ++i)
{
if (m_values [i] != 0)
return false;
}
return true;
}
/** Determine if any bit is non-zero. */
bool isNotZero () const
{
return ! isZero ();
}
/** Support conversion to `bool`.
@return `true` if any bit is non-zero.
*/
explicit
operator bool() const
{
return isNotZero ();
}
/** Get an iterator to the beginning. */
iterator begin ()
{
return get();
}
/** Get an iterator to past-the-end. */
iterator end ()
{
return get()+Bytes;
}
/** Get a const iterator to the beginning. */
const_iterator begin () const
{
return get();
}
/** Get a const iterator to past-the-end. */
const_iterator end () const
{
return get()+Bytes;
}
/** Get a const iterator to the beginning. */
const_iterator cbegin () const
{
return get();
}
/** Get a const iterator to past-the-end. */
const_iterator cend () const
{
return get()+Bytes;
}
/** Compare two objects of equal size.
The comparison is performed using a numeric lexicographical comparison.
*/
int compare (UnsignedInteger const& other) const
{
return memcmp (cbegin (), other.cbegin (), Bytes);
}
/** Determine equality. */
bool operator== (UnsignedInteger const& other) const
{
return compare (other) == 0;
}
/** Determine inequality. */
bool operator!= (UnsignedInteger const& other) const
{
return compare (other) != 0;
}
/** Ordered comparison. */
bool operator< (UnsignedInteger const& other) const
{
return compare (other) < 0;
}
/** Ordered comparison. */
bool operator<= (UnsignedInteger const& other) const
{
return compare (other) <= 0;
}
/** Ordered comparison. */
bool operator> (UnsignedInteger const& other) const
{
return compare (other) > 0;
}
/** Ordered comparison. */
bool operator>= (UnsignedInteger const& other) const
{
return compare (other) >= 0;
}
private:
static std::size_t const CalcCount = (Bytes + sizeof (IntCalcType) - 1) / sizeof (IntCalcType);
value_type* get ()
{
return (reinterpret_cast <value_type*> (&m_values [0])) +
((sizeof(IntCalcType)-(Bytes&(sizeof(IntCalcType)-1)))&(sizeof(IntCalcType)-1));
}
value_type const* get () const
{
return (reinterpret_cast <value_type const*> (&m_values [0])) +
((sizeof(IntCalcType)-(Bytes&(sizeof(IntCalcType)-1)))&(sizeof(IntCalcType)-1));
}
IntCalcType m_values [CalcCount];
};
}
#endif

View File

@@ -1,442 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_CRYPTO_UNSIGNEDINTEGERCALC_H_INCLUDED
#define BEAST_CRYPTO_UNSIGNEDINTEGERCALC_H_INCLUDED
#include <beast/ByteOrder.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <utility>
namespace beast {
namespace detail {
template <typename UInt>
struct DoubleWidthUInt;
template <>
struct DoubleWidthUInt <std::uint16_t>
{
typedef std::uint32_t type;
};
template <>
struct DoubleWidthUInt <std::uint32_t>
{
typedef std::uint64_t type;
};
}
/** Multiprecision unsigned integer suitable for calculations.
The data is stored in "calculation" format, which means it can be
readily used for performing calculations, but no raw access to the
bytes are provided. To transmit a serialized unsigned integer or
perform base encodings, it must be converted back into UnsignedInteger.
The number is represented as a series of native UInt unsigned integer
types, in order of increasing significance.
This is a lightweight object, storage and ownership of the underlying
data buffer is an external responsibility. The makes the class cheap to
copy and pass by value.
A consequence of this ownership model is that arithmetics operators
which return results by value cannot be included in the interface.
*/
template <typename UInt>
class UnsignedIntegerCalc
{
public:
typedef typename detail::DoubleWidthUInt <UInt>::type UIntBig;
typedef std::size_t size_type;
static UInt const maxUInt = ((UInt)(-1));
static size_type const numBits = (sizeof(UInt)*8);
//--------------------------------------------------------------------------
/** Construct an empty integer / zero bits. */
UnsignedIntegerCalc ()
: m_size (0)
, m_values (nullptr)
{
}
/** Construct a reference to an existing buffer. */
UnsignedIntegerCalc (UnsignedIntegerCalc const& other)
: m_size (other.m_size)
, m_values (other.m_values)
{
}
/** Construct from an existing array of values.
The existing data must already be in the "calculation" format.
*/
UnsignedIntegerCalc (size_type count, UInt* values)
: m_size (count)
, m_values (values)
{
}
/** Convert to calculation format from canonical format.
This overwrites the callers memory without transferring ownership.
Canonical format is defined as a big endian byte oriented
multiprecision integer format. The buffer should point to the
beginning of the storage area and not the beginning of the canonical
data. Bytes is the desired canonical bytes.
*/
static UnsignedIntegerCalc fromCanonical (
void* buffer, size_type const bytes, bool swizzle = true)
{
UInt* const values (reinterpret_cast <UInt*> (buffer));
size_type const count ((bytes + sizeof (UInt) - 1) / sizeof (UInt));
if (swizzle)
{
// Zero fill the possibly uninitialized pad bytes
std::memset (buffer, 0,
((sizeof(UInt)-(bytes&(sizeof(UInt)-1)))&(sizeof(UInt)-1)));
// Swap and swizzle
UInt* lo (values);
UInt* hi (values + count - 1);
while (lo < hi)
{
std::swap (*lo, *hi);
*lo = fromNetworkByteOrder <UInt> (*lo);
++lo;
*hi = fromNetworkByteOrder <UInt> (*hi);
++hi;
}
if (lo == hi)
*lo = fromNetworkByteOrder <UInt> (*lo);
}
return UnsignedIntegerCalc (count, values);
}
/** Convert the buffer back into canonical format.
Since ownership was never transferred, the caller's data is
restored to its original format. Typically this will be done
as the last step of a series of operations.
*/
void toCanonical ()
{
// Swap and swizzle
UInt* lo (m_values);
UInt* hi (m_values + m_size - 1);
while (lo < hi)
{
std::swap (*lo, *hi);
*lo = toNetworkByteOrder <UInt> (*lo); ++lo;
*hi = toNetworkByteOrder <UInt> (*hi); --hi;
}
if (lo == hi)
*lo = toNetworkByteOrder <UInt> (*lo);
}
/** Assign a value from another integer.
@note This does not transfer the reference to the buffer, it
copies the values from one buffer to the other.
*/
UnsignedIntegerCalc& operator= (UnsignedIntegerCalc const& other)
{
assert (other.size() <= size());
size_type n (size());
UInt* dest (m_values + size());
for (; n-- > other.size();)
*--dest = 0;
UInt const* rhs (other.m_values + n);
for (; n--;)
*--dest = *--rhs;
return *this;
}
/** Returns `true` if this represents the number zero. */
bool isZero () const
{
for (size_type n (size()); n--;)
if (m_values [n] != 0)
return false;
return true;
}
/** Returns `true` if this represents any number other than zero. */
bool isNotZero () const
{
return ! isZero ();
}
/** Safe conversion to `bool`, `true` means a non-zero value. */
explicit
operator bool() const
{
return isNotZero ();
}
/** Returns `true` if the buffer has 0 values. */
bool empty () const
{
return m_size == 0;
}
/** Returns the size of the buffer, in values. */
size_type size () const
{
return m_size;
}
/** Safe array indexing to arbitrary positions.
If the index is out of range, zero is returned.
*/
UInt operator[] (size_type n) const
{
if (n >= 0 && n < size())
return m_values [n];
return 0;
}
/** Universal comparison.
The comparison is performed numerically.
The return values have the same meaning as memcmp().
*/
int compare (UnsignedIntegerCalc const& other) const
{
if (size() == 0)
{
if (other.size() == 0)
return 0;
return -1;
}
else if (other.size() == 0)
{
return 1;
}
for (size_type n (std::max (size(), other.size())); n--;)
{
UInt lhs ((*this)[n]);
UInt rhs (other[n]);
if (lhs < rhs)
return -1;
else if (lhs > rhs)
return 1;
}
return 0;
}
/** Determine equality. */
bool operator== (UnsignedIntegerCalc const& other) const
{
return compare (other) == 0;
}
/** Determine inequality. */
bool operator!= (UnsignedIntegerCalc const& other) const
{
return compare (other) != 0;
}
/** Ordered comparison. */
bool operator< (UnsignedIntegerCalc const& other) const
{
return compare (other) < 0;
}
/** Ordered comparison. */
bool operator<= (UnsignedIntegerCalc const& other) const
{
return compare (other) <= 0;
}
/** Ordered comparison. */
bool operator> (UnsignedIntegerCalc const& other) const
{
return compare (other) > 0;
}
/** Ordered comparison. */
bool operator>= (UnsignedIntegerCalc const& other) const
{
return compare (other) >= 0;
}
/** Assign zero. */
void clear ()
{
UInt* dest (m_values - 1);
for (size_type n (size()); n--;)
*++dest = 0;
}
/** Perform bitwise logical-not. */
/*
UnsignedIntegerCalc& not ()
{
unaryAssign (Not());
return *this;
}
*/
/** Perform bitwise logical-or. */
UnsignedIntegerCalc& operator|= (UnsignedIntegerCalc const& rhs)
{
binaryAssign (rhs, Or());
return *this;
}
/** Perform bitwise logical-and. */
UnsignedIntegerCalc& operator&= (UnsignedIntegerCalc const& rhs)
{
binaryAssign (rhs, And());
return *this;
}
/** Perform bitwise logical-xor. */
UnsignedIntegerCalc& operator^= (UnsignedIntegerCalc const& rhs)
{
binaryAssign (rhs, Xor());
return *this;
}
/** Perform addition. */
UnsignedIntegerCalc& operator+= (UnsignedIntegerCalc const& v)
{
UIntBig carry (0);
UInt* lhs (m_values);
UInt const* rhs (v.m_values - 1);
for (size_type n (0); n<size() || n<v.size(); ++n)
{
UIntBig part (carry);
carry = 0;
if (n < size())
part += *lhs;
if (n < v.size())
part += *++rhs;
if (part > maxUInt)
{
part &= maxUInt;
carry = 1;
}
*lhs++ = UInt (part);
}
assert (carry == 0); // overflow
return *this;
}
/** Perform small addition. */
UnsignedIntegerCalc& operator+= (UInt rhs)
{
UnsignedIntegerCalc const v (1, &rhs);
return operator+= (v);
}
/** Perform small multiply. */
UnsignedIntegerCalc& operator*= (UInt rhs)
{
UIntBig carry (0);
UInt* lhs (m_values - 1);
for (size_type n (size()); n--;)
{
UIntBig part (carry);
carry = 0;
part += (*++lhs) * UIntBig(rhs);
carry = part >> numBits;
*lhs = UInt (part & maxUInt);
}
assert (carry == 0); // overflow
return *this;
}
/** Small division. */
UnsignedIntegerCalc operator/= (UInt rhs)
{
UIntBig dividend (0);
UInt* lhs (m_values+size());
for (size_type n (size()); n--;)
{
dividend |= *--lhs;
*lhs = UInt (dividend / rhs);
dividend = (dividend % rhs) << numBits;
}
return *this;
}
/** Small modulus. */
UInt operator% (UInt rhs) const
{
UIntBig modsq = 1;
UIntBig result = 0;
UInt const* lhs (m_values);
for (size_type n (size()); n--; ++lhs)
{
for (int bit (0); bit < numBits; ++bit)
{
if (((*lhs) & (1 << bit)) != 0)
{
result += modsq;
if (result >= rhs)
result -= rhs;
}
modsq <<= 1;
if (modsq >= rhs)
modsq -= rhs;
}
}
return UInt (result);
}
private:
struct Not { void operator() (UInt& rv) const { rv = ~rv; } };
struct Or { void operator() (UInt& lhs, UInt rhs) const { lhs |= rhs; } };
struct And { void operator() (UInt& lhs, UInt rhs) const { lhs &= rhs; } };
struct Xor { void operator() (UInt& lhs, UInt rhs) const { lhs ^= rhs; } };
template <class Operator>
void unaryAssign (Operator op = Operator())
{
UInt* dest (m_values-1);
for (size_type n (size()); n--;)
op (*++dest);
}
template <class Operator>
void binaryAssign (UnsignedIntegerCalc const& other, Operator op = Operator ())
{
UInt* dest (m_values + size());
size_type n (size());
for (; n-- > other.size();)
*--dest = 0;
UInt const* rhs (other.m_values + n);
for (UInt const* rhs (other.m_values + n); n--;)
op (*--dest, *--rhs);
}
size_type m_size;
UInt* m_values;
};
}
#endif

View File

@@ -1,346 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions are Copyright (c) 2013 the authors listed at the following URL,
and/or the authors of referenced articles or incorporated external code:
http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C)
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/crypto/UnsignedInteger.h>
#include <beast/unit_test/suite.h>
namespace beast {
namespace multiprecsion {
#if 0
/* Copyright (c) 2013 the authors listed at the following URL, and/or
the authors of referenced articles or incorporated external code:
http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C)
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.
*/
//
// Retrieved from: http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C)?oldid=16902
//
typedef unsigned short component_t;
typedef unsigned long double_component_t;
#define MAX_COMPONENT ((component_t)(-1))
#define COMPONENT_BITS (sizeof(component_t)*CHAR_BIT)
#define LOG_2_10 3.3219280948873623478703194294894
#define MIN(x,y) ((x)<(y) ? (x) : (y))
#define MAX(x,y) ((x)>(y) ? (x) : (y))
typedef struct {
component_t* c; /* least-significant word first */
int num_components;
} integer;
integer create_integer(int components);
void free_integer(integer i);
void set_zero_integer(integer i);
void copy_integer(integer source, integer target);
void add_integer(integer left, integer right, integer result);
void subtract_integer(integer left, integer right, integer result);
void multiply_small_integer(integer left, component_t right, integer result);
void multiply_integer(integer left, integer right, integer result);
int compare_integers(integer left, integer right);
void shift_left_one_integer(integer arg);
void shift_right_one_integer(integer arg);
component_t mod_small_integer(integer left, component_t right);
void mod_integer(integer left, integer right, integer result);
void divide_small_integer(integer left, component_t right, integer result);
integer string_to_integer(char* s);
char* integer_to_string(integer x);
int is_zero_integer(integer x);
//------------------------------------------------------------------------------
integer create_integer(int components) {
integer result;
result.num_components = components;
result.c = (component_t*)malloc(sizeof(component_t)*components);
return result;
}
void free_integer(integer i) {
free(i.c);
}
void set_zero_integer(integer i) {
memset(i.c, 0, sizeof(component_t)*i.num_components);
}
int is_zero_integer(integer x) {
int i;
for(i=0; i < x.num_components; i++) {
if (x.c[i] != 0) return 0;
}
return 1;
}
void copy_integer(integer source, integer target) {
memmove(target.c, source.c,
sizeof(component_t)*MIN(source.num_components, target.num_components));
if (target.num_components > source.num_components) {
memset(target.c + source.num_components, 0,
sizeof(component_t)*(target.num_components - source.num_components));
}
}
void add_integer(integer left, integer right, integer result) {
double_component_t carry = 0;
int i;
for(i=0; i<left.num_components || i<right.num_components || carry != 0; i++) {
double_component_t partial_sum = carry;
carry = 0;
if (i < left.num_components) partial_sum += left.c[i];
if (i < right.num_components) partial_sum += right.c[i];
if (partial_sum > MAX_COMPONENT) {
partial_sum &= MAX_COMPONENT;
carry = 1;
}
result.c[i] = (component_t)partial_sum;
}
for ( ; i < result.num_components; i++) { result.c[i] = 0; }
}
void subtract_integer(integer left, integer right, integer result) {
int borrow = 0;
int i;
for(i=0; i<left.num_components; i++) {
double_component_t lhs = left.c[i];
double_component_t rhs = (i < right.num_components) ? right.c[i] : 0;
if (borrow) {
if (lhs <= rhs) {
/* leave borrow set to 1 */
lhs += (MAX_COMPONENT + 1) - 1;
} else {
borrow = 0;
lhs--;
}
}
if (lhs < rhs) {
borrow = 1;
lhs += MAX_COMPONENT + 1;
}
result.c[i] = lhs - rhs;
}
for ( ; i < result.num_components; i++) { result.c[i] = 0; }
}
void multiply_small_integer(integer left, component_t right, integer result) {
double_component_t carry = 0;
int i;
for(i=0; i<left.num_components || carry != 0; i++) {
double_component_t partial_sum = carry;
carry = 0;
if (i < left.num_components) partial_sum += left.c[i]*right;
carry = partial_sum >> COMPONENT_BITS;
result.c[i] = (component_t)(partial_sum & MAX_COMPONENT);
}
for ( ; i < result.num_components; i++) { result.c[i] = 0; }
}
void multiply_integer(integer left, integer right, integer result) {
int i, lidx, ridx;
double_component_t carry = 0;
int max_size_no_carry;
int left_max_component = left.num_components - 1;
int right_max_component = right.num_components - 1;
while(left.c[left_max_component] == 0) left_max_component--;
while(right.c[right_max_component] == 0) right_max_component--;
max_size_no_carry = left_max_component + right_max_component;
for(i=0; i <= max_size_no_carry || carry != 0; i++) {
double_component_t partial_sum = carry;
carry = 0;
lidx = MIN(i, left_max_component);
ridx = i - lidx;
while(lidx >= 0 && ridx <= right_max_component) {
partial_sum += ((double_component_t)left.c[lidx])*right.c[ridx];
carry += partial_sum >> COMPONENT_BITS;
partial_sum &= MAX_COMPONENT;
lidx--; ridx++;
}
result.c[i] = partial_sum;
}
for ( ; i < result.num_components; i++) { result.c[i] = 0; }
}
int compare_integers(integer left, integer right) {
int i = MAX(left.num_components - 1, right.num_components - 1);
for ( ; i >= 0; i--) {
component_t left_comp =
(i < left.num_components) ? left.c[i] : 0;
component_t right_comp =
(i < right.num_components) ? right.c[i] : 0;
if (left_comp < right_comp)
return -1;
else if (left_comp > right_comp)
return 1;
}
return 0;
}
void shift_left_one_integer(integer arg) {
int i;
arg.c[arg.num_components - 1] <<= 1;
for (i = arg.num_components - 2; i >= 0; i--) {
arg.c[i + 1] |= arg.c[i] >> (COMPONENT_BITS - 1);
arg.c[i] <<= 1;
}
}
void shift_right_one_integer(integer arg) {
int i;
arg.c[0] >>= 1;
for (i = 1; i < arg.num_components; i++) {
arg.c[i - 1] |= (arg.c[i] & 1) << (COMPONENT_BITS - 1);
arg.c[i] >>= 1;
}
}
component_t mod_small_integer(integer left, component_t right) {
double_component_t mod_two_power = 1;
double_component_t result = 0;
int i, bit;
for(i=0; i<left.num_components; i++) {
for(bit=0; bit<COMPONENT_BITS; bit++) {
if ((left.c[i] & (1 << bit)) != 0) {
result += mod_two_power;
if (result >= right) {
result -= right;
}
}
mod_two_power <<= 1;
if (mod_two_power >= right) {
mod_two_power -= right;
}
}
}
return (component_t)result;
}
void mod_integer(integer left, integer right, integer result) {
integer mod_two_power = create_integer(right.num_components + 1);
int i, bit;
set_zero_integer(result);
set_zero_integer(mod_two_power);
mod_two_power.c[0] = 1;
for(i=0; i<left.num_components; i++) {
for(bit=0; bit<COMPONENT_BITS; bit++) {
if ((left.c[i] & (1 << bit)) != 0) {
add_integer(result, mod_two_power, result);
if (compare_integers(result, right) >= 0) {
subtract_integer(result, right, result);
}
}
shift_left_one_integer(mod_two_power);
if (compare_integers(mod_two_power, right) >= 0) {
subtract_integer(mod_two_power, right, mod_two_power);
}
}
}
free_integer(mod_two_power);
}
void divide_small_integer(integer left, component_t right, integer result) {
double_component_t dividend = 0;
int i;
for (i = left.num_components - 1; i >= 0; i--) {
dividend |= left.c[i];
result.c[i] = dividend/right;
dividend = (dividend % right) << COMPONENT_BITS;
}
}
integer string_to_integer(char* s) {
integer result = create_integer((int)ceil(LOG_2_10*strlen(s)/COMPONENT_BITS));
set_zero_integer(result);
integer digit = create_integer(1);
int i;
for (i = 0; s[i] != '\0'; i++) {
multiply_small_integer(result, 10, result);
digit.c[0] = s[i] - '0';
add_integer(result, digit, result);
}
free_integer(digit);
return result;
}
char* integer_to_string(integer x) {
int i, result_len;
char* result =
(char*)malloc((int)ceil(COMPONENT_BITS*x.num_components/LOG_2_10) + 2);
integer ten = create_integer(1);
ten.c[0] = 10;
if (is_zero_integer(x)) {
strcpy(result, "0");
} else {
for (i = 0; !is_zero_integer(x); i++) {
result[i] = (char)mod_small_integer(x, 10) + '0';
divide_small_integer(x, 10, x);
}
result[i] = '\0';
}
result_len = strlen(result);
for(i=0; i < result_len/2; i++) {
char temp = result[i];
result[i] = result[result_len - i - 1];
result[result_len - i - 1] = temp;
}
free_integer(ten);
return result;
}
#endif
}
}

View File

@@ -1,417 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
// MODULES: ../../../modules/beast_core/beast_core.beast_core.unity.cpp ../../strings/Strings.cpp ../../chrono/Chrono.cpp ../../threads/Threads.cpp
#include <beast/crypto/BinaryEncoding.h>
#include <beast/crypto/UnsignedInteger.h>
#include <beast/unit_test/suite.h>
#include <beast/module/core/maths/Random.h>
#include <cstddef>
#include <string>
namespace beast {
/** Generic algorithms for base encoding and decoding. */
class BinaryEncoding
{
public:
/** Concept: Conversion
X denotes a Conversion class, a is a value of type X,
i is an integral type.
Requirements:
Expression Type Notes/Contracts
------------- ----------- ------------------
X a;
X::radix size_type constexpr
a.map (i) char maps base numeral to a char
*/
/** Encode the unsigned integer into a string using the specified conversion. */
template <typename Conversion, std::size_t Bytes>
static std::string encode (UnsignedInteger <Bytes> v, Conversion c = Conversion ())
{
// bi is destroyed in this process
typename UnsignedInteger <Bytes>::CalcType bi (v.toCalcType ());
std::size_t const radix (Conversion::radix);
std::string s;
s.reserve (bi.size() * 3); // guess
while (bi.isNotZero ())
{
std::size_t const m (bi % radix);
bi /= radix;
s.push_back (c.map (m));
}
std::reverse (s.begin(), s.end());
return s;
}
/** Decode the string into an unsigned integer.
The size must match exactly
@return `true` on success.
*/
template <typename Conversion, std::size_t Bytes>
static bool decode (UnsignedInteger <Bytes>& rv,
std::string const& s, Conversion c = Conversion ())
{
typename UnsignedInteger <Bytes>::CalcType bi (rv.toCalcType (false));
std::size_t const radix (Conversion::radix);
bi.clear ();
for (std::string::const_iterator iter (s.begin()); iter != s.end(); ++iter)
{
int const v (c.invert (*iter));
if (v == -1)
return false;
bi *= radix;
bi += v;
}
bi.toCanonical();
return true;
}
};
//------------------------------------------------------------------------------
// Some common code
template <class Conversion>
class BaseConversion
{
public:
char map (std::size_t i) const
{
return Conversion::alphabet () [i];
}
int invert (char c) const
{
return Conversion::inverse_alphabet () [c];
}
static std::vector <int> const& inverse_alphabet ()
{
static std::vector <int> t (invert (Conversion::alphabet(), Conversion::radix));
return t;
}
/** Build the inverse mapping table from characters to digits. */
static std::vector <int>
invert (std::string const& alphabet, int radix)
{
std::vector <int> table (256, -1);
for (int i (0); i < radix; ++i)
table [alphabet [i]] = i;
return table;
}
};
//------------------------------------------------------------------------------
/** Foolproof hexadecimal encoding and decoding facility.
This is to check the correctness of the more complex converters.
*/
class HexEncoding
{
public:
template <std::size_t Bytes>
static std::string encode (UnsignedInteger <Bytes> const& v)
{
std::string s;
std::uint8_t const* src (v.cbegin()-1);
char const* const tab (alphabet().c_str());
s.reserve (Bytes * 2);
for (std::size_t bytes (v.size);bytes--;)
{
std::uint8_t const v (*++src);
s.push_back (tab [v>>4]);
s.push_back (tab [v&0x0f]);
}
return s;
}
template <std::size_t Bytes>
static bool decode (UnsignedInteger <Bytes>& rv,
std::string const& s)
{
// can't have an odd size
if (s.size() & 1)
return false;
std::uint8_t* dest (rv.begin()-1);
int const* const tab (&inverse_alphabet().front());
for (std::string::const_iterator iter (s.begin()); iter != s.end();)
{
int const n1 (tab [*iter++]);
if (n1 == -1)
return false;
int const n2 (tab [*iter++]);
if (n2 == -1)
return false;
*++dest = ((std::uint8_t)((n1<<4)|n2));
}
return true;
}
static std::string const& alphabet ()
{
static std::string s ("0123456789ABCDEF");
return s;
}
static std::vector <int> const& inverse_alphabet ()
{
static std::vector <int> s (invert (alphabet(), 16));
return s;
}
/** Build the inverse mapping table from characters to digits. */
static std::vector <int>
invert (std::string const& alphabet, int radix)
{
std::vector <int> table (256, -1);
for (int i (0); i < radix; ++i)
table [alphabet [i]] = int(i);
return table;
}
};
//------------------------------------------------------------------------------
/** Base58 conversion used by Bitcoin. */
class BitcoinBase58Conversion : public BaseConversion <BitcoinBase58Conversion>
{
public:
static std::size_t const radix = 58;
char const* name () const
{
return "BitcoinBase58";
}
static std::string const& alphabet ()
{
static std::string s (
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
);
return s;
}
};
//------------------------------------------------------------------------------
/** Base58 conversion used by Ripple. */
class RippleBase58Conversion : public BaseConversion <RippleBase58Conversion>
{
public:
static std::size_t const radix = 58;
char const* name () const
{
return "RippleBase58";
}
static std::string const& alphabet ()
{
static std::string s (
"rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
);
return s;
}
};
//------------------------------------------------------------------------------
class Base64Conversion : public BaseConversion <Base64Conversion>
{
public:
static std::size_t const radix = 64;
char const* name () const
{
return "Base64";
}
static std::string const& alphabet ()
{
static std::string s (
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
);
return s;
}
};
//------------------------------------------------------------------------------
class Base16Conversion : public BaseConversion <Base16Conversion>
{
public:
static std::size_t const radix = 16;
char const* name () const
{
return "Hex";
}
static std::string const& alphabet ()
{
static std::string s (
"0123456789ABCDEF"
);
return s;
}
};
//------------------------------------------------------------------------------
class BinaryEncoding_test : public unit_test::suite
{
public:
// This is a baseline for the other tests
template <std::size_t Bytes>
void testBase16 ()
{
Random r;
testcase ("base16");
for (int i = 0; i < 50; ++i)
{
typedef UnsignedInteger <Bytes> UInt;
UInt v0;
r.fillBitsRandomly (v0.begin(), UInt::size);
std::string const good (HexEncoding::encode (v0));
UInt v1;
bool const success (HexEncoding::decode (v1, good));
if (expect (success))
{
expect (v0 == v1);
Base16Conversion c;
std::string const check (BinaryEncoding::encode (v0, c));
expect (good == check,
std::string ("expected ") + good + " but got " + check);
}
}
}
template <std::size_t Bytes>
void testBase64Bytes (
std::string const& vin, std::string const& vout,
Base64Conversion c = Base64Conversion ())
{
typedef UnsignedInteger <Bytes> UInt;
UInt v1 (vin.c_str());
std::string const s1 (BinaryEncoding::encode (v1, c));
log <<
vout + " to " + s1;
expect (vout == s1);
UInt v2;
bool const success (BinaryEncoding::decode (v2, vout, c));
if (expect (success))
{
std::string const s2 (BinaryEncoding::encode (v2, c));
log <<
vin + " to " + s2;
}
}
void testBase64 ()
{
testcase ("Base64");
// input (uint)
std::string const vin [] = {
"","f","fo","foo","foob","fooba","foobar"
};
// output (encoded string)
std::string const vout [] = {
"","Zg==","Zm8=","Zm9v","Zm9vYg==","Zm9vYmE=","Zm9vYmFy"
};
//testBase64Bytes <0> (vin [0], vout [0]);
testBase64Bytes <1> (vin [1], vout [1]);
testBase64Bytes <2> (vin [2], vout [2]);
testBase64Bytes <3> (vin [3], vout [3]);
testBase64Bytes <4> (vin [4], vout [4]);
testBase64Bytes <5> (vin [5], vout [5]);
testBase64Bytes <6> (vin [6], vout [6]);
}
template <typename Conversion, std::size_t Bytes>
void testEncode (Conversion c = Conversion())
{
typedef UnsignedInteger <Bytes> UInt;
#if 0
std::stringstream ss;
ss <<
c.name() << " <" << Bytes << ">";
testcase (ss.str());
#else
testcase << c.name() << " <" << Bytes << ">";
#endif
Random r;
for (int i = 0; i < 50; ++i)
{
UInt v1;
r.fillBitsRandomly (v1.begin(), UInt::size);
std::string const s1 (BinaryEncoding::encode (v1, c));
UInt v2;
bool success (BinaryEncoding::decode (v2, s1, c));
if (expect (success))
expect (v1 == v2);
}
}
void run ()
{
testBase16 <10> ();
#if 0
testEncode <Base16Conversion, 1> ();
testEncode <Base16Conversion, 2> ();
testEncode <Base16Conversion, 3> ();
testEncode <Base16Conversion, 4> ();
testEncode <Base16Conversion, 5> ();
testEncode <Base16Conversion, 6> ();
testEncode <Base16Conversion, 7> ();
testEncode <Base16Conversion, 8> ();
testEncode <Base16Conversion, 9> ();
testEncode <Base16Conversion, 10> ();
testBase64 ();
testEncode <Base64Conversion, 20> ();
testEncode <Base64Conversion, 33> ();
testEncode <RippleBase58Conversion, 20> ();
testEncode <RippleBase58Conversion, 33> ();
testEncode <BitcoinBase58Conversion, 20> ();
testEncode <BitcoinBase58Conversion, 33> ();
#endif
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(BinaryEncoding,crypto,beast);
}

View File

@@ -1,81 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions are Copyright (c) 2013 the authors listed at the following URL,
and/or the authors of referenced articles or incorporated external code:
http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C)
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/crypto/UnsignedInteger.h>
#include <beast/unit_test/suite.h>
namespace beast {
class UnsignedInteger_test : public unit_test::suite
{
public:
template <unsigned int Bytes>
void test ()
{
typedef UnsignedInteger <Bytes> UInt;
std::stringstream ss;
ss <<
"bytes=" << Bytes;
testcase (ss.str());
UInt zero;
zero.fill (0);
expect (zero.isZero (), "should be zero");
expect (! zero.isNotZero (), "sould not be non-zero");
UInt one (UInt::createFromInteger (1U));
expect (one == UInt::createFromInteger (1U), "should be equal");
expect (! one.isZero (), "should not be zero");
expect (one.isNotZero (), "sould be non-zero");
expect (zero < one, "should be less");
expect (one > zero, "should be greater");
expect (zero >= zero, "should be less than or equal");
expect (one <= one, "should be less than or equal");
expect (zero == zero, "should be equal");
expect (zero != one, "should not be equal");
expect (zero == UInt::createFromInteger (0U), "should be zero");
expect (one == UInt::createFromInteger (1U), "should be one");
expect (one != UInt::createFromInteger (2U), "should not be two");
UInt largest = UInt::createFilled (0xff);
expect (largest > zero && largest > one, "should be greater");
}
void run()
{
test <16> ();
test <33> ();
}
private:
};
BEAST_DEFINE_TESTSUITE(UnsignedInteger,crypto,beast);
}

View File

@@ -347,7 +347,7 @@ public:
ss << s; ss << s;
} }
//m_journal.trace << std::endl << ss.str (); //m_journal.trace << std::endl << ss.str ();
Logger::outputDebugString (ss.str ()); outputDebugString (ss.str ());
#endif #endif
} }

View File

@@ -20,8 +20,7 @@
#ifndef BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED #ifndef BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
#define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED #define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
#include <beast/Atomic.h> #include <atomic>
#include <iterator> #include <iterator>
#include <type_traits> #include <type_traits>
@@ -80,7 +79,7 @@ public:
LockFreeStackIterator& operator++ () LockFreeStackIterator& operator++ ()
{ {
m_node = m_node->m_next.get(); m_node = m_node->m_next.load ();
return static_cast <LockFreeStackIterator&> (*this); return static_cast <LockFreeStackIterator&> (*this);
} }
@@ -147,22 +146,24 @@ public:
class Node class Node
{ {
public: public:
Node () = default; Node ()
: m_next (nullptr)
{ }
explicit Node (Node* next)
: m_next (next)
{ }
Node(Node const&) = delete; Node(Node const&) = delete;
Node& operator= (Node const&) = delete; Node& operator= (Node const&) = delete;
explicit Node (Node* next) : m_next (next)
{
}
private: private:
friend class LockFreeStack; friend class LockFreeStack;
template <class Container, bool IsConst> template <class Container, bool IsConst>
friend class LockFreeStackIterator; friend class LockFreeStackIterator;
Atomic <Node*> m_next; std::atomic <Node*> m_next;
}; };
public: public:
@@ -190,7 +191,7 @@ public:
/** Returns true if the stack is empty. */ /** Returns true if the stack is empty. */
bool empty() const bool empty() const
{ {
return m_head.get() == &m_end; return m_head.load () == &m_end;
} }
/** Push a node onto the stack. /** Push a node onto the stack.
@@ -208,14 +209,15 @@ public:
bool push_front (Node* node) bool push_front (Node* node)
{ {
bool first; bool first;
Node* head; Node* old_head = m_head.load (std::memory_order_relaxed);
do do
{ {
head = m_head.get (); first = (old_head == &m_end);
first = head == &m_end; node->m_next = old_head;
node->m_next = head;
} }
while (!m_head.compareAndSetBool (node, head)); while (!m_head.compare_exchange_strong (old_head, node,
std::memory_order_release,
std::memory_order_relaxed));
return first; return first;
} }
@@ -230,16 +232,17 @@ public:
*/ */
Element* pop_front () Element* pop_front ()
{ {
Node* node; Node* node = m_head.load ();
Node* head; Node* new_head;
do do
{ {
node = m_head.get ();
if (node == &m_end) if (node == &m_end)
return nullptr; return nullptr;
head = node->m_next.get (); new_head = node->m_next.load ();
} }
while (!m_head.compareAndSetBool (head, node)); while (!m_head.compare_exchange_strong (node, new_head,
std::memory_order_release,
std::memory_order_relaxed));
return static_cast <Element*> (node); return static_cast <Element*> (node);
} }
@@ -252,7 +255,7 @@ public:
/** @{ */ /** @{ */
iterator begin () iterator begin ()
{ {
return iterator (m_head.get ()); return iterator (m_head.load ());
} }
iterator end () iterator end ()
@@ -262,7 +265,7 @@ public:
const_iterator begin () const const_iterator begin () const
{ {
return const_iterator (m_head.get ()); return const_iterator (m_head.load ());
} }
const_iterator end () const const_iterator end () const
@@ -272,7 +275,7 @@ public:
const_iterator cbegin () const const_iterator cbegin () const
{ {
return const_iterator (m_head.get ()); return const_iterator (m_head.load ());
} }
const_iterator cend () const const_iterator cend () const
@@ -283,7 +286,7 @@ public:
private: private:
Node m_end; Node m_end;
Atomic <Node*> m_head; std::atomic <Node*> m_head;
}; };
} }

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_ASIO_ASYNCOBJECT_H_INCLUDED #ifndef BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
#define BEAST_ASIO_ASYNCOBJECT_H_INCLUDED #define BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
#include <beast/Atomic.h> #include <atomic>
#include <cassert> #include <cassert>
namespace beast { namespace beast {
@@ -33,11 +33,16 @@ namespace asio {
template <class Derived> template <class Derived>
class AsyncObject class AsyncObject
{ {
protected:
AsyncObject ()
: m_pending (0)
{ }
public: public:
~AsyncObject () ~AsyncObject ()
{ {
// Destroying the object with I/O pending? Not a clean exit! // Destroying the object with I/O pending? Not a clean exit!
assert (m_pending.get() == 0); assert (m_pending.load () == 0);
} }
/** RAII container that maintains the count of pending I/O. /** RAII container that maintains the count of pending I/O.
@@ -65,8 +70,9 @@ public:
m_owner->asyncHandlersComplete (); m_owner->asyncHandlersComplete ();
} }
CompletionCounter& operator= (CompletionCounter const&) = delete;
private: private:
CompletionCounter& operator= (CompletionCounter const&);
Derived* m_owner; Derived* m_owner;
}; };
@@ -83,7 +89,7 @@ public:
private: private:
// The number of handlers pending. // The number of handlers pending.
beast::Atomic <int> m_pending; std::atomic <int> m_pending;
}; };
} }

View File

@@ -1050,8 +1050,8 @@ private:
void minimiseStorageAfterRemoval() void minimiseStorageAfterRemoval()
{ {
if (data.numAllocated > bmax (minimumAllocatedSize, numUsed * 2)) if (data.numAllocated > std::max (minimumAllocatedSize, numUsed * 2))
data.shrinkToNoMoreThan (bmax (numUsed, bmax (minimumAllocatedSize, 64 / (int) sizeof (ElementType)))); data.shrinkToNoMoreThan (std::max (numUsed, std::max (minimumAllocatedSize, 64 / (int) sizeof (ElementType))));
} }
}; };

View File

@@ -1,371 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_LINKEDLISTPOINTER_H_INCLUDED
#define BEAST_LINKEDLISTPOINTER_H_INCLUDED
namespace beast
{
//==============================================================================
/**
Helps to manipulate singly-linked lists of objects.
For objects that are designed to contain a pointer to the subsequent item in the
list, this class contains methods to deal with the list. To use it, the ObjectType
class that it points to must contain a LinkedListPointer called nextListItem, e.g.
@code
struct MyObject
{
int x, y, z;
// A linkable object must contain a member with this name and type, which must be
// accessible by the LinkedListPointer class. (This doesn't mean it has to be public -
// you could make your class a friend of a LinkedListPointer<MyObject> instead).
LinkedListPointer<MyObject> nextListItem;
};
LinkedListPointer<MyObject> myList;
myList.append (new MyObject());
myList.append (new MyObject());
int numItems = myList.size(); // returns 2
MyObject* lastInList = myList.getLast();
@endcode
*/
template <class ObjectType>
class LinkedListPointer
{
public:
//==============================================================================
/** Creates a null pointer to an empty list. */
LinkedListPointer() noexcept
: item (nullptr)
{
}
LinkedListPointer(LinkedListPointer const&) = delete;
LinkedListPointer& operator= (LinkedListPointer const&) = delete;
/** Creates a pointer to a list whose head is the item provided. */
explicit LinkedListPointer (ObjectType* const headItem) noexcept
: item (headItem)
{
}
/** Sets this pointer to point to a new list. */
LinkedListPointer& operator= (ObjectType* const newItem) noexcept
{
item = newItem;
return *this;
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
LinkedListPointer (LinkedListPointer&& other) noexcept
: item (other.item)
{
other.item = nullptr;
}
LinkedListPointer& operator= (LinkedListPointer&& other) noexcept
{
bassert (this != &other); // hopefully the compiler should make this situation impossible!
item = other.item;
other.item = nullptr;
return *this;
}
#endif
//==============================================================================
/** Returns the item which this pointer points to. */
inline operator ObjectType*() const noexcept
{
return item;
}
/** Returns the item which this pointer points to. */
inline ObjectType* get() const noexcept
{
return item;
}
/** Returns the last item in the list which this pointer points to.
This will iterate the list and return the last item found. Obviously the speed
of this operation will be proportional to the size of the list. If the list is
empty the return value will be this object.
If you're planning on appending a number of items to your list, it's much more
efficient to use the Appender class than to repeatedly call getLast() to find the end.
*/
LinkedListPointer& getLast() noexcept
{
LinkedListPointer* l = this;
while (l->item != nullptr)
l = &(l->item->nextListItem);
return *l;
}
/** Returns the number of items in the list.
Obviously with a simple linked list, getting the size involves iterating the list, so
this can be a lengthy operation - be careful when using this method in your code.
*/
int size() const noexcept
{
int total = 0;
for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
++total;
return total;
}
/** Returns the item at a given index in the list.
Since the only way to find an item is to iterate the list, this operation can obviously
be slow, depending on its size, so you should be careful when using this in algorithms.
*/
LinkedListPointer& operator[] (int index) noexcept
{
LinkedListPointer* l = this;
while (--index >= 0 && l->item != nullptr)
l = &(l->item->nextListItem);
return *l;
}
/** Returns the item at a given index in the list.
Since the only way to find an item is to iterate the list, this operation can obviously
be slow, depending on its size, so you should be careful when using this in algorithms.
*/
const LinkedListPointer& operator[] (int index) const noexcept
{
const LinkedListPointer* l = this;
while (--index >= 0 && l->item != nullptr)
l = &(l->item->nextListItem);
return *l;
}
/** Returns true if the list contains the given item. */
bool contains (const ObjectType* const itemToLookFor) const noexcept
{
for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
if (itemToLookFor == i)
return true;
return false;
}
//==============================================================================
/** Inserts an item into the list, placing it before the item that this pointer
currently points to.
*/
void insertNext (ObjectType* const newItem)
{
bassert (newItem != nullptr);
bassert (newItem->nextListItem == nullptr);
newItem->nextListItem = item;
item = newItem;
}
/** Inserts an item at a numeric index in the list.
Obviously this will involve iterating the list to find the item at the given index,
so be careful about the impact this may have on execution time.
*/
void insertAtIndex (int index, ObjectType* newItem)
{
bassert (newItem != nullptr);
LinkedListPointer* l = this;
while (index != 0 && l->item != nullptr)
{
l = &(l->item->nextListItem);
--index;
}
l->insertNext (newItem);
}
/** Replaces the object that this pointer points to, appending the rest of the list to
the new object, and returning the old one.
*/
ObjectType* replaceNext (ObjectType* const newItem) noexcept
{
bassert (newItem != nullptr);
bassert (newItem->nextListItem == nullptr);
ObjectType* const oldItem = item;
item = newItem;
item->nextListItem = oldItem->nextListItem.item;
oldItem->nextListItem.item = nullptr;
return oldItem;
}
/** Adds an item to the end of the list.
This operation involves iterating the whole list, so can be slow - if you need to
append a number of items to your list, it's much more efficient to use the Appender
class than to repeatedly call append().
*/
void append (ObjectType* const newItem)
{
getLast().item = newItem;
}
/** Creates copies of all the items in another list and adds them to this one.
This will use the ObjectType's copy constructor to try to create copies of each
item in the other list, and appends them to this list.
*/
void addCopyOfList (const LinkedListPointer& other)
{
LinkedListPointer* insertPoint = this;
for (ObjectType* i = other.item; i != nullptr; i = i->nextListItem)
{
insertPoint->insertNext (new ObjectType (*i));
insertPoint = &(insertPoint->item->nextListItem);
}
}
/** Removes the head item from the list.
This won't delete the object that is removed, but returns it, so the caller can
delete it if necessary.
*/
ObjectType* removeNext() noexcept
{
ObjectType* const oldItem = item;
if (oldItem != nullptr)
{
item = oldItem->nextListItem;
oldItem->nextListItem.item = nullptr;
}
return oldItem;
}
/** Removes a specific item from the list.
Note that this will not delete the item, it simply unlinks it from the list.
*/
void remove (ObjectType* const itemToRemove)
{
if (LinkedListPointer* const l = findPointerTo (itemToRemove))
l->removeNext();
}
/** Iterates the list, calling the delete operator on all of its elements and
leaving this pointer empty.
*/
void deleteAll()
{
while (item != nullptr)
{
ObjectType* const oldItem = item;
item = oldItem->nextListItem;
delete oldItem;
}
}
/** Finds a pointer to a given item.
If the item is found in the list, this returns the pointer that points to it. If
the item isn't found, this returns null.
*/
LinkedListPointer* findPointerTo (ObjectType* const itemToLookFor) noexcept
{
LinkedListPointer* l = this;
while (l->item != nullptr)
{
if (l->item == itemToLookFor)
return l;
l = &(l->item->nextListItem);
}
return nullptr;
}
/** Copies the items in the list to an array.
The destArray must contain enough elements to hold the entire list - no checks are
made for this!
*/
void copyToArray (ObjectType** destArray) const noexcept
{
bassert (destArray != nullptr);
for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
*destArray++ = i;
}
/** Swaps this pointer with another one */
void swapWith (LinkedListPointer& other) noexcept
{
std::swap (item, other.item);
}
//==============================================================================
/**
Allows efficient repeated insertions into a list.
You can create an Appender object which points to the last element in your
list, and then repeatedly call Appender::append() to add items to the end
of the list in O(1) time.
*/
class Appender
{
public:
/** Creates an appender which will add items to the given list.
*/
Appender (LinkedListPointer& endOfListPointer) noexcept
: endOfList (&endOfListPointer)
{
// This can only be used to add to the end of a list.
bassert (endOfListPointer.item == nullptr);
}
Appender(LinkedListPointer const&) = delete;
Appender& operator= (Appender const&) = delete;
/** Appends an item to the list. */
void append (ObjectType* const newItem) noexcept
{
*endOfList = newItem;
endOfList = &(newItem->nextListItem);
}
private:
LinkedListPointer* endOfList;
};
private:
//==============================================================================
ObjectType* item;
};
} // beast
#endif // BEAST_LINKEDLISTPOINTER_H_INCLUDED

View File

@@ -1,99 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_SCOPEDVALUESETTER_H_INCLUDED
#define BEAST_SCOPEDVALUESETTER_H_INCLUDED
namespace beast
{
//==============================================================================
/**
Helper class providing an RAII-based mechanism for temporarily setting and
then re-setting a value.
E.g. @code
int x = 1;
{
ScopedValueSetter setter (x, 2);
// x is now 2
}
// x is now 1 again
{
ScopedValueSetter setter (x, 3, 4);
// x is now 3
}
// x is now 4
@endcode
*/
template <typename ValueType>
class ScopedValueSetter
{
public:
/** Creates a ScopedValueSetter that will immediately change the specified value to the
given new value, and will then reset it to its original value when this object is deleted.
*/
ScopedValueSetter (ValueType& valueToSet,
ValueType newValue)
: value (valueToSet),
originalValue (valueToSet)
{
valueToSet = newValue;
}
/** Creates a ScopedValueSetter that will immediately change the specified value to the
given new value, and will then reset it to be valueWhenDeleted when this object is deleted.
*/
ScopedValueSetter (ValueType& valueToSet,
ValueType newValue,
ValueType valueWhenDeleted)
: value (valueToSet),
originalValue (valueWhenDeleted)
{
valueToSet = newValue;
}
ScopedValueSetter(ScopedValueSetter const&) = delete;
ScopedValueSetter& operator= (ScopedValueSetter const&) = delete;
~ScopedValueSetter()
{
value = originalValue;
}
private:
//==============================================================================
ValueType& value;
const ValueType originalValue;
};
} // beast
#endif // BEAST_SCOPEDVALUESETTER_H_INCLUDED

View File

@@ -41,7 +41,6 @@
// New header-only library modeled more closely according to boost // New header-only library modeled more closely according to boost
#include <beast/SmartPtr.h> #include <beast/SmartPtr.h>
#include <beast/StaticAssert.h>
#include <beast/Atomic.h> #include <beast/Atomic.h>
#include <beast/Arithmetic.h> #include <beast/Arithmetic.h>
#include <beast/ByteOrder.h> #include <beast/ByteOrder.h>
@@ -136,13 +135,9 @@ class FileOutputStream;
#include <beast/module/core/thread/MutexTraits.h> #include <beast/module/core/thread/MutexTraits.h>
#include <beast/module/core/diagnostic/FatalError.h> #include <beast/module/core/diagnostic/FatalError.h>
#include <beast/module/core/text/LexicalCast.h> #include <beast/module/core/text/LexicalCast.h>
#include <beast/module/core/maths/Math.h>
#include <beast/module/core/logging/Logger.h> #include <beast/module/core/logging/Logger.h>
#include <beast/module/core/containers/LinkedListPointer.h>
#include <beast/module/core/maths/Random.h> #include <beast/module/core/maths/Random.h>
#include <beast/module/core/text/StringPairArray.h> #include <beast/module/core/text/StringPairArray.h>
#include <beast/module/core/containers/ScopedValueSetter.h>
#include <beast/module/core/maths/Range.h>
#include <beast/module/core/files/DirectoryIterator.h> #include <beast/module/core/files/DirectoryIterator.h>
#include <beast/module/core/streams/InputStream.h> #include <beast/module/core/streams/InputStream.h>
#include <beast/module/core/files/FileInputStream.h> #include <beast/module/core/files/FileInputStream.h>
@@ -150,17 +145,11 @@ class FileOutputStream;
#include <beast/module/core/streams/FileInputSource.h> #include <beast/module/core/streams/FileInputSource.h>
#include <beast/module/core/streams/OutputStream.h> #include <beast/module/core/streams/OutputStream.h>
#include <beast/module/core/files/FileOutputStream.h> #include <beast/module/core/files/FileOutputStream.h>
#include <beast/module/core/files/FileSearchPath.h>
#include <beast/module/core/files/RandomAccessFile.h>
#include <beast/module/core/files/TemporaryFile.h>
#include <beast/module/core/logging/Logger.h>
#include <beast/module/core/memory/SharedSingleton.h> #include <beast/module/core/memory/SharedSingleton.h>
#include <beast/module/core/misc/WindowsRegistry.h>
#include <beast/module/core/streams/MemoryOutputStream.h> #include <beast/module/core/streams/MemoryOutputStream.h>
#include <beast/module/core/system/SystemStats.h> #include <beast/module/core/system/SystemStats.h>
#include <beast/module/core/diagnostic/SemanticVersion.h> #include <beast/module/core/diagnostic/SemanticVersion.h>
#include <beast/module/core/threads/DynamicLibrary.h>
#include <beast/module/core/threads/Process.h> #include <beast/module/core/threads/Process.h>
#include <beast/module/core/diagnostic/UnitTestUtilities.h> #include <beast/module/core/diagnostic/UnitTestUtilities.h>

View File

@@ -134,11 +134,6 @@
#include <beast/module/core/files/File.cpp> #include <beast/module/core/files/File.cpp>
#include <beast/module/core/files/FileInputStream.cpp> #include <beast/module/core/files/FileInputStream.cpp>
#include <beast/module/core/files/FileOutputStream.cpp> #include <beast/module/core/files/FileOutputStream.cpp>
#include <beast/module/core/files/FileSearchPath.cpp>
#include <beast/module/core/files/RandomAccessFile.cpp>
#include <beast/module/core/files/TemporaryFile.cpp>
#include <beast/module/core/logging/Logger.cpp>
#include <beast/module/core/maths/Random.cpp> #include <beast/module/core/maths/Random.cpp>
@@ -182,9 +177,7 @@
#include <beast/module/core/native/mac_Threads.mm> #include <beast/module/core/native/mac_Threads.mm>
#elif BEAST_WINDOWS #elif BEAST_WINDOWS
#include <beast/module/core/native/win32_ComSmartPtr.h>
#include <beast/module/core/native/win32_Files.cpp> #include <beast/module/core/native/win32_Files.cpp>
#include <beast/module/core/native/win32_Registry.cpp>
#include <beast/module/core/native/win32_SystemStats.cpp> #include <beast/module/core/native/win32_SystemStats.cpp>
#include <beast/module/core/native/win32_Threads.cpp> #include <beast/module/core/native/win32_Threads.cpp>

View File

@@ -26,45 +26,50 @@ namespace beast {
// FatalError::Reporter // FatalError::Reporter
// //
void FatalError::Reporter::onFatalError ( void FatalError::Reporter::onFatalError (
char const* message, char const* stackBacktrace, char const* filePath, int lineNumber) char const* message,
char const* backtrace,
char const* filePath,
int lineNumber)
{ {
String formattedMessage = formatMessage ( reportMessage (formatMessage (message, backtrace, filePath, lineNumber));
message, stackBacktrace, filePath, lineNumber);
reportMessage (formattedMessage);
} }
void FatalError::Reporter::reportMessage (String& formattedMessage) void FatalError::Reporter::reportMessage (std::string const& message)
{ {
std::cerr << formattedMessage.toRawUTF8 (); std::cerr << message << std::endl;
} }
String FatalError::Reporter::formatMessage ( std::string FatalError::Reporter::formatMessage (
char const* message, char const* stackBacktrace, char const* filePath, int lineNumber) char const* message,
char const* backtrace,
char const* filePath,
int lineNumber)
{ {
String formattedMessage; std::string output;
formattedMessage.preallocateBytes (16 * 1024); output.reserve (16 * 1024);
formattedMessage << message; output.append (message);
if (filePath != nullptr && filePath [0] != 0) if (filePath != nullptr && filePath [0] != 0)
{ {
formattedMessage << ", in " << formatFilePath (filePath) output.append (", in ");
<< " line " << String (lineNumber); output.append (formatFilePath (filePath));
output.append (" line ");
output.append (std::to_string (lineNumber));
} }
formattedMessage << newLine; output.append ("\n");
if (stackBacktrace != nullptr && stackBacktrace [0] != 0) if (backtrace != nullptr && backtrace[0] != 0)
{ {
formattedMessage << "Stack:" << newLine; output.append ("Stack:\n");
formattedMessage << stackBacktrace; output.append (backtrace);
} }
return formattedMessage; return output;
} }
String FatalError::Reporter::formatFilePath (char const* filePath) std::string FatalError::Reporter::formatFilePath (char const* filePath)
{ {
return filePath; return filePath;
} }
@@ -94,19 +99,13 @@ FatalError::FatalError (char const* message, char const* fileName, int lineNumbe
std::lock_guard <LockType> lock (s_mutex); std::lock_guard <LockType> lock (s_mutex);
String const backtraceString = SystemStats::getStackBacktrace (); auto const backtrace = SystemStats::getStackBacktrace ();
char const* const szStackBacktrace = backtraceString.toRawUTF8 (); Reporter* const reporter = s_reporter;
String const fileNameString = fileName;
char const* const szFileName = fileNameString.toRawUTF8 ();
Reporter* const reporter (s_reporter);
if (reporter != nullptr) if (reporter != nullptr)
{ {
reporter->onFatalError (message, szStackBacktrace, szFileName, lineNumber); reporter->onFatalError (message, backtrace.c_str (), fileName, lineNumber);
} }
Process::terminate (); Process::terminate ();

View File

@@ -68,7 +68,7 @@ public:
@param lineNumber The line number in the source file. @param lineNumber The line number in the source file.
*/ */
virtual void onFatalError (char const* message, virtual void onFatalError (char const* message,
char const* stackBacktrace, char const* backtrace,
char const* filePath, char const* filePath,
int lineNumber); int lineNumber);
@@ -80,7 +80,7 @@ public:
@param formattedMessage The message to report. @param formattedMessage The message to report.
*/ */
virtual void reportMessage (String& formattedMessage); virtual void reportMessage (std::string const& formattedMessage);
protected: protected:
/** Called to format the message. /** Called to format the message.
@@ -96,10 +96,11 @@ public:
@param filePath The file path from the report. @param filePath The file path from the report.
@param lineNumber The line number from the report @param lineNumber The line number from the report
*/ */
virtual String formatMessage (char const* message, virtual std::string formatMessage (
char const* stackBacktrace, char const* message,
char const* filePath, char const* backtrace,
int lineNumber); char const* filePath,
int lineNumber);
/** Call to reformat the file path. /** Call to reformat the file path.
@@ -111,7 +112,7 @@ public:
You can override this to do a custom format on the file path. You can override this to do a custom format on the file path.
*/ */
virtual String formatFilePath (char const* filePath); virtual std::string formatFilePath (char const* filePath);
}; };
/** Returns the current fatal error reporter. */ /** Returns the current fatal error reporter. */

View File

@@ -272,7 +272,7 @@ int compare (SemanticVersion const& lhs, SemanticVersion const& rhs)
return -1; return -1;
// Compare pre-release identifiers // Compare pre-release identifiers
for (int i = 0; i < bmax (lhs.preReleaseIdentifiers.size (), rhs.preReleaseIdentifiers.size ()); ++i) for (int i = 0; i < std::max (lhs.preReleaseIdentifiers.size (), rhs.preReleaseIdentifiers.size ()); ++i)
{ {
// A larger list of identifiers has a higher precedence // A larger list of identifiers has a higher precedence
if (i >= rhs.preReleaseIdentifiers.size ()) if (i >= rhs.preReleaseIdentifiers.size ())

View File

@@ -22,6 +22,8 @@
//============================================================================== //==============================================================================
#include <beast/unit_test/suite.h> #include <beast/unit_test/suite.h>
#include <algorithm>
#include <memory> #include <memory>
namespace beast { namespace beast {
@@ -168,10 +170,6 @@ String File::parseAbsolutePath (const String& p)
path if that's what was supplied, or would evaluate a partial path relative to the CWD. path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/ */
bassertfalse; bassertfalse;
#if BEAST_LOG_ASSERTIONS
Logger::writeToLog ("Illegal absolute path: " + path);
#endif
} }
#endif #endif
@@ -422,21 +420,6 @@ File File::getSiblingFile (const String& fileName) const
return getParentDirectory().getChildFile (fileName); return getParentDirectory().getChildFile (fileName);
} }
//==============================================================================
String File::descriptionOfSizeInBytes (const std::int64_t bytes)
{
const char* suffix;
double divisor = 0;
if (bytes == 1) { suffix = " byte"; }
else if (bytes < 1024) { suffix = " bytes"; }
else if (bytes < 1024 * 1024) { suffix = " KB"; divisor = 1024.0; }
else if (bytes < 1024 * 1024 * 1024) { suffix = " MB"; divisor = 1024.0 * 1024.0; }
else { suffix = " GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
return (divisor > 0 ? String (bytes / divisor, 1) : String (bytes)) + suffix;
}
//============================================================================== //==============================================================================
Result File::create() const Result File::create() const
{ {
@@ -486,31 +469,6 @@ bool File::setLastModificationTime (Time t) const { return setFileTimesIntern
bool File::setLastAccessTime (Time t) const { return setFileTimesInternal (0, t.toMilliseconds(), 0); } bool File::setLastAccessTime (Time t) const { return setFileTimesInternal (0, t.toMilliseconds(), 0); }
bool File::setCreationTime (Time t) const { return setFileTimesInternal (0, 0, t.toMilliseconds()); } bool File::setCreationTime (Time t) const { return setFileTimesInternal (0, 0, t.toMilliseconds()); }
//==============================================================================
bool File::loadFileAsData (MemoryBlock& destBlock) const
{
if (! existsAsFile())
return false;
FileInputStream in (*this);
return in.openedOk() && getSize() == in.readIntoMemoryBlock (destBlock);
}
String File::loadFileAsString() const
{
if (! existsAsFile())
return String::empty;
FileInputStream in (*this);
return in.openedOk() ? in.readEntireStreamAsString()
: String::empty;
}
void File::readLines (StringArray& destLines) const
{
destLines.addLines (loadFileAsString());
}
//============================================================================== //==============================================================================
int File::findChildFiles (Array<File>& results, int File::findChildFiles (Array<File>& results,
const int whatToLookFor, const int whatToLookFor,
@@ -666,12 +624,6 @@ File File::withFileExtension (const String& newExtension) const
return getSiblingFile (filePart + newExtension); return getSiblingFile (filePart + newExtension);
} }
//==============================================================================
bool File::startAsProcess (const String& parameters) const
{
return exists() && Process::openDocument (fullPath, parameters);
}
//============================================================================== //==============================================================================
FileInputStream* File::createInputStream() const FileInputStream* File::createInputStream() const
{ {
@@ -704,17 +656,6 @@ bool File::appendData (const void* const dataToAppend,
return out.openedOk() && out.write (dataToAppend, numberOfBytes); return out.openedOk() && out.write (dataToAppend, numberOfBytes);
} }
bool File::replaceWithData (const void* const dataToWrite,
const size_t numberOfBytes) const
{
if (numberOfBytes == 0)
return deleteFile();
TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
tempFile.getFile().appendData (dataToWrite, numberOfBytes);
return tempFile.overwriteTargetFileWithTemporary();
}
bool File::appendText (const String& text, bool File::appendText (const String& text,
const bool asUnicode, const bool asUnicode,
const bool writeUnicodeHeaderBytes) const const bool writeUnicodeHeaderBytes) const
@@ -728,49 +669,6 @@ bool File::appendText (const String& text,
return true; return true;
} }
bool File::replaceWithText (const String& textToWrite,
const bool asUnicode,
const bool writeUnicodeHeaderBytes) const
{
TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
tempFile.getFile().appendText (textToWrite, asUnicode, writeUnicodeHeaderBytes);
return tempFile.overwriteTargetFileWithTemporary();
}
bool File::hasIdenticalContentTo (const File& other) const
{
if (other == *this)
return true;
if (getSize() == other.getSize() && existsAsFile() && other.existsAsFile())
{
FileInputStream in1 (*this), in2 (other);
if (in1.openedOk() && in2.openedOk())
{
const int bufferSize = 4096;
HeapBlock <char> buffer1 (bufferSize), buffer2 (bufferSize);
for (;;)
{
const int num1 = in1.read (buffer1, bufferSize);
const int num2 = in2.read (buffer2, bufferSize);
if (num1 != num2)
break;
if (num1 <= 0)
return true;
if (memcmp (buffer1, buffer2, (size_t) num1) != 0)
break;
}
}
}
return false;
}
//============================================================================== //==============================================================================
String File::createLegalPathName (const String& original) String File::createLegalPathName (const String& original)
{ {
@@ -798,7 +696,7 @@ String File::createLegalFileName (const String& original)
{ {
const int lastDot = s.lastIndexOfChar ('.'); const int lastDot = s.lastIndexOfChar ('.');
if (lastDot > bmax (0, len - 12)) if (lastDot > std::max (0, len - 12))
{ {
s = s.substring (0, maxLength - (len - lastDot)) s = s.substring (0, maxLength - (len - lastDot))
+ s.substring (lastDot); + s.substring (lastDot);
@@ -929,34 +827,14 @@ public:
expect (! home.existsAsFile()); expect (! home.existsAsFile());
expect (File::getSpecialLocation (File::userDocumentsDirectory).isDirectory()); expect (File::getSpecialLocation (File::userDocumentsDirectory).isDirectory());
expect (File::getSpecialLocation (File::userApplicationDataDirectory).isDirectory()); expect (File::getSpecialLocation (File::userApplicationDataDirectory).isDirectory());
expect (File::getSpecialLocation (File::currentExecutableFile).exists());
expect (File::getSpecialLocation (File::currentApplicationFile).exists());
expect (File::getSpecialLocation (File::invokedExecutableFile).exists());
expect (home.getVolumeTotalSize() > 1024 * 1024); expect (home.getVolumeTotalSize() > 1024 * 1024);
expect (home.getBytesFreeOnVolume() > 0); expect (home.getBytesFreeOnVolume() > 0);
expect (! home.isHidden());
expect (home.isOnHardDisk());
expect (! home.isOnCDRomDrive());
expect (File::getCurrentWorkingDirectory().exists()); expect (File::getCurrentWorkingDirectory().exists());
expect (home.setAsCurrentWorkingDirectory()); expect (home.setAsCurrentWorkingDirectory());
#if BEAST_WINDOWS #if BEAST_WINDOWS
expect (File::getCurrentWorkingDirectory() == home); expect (File::getCurrentWorkingDirectory() == home);
#endif #endif
{
Array<File> roots;
File::findFileSystemRoots (roots);
expect (roots.size() > 0);
int numRootsExisting = 0;
for (int i = 0; i < roots.size(); ++i)
if (roots[i].exists())
++numRootsExisting;
// (on windows, some of the drives may not contain media, so as long as at least one is ok..)
expect (numRootsExisting > 0);
}
testcase ("Writing"); testcase ("Writing");
File demoFolder (temp.getChildFile ("Beast UnitTests Temp Folder.folder")); File demoFolder (temp.getChildFile ("Beast UnitTests Temp Folder.folder"));
@@ -998,7 +876,6 @@ public:
expect (tempFile.exists()); expect (tempFile.exists());
expect (tempFile.getSize() == 10); expect (tempFile.getSize() == 10);
expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000); expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000);
expect (tempFile.loadFileAsString() == String ("0123456789"));
expect (! demoFolder.containsSubDirectories()); expect (! demoFolder.containsSubDirectories());
expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName()); expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName());
@@ -1023,13 +900,6 @@ public:
Time t2 = tempFile.getLastModificationTime(); Time t2 = tempFile.getLastModificationTime();
expect (std::abs ((int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000); expect (std::abs ((int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
{
MemoryBlock mb;
tempFile.loadFileAsData (mb);
expect (mb.getSize() == 10);
expect (mb[0] == '0');
}
{ {
expect (tempFile.getSize() == 10); expect (tempFile.getSize() == 10);
FileOutputStream fo (tempFile); FileOutputStream fo (tempFile);
@@ -1047,13 +917,10 @@ public:
expect (tempFile.appendData ("abcdefghij", 10)); expect (tempFile.appendData ("abcdefghij", 10));
expect (tempFile.getSize() == 20); expect (tempFile.getSize() == 20);
expect (tempFile.replaceWithData ("abcdefghij", 10));
expect (tempFile.getSize() == 10);
File tempFile2 (tempFile.getNonexistentSibling (false)); File tempFile2 (tempFile.getNonexistentSibling (false));
expect (tempFile.copyFileTo (tempFile2)); expect (tempFile.copyFileTo (tempFile2));
expect (tempFile2.exists()); expect (tempFile2.exists());
expect (tempFile2.hasIdenticalContentTo (tempFile));
expect (tempFile.deleteFile()); expect (tempFile.deleteFile());
expect (! tempFile.exists()); expect (! tempFile.exists());
expect (tempFile2.moveFileTo (tempFile)); expect (tempFile2.moveFileTo (tempFile));

View File

@@ -134,13 +134,6 @@ public:
*/ */
std::int64_t getSize() const; std::int64_t getSize() const;
/** Utility function to convert a file size in bytes to a neat string description.
So for example 100 would return "100 bytes", 2000 would return "2 KB",
2000000 would produce "2 MB", etc.
*/
static String descriptionOfSizeInBytes (std::int64_t bytes);
//============================================================================== //==============================================================================
/** Returns the complete, absolute path of this file. /** Returns the complete, absolute path of this file.
@@ -354,16 +347,6 @@ public:
bool setReadOnly (bool shouldBeReadOnly, bool setReadOnly (bool shouldBeReadOnly,
bool applyRecursively = false) const; bool applyRecursively = false) const;
/** Returns true if this file is a hidden or system file.
The criteria for deciding whether a file is hidden are platform-dependent.
*/
bool isHidden() const;
/** If this file is a link, this returns the file that it points to.
If this file isn't actually link, it'll just return itself.
*/
File getLinkedTarget() const;
//============================================================================== //==============================================================================
/** Returns the last modification time of this file. /** Returns the last modification time of this file.
@@ -410,14 +393,6 @@ public:
*/ */
bool setCreationTime (Time newTime) const; bool setCreationTime (Time newTime) const;
/** If possible, this will try to create a version string for the given file.
The OS may be able to look at the file and give a version for it - e.g. with
executables, bundles, dlls, etc. If no version is available, this will
return an empty string.
*/
String getVersion() const;
//============================================================================== //==============================================================================
/** Creates an empty file if it doesn't already exist. /** Creates an empty file if it doesn't already exist.
@@ -464,14 +439,6 @@ public:
*/ */
bool deleteRecursively() const; bool deleteRecursively() const;
/** Moves this file or folder to the trash.
@returns true if the operation succeeded. It could fail if the trash is full, or
if the file is write-protected, so you should check the return value
and act appropriately.
*/
bool moveToTrash() const;
/** Moves or renames a file. /** Moves or renames a file.
Tries to move a file to a different location. Tries to move a file to a different location.
@@ -572,7 +539,7 @@ public:
@returns a stream that will read from this file (initially positioned at the @returns a stream that will read from this file (initially positioned at the
start of the file), or nullptr if the file can't be opened for some reason start of the file), or nullptr if the file can't be opened for some reason
@see createOutputStream, loadFileAsData @see createOutputStream
*/ */
FileInputStream* createInputStream() const; FileInputStream* createInputStream() const;
@@ -588,33 +555,6 @@ public:
*/ */
FileOutputStream* createOutputStream (size_t bufferSize = 0x8000) const; FileOutputStream* createOutputStream (size_t bufferSize = 0x8000) const;
//==============================================================================
/** Loads a file's contents into memory as a block of binary data.
Of course, trying to load a very large file into memory will blow up, so
it's better to check first.
@param result the data block to which the file's contents should be appended - note
that if the memory block might already contain some data, you
might want to clear it first
@returns true if the file could all be read into memory
*/
bool loadFileAsData (MemoryBlock& result) const;
/** Reads a file into memory as a string.
Attempts to load the entire file as a zero-terminated string.
This makes use of InputStream::readEntireStreamAsString, which can
read either UTF-16 or UTF-8 file formats.
*/
String loadFileAsString() const;
/** Reads the contents of this file as text and splits it into lines, which are
appended to the given StringArray.
*/
void readLines (StringArray& destLines) const;
//============================================================================== //==============================================================================
/** Appends a block of binary data to the end of the file. /** Appends a block of binary data to the end of the file.
@@ -625,23 +565,6 @@ public:
bool appendData (const void* dataToAppend, bool appendData (const void* dataToAppend,
size_t numberOfBytes) const; size_t numberOfBytes) const;
/** Replaces this file's contents with a given block of data.
This will delete the file and replace it with the given data.
A nice feature of this method is that it's safe - instead of deleting
the file first and then re-writing it, it creates a new temporary file,
writes the data to that, and then moves the new file to replace the existing
file. This means that if the power gets pulled out or something crashes,
you're a lot less likely to end up with a corrupted or unfinished file..
Returns true if the operation succeeds, or false if it fails.
@see appendText
*/
bool replaceWithData (const void* dataToWrite,
size_t numberOfBytes) const;
/** Appends a string to the end of the file. /** Appends a string to the end of the file.
This will try to append a text string to the file, as either 16-bit unicode This will try to append a text string to the file, as either 16-bit unicode
@@ -658,50 +581,7 @@ public:
bool asUnicode = false, bool asUnicode = false,
bool writeUnicodeHeaderBytes = false) const; bool writeUnicodeHeaderBytes = false) const;
/** Replaces this file's contents with a given text string.
This will delete the file and replace it with the given text.
A nice feature of this method is that it's safe - instead of deleting
the file first and then re-writing it, it creates a new temporary file,
writes the text to that, and then moves the new file to replace the existing
file. This means that if the power gets pulled out or something crashes,
you're a lot less likely to end up with an empty file..
For an explanation of the parameters here, see the appendText() method.
Returns true if the operation succeeds, or false if it fails.
@see appendText
*/
bool replaceWithText (const String& textToWrite,
bool asUnicode = false,
bool writeUnicodeHeaderBytes = false) const;
/** Attempts to scan the contents of this file and compare it to another file, returning
true if this is possible and they match byte-for-byte.
*/
bool hasIdenticalContentTo (const File& other) const;
//============================================================================== //==============================================================================
/** Creates a set of files to represent each file root.
e.g. on Windows this will create files for "c:\", "d:\" etc according
to which ones are available. On the Mac/Linux, this will probably
just add a single entry for "/".
*/
static void findFileSystemRoots (Array<File>& results);
/** Finds the name of the drive on which this file lives.
@returns the volume label of the drive, or an empty string if this isn't possible
*/
String getVolumeLabel() const;
/** Returns the serial number of the volume on which this file lives.
@returns the serial number, or zero if there's a problem doing this
*/
int getVolumeSerialNumber() const;
/** Returns the number of bytes free on the drive that this file lives on. /** Returns the number of bytes free on the drive that this file lives on.
@returns the number of bytes free, or 0 if there's a problem finding this out @returns the number of bytes free, or 0 if there's a problem finding this out
@@ -716,41 +596,6 @@ public:
*/ */
std::int64_t getVolumeTotalSize() const; std::int64_t getVolumeTotalSize() const;
/** Returns true if this file is on a CD or DVD drive. */
bool isOnCDRomDrive() const;
/** Returns true if this file is on a hard disk.
This will fail if it's a network drive, but will still be true for
removable hard-disks.
*/
bool isOnHardDisk() const;
/** Returns true if this file is on a removable disk drive.
This might be a usb-drive, a CD-rom, or maybe a network drive.
*/
bool isOnRemovableDrive() const;
//==============================================================================
/** Launches the file as a process.
- if the file is executable, this will run it.
- if it's a document of some kind, it will launch the document with its
default viewer application.
- if it's a folder, it will be opened in Explorer, Finder, or equivalent.
@see revealToUser
*/
bool startAsProcess (const String& parameters = String::empty) const;
/** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location.
@see startAsProcess
*/
void revealToUser() const;
//============================================================================== //==============================================================================
/** A set of types of location that can be passed to the getSpecialLocation() method. /** A set of types of location that can be passed to the getSpecialLocation() method.
*/ */
@@ -806,39 +651,6 @@ public:
*/ */
tempDirectory, tempDirectory,
/** Returns this application's executable file.
If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
host app.
On the mac this will return the unix binary, not the package folder - see
currentApplicationFile for that.
See also invokedExecutableFile, which is similar, but if the exe was launched from a
file link, invokedExecutableFile will return the name of the link.
*/
currentExecutableFile,
/** Returns this application's location.
If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
host app.
On the mac this will return the package folder (if it's in one), not the unix binary
that's inside it - compare with currentExecutableFile.
*/
currentApplicationFile,
/** Returns the file that was invoked to launch this executable.
This may differ from currentExecutableFile if the app was started from e.g. a link - this
will return the name of the link that was used, whereas currentExecutableFile will return
the actual location of the target executable.
*/
invokedExecutableFile,
/** In a plugin, this will return the path of the host executable. */
hostApplicationPath,
/** The directory in which applications normally get installed. /** The directory in which applications normally get installed.
So on windows, this would be something like "c:\program files", on the So on windows, this would be something like "c:\program files", on the
Mac "/Applications", or "/usr" on linux. Mac "/Applications", or "/usr" on linux.
@@ -926,25 +738,6 @@ public:
/** Adds a separator character to the end of a path if it doesn't already have one. */ /** Adds a separator character to the end of a path if it doesn't already have one. */
static String addTrailingSeparator (const String& path); static String addTrailingSeparator (const String& path);
#if BEAST_MAC || BEAST_IOS || DOXYGEN
//==============================================================================
/** OSX ONLY - Finds the OSType of a file from the its resources. */
OSType getMacOSType() const;
/** OSX ONLY - Returns true if this file is actually a bundle. */
bool isBundle() const;
#endif
#if BEAST_MAC || DOXYGEN
/** OSX ONLY - Adds this file to the OSX dock */
void addToDock() const;
#endif
#if BEAST_WINDOWS
/** Windows ONLY - Creates a win32 .LNK shortcut file that links to this file. */
bool createLink (const String& description, const File& linkFileToCreate) const;
#endif
private: private:
//============================================================================== //==============================================================================
String fullPath; String fullPath;

View File

@@ -21,6 +21,8 @@
*/ */
//============================================================================== //==============================================================================
#include <algorithm>
namespace beast namespace beast
{ {
@@ -34,7 +36,7 @@ FileOutputStream::FileOutputStream (const File& f, const size_t bufferSizeToUse)
currentPosition (0), currentPosition (0),
bufferSize (bufferSizeToUse), bufferSize (bufferSizeToUse),
bytesInBuffer (0), bytesInBuffer (0),
buffer (bmax (bufferSizeToUse, (size_t) 16)) buffer (std::max (bufferSizeToUse, (size_t) 16))
{ {
openHandle(); openHandle();
} }

View File

@@ -49,8 +49,6 @@ public:
be set to the end of the file. To overwrite an existing file, be set to the end of the file. To overwrite an existing file,
use File::deleteFile() before opening the stream, or use setPosition(0) use File::deleteFile() before opening the stream, or use setPosition(0)
after it's opened (although this won't truncate the file). after it's opened (although this won't truncate the file).
@see TemporaryFile
*/ */
FileOutputStream (const File& fileToWriteTo, FileOutputStream (const File& fileToWriteTo,
size_t bufferSizeToUse = 16384); size_t bufferSizeToUse = 16384);

View File

@@ -1,171 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace beast
{
FileSearchPath::FileSearchPath()
{
}
FileSearchPath::FileSearchPath (const String& path)
{
init (path);
}
FileSearchPath::FileSearchPath (const FileSearchPath& other)
: directories (other.directories)
{
}
FileSearchPath::~FileSearchPath()
{
}
FileSearchPath& FileSearchPath::operator= (const String& path)
{
init (path);
return *this;
}
void FileSearchPath::init (const String& path)
{
directories.clear();
directories.addTokens (path, ";", "\"");
directories.trim();
directories.removeEmptyStrings();
for (int i = directories.size(); --i >= 0;)
directories.set (i, directories[i].unquoted());
}
int FileSearchPath::getNumPaths() const
{
return directories.size();
}
File FileSearchPath::operator[] (const int index) const
{
return File (directories [index]);
}
String FileSearchPath::toString() const
{
StringArray directories2 (directories);
for (int i = directories2.size(); --i >= 0;)
if (directories2[i].containsChar (';'))
directories2.set (i, directories2[i].quoted());
return directories2.joinIntoString (";");
}
void FileSearchPath::add (const File& dir, const int insertIndex)
{
directories.insert (insertIndex, dir.getFullPathName());
}
void FileSearchPath::addIfNotAlreadyThere (const File& dir)
{
for (int i = 0; i < directories.size(); ++i)
if (File (directories[i]) == dir)
return;
add (dir);
}
void FileSearchPath::remove (const int index)
{
directories.remove (index);
}
void FileSearchPath::addPath (const FileSearchPath& other)
{
for (int i = 0; i < other.getNumPaths(); ++i)
addIfNotAlreadyThere (other[i]);
}
void FileSearchPath::removeRedundantPaths()
{
for (int i = directories.size(); --i >= 0;)
{
const File d1 (directories[i]);
for (int j = directories.size(); --j >= 0;)
{
const File d2 (directories[j]);
if ((i != j) && (d1.isAChildOf (d2) || d1 == d2))
{
directories.remove (i);
break;
}
}
}
}
void FileSearchPath::removeNonExistentPaths()
{
for (int i = directories.size(); --i >= 0;)
if (! File (directories[i]).isDirectory())
directories.remove (i);
}
int FileSearchPath::findChildFiles (Array<File>& results,
const int whatToLookFor,
const bool searchRecursively,
const String& wildCardPattern) const
{
int total = 0;
for (int i = 0; i < directories.size(); ++i)
total += operator[] (i).findChildFiles (results,
whatToLookFor,
searchRecursively,
wildCardPattern);
return total;
}
bool FileSearchPath::isFileInPath (const File& fileToCheck,
const bool checkRecursively) const
{
for (int i = directories.size(); --i >= 0;)
{
const File d (directories[i]);
if (checkRecursively)
{
if (fileToCheck.isAChildOf (d))
return true;
}
else
{
if (fileToCheck.getParentDirectory() == d)
return true;
}
}
return false;
}
} // beast

View File

@@ -1,163 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_FILESEARCHPATH_H_INCLUDED
#define BEAST_FILESEARCHPATH_H_INCLUDED
namespace beast
{
//==============================================================================
/**
Encapsulates a set of folders that make up a search path.
@see File
*/
class FileSearchPath : LeakChecked <FileSearchPath>
{
public:
//==============================================================================
/** Creates an empty search path. */
FileSearchPath();
/** Creates a search path from a string of pathnames.
The path can be semicolon- or comma-separated, e.g.
"/foo/bar;/foo/moose;/fish/moose"
The separate folders are tokenised and added to the search path.
*/
FileSearchPath (const String& path);
/** Creates a copy of another search path. */
FileSearchPath (const FileSearchPath& other);
/** Destructor. */
~FileSearchPath();
/** Uses a string containing a list of pathnames to re-initialise this list.
This search path is cleared and the semicolon- or comma-separated folders
in this string are added instead. e.g. "/foo/bar;/foo/moose;/fish/moose"
*/
FileSearchPath& operator= (const String& path);
//==============================================================================
/** Returns the number of folders in this search path.
@see operator[]
*/
int getNumPaths() const;
/** Returns one of the folders in this search path.
The file returned isn't guaranteed to actually be a valid directory.
@see getNumPaths
*/
File operator[] (int index) const;
/** Returns the search path as a semicolon-separated list of directories. */
String toString() const;
//==============================================================================
/** Adds a new directory to the search path.
The new directory is added to the end of the list if the insertIndex parameter is
less than zero, otherwise it is inserted at the given index.
*/
void add (const File& directoryToAdd,
int insertIndex = -1);
/** Adds a new directory to the search path if it's not already in there. */
void addIfNotAlreadyThere (const File& directoryToAdd);
/** Removes a directory from the search path. */
void remove (int indexToRemove);
/** Merges another search path into this one.
This will remove any duplicate directories.
*/
void addPath (const FileSearchPath& other);
/** Removes any directories that are actually subdirectories of one of the other directories in the search path.
If the search is intended to be recursive, there's no point having nested folders in the search
path, because they'll just get searched twice and you'll get duplicate results.
e.g. if the path is "c:\abc\de;c:\abc", this method will simplify it to "c:\abc"
*/
void removeRedundantPaths();
/** Removes any directories that don't actually exist. */
void removeNonExistentPaths();
//==============================================================================
/** Searches the path for a wildcard.
This will search all the directories in the search path in order, adding any
matching files to the results array.
@param results an array to append the results to
@param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying whether to
return files, directories, or both.
@param searchRecursively whether to recursively search the subdirectories too
@param wildCardPattern a pattern to match against the filenames
@returns the number of files added to the array
@see File::findChildFiles
*/
int findChildFiles (Array<File>& results,
int whatToLookFor,
bool searchRecursively,
const String& wildCardPattern = "*") const;
//==============================================================================
/** Finds out whether a file is inside one of the path's directories.
This will return true if the specified file is a child of one of the
directories specified by this path. Note that this doesn't actually do any
searching or check that the files exist - it just looks at the pathnames
to work out whether the file would be inside a directory.
@param fileToCheck the file to look for
@param checkRecursively if true, then this will return true if the file is inside a
subfolder of one of the path's directories (at any depth). If false
it will only return true if the file is actually a direct child
of one of the directories.
@see File::isAChildOf
*/
bool isFileInPath (const File& fileToCheck,
bool checkRecursively) const;
private:
//==============================================================================
StringArray directories;
void init (const String& path);
};
} // beast
#endif // BEAST_FILESEARCHPATH_H_INCLUDED

View File

@@ -1,274 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/unit_test/suite.h>
namespace beast {
RandomAccessFile::RandomAccessFile () noexcept
: fileHandle (nullptr)
, currentPosition (0)
{
}
RandomAccessFile::~RandomAccessFile ()
{
close ();
}
Result RandomAccessFile::open (File const& path, Mode mode)
{
close ();
return nativeOpen (path, mode);
}
void RandomAccessFile::close ()
{
if (isOpen ())
{
nativeFlush ();
nativeClose ();
}
}
Result RandomAccessFile::setPosition (FileOffset newPosition)
{
if (newPosition != currentPosition)
{
// VFALCO NOTE I dislike return from the middle but
// Result::ok() is showing up in the profile
//
return nativeSetPosition (newPosition);
}
return Result::ok ();
}
Result RandomAccessFile::read (void* buffer, ByteCount numBytes, ByteCount* pActualAmount)
{
return nativeRead (buffer, numBytes, pActualAmount);
}
Result RandomAccessFile::write (const void* data, ByteCount numBytes, ByteCount* pActualAmount)
{
bassert (data != nullptr && ((std::ptrdiff_t) numBytes) >= 0);
Result result (Result::ok ());
ByteCount amountWritten = 0;
result = nativeWrite (data, numBytes, &amountWritten);
if (result.wasOk ())
currentPosition += amountWritten;
if (pActualAmount != nullptr)
*pActualAmount = amountWritten;
return result;
}
Result RandomAccessFile::truncate ()
{
Result result = flush ();
if (result.wasOk ())
result = nativeTruncate ();
return result;
}
Result RandomAccessFile::flush ()
{
return nativeFlush ();
}
//------------------------------------------------------------------------------
class RandomAccessFile_test : public unit_test::suite
{
public:
enum
{
maxPayload = 8192
};
/* For this test we will create a file which consists of a fixed
number of variable length records. Each record is numbered sequentially
starting at 0. To calculate the position of each record we first build
a table of size/offset pairs using a pseudorandom number generator.
*/
struct Record
{
int index;
int bytes;
int offset;
};
typedef HeapBlock <Record> Records;
// Produce the pseudo-random set of records.
static void createRecords (HeapBlock <Record>& records,
int numRecords,
int maxBytes,
std::int64_t seedValue)
{
using namespace UnitTestUtilities;
Random r (seedValue);
records.malloc (numRecords);
int offset = 0;
for (int i = 0; i < numRecords; ++i)
{
int const bytes = r.nextInt (maxBytes) + 1;
records [i].index = i;
records [i].bytes = bytes;
records [i].offset = offset;
offset += bytes;
}
repeatableShuffle (numRecords, records, seedValue);
}
// Write all the records to the file.
// The payload is pseudo-randomly generated.
void writeRecords (RandomAccessFile& file,
int numRecords,
HeapBlock <Record> const& records,
std::int64_t seedValue)
{
using namespace UnitTestUtilities;
for (int i = 0; i < numRecords; ++i)
{
Payload p (records [i].bytes);
p.repeatableRandomFill (records [i].bytes,
records [i].bytes,
records [i].index + seedValue);
file.setPosition (records [i].offset);
Result result = file.write (p.data.getData (), p.bytes);
expect (result.wasOk (), "Should be ok");
}
}
// Read the records and verify the consistency.
void readRecords (RandomAccessFile& file,
int numRecords,
HeapBlock <Record> const& records,
std::int64_t seedValue)
{
using namespace UnitTestUtilities;
for (int i = 0; i < numRecords; ++i)
{
Record const& record (records [i]);
int const bytes = record.bytes;
Payload p1 (bytes);
Payload p2 (bytes);
p1.repeatableRandomFill (bytes, bytes, record.index + seedValue);
file.setPosition (record.offset);
Result result = file.read (p2.data.getData (), bytes);
expect (result.wasOk (), "Should be ok");
if (result.wasOk ())
{
p2.bytes = bytes;
expect (p1 == p2, "Should be equal");
}
}
}
// Perform the test at the given buffer size.
void testFile (int const numRecords)
{
using namespace UnitTestUtilities;
int const seedValue = 50;
std::stringstream ss;
ss << numRecords << " records";
testcase (ss.str());
// Calculate the path
File const path (File::createTempFile ("RandomAccessFile"));
// Create a predictable set of records
HeapBlock <Record> records (numRecords);
createRecords (records, numRecords, maxPayload, seedValue);
Result result (Result::ok ());
{
// Create the file
RandomAccessFile file;
result = file.open (path, RandomAccessFile::readWrite);
expect (result.wasOk (), "Should be ok");
if (result.wasOk ())
{
writeRecords (file, numRecords, records, seedValue);
readRecords (file, numRecords, records, seedValue);
repeatableShuffle (numRecords, records, seedValue);
readRecords (file, numRecords, records, seedValue);
}
}
if (result.wasOk ())
{
// Re-open the file in read only mode
RandomAccessFile file;
result = file.open (path, RandomAccessFile::readOnly);
expect (result.wasOk (), "Should be ok");
if (result.wasOk ())
{
readRecords (file, numRecords, records, seedValue);
}
}
}
void run ()
{
testFile (10000);
}
};
BEAST_DEFINE_TESTSUITE(RandomAccessFile,beast_core,beast);
} // beast

View File

@@ -1,203 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_RANDOMACCESSFILE_H_INCLUDED
#define BEAST_RANDOMACCESSFILE_H_INCLUDED
namespace beast
{
/** Provides random access reading and writing to an operating system file.
This class wraps the underlying native operating system routines for
opening and closing a file for reading and/or writing, seeking within
the file, and performing read and write operations. There are also methods
provided for obtaining an input or output stream which will work with
the file.
@note All files are opened in binary mode. No text newline conversions
are performed.
@note None of these members are thread safe. The caller is responsible
for synchronization.
@see FileInputStream, FileOutputStream
*/
class RandomAccessFile : LeakChecked <RandomAccessFile>
{
public:
/** The type of an FileOffset.
This can be useful when writing templates.
*/
typedef std::int64_t FileOffset;
/** The type of a byte count.
This can be useful when writing templates.
*/
typedef size_t ByteCount;
/** The access mode.
@see open
*/
enum Mode
{
readOnly,
readWrite
};
//==============================================================================
/** Creates an unopened file object.
@see open, isOpen
*/
RandomAccessFile () noexcept;
RandomAccessFile(RandomAccessFile const&) = delete;
RandomAccessFile& operator= (RandomAccessFile const&) = delete;
/** Destroy the file object.
If the operating system file is open it will be closed.
*/
~RandomAccessFile ();
/** Determine if a file is open.
@return `true` if the operating system file is open.
*/
bool isOpen () const noexcept { return fileHandle != nullptr; }
/** Opens a file object.
The file is opened with the specified permissions. The initial
position is set to the beginning of the file.
@note If a file is already open, it will be closed first.
@param path The path to the file
@param mode The access permissions
@return An indication of the success of the operation.
@see Mode
*/
Result open (File const& path, Mode mode);
/** Closes the file object.
Any data that needs to be flushed will be written before the file is closed.
@note If no file is opened, this call does nothing.
*/
void close ();
/** Retrieve the @ref File associated with this object.
@return The associated @ref File.
*/
File const& getFile () const noexcept { return file; }
/** Get the current position.
The next read or write will take place from here.
@return The current position, as an absolute byte FileOffset from the begining.
*/
FileOffset getPosition () const noexcept { return currentPosition; }
/** Set the current position.
The next read or write will take place at this location.
@param newPosition The byte FileOffset from the beginning of the file to move to.
@return `true` if the operation was successful.
*/
Result setPosition (FileOffset newPosition);
/** Read data at the current position.
The caller is responsible for making sure that the memory pointed to
by `buffer` is at least as large as `bytesToRead`.
@note The file must have been opened with read permission.
@param buffer The memory to store the incoming data
@param numBytes The number of bytes to read.
@param pActualAmount Pointer to store the actual amount read, or `nullptr`.
@return `true` if all the bytes were read.
*/
Result read (void* buffer, ByteCount numBytes, ByteCount* pActualAmount = 0);
/** Write data at the current position.
The current position is advanced past the data written. If data is
written past the end of the file, the file size is increased on disk.
The caller is responsible for making sure that the memory pointed to
by `buffer` is at least as large as `bytesToWrite`.
@note The file must have been opened with write permission.
@param data A pointer to the data buffer to write to the file.
@param numBytes The number of bytes to write.
@param pActualAmount Pointer to store the actual amount written, or `nullptr`.
@return `true` if all the data was written.
*/
Result write (const void* data, ByteCount numBytes, ByteCount* pActualAmount = 0);
/** Truncate the file at the current position.
*/
Result truncate ();
/** Flush the output buffers.
This calls the operating system to make sure all data has been written.
*/
Result flush();
//==============================================================================
private:
// Some of these these methods are implemented natively on
// the corresponding platform.
//
// See beast_posix_SharedCode.h and beast_win32_Files.cpp
//
Result nativeOpen (File const& path, Mode mode);
void nativeClose ();
Result nativeSetPosition (FileOffset newPosition);
Result nativeRead (void* buffer, ByteCount numBytes, ByteCount* pActualAmount = 0);
Result nativeWrite (const void* data, ByteCount numBytes, ByteCount* pActualAmount = 0);
Result nativeTruncate ();
Result nativeFlush ();
private:
File file;
void* fileHandle;
FileOffset currentPosition;
};
} // beast
#endif

View File

@@ -1,117 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace beast
{
static File createTempFile (const File& parentDirectory, String name,
const String& suffix, const int optionFlags)
{
if ((optionFlags & TemporaryFile::useHiddenFile) != 0)
name = "." + name;
return parentDirectory.getNonexistentChildFile (name, suffix, (optionFlags & TemporaryFile::putNumbersInBrackets) != 0);
}
TemporaryFile::TemporaryFile (const String& suffix, const int optionFlags)
: temporaryFile (createTempFile (File::getSpecialLocation (File::tempDirectory),
"temp_" + String::toHexString (Random::getSystemRandom().nextInt()),
suffix, optionFlags))
{
}
TemporaryFile::TemporaryFile (const File& target, const int optionFlags)
: temporaryFile (createTempFile (target.getParentDirectory(),
target.getFileNameWithoutExtension()
+ "_temp" + String::toHexString (Random::getSystemRandom().nextInt()),
target.getFileExtension(), optionFlags)),
targetFile (target)
{
// If you use this constructor, you need to give it a valid target file!
bassert (targetFile != File::nonexistent ());
}
TemporaryFile::TemporaryFile (const File& target, const File& temporary)
: temporaryFile (temporary), targetFile (target)
{
}
TemporaryFile::~TemporaryFile()
{
if (! deleteTemporaryFile())
{
/* Failed to delete our temporary file! The most likely reason for this would be
that you've not closed an output stream that was being used to write to file.
If you find that something beyond your control is changing permissions on
your temporary files and preventing them from being deleted, you may want to
call TemporaryFile::deleteTemporaryFile() to detect those error cases and
handle them appropriately.
*/
bassertfalse;
}
}
//==============================================================================
bool TemporaryFile::overwriteTargetFileWithTemporary() const
{
// This method only works if you created this object with the constructor
// that takes a target file!
bassert (targetFile != File::nonexistent ());
if (temporaryFile.exists())
{
// Have a few attempts at overwriting the file before giving up..
for (int i = 5; --i >= 0;)
{
if (temporaryFile.moveFileTo (targetFile))
return true;
Thread::sleep (100);
}
}
else
{
// There's no temporary file to use. If your write failed, you should
// probably check, and not bother calling this method.
bassertfalse;
}
return false;
}
bool TemporaryFile::deleteTemporaryFile() const
{
// Have a few attempts at deleting the file before giving up..
for (int i = 5; --i >= 0;)
{
if (temporaryFile.deleteFile())
return true;
Thread::sleep (50);
}
return false;
}
} // beast

View File

@@ -1,169 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TEMPORARYFILE_H_INCLUDED
#define BEAST_TEMPORARYFILE_H_INCLUDED
namespace beast
{
//==============================================================================
/**
Manages a temporary file, which will be deleted when this object is deleted.
This object is intended to be used as a stack based object, using its scope
to make sure the temporary file isn't left lying around.
For example:
@code
{
File myTargetFile ("~/myfile.txt");
// this will choose a file called something like "~/myfile_temp239348.txt"
// which definitely doesn't exist at the time the constructor is called.
TemporaryFile temp (myTargetFile);
// create a stream to the temporary file, and write some data to it...
std::unique_ptr <FileOutputStream> out (temp.getFile().createOutputStream());
if (out != nullptr)
{
out->write ( ...etc )
out = nullptr; // (deletes the stream)
// ..now we've finished writing, this will rename the temp file to
// make it replace the target file we specified above.
bool succeeded = temp.overwriteTargetFileWithTemporary();
}
// ..and even if something went wrong and our overwrite failed,
// as the TemporaryFile object goes out of scope here, it'll make sure
// that the temp file gets deleted.
}
@endcode
@see File, FileOutputStream
*/
class TemporaryFile : LeakChecked <TemporaryFile>
{
public:
//==============================================================================
enum OptionFlags
{
useHiddenFile = 1, /**< Indicates that the temporary file should be hidden -
i.e. its name should start with a dot. */
putNumbersInBrackets = 2 /**< Indicates that when numbers are appended to make sure
the file is unique, they should go in brackets rather
than just being appended (see File::getNonexistentSibling() )*/
};
//==============================================================================
/** Creates a randomly-named temporary file in the default temp directory.
@param suffix a file suffix to use for the file
@param optionFlags a combination of the values listed in the OptionFlags enum
The file will not be created until you write to it. And remember that when
this object is deleted, the file will also be deleted!
*/
TemporaryFile (const String& suffix = String::empty,
int optionFlags = 0);
/** Creates a temporary file in the same directory as a specified file.
This is useful if you have a file that you want to overwrite, but don't
want to harm the original file if the write operation fails. You can
use this to create a temporary file next to the target file, then
write to the temporary file, and finally use overwriteTargetFileWithTemporary()
to replace the target file with the one you've just written.
This class won't create any files until you actually write to them. And remember
that when this object is deleted, the temporary file will also be deleted!
@param targetFile the file that you intend to overwrite - the temporary
file will be created in the same directory as this
@param optionFlags a combination of the values listed in the OptionFlags enum
*/
TemporaryFile (const File& targetFile,
int optionFlags = 0);
/** Creates a temporary file using an explicit filename.
The other constructors are a better choice than this one, unless for some reason
you need to explicitly specify the temporary file you want to use.
@param targetFile the file that you intend to overwrite
@param temporaryFile the temporary file to be used
*/
TemporaryFile (const File& targetFile,
const File& temporaryFile);
TemporaryFile(TemporaryFile const&) = delete;
TemporaryFile& operator= (TemporaryFile const&) = delete;
/** Destructor.
When this object is deleted it will make sure that its temporary file is
also deleted! If the operation fails, it'll throw an assertion in debug
mode.
*/
~TemporaryFile();
//==============================================================================
/** Returns the temporary file. */
const File& getFile() const noexcept { return temporaryFile; }
/** Returns the target file that was specified in the constructor. */
const File& getTargetFile() const noexcept { return targetFile; }
/** Tries to move the temporary file to overwrite the target file that was
specified in the constructor.
If you used the constructor that specified a target file, this will attempt
to replace that file with the temporary one.
Before calling this, make sure:
- that you've actually written to the temporary file
- that you've closed any open streams that you were using to write to it
- and that you don't have any streams open to the target file, which would
prevent it being overwritten
If the file move succeeds, this returns false, and the temporary file will
have disappeared. If it fails, the temporary file will probably still exist,
but will be deleted when this object is destroyed.
*/
bool overwriteTargetFileWithTemporary() const;
/** Attempts to delete the temporary file, if it exists.
@returns true if the file is successfully deleted (or if it didn't exist).
*/
bool deleteTemporaryFile() const;
private:
//==============================================================================
const File temporaryFile, targetFile;
};
} // beast
#endif // BEAST_TEMPORARYFILE_H_INCLUDED

View File

@@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace beast
{
Logger::Logger() {}
Logger::~Logger()
{
// You're deleting this logger while it's still being used!
// Always call Logger::setCurrentLogger (nullptr) before deleting the active logger.
bassert (currentLogger != this);
}
Logger* Logger::currentLogger = nullptr;
void Logger::setCurrentLogger (Logger* const newLogger) noexcept { currentLogger = newLogger; }
Logger* Logger::getCurrentLogger() noexcept { return currentLogger; }
void Logger::writeToLog (const String& message)
{
if (currentLogger != nullptr)
currentLogger->logMessage (message);
else
outputDebugString (message);
}
#if BEAST_LOG_ASSERTIONS || BEAST_DEBUG
void logAssertion (const char* const filename, const int lineNum)
{
String m ("BEAST Assertion failure in ");
m << File::createFileWithoutCheckingPath (filename).getFileName() << ':' << lineNum;
#if BEAST_LOG_ASSERTIONS
Logger::writeToLog (m);
#else
BDBG (m);
#endif
}
#endif
} // beast

View File

@@ -29,66 +29,7 @@
namespace beast namespace beast
{ {
//============================================================================== void outputDebugString (std::string const& text);
/**
Acts as an application-wide logging class.
A subclass of Logger can be created and passed into the Logger::setCurrentLogger
method and this will then be used by all calls to writeToLog.
The logger class also contains methods for writing messages to the debugger's
output stream.
*/
class Logger
{
public:
//==============================================================================
/** Destructor. */
virtual ~Logger();
//==============================================================================
/** Sets the current logging class to use.
Note that the object passed in will not be owned or deleted by the logger, so
the caller must make sure that it is not deleted while still being used.
A null pointer can be passed-in to disable any logging.
*/
static void setCurrentLogger (Logger* newLogger) noexcept;
/** Returns the current logger, or nullptr if none has been set. */
static Logger* getCurrentLogger() noexcept;
/** Writes a string to the current logger.
This will pass the string to the logger's logMessage() method if a logger
has been set.
@see logMessage
*/
static void writeToLog (const String& message);
//==============================================================================
/** Writes a message to the standard error stream.
This can be called directly, or by using the DBG() macro in
CompilerConfig.h (which will avoid calling the method in non-debug builds).
*/
static void outputDebugString (const String& text);
protected:
//==============================================================================
Logger();
/** This is overloaded by subclasses to implement custom logging behaviour.
@see setCurrentLogger
*/
virtual void logMessage (const String& message) = 0;
private:
static Logger* currentLogger;
};
} // beast } // beast

View File

@@ -1,89 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_MATH_H_INCLUDED
#define BEAST_MATH_H_INCLUDED
namespace beast
{
//
// Miscellaneous mathematical calculations
//
// Calculate the bin for a value given the bin size.
// This correctly handles negative numbers. For example
// if value == -1 then calc_bin returns -1.
template <typename Ty>
inline Ty calc_bin (Ty value, int size)
{
if (value >= 0)
return value / size;
else
return (value - size + 1) / size;
}
// Given a number and a bin size, this returns the first
// corresponding value of the bin associated with the given number.
// It correctly handles negative numbers. For example,
// if value == -1 then calc_bin always returns -size
template <typename Ty>
inline Ty calc_bin_start (Ty value, int size)
{
return calc_bin (value, size) * size;
}
template <class T>
inline T pi () noexcept
{
return 3.14159265358979;
}
template <class T>
inline T twoPi () noexcept
{
return 6.28318530717958;
}
template <class T>
inline T oneOverTwoPi () noexcept
{
return 0.1591549430918955;
}
template <class T, class U>
inline T degreesToRadians (U degrees)
{
return T (degrees * 0.0174532925199433);
}
template <class T, class U>
inline T radiansToDegrees (U radians)
{
T deg = T (radians * U (57.29577951308238));
if (deg < 0)
deg += 360;
return deg;
}
} // beast
#endif

View File

@@ -1,263 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_RANGE_H_INCLUDED
#define BEAST_RANGE_H_INCLUDED
namespace beast
{
//==============================================================================
/** A general-purpose range object, that simply represents any linear range with
a start and end point.
The templated parameter is expected to be a primitive integer or floating point
type, though class types could also be used if they behave in a number-like way.
*/
template <typename ValueType>
class Range
{
public:
//==============================================================================
/** Constructs an empty range. */
Range() noexcept : start(), end()
{
}
/** Constructs a range with given start and end values. */
Range (const ValueType startValue, const ValueType endValue) noexcept
: start (startValue), end (bmax (startValue, endValue))
{
}
/** Constructs a copy of another range. */
Range (const Range& other) noexcept
: start (other.start), end (other.end)
{
}
/** Copies another range object. */
Range& operator= (Range other) noexcept
{
start = other.start;
end = other.end;
return *this;
}
/** Returns the range that lies between two positions (in either order). */
static Range between (const ValueType position1, const ValueType position2) noexcept
{
return position1 < position2 ? Range (position1, position2)
: Range (position2, position1);
}
/** Returns a range with the specified start position and a length of zero. */
static Range emptyRange (const ValueType start) noexcept
{
return Range (start, start);
}
//==============================================================================
/** Returns the start of the range. */
inline ValueType getStart() const noexcept { return start; }
/** Returns the length of the range. */
inline ValueType getLength() const noexcept { return end - start; }
/** Returns the end of the range. */
inline ValueType getEnd() const noexcept { return end; }
/** Returns true if the range has a length of zero. */
inline bool isEmpty() const noexcept { return start == end; }
//==============================================================================
/** Changes the start position of the range, leaving the end position unchanged.
If the new start position is higher than the current end of the range, the end point
will be pushed along to equal it, leaving an empty range at the new position.
*/
void setStart (const ValueType newStart) noexcept
{
start = newStart;
if (end < newStart)
end = newStart;
}
/** Returns a range with the same end as this one, but a different start.
If the new start position is higher than the current end of the range, the end point
will be pushed along to equal it, returning an empty range at the new position.
*/
Range withStart (const ValueType newStart) const noexcept
{
return Range (newStart, bmax (newStart, end));
}
/** Returns a range with the same length as this one, but moved to have the given start position. */
Range movedToStartAt (const ValueType newStart) const noexcept
{
return Range (newStart, end + (newStart - start));
}
/** Changes the end position of the range, leaving the start unchanged.
If the new end position is below the current start of the range, the start point
will be pushed back to equal the new end point.
*/
void setEnd (const ValueType newEnd) noexcept
{
end = newEnd;
if (newEnd < start)
start = newEnd;
}
/** Returns a range with the same start position as this one, but a different end.
If the new end position is below the current start of the range, the start point
will be pushed back to equal the new end point.
*/
Range withEnd (const ValueType newEnd) const noexcept
{
return Range (bmin (start, newEnd), newEnd);
}
/** Returns a range with the same length as this one, but moved to have the given end position. */
Range movedToEndAt (const ValueType newEnd) const noexcept
{
return Range (start + (newEnd - end), newEnd);
}
/** Changes the length of the range.
Lengths less than zero are treated as zero.
*/
void setLength (const ValueType newLength) noexcept
{
end = start + bmax (ValueType(), newLength);
}
/** Returns a range with the same start as this one, but a different length.
Lengths less than zero are treated as zero.
*/
Range withLength (const ValueType newLength) const noexcept
{
return Range (start, start + newLength);
}
//==============================================================================
/** Adds an amount to the start and end of the range. */
inline Range operator+= (const ValueType amountToAdd) noexcept
{
start += amountToAdd;
end += amountToAdd;
return *this;
}
/** Subtracts an amount from the start and end of the range. */
inline Range operator-= (const ValueType amountToSubtract) noexcept
{
start -= amountToSubtract;
end -= amountToSubtract;
return *this;
}
/** Returns a range that is equal to this one with an amount added to its
start and end.
*/
Range operator+ (const ValueType amountToAdd) const noexcept
{
return Range (start + amountToAdd, end + amountToAdd);
}
/** Returns a range that is equal to this one with the specified amount
subtracted from its start and end. */
Range operator- (const ValueType amountToSubtract) const noexcept
{
return Range (start - amountToSubtract, end - amountToSubtract);
}
bool operator== (Range other) const noexcept { return start == other.start && end == other.end; }
bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; }
//==============================================================================
/** Returns true if the given position lies inside this range. */
bool contains (const ValueType position) const noexcept
{
return start <= position && position < end;
}
/** Returns the nearest value to the one supplied, which lies within the range. */
ValueType clipValue (const ValueType value) const noexcept
{
return blimit (start, end, value);
}
/** Returns true if the given range lies entirely inside this range. */
bool contains (Range other) const noexcept
{
return start <= other.start && end >= other.end;
}
/** Returns true if the given range intersects this one. */
bool intersects (Range other) const noexcept
{
return other.start < end && start < other.end;
}
/** Returns the range that is the intersection of the two ranges, or an empty range
with an undefined start position if they don't overlap. */
Range getIntersectionWith (Range other) const noexcept
{
return Range (bmax (start, other.start),
bmin (end, other.end));
}
/** Returns the smallest range that contains both this one and the other one. */
Range getUnionWith (Range other) const noexcept
{
return Range (bmin (start, other.start),
bmax (end, other.end));
}
/** Returns a given range, after moving it forwards or backwards to fit it
within this range.
If the supplied range has a greater length than this one, the return value
will be this range.
Otherwise, if the supplied range is smaller than this one, the return value
will be the new range, shifted forwards or backwards so that it doesn't extend
beyond this one, but keeping its original length.
*/
Range constrainRange (Range rangeToConstrain) const noexcept
{
const ValueType otherLen = rangeToConstrain.getLength();
return getLength() <= otherLen
? *this
: rangeToConstrain.movedToStartAt (blimit (start, end - otherLen, rangeToConstrain.getStart()));
}
private:
//==============================================================================
ValueType start, end;
};
} // beast
#endif // BEAST_RANGE_H_INCLUDED

View File

@@ -21,6 +21,8 @@
*/ */
//============================================================================== //==============================================================================
#include <algorithm>
namespace beast namespace beast
{ {
@@ -191,7 +193,7 @@ void MemoryBlock::insert (const void* const srcData, const size_t numBytes, size
if (numBytes > 0) if (numBytes > 0)
{ {
bassert (srcData != nullptr); // this must not be null! bassert (srcData != nullptr); // this must not be null!
insertPosition = bmin (size, insertPosition); insertPosition = std::min (size, insertPosition);
const size_t trailingDataSize = size - insertPosition; const size_t trailingDataSize = size - insertPosition;
setSize (size + numBytes, false); setSize (size + numBytes, false);
@@ -277,7 +279,7 @@ int MemoryBlock::getBitRange (const size_t bitRangeStart, size_t numBits) const
while (numBits > 0 && (size_t) byte < size) while (numBits > 0 && (size_t) byte < size)
{ {
const size_t bitsThisTime = bmin (numBits, 8 - offsetInByte); const size_t bitsThisTime = std::min (numBits, 8 - offsetInByte);
const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte; const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;
res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar); res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);
@@ -299,7 +301,7 @@ void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int b
while (numBits > 0 && (size_t) byte < size) while (numBits > 0 && (size_t) byte < size)
{ {
const size_t bitsThisTime = bmin (numBits, 8 - offsetInByte); const size_t bitsThisTime = std::min (numBits, 8 - offsetInByte);
const std::uint32_t tempMask = (mask << offsetInByte) | ~((((std::uint32_t) 0xffffffff) >> offsetInByte) << offsetInByte); const std::uint32_t tempMask = (mask << offsetInByte) | ~((((std::uint32_t) 0xffffffff) >> offsetInByte) << offsetInByte);
const std::uint32_t tempBits = (std::uint32_t) bitsToSet << offsetInByte; const std::uint32_t tempBits = (std::uint32_t) bitsToSet << offsetInByte;

View File

@@ -1,120 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_WINDOWSREGISTRY_H_INCLUDED
#define BEAST_WINDOWSREGISTRY_H_INCLUDED
namespace beast
{
#if BEAST_WINDOWS || DOXYGEN
/**
Contains some static helper functions for manipulating the MS Windows registry
(Only available on Windows, of course!)
*/
namespace WindowsRegistry
{
//==============================================================================
/** Returns a string from the registry.
The path is a string for the entire path of a value in the registry,
e.g. "HKEY_CURRENT_USER\Software\foo\bar"
*/
String getValue (const String& regValuePath,
const String& defaultValue = String::empty);
/** Returns a string from the WOW64 registry.
The path is a string for the entire path of a value in the registry,
e.g. "HKEY_CURRENT_USER\Software\foo\bar"
*/
String getValueWow64 (const String& regValuePath,
const String& defaultValue = String::empty);
/** Reads a binary block from the registry.
The path is a string for the entire path of a value in the registry,
e.g. "HKEY_CURRENT_USER\Software\foo\bar"
@returns a DWORD indicating the type of the key.
*/
std::uint32_t getBinaryValue (const String& regValuePath, MemoryBlock& resultData);
/** Sets a registry value as a string.
This will take care of creating any groups needed to get to the given registry value.
*/
bool setValue (const String& regValuePath, const String& value);
/** Sets a registry value as a DWORD.
This will take care of creating any groups needed to get to the given registry value.
*/
bool setValue (const String& regValuePath, std::uint32_t value);
/** Sets a registry value as a QWORD.
This will take care of creating any groups needed to get to the given registry value.
*/
bool setValue (const String& regValuePath, std::uint64_t value);
/** Sets a registry value as a binary block.
This will take care of creating any groups needed to get to the given registry value.
*/
bool setValue (const String& regValuePath, const MemoryBlock& value);
/** Returns true if the given value exists in the registry. */
bool valueExists (const String& regValuePath);
/** Returns true if the given value exists in the registry. */
bool valueExistsWow64 (const String& regValuePath);
/** Deletes a registry value. */
void deleteValue (const String& regValuePath);
/** Deletes a registry key (which is registry-talk for 'folder'). */
void deleteKey (const String& regKeyPath);
/** Creates a file association in the registry.
This lets you set the executable that should be launched by a given file extension.
@param fileExtension the file extension to associate, including the
initial dot, e.g. ".txt"
@param symbolicDescription a space-free short token to identify the file type
@param fullDescription a human-readable description of the file type
@param targetExecutable the executable that should be launched
@param iconResourceNumber the icon that gets displayed for the file type will be
found by looking up this resource number in the
executable. Pass 0 here to not use an icon
@param registerForCurrentUserOnly if false, this will try to register the association
for all users (you might not have permission to do this
unless running in an installer). If true, it will register the
association in HKEY_CURRENT_USER.
*/
bool registerFileAssociation (const String& fileExtension,
const String& symbolicDescription,
const String& fullDescription,
const File& targetExecutable,
int iconResourceNumber,
bool registerForCurrentUserOnly);
};
#endif
} // beast
#endif // BEAST_WINDOWSREGISTRY_H_INCLUDED

View File

@@ -149,18 +149,6 @@
#endif #endif
#endif #endif
/* Used with DynamicLibrary to simplify importing functions from a win32 DLL.
dll: the DynamicLibrary object
functionName: function to import
localFunctionName: name you want to use to actually call it (must be different)
returnType: the return type
params: list of params (bracketed)
*/
#define BEAST_LOAD_WINAPI_FUNCTION(dll, functionName, localFunctionName, returnType, params) \
typedef returnType (WINAPI *type##localFunctionName) params; \
type##localFunctionName localFunctionName = (type##localFunctionName) dll.getFunction (#functionName);
//============================================================================== //==============================================================================
#elif BEAST_LINUX || BEAST_BSD #elif BEAST_LINUX || BEAST_BSD
#include <sched.h> #include <sched.h>

View File

@@ -55,85 +55,19 @@ bool File::copyInternal (const File& dest) const
return false; return false;
} }
void File::findFileSystemRoots (Array<File>& destArray)
{
destArray.add (File ("/"));
}
//==============================================================================
bool File::isOnCDRomDrive() const
{
struct statfs buf;
return statfs (getFullPathName().toUTF8(), &buf) == 0
&& buf.f_type == (short) U_ISOFS_SUPER_MAGIC;
}
bool File::isOnHardDisk() const
{
struct statfs buf;
if (statfs (getFullPathName().toUTF8(), &buf) == 0)
{
switch (buf.f_type)
{
case U_ISOFS_SUPER_MAGIC: // CD-ROM
case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
case U_NFS_SUPER_MAGIC: // Network NFS
case U_SMB_SUPER_MAGIC: // Network Samba
return false;
default:
// Assume anything else is a hard-disk (but note it could
// be a RAM disk. There isn't a good way of determining
// this for sure)
return true;
}
}
// Assume so if this fails for some reason
return true;
}
bool File::isOnRemovableDrive() const
{
bassertfalse; // XXX not implemented for FreeBSD!
return false;
}
bool File::isHidden() const
{
return getFileName().startsWithChar ('.');
}
//==============================================================================
namespace
{
File beast_readlink (const String& file, const File& defaultFile)
{
const size_t size = 8192;
HeapBlock<char> buffer;
buffer.malloc (size + 4);
const size_t numBytes = readlink (file.toUTF8(), buffer, size);
if (numBytes > 0 && numBytes <= size)
return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes));
return defaultFile;
}
}
File File::getLinkedTarget() const
{
return beast_readlink (getFullPathName().toUTF8(), *this);
}
//============================================================================== //==============================================================================
static File resolveXDGFolder (const char* const type, const char* const fallbackFolder) static File resolveXDGFolder (const char* const type, const char* const fallbackFolder)
{ {
File userDirs ("~/.config/user-dirs.dirs");
StringArray confLines; StringArray confLines;
File ("~/.config/user-dirs.dirs").readLines (confLines);
if (userDirs.existsAsFile())
{
FileInputStream in (userDirs);
if (in.openedOk())
confLines.addLines (in.readEntireStreamAsString());
}
for (int i = 0; i < confLines.size(); ++i) for (int i = 0; i < confLines.size(); ++i)
{ {
@@ -199,18 +133,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return tmp; return tmp;
} }
case invokedExecutableFile:
if (beast_argv != nullptr && beast_argc > 0)
return File (CharPointer_UTF8 (beast_argv[0]));
// deliberate fall-through...
case currentExecutableFile:
case currentApplicationFile:
return beast_getExecutableFile();
case hostApplicationPath:
return beast_readlink ("/proc/self/exe", beast_getExecutableFile());
default: default:
bassertfalse; // unknown type? bassertfalse; // unknown type?
break; break;
@@ -219,30 +141,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File::nonexistent (); return File::nonexistent ();
} }
//==============================================================================
String File::getVersion() const
{
return String::empty; // xxx not yet implemented
}
//==============================================================================
bool File::moveToTrash() const
{
if (! exists())
return true;
File trashCan ("~/.Trash");
if (! trashCan.isDirectory())
trashCan = "~/.local/share/Trash/files";
if (! trashCan.isDirectory())
return false;
return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
getFileExtension()));
}
//============================================================================== //==============================================================================
class DirectoryIterator::NativeIterator::Pimpl class DirectoryIterator::NativeIterator::Pimpl
{ {
@@ -319,59 +217,4 @@ bool DirectoryIterator::NativeIterator::next (String& filenameFound,
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
} }
//==============================================================================
static bool isFileExecutable (const String& filename)
{
beast_statStruct info;
return beast_stat (filename, info)
&& S_ISREG (info.st_mode)
&& access (filename.toUTF8(), X_OK) == 0;
}
bool Process::openDocument (const String& fileName, const String& parameters)
{
String cmdString (fileName.replace (" ", "\\ ",false));
cmdString << " " << parameters;
if ( cmdString.startsWithIgnoreCase ("file:")
|| File::createFileWithoutCheckingPath (fileName).isDirectory()
|| ! isFileExecutable (fileName))
{
// create a command that tries to launch a bunch of likely browsers
const char* const browserNames[] = { "xdg-open", "firefox", "seamonkey",
"chrome", "opera", "konqueror" };
StringArray cmdLines;
for (int i = 0; i < numElementsInArray (browserNames); ++i)
cmdLines.add (String (browserNames[i]) + " " + cmdString.trim().quoted());
cmdString = cmdLines.joinIntoString (" || ");
}
const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 };
const int cpid = fork();
if (cpid == 0)
{
setsid();
// Child process
execve (argv[0], (char**) argv, environ);
exit (0);
}
return cpid >= 0;
}
void File::revealToUser() const
{
if (isDirectory())
startAsProcess();
else if (getParentDirectory().exists())
getParentDirectory().startAsProcess();
}
} // beast } // beast

View File

@@ -19,277 +19,22 @@
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//==============================================================================
// sysinfo() from sysinfo-bsd
// https://code.google.com/p/sysinfo-bsd/
/*
* Copyright (C) 2010 Kostas Petrikas, All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name(s) of the author(s) may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace beast
{
#define SI_LOAD_SHIFT 16
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned short pad; /* leaving this for linux compatability */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* leaving this for linux compatability */
};
#define NLOADS 3
#define UNIT_S 1024 /*Kb*/
#define R_IGNORE -1
/*the macros*/
#define R_ERROR(_EC) {if(_EC > R_IGNORE)errno = _EC; return -1;}
#define GETSYSCTL(name, var) getsysctl((char*)name, &(var), sizeof(var))
#define PAGE_2_UNIT(_PAGE) (((double)_PAGE * page_s) / UNIT_S)
/*sysctl wrapper*/
static int getsysctl(char *name, void *ptr, size_t len){
size_t nlen = len;
if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)
return -1;
if (nlen != len)
return -1;
return 0;
}
int sysinfo(struct sysinfo *info){
kvm_t *kvmh;
double load_avg[NLOADS];
int page_s = getpagesize();
if (info == NULL)
R_ERROR(EFAULT);
memset(info, 0, sizeof(struct sysinfo));
info -> mem_unit = UNIT_S;
/*kvm init*/
if ((kvmh = kvm_open(NULL, "/dev/null", "/dev/null",
O_RDONLY, "kvm_open")) == NULL)
R_ERROR(0);
/*load averages*/
if (kvm_getloadavg(kvmh, load_avg, NLOADS) == -1)
R_ERROR(0);
info -> loads[0] = (u_long)((float)load_avg[0] * USHRT_MAX);
info -> loads[1] = (u_long)((float)load_avg[1] * USHRT_MAX);
info -> loads[2] = (u_long)((float)load_avg[2] * USHRT_MAX);
/*swap space*/
struct kvm_swap k_swap;
if (kvm_getswapinfo(kvmh, &k_swap, 1, 0) == -1)
R_ERROR(0);
info -> totalswap =
(u_long)PAGE_2_UNIT(k_swap.ksw_total);
info -> freeswap = info -> totalswap -
(u_long)PAGE_2_UNIT(k_swap.ksw_used);
/*processes*/
int n_procs;
if (kvm_getprocs(kvmh, KERN_PROC_ALL, 0, &n_procs) == NULL)
R_ERROR(0);
info -> procs = (u_short)n_procs;
/*end of kvm session*/
if (kvm_close(kvmh) == -1)
R_ERROR(0);
/*uptime*/
struct timespec ts;
if (clock_gettime(CLOCK_UPTIME, &ts) == -1)
R_ERROR(R_IGNORE);
info -> uptime = (long)ts.tv_sec;
/*ram*/
int total_pages,
free_pages,
active_pages,
inactive_pages;
u_long shmmax;
if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages) == -1)
R_ERROR(R_IGNORE);
if (GETSYSCTL("vm.stats.vm.v_free_count", free_pages) == -1)
R_ERROR(R_IGNORE);
if (GETSYSCTL("vm.stats.vm.v_active_count", active_pages) == -1)
R_ERROR(R_IGNORE);
if (GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_pages) == -1)
R_ERROR(R_IGNORE);
if (GETSYSCTL("kern.ipc.shmmax", shmmax) == -1)
R_ERROR(R_IGNORE);
info -> totalram = (u_long)PAGE_2_UNIT(total_pages);
info -> freeram = (u_long)PAGE_2_UNIT(free_pages);
info -> bufferram = (u_long)PAGE_2_UNIT(active_pages);
info -> sharedram = shmmax / UNIT_S;
/*high mem (todo)*/
info -> totalhigh = 0; /*Does this supose to refer to HMA or reserved ram?*/
info -> freehigh = 0;
return 0;
}
//============================================================================== //==============================================================================
void Logger::outputDebugString (const String& text) void outputDebugString (std::string const& text)
{ {
std::cerr << text << std::endl; std::cerr << text << std::endl;
} }
//============================================================================== //==============================================================================
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() std::string SystemStats::getComputerName()
{
return FreeBSD;
}
String SystemStats::getOperatingSystemName()
{
return "FreeBSD";
}
bool SystemStats::isOperatingSystem64Bit()
{
#if BEAST_64BIT
return true;
#else
//xxx not sure how to find this out?..
return false;
#endif
}
//==============================================================================
namespace BSDStatsHelpers
{
String getDmesgInfo (const char* const key)
{
StringArray lines;
File ("/var/run/dmesg.boot").readLines (lines);
for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order)
if (lines[i].startsWith (key))
return lines[i].substring (strlen (key)).trim();
return String::empty;
}
}
String SystemStats::getCpuVendor()
{
return BSDStatsHelpers::getDmesgInfo (" Origin =").upToFirstOccurrenceOf (" ", false, false).unquoted();
}
int SystemStats::getCpuSpeedInMegaherz()
{
return roundToInt (BSDStatsHelpers::getDmesgInfo ("CPU:").fromLastOccurrenceOf ("(", false, false).upToFirstOccurrenceOf ("-MHz", false, false).getFloatValue());
}
int SystemStats::getMemorySizeInMegabytes()
{
struct sysinfo sysi;
if (sysinfo (&sysi) == 0)
return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
return 0;
}
int SystemStats::getPageSize()
{
return sysconf (_SC_PAGESIZE);
}
//==============================================================================
String SystemStats::getLogonName()
{
const char* user = getenv ("USER");
if (user == nullptr)
{
struct passwd* const pw = getpwuid (getuid());
if (pw != nullptr)
user = pw->pw_name;
}
return CharPointer_UTF8 (user);
}
String SystemStats::getFullUserName()
{
return getLogonName();
}
String SystemStats::getComputerName()
{ {
char name [256] = { 0 }; char name [256] = { 0 };
if (gethostname (name, sizeof (name) - 1) == 0) if (gethostname (name, sizeof (name) - 1) == 0)
return name; return name;
return String::empty; return std::string{};
}
//==============================================================================
void CPUInformation::initialise() noexcept
{
const String features (BSDStatsHelpers::getDmesgInfo (" Features="));
hasMMX = features.contains ("MMX");
hasSSE = features.contains ("SSE");
hasSSE2 = features.contains ("SSE2");
const String features2 (BSDStatsHelpers::getDmesgInfo (" Features2="));
hasSSE3 = features2.contains ("SSE3");
const String amdfeatures2 (BSDStatsHelpers::getDmesgInfo (" AMD Features2="));
has3DNow = amdfeatures2.contains ("3DNow!");
} }
//============================================================================== //==============================================================================
@@ -319,13 +64,4 @@ double Time::getMillisecondCounterHiRes() noexcept
return getHighResolutionTicks() * 0.001; return getHighResolutionTicks() * 0.001;
} }
bool Time::setSystemTimeToThisTime() const
{
timeval t;
t.tv_sec = millisSinceEpoch / 1000;
t.tv_usec = (millisSinceEpoch - t.tv_sec * 1000) * 1000;
return settimeofday (&t, 0) == 0;
}
} // beast } // beast

View File

@@ -23,33 +23,7 @@
namespace beast namespace beast
{ {
/*
Note that a lot of methods that you'd expect to find in this file actually
live in beast_posix_SharedCode.h!
*/
//============================================================================== //==============================================================================
void Process::setPriority (const ProcessPriority prior)
{
const int policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;
const int minp = sched_get_priority_min (policy);
const int maxp = sched_get_priority_max (policy);
struct sched_param param;
switch (prior)
{
case LowPriority:
case NormalPriority: param.sched_priority = 0; break;
case HighPriority: param.sched_priority = minp + (maxp - minp) / 4; break;
case RealtimePriority: param.sched_priority = minp + (3 * (maxp - minp) / 4); break;
default: bassertfalse; break;
}
pthread_setschedparam (pthread_self(), policy, &param);
}
bool beast_isRunningUnderDebugger() bool beast_isRunningUnderDebugger()
{ {
// XXX not implemented for FreeBSD! // XXX not implemented for FreeBSD!
@@ -62,13 +36,4 @@ bool Process::isRunningUnderDebugger()
return beast_isRunningUnderDebugger(); return beast_isRunningUnderDebugger();
} }
static void swapUserAndEffectiveUser()
{
(void) setreuid (geteuid(), getuid());
(void) setregid (getegid(), getgid());
}
void Process::raisePrivilege() { if (geteuid() != 0 && getuid() == 0) swapUserAndEffectiveUser(); }
void Process::lowerPrivilege() { if (geteuid() == 0 && getuid() != 0) swapUserAndEffectiveUser(); }
} // beast } // beast

View File

@@ -55,85 +55,19 @@ bool File::copyInternal (const File& dest) const
return false; return false;
} }
void File::findFileSystemRoots (Array<File>& destArray)
{
destArray.add (File ("/"));
}
//==============================================================================
bool File::isOnCDRomDrive() const
{
struct statfs buf;
return statfs (getFullPathName().toUTF8(), &buf) == 0
&& buf.f_type == (short) U_ISOFS_SUPER_MAGIC;
}
bool File::isOnHardDisk() const
{
struct statfs buf;
if (statfs (getFullPathName().toUTF8(), &buf) == 0)
{
switch (buf.f_type)
{
case U_ISOFS_SUPER_MAGIC: // CD-ROM
case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
case U_NFS_SUPER_MAGIC: // Network NFS
case U_SMB_SUPER_MAGIC: // Network Samba
return false;
default:
// Assume anything else is a hard-disk (but note it could
// be a RAM disk. There isn't a good way of determining
// this for sure)
return true;
}
}
// Assume so if this fails for some reason
return true;
}
bool File::isOnRemovableDrive() const
{
bassertfalse; // xxx not implemented for linux!
return false;
}
bool File::isHidden() const
{
return getFileName().startsWithChar ('.');
}
//==============================================================================
namespace
{
File beast_readlink (const String& file, const File& defaultFile)
{
const size_t size = 8192;
HeapBlock<char> buffer;
buffer.malloc (size + 4);
const size_t numBytes = readlink (file.toUTF8(), buffer, size);
if (numBytes > 0 && numBytes <= size)
return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes));
return defaultFile;
}
}
File File::getLinkedTarget() const
{
return beast_readlink (getFullPathName().toUTF8(), *this);
}
//============================================================================== //==============================================================================
static File resolveXDGFolder (const char* const type, const char* const fallbackFolder) static File resolveXDGFolder (const char* const type, const char* const fallbackFolder)
{ {
File userDirs ("~/.config/user-dirs.dirs");
StringArray confLines; StringArray confLines;
File ("~/.config/user-dirs.dirs").readLines (confLines);
if (userDirs.existsAsFile())
{
FileInputStream in (userDirs);
if (in.openedOk())
confLines.addLines (in.readEntireStreamAsString());
}
for (int i = 0; i < confLines.size(); ++i) for (int i = 0; i < confLines.size(); ++i)
{ {
@@ -199,18 +133,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return tmp; return tmp;
} }
case invokedExecutableFile:
if (beast_argv != nullptr && beast_argc > 0)
return File (CharPointer_UTF8 (beast_argv[0]));
// deliberate fall-through...
case currentExecutableFile:
case currentApplicationFile:
return beast_getExecutableFile();
case hostApplicationPath:
return beast_readlink ("/proc/self/exe", beast_getExecutableFile());
default: default:
bassertfalse; // unknown type? bassertfalse; // unknown type?
break; break;
@@ -219,30 +141,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File::nonexistent (); return File::nonexistent ();
} }
//==============================================================================
String File::getVersion() const
{
return String::empty; // xxx not yet implemented
}
//==============================================================================
bool File::moveToTrash() const
{
if (! exists())
return true;
File trashCan ("~/.Trash");
if (! trashCan.isDirectory())
trashCan = "~/.local/share/Trash/files";
if (! trashCan.isDirectory())
return false;
return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
getFileExtension()));
}
//============================================================================== //==============================================================================
class DirectoryIterator::NativeIterator::Pimpl class DirectoryIterator::NativeIterator::Pimpl
{ {
@@ -319,59 +217,4 @@ bool DirectoryIterator::NativeIterator::next (String& filenameFound,
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
} }
//==============================================================================
static bool isFileExecutable (const String& filename)
{
beast_statStruct info;
return beast_stat (filename, info)
&& S_ISREG (info.st_mode)
&& access (filename.toUTF8(), X_OK) == 0;
}
bool Process::openDocument (const String& fileName, const String& parameters)
{
String cmdString (fileName.replace (" ", "\\ ",false));
cmdString << " " << parameters;
if ( cmdString.startsWithIgnoreCase ("file:")
|| File::createFileWithoutCheckingPath (fileName).isDirectory()
|| ! isFileExecutable (fileName))
{
// create a command that tries to launch a bunch of likely browsers
const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
"google-chrome", "chromium-browser", "opera", "konqueror" };
StringArray cmdLines;
for (int i = 0; i < numElementsInArray (browserNames); ++i)
cmdLines.add (String (browserNames[i]) + " " + cmdString.trim().quoted());
cmdString = cmdLines.joinIntoString (" || ");
}
const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 };
const int cpid = fork();
if (cpid == 0)
{
setsid();
// Child process
execve (argv[0], (char**) argv, environ);
exit (0);
}
return cpid >= 0;
}
void File::revealToUser() const
{
if (isDirectory())
startAsProcess();
else if (getParentDirectory().exists())
getParentDirectory().startAsProcess();
}
} // beast } // beast

View File

@@ -24,108 +24,19 @@
namespace beast namespace beast
{ {
void Logger::outputDebugString (const String& text) void outputDebugString (std::string const& text)
{ {
std::cerr << text << std::endl; std::cerr << text << std::endl;
} }
//============================================================================== //==============================================================================
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() std::string SystemStats::getComputerName()
{
return Linux;
}
String SystemStats::getOperatingSystemName()
{
return "Linux";
}
bool SystemStats::isOperatingSystem64Bit()
{
#if BEAST_64BIT
return true;
#else
//xxx not sure how to find this out?..
return false;
#endif
}
//==============================================================================
namespace LinuxStatsHelpers
{
String getCpuInfo (const char* const key)
{
StringArray lines;
File ("/proc/cpuinfo").readLines (lines);
for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order)
if (lines[i].startsWithIgnoreCase (key))
return lines[i].fromFirstOccurrenceOf (":", false, false).trim();
return String::empty;
}
}
String SystemStats::getCpuVendor()
{
return LinuxStatsHelpers::getCpuInfo ("vendor_id");
}
int SystemStats::getCpuSpeedInMegaherz()
{
return roundToInt (LinuxStatsHelpers::getCpuInfo ("cpu MHz").getFloatValue());
}
int SystemStats::getMemorySizeInMegabytes()
{
struct sysinfo sysi;
if (sysinfo (&sysi) == 0)
return sysi.totalram * sysi.mem_unit / (1024 * 1024);
return 0;
}
int SystemStats::getPageSize()
{
return sysconf (_SC_PAGESIZE);
}
//==============================================================================
String SystemStats::getLogonName()
{
const char* user = getenv ("USER");
if (user == nullptr)
if (passwd* const pw = getpwuid (getuid()))
user = pw->pw_name;
return CharPointer_UTF8 (user);
}
String SystemStats::getFullUserName()
{
return getLogonName();
}
String SystemStats::getComputerName()
{ {
char name [256] = { 0 }; char name [256] = { 0 };
if (gethostname (name, sizeof (name) - 1) == 0) if (gethostname (name, sizeof (name) - 1) == 0)
return name; return name;
return String::empty; return std::string{};
}
//==============================================================================
void CPUInformation::initialise() noexcept
{
const String flags (LinuxStatsHelpers::getCpuInfo ("flags"));
hasMMX = flags.contains ("mmx");
hasSSE = flags.contains ("sse");
hasSSE2 = flags.contains ("sse2");
hasSSE3 = flags.contains ("sse3");
has3DNow = flags.contains ("3dnow");
} }
//============================================================================== //==============================================================================
@@ -155,13 +66,4 @@ double Time::getMillisecondCounterHiRes() noexcept
return getHighResolutionTicks() * 0.001; return getHighResolutionTicks() * 0.001;
} }
bool Time::setSystemTimeToThisTime() const
{
timeval t;
t.tv_sec = millisSinceEpoch / 1000;
t.tv_usec = (millisSinceEpoch - t.tv_sec * 1000) * 1000;
return settimeofday (&t, 0) == 0;
}
} // beast } // beast

View File

@@ -23,33 +23,7 @@
namespace beast namespace beast
{ {
/*
Note that a lot of methods that you'd expect to find in this file actually
live in beast_posix_SharedCode.h!
*/
//============================================================================== //==============================================================================
void Process::setPriority (const ProcessPriority prior)
{
const int policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;
const int minp = sched_get_priority_min (policy);
const int maxp = sched_get_priority_max (policy);
struct sched_param param;
switch (prior)
{
case LowPriority:
case NormalPriority: param.sched_priority = 0; break;
case HighPriority: param.sched_priority = minp + (maxp - minp) / 4; break;
case RealtimePriority: param.sched_priority = minp + (3 * (maxp - minp) / 4); break;
default: bassertfalse; break;
}
pthread_setschedparam (pthread_self(), policy, &param);
}
bool beast_isRunningUnderDebugger() bool beast_isRunningUnderDebugger()
{ {
static char testResult = 0; static char testResult = 0;
@@ -73,17 +47,4 @@ bool Process::isRunningUnderDebugger()
return beast_isRunningUnderDebugger(); return beast_isRunningUnderDebugger();
} }
// TODO(tom): raisePrivilege and lowerPrivilege don't seem to be called. If we
// start using them, we should deal with the return codes of setreuid() and
// setregid().
static bool swapUserAndEffectiveUser()
{
auto r1 = setreuid (geteuid(), getuid());
auto r2 = setregid (getegid(), getgid());
return !(r1 || r2);
}
void Process::raisePrivilege() { if (geteuid() != 0 && getuid() == 0) swapUserAndEffectiveUser(); }
void Process::lowerPrivilege() { if (geteuid() == 0 && getuid() != 0) swapUserAndEffectiveUser(); }
} // beast } // beast

View File

@@ -49,12 +49,6 @@ bool File::copyInternal (const File& dest) const
} }
} }
void File::findFileSystemRoots (Array<File>& destArray)
{
destArray.add (File ("/"));
}
//============================================================================== //==============================================================================
namespace FileHelpers namespace FileHelpers
{ {
@@ -128,47 +122,6 @@ namespace FileHelpers
} }
} }
bool File::isOnCDRomDrive() const
{
const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 };
return FileHelpers::isFileOnDriveType (*this, cdTypes);
}
bool File::isOnHardDisk() const
{
const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 };
return ! (isOnCDRomDrive() || FileHelpers::isFileOnDriveType (*this, nonHDTypes));
}
bool File::isOnRemovableDrive() const
{
#if BEAST_IOS
return false; // xxx is this possible?
#else
BEAST_AUTORELEASEPOOL
{
BOOL removable = false;
[[NSWorkspace sharedWorkspace]
getFileSystemInfoForPath: beastStringToNS (getFullPathName())
isRemovable: &removable
isWritable: nil
isUnmountable: nil
description: nil
type: nil];
return removable;
}
#endif
}
bool File::isHidden() const
{
return FileHelpers::isHiddenFile (getFullPathName());
}
//============================================================================== //==============================================================================
const char* const* beast_argv = nullptr; const char* const* beast_argv = nullptr;
int beast_argc = 0; int beast_argc = 0;
@@ -214,38 +167,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
case commonDocumentsDirectory: resultPath = "/Users/Shared"; break; case commonDocumentsDirectory: resultPath = "/Users/Shared"; break;
case globalApplicationsDirectory: resultPath = "/Applications"; break; case globalApplicationsDirectory: resultPath = "/Applications"; break;
case invokedExecutableFile:
if (beast_argv != nullptr && beast_argc > 0)
return File (CharPointer_UTF8 (beast_argv[0]));
// deliberate fall-through...
case currentExecutableFile:
return beast_getExecutableFile();
case currentApplicationFile:
{
const File exe (beast_getExecutableFile());
const File parent (exe.getParentDirectory());
#if BEAST_IOS
return parent;
#else
return parent.getFullPathName().endsWithIgnoreCase ("Contents/MacOS")
? parent.getParentDirectory().getParentDirectory()
: exe;
#endif
}
case hostApplicationPath:
{
unsigned int size = 8192;
HeapBlock<char> buffer;
buffer.calloc (size + 8);
_NSGetExecutablePath (buffer.getData(), &size);
return String::fromUTF8 (buffer, (int) size);
}
default: default:
bassertfalse; // unknown type? bassertfalse; // unknown type?
break; break;
@@ -258,59 +179,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File::nonexistent (); return File::nonexistent ();
} }
//==============================================================================
String File::getVersion() const
{
BEAST_AUTORELEASEPOOL
{
if (NSBundle* bundle = [NSBundle bundleWithPath: beastStringToNS (getFullPathName())])
if (NSDictionary* info = [bundle infoDictionary])
if (NSString* name = [info valueForKey: nsStringLiteral ("CFBundleShortVersionString")])
return nsStringToBeast (name);
}
return String::empty;
}
//==============================================================================
File File::getLinkedTarget() const
{
#if BEAST_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
NSString* dest = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: beastStringToNS (getFullPathName()) error: nil];
#else
// (the cast here avoids a deprecation warning)
NSString* dest = [((id) [NSFileManager defaultManager]) pathContentOfSymbolicLinkAtPath: beastStringToNS (getFullPathName())];
#endif
if (dest != nil)
return File (nsStringToBeast (dest));
return *this;
}
//==============================================================================
bool File::moveToTrash() const
{
if (! exists())
return true;
#if BEAST_IOS
return deleteFile(); //xxx is there a trashcan on the iOS?
#else
BEAST_AUTORELEASEPOOL
{
NSString* p = beastStringToNS (getFullPathName());
return [[NSWorkspace sharedWorkspace]
performFileOperation: NSWorkspaceRecycleOperation
source: [p stringByDeletingLastPathComponent]
destination: nsEmptyString()
files: [NSArray arrayWithObject: [p lastPathComponent]]
tag: nil ];
}
#endif
}
//============================================================================== //==============================================================================
class DirectoryIterator::NativeIterator::Pimpl class DirectoryIterator::NativeIterator::Pimpl
{ {
@@ -389,99 +257,4 @@ bool DirectoryIterator::NativeIterator::next (String& filenameFound,
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
} }
//==============================================================================
bool Process::openDocument (const String& fileName, const String& parameters)
{
#if BEAST_IOS
return [[UIApplication sharedApplication] openURL: [NSURL URLWithString: beastStringToNS (fileName)]];
#else
BEAST_AUTORELEASEPOOL
{
if (parameters.isEmpty())
{
return [[NSWorkspace sharedWorkspace] openFile: beastStringToNS (fileName)]
|| [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: beastStringToNS (fileName)]];
}
bool ok = false;
const File file (fileName);
if (file.isBundle())
{
NSMutableArray* urls = [NSMutableArray array];
StringArray docs;
docs.addTokens (parameters, true);
for (int i = 0; i < docs.size(); ++i)
[urls addObject: beastStringToNS (docs[i])];
ok = [[NSWorkspace sharedWorkspace] openURLs: urls
withAppBundleIdentifier: [[NSBundle bundleWithPath: beastStringToNS (fileName)] bundleIdentifier]
options: 0
additionalEventParamDescriptor: nil
launchIdentifiers: nil];
}
else if (file.exists())
{
ok = FileHelpers::launchExecutable ("\"" + fileName + "\" " + parameters);
}
return ok;
}
#endif
}
void File::revealToUser() const
{
#if ! BEAST_IOS
if (exists())
[[NSWorkspace sharedWorkspace] selectFile: beastStringToNS (getFullPathName()) inFileViewerRootedAtPath: nsEmptyString()];
else if (getParentDirectory().exists())
getParentDirectory().revealToUser();
#endif
}
//==============================================================================
OSType File::getMacOSType() const
{
BEAST_AUTORELEASEPOOL
{
#if BEAST_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
NSDictionary* fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath: beastStringToNS (getFullPathName()) error: nil];
#else
// (the cast here avoids a deprecation warning)
NSDictionary* fileDict = [((id) [NSFileManager defaultManager]) fileAttributesAtPath: beastStringToNS (getFullPathName()) traverseLink: NO];
#endif
return [fileDict fileHFSTypeCode];
}
}
bool File::isBundle() const
{
#if BEAST_IOS
return false; // xxx can't find a sensible way to do this without trying to open the bundle..
#else
BEAST_AUTORELEASEPOOL
{
return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: beastStringToNS (getFullPathName())];
}
#endif
}
#if BEAST_MAC
void File::addToDock() const
{
// check that it's not already there...
if (! beast_getOutputFromCommand ("defaults read com.apple.dock persistent-apps").containsIgnoreCase (getFullPathName()))
{
beast_runSystemCommand ("defaults write com.apple.dock persistent-apps -array-add \"<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>"
+ getFullPathName() + "</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>\"");
beast_runSystemCommand ("osascript -e \"tell application \\\"Dock\\\" to quit\"");
}
}
#endif
} // beast } // beast

View File

@@ -35,51 +35,16 @@ ScopedAutoReleasePool::~ScopedAutoReleasePool()
} }
//============================================================================== //==============================================================================
void Logger::outputDebugString (const String& text) void outputDebugString (std::string const& text)
{ {
// Would prefer to use std::cerr here, but avoiding it for // Would prefer to use std::cerr here, but avoiding it for
// the moment, due to clang JIT linkage problems. // the moment, due to clang JIT linkage problems.
fputs (text.toRawUTF8(), stderr); fputs (text.c_str (), stderr);
fputs ("\n", stderr); fputs ("\n", stderr);
fflush (stderr); fflush (stderr);
} }
//============================================================================== //==============================================================================
namespace SystemStatsHelpers
{
#if BEAST_INTEL && ! BEAST_NO_INLINE_ASM
static void doCPUID (std::uint32_t& a, std::uint32_t& b, std::uint32_t& c, std::uint32_t& d, std::uint32_t type)
{
std::uint32_t la = a, lb = b, lc = c, ld = d;
asm ("mov %%ebx, %%esi \n\t"
"cpuid \n\t"
"xchg %%esi, %%ebx"
: "=a" (la), "=S" (lb), "=c" (lc), "=d" (ld) : "a" (type)
#if BEAST_64BIT
, "b" (lb), "c" (lc), "d" (ld)
#endif
);
a = la; b = lb; c = lc; d = ld;
}
#endif
}
//==============================================================================
void CPUInformation::initialise() noexcept
{
#if BEAST_INTEL && ! BEAST_NO_INLINE_ASM
std::uint32_t a = 0, b = 0, d = 0, c = 0;
SystemStatsHelpers::doCPUID (a, b, c, d, 1);
hasMMX = (d & (1u << 23)) != 0;
hasSSE = (d & (1u << 25)) != 0;
hasSSE2 = (d & (1u << 26)) != 0;
has3DNow = (b & (1u << 31)) != 0;
hasSSE3 = (c & (1u << 0)) != 0;
#endif
}
#if BEAST_MAC #if BEAST_MAC
struct RLimitInitialiser struct RLimitInitialiser
@@ -97,111 +62,13 @@ static RLimitInitialiser rLimitInitialiser;
#endif #endif
//============================================================================== //==============================================================================
#if ! BEAST_IOS std::string SystemStats::getComputerName()
static String getOSXVersion()
{
BEAST_AUTORELEASEPOOL
{
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:
nsStringLiteral ("/System/Library/CoreServices/SystemVersion.plist")];
return nsStringToBeast ([dict objectForKey: nsStringLiteral ("ProductVersion")]);
}
}
#endif
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
{
#if BEAST_IOS
return iOS;
#else
StringArray parts;
parts.addTokens (getOSXVersion(), ".", String::empty);
bassert (parts[0].getIntValue() == 10);
const int major = parts[1].getIntValue();
bassert (major > 2);
return (OperatingSystemType) (major + MacOSX_10_4 - 4);
#endif
}
String SystemStats::getOperatingSystemName()
{
#if BEAST_IOS
return "iOS " + nsStringToBeast ([[UIDevice currentDevice] systemVersion]);
#else
return "Mac OSX " + getOSXVersion();
#endif
}
bool SystemStats::isOperatingSystem64Bit()
{
#if BEAST_IOS
return false;
#elif BEAST_64BIT
return true;
#else
return getOperatingSystemType() >= MacOSX_10_6;
#endif
}
int SystemStats::getMemorySizeInMegabytes()
{
std::uint64_t mem = 0;
size_t memSize = sizeof (mem);
int mib[] = { CTL_HW, HW_MEMSIZE };
sysctl (mib, 2, &mem, &memSize, 0, 0);
return (int) (mem / (1024 * 1024));
}
String SystemStats::getCpuVendor()
{
#if BEAST_INTEL && ! BEAST_NO_INLINE_ASM
std::uint32_t dummy = 0;
std::uint32_t vendor[4] = { 0 };
SystemStatsHelpers::doCPUID (dummy, vendor[0], vendor[2], vendor[1], 0);
return String (reinterpret_cast <const char*> (vendor), 12);
#else
return String::empty;
#endif
}
int SystemStats::getCpuSpeedInMegaherz()
{
std::uint64_t speedHz = 0;
size_t speedSize = sizeof (speedHz);
int mib[] = { CTL_HW, HW_CPU_FREQ };
sysctl (mib, 2, &speedHz, &speedSize, 0, 0);
#if BEAST_BIG_ENDIAN
if (speedSize == 4)
speedHz >>= 32;
#endif
return (int) (speedHz / 1000000);
}
//==============================================================================
String SystemStats::getLogonName()
{
return nsStringToBeast (NSUserName());
}
String SystemStats::getFullUserName()
{
return nsStringToBeast (NSFullUserName());
}
String SystemStats::getComputerName()
{ {
char name [256] = { 0 }; char name [256] = { 0 };
if (gethostname (name, sizeof (name) - 1) == 0) if (gethostname (name, sizeof (name) - 1) == 0)
return String (name).upToLastOccurrenceOf (".local", false, true); return String (name).upToLastOccurrenceOf (".local", false, true).toStdString();
return String::empty; return std::string{};
} }
//============================================================================== //==============================================================================
@@ -256,16 +123,4 @@ double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHan
std::int64_t Time::getHighResolutionTicksPerSecond() noexcept { return hiResCounterHandler().highResTimerFrequency; } std::int64_t Time::getHighResolutionTicksPerSecond() noexcept { return hiResCounterHandler().highResTimerFrequency; }
std::int64_t Time::getHighResolutionTicks() noexcept { return (std::int64_t) mach_absolute_time(); } std::int64_t Time::getHighResolutionTicks() noexcept { return (std::int64_t) mach_absolute_time(); }
bool Time::setSystemTimeToThisTime() const
{
bassertfalse;
return false;
}
//==============================================================================
int SystemStats::getPageSize()
{
return (int) NSPageSize();
}
} // beast } // beast

View File

@@ -23,44 +23,6 @@
namespace beast namespace beast
{ {
/*
Note that a lot of methods that you'd expect to find in this file actually
live in beast_posix_SharedCode.h!
*/
//==============================================================================
bool Process::isForegroundProcess()
{
#if BEAST_MAC
return [NSApp isActive];
#else
return true; // xxx change this if more than one app is ever possible on iOS!
#endif
}
void Process::makeForegroundProcess()
{
#if BEAST_MAC
[NSApp activateIgnoringOtherApps: YES];
#endif
}
void Process::raisePrivilege()
{
bassertfalse;
}
void Process::lowerPrivilege()
{
bassertfalse;
}
void Process::setPriority (ProcessPriority)
{
// xxx
}
//============================================================================== //==============================================================================
bool beast_isRunningUnderDebugger() bool beast_isRunningUnderDebugger()
{ {

View File

@@ -411,193 +411,6 @@ Result FileOutputStream::truncate()
return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition)); return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition));
} }
//==============================================================================
Result RandomAccessFile::nativeOpen (File const& path, Mode mode)
{
bassert (! isOpen ());
Result result (Result::ok ());
if (path.exists())
{
int oflag;
switch (mode)
{
case readOnly:
oflag = O_RDONLY;
break;
default:
case readWrite:
oflag = O_RDWR;
break;
};
const int f = ::open (path.getFullPathName().toUTF8(), oflag, 00644);
if (f != -1)
{
currentPosition = lseek (f, 0, SEEK_SET);
if (currentPosition >= 0)
{
file = path;
fileHandle = fdToVoidPointer (f);
}
else
{
result = getResultForErrno();
::close (f);
}
}
else
{
result = getResultForErrno();
}
}
else if (mode == readWrite)
{
const int f = ::open (path.getFullPathName().toUTF8(), O_RDWR + O_CREAT, 00644);
if (f != -1)
{
file = path;
fileHandle = fdToVoidPointer (f);
}
else
{
result = getResultForErrno();
}
}
else
{
// file doesn't exist and we're opening read-only
Result::fail (String (strerror (ENOENT)));
}
return result;
}
void RandomAccessFile::nativeClose ()
{
bassert (isOpen ());
file = File::nonexistent ();
::close (getFD (fileHandle));
fileHandle = nullptr;
currentPosition = 0;
}
Result RandomAccessFile::nativeSetPosition (FileOffset newPosition)
{
bassert (isOpen ());
off_t const actualPosition = lseek (getFD (fileHandle), newPosition, SEEK_SET);
currentPosition = actualPosition;
if (actualPosition != newPosition)
{
// VFALCO NOTE I dislike return from the middle but
// Result::ok() is showing up in the profile
//
return getResultForErrno();
}
return Result::ok();
}
Result RandomAccessFile::nativeRead (void* buffer, ByteCount numBytes, ByteCount* pActualAmount)
{
bassert (isOpen ());
std::ptrdiff_t bytesRead = ::read (getFD (fileHandle), buffer, numBytes);
if (bytesRead < 0)
{
if (pActualAmount != nullptr)
*pActualAmount = 0;
// VFALCO NOTE I dislike return from the middle but
// Result::ok() is showing up in the profile
//
return getResultForErrno();
}
currentPosition += bytesRead;
if (pActualAmount != nullptr)
*pActualAmount = bytesRead;
return Result::ok();
}
Result RandomAccessFile::nativeWrite (void const* data, ByteCount numBytes, size_t* pActualAmount)
{
bassert (isOpen ());
std::ptrdiff_t bytesWritten = ::write (getFD (fileHandle), data, numBytes);
// write(3) says that the actual return will be exactly -1 on
// error, but we will assume anything negative indicates failure.
//
if (bytesWritten < 0)
{
if (pActualAmount != nullptr)
*pActualAmount = 0;
// VFALCO NOTE I dislike return from the middle but
// Result::ok() is showing up in the profile
//
return getResultForErrno();
}
if (pActualAmount != nullptr)
*pActualAmount = bytesWritten;
return Result::ok();
}
Result RandomAccessFile::nativeTruncate ()
{
bassert (isOpen ());
flush();
return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition));
}
Result RandomAccessFile::nativeFlush ()
{
bassert (isOpen ());
Result result (Result::ok ());
if (fsync (getFD (fileHandle)) == -1)
result = getResultForErrno();
#if BEAST_ANDROID
// This stuff tells the OS to asynchronously update the metadata
// that the OS has cached aboud the file - this metadata is used
// when the device is acting as a USB drive, and unless it's explicitly
// refreshed, it'll get out of step with the real file.
const LocalRef<jstring> t (javaString (file.getFullPathName()));
android.activity.callVoidMethod (BeastAppActivity.scanFile, t.get());
#endif
return result;
}
//==============================================================================
String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
{
if (const char* s = ::getenv (name.toUTF8()))
return String::fromUTF8 (s);
return defaultValue;
}
//============================================================================== //==============================================================================
#if BEAST_PROBEASTR_LIVE_BUILD #if BEAST_PROBEASTR_LIVE_BUILD
extern "C" const char* beast_getCurrentExecutablePath(); extern "C" const char* beast_getCurrentExecutablePath();
@@ -645,105 +458,4 @@ std::int64_t File::getVolumeTotalSize() const
return 0; return 0;
} }
String File::getVolumeLabel() const
{
#if BEAST_MAC
struct VolAttrBuf
{
u_int32_t length;
attrreference_t mountPointRef;
char mountPointSpace [MAXPATHLEN];
} attrBuf;
struct attrlist attrList;
zerostruct (attrList); // (can't use "= { 0 }" on this object because it's typedef'ed as a C struct)
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
File f (*this);
for (;;)
{
if (getattrlist (f.getFullPathName().toUTF8(), &attrList, &attrBuf, sizeof (attrBuf), 0) == 0)
return String::fromUTF8 (((const char*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset,
(int) attrBuf.mountPointRef.attr_length);
const File parent (f.getParentDirectory());
if (f == parent)
break;
f = parent;
}
#endif
return String::empty;
}
int File::getVolumeSerialNumber() const
{
int result = 0;
/* int fd = open (getFullPathName().toUTF8(), O_RDONLY | O_NONBLOCK);
char info [512];
#ifndef HDIO_GET_IDENTITY
#define HDIO_GET_IDENTITY 0x030d
#endif
if (ioctl (fd, HDIO_GET_IDENTITY, info) == 0)
{
DBG (String (info + 20, 20));
result = String (info + 20, 20).trim().getIntValue();
}
close (fd);*/
return result;
}
//==============================================================================
void beast_runSystemCommand (const String&);
void beast_runSystemCommand (const String& command)
{
int result = system (command.toUTF8());
(void) result;
}
String beast_getOutputFromCommand (const String&);
String beast_getOutputFromCommand (const String& command)
{
// slight bodge here, as we just pipe the output into a temp file and read it...
const File tempFile (File::getSpecialLocation (File::tempDirectory)
.getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false));
beast_runSystemCommand (command + " > " + tempFile.getFullPathName());
String result (tempFile.loadFileAsString());
tempFile.deleteFile();
return result;
}
//==============================================================================
bool DynamicLibrary::open (const String& name)
{
close();
handle = dlopen (name.isEmpty() ? nullptr : name.toUTF8().getAddress(), RTLD_LOCAL | RTLD_NOW);
return handle != nullptr;
}
void DynamicLibrary::close()
{
if (handle != nullptr)
{
dlclose (handle);
handle = nullptr;
}
}
void* DynamicLibrary::getFunction (const String& functionName) noexcept
{
return handle != nullptr ? dlsym (handle, functionName.toUTF8()) : nullptr;
}
} // beast } // beast

View File

@@ -1,170 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_WIN32_COMSMARTPTR_H_INCLUDED
#define BEAST_WIN32_COMSMARTPTR_H_INCLUDED
namespace beast
{
#ifndef _MSC_VER
template<typename Type> struct UUIDGetter { static CLSID get() { bassertfalse; return CLSID(); } };
#define __uuidof(x) UUIDGetter<x>::get()
#endif
inline GUID uuidFromString (const char* const s) noexcept
{
unsigned long p0;
unsigned int p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
#ifndef _MSC_VER
sscanf
#else
sscanf_s
#endif
(s, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
&p0, &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10);
GUID g = { p0, (std::uint16_t) p1, (std::uint16_t) p2, { (std::uint8_t) p3, (std::uint8_t) p4, (std::uint8_t) p5, (std::uint8_t) p6,
(std::uint8_t) p7, (std::uint8_t) p8, (std::uint8_t) p9, (std::uint8_t) p10 }};
return g;
}
//==============================================================================
/** A simple COM smart pointer.
*/
template <class ComClass>
class ComSmartPtr
{
public:
ComSmartPtr() throw() : p (0) {}
ComSmartPtr (ComClass* const obj) : p (obj) { if (p) p->AddRef(); }
ComSmartPtr (const ComSmartPtr<ComClass>& other) : p (other.p) { if (p) p->AddRef(); }
~ComSmartPtr() { release(); }
operator ComClass*() const throw() { return p; }
ComClass& operator*() const throw() { return *p; }
ComClass* operator->() const throw() { return p; }
ComSmartPtr& operator= (ComClass* const newP)
{
if (newP != 0) newP->AddRef();
release();
p = newP;
return *this;
}
ComSmartPtr& operator= (const ComSmartPtr<ComClass>& newP) { return operator= (newP.p); }
// Releases and nullifies this pointer and returns its address
ComClass** resetAndGetPointerAddress()
{
release();
p = 0;
return &p;
}
HRESULT CoCreateInstance (REFCLSID classUUID, DWORD dwClsContext = CLSCTX_INPROC_SERVER)
{
HRESULT hr = ::CoCreateInstance (classUUID, 0, dwClsContext, __uuidof (ComClass), (void**) resetAndGetPointerAddress());
bassert (hr != CO_E_NOTINITIALIZED); // You haven't called CoInitialize for the current thread!
return hr;
}
template <class OtherComClass>
HRESULT QueryInterface (REFCLSID classUUID, ComSmartPtr<OtherComClass>& destObject) const
{
if (p == 0)
return E_POINTER;
return p->QueryInterface (classUUID, (void**) destObject.resetAndGetPointerAddress());
}
template <class OtherComClass>
HRESULT QueryInterface (ComSmartPtr<OtherComClass>& destObject) const
{
return this->QueryInterface (__uuidof (OtherComClass), destObject);
}
private:
ComClass* p;
void release() { if (p != 0) p->Release(); }
ComClass** operator&() throw(); // private to avoid it being used accidentally
};
//==============================================================================
#define BEAST_COMRESULT HRESULT __stdcall
//==============================================================================
template <class ComClass>
class ComBaseClassHelperBase : public ComClass
{
public:
ComBaseClassHelperBase (unsigned int initialRefCount) : refCount (initialRefCount) {}
virtual ~ComBaseClassHelperBase() {}
ULONG __stdcall AddRef() { return ++refCount; }
ULONG __stdcall Release() { const ULONG r = --refCount; if (r == 0) delete this; return r; }
protected:
ULONG refCount;
BEAST_COMRESULT QueryInterface (REFIID refId, void** result)
{
if (refId == IID_IUnknown)
return castToType <IUnknown> (result);
*result = 0;
return E_NOINTERFACE;
}
template <class Type>
BEAST_COMRESULT castToType (void** result)
{
this->AddRef(); *result = dynamic_cast <Type*> (this); return S_OK;
}
};
/** Handy base class for writing COM objects, providing ref-counting and a basic QueryInterface method.
*/
template <class ComClass>
class ComBaseClassHelper : public ComBaseClassHelperBase <ComClass>
{
public:
ComBaseClassHelper (unsigned int initialRefCount = 1) : ComBaseClassHelperBase <ComClass> (initialRefCount) {}
~ComBaseClassHelper() {}
BEAST_COMRESULT QueryInterface (REFIID refId, void** result)
{
if (refId == __uuidof (ComClass))
return this->template castToType <ComClass> (result);
return ComBaseClassHelperBase <ComClass>::QueryInterface (refId, result);
}
};
} // beast
#endif // BEAST_WIN32_COMSMARTPTR_H_INCLUDED

View File

@@ -31,6 +31,9 @@ namespace beast
//============================================================================== //==============================================================================
namespace WindowsFileHelpers namespace WindowsFileHelpers
{ {
static_assert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME),
"The FILETIME structure format has been modified.");
DWORD getAtts (const String& path) DWORD getAtts (const String& path)
{ {
return GetFileAttributes (path.toWideCharPointer()); return GetFileAttributes (path.toWideCharPointer());
@@ -38,8 +41,6 @@ namespace WindowsFileHelpers
std::int64_t fileTimeToTime (const FILETIME* const ft) std::int64_t fileTimeToTime (const FILETIME* const ft)
{ {
static_bassert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME)); // tell me if this fails!
return (std::int64_t) ((reinterpret_cast<const ULARGE_INTEGER*> (ft)->QuadPart - 116444736000000000LL) / 10000); return (std::int64_t) ((reinterpret_cast<const ULARGE_INTEGER*> (ft)->QuadPart - 116444736000000000LL) / 10000);
} }
@@ -161,11 +162,6 @@ bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const
|| SetFileAttributes (fullPath.toWideCharPointer(), newAtts) != FALSE; || SetFileAttributes (fullPath.toWideCharPointer(), newAtts) != FALSE;
} }
bool File::isHidden() const
{
return (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_HIDDEN) != 0;
}
//============================================================================== //==============================================================================
bool File::deleteFile() const bool File::deleteFile() const
{ {
@@ -176,26 +172,6 @@ bool File::deleteFile() const
: DeleteFile (fullPath.toWideCharPointer()) != 0; : DeleteFile (fullPath.toWideCharPointer()) != 0;
} }
bool File::moveToTrash() const
{
if (! exists())
return true;
// The string we pass in must be double null terminated..
const size_t numBytes = CharPointer_UTF16::getBytesRequiredFor (fullPath.getCharPointer()) + 8;
HeapBlock<WCHAR> doubleNullTermPath;
doubleNullTermPath.calloc (numBytes, 1);
fullPath.copyToUTF16 (doubleNullTermPath, numBytes);
SHFILEOPSTRUCT fos = { 0 };
fos.wFunc = FO_DELETE;
fos.pFrom = doubleNullTermPath;
fos.fFlags = FOF_ALLOWUNDO | FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION
| FOF_NOCONFIRMMKDIR | FOF_RENAMEONCOLLISION;
return SHFileOperation (&fos) == 0;
}
bool File::copyInternal (const File& dest) const bool File::copyInternal (const File& dest) const
{ {
return CopyFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer(), false) != 0; return CopyFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer(), false) != 0;
@@ -312,162 +288,6 @@ Result FileOutputStream::truncate()
//============================================================================== //==============================================================================
Result RandomAccessFile::nativeOpen (File const& path, Mode mode)
{
bassert (! isOpen ());
Result result (Result::ok ());
DWORD dwDesiredAccess;
switch (mode)
{
case readOnly:
dwDesiredAccess = GENERIC_READ;
break;
default:
case readWrite:
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
break;
};
DWORD dwCreationDisposition;
switch (mode)
{
case readOnly:
dwCreationDisposition = OPEN_EXISTING;
break;
default:
case readWrite:
dwCreationDisposition = OPEN_ALWAYS;
break;
};
HANDLE h = CreateFile (path.getFullPathName().toWideCharPointer(),
dwDesiredAccess,
FILE_SHARE_READ,
0,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
0);
if (h != INVALID_HANDLE_VALUE)
{
file = path;
fileHandle = h;
result = setPosition (0);
if (result.failed ())
nativeClose ();
}
else
{
result = WindowsFileHelpers::getResultForLastError();
}
return result;
}
void RandomAccessFile::nativeClose ()
{
bassert (isOpen ());
CloseHandle ((HANDLE) fileHandle);
file = File::nonexistent ();
fileHandle = nullptr;
currentPosition = 0;
}
Result RandomAccessFile::nativeSetPosition (FileOffset newPosition)
{
bassert (isOpen ());
Result result (Result::ok ());
LARGE_INTEGER li;
li.QuadPart = newPosition;
li.LowPart = SetFilePointer ((HANDLE) fileHandle,
(LONG) li.LowPart,
&li.HighPart,
FILE_BEGIN);
if (li.LowPart != INVALID_SET_FILE_POINTER)
{
currentPosition = li.QuadPart;
}
else
{
result = WindowsFileHelpers::getResultForLastError();
}
return result;
}
Result RandomAccessFile::nativeRead (void* buffer, ByteCount numBytes, ByteCount* pActualAmount)
{
bassert (isOpen ());
Result result (Result::ok ());
DWORD actualNum = 0;
if (! ReadFile ((HANDLE) fileHandle, buffer, (DWORD) numBytes, &actualNum, 0))
result = WindowsFileHelpers::getResultForLastError();
currentPosition += actualNum;
if (pActualAmount != nullptr)
*pActualAmount = actualNum;
return result;
}
Result RandomAccessFile::nativeWrite (void const* data, ByteCount numBytes, size_t* pActualAmount)
{
bassert (isOpen ());
Result result (Result::ok ());
DWORD actualNum = 0;
if (! WriteFile ((HANDLE) fileHandle, data, (DWORD) numBytes, &actualNum, 0))
result = WindowsFileHelpers::getResultForLastError();
if (pActualAmount != nullptr)
*pActualAmount = actualNum;
return result;
}
Result RandomAccessFile::nativeTruncate ()
{
bassert (isOpen ());
Result result (Result::ok ());
if (! SetEndOfFile ((HANDLE) fileHandle))
result = WindowsFileHelpers::getResultForLastError();
return result;
}
Result RandomAccessFile::nativeFlush ()
{
bassert (isOpen ());
Result result (Result::ok ());
if (! FlushFileBuffers ((HANDLE) fileHandle))
result = WindowsFileHelpers::getResultForLastError();
return result;
}
//==============================================================================
std::int64_t File::getSize() const std::int64_t File::getSize() const
{ {
WIN32_FILE_ATTRIBUTE_DATA attributes; WIN32_FILE_ATTRIBUTE_DATA attributes;
@@ -519,51 +339,6 @@ bool File::setFileTimesInternal (std::int64_t modificationTime, std::int64_t acc
} }
//============================================================================== //==============================================================================
void File::findFileSystemRoots (Array<File>& destArray)
{
TCHAR buffer [2048] = { 0 };
GetLogicalDriveStrings (2048, buffer);
const TCHAR* n = buffer;
StringArray roots;
while (*n != 0)
{
roots.add (String (n));
while (*n++ != 0)
{}
}
roots.sort (true);
for (int i = 0; i < roots.size(); ++i)
destArray.add (roots [i]);
}
//==============================================================================
String File::getVolumeLabel() const
{
TCHAR dest[64];
if (! GetVolumeInformation (WindowsFileHelpers::getDriveFromPath (getFullPathName()).toWideCharPointer(), dest,
(DWORD) numElementsInArray (dest), 0, 0, 0, 0, 0))
dest[0] = 0;
return dest;
}
int File::getVolumeSerialNumber() const
{
TCHAR dest[64];
DWORD serialNum;
if (! GetVolumeInformation (WindowsFileHelpers::getDriveFromPath (getFullPathName()).toWideCharPointer(), dest,
(DWORD) numElementsInArray (dest), &serialNum, 0, 0, 0, 0))
return 0;
return (int) serialNum;
}
std::int64_t File::getBytesFreeOnVolume() const std::int64_t File::getBytesFreeOnVolume() const
{ {
return WindowsFileHelpers::getDiskSpaceInfo (getFullPathName(), false); return WindowsFileHelpers::getDiskSpaceInfo (getFullPathName(), false);
@@ -574,38 +349,6 @@ std::int64_t File::getVolumeTotalSize() const
return WindowsFileHelpers::getDiskSpaceInfo (getFullPathName(), true); return WindowsFileHelpers::getDiskSpaceInfo (getFullPathName(), true);
} }
//==============================================================================
bool File::isOnCDRomDrive() const
{
return WindowsFileHelpers::getWindowsDriveType (getFullPathName()) == DRIVE_CDROM;
}
bool File::isOnHardDisk() const
{
if (fullPath.isEmpty())
return false;
const unsigned int n = WindowsFileHelpers::getWindowsDriveType (getFullPathName());
if (fullPath.toLowerCase()[0] <= 'b' && fullPath[1] == ':')
return n != DRIVE_REMOVABLE;
return n != DRIVE_CDROM && n != DRIVE_REMOTE;
}
bool File::isOnRemovableDrive() const
{
if (fullPath.isEmpty())
return false;
const unsigned int n = WindowsFileHelpers::getWindowsDriveType (getFullPathName());
return n == DRIVE_CDROM
|| n == DRIVE_REMOTE
|| n == DRIVE_REMOVABLE
|| n == DRIVE_RAMDISK;
}
//============================================================================== //==============================================================================
File File::getSpecialLocation (const SpecialLocationType type) File File::getSpecialLocation (const SpecialLocationType type)
{ {
@@ -632,14 +375,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File (String (dest)); return File (String (dest));
} }
case invokedExecutableFile:
case currentExecutableFile:
case currentApplicationFile:
return WindowsFileHelpers::getModuleFileName ((HINSTANCE) Process::getCurrentModuleInstanceHandle());
case hostApplicationPath:
return WindowsFileHelpers::getModuleFileName (0);
default: default:
bassertfalse; // unknown type? bassertfalse; // unknown type?
return File::nonexistent (); return File::nonexistent ();
@@ -662,76 +397,6 @@ bool File::setAsCurrentWorkingDirectory() const
return SetCurrentDirectory (getFullPathName().toWideCharPointer()) != FALSE; return SetCurrentDirectory (getFullPathName().toWideCharPointer()) != FALSE;
} }
//==============================================================================
String File::getVersion() const
{
String result;
DWORD handle = 0;
DWORD bufferSize = GetFileVersionInfoSize (getFullPathName().toWideCharPointer(), &handle);
HeapBlock<char> buffer;
buffer.calloc (bufferSize);
if (GetFileVersionInfo (getFullPathName().toWideCharPointer(), 0, bufferSize, buffer))
{
VS_FIXEDFILEINFO* vffi;
UINT len = 0;
if (VerQueryValue (buffer, (LPTSTR) _T("\\"), (LPVOID*) &vffi, &len))
{
result << (int) HIWORD (vffi->dwFileVersionMS) << '.'
<< (int) LOWORD (vffi->dwFileVersionMS) << '.'
<< (int) HIWORD (vffi->dwFileVersionLS) << '.'
<< (int) LOWORD (vffi->dwFileVersionLS);
}
}
return result;
}
//==============================================================================
File File::getLinkedTarget() const
{
File result (*this);
String p (getFullPathName());
if (! exists())
p += ".lnk";
else if (! hasFileExtension (".lnk"))
return result;
ComSmartPtr <IShellLink> shellLink;
ComSmartPtr <IPersistFile> persistFile;
if (SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))
&& SUCCEEDED (shellLink.QueryInterface (persistFile))
&& SUCCEEDED (persistFile->Load (p.toWideCharPointer(), STGM_READ))
&& SUCCEEDED (shellLink->Resolve (0, SLR_ANY_MATCH | SLR_NO_UI)))
{
WIN32_FIND_DATA winFindData;
WCHAR resolvedPath [MAX_PATH];
if (SUCCEEDED (shellLink->GetPath (resolvedPath, MAX_PATH, &winFindData, SLGP_UNCPRIORITY)))
result = File (resolvedPath);
}
return result;
}
bool File::createLink (const String& description, const File& linkFileToCreate) const
{
linkFileToCreate.deleteFile();
ComSmartPtr <IShellLink> shellLink;
ComSmartPtr <IPersistFile> persistFile;
return SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))
&& SUCCEEDED (shellLink->SetPath (getFullPathName().toWideCharPointer()))
&& SUCCEEDED (shellLink->SetDescription (description.toWideCharPointer()))
&& SUCCEEDED (shellLink.QueryInterface (persistFile))
&& SUCCEEDED (persistFile->Save (linkFileToCreate.getFullPathName().toWideCharPointer(), TRUE));
}
//============================================================================== //==============================================================================
class DirectoryIterator::NativeIterator::Pimpl class DirectoryIterator::NativeIterator::Pimpl
: LeakChecked <DirectoryIterator::NativeIterator::Pimpl> : LeakChecked <DirectoryIterator::NativeIterator::Pimpl>
@@ -805,33 +470,4 @@ bool DirectoryIterator::NativeIterator::next (String& filenameFound,
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
} }
//==============================================================================
bool Process::openDocument (const String& fileName, const String& parameters)
{
HINSTANCE hInstance = 0;
hInstance = ShellExecute (0, 0, fileName.toWideCharPointer(),
parameters.toWideCharPointer(), 0, SW_SHOWDEFAULT);
return hInstance > (HINSTANCE) 32;
}
void File::revealToUser() const
{
DynamicLibrary dll ("Shell32.dll");
BEAST_LOAD_WINAPI_FUNCTION (dll, ILCreateFromPathW, ilCreateFromPathW, ITEMIDLIST*, (LPCWSTR))
BEAST_LOAD_WINAPI_FUNCTION (dll, ILFree, ilFree, void, (ITEMIDLIST*))
BEAST_LOAD_WINAPI_FUNCTION (dll, SHOpenFolderAndSelectItems, shOpenFolderAndSelectItems, HRESULT, (ITEMIDLIST*, UINT, void*, DWORD))
if (ilCreateFromPathW != nullptr && shOpenFolderAndSelectItems != nullptr && ilFree != nullptr)
{
if (ITEMIDLIST* const itemIDList = ilCreateFromPathW (fullPath.toWideCharPointer()))
{
shOpenFolderAndSelectItems (itemIDList, 0, nullptr, 0);
ilFree (itemIDList);
}
}
}
} // beast } // beast

View File

@@ -1,222 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace beast
{
struct RegistryKeyWrapper
{
RegistryKeyWrapper (String name, const bool createForWriting, const DWORD wow64Flags)
: key (0), wideCharValueName (nullptr)
{
HKEY rootKey = 0;
if (name.startsWithIgnoreCase ("HKEY_CURRENT_USER\\")) rootKey = HKEY_CURRENT_USER;
else if (name.startsWithIgnoreCase ("HKEY_LOCAL_MACHINE\\")) rootKey = HKEY_LOCAL_MACHINE;
else if (name.startsWithIgnoreCase ("HKEY_CLASSES_ROOT\\")) rootKey = HKEY_CLASSES_ROOT;
if (rootKey != 0)
{
name = name.substring (name.indexOfChar ('\\') + 1);
const int lastSlash = name.lastIndexOfChar ('\\');
valueName = name.substring (lastSlash + 1);
wideCharValueName = valueName.toWideCharPointer();
name = name.substring (0, lastSlash);
const wchar_t* const wideCharName = name.toWideCharPointer();
DWORD result;
if (createForWriting)
RegCreateKeyEx (rootKey, wideCharName, 0, 0, REG_OPTION_NON_VOLATILE,
KEY_WRITE | KEY_QUERY_VALUE | wow64Flags, 0, &key, &result);
else
RegOpenKeyEx (rootKey, wideCharName, 0, KEY_READ | wow64Flags, &key);
}
}
RegistryKeyWrapper (RegistryKeyWrapper const&) = delete;
RegistryKeyWrapper& operator= (RegistryKeyWrapper const&) = delete;
~RegistryKeyWrapper()
{
if (key != 0)
RegCloseKey (key);
}
static bool setValue (const String& regValuePath, const DWORD type,
const void* data, size_t dataSize)
{
const RegistryKeyWrapper key (regValuePath, true, 0);
return key.key != 0
&& RegSetValueEx (key.key, key.wideCharValueName, 0, type,
reinterpret_cast <const BYTE*> (data),
(DWORD) dataSize) == ERROR_SUCCESS;
}
static std::uint32_t getBinaryValue (const String& regValuePath, MemoryBlock& result, DWORD wow64Flags)
{
const RegistryKeyWrapper key (regValuePath, false, wow64Flags);
if (key.key != 0)
{
for (unsigned long bufferSize = 1024; ; bufferSize *= 2)
{
result.setSize (bufferSize, false);
DWORD type = REG_NONE;
const LONG err = RegQueryValueEx (key.key, key.wideCharValueName, 0, &type,
(LPBYTE) result.getData(), &bufferSize);
if (err == ERROR_SUCCESS)
{
result.setSize (bufferSize, false);
return type;
}
if (err != ERROR_MORE_DATA)
break;
}
}
return REG_NONE;
}
static String getValue (const String& regValuePath, const String& defaultValue, DWORD wow64Flags)
{
MemoryBlock buffer;
switch (getBinaryValue (regValuePath, buffer, wow64Flags))
{
case REG_SZ: return static_cast <const WCHAR*> (buffer.getData());
case REG_DWORD: return String ((int) *reinterpret_cast<const DWORD*> (buffer.getData()));
default: break;
}
return defaultValue;
}
static bool valueExists (const String& regValuePath, const DWORD wow64Flags)
{
const RegistryKeyWrapper key (regValuePath, false, wow64Flags);
if (key.key == 0)
return false;
unsigned char buffer [512];
unsigned long bufferSize = sizeof (buffer);
DWORD type = 0;
const LONG result = RegQueryValueEx (key.key, key.wideCharValueName,
0, &type, buffer, &bufferSize);
return result == ERROR_SUCCESS || result == ERROR_MORE_DATA;
}
HKEY key;
const wchar_t* wideCharValueName;
String valueName;
};
std::uint32_t WindowsRegistry::getBinaryValue (const String& regValuePath, MemoryBlock& result)
{
return RegistryKeyWrapper::getBinaryValue (regValuePath, result, 0);
}
String WindowsRegistry::getValue (const String& regValuePath, const String& defaultValue)
{
return RegistryKeyWrapper::getValue (regValuePath, defaultValue, 0);
}
String WindowsRegistry::getValueWow64 (const String& regValuePath, const String& defaultValue)
{
return RegistryKeyWrapper::getValue (regValuePath, defaultValue, 0x100 /*KEY_WOW64_64KEY*/);
}
bool WindowsRegistry::valueExistsWow64 (const String& regValuePath)
{
return RegistryKeyWrapper::valueExists (regValuePath, 0x100 /*KEY_WOW64_64KEY*/);
}
bool WindowsRegistry::setValue (const String& regValuePath, const String& value)
{
return RegistryKeyWrapper::setValue (regValuePath, REG_SZ, value.toWideCharPointer(),
CharPointer_UTF16::getBytesRequiredFor (value.getCharPointer()));
}
bool WindowsRegistry::setValue (const String& regValuePath, const std::uint32_t value)
{
return RegistryKeyWrapper::setValue (regValuePath, REG_DWORD, &value, sizeof (value));
}
bool WindowsRegistry::setValue (const String& regValuePath, const std::uint64_t value)
{
return RegistryKeyWrapper::setValue (regValuePath, REG_QWORD, &value, sizeof (value));
}
bool WindowsRegistry::setValue (const String& regValuePath, const MemoryBlock& value)
{
return RegistryKeyWrapper::setValue (regValuePath, REG_BINARY, value.getData(), value.getSize());
}
bool WindowsRegistry::valueExists (const String& regValuePath)
{
return RegistryKeyWrapper::valueExists (regValuePath, 0);
}
void WindowsRegistry::deleteValue (const String& regValuePath)
{
const RegistryKeyWrapper key (regValuePath, true, 0);
if (key.key != 0)
RegDeleteValue (key.key, key.wideCharValueName);
}
void WindowsRegistry::deleteKey (const String& regKeyPath)
{
const RegistryKeyWrapper key (regKeyPath, true, 0);
if (key.key != 0)
RegDeleteKey (key.key, key.wideCharValueName);
}
bool WindowsRegistry::registerFileAssociation (const String& fileExtension,
const String& symbolicDescription,
const String& fullDescription,
const File& targetExecutable,
const int iconResourceNumber,
const bool registerForCurrentUserOnly)
{
const char* const root = registerForCurrentUserOnly ? "HKEY_CURRENT_USER\\Software\\Classes\\"
: "HKEY_CLASSES_ROOT\\";
const String key (root + symbolicDescription);
return setValue (root + fileExtension + "\\", symbolicDescription)
&& setValue (key + "\\", fullDescription)
&& setValue (key + "\\shell\\open\\command\\", targetExecutable.getFullPathName() + " \"%1\"")
&& (iconResourceNumber == 0
|| setValue (key + "\\DefaultIcon\\",
targetExecutable.getFullPathName() + "," + String (-iconResourceNumber)));
}
} // beast

View File

@@ -24,200 +24,9 @@
namespace beast namespace beast
{ {
void Logger::outputDebugString (const String& text) void outputDebugString (std::string const& text)
{ {
OutputDebugString ((text + "\n").toWideCharPointer()); OutputDebugStringA ((text + "\n").c_str ());
}
//==============================================================================
#ifdef BEAST_DLL_BUILD
void* beastDLL_malloc (size_t sz) { return std::malloc (sz); }
void beastDLL_free (void* block) { std::free (block); }
#endif
//==============================================================================
#if BEAST_USE_INTRINSICS
// CPU info functions using intrinsics...
#pragma intrinsic (__cpuid)
#pragma intrinsic (__rdtsc)
String SystemStats::getCpuVendor()
{
int info [4];
__cpuid (info, 0);
char v [12];
memcpy (v, info + 1, 4);
memcpy (v + 4, info + 3, 4);
memcpy (v + 8, info + 2, 4);
return String (v, 12);
}
#else
//==============================================================================
// CPU info functions using old fashioned inline asm...
static void beast_getCpuVendor (char* const v)
{
int vendor[4] = { 0 };
#if ! BEAST_MINGW
__try
#endif
{
#if BEAST_GCC
unsigned int dummy = 0;
__asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0));
#else
__asm
{
mov eax, 0
cpuid
mov [vendor], ebx
mov [vendor + 4], edx
mov [vendor + 8], ecx
}
#endif
}
#if ! BEAST_MINGW
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
#endif
memcpy (v, vendor, 16);
}
String SystemStats::getCpuVendor()
{
char v [16];
beast_getCpuVendor (v);
return String (v, 16);
}
#endif
//==============================================================================
void CPUInformation::initialise() noexcept
{
hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0;
hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0;
hasSSE3 = IsProcessorFeaturePresent (13 /*PF_SSE3_INSTRUCTIONS_AVAILABLE*/) != 0;
has3DNow = IsProcessorFeaturePresent (7 /*PF_AMD3D_INSTRUCTIONS_AVAILABLE*/) != 0;
}
//==============================================================================
static bool isWindowsVersionOrLater (SystemStats::OperatingSystemType target)
{
OSVERSIONINFOEX info;
zerostruct (info);
info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
if (target >= SystemStats::WinVista)
{
info.dwMajorVersion = 6;
switch (target)
{
case SystemStats::WinVista: info.dwMinorVersion = 0; break;
case SystemStats::Windows7: info.dwMinorVersion = 1; break;
case SystemStats::Windows8: info.dwMinorVersion = 2; break;
default: bassertfalse; break;
}
}
else
{
info.dwMajorVersion = 5;
info.dwMinorVersion = target >= SystemStats::WinXP ? 1 : 0;
}
DWORDLONG mask = 0;
VER_SET_CONDITION (mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION (mask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION (mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
VER_SET_CONDITION (mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
return VerifyVersionInfo (&info,
VER_MAJORVERSION | VER_MINORVERSION
| VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
mask) != FALSE;
}
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
{
const SystemStats::OperatingSystemType types[]
= { Windows8, Windows7, WinVista, WinXP, Win2000 };
for (int i = 0; i < numElementsInArray (types); ++i)
if (isWindowsVersionOrLater (types[i]))
return types[i];
bassertfalse; // need to support whatever new version is running!
return UnknownOS;
}
String SystemStats::getOperatingSystemName()
{
const char* name = "Unknown OS";
switch (getOperatingSystemType())
{
case Windows7: name = "Windows 7"; break;
case Windows8: name = "Windows 8"; break;
case WinVista: name = "Windows Vista"; break;
case WinXP: name = "Windows XP"; break;
case Win2000: name = "Windows 2000"; break;
default: bassertfalse; break; // !! new type of OS?
}
return name;
}
bool SystemStats::isOperatingSystem64Bit()
{
#if BEAST_64BIT
return true;
#else
typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process
= (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandleA ("kernel32"), "IsWow64Process");
BOOL isWow64 = FALSE;
return fnIsWow64Process != nullptr
&& fnIsWow64Process (GetCurrentProcess(), &isWow64)
&& isWow64 != FALSE;
#endif
}
//==============================================================================
int SystemStats::getMemorySizeInMegabytes()
{
MEMORYSTATUSEX mem;
mem.dwLength = sizeof (mem);
GlobalMemoryStatusEx (&mem);
return (int) (mem.ullTotalPhys / (1024 * 1024)) + 1;
}
//==============================================================================
String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
{
DWORD len = GetEnvironmentVariableW (name.toWideCharPointer(), nullptr, 0);
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
return String (defaultValue);
HeapBlock<WCHAR> buffer (len);
len = GetEnvironmentVariableW (name.toWideCharPointer(), buffer, len);
return String (CharPointer_wchar_t (buffer),
CharPointer_wchar_t (buffer + len));
} }
//============================================================================== //==============================================================================
@@ -251,9 +60,12 @@ public:
const std::int64_t mainCounterAsHiResTicks = (beast_millisecondsSinceStartup() * hiResTicksPerSecond) / 1000; const std::int64_t mainCounterAsHiResTicks = (beast_millisecondsSinceStartup() * hiResTicksPerSecond) / 1000;
const std::int64_t newOffset = mainCounterAsHiResTicks - ticks.QuadPart; const std::int64_t newOffset = mainCounterAsHiResTicks - ticks.QuadPart;
std::int64_t offsetDrift = newOffset - hiResTicksOffset;
// fix for a very obscure PCI hardware bug that can make the counter // fix for a very obscure PCI hardware bug that can make the counter
// sometimes jump forwards by a few seconds.. // sometimes jump forwards by a few seconds..
const std::int64_t offsetDrift = abs64 (newOffset - hiResTicksOffset); if (offsetDrift < 0)
offsetDrift = -offsetDrift;
if (offsetDrift > (hiResTicksPerSecond >> 1)) if (offsetDrift > (hiResTicksPerSecond >> 1))
hiResTicksOffset = newOffset; hiResTicksOffset = newOffset;
@@ -277,120 +89,13 @@ std::int64_t Time::getHighResolutionTicks() noexcept { return hiResCo
double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHandler.getMillisecondCounterHiRes(); } double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHandler.getMillisecondCounterHiRes(); }
//============================================================================== //==============================================================================
static std::int64_t beast_getClockCycleCounter() noexcept std::string SystemStats::getComputerName()
{ {
#if BEAST_USE_INTRINSICS char text [MAX_COMPUTERNAME_LENGTH + 2] = { 0 };
// MS intrinsics version... DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
return (std::int64_t) __rdtsc(); if (!GetComputerNameA (text, &len))
text[0] = 0;
#elif BEAST_GCC return text;
// GNU inline asm version...
unsigned int hi = 0, lo = 0;
__asm__ __volatile__ (
"xor %%eax, %%eax \n\
xor %%edx, %%edx \n\
rdtsc \n\
movl %%eax, %[lo] \n\
movl %%edx, %[hi]"
:
: [hi] "m" (hi),
[lo] "m" (lo)
: "cc", "eax", "ebx", "ecx", "edx", "memory");
return (std::int64_t) ((((std::uint64_t) hi) << 32) | lo);
#else
// MSVC inline asm version...
unsigned int hi = 0, lo = 0;
__asm
{
xor eax, eax
xor edx, edx
rdtsc
mov lo, eax
mov hi, edx
}
return (std::int64_t) ((((std::uint64_t) hi) << 32) | lo);
#endif
}
int SystemStats::getCpuSpeedInMegaherz()
{
const std::int64_t cycles = beast_getClockCycleCounter();
const std::uint32_t millis = Time::getMillisecondCounter();
int lastResult = 0;
for (;;)
{
int n = 1000000;
while (--n > 0) {}
const std::uint32_t millisElapsed = Time::getMillisecondCounter() - millis;
const std::int64_t cyclesNow = beast_getClockCycleCounter();
if (millisElapsed > 80)
{
const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000);
if (millisElapsed > 500 || (lastResult == newResult && newResult > 100))
return newResult;
lastResult = newResult;
}
}
}
//==============================================================================
bool Time::setSystemTimeToThisTime() const
{
SYSTEMTIME st;
st.wDayOfWeek = 0;
st.wYear = (WORD) getYear();
st.wMonth = (WORD) (getMonth() + 1);
st.wDay = (WORD) getDayOfMonth();
st.wHour = (WORD) getHours();
st.wMinute = (WORD) getMinutes();
st.wSecond = (WORD) getSeconds();
st.wMilliseconds = (WORD) (millisSinceEpoch % 1000);
// do this twice because of daylight saving conversion problems - the
// first one sets it up, the second one kicks it in.
return SetLocalTime (&st) != 0
&& SetLocalTime (&st) != 0;
}
int SystemStats::getPageSize()
{
SYSTEM_INFO systemInfo;
GetNativeSystemInfo (&systemInfo);
return (int) systemInfo.dwPageSize;
}
//==============================================================================
String SystemStats::getLogonName()
{
TCHAR text [256] = { 0 };
DWORD len = (DWORD) numElementsInArray (text) - 1;
GetUserName (text, &len);
return String (text, len);
}
String SystemStats::getFullUserName()
{
return getLogonName();
}
String SystemStats::getComputerName()
{
TCHAR text [MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
DWORD len = (DWORD) numElementsInArray (text) - 1;
GetComputerName (text, &len);
return String (text, len);
} }
} // beast } // beast

View File

@@ -56,14 +56,17 @@ __int64 beast_InterlockedCompareExchange64 (volatile __int64* value, __int64 new
//============================================================================== //==============================================================================
CriticalSection::CriticalSection() noexcept CriticalSection::CriticalSection() noexcept
{ {
// (just to check the MS haven't changed this structure and broken things...) // (just to check the MS haven't changed this structure and broken things...)
#if BEAST_VC7_OR_EARLIER #if BEAST_VC7_OR_EARLIER
static_bassert (sizeof (CRITICAL_SECTION) <= 24); static_assert (sizeof (CRITICAL_SECTION) <= 24,
#else "The size of the CRITICAL_SECTION structure is less not what we expected.");
static_bassert (sizeof (CRITICAL_SECTION) <= sizeof (section)); #else
#endif static_assert (sizeof (CRITICAL_SECTION) <= sizeof (CriticalSection::section),
"The size of the CRITICAL_SECTION structure is less not what we expected.");
#endif
InitializeCriticalSection ((CRITICAL_SECTION*) section); InitializeCriticalSection ((CRITICAL_SECTION*) section);
} }
@@ -74,38 +77,6 @@ bool CriticalSection::tryEnter() const noexcept { return TryEnterCriticalSection
void CriticalSection::exit() const noexcept { LeaveCriticalSection ((CRITICAL_SECTION*) section); } void CriticalSection::exit() const noexcept { LeaveCriticalSection ((CRITICAL_SECTION*) section); }
//============================================================================== //==============================================================================
static int lastProcessPriority = -1;
// called by WindowDriver because Windows does weird things to process priority
// when you swap apps, and this forces an update when the app is brought to the front.
void beast_repeatLastProcessPriority()
{
if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..)
{
DWORD p;
switch (lastProcessPriority)
{
case Process::LowPriority: p = IDLE_PRIORITY_CLASS; break;
case Process::NormalPriority: p = NORMAL_PRIORITY_CLASS; break;
case Process::HighPriority: p = HIGH_PRIORITY_CLASS; break;
case Process::RealtimePriority: p = REALTIME_PRIORITY_CLASS; break;
default: bassertfalse; return; // bad priority value
}
SetPriorityClass (GetCurrentProcess(), p);
}
}
void Process::setPriority (ProcessPriority prior)
{
if (lastProcessPriority != (int) prior)
{
lastProcessPriority = (int) prior;
beast_repeatLastProcessPriority();
}
}
bool beast_isRunningUnderDebugger() bool beast_isRunningUnderDebugger()
{ {
return IsDebuggerPresent() != FALSE; return IsDebuggerPresent() != FALSE;
@@ -117,32 +88,6 @@ bool Process::isRunningUnderDebugger()
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void* currentModuleHandle = nullptr;
void* Process::getCurrentModuleInstanceHandle() noexcept
{
if (currentModuleHandle == nullptr)
currentModuleHandle = GetModuleHandleA (nullptr);
return currentModuleHandle;
}
void Process::setCurrentModuleInstanceHandle (void* const newHandle) noexcept
{
currentModuleHandle = newHandle;
}
void Process::raisePrivilege()
{
bassertfalse; // xxx not implemented
}
void Process::lowerPrivilege()
{
bassertfalse; // xxx not implemented
}
void Process::terminate() void Process::terminate()
{ {
#if BEAST_MSVC && BEAST_CHECK_MEMORY_LEAKS #if BEAST_MSVC && BEAST_CHECK_MEMORY_LEAKS
@@ -153,37 +98,6 @@ void Process::terminate()
ExitProcess (0); ExitProcess (0);
} }
bool beast_isRunningInWine()
{
HMODULE ntdll = GetModuleHandleA ("ntdll");
return ntdll != 0 && GetProcAddress (ntdll, "wine_get_version") != nullptr;
}
//==============================================================================
bool DynamicLibrary::open (const String& name)
{
close();
handle = LoadLibrary (name.toWideCharPointer());
return handle != nullptr;
}
void DynamicLibrary::close()
{
if (handle != nullptr)
{
FreeLibrary ((HMODULE) handle);
handle = nullptr;
}
}
void* DynamicLibrary::getFunction (const String& functionName) noexcept
{
return handle != nullptr ? (void*) GetProcAddress ((HMODULE) handle, functionName.toUTF8()) // (void* cast is required for mingw)
: nullptr;
}
//============================================================================== //==============================================================================
} // beast } // beast

View File

@@ -68,7 +68,8 @@ short InputStream::readShortBigEndian()
int InputStream::readInt() int InputStream::readInt()
{ {
static_bassert (sizeof (int) == 4); static_assert (sizeof (int) == 4,
"The size of an integer must be exactly 4 bytes");
char temp[4]; char temp[4];
@@ -153,7 +154,9 @@ std::int64_t InputStream::readInt64BigEndian()
float InputStream::readFloat() float InputStream::readFloat()
{ {
// the union below relies on these types being the same size... // the union below relies on these types being the same size...
static_bassert (sizeof (std::int32_t) == sizeof (float)); static_assert (sizeof (std::int32_t) == sizeof (float),
"The size of a float must be equal to the size of an std::int32_t");
union { std::int32_t asInt; float asFloat; } n; union { std::int32_t asInt; float asFloat; } n;
n.asInt = (std::int32_t) readInt(); n.asInt = (std::int32_t) readInt();
return n.asFloat; return n.asFloat;
@@ -248,11 +251,11 @@ void InputStream::skipNextBytes (std::int64_t numBytesToSkip)
{ {
if (numBytesToSkip > 0) if (numBytesToSkip > 0)
{ {
const int skipBufferSize = (int) bmin (numBytesToSkip, (std::int64_t) 16384); const int skipBufferSize = (int) std::min (numBytesToSkip, (std::int64_t) 16384);
HeapBlock<char> temp ((size_t) skipBufferSize); HeapBlock<char> temp ((size_t) skipBufferSize);
while (numBytesToSkip > 0 && ! isExhausted()) while (numBytesToSkip > 0 && ! isExhausted())
numBytesToSkip -= read (temp, (int) bmin (numBytesToSkip, (std::int64_t) skipBufferSize)); numBytesToSkip -= read (temp, (int) std::min (numBytesToSkip, (std::int64_t) skipBufferSize));
} }
} }

View File

@@ -21,6 +21,8 @@
*/ */
//============================================================================== //==============================================================================
#include <algorithm>
namespace beast namespace beast
{ {
@@ -85,7 +87,7 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
if (blockToUse != nullptr) if (blockToUse != nullptr)
{ {
if (storageNeeded >= blockToUse->getSize()) if (storageNeeded >= blockToUse->getSize())
blockToUse->ensureSize ((storageNeeded + bmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u); blockToUse->ensureSize ((storageNeeded + std::min (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
data = static_cast <char*> (blockToUse->getData()); data = static_cast <char*> (blockToUse->getData());
} }
@@ -99,7 +101,7 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
char* const writePointer = data + position; char* const writePointer = data + position;
position += numBytes; position += numBytes;
size = bmax (size, position); size = std::max (size, position);
return writePointer; return writePointer;
} }

View File

@@ -21,6 +21,8 @@
*/ */
//============================================================================== //==============================================================================
#include <algorithm>
namespace beast namespace beast
{ {
@@ -98,7 +100,8 @@ bool OutputStream::writeShortBigEndian (short value)
bool OutputStream::writeInt32 (std::int32_t value) bool OutputStream::writeInt32 (std::int32_t value)
{ {
static_bassert (sizeof (std::int32_t) == 4); static_assert (sizeof (std::int32_t) == 4,
"The size of an integer must be exactly 4 bytes.");
const unsigned int v = ByteOrder::swapIfBigEndian ((std::uint32_t) value); const unsigned int v = ByteOrder::swapIfBigEndian ((std::uint32_t) value);
return write (&v, 4); return write (&v, 4);
@@ -106,7 +109,8 @@ bool OutputStream::writeInt32 (std::int32_t value)
bool OutputStream::writeInt (int value) bool OutputStream::writeInt (int value)
{ {
static_bassert (sizeof (int) == 4); static_assert (sizeof (int) == 4,
"The size of an integer must be exactly 4 bytes.");
const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value); const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value);
return write (&v, 4); return write (&v, 4);
@@ -114,14 +118,16 @@ bool OutputStream::writeInt (int value)
bool OutputStream::writeInt32BigEndian (int value) bool OutputStream::writeInt32BigEndian (int value)
{ {
static_bassert (sizeof (std::int32_t) == 4); static_assert (sizeof (std::int32_t) == 4,
"The size of an integer must be exactly 4 bytes.");
const std::uint32_t v = ByteOrder::swapIfLittleEndian ((std::uint32_t) value); const std::uint32_t v = ByteOrder::swapIfLittleEndian ((std::uint32_t) value);
return write (&v, 4); return write (&v, 4);
} }
bool OutputStream::writeIntBigEndian (int value) bool OutputStream::writeIntBigEndian (int value)
{ {
static_bassert (sizeof (int) == 4); static_assert (sizeof (int) == 4,
"The size of an integer must be exactly 4 bytes.");
const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value); const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value);
return write (&v, 4); return write (&v, 4);
} }
@@ -274,7 +280,7 @@ int OutputStream::writeFromInputStream (InputStream& source, std::int64_t numByt
while (numBytesToWrite > 0) while (numBytesToWrite > 0)
{ {
char buffer [8192]; char buffer [8192];
const int num = source.read (buffer, (int) bmin (numBytesToWrite, (std::int64_t) sizeof (buffer))); const int num = source.read (buffer, (int) std::min (numBytesToWrite, (std::int64_t) sizeof (buffer)));
if (num <= 0) if (num <= 0)
break; break;

View File

@@ -21,59 +21,37 @@
*/ */
//============================================================================== //==============================================================================
// Some basic tests, to keep an eye on things and make sure these types work ok
// on all platforms.
static_assert (sizeof (std::intptr_t) == sizeof (void*), "std::intptr_t must be the same size as void*");
static_assert (sizeof (std::int8_t) == 1, "std::int8_t must be exactly 1 byte!");
static_assert (sizeof (std::int16_t) == 2, "std::int16_t must be exactly 2 bytes!");
static_assert (sizeof (std::int32_t) == 4, "std::int32_t must be exactly 4 bytes!");
static_assert (sizeof (std::int64_t) == 8, "std::int64_t must be exactly 8 bytes!");
static_assert (sizeof (std::uint8_t) == 1, "std::uint8_t must be exactly 1 byte!");
static_assert (sizeof (std::uint16_t) == 2, "std::uint16_t must be exactly 2 bytes!");
static_assert (sizeof (std::uint32_t) == 4, "std::uint32_t must be exactly 4 bytes!");
static_assert (sizeof (std::uint64_t) == 8, "std::uint64_t must be exactly 8 bytes!");
namespace beast namespace beast
{ {
String SystemStats::getBeastVersion() std::string
SystemStats::getBeastVersion()
{ {
// Some basic tests, to keep an eye on things and make sure these types work ok return "Beast v" + std::to_string (BEAST_MAJOR_VERSION) +
// on all platforms. Let me know if any of these assertions fail on your system! "." + std::to_string (BEAST_MINOR_VERSION) +
static_bassert (sizeof (std::intptr_t) == sizeof (void*)); "." + std::to_string (BEAST_BUILDNUMBER);
static_bassert (sizeof (std::int8_t) == 1);
static_bassert (sizeof (std::uint8_t) == 1);
static_bassert (sizeof (std::int16_t) == 2);
static_bassert (sizeof (std::uint16_t) == 2);
static_bassert (sizeof (std::int32_t) == 4);
static_bassert (sizeof (std::uint32_t) == 4);
static_bassert (sizeof (std::int64_t) == 8);
static_bassert (sizeof (std::uint64_t) == 8);
return "Beast v" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
"." BEAST_STRINGIFY(BEAST_MINOR_VERSION)
"." BEAST_STRINGIFY(BEAST_BUILDNUMBER);
} }
//============================================================================== //==============================================================================
struct CPUInformation std::string
SystemStats::getStackBacktrace()
{ {
CPUInformation() noexcept std::string result;
: hasMMX (false), hasSSE (false),
hasSSE2 (false), hasSSE3 (false), has3DNow (false)
{
initialise();
}
void initialise() noexcept;
bool hasMMX, hasSSE, hasSSE2, hasSSE3, has3DNow;
};
static const CPUInformation& getCPUInformation() noexcept
{
static CPUInformation info;
return info;
}
bool SystemStats::hasMMX() noexcept { return getCPUInformation().hasMMX; }
bool SystemStats::hasSSE() noexcept { return getCPUInformation().hasSSE; }
bool SystemStats::hasSSE2() noexcept { return getCPUInformation().hasSSE2; }
bool SystemStats::hasSSE3() noexcept { return getCPUInformation().hasSSE3; }
bool SystemStats::has3DNow() noexcept { return getCPUInformation().has3DNow; }
//==============================================================================
String SystemStats::getStackBacktrace()
{
String result;
#if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD #if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD
bassertfalse; // sorry, not implemented yet! bassertfalse; // sorry, not implemented yet!
@@ -96,16 +74,27 @@ String SystemStats::getStackBacktrace()
if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol)) if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol))
{ {
result << i << ": "; result.append (std::to_string (i) + ": ");
IMAGEHLP_MODULE64 moduleInfo; IMAGEHLP_MODULE64 moduleInfo;
zerostruct (moduleInfo); zerostruct (moduleInfo);
moduleInfo.SizeOfStruct = sizeof (moduleInfo); moduleInfo.SizeOfStruct = sizeof (moduleInfo);
if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo)) if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
result << moduleInfo.ModuleName << ": "; {
result.append (moduleInfo.ModuleName);
result.append (": ");
}
result << symbol->Name << " + 0x" << String::toHexString ((std::int64_t) displacement) << newLine; result.append (symbol->Name);
if (displacement)
{
result.append ("+");
result.append (std::to_string (displacement));
}
result.append ("\r\n");
} }
} }
@@ -115,7 +104,10 @@ String SystemStats::getStackBacktrace()
char** frameStrings = backtrace_symbols (stack, frames); char** frameStrings = backtrace_symbols (stack, frames);
for (int i = 0; i < frames; ++i) for (int i = 0; i < frames; ++i)
result << frameStrings[i] << newLine; {
result.append (frameStrings[i]);
result.append ("\n");
}
::free (frameStrings); ::free (frameStrings);
#endif #endif

View File

@@ -37,112 +37,18 @@ namespace SystemStats
/** Returns the current version of BEAST, /** Returns the current version of BEAST,
See also the BEAST_VERSION, BEAST_MAJOR_VERSION and BEAST_MINOR_VERSION macros. See also the BEAST_VERSION, BEAST_MAJOR_VERSION and BEAST_MINOR_VERSION macros.
*/ */
String getBeastVersion(); std::string getBeastVersion();
//============================================================================== //==============================================================================
/** The set of possible results of the getOperatingSystemType() method. */
enum OperatingSystemType
{
UnknownOS = 0,
MacOSX_10_4 = 0x1004,
MacOSX_10_5 = 0x1005,
MacOSX_10_6 = 0x1006,
MacOSX_10_7 = 0x1007,
MacOSX_10_8 = 0x1008,
Linux = 0x2000,
FreeBSD = 0x2001,
Android = 0x3000,
Win2000 = 0x4105,
WinXP = 0x4106,
WinVista = 0x4107,
Windows7 = 0x4108,
Windows8 = 0x4109,
Windows = 0x4000, /**< To test whether any version of Windows is running,
you can use the expression ((getOperatingSystemType() & Windows) != 0). */
iOS = 0x8000
};
/** Returns the type of operating system we're running on.
@returns one of the values from the OperatingSystemType enum.
@see getOperatingSystemName
*/
OperatingSystemType getOperatingSystemType();
/** Returns the name of the type of operating system we're running on.
@returns a string describing the OS type.
@see getOperatingSystemType
*/
String getOperatingSystemName();
/** Returns true if the OS is 64-bit, or false for a 32-bit OS.
*/
bool isOperatingSystem64Bit();
/** Returns an environment variable.
If the named value isn't set, this will return the defaultValue string instead.
*/
String getEnvironmentVariable (const String& name, const String& defaultValue);
//==============================================================================
/** Returns the current user's name, if available.
@see getFullUserName()
*/
String getLogonName();
/** Returns the current user's full name, if available.
On some OSes, this may just return the same value as getLogonName().
@see getLogonName()
*/
String getFullUserName();
/** Returns the host-name of the computer. */ /** Returns the host-name of the computer. */
String getComputerName(); std::string getComputerName();
//==============================================================================
// CPU and memory information..
/** Returns the approximate CPU speed.
@returns the speed in megahertz, e.g. 1500, 2500, 32000 (depending on
what year you're reading this...)
*/
int getCpuSpeedInMegaherz();
/** Returns a string to indicate the CPU vendor.
Might not be known on some systems.
*/
String getCpuVendor();
bool hasMMX() noexcept; /**< Returns true if Intel MMX instructions are available. */
bool hasSSE() noexcept; /**< Returns true if Intel SSE instructions are available. */
bool hasSSE2() noexcept; /**< Returns true if Intel SSE2 instructions are available. */
bool hasSSE3() noexcept; /**< Returns true if Intel SSE2 instructions are available. */
bool has3DNow() noexcept; /**< Returns true if AMD 3DNOW instructions are available. */
//==============================================================================
/** Finds out how much RAM is in the machine.
@returns the approximate number of megabytes of memory, or zero if
something goes wrong when finding out.
*/
int getMemorySizeInMegabytes();
/** Returns the system page-size.
This is only used by programmers with beards.
*/
int getPageSize();
//============================================================================== //==============================================================================
/** Returns a backtrace of the current call-stack. /** Returns a backtrace of the current call-stack.
The usefulness of the result will depend on the level of debug symbols The usefulness of the result will depend on the level of debug symbols
that are available in the executable. that are available in the executable.
*/ */
String getStackBacktrace(); std::string getStackBacktrace();
/** A void() function type, used by setApplicationCrashHandler(). */ /** A void() function type, used by setApplicationCrashHandler(). */
typedef void (*CrashHandlerFunction)(); typedef void (*CrashHandlerFunction)();

View File

@@ -21,6 +21,8 @@
*/ */
//============================================================================== //==============================================================================
#include <algorithm>
namespace beast namespace beast
{ {
@@ -321,7 +323,7 @@ void StringArray::move (const int currentIndex, int newIndex) noexcept
String StringArray::joinIntoString (const String& separator, int start, int numberToJoin) const String StringArray::joinIntoString (const String& separator, int start, int numberToJoin) const
{ {
const int last = (numberToJoin < 0) ? size() const int last = (numberToJoin < 0) ? size()
: bmin (size(), start + numberToJoin); : std::min (size(), start + numberToJoin);
if (start < 0) if (start < 0)
start = 0; start = 0;

View File

@@ -21,12 +21,18 @@
namespace beast { namespace beast {
Workers::Workers (Callback& callback, String const& threadNames, int numberOfThreads) Workers::Workers (
: m_callback (callback) Callback& callback,
, m_threadNames (threadNames) std::string const& threadNames,
, m_allPaused (true, true) int numberOfThreads)
, m_semaphore (0) : m_callback (callback)
, m_numberOfThreads (0) , m_threadNames (threadNames)
, m_allPaused (true, true)
, m_semaphore (0)
, m_numberOfThreads (0)
, m_activeCount (0)
, m_pauseCount (0)
, m_runningTaskCount (0)
{ {
setNumberOfThreads (numberOfThreads); setNumberOfThreads (numberOfThreads);
} }
@@ -112,7 +118,7 @@ void Workers::addTask ()
int Workers::numberOfCurrentlyRunningTasks () const noexcept int Workers::numberOfCurrentlyRunningTasks () const noexcept
{ {
return m_runningTaskCount.get (); return m_runningTaskCount.load ();
} }
void Workers::deleteWorkers (LockFreeStack <Worker>& stack) void Workers::deleteWorkers (LockFreeStack <Worker>& stack)
@@ -166,7 +172,7 @@ void Workers::Worker::run ()
// See if there's a pause request. This // See if there's a pause request. This
// counts as an "internal task." // counts as an "internal task."
// //
int pauseCount = m_workers.m_pauseCount.get (); int pauseCount = m_workers.m_pauseCount.load ();
if (pauseCount > 0) if (pauseCount > 0)
{ {
@@ -242,7 +248,7 @@ public:
} }
WaitableEvent finished; WaitableEvent finished;
Atomic <int> count; std::atomic <int> count;
}; };
template <class T1, class T2> template <class T1, class T2>
@@ -254,10 +260,7 @@ public:
void testThreads (int const threadCount) void testThreads (int const threadCount)
{ {
std::stringstream ss; testcase ("threadCount = " + std::to_string (threadCount));
ss <<
"threadCount = " << threadCount;
testcase (ss.str());
TestCallback cb (threadCount); TestCallback cb (threadCount);
@@ -278,7 +281,7 @@ public:
w.pauseAllThreadsAndWait (); w.pauseAllThreadsAndWait ();
int const count (cb.count.get ()); int const count (cb.count.load ());
expectEquals (count, 0); expectEquals (count, 0);
} }

View File

@@ -20,10 +20,11 @@
#ifndef BEAST_WORKERS_H_INCLUDED #ifndef BEAST_WORKERS_H_INCLUDED
#define BEAST_WORKERS_H_INCLUDED #define BEAST_WORKERS_H_INCLUDED
#include <beast/module/core/system/SystemStats.h>
#include <beast/threads/Thread.h> #include <beast/threads/Thread.h>
#include <beast/threads/semaphore.h> #include <beast/threads/semaphore.h>
#include <atomic>
#include <string>
#include <thread> #include <thread>
namespace beast { namespace beast {
@@ -55,7 +56,7 @@ public:
@param threadNames The name given to each created worker thread. @param threadNames The name given to each created worker thread.
*/ */
explicit Workers (Callback& callback, explicit Workers (Callback& callback,
String const& threadNames = "Worker", std::string const& threadNames = "Worker",
int numberOfThreads = int numberOfThreads =
static_cast<int>(std::thread::hardware_concurrency())); static_cast<int>(std::thread::hardware_concurrency()));
@@ -141,9 +142,9 @@ private:
WaitableEvent m_allPaused; // signaled when all threads paused WaitableEvent m_allPaused; // signaled when all threads paused
semaphore m_semaphore; // each pending task is 1 resource semaphore m_semaphore; // each pending task is 1 resource
int m_numberOfThreads; // how many we want active now int m_numberOfThreads; // how many we want active now
Atomic <int> m_activeCount; // to know when all are paused std::atomic <int> m_activeCount; // to know when all are paused
Atomic <int> m_pauseCount; // how many threads need to pause now std::atomic <int> m_pauseCount; // how many threads need to pause now
Atomic <int> m_runningTaskCount; // how many calls to processTask() active std::atomic <int> m_runningTaskCount; // how many calls to processTask() active
LockFreeStack <Worker> m_everyone; // holds all created workers LockFreeStack <Worker> m_everyone; // holds all created workers
LockFreeStack <Worker, PausedTag> m_paused; // holds just paused workers LockFreeStack <Worker, PausedTag> m_paused; // holds just paused workers
}; };

View File

@@ -1,85 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_DYNAMICLIBRARY_H_INCLUDED
#define BEAST_DYNAMICLIBRARY_H_INCLUDED
namespace beast
{
/**
Handles the opening and closing of DLLs.
This class can be used to open a DLL and get some function pointers from it.
Since the DLL is freed when this object is deleted, it's handy for managing
library lifetimes using RAII.
*/
class DynamicLibrary : LeakChecked <DynamicLibrary>
{
public:
/** Creates an unopened DynamicLibrary object.
Call open() to actually open one.
*/
DynamicLibrary() noexcept : handle (nullptr) {}
/**
*/
DynamicLibrary (const String& name) : handle (nullptr) { open (name); }
DynamicLibrary (DynamicLibrary const&) = delete;
DynamicLibrary& operator= (DynamicLibrary const&) = delete;
/** Destructor.
If a library is currently open, it will be closed when this object is destroyed.
*/
~DynamicLibrary() { close(); }
/** Opens a DLL.
The name and the method by which it gets found is of course platform-specific, and
may or may not include a path, depending on the OS.
If a library is already open when this method is called, it will first close the library
before attempting to load the new one.
@returns true if the library was successfully found and opened.
*/
bool open (const String& name);
/** Releases the currently-open DLL, or has no effect if none was open. */
void close();
/** Tries to find a named function in the currently-open DLL, and returns a pointer to it.
If no library is open, or if the function isn't found, this will return a null pointer.
*/
void* getFunction (const String& functionName) noexcept;
/** Returns the platform-specific native library handle.
You'll need to cast this to whatever is appropriate for the OS that's in use.
*/
void* getNativeHandle() const noexcept { return handle; }
private:
void* handle;
};
} // beast
#endif // BEAST_DYNAMICLIBRARY_H_INCLUDED

View File

@@ -36,22 +36,6 @@ namespace beast {
*/ */
namespace Process namespace Process
{ {
//==============================================================================
enum ProcessPriority
{
LowPriority = 0,
NormalPriority = 1,
HighPriority = 2,
RealtimePriority = 3
};
/** Changes the current process's priority.
@param priority the process priority, where
0=low, 1=normal, 2=high, 3=realtime
*/
void setPriority (const ProcessPriority priority);
/** Kills the current process immediately. /** Kills the current process immediately.
This is an emergency process terminator that kills the application This is an emergency process terminator that kills the application
@@ -63,70 +47,8 @@ namespace Process
void terminate(); void terminate();
//============================================================================== //==============================================================================
/** Returns true if this application process is the one that the user is
currently using.
*/
bool isForegroundProcess();
/** Attempts to make the current process the active one.
(This is not possible on some platforms).
*/
void makeForegroundProcess();
//==============================================================================
/** Raises the current process's privilege level.
Does nothing if this isn't supported by the current OS, or if process
privilege level is fixed.
*/
void raisePrivilege();
/** Lowers the current process's privilege level.
Does nothing if this isn't supported by the current OS, or if process
privilege level is fixed.
*/
void lowerPrivilege();
/** Returns true if this process is being hosted by a debugger. */ /** Returns true if this process is being hosted by a debugger. */
bool isRunningUnderDebugger(); bool isRunningUnderDebugger();
//==============================================================================
/** Tries to launch the OS's default reader application for a given file or URL. */
bool openDocument (const String& documentURL, const String& parameters);
#if BEAST_WINDOWS || DOXYGEN
//==============================================================================
/** WINDOWS ONLY - This returns the HINSTANCE of the current module.
The return type is a void* to avoid being dependent on windows.h - just cast
it to a HINSTANCE to use it.
In a normal BEAST application, this will be automatically set to the module
handle of the executable.
If you've built a DLL and plan to use any BEAST messaging or windowing classes,
you'll need to make sure you call the setCurrentModuleInstanceHandle()
to provide the correct module handle in your DllMain() function, because
the system relies on the correct instance handle when opening windows.
*/
void* getCurrentModuleInstanceHandle() noexcept;
/** WINDOWS ONLY - Sets a new module handle to be used by the library.
The parameter type is a void* to avoid being dependent on windows.h, but it actually
expects a HINSTANCE value.
@see getCurrentModuleInstanceHandle()
*/
void setCurrentModuleInstanceHandle (void* newHandle) noexcept;
#endif
#if BEAST_MAC || DOXYGEN
//==============================================================================
/** OSX ONLY - Shows or hides the OSX dock icon for this app. */
void setDockIconVisible (bool isVisible);
#endif
}; };
} // beast } // beast

View File

@@ -21,6 +21,9 @@
*/ */
//============================================================================== //==============================================================================
#include <algorithm>
#include <thread>
namespace beast namespace beast
{ {
@@ -257,14 +260,14 @@ void Time::waitForMillisecondCounter (const std::uint32_t targetTime) noexcept
if (toWait > 2) if (toWait > 2)
{ {
Thread::sleep (bmin (20, toWait >> 1)); Thread::sleep (std::min (20, toWait >> 1));
} }
else else
{ {
// xxx should consider using mutex_pause on the mac as it apparently // xxx should consider using mutex_pause on the mac as it apparently
// makes it seem less like a spinlock and avoids lowering the thread pri. // makes it seem less like a spinlock and avoids lowering the thread pri.
for (int i = 10; --i >= 0;) for (int i = 10; --i >= 0;)
Thread::yield(); std::this_thread::yield();
} }
} }
} }

View File

@@ -270,14 +270,6 @@ public:
/** Subtracts a RelativeTime from this time. */ /** Subtracts a RelativeTime from this time. */
Time& operator-= (RelativeTime delta); Time& operator-= (RelativeTime delta);
//==============================================================================
/** Tries to set the computer's clock.
@returns true if this succeeds, although depending on the system, the
application might not have sufficient privileges to do this.
*/
bool setSystemTimeToThisTime() const;
//============================================================================== //==============================================================================
/** Returns the name of a day of the week. /** Returns the name of a day of the week.

View File

@@ -30,12 +30,13 @@
#include <beast/ByteOrder.h> #include <beast/ByteOrder.h>
#include <beast/Memory.h> #include <beast/Memory.h>
#include <beast/StaticAssert.h>
#include <beast/Arithmetic.h> #include <beast/Arithmetic.h>
#include <beast/HeapBlock.h> #include <beast/HeapBlock.h>
#include <stdarg.h> #include <stdarg.h>
#include <algorithm>
namespace beast { namespace beast {
#if BEAST_MSVC #if BEAST_MSVC
@@ -54,6 +55,21 @@ static inline CharPointer_wchar_t castToCharPointer_wchar_t (const void* t) noex
return CharPointer_wchar_t (static_cast <const CharPointer_wchar_t::CharType*> (t)); return CharPointer_wchar_t (static_cast <const CharPointer_wchar_t::CharType*> (t));
} }
//==============================================================================
// Let me know if any of these assertions fail on your system!
#if BEAST_NATIVE_WCHAR_IS_UTF8
static_assert (sizeof (wchar_t) == 1,
"The size of a wchar_t should be exactly 1 byte for UTF-8");
#elif BEAST_NATIVE_WCHAR_IS_UTF16
static_assert (sizeof (wchar_t) == 2,
"The size of a wchar_t should be exactly 2 bytes for UTF-16");
#elif BEAST_NATIVE_WCHAR_IS_UTF32
static_assert (sizeof (wchar_t) == 4,
"The size of a wchar_t should be exactly 4 bytes for UTF-32");
#else
#error "The size of a wchar_t is not known!"
#endif
//============================================================================== //==============================================================================
class StringHolder class StringHolder
{ {
@@ -199,7 +215,7 @@ public:
if (b->refCount.get() <= 0 && b->allocatedNumBytes >= numBytes) if (b->refCount.get() <= 0 && b->allocatedNumBytes >= numBytes)
return text; return text;
CharPointerType newText (createUninitialisedBytes (bmax (b->allocatedNumBytes, numBytes))); CharPointerType newText (createUninitialisedBytes (std::max (b->allocatedNumBytes, numBytes)));
memcpy (newText.getAddress(), text.getAddress(), b->allocatedNumBytes); memcpy (newText.getAddress(), text.getAddress(), b->allocatedNumBytes);
release (b); release (b);
@@ -225,20 +241,6 @@ private:
return reinterpret_cast <StringHolder*> (reinterpret_cast <char*> (text.getAddress()) return reinterpret_cast <StringHolder*> (reinterpret_cast <char*> (text.getAddress())
- (reinterpret_cast <size_t> (reinterpret_cast <StringHolder*> (1)->text) - 1)); - (reinterpret_cast <size_t> (reinterpret_cast <StringHolder*> (1)->text) - 1));
} }
void compileTimeChecks()
{
// Let me know if any of these assertions fail on your system!
#if BEAST_NATIVE_WCHAR_IS_UTF8
static_bassert (sizeof (wchar_t) == 1);
#elif BEAST_NATIVE_WCHAR_IS_UTF16
static_bassert (sizeof (wchar_t) == 2);
#elif BEAST_NATIVE_WCHAR_IS_UTF32
static_bassert (sizeof (wchar_t) == 4);
#else
#error "native wchar_t size is unknown"
#endif
}
}; };
StringHolder StringHolder::empty; StringHolder StringHolder::empty;
@@ -1126,7 +1128,7 @@ public:
if (bytesWritten > allocatedBytes) if (bytesWritten > allocatedBytes)
{ {
allocatedBytes += bmax ((size_t) 8, allocatedBytes / 16); allocatedBytes += std::max ((size_t) 8, allocatedBytes / 16);
const size_t destOffset = (size_t) (((char*) dest.getAddress()) - (char*) result.getCharPointer().getAddress()); const size_t destOffset = (size_t) (((char*) dest.getAddress()) - (char*) result.getCharPointer().getAddress());
result.preallocateBytes (allocatedBytes); result.preallocateBytes (allocatedBytes);
dest = addBytesToPointer (result.getCharPointer().getAddress(), (int) destOffset); dest = addBytesToPointer (result.getCharPointer().getAddress(), (int) destOffset);
@@ -1349,12 +1351,12 @@ String String::substring (int start) const
String String::dropLastCharacters (const int numberToDrop) const String String::dropLastCharacters (const int numberToDrop) const
{ {
return String (text, (size_t) bmax (0, length() - numberToDrop)); return String (text, (size_t) std::max (0, length() - numberToDrop));
} }
String String::getLastCharacters (const int numCharacters) const String String::getLastCharacters (const int numCharacters) const
{ {
return String (text + bmax (0, length() - bmax (0, numCharacters))); return String (text + std::max (0, length() - std::max (0, numCharacters)));
} }
String String::fromFirstOccurrenceOf (const String& sub, String String::fromFirstOccurrenceOf (const String& sub,
@@ -1882,7 +1884,7 @@ struct StringEncodingConverter
const CharPointerType_Dest extraSpace (static_cast <DestChar*> (newSpace)); const CharPointerType_Dest extraSpace (static_cast <DestChar*> (newSpace));
#if BEAST_DEBUG // (This just avoids spurious warnings from valgrind about the uninitialised bytes at the end of the buffer..) #if BEAST_DEBUG // (This just avoids spurious warnings from valgrind about the uninitialised bytes at the end of the buffer..)
const size_t bytesToClear = (size_t) bmin ((int) extraBytesNeeded, 4); const size_t bytesToClear = (size_t) std::min ((int) extraBytesNeeded, 4);
zeromem (addBytesToPointer (newSpace, extraBytesNeeded - bytesToClear), bytesToClear); zeromem (addBytesToPointer (newSpace, extraBytesNeeded - bytesToClear), bytesToClear);
#endif #endif

View File

@@ -24,10 +24,11 @@
#ifndef BEAST_THREADS_SPINLOCK_H_INCLUDED #ifndef BEAST_THREADS_SPINLOCK_H_INCLUDED
#define BEAST_THREADS_SPINLOCK_H_INCLUDED #define BEAST_THREADS_SPINLOCK_H_INCLUDED
#include <beast/Atomic.h>
#include <beast/threads/UnlockGuard.h> #include <beast/threads/UnlockGuard.h>
#include <atomic>
#include <mutex> #include <mutex>
#include <thread>
namespace beast { namespace beast {
@@ -53,10 +54,21 @@ public:
/** Provides the type of scoped unlocker to use with a SpinLock. */ /** Provides the type of scoped unlocker to use with a SpinLock. */
typedef UnlockGuard <SpinLock> ScopedUnlockType; typedef UnlockGuard <SpinLock> ScopedUnlockType;
SpinLock() = default; SpinLock()
: m_lock (0)
{
}
~SpinLock() = default;
SpinLock (SpinLock const&) = delete; SpinLock (SpinLock const&) = delete;
SpinLock& operator= (SpinLock const&) = delete; SpinLock& operator= (SpinLock const&) = delete;
~SpinLock() = default;
/** Attempts to acquire the lock, returning true if this was successful. */
inline bool tryEnter() const noexcept
{
return (m_lock.exchange (1) == 0);
}
/** Acquires the lock. /** Acquires the lock.
This will block until the lock has been successfully acquired by this thread. This will block until the lock has been successfully acquired by this thread.
@@ -67,19 +79,27 @@ public:
It's strongly recommended that you never call this method directly - instead use the It's strongly recommended that you never call this method directly - instead use the
ScopedLockType class to manage the locking using an RAII pattern instead. ScopedLockType class to manage the locking using an RAII pattern instead.
*/ */
void enter() const noexcept; void enter() const noexcept
/** Attempts to acquire the lock, returning true if this was successful. */
inline bool tryEnter() const noexcept
{ {
return m_lock.compareAndSetBool (1, 0); if (! tryEnter())
{
for (int i = 20; --i >= 0;)
{
if (tryEnter())
return;
}
while (! tryEnter())
std::this_thread::yield ();
}
} }
/** Releases the lock. */ /** Releases the lock. */
inline void exit() const noexcept inline void exit() const noexcept
{ {
bassert (m_lock.value == 1); // Agh! Releasing a lock that isn't currently held! // Agh! Releasing a lock that isn't currently held!
m_lock = 0; bassert (m_lock.load () == 1);
m_lock.store (0);
} }
void lock () const void lock () const
@@ -90,8 +110,7 @@ public:
{ return tryEnter(); } { return tryEnter(); }
private: private:
//============================================================================== mutable std::atomic<int> m_lock;
mutable Atomic<int> m_lock;
}; };
} }

View File

@@ -20,12 +20,13 @@
#ifndef BEAST_THREADS_STOPPABLE_H_INCLUDED #ifndef BEAST_THREADS_STOPPABLE_H_INCLUDED
#define BEAST_THREADS_STOPPABLE_H_INCLUDED #define BEAST_THREADS_STOPPABLE_H_INCLUDED
#include <beast/Atomic.h>
#include <beast/intrusive/LockFreeStack.h> #include <beast/intrusive/LockFreeStack.h>
#include <beast/utility/Journal.h> #include <beast/utility/Journal.h>
#include <beast/threads/WaitableEvent.h> #include <beast/threads/WaitableEvent.h>
#include <atomic>
namespace beast { namespace beast {
class RootStoppable; class RootStoppable;
@@ -265,7 +266,7 @@ protected:
char const* m_name; char const* m_name;
RootStoppable& m_root; RootStoppable& m_root;
Child m_child; Child m_child;
Atomic <int> m_started; std::atomic <int> m_started;
bool volatile m_stopped; bool volatile m_stopped;
bool volatile m_childrenStopped; bool volatile m_childrenStopped;
Children m_children; Children m_children;
@@ -279,7 +280,7 @@ class RootStoppable : public Stoppable
public: public:
explicit RootStoppable (char const* name); explicit RootStoppable (char const* name);
~RootStoppable (); ~RootStoppable () = default;
bool isStopping() const; bool isStopping() const;
@@ -318,9 +319,9 @@ public:
void stopAsync (); void stopAsync ();
private: private:
Atomic <int> m_prepared; std::atomic <int> m_prepared;
Atomic <int> m_calledStop; std::atomic <int> m_calledStop;
Atomic <int> m_calledStopAsync; std::atomic <int> m_calledStopAsync;
}; };
/** @} */ /** @} */

View File

@@ -202,9 +202,6 @@ public:
// this can be called from any thread that needs to pause.. // this can be called from any thread that needs to pause..
static void sleep (int milliseconds); static void sleep (int milliseconds);
/** Yields the calling thread's current time-slot. */
static void yield();
//============================================================================== //==============================================================================
/** Makes the thread wait for a notification. /** Makes the thread wait for a notification.

View File

@@ -27,5 +27,4 @@
#include <beast/threads/impl/Thread.cpp> #include <beast/threads/impl/Thread.cpp>
#include <beast/threads/impl/WaitableEvent.cpp> #include <beast/threads/impl/WaitableEvent.cpp>
#include <beast/threads/tests/Atomic.test.cpp>
#include <beast/threads/tests/ServiceQueue.cpp> #include <beast/threads/tests/ServiceQueue.cpp>

View File

@@ -25,6 +25,7 @@ Stoppable::Stoppable (char const* name, RootStoppable& root)
: m_name (name) : m_name (name)
, m_root (root) , m_root (root)
, m_child (this) , m_child (this)
, m_started (0)
, m_stopped (false) , m_stopped (false)
, m_childrenStopped (false) , m_childrenStopped (false)
{ {
@@ -34,6 +35,7 @@ Stoppable::Stoppable (char const* name, Stoppable& parent)
: m_name (name) : m_name (name)
, m_root (parent.m_root) , m_root (parent.m_root)
, m_child (this) , m_child (this)
, m_started (0)
, m_stopped (false) , m_stopped (false)
, m_childrenStopped (false) , m_childrenStopped (false)
{ {
@@ -46,7 +48,7 @@ Stoppable::Stoppable (char const* name, Stoppable& parent)
Stoppable::~Stoppable () Stoppable::~Stoppable ()
{ {
// Children must be stopped. // Children must be stopped.
bassert (m_started.get() == 0 || m_childrenStopped); bassert (m_started.load () == 0 || m_childrenStopped);
} }
bool Stoppable::isStopping() const bool Stoppable::isStopping() const
@@ -143,44 +145,39 @@ void Stoppable::stopRecursive (Journal journal)
RootStoppable::RootStoppable (char const* name) RootStoppable::RootStoppable (char const* name)
: Stoppable (name, *this) : Stoppable (name, *this)
{ , m_prepared (0)
} , m_calledStop (0)
, m_calledStopAsync (0)
RootStoppable::~RootStoppable ()
{ {
} }
bool RootStoppable::isStopping() const bool RootStoppable::isStopping() const
{ {
return m_calledStopAsync.get() != 0; return m_calledStopAsync.load () != 0;
} }
void RootStoppable::prepare () void RootStoppable::prepare ()
{ {
if (! m_prepared.compareAndSetBool (1, 0)) if (m_prepared.exchange (1) == 0)
return; prepareRecursive ();
prepareRecursive ();
} }
void RootStoppable::start () void RootStoppable::start ()
{ {
// Courtesy call to prepare. // Courtesy call to prepare.
if (m_prepared.compareAndSetBool (1, 0)) if (m_prepared.exchange (1) == 0)
prepareRecursive (); prepareRecursive ();
if (! m_started.compareAndSetBool (1, 0)) if (m_started.exchange (1) == 0)
return; startRecursive ();
startRecursive ();
} }
void RootStoppable::stop (Journal journal) void RootStoppable::stop (Journal journal)
{ {
// Must have a prior call to start() // Must have a prior call to start()
bassert (m_started.get() != 0); bassert (m_started.load () != 0);
if (! m_calledStop.compareAndSetBool (1, 0)) if (m_calledStop.exchange (1) == 1)
{ {
journal.warning << "Stoppable::stop called again"; journal.warning << "Stoppable::stop called again";
return; return;
@@ -192,10 +189,8 @@ void RootStoppable::stop (Journal journal)
void RootStoppable::stopAsync () void RootStoppable::stopAsync ()
{ {
if (! m_calledStopAsync.compareAndSetBool (1, 0)) if (m_calledStopAsync.exchange (1) == 0)
return; stopAsyncRecursive ();
stopAsyncRecursive ();
} }
} }

View File

@@ -268,23 +268,6 @@ void Thread::notify() const
defaultEvent.signal(); defaultEvent.signal();
} }
//==============================================================================
// This is here so we dont have circular includes
//
void SpinLock::enter() const noexcept
{
if (! tryEnter())
{
for (int i = 20; --i >= 0;)
if (tryEnter())
return;
while (! tryEnter())
Thread::yield();
}
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -429,11 +412,6 @@ void Thread::sleep (const int millisecs)
} }
} }
void Thread::yield()
{
Sleep (0);
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -566,11 +544,6 @@ Thread::ThreadID Thread::getCurrentThreadId()
return (ThreadID) pthread_self(); return (ThreadID) pthread_self();
} }
void Thread::yield()
{
sched_yield();
}
//============================================================================== //==============================================================================
/* Remove this macro if you're having problems compiling the cpu affinity /* Remove this macro if you're having problems compiling the cpu affinity
calls (the API for these has changed about quite a bit in various Linux calls (the API for these has changed about quite a bit in various Linux

View File

@@ -1,139 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#if BEAST_INCLUDE_BEASTCONFIG
#include "../../BeastConfig.h"
#endif
#include <beast/Atomic.h>
#include <beast/Arithmetic.h>
#include <beast/ByteOrder.h>
#include <beast/unit_test/suite.h>
namespace beast {
class Atomic_test : public unit_test::suite
{
public:
template <typename Type>
void testFloat ()
{
Atomic<Type> a, b;
a = (Type) 21;
memoryBarrier();
/* These are some simple test cases to check the atomics - let me know
if any of these assertions fail on your system!
*/
expect (a.get() == (Type) 21);
expect (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21);
expect (a.get() == (Type) 21);
expect (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21);
expect (a.get() == (Type) 101);
expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
expect (a.get() == (Type) 101);
expect (a.compareAndSetBool ((Type) 200, a.get()));
expect (a.get() == (Type) 200);
expect (a.exchange ((Type) 300) == (Type) 200);
expect (a.get() == (Type) 300);
b = a;
expect (b.get() == a.get());
}
template <typename Type>
void testInteger ()
{
Atomic<Type> a, b;
a.set ((Type) 10);
expect (a.value == (Type) 10);
expect (a.get() == (Type) 10);
a += (Type) 15;
expect (a.get() == (Type) 25);
memoryBarrier();
a -= (Type) 5;
expect (a.get() == (Type) 20);
expect (++a == (Type) 21);
++a;
expect (--a == (Type) 21);
expect (a.get() == (Type) 21);
memoryBarrier();
testFloat <Type> ();
}
void run()
{
testcase ("Misc");
char a1[7];
expect (numElementsInArray(a1) == 7);
int a2[3];
expect (numElementsInArray(a2) == 3);
expect (ByteOrder::swap ((std::uint16_t) 0x1122) == 0x2211);
expect (ByteOrder::swap ((std::uint32_t) 0x11223344) == 0x44332211);
expect (ByteOrder::swap ((std::uint64_t) 0x1122334455667788LL) == 0x8877665544332211LL);
testcase ("int");
testInteger <int> ();
testcase ("unsigned int");
testInteger <unsigned int> ();
testcase ("std::int32_t");
testInteger <std::int32_t> ();
testcase ("std::uint32_t");
testInteger <std::uint32_t> ();
testcase ("long");
testInteger <long> ();
testcase ("void*");
testInteger <void*> ();
testcase ("int*");
testInteger <int*> ();
testcase ("float");
testFloat <float> ();
#if ! BEAST_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
testcase ("std::int64_t");
testInteger <std::int64_t> ();
testcase ("std::uint64_t");
testInteger <std::uint64_t> ();
testcase ("double");
testFloat <double> ();
#endif
}
};
BEAST_DEFINE_TESTSUITE(Atomic,thread,beast);
}

View File

@@ -21,10 +21,11 @@
#define BEAST_UTILITY_LEAKCHECKED_H_INCLUDED #define BEAST_UTILITY_LEAKCHECKED_H_INCLUDED
#include <beast/Config.h> #include <beast/Config.h>
#include <beast/Atomic.h>
#include <beast/intrusive/LockFreeStack.h> #include <beast/intrusive/LockFreeStack.h>
#include <beast/utility/StaticObject.h> #include <beast/utility/StaticObject.h>
#include <atomic>
namespace beast { namespace beast {
namespace detail { namespace detail {
@@ -63,7 +64,7 @@ protected:
class Singleton; class Singleton;
friend class LeakCheckedBase; friend class LeakCheckedBase;
Atomic <int> m_count; std::atomic <int> m_count;
}; };
static void reportDanglingPointer (char const* objectName); static void reportDanglingPointer (char const* objectName);

View File

@@ -20,6 +20,10 @@
#ifndef BEAST_UTILITY_STATICOBJECT_H_INCLUDED #ifndef BEAST_UTILITY_STATICOBJECT_H_INCLUDED
#define BEAST_UTILITY_STATICOBJECT_H_INCLUDED #define BEAST_UTILITY_STATICOBJECT_H_INCLUDED
#include <atomic>
#include <chrono>
#include <thread>
namespace beast { namespace beast {
// Spec: N2914=09-0104 // Spec: N2914=09-0104
@@ -31,12 +35,6 @@ namespace beast {
// other initialization takes place. // other initialization takes place.
// //
namespace detail {
extern void staticObjectWait (std::size_t n);
}
/** Wrapper to produce an object with static storage duration. /** Wrapper to produce an object with static storage duration.
The object is constructed in a thread-safe fashion when the get function The object is constructed in a thread-safe fashion when the get function
@@ -59,9 +57,9 @@ public:
{ {
StaticData& staticData (StaticData::get()); StaticData& staticData (StaticData::get());
if (staticData.state.get() != initialized) if (staticData.state.load () != initialized)
{ {
if (staticData.state.compareAndSetBool (initializing, uninitialized)) if (staticData.state.exchange (initializing) == uninitialized)
{ {
// Initialize the object. // Initialize the object.
new (&staticData.object) Object; new (&staticData.object) Object;
@@ -69,23 +67,35 @@ public:
} }
else else
{ {
for (std::size_t n = 0; staticData.state.get() != initialized; ++n) std::size_t n = 0;
while (staticData.state.load () != initialized)
{ {
detail::staticObjectWait (n); ++n;
std::this_thread::yield ();
if (n > 10)
{
std::chrono::milliseconds duration (1);
if (n > 100)
duration *= 10;
std::this_thread::sleep_for (duration);
}
} }
} }
} }
assert (staticData.state.load () == initialized);
return staticData.object; return staticData.object;
} }
private: private:
enum static int const uninitialized = 0;
{ static int const initializing = 1;
uninitialized = 0, // must be zero to function properly static int const initialized = 2;
initializing,
initialized
};
// This structure gets zero-filled at static initialization time. // This structure gets zero-filled at static initialization time.
// No constructors are called. // No constructors are called.
@@ -93,7 +103,7 @@ private:
class StaticData class StaticData
{ {
public: public:
Atomic <int> state; std::atomic <int> state;
Object object; Object object;
static StaticData& get () static StaticData& get ()

View File

@@ -26,7 +26,6 @@
#include <beast/utility/impl/Debug.cpp> #include <beast/utility/impl/Debug.cpp>
#include <beast/utility/impl/Journal.cpp> #include <beast/utility/impl/Journal.cpp>
#include <beast/utility/impl/LeakChecked.cpp> #include <beast/utility/impl/LeakChecked.cpp>
#include <beast/utility/impl/StaticObject.cpp>
#include <beast/utility/impl/PropertyStream.cpp> #include <beast/utility/impl/PropertyStream.cpp>
#include <beast/utility/tests/bassert.test.cpp> #include <beast/utility/tests/bassert.test.cpp>

View File

@@ -335,10 +335,6 @@ public:
void run () void run ()
{ {
log <<
"operatingSystemName = '" <<
SystemStats::getOperatingSystemName () << "'";
log << log <<
"_DEBUG = " << "_DEBUG = " <<
String::fromNumber (envDebug ()); String::fromNumber (envDebug ());

View File

@@ -18,7 +18,6 @@
//============================================================================== //==============================================================================
#include <beast/utility/LeakChecked.h> #include <beast/utility/LeakChecked.h>
#include <beast/module/core/logging/Logger.h>
namespace beast { namespace beast {
@@ -62,6 +61,7 @@ private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
LeakCheckedBase::LeakCounterBase::LeakCounterBase () LeakCheckedBase::LeakCounterBase::LeakCounterBase ()
: m_count (0)
{ {
Singleton::getInstance ().push_back (this); Singleton::getInstance ().push_back (this);
} }
@@ -73,51 +73,20 @@ void LeakCheckedBase::LeakCounterBase::checkForLeaks ()
// //
this->checkPureVirtual (); this->checkPureVirtual ();
int const count = m_count.get (); int const count = m_count.load ();
if (count > 0) if (count > 0)
{ {
/** If you hit this, then you've leaked one or more objects of the outputDebugString ("Leaked objects: " + std::to_string (count) +
specified class; the name should have been printed by the line " instances of " + getClassName ());
below.
If you're leaking, it's probably because you're using old-fashioned,
non-RAII techniques for your object management. Tut, tut. Always,
always use ScopedPointers, OwnedArrays, SharedObjects,
etc, and avoid the 'delete' operator at all costs!
*/
BDBG ("Leaked objects: " << count << " of " << getClassName ());
//bassertfalse;
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if BEAST_DEBUG
void LeakCheckedBase::reportDanglingPointer (char const* objectName) void LeakCheckedBase::reportDanglingPointer (char const* objectName)
#else
void LeakCheckedBase::reportDanglingPointer (char const*)
#endif
{ {
/* If you hit this, then you've managed to delete more instances outputDebugString (std::string ("Dangling pointer deletion: ") + objectName);
of this class than you've created. That indicates that you're
deleting some dangling pointers.
Note that although this assertion will have been triggered
during a destructor, it might not be this particular deletion
that's at fault - the incorrect one may have happened at an
earlier point in the program, and simply not been detected
until now.
Most errors like this are caused by using old-fashioned,
non-RAII techniques for your object management. Tut, tut.
Always, always use ScopedPointers, OwnedArrays,
SharedObjects, etc, and avoid the 'delete' operator
at all costs!
*/
BDBG ("Dangling pointer deletion: " << objectName);
bassertfalse; bassertfalse;
} }

View File

@@ -1,41 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/utility/StaticObject.h>
#include <beast/threads/Thread.h>
namespace beast {
namespace detail
{
// This is here so we don't need the Thread class declaration
void staticObjectWait (std::size_t n)
{
// Wait for initialization
Thread::yield ();
if (n > 10)
Thread::sleep (1);
else if (n > 100)
Thread::sleep (10);
}
}
}