mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-11-08 14:05:23 +00:00
补充某些必要的文件
This commit is contained in:
154
cocos2d-x/external/win32/include/spidermonkey/mozilla/Alignment.h
vendored
Executable file
154
cocos2d-x/external/win32/include/spidermonkey/mozilla/Alignment.h
vendored
Executable file
@@ -0,0 +1,154 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Functionality related to memory alignment. */
|
||||
|
||||
#ifndef mozilla_Alignment_h
|
||||
#define mozilla_Alignment_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* This class, and the corresponding macro MOZ_ALIGNOF, figures out how many
|
||||
* bytes of alignment a given type needs.
|
||||
*/
|
||||
template<typename T>
|
||||
class AlignmentFinder
|
||||
{
|
||||
struct Aligner
|
||||
{
|
||||
char mChar;
|
||||
T mT;
|
||||
};
|
||||
|
||||
public:
|
||||
static const size_t alignment = sizeof(Aligner) - sizeof(T);
|
||||
};
|
||||
|
||||
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
|
||||
|
||||
/*
|
||||
* Declare the MOZ_ALIGNED_DECL macro for declaring aligned types.
|
||||
*
|
||||
* For instance,
|
||||
*
|
||||
* MOZ_ALIGNED_DECL(char arr[2], 8);
|
||||
*
|
||||
* will declare a two-character array |arr| aligned to 8 bytes.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define MOZ_ALIGNED_DECL(_type, _align) \
|
||||
_type __attribute__((aligned(_align)))
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_ALIGNED_DECL(_type, _align) \
|
||||
__declspec(align(_align)) _type
|
||||
#else
|
||||
# warning "We don't know how to align variables on this compiler."
|
||||
# define MOZ_ALIGNED_DECL(_type, _align) _type
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AlignedElem<N> is a structure whose alignment is guaranteed to be at least N
|
||||
* bytes.
|
||||
*
|
||||
* We support 1, 2, 4, 8, and 16-bit alignment.
|
||||
*/
|
||||
template<size_t Align>
|
||||
struct AlignedElem;
|
||||
|
||||
/*
|
||||
* We have to specialize this template because GCC doesn't like
|
||||
* __attribute__((aligned(foo))) where foo is a template parameter.
|
||||
*/
|
||||
|
||||
template<>
|
||||
struct AlignedElem<1>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 1);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<2>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 2);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<4>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 4);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<8>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 8);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<16>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 16);
|
||||
};
|
||||
|
||||
/*
|
||||
* This utility pales in comparison to Boost's aligned_storage. The utility
|
||||
* simply assumes that uint64_t is enough alignment for anyone. This may need
|
||||
* to be extended one day...
|
||||
*
|
||||
* As an important side effect, pulling the storage into this template is
|
||||
* enough obfuscation to confuse gcc's strict-aliasing analysis into not giving
|
||||
* false negatives when we cast from the char buffer to whatever type we've
|
||||
* constructed using the bytes.
|
||||
*/
|
||||
template<size_t Nbytes>
|
||||
struct AlignedStorage
|
||||
{
|
||||
union U
|
||||
{
|
||||
char mBytes[Nbytes];
|
||||
uint64_t mDummy;
|
||||
} u;
|
||||
|
||||
const void* addr() const { return u.mBytes; }
|
||||
void* addr() { return u.mBytes; }
|
||||
|
||||
AlignedStorage() = default;
|
||||
|
||||
// AlignedStorage is non-copyable: the default copy constructor violates
|
||||
// strict aliasing rules, per bug 1269319.
|
||||
AlignedStorage(const AlignedStorage&) = delete;
|
||||
void operator=(const AlignedStorage&) = delete;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS AlignedStorage2
|
||||
{
|
||||
union U
|
||||
{
|
||||
char mBytes[sizeof(T)];
|
||||
uint64_t mDummy;
|
||||
} u;
|
||||
|
||||
const T* addr() const { return reinterpret_cast<const T*>(u.mBytes); }
|
||||
T* addr() { return static_cast<T*>(static_cast<void*>(u.mBytes)); }
|
||||
|
||||
AlignedStorage2() = default;
|
||||
|
||||
// AlignedStorage2 is non-copyable: the default copy constructor violates
|
||||
// strict aliasing rules, per bug 1269319.
|
||||
AlignedStorage2(const AlignedStorage2&) = delete;
|
||||
void operator=(const AlignedStorage2&) = delete;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_Alignment_h */
|
||||
133
cocos2d-x/external/win32/include/spidermonkey/mozilla/AllocPolicy.h
vendored
Executable file
133
cocos2d-x/external/win32/include/spidermonkey/mozilla/AllocPolicy.h
vendored
Executable file
@@ -0,0 +1,133 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* An allocation policy concept, usable for structures and algorithms to
|
||||
* control how memory is allocated and how failures are handled.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_AllocPolicy_h
|
||||
#define mozilla_AllocPolicy_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TemplateLib.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* Allocation policies are used to implement the standard allocation behaviors
|
||||
* in a customizable way. Additionally, custom behaviors may be added to these
|
||||
* behaviors, such as additionally reporting an error through an out-of-band
|
||||
* mechanism when OOM occurs. The concept modeled here is as follows:
|
||||
*
|
||||
* - public copy constructor, assignment, destructor
|
||||
* - template <typename T> T* maybe_pod_malloc(size_t)
|
||||
* Fallible, but doesn't report an error on OOM.
|
||||
* - template <typename T> T* maybe_pod_calloc(size_t)
|
||||
* Fallible, but doesn't report an error on OOM.
|
||||
* - template <typename T> T* maybe_pod_realloc(T*, size_t, size_t)
|
||||
* Fallible, but doesn't report an error on OOM. The old allocation
|
||||
* size is passed in, in addition to the new allocation size requested.
|
||||
* - template <typename T> T* pod_malloc(size_t)
|
||||
* Responsible for OOM reporting when null is returned.
|
||||
* - template <typename T> T* pod_calloc(size_t)
|
||||
* Responsible for OOM reporting when null is returned.
|
||||
* - template <typename T> T* pod_realloc(T*, size_t, size_t)
|
||||
* Responsible for OOM reporting when null is returned. The old allocation
|
||||
* size is passed in, in addition to the new allocation size requested.
|
||||
* - void free_(void*)
|
||||
* - void reportAllocOverflow() const
|
||||
* Called on allocation overflow (that is, an allocation implicitly tried
|
||||
* to allocate more than the available memory space -- think allocating an
|
||||
* array of large-size objects, where N * size overflows) before null is
|
||||
* returned.
|
||||
* - bool checkSimulatedOOM() const
|
||||
* Some clients generally allocate memory yet in some circumstances won't
|
||||
* need to do so. For example, appending to a vector with a small amount of
|
||||
* inline storage generally allocates memory, but no allocation occurs
|
||||
* unless appending exceeds inline storage. But for testing purposes, it
|
||||
* can be useful to treat *every* operation as allocating.
|
||||
* Clients (such as this hypothetical append method implementation) should
|
||||
* call this method in situations that don't allocate, but could generally,
|
||||
* to support this. The default behavior should return true; more
|
||||
* complicated behavior might be to return false only after a certain
|
||||
* number of allocations-or-check-simulated-OOMs (coordinating with the
|
||||
* other AllocPolicy methods) have occurred.
|
||||
*
|
||||
* mfbt provides (and typically uses by default) only MallocAllocPolicy, which
|
||||
* does nothing more than delegate to the malloc/alloc/free functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A policy that straightforwardly uses malloc/calloc/realloc/free and adds no
|
||||
* extra behaviors.
|
||||
*/
|
||||
class MallocAllocPolicy
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
T* maybe_pod_malloc(size_t aNumElems)
|
||||
{
|
||||
if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<T*>(malloc(aNumElems * sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* maybe_pod_calloc(size_t aNumElems)
|
||||
{
|
||||
return static_cast<T*>(calloc(aNumElems, sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
|
||||
{
|
||||
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<T*>(realloc(aPtr, aNewSize * sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* pod_malloc(size_t aNumElems)
|
||||
{
|
||||
return maybe_pod_malloc<T>(aNumElems);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* pod_calloc(size_t aNumElems)
|
||||
{
|
||||
return maybe_pod_calloc<T>(aNumElems);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
|
||||
{
|
||||
return maybe_pod_realloc<T>(aPtr, aOldSize, aNewSize);
|
||||
}
|
||||
|
||||
void free_(void* aPtr)
|
||||
{
|
||||
free(aPtr);
|
||||
}
|
||||
|
||||
void reportAllocOverflow() const
|
||||
{
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool checkSimulatedOOM() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_AllocPolicy_h */
|
||||
147
cocos2d-x/external/win32/include/spidermonkey/mozilla/AlreadyAddRefed.h
vendored
Executable file
147
cocos2d-x/external/win32/include/spidermonkey/mozilla/AlreadyAddRefed.h
vendored
Executable file
@@ -0,0 +1,147 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Typed temporary pointers for reference-counted smart pointers. */
|
||||
|
||||
#ifndef AlreadyAddRefed_h
|
||||
#define AlreadyAddRefed_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct unused_t;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* already_AddRefed cooperates with reference counting smart pointers to enable
|
||||
* you to assign in a pointer _without_ |AddRef|ing it. You might want to use
|
||||
* this as a return type from a function that returns an already |AddRef|ed
|
||||
* pointer.
|
||||
*
|
||||
* TODO Move already_AddRefed to namespace mozilla. This has not yet been done
|
||||
* because of the sheer number of usages of already_AddRefed.
|
||||
*/
|
||||
template<class T>
|
||||
struct MOZ_MUST_USE_TYPE MOZ_NON_AUTOABLE already_AddRefed
|
||||
{
|
||||
/*
|
||||
* We want to allow returning nullptr from functions returning
|
||||
* already_AddRefed<T>, for simplicity. But we also don't want to allow
|
||||
* returning raw T*, instead preferring creation of already_AddRefed<T> from
|
||||
* a reference counting smart pointer.
|
||||
*
|
||||
* We address the latter requirement by making the (T*) constructor explicit.
|
||||
* But |return nullptr| won't consider an explicit constructor, so we need
|
||||
* another constructor to handle it. Plain old (decltype(nullptr)) doesn't
|
||||
* cut it, because if nullptr is emulated as __null (with type int or long),
|
||||
* passing nullptr to an int/long parameter triggers compiler warnings. We
|
||||
* need a type that no one can pass accidentally; a pointer-to-member-function
|
||||
* (where no such function exists) does the trick nicely.
|
||||
*
|
||||
* That handles the return-value case. What about for locals, argument types,
|
||||
* and so on? |already_AddRefed<T>(nullptr)| considers both overloads (and
|
||||
* the (already_AddRefed<T>&&) overload as well!), so there's an ambiguity.
|
||||
* We can target true nullptr using decltype(nullptr), but we can't target
|
||||
* emulated nullptr the same way, because passing __null to an int/long
|
||||
* parameter triggers compiler warnings. So just give up on this, and provide
|
||||
* this behavior through the default constructor.
|
||||
*
|
||||
* We can revert to simply explicit (T*) and implicit (decltype(nullptr)) when
|
||||
* nullptr no longer needs to be emulated to support the ancient b2g compiler.
|
||||
* (The () overload could also be removed, if desired, if we changed callers.)
|
||||
*/
|
||||
already_AddRefed() : mRawPtr(nullptr) {}
|
||||
|
||||
// The return and argument types here are arbitrarily selected so no
|
||||
// corresponding member function exists.
|
||||
typedef void (already_AddRefed::* MatchNullptr)(double, float);
|
||||
MOZ_IMPLICIT already_AddRefed(MatchNullptr aRawPtr) : mRawPtr(nullptr) {}
|
||||
|
||||
explicit already_AddRefed(T* aRawPtr) : mRawPtr(aRawPtr) {}
|
||||
|
||||
// Disallow copy constructor and copy assignment operator: move semantics used instead.
|
||||
already_AddRefed(const already_AddRefed<T>& aOther) = delete;
|
||||
already_AddRefed<T>& operator=(const already_AddRefed<T>& aOther) = delete;
|
||||
|
||||
already_AddRefed(already_AddRefed<T>&& aOther) : mRawPtr(aOther.take()) {}
|
||||
|
||||
already_AddRefed<T>& operator=(already_AddRefed<T>&& aOther)
|
||||
{
|
||||
mRawPtr = aOther.take();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper is useful in cases like
|
||||
*
|
||||
* already_AddRefed<BaseClass>
|
||||
* Foo()
|
||||
* {
|
||||
* RefPtr<SubClass> x = ...;
|
||||
* return x.forget();
|
||||
* }
|
||||
*
|
||||
* The autoconversion allows one to omit the idiom
|
||||
*
|
||||
* RefPtr<BaseClass> y = x.forget();
|
||||
* return y.forget();
|
||||
*
|
||||
* Note that nsRefPtr is the XPCOM reference counting smart pointer class.
|
||||
*/
|
||||
template <typename U>
|
||||
MOZ_IMPLICIT already_AddRefed(already_AddRefed<U>&& aOther) : mRawPtr(aOther.take()) {}
|
||||
|
||||
~already_AddRefed() { MOZ_ASSERT(!mRawPtr); }
|
||||
|
||||
// Specialize the unused operator<< for already_AddRefed, to allow
|
||||
// nsCOMPtr<nsIFoo> foo;
|
||||
// Unused << foo.forget();
|
||||
// Note that nsCOMPtr is the XPCOM reference counting smart pointer class.
|
||||
friend void operator<<(const mozilla::unused_t& aUnused,
|
||||
const already_AddRefed<T>& aRhs)
|
||||
{
|
||||
auto mutableAlreadyAddRefed = const_cast<already_AddRefed<T>*>(&aRhs);
|
||||
aUnused << mutableAlreadyAddRefed->take();
|
||||
}
|
||||
|
||||
MOZ_MUST_USE T* take()
|
||||
{
|
||||
T* rawPtr = mRawPtr;
|
||||
mRawPtr = nullptr;
|
||||
return rawPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper provides a static_cast replacement for already_AddRefed, so
|
||||
* if you have
|
||||
*
|
||||
* already_AddRefed<Parent> F();
|
||||
*
|
||||
* you can write
|
||||
*
|
||||
* already_AddRefed<Child>
|
||||
* G()
|
||||
* {
|
||||
* return F().downcast<Child>();
|
||||
* }
|
||||
*/
|
||||
template<class U>
|
||||
already_AddRefed<U> downcast()
|
||||
{
|
||||
U* tmp = static_cast<U*>(mRawPtr);
|
||||
mRawPtr = nullptr;
|
||||
return already_AddRefed<U>(tmp);
|
||||
}
|
||||
|
||||
private:
|
||||
T* MOZ_OWNING_REF mRawPtr;
|
||||
};
|
||||
|
||||
#endif // AlreadyAddRefed_h
|
||||
88
cocos2d-x/external/win32/include/spidermonkey/mozilla/Array.h
vendored
Executable file
88
cocos2d-x/external/win32/include/spidermonkey/mozilla/Array.h
vendored
Executable file
@@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A compile-time constant-length array with bounds-checking assertions. */
|
||||
|
||||
#ifndef mozilla_Array_h
|
||||
#define mozilla_Array_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/ReverseIterator.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T, size_t Length>
|
||||
class Array
|
||||
{
|
||||
T mArr[Length];
|
||||
|
||||
public:
|
||||
Array() {}
|
||||
|
||||
template <typename... Args>
|
||||
MOZ_IMPLICIT Array(Args&&... aArgs)
|
||||
: mArr{mozilla::Forward<Args>(aArgs)...}
|
||||
{
|
||||
static_assert(sizeof...(aArgs) == Length,
|
||||
"The number of arguments should be equal to the template parameter Length");
|
||||
}
|
||||
|
||||
T& operator[](size_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex < Length);
|
||||
return mArr[aIndex];
|
||||
}
|
||||
|
||||
const T& operator[](size_t aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(aIndex < Length);
|
||||
return mArr[aIndex];
|
||||
}
|
||||
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef ReverseIterator<T*> reverse_iterator;
|
||||
typedef ReverseIterator<const T*> const_reverse_iterator;
|
||||
|
||||
// Methods for range-based for loops.
|
||||
iterator begin() { return mArr; }
|
||||
const_iterator begin() const { return mArr; }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() { return mArr + Length; }
|
||||
const_iterator end() const { return mArr + Length; }
|
||||
const_iterator cend() const { return end(); }
|
||||
|
||||
// Methods for reverse iterating.
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Array<T, 0>
|
||||
{
|
||||
public:
|
||||
T& operator[](size_t aIndex)
|
||||
{
|
||||
MOZ_CRASH("indexing into zero-length array");
|
||||
}
|
||||
|
||||
const T& operator[](size_t aIndex) const
|
||||
{
|
||||
MOZ_CRASH("indexing into zero-length array");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_Array_h */
|
||||
194
cocos2d-x/external/win32/include/spidermonkey/mozilla/ArrayUtils.h
vendored
Executable file
194
cocos2d-x/external/win32/include/spidermonkey/mozilla/ArrayUtils.h
vendored
Executable file
@@ -0,0 +1,194 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Implements various helper functions related to arrays.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_ArrayUtils_h
|
||||
#define mozilla_ArrayUtils_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* Safely subtract two pointers when it is known that aEnd >= aBegin, yielding a
|
||||
* size_t result.
|
||||
*
|
||||
* Ordinary pointer subtraction yields a ptrdiff_t result, which, being signed,
|
||||
* has insufficient range to express the distance between pointers at opposite
|
||||
* ends of the address space. Furthermore, most compilers use ptrdiff_t to
|
||||
* represent the intermediate byte address distance, before dividing by
|
||||
* sizeof(T); if that intermediate result overflows, they'll produce results
|
||||
* with the wrong sign even when the correct scaled distance would fit in a
|
||||
* ptrdiff_t.
|
||||
*/
|
||||
template<class T>
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PointerRangeSize(T* aBegin, T* aEnd)
|
||||
{
|
||||
MOZ_ASSERT(aEnd >= aBegin);
|
||||
return (size_t(aEnd) - size_t(aBegin)) / sizeof(T);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the length of an array with constant length. (Use of this method
|
||||
* with a non-array pointer will not compile.)
|
||||
*
|
||||
* Beware of the implicit trailing '\0' when using this with string constants.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
constexpr size_t
|
||||
ArrayLength(T (&aArr)[N])
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
constexpr size_t
|
||||
ArrayLength(const Array<T, N>& aArr)
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
template<typename E, E N, typename T>
|
||||
constexpr size_t
|
||||
ArrayLength(const EnumeratedArray<E, N, T>& aArr)
|
||||
{
|
||||
return size_t(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the address one past the last element of a constant-length array.
|
||||
*
|
||||
* Beware of the implicit trailing '\0' when using this with string constants.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
constexpr T*
|
||||
ArrayEnd(T (&aArr)[N])
|
||||
{
|
||||
return aArr + ArrayLength(aArr);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
constexpr T*
|
||||
ArrayEnd(Array<T, N>& aArr)
|
||||
{
|
||||
return &aArr[0] + ArrayLength(aArr);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
constexpr const T*
|
||||
ArrayEnd(const Array<T, N>& aArr)
|
||||
{
|
||||
return &aArr[0] + ArrayLength(aArr);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename AlignType, typename Pointee,
|
||||
typename = EnableIf<!IsVoid<AlignType>::value>>
|
||||
struct AlignedChecker
|
||||
{
|
||||
static void
|
||||
test(const Pointee* aPtr)
|
||||
{
|
||||
MOZ_ASSERT((uintptr_t(aPtr) % MOZ_ALIGNOF(AlignType)) == 0,
|
||||
"performing a range-check with a misaligned pointer");
|
||||
}
|
||||
};
|
||||
|
||||
template<typename AlignType, typename Pointee>
|
||||
struct AlignedChecker<AlignType, Pointee>
|
||||
{
|
||||
static void
|
||||
test(const Pointee* aPtr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Determines whether |aPtr| points at an object in the range [aBegin, aEnd).
|
||||
*
|
||||
* |aPtr| must have the same alignment as |aBegin| and |aEnd|. This usually
|
||||
* should be achieved by ensuring |aPtr| points at a |U|, not just that it
|
||||
* points at a |T|.
|
||||
*
|
||||
* It is a usage error for any argument to be misaligned.
|
||||
*
|
||||
* It's okay for T* to be void*, and if so U* may also be void*. In the latter
|
||||
* case no argument is required to be aligned (obviously, as void* implies no
|
||||
* particular alignment).
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
inline typename EnableIf<IsSame<T, U>::value ||
|
||||
IsBaseOf<T, U>::value ||
|
||||
IsVoid<T>::value,
|
||||
bool>::Type
|
||||
IsInRange(const T* aPtr, const U* aBegin, const U* aEnd)
|
||||
{
|
||||
MOZ_ASSERT(aBegin <= aEnd);
|
||||
detail::AlignedChecker<U, T>::test(aPtr);
|
||||
detail::AlignedChecker<U, U>::test(aBegin);
|
||||
detail::AlignedChecker<U, U>::test(aEnd);
|
||||
return aBegin <= reinterpret_cast<const U*>(aPtr) &&
|
||||
reinterpret_cast<const U*>(aPtr) < aEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience version of the above method when the valid range is specified as
|
||||
* uintptr_t values. As above, |aPtr| must be aligned, and |aBegin| and |aEnd|
|
||||
* must be aligned with respect to |T|.
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsInRange(const T* aPtr, uintptr_t aBegin, uintptr_t aEnd)
|
||||
{
|
||||
return IsInRange(aPtr,
|
||||
reinterpret_cast<const T*>(aBegin),
|
||||
reinterpret_cast<const T*>(aEnd));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* Helper for the MOZ_ARRAY_LENGTH() macro to make the length a typesafe
|
||||
* compile-time constant even on compilers lacking constexpr support.
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
char (&ArrayLengthHelper(T (&array)[N]))[N];
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* MOZ_ARRAY_LENGTH() is an alternative to mozilla::ArrayLength() for C files
|
||||
* that can't use C++ template functions and for static_assert() calls that
|
||||
* can't call ArrayLength() when it is not a C++11 constexpr function.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# define MOZ_ARRAY_LENGTH(array) sizeof(mozilla::detail::ArrayLengthHelper(array))
|
||||
#else
|
||||
# define MOZ_ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_ArrayUtils_h */
|
||||
585
cocos2d-x/external/win32/include/spidermonkey/mozilla/Assertions.h
vendored
Executable file
585
cocos2d-x/external/win32/include/spidermonkey/mozilla/Assertions.h
vendored
Executable file
@@ -0,0 +1,585 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implementations of runtime and static assertion macros for C and C++. */
|
||||
|
||||
#ifndef mozilla_Assertions_h
|
||||
#define mozilla_Assertions_h
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && defined(__cplusplus)
|
||||
#define MOZ_DUMP_ASSERTION_STACK
|
||||
#endif
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MacroArgs.h"
|
||||
#include "mozilla/StaticAnalysisFunctions.h"
|
||||
#include "mozilla/Types.h"
|
||||
#ifdef MOZ_DUMP_ASSERTION_STACK
|
||||
#include "nsTraceRefcnt.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_HAS_MOZGLUE) || defined(MOZILLA_INTERNAL_API)
|
||||
/*
|
||||
* The crash reason set by MOZ_CRASH_ANNOTATE is consumed by the crash reporter
|
||||
* if present. It is declared here (and defined in Assertions.cpp) to make it
|
||||
* available to all code, even libraries that don't link with the crash reporter
|
||||
* directly.
|
||||
*/
|
||||
MOZ_BEGIN_EXTERN_C
|
||||
extern MFBT_DATA const char* gMozCrashReason;
|
||||
MOZ_END_EXTERN_C
|
||||
|
||||
static inline void
|
||||
AnnotateMozCrashReason(const char* reason)
|
||||
{
|
||||
gMozCrashReason = reason;
|
||||
}
|
||||
# define MOZ_CRASH_ANNOTATE(...) AnnotateMozCrashReason(__VA_ARGS__)
|
||||
#else
|
||||
# define MOZ_CRASH_ANNOTATE(...) do { /* nothing */ } while (0)
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef WIN32
|
||||
/*
|
||||
* TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
|
||||
* further depends on <windef.h>. We hardcode these few definitions manually
|
||||
* because those headers clutter the global namespace with a significant
|
||||
* number of undesired macros and symbols.
|
||||
*/
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
__declspec(dllimport) int __stdcall
|
||||
TerminateProcess(void* hProcess, unsigned int uExitCode);
|
||||
__declspec(dllimport) void* __stdcall GetCurrentProcess(void);
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
# include <android/log.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_STATIC_ASSERT may be used to assert a condition *at compile time* in C.
|
||||
* In C++11, static_assert is provided by the compiler to the same effect.
|
||||
* This can be useful when you make certain assumptions about what must hold for
|
||||
* optimal, or even correct, behavior. For example, you might assert that the
|
||||
* size of a struct is a multiple of the target architecture's word size:
|
||||
*
|
||||
* struct S { ... };
|
||||
* // C
|
||||
* MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
|
||||
* "S should be a multiple of word size for efficiency");
|
||||
* // C++11
|
||||
* static_assert(sizeof(S) % sizeof(size_t) == 0,
|
||||
* "S should be a multiple of word size for efficiency");
|
||||
*
|
||||
* This macro can be used in any location where both an extern declaration and a
|
||||
* typedef could be used.
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
/*
|
||||
* Some of the definitions below create an otherwise-unused typedef. This
|
||||
* triggers compiler warnings with some versions of gcc, so mark the typedefs
|
||||
* as permissibly-unused to disable the warnings.
|
||||
*/
|
||||
# if defined(__GNUC__)
|
||||
# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
|
||||
# else
|
||||
# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE /* nothing */
|
||||
# endif
|
||||
# define MOZ_STATIC_ASSERT_GLUE1(x, y) x##y
|
||||
# define MOZ_STATIC_ASSERT_GLUE(x, y) MOZ_STATIC_ASSERT_GLUE1(x, y)
|
||||
# if defined(__SUNPRO_CC)
|
||||
/*
|
||||
* The Sun Studio C++ compiler is buggy when declaring, inside a function,
|
||||
* another extern'd function with an array argument whose length contains a
|
||||
* sizeof, triggering the error message "sizeof expression not accepted as
|
||||
* size of array parameter". This bug (6688515, not public yet) would hit
|
||||
* defining moz_static_assert as a function, so we always define an extern
|
||||
* array for Sun Studio.
|
||||
*
|
||||
* We include the line number in the symbol name in a best-effort attempt
|
||||
* to avoid conflicts (see below).
|
||||
*/
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||
extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
|
||||
# elif defined(__COUNTER__)
|
||||
/*
|
||||
* If there was no preferred alternative, use a compiler-agnostic version.
|
||||
*
|
||||
* Note that the non-__COUNTER__ version has a bug in C++: it can't be used
|
||||
* in both |extern "C"| and normal C++ in the same translation unit. (Alas
|
||||
* |extern "C"| isn't allowed in a function.) The only affected compiler
|
||||
* we really care about is gcc 4.2. For that compiler and others like it,
|
||||
* we include the line number in the function name to do the best we can to
|
||||
* avoid conflicts. These should be rare: a conflict would require use of
|
||||
* MOZ_STATIC_ASSERT on the same line in separate files in the same
|
||||
* translation unit, *and* the uses would have to be in code with
|
||||
* different linkage, *and* the first observed use must be in C++-linkage
|
||||
* code.
|
||||
*/
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||
typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1] MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
# else
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||
extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1]) MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
# endif
|
||||
|
||||
#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
|
||||
#else
|
||||
#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) static_assert(!(cond) || (expr), reason)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prints |aStr| as an assertion failure (using aFilename and aLine as the
|
||||
* location of the assertion) to the standard debug-output channel.
|
||||
*
|
||||
* Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method. This
|
||||
* method is primarily for internal use in this header, and only secondarily
|
||||
* for use in implementing release-build assertions.
|
||||
*/
|
||||
static MOZ_COLD MOZ_ALWAYS_INLINE void
|
||||
MOZ_ReportAssertionFailure(const char* aStr, const char* aFilename, int aLine)
|
||||
MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
|
||||
{
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
|
||||
"Assertion failure: %s, at %s:%d\n",
|
||||
aStr, aFilename, aLine);
|
||||
#else
|
||||
fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine);
|
||||
#if defined (MOZ_DUMP_ASSERTION_STACK)
|
||||
nsTraceRefcnt::WalkTheStack(stderr);
|
||||
#endif
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static MOZ_COLD MOZ_ALWAYS_INLINE void
|
||||
MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine)
|
||||
MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
|
||||
{
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH",
|
||||
"Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
|
||||
#else
|
||||
fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
|
||||
#if defined(MOZ_DUMP_ASSERTION_STACK)
|
||||
nsTraceRefcnt::WalkTheStack(stderr);
|
||||
#endif
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* MOZ_REALLY_CRASH is used in the implementation of MOZ_CRASH(). You should
|
||||
* call MOZ_CRASH instead.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
/*
|
||||
* On MSVC use the __debugbreak compiler intrinsic, which produces an inline
|
||||
* (not nested in a system function) breakpoint. This distinctively invokes
|
||||
* Breakpad without requiring system library symbols on all stack-processing
|
||||
* machines, as a nested breakpoint would require.
|
||||
*
|
||||
* We use TerminateProcess with the exit code aborting would generate
|
||||
* because we don't want to invoke atexit handlers, destructors, library
|
||||
* unload handlers, and so on when our process might be in a compromised
|
||||
* state.
|
||||
*
|
||||
* We don't use abort() because it'd cause Windows to annoyingly pop up the
|
||||
* process error dialog multiple times. See bug 345118 and bug 426163.
|
||||
*
|
||||
* We follow TerminateProcess() with a call to MOZ_NoReturn() so that the
|
||||
* compiler doesn't hassle us to provide a return statement after a
|
||||
* MOZ_REALLY_CRASH() call.
|
||||
*
|
||||
* (Technically these are Windows requirements, not MSVC requirements. But
|
||||
* practically you need MSVC for debugging, and we only ship builds created
|
||||
* by MSVC, so doing it this way reduces complexity.)
|
||||
*/
|
||||
|
||||
__declspec(noreturn) __inline void MOZ_NoReturn() {}
|
||||
|
||||
# ifdef __cplusplus
|
||||
# define MOZ_REALLY_CRASH() \
|
||||
do { \
|
||||
::__debugbreak(); \
|
||||
*((volatile int*) NULL) = __LINE__; \
|
||||
::TerminateProcess(::GetCurrentProcess(), 3); \
|
||||
::MOZ_NoReturn(); \
|
||||
} while (0)
|
||||
# else
|
||||
# define MOZ_REALLY_CRASH() \
|
||||
do { \
|
||||
__debugbreak(); \
|
||||
*((volatile int*) NULL) = __LINE__; \
|
||||
TerminateProcess(GetCurrentProcess(), 3); \
|
||||
MOZ_NoReturn(); \
|
||||
} while (0)
|
||||
# endif
|
||||
#else
|
||||
# ifdef __cplusplus
|
||||
# define MOZ_REALLY_CRASH() \
|
||||
do { \
|
||||
*((volatile int*) NULL) = __LINE__; \
|
||||
::abort(); \
|
||||
} while (0)
|
||||
# else
|
||||
# define MOZ_REALLY_CRASH() \
|
||||
do { \
|
||||
*((volatile int*) NULL) = __LINE__; \
|
||||
abort(); \
|
||||
} while (0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_CRASH([explanation-string]) crashes the program, plain and simple, in a
|
||||
* Breakpad-compatible way, in both debug and release builds.
|
||||
*
|
||||
* MOZ_CRASH is a good solution for "handling" failure cases when you're
|
||||
* unwilling or unable to handle them more cleanly -- for OOM, for likely memory
|
||||
* corruption, and so on. It's also a good solution if you need safe behavior
|
||||
* in release builds as well as debug builds. But if the failure is one that
|
||||
* should be debugged and fixed, MOZ_ASSERT is generally preferable.
|
||||
*
|
||||
* The optional explanation-string, if provided, must be a string literal
|
||||
* explaining why we're crashing. This argument is intended for use with
|
||||
* MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's
|
||||
* obvious why we're crashing.
|
||||
*
|
||||
* If we're a DEBUG build and we crash at a MOZ_CRASH which provides an
|
||||
* explanation-string, we print the string to stderr. Otherwise, we don't
|
||||
* print anything; this is because we want MOZ_CRASH to be 100% safe in release
|
||||
* builds, and it's hard to print to stderr safely when memory might have been
|
||||
* corrupted.
|
||||
*/
|
||||
#ifndef DEBUG
|
||||
# define MOZ_CRASH(...) \
|
||||
do { \
|
||||
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
|
||||
MOZ_REALLY_CRASH(); \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOZ_CRASH(...) \
|
||||
do { \
|
||||
MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
|
||||
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
|
||||
MOZ_REALLY_CRASH(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in
|
||||
* debug builds. If it is, execution continues. Otherwise, an error message
|
||||
* including the expression and the explanation-string (if provided) is printed,
|
||||
* an attempt is made to invoke any existing debugger, and execution halts.
|
||||
* MOZ_ASSERT is fatal: no recovery is possible. Do not assert a condition
|
||||
* which can correctly be falsy.
|
||||
*
|
||||
* The optional explanation-string, if provided, must be a string literal
|
||||
* explaining the assertion. It is intended for use with assertions whose
|
||||
* correctness or rationale is non-obvious, and for assertions where the "real"
|
||||
* condition being tested is best described prosaically. Don't provide an
|
||||
* explanation if it's not actually helpful.
|
||||
*
|
||||
* // No explanation needed: pointer arguments often must not be NULL.
|
||||
* MOZ_ASSERT(arg);
|
||||
*
|
||||
* // An explanation can be helpful to explain exactly how we know an
|
||||
* // assertion is valid.
|
||||
* MOZ_ASSERT(state == WAITING_FOR_RESPONSE,
|
||||
* "given that <thingA> and <thingB>, we must have...");
|
||||
*
|
||||
* // Or it might disambiguate multiple identical (save for their location)
|
||||
* // assertions of the same expression.
|
||||
* MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
|
||||
* "we already set [[PrimitiveThis]] for this Boolean object");
|
||||
* MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
|
||||
* "we already set [[PrimitiveThis]] for this String object");
|
||||
*
|
||||
* MOZ_ASSERT has no effect in non-debug builds. It is designed to catch bugs
|
||||
* *only* during debugging, not "in the field". If you want the latter, use
|
||||
* MOZ_RELEASE_ASSERT, which applies to non-debug builds as well.
|
||||
*
|
||||
* MOZ_DIAGNOSTIC_ASSERT works like MOZ_RELEASE_ASSERT in Nightly/Aurora and
|
||||
* MOZ_ASSERT in Beta/Release - use this when a condition is potentially rare
|
||||
* enough to require real user testing to hit, but is not security-sensitive.
|
||||
* This can cause user pain, so use it sparingly. If a MOZ_DIAGNOSTIC_ASSERT
|
||||
* is firing, it should promptly be converted to a MOZ_ASSERT while the failure
|
||||
* is being investigated, rather than letting users suffer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implement MOZ_VALIDATE_ASSERT_CONDITION_TYPE, which is used to guard against
|
||||
* accidentally passing something unintended in lieu of an assertion condition.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include "mozilla/TypeTraits.h"
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct AssertionConditionType
|
||||
{
|
||||
typedef typename RemoveReference<T>::Type ValueT;
|
||||
static_assert(!IsArray<ValueT>::value,
|
||||
"Expected boolean assertion condition, got an array or a "
|
||||
"string!");
|
||||
static_assert(!IsFunction<ValueT>::value,
|
||||
"Expected boolean assertion condition, got a function! Did "
|
||||
"you intend to call that function?");
|
||||
static_assert(!IsFloatingPoint<ValueT>::value,
|
||||
"It's often a bad idea to assert that a floating-point number "
|
||||
"is nonzero, because such assertions tend to intermittently "
|
||||
"fail. Shouldn't your code gracefully handle this case instead "
|
||||
"of asserting? Anyway, if you really want to do that, write an "
|
||||
"explicit boolean condition, like !!x or x!=0.");
|
||||
|
||||
static const bool isValid = true;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
# define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x) \
|
||||
static_assert(mozilla::detail::AssertionConditionType<decltype(x)>::isValid, \
|
||||
"invalid assertion condition")
|
||||
#else
|
||||
# define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x)
|
||||
#endif
|
||||
|
||||
/* First the single-argument form. */
|
||||
#define MOZ_ASSERT_HELPER1(expr) \
|
||||
do { \
|
||||
MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
|
||||
if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
|
||||
MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
|
||||
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ")"); \
|
||||
MOZ_REALLY_CRASH(); \
|
||||
} \
|
||||
} while (0)
|
||||
/* Now the two-argument form. */
|
||||
#define MOZ_ASSERT_HELPER2(expr, explain) \
|
||||
do { \
|
||||
MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
|
||||
if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
|
||||
MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
|
||||
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ") (" explain ")"); \
|
||||
MOZ_REALLY_CRASH(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MOZ_RELEASE_ASSERT_GLUE(a, b) a b
|
||||
#define MOZ_RELEASE_ASSERT(...) \
|
||||
MOZ_RELEASE_ASSERT_GLUE( \
|
||||
MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \
|
||||
(__VA_ARGS__))
|
||||
|
||||
#ifdef DEBUG
|
||||
# define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
|
||||
#else
|
||||
# define MOZ_ASSERT(...) do { } while (0)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef RELEASE_OR_BETA
|
||||
# define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT
|
||||
#else
|
||||
# define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
|
||||
* true.
|
||||
*
|
||||
* MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
|
||||
*
|
||||
* As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds. It is
|
||||
* designed to catch bugs during debugging, not "in the field".
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define MOZ_ASSERT_IF(cond, expr) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
MOZ_ASSERT(expr); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOZ_ASSERT_IF(cond, expr) do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ASSUME_UNREACHABLE_MARKER() expands to an expression which states that
|
||||
* it is undefined behavior for execution to reach this point. No guarantees
|
||||
* are made about what will happen if this is reached at runtime. Most code
|
||||
* should use MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE because it has extra
|
||||
* asserts.
|
||||
*/
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
# define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_ASSUME_UNREACHABLE_MARKER() __assume(0)
|
||||
#else
|
||||
# ifdef __cplusplus
|
||||
# define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort()
|
||||
# else
|
||||
# define MOZ_ASSUME_UNREACHABLE_MARKER() abort()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE([reason]) tells the compiler that it
|
||||
* can assume that the macro call cannot be reached during execution. This lets
|
||||
* the compiler generate better-optimized code under some circumstances, at the
|
||||
* expense of the program's behavior being undefined if control reaches the
|
||||
* MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE.
|
||||
*
|
||||
* In Gecko, you probably should not use this macro outside of performance- or
|
||||
* size-critical code, because it's unsafe. If you don't care about code size
|
||||
* or performance, you should probably use MOZ_ASSERT or MOZ_CRASH.
|
||||
*
|
||||
* SpiderMonkey is a different beast, and there it's acceptable to use
|
||||
* MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE more widely.
|
||||
*
|
||||
* Note that MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE is noreturn, so it's valid
|
||||
* not to return a value following a MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE
|
||||
* call.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* enum ValueType {
|
||||
* VALUE_STRING,
|
||||
* VALUE_INT,
|
||||
* VALUE_FLOAT
|
||||
* };
|
||||
*
|
||||
* int ptrToInt(ValueType type, void* value) {
|
||||
* {
|
||||
* // We know for sure that type is either INT or FLOAT, and we want this
|
||||
* // code to run as quickly as possible.
|
||||
* switch (type) {
|
||||
* case VALUE_INT:
|
||||
* return *(int*) value;
|
||||
* case VALUE_FLOAT:
|
||||
* return (int) *(float*) value;
|
||||
* default:
|
||||
* MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected ValueType");
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unconditional assert in debug builds for (assumed) unreachable code paths
|
||||
* that have a safe return without crashing in release builds.
|
||||
*/
|
||||
#define MOZ_ASSERT_UNREACHABLE(reason) \
|
||||
MOZ_ASSERT(false, "MOZ_ASSERT_UNREACHABLE: " reason)
|
||||
|
||||
#define MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(reason) \
|
||||
do { \
|
||||
MOZ_ASSERT_UNREACHABLE(reason); \
|
||||
MOZ_ASSUME_UNREACHABLE_MARKER(); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
|
||||
* switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
|
||||
* debug builds, but intentionally fall through in release builds to handle
|
||||
* unexpected values.
|
||||
*
|
||||
* Why do we need MOZ_FALLTHROUGH_ASSERT in addition to MOZ_FALLTHROUGH? In
|
||||
* release builds, the MOZ_ASSERT(false) will expand to `do { } while (0)`,
|
||||
* requiring a MOZ_FALLTHROUGH annotation to suppress a -Wimplicit-fallthrough
|
||||
* warning. In debug builds, the MOZ_ASSERT(false) will expand to something like
|
||||
* `if (true) { MOZ_CRASH(); }` and the MOZ_FALLTHROUGH annotation will cause
|
||||
* a -Wunreachable-code warning. The MOZ_FALLTHROUGH_ASSERT macro breaks this
|
||||
* warning stalemate.
|
||||
*
|
||||
* // Example before MOZ_FALLTHROUGH_ASSERT:
|
||||
* switch (foo) {
|
||||
* default:
|
||||
* // This case wants to assert in debug builds, fall through in release.
|
||||
* MOZ_ASSERT(false); // -Wimplicit-fallthrough warning in release builds!
|
||||
* MOZ_FALLTHROUGH; // but -Wunreachable-code warning in debug builds!
|
||||
* case 5:
|
||||
* return 5;
|
||||
* }
|
||||
*
|
||||
* // Example with MOZ_FALLTHROUGH_ASSERT:
|
||||
* switch (foo) {
|
||||
* default:
|
||||
* // This case asserts in debug builds, falls through in release.
|
||||
* MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
|
||||
* case 5:
|
||||
* return 5;
|
||||
* }
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define MOZ_FALLTHROUGH_ASSERT(reason) MOZ_CRASH("MOZ_FALLTHROUGH_ASSERT: " reason)
|
||||
#else
|
||||
# define MOZ_FALLTHROUGH_ASSERT(...) MOZ_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
|
||||
* expression, in debug builds and in release builds both. Then, in debug
|
||||
* builds only, the value of the expression is asserted either true or false
|
||||
* using MOZ_ASSERT.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define MOZ_ALWAYS_TRUE(expr) \
|
||||
do { \
|
||||
if ((expr)) { \
|
||||
/* Do nothing. */ \
|
||||
} else { \
|
||||
MOZ_ASSERT(false, #expr); \
|
||||
} \
|
||||
} while (0)
|
||||
# define MOZ_ALWAYS_FALSE(expr) \
|
||||
do { \
|
||||
if ((expr)) { \
|
||||
MOZ_ASSERT(false, #expr); \
|
||||
} else { \
|
||||
/* Do nothing. */ \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOZ_ALWAYS_TRUE(expr) \
|
||||
do { \
|
||||
if ((expr)) { \
|
||||
/* Silence MOZ_MUST_USE. */ \
|
||||
} \
|
||||
} while (0)
|
||||
# define MOZ_ALWAYS_FALSE(expr) \
|
||||
do { \
|
||||
if ((expr)) { \
|
||||
/* Silence MOZ_MUST_USE. */ \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#undef MOZ_DUMP_ASSERTION_STACK
|
||||
#undef MOZ_CRASH_CRASHREPORT
|
||||
|
||||
#endif /* mozilla_Assertions_h */
|
||||
800
cocos2d-x/external/win32/include/spidermonkey/mozilla/Atomics.h
vendored
Executable file
800
cocos2d-x/external/win32/include/spidermonkey/mozilla/Atomics.h
vendored
Executable file
@@ -0,0 +1,800 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Implements (almost always) lock-free atomic operations. The operations here
|
||||
* are a subset of that which can be found in C++11's <atomic> header, with a
|
||||
* different API to enforce consistent memory ordering constraints.
|
||||
*
|
||||
* Anyone caught using |volatile| for inter-thread memory safety needs to be
|
||||
* sent a copy of this header and the C++11 standard.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_Atomics_h
|
||||
#define mozilla_Atomics_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Our minimum deployment target on clang/OS X is OS X 10.6, whose SDK
|
||||
* does not have <atomic>. So be sure to check for <atomic> support
|
||||
* along with C++0x support.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
# define MOZ_HAVE_CXX11_ATOMICS
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
/*
|
||||
* Clang doesn't like <atomic> from libstdc++ before 4.7 due to the
|
||||
* loose typing of the atomic builtins. GCC 4.5 and 4.6 lacks inline
|
||||
* definitions for unspecialized std::atomic and causes linking errors.
|
||||
* Therefore, we require at least 4.7.0 for using libstdc++.
|
||||
*
|
||||
* libc++ <atomic> is only functional with clang.
|
||||
*/
|
||||
# if MOZ_USING_LIBSTDCXX && MOZ_LIBSTDCXX_VERSION_AT_LEAST(4, 7, 0)
|
||||
# define MOZ_HAVE_CXX11_ATOMICS
|
||||
# elif MOZ_USING_LIBCXX && defined(__clang__)
|
||||
# define MOZ_HAVE_CXX11_ATOMICS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* An enum of memory ordering possibilities for atomics.
|
||||
*
|
||||
* Memory ordering is the observable state of distinct values in memory.
|
||||
* (It's a separate concept from atomicity, which concerns whether an
|
||||
* operation can ever be observed in an intermediate state. Don't
|
||||
* conflate the two!) Given a sequence of operations in source code on
|
||||
* memory, it is *not* always the case that, at all times and on all
|
||||
* cores, those operations will appear to have occurred in that exact
|
||||
* sequence. First, the compiler might reorder that sequence, if it
|
||||
* thinks another ordering will be more efficient. Second, the CPU may
|
||||
* not expose so consistent a view of memory. CPUs will often perform
|
||||
* their own instruction reordering, above and beyond that performed by
|
||||
* the compiler. And each core has its own memory caches, and accesses
|
||||
* (reads and writes both) to "memory" may only resolve to out-of-date
|
||||
* cache entries -- not to the "most recently" performed operation in
|
||||
* some global sense. Any access to a value that may be used by
|
||||
* multiple threads, potentially across multiple cores, must therefore
|
||||
* have a memory ordering imposed on it, for all code on all
|
||||
* threads/cores to have a sufficiently coherent worldview.
|
||||
*
|
||||
* http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync and
|
||||
* http://en.cppreference.com/w/cpp/atomic/memory_order go into more
|
||||
* detail on all this, including examples of how each mode works.
|
||||
*
|
||||
* Note that for simplicity and practicality, not all of the modes in
|
||||
* C++11 are supported. The missing C++11 modes are either subsumed by
|
||||
* the modes we provide below, or not relevant for the CPUs we support
|
||||
* in Gecko. These three modes are confusing enough as it is!
|
||||
*/
|
||||
enum MemoryOrdering {
|
||||
/*
|
||||
* Relaxed ordering is the simplest memory ordering: none at all.
|
||||
* When the result of a write is observed, nothing may be inferred
|
||||
* about other memory. Writes ostensibly performed "before" on the
|
||||
* writing thread may not yet be visible. Writes performed "after" on
|
||||
* the writing thread may already be visible, if the compiler or CPU
|
||||
* reordered them. (The latter can happen if reads and/or writes get
|
||||
* held up in per-processor caches.) Relaxed ordering means
|
||||
* operations can always use cached values (as long as the actual
|
||||
* updates to atomic values actually occur, correctly, eventually), so
|
||||
* it's usually the fastest sort of atomic access. For this reason,
|
||||
* *it's also the most dangerous kind of access*.
|
||||
*
|
||||
* Relaxed ordering is good for things like process-wide statistics
|
||||
* counters that don't need to be consistent with anything else, so
|
||||
* long as updates themselves are atomic. (And so long as any
|
||||
* observations of that value can tolerate being out-of-date -- if you
|
||||
* need some sort of up-to-date value, you need some sort of other
|
||||
* synchronizing operation.) It's *not* good for locks, mutexes,
|
||||
* reference counts, etc. that mediate access to other memory, or must
|
||||
* be observably consistent with other memory.
|
||||
*
|
||||
* x86 architectures don't take advantage of the optimization
|
||||
* opportunities that relaxed ordering permits. Thus it's possible
|
||||
* that using relaxed ordering will "work" on x86 but fail elsewhere
|
||||
* (ARM, say, which *does* implement non-sequentially-consistent
|
||||
* relaxed ordering semantics). Be extra-careful using relaxed
|
||||
* ordering if you can't easily test non-x86 architectures!
|
||||
*/
|
||||
Relaxed,
|
||||
|
||||
/*
|
||||
* When an atomic value is updated with ReleaseAcquire ordering, and
|
||||
* that new value is observed with ReleaseAcquire ordering, prior
|
||||
* writes (atomic or not) are also observable. What ReleaseAcquire
|
||||
* *doesn't* give you is any observable ordering guarantees for
|
||||
* ReleaseAcquire-ordered operations on different objects. For
|
||||
* example, if there are two cores that each perform ReleaseAcquire
|
||||
* operations on separate objects, each core may or may not observe
|
||||
* the operations made by the other core. The only way the cores can
|
||||
* be synchronized with ReleaseAcquire is if they both
|
||||
* ReleaseAcquire-access the same object. This implies that you can't
|
||||
* necessarily describe some global total ordering of ReleaseAcquire
|
||||
* operations.
|
||||
*
|
||||
* ReleaseAcquire ordering is good for (as the name implies) atomic
|
||||
* operations on values controlling ownership of things: reference
|
||||
* counts, mutexes, and the like. However, if you are thinking about
|
||||
* using these to implement your own locks or mutexes, you should take
|
||||
* a good, hard look at actual lock or mutex primitives first.
|
||||
*/
|
||||
ReleaseAcquire,
|
||||
|
||||
/*
|
||||
* When an atomic value is updated with SequentiallyConsistent
|
||||
* ordering, all writes observable when the update is observed, just
|
||||
* as with ReleaseAcquire ordering. But, furthermore, a global total
|
||||
* ordering of SequentiallyConsistent operations *can* be described.
|
||||
* For example, if two cores perform SequentiallyConsistent operations
|
||||
* on separate objects, one core will observably perform its update
|
||||
* (and all previous operations will have completed), then the other
|
||||
* core will observably perform its update (and all previous
|
||||
* operations will have completed). (Although those previous
|
||||
* operations aren't themselves ordered -- they could be intermixed,
|
||||
* or ordered if they occur on atomic values with ordering
|
||||
* requirements.) SequentiallyConsistent is the *simplest and safest*
|
||||
* ordering of atomic operations -- it's always as if one operation
|
||||
* happens, then another, then another, in some order -- and every
|
||||
* core observes updates to happen in that single order. Because it
|
||||
* has the most synchronization requirements, operations ordered this
|
||||
* way also tend to be slowest.
|
||||
*
|
||||
* SequentiallyConsistent ordering can be desirable when multiple
|
||||
* threads observe objects, and they all have to agree on the
|
||||
* observable order of changes to them. People expect
|
||||
* SequentiallyConsistent ordering, even if they shouldn't, when
|
||||
* writing code, atomic or otherwise. SequentiallyConsistent is also
|
||||
* the ordering of choice when designing lockless data structures. If
|
||||
* you don't know what order to use, use this one.
|
||||
*/
|
||||
SequentiallyConsistent,
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// Build up the underlying intrinsics.
|
||||
#ifdef MOZ_HAVE_CXX11_ATOMICS
|
||||
|
||||
# include <atomic>
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* We provide CompareExchangeFailureOrder to work around a bug in some
|
||||
* versions of GCC's <atomic> header. See bug 898491.
|
||||
*/
|
||||
template<MemoryOrdering Order> struct AtomicOrderConstraints;
|
||||
|
||||
template<>
|
||||
struct AtomicOrderConstraints<Relaxed>
|
||||
{
|
||||
static const std::memory_order AtomicRMWOrder = std::memory_order_relaxed;
|
||||
static const std::memory_order LoadOrder = std::memory_order_relaxed;
|
||||
static const std::memory_order StoreOrder = std::memory_order_relaxed;
|
||||
static const std::memory_order CompareExchangeFailureOrder =
|
||||
std::memory_order_relaxed;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AtomicOrderConstraints<ReleaseAcquire>
|
||||
{
|
||||
static const std::memory_order AtomicRMWOrder = std::memory_order_acq_rel;
|
||||
static const std::memory_order LoadOrder = std::memory_order_acquire;
|
||||
static const std::memory_order StoreOrder = std::memory_order_release;
|
||||
static const std::memory_order CompareExchangeFailureOrder =
|
||||
std::memory_order_acquire;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AtomicOrderConstraints<SequentiallyConsistent>
|
||||
{
|
||||
static const std::memory_order AtomicRMWOrder = std::memory_order_seq_cst;
|
||||
static const std::memory_order LoadOrder = std::memory_order_seq_cst;
|
||||
static const std::memory_order StoreOrder = std::memory_order_seq_cst;
|
||||
static const std::memory_order CompareExchangeFailureOrder =
|
||||
std::memory_order_seq_cst;
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicBase
|
||||
{
|
||||
typedef std::atomic<T> ValueType;
|
||||
typedef AtomicOrderConstraints<Order> OrderedOp;
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicMemoryOps : public IntrinsicBase<T, Order>
|
||||
{
|
||||
typedef IntrinsicBase<T, Order> Base;
|
||||
|
||||
static T load(const typename Base::ValueType& aPtr)
|
||||
{
|
||||
return aPtr.load(Base::OrderedOp::LoadOrder);
|
||||
}
|
||||
|
||||
static void store(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
aPtr.store(aVal, Base::OrderedOp::StoreOrder);
|
||||
}
|
||||
|
||||
static T exchange(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
return aPtr.exchange(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
|
||||
static bool compareExchange(typename Base::ValueType& aPtr,
|
||||
T aOldVal, T aNewVal)
|
||||
{
|
||||
return aPtr.compare_exchange_strong(aOldVal, aNewVal,
|
||||
Base::OrderedOp::AtomicRMWOrder,
|
||||
Base::OrderedOp::CompareExchangeFailureOrder);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicAddSub : public IntrinsicBase<T, Order>
|
||||
{
|
||||
typedef IntrinsicBase<T, Order> Base;
|
||||
|
||||
static T add(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
return aPtr.fetch_add(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
|
||||
static T sub(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
return aPtr.fetch_sub(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicAddSub<T*, Order> : public IntrinsicBase<T*, Order>
|
||||
{
|
||||
typedef IntrinsicBase<T*, Order> Base;
|
||||
|
||||
static T* add(typename Base::ValueType& aPtr, ptrdiff_t aVal)
|
||||
{
|
||||
return aPtr.fetch_add(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
|
||||
static T* sub(typename Base::ValueType& aPtr, ptrdiff_t aVal)
|
||||
{
|
||||
return aPtr.fetch_sub(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicIncDec : public IntrinsicAddSub<T, Order>
|
||||
{
|
||||
typedef IntrinsicBase<T, Order> Base;
|
||||
|
||||
static T inc(typename Base::ValueType& aPtr)
|
||||
{
|
||||
return IntrinsicAddSub<T, Order>::add(aPtr, 1);
|
||||
}
|
||||
|
||||
static T dec(typename Base::ValueType& aPtr)
|
||||
{
|
||||
return IntrinsicAddSub<T, Order>::sub(aPtr, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct AtomicIntrinsics : public IntrinsicMemoryOps<T, Order>,
|
||||
public IntrinsicIncDec<T, Order>
|
||||
{
|
||||
typedef IntrinsicBase<T, Order> Base;
|
||||
|
||||
static T or_(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
return aPtr.fetch_or(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
|
||||
static T xor_(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
return aPtr.fetch_xor(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
|
||||
static T and_(typename Base::ValueType& aPtr, T aVal)
|
||||
{
|
||||
return aPtr.fetch_and(aVal, Base::OrderedOp::AtomicRMWOrder);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct AtomicIntrinsics<T*, Order>
|
||||
: public IntrinsicMemoryOps<T*, Order>, public IntrinsicIncDec<T*, Order>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ToStorageTypeArgument
|
||||
{
|
||||
static constexpr T convert (T aT) { return aT; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* The __sync_* family of intrinsics is documented here:
|
||||
*
|
||||
* http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Atomic-Builtins.html
|
||||
*
|
||||
* While these intrinsics are deprecated in favor of the newer __atomic_*
|
||||
* family of intrincs:
|
||||
*
|
||||
* http://gcc.gnu.org/onlinedocs/gcc-4.7.3/gcc/_005f_005fatomic-Builtins.html
|
||||
*
|
||||
* any GCC version that supports the __atomic_* intrinsics will also support
|
||||
* the <atomic> header and so will be handled above. We provide a version of
|
||||
* atomics using the __sync_* intrinsics to support older versions of GCC.
|
||||
*
|
||||
* All __sync_* intrinsics that we use below act as full memory barriers, for
|
||||
* both compiler and hardware reordering, except for __sync_lock_test_and_set,
|
||||
* which is a only an acquire barrier. When we call __sync_lock_test_and_set,
|
||||
* we add a barrier above it as appropriate.
|
||||
*/
|
||||
|
||||
template<MemoryOrdering Order> struct Barrier;
|
||||
|
||||
/*
|
||||
* Some processors (in particular, x86) don't require quite so many calls to
|
||||
* __sync_sychronize as our specializations of Barrier produce. If
|
||||
* performance turns out to be an issue, defining these specializations
|
||||
* on a per-processor basis would be a good first tuning step.
|
||||
*/
|
||||
|
||||
template<>
|
||||
struct Barrier<Relaxed>
|
||||
{
|
||||
static void beforeLoad() {}
|
||||
static void afterLoad() {}
|
||||
static void beforeStore() {}
|
||||
static void afterStore() {}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Barrier<ReleaseAcquire>
|
||||
{
|
||||
static void beforeLoad() {}
|
||||
static void afterLoad() { __sync_synchronize(); }
|
||||
static void beforeStore() { __sync_synchronize(); }
|
||||
static void afterStore() {}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Barrier<SequentiallyConsistent>
|
||||
{
|
||||
static void beforeLoad() { __sync_synchronize(); }
|
||||
static void afterLoad() { __sync_synchronize(); }
|
||||
static void beforeStore() { __sync_synchronize(); }
|
||||
static void afterStore() { __sync_synchronize(); }
|
||||
};
|
||||
|
||||
template<typename T, bool TIsEnum = IsEnum<T>::value>
|
||||
struct AtomicStorageType
|
||||
{
|
||||
// For non-enums, just use the type directly.
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct AtomicStorageType<T, true>
|
||||
: Conditional<sizeof(T) == 4, uint32_t, uint64_t>
|
||||
{
|
||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8,
|
||||
"wrong type computed in conditional above");
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicMemoryOps
|
||||
{
|
||||
typedef typename AtomicStorageType<T>::Type ValueType;
|
||||
|
||||
static T load(const ValueType& aPtr)
|
||||
{
|
||||
Barrier<Order>::beforeLoad();
|
||||
T val = T(aPtr);
|
||||
Barrier<Order>::afterLoad();
|
||||
return val;
|
||||
}
|
||||
|
||||
static void store(ValueType& aPtr, T aVal)
|
||||
{
|
||||
Barrier<Order>::beforeStore();
|
||||
aPtr = ValueType(aVal);
|
||||
Barrier<Order>::afterStore();
|
||||
}
|
||||
|
||||
static T exchange(ValueType& aPtr, T aVal)
|
||||
{
|
||||
// __sync_lock_test_and_set is only an acquire barrier; loads and stores
|
||||
// can't be moved up from after to before it, but they can be moved down
|
||||
// from before to after it. We may want a stricter ordering, so we need
|
||||
// an explicit barrier.
|
||||
Barrier<Order>::beforeStore();
|
||||
return T(__sync_lock_test_and_set(&aPtr, ValueType(aVal)));
|
||||
}
|
||||
|
||||
static bool compareExchange(ValueType& aPtr, T aOldVal, T aNewVal)
|
||||
{
|
||||
return __sync_bool_compare_and_swap(&aPtr, ValueType(aOldVal), ValueType(aNewVal));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicAddSub
|
||||
: public IntrinsicMemoryOps<T, Order>
|
||||
{
|
||||
typedef IntrinsicMemoryOps<T, Order> Base;
|
||||
typedef typename Base::ValueType ValueType;
|
||||
|
||||
static T add(ValueType& aPtr, T aVal)
|
||||
{
|
||||
return T(__sync_fetch_and_add(&aPtr, ValueType(aVal)));
|
||||
}
|
||||
|
||||
static T sub(ValueType& aPtr, T aVal)
|
||||
{
|
||||
return T(__sync_fetch_and_sub(&aPtr, ValueType(aVal)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicAddSub<T*, Order>
|
||||
: public IntrinsicMemoryOps<T*, Order>
|
||||
{
|
||||
typedef IntrinsicMemoryOps<T*, Order> Base;
|
||||
typedef typename Base::ValueType ValueType;
|
||||
|
||||
/*
|
||||
* The reinterpret_casts are needed so that
|
||||
* __sync_fetch_and_{add,sub} will properly type-check.
|
||||
*
|
||||
* Also, these functions do not provide standard semantics for
|
||||
* pointer types, so we need to adjust the addend.
|
||||
*/
|
||||
static ValueType add(ValueType& aPtr, ptrdiff_t aVal)
|
||||
{
|
||||
ValueType amount = reinterpret_cast<ValueType>(aVal * sizeof(T));
|
||||
return __sync_fetch_and_add(&aPtr, amount);
|
||||
}
|
||||
|
||||
static ValueType sub(ValueType& aPtr, ptrdiff_t aVal)
|
||||
{
|
||||
ValueType amount = reinterpret_cast<ValueType>(aVal * sizeof(T));
|
||||
return __sync_fetch_and_sub(&aPtr, amount);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct IntrinsicIncDec : public IntrinsicAddSub<T, Order>
|
||||
{
|
||||
typedef IntrinsicAddSub<T, Order> Base;
|
||||
typedef typename Base::ValueType ValueType;
|
||||
|
||||
static T inc(ValueType& aPtr) { return Base::add(aPtr, 1); }
|
||||
static T dec(ValueType& aPtr) { return Base::sub(aPtr, 1); }
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct AtomicIntrinsics : public IntrinsicIncDec<T, Order>
|
||||
{
|
||||
static T or_( T& aPtr, T aVal) { return __sync_fetch_and_or(&aPtr, aVal); }
|
||||
static T xor_(T& aPtr, T aVal) { return __sync_fetch_and_xor(&aPtr, aVal); }
|
||||
static T and_(T& aPtr, T aVal) { return __sync_fetch_and_and(&aPtr, aVal); }
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
struct AtomicIntrinsics<T*, Order> : public IntrinsicIncDec<T*, Order>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T, bool TIsEnum = IsEnum<T>::value>
|
||||
struct ToStorageTypeArgument
|
||||
{
|
||||
typedef typename AtomicStorageType<T>::Type ResultType;
|
||||
|
||||
static constexpr ResultType convert (T aT) { return ResultType(aT); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ToStorageTypeArgument<T, false>
|
||||
{
|
||||
static constexpr T convert (T aT) { return aT; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
#else
|
||||
# error "Atomic compiler intrinsics are not supported on your platform"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
class AtomicBase
|
||||
{
|
||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8,
|
||||
"mozilla/Atomics.h only supports 32-bit and 64-bit types");
|
||||
|
||||
protected:
|
||||
typedef typename detail::AtomicIntrinsics<T, Order> Intrinsics;
|
||||
typedef typename Intrinsics::ValueType ValueType;
|
||||
ValueType mValue;
|
||||
|
||||
public:
|
||||
constexpr AtomicBase() : mValue() {}
|
||||
explicit constexpr AtomicBase(T aInit)
|
||||
: mValue(ToStorageTypeArgument<T>::convert(aInit))
|
||||
{}
|
||||
|
||||
// Note: we can't provide operator T() here because Atomic<bool> inherits
|
||||
// from AtomcBase with T=uint32_t and not T=bool. If we implemented
|
||||
// operator T() here, it would cause errors when comparing Atomic<bool> with
|
||||
// a regular bool.
|
||||
|
||||
T operator=(T aVal)
|
||||
{
|
||||
Intrinsics::store(mValue, aVal);
|
||||
return aVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an atomic swap operation. aVal is stored and the previous
|
||||
* value of this variable is returned.
|
||||
*/
|
||||
T exchange(T aVal)
|
||||
{
|
||||
return Intrinsics::exchange(mValue, aVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an atomic compare-and-swap operation and returns true if it
|
||||
* succeeded. This is equivalent to atomically doing
|
||||
*
|
||||
* if (mValue == aOldValue) {
|
||||
* mValue = aNewValue;
|
||||
* return true;
|
||||
* } else {
|
||||
* return false;
|
||||
* }
|
||||
*/
|
||||
bool compareExchange(T aOldValue, T aNewValue)
|
||||
{
|
||||
return Intrinsics::compareExchange(mValue, aOldValue, aNewValue);
|
||||
}
|
||||
|
||||
private:
|
||||
template<MemoryOrdering AnyOrder>
|
||||
AtomicBase(const AtomicBase<T, AnyOrder>& aCopy) = delete;
|
||||
};
|
||||
|
||||
template<typename T, MemoryOrdering Order>
|
||||
class AtomicBaseIncDec : public AtomicBase<T, Order>
|
||||
{
|
||||
typedef typename detail::AtomicBase<T, Order> Base;
|
||||
|
||||
public:
|
||||
constexpr AtomicBaseIncDec() : Base() {}
|
||||
explicit constexpr AtomicBaseIncDec(T aInit) : Base(aInit) {}
|
||||
|
||||
using Base::operator=;
|
||||
|
||||
operator T() const { return Base::Intrinsics::load(Base::mValue); }
|
||||
T operator++(int) { return Base::Intrinsics::inc(Base::mValue); }
|
||||
T operator--(int) { return Base::Intrinsics::dec(Base::mValue); }
|
||||
T operator++() { return Base::Intrinsics::inc(Base::mValue) + 1; }
|
||||
T operator--() { return Base::Intrinsics::dec(Base::mValue) - 1; }
|
||||
|
||||
private:
|
||||
template<MemoryOrdering AnyOrder>
|
||||
AtomicBaseIncDec(const AtomicBaseIncDec<T, AnyOrder>& aCopy) = delete;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* A wrapper for a type that enforces that all memory accesses are atomic.
|
||||
*
|
||||
* In general, where a variable |T foo| exists, |Atomic<T> foo| can be used in
|
||||
* its place. Implementations for integral and pointer types are provided
|
||||
* below.
|
||||
*
|
||||
* Atomic accesses are sequentially consistent by default. You should
|
||||
* use the default unless you are tall enough to ride the
|
||||
* memory-ordering roller coaster (if you're not sure, you aren't) and
|
||||
* you have a compelling reason to do otherwise.
|
||||
*
|
||||
* There is one exception to the case of atomic memory accesses: providing an
|
||||
* initial value of the atomic value is not guaranteed to be atomic. This is a
|
||||
* deliberate design choice that enables static atomic variables to be declared
|
||||
* without introducing extra static constructors.
|
||||
*/
|
||||
template<typename T,
|
||||
MemoryOrdering Order = SequentiallyConsistent,
|
||||
typename Enable = void>
|
||||
class Atomic;
|
||||
|
||||
/**
|
||||
* Atomic<T> implementation for integral types.
|
||||
*
|
||||
* In addition to atomic store and load operations, compound assignment and
|
||||
* increment/decrement operators are implemented which perform the
|
||||
* corresponding read-modify-write operation atomically. Finally, an atomic
|
||||
* swap method is provided.
|
||||
*/
|
||||
template<typename T, MemoryOrdering Order>
|
||||
class Atomic<T, Order, typename EnableIf<IsIntegral<T>::value &&
|
||||
!IsSame<T, bool>::value>::Type>
|
||||
: public detail::AtomicBaseIncDec<T, Order>
|
||||
{
|
||||
typedef typename detail::AtomicBaseIncDec<T, Order> Base;
|
||||
|
||||
public:
|
||||
constexpr Atomic() : Base() {}
|
||||
explicit constexpr Atomic(T aInit) : Base(aInit) {}
|
||||
|
||||
using Base::operator=;
|
||||
|
||||
T operator+=(T aDelta)
|
||||
{
|
||||
return Base::Intrinsics::add(Base::mValue, aDelta) + aDelta;
|
||||
}
|
||||
|
||||
T operator-=(T aDelta)
|
||||
{
|
||||
return Base::Intrinsics::sub(Base::mValue, aDelta) - aDelta;
|
||||
}
|
||||
|
||||
T operator|=(T aVal)
|
||||
{
|
||||
return Base::Intrinsics::or_(Base::mValue, aVal) | aVal;
|
||||
}
|
||||
|
||||
T operator^=(T aVal)
|
||||
{
|
||||
return Base::Intrinsics::xor_(Base::mValue, aVal) ^ aVal;
|
||||
}
|
||||
|
||||
T operator&=(T aVal)
|
||||
{
|
||||
return Base::Intrinsics::and_(Base::mValue, aVal) & aVal;
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic(Atomic<T, Order>& aOther) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Atomic<T> implementation for pointer types.
|
||||
*
|
||||
* An atomic compare-and-swap primitive for pointer variables is provided, as
|
||||
* are atomic increment and decement operators. Also provided are the compound
|
||||
* assignment operators for addition and subtraction. Atomic swap (via
|
||||
* exchange()) is included as well.
|
||||
*/
|
||||
template<typename T, MemoryOrdering Order>
|
||||
class Atomic<T*, Order> : public detail::AtomicBaseIncDec<T*, Order>
|
||||
{
|
||||
typedef typename detail::AtomicBaseIncDec<T*, Order> Base;
|
||||
|
||||
public:
|
||||
constexpr Atomic() : Base() {}
|
||||
explicit constexpr Atomic(T* aInit) : Base(aInit) {}
|
||||
|
||||
using Base::operator=;
|
||||
|
||||
T* operator+=(ptrdiff_t aDelta)
|
||||
{
|
||||
return Base::Intrinsics::add(Base::mValue, aDelta) + aDelta;
|
||||
}
|
||||
|
||||
T* operator-=(ptrdiff_t aDelta)
|
||||
{
|
||||
return Base::Intrinsics::sub(Base::mValue, aDelta) - aDelta;
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic(Atomic<T*, Order>& aOther) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Atomic<T> implementation for enum types.
|
||||
*
|
||||
* The atomic store and load operations and the atomic swap method is provided.
|
||||
*/
|
||||
template<typename T, MemoryOrdering Order>
|
||||
class Atomic<T, Order, typename EnableIf<IsEnum<T>::value>::Type>
|
||||
: public detail::AtomicBase<T, Order>
|
||||
{
|
||||
typedef typename detail::AtomicBase<T, Order> Base;
|
||||
|
||||
public:
|
||||
constexpr Atomic() : Base() {}
|
||||
explicit constexpr Atomic(T aInit) : Base(aInit) {}
|
||||
|
||||
operator T() const { return T(Base::Intrinsics::load(Base::mValue)); }
|
||||
|
||||
using Base::operator=;
|
||||
|
||||
private:
|
||||
Atomic(Atomic<T, Order>& aOther) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Atomic<T> implementation for boolean types.
|
||||
*
|
||||
* The atomic store and load operations and the atomic swap method is provided.
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* - sizeof(Atomic<bool>) != sizeof(bool) for some implementations of
|
||||
* bool and/or some implementations of std::atomic. This is allowed in
|
||||
* [atomic.types.generic]p9.
|
||||
*
|
||||
* - It's not obvious whether the 8-bit atomic functions on Windows are always
|
||||
* inlined or not. If they are not inlined, the corresponding functions in the
|
||||
* runtime library are not available on Windows XP. This is why we implement
|
||||
* Atomic<bool> with an underlying type of uint32_t.
|
||||
*/
|
||||
template<MemoryOrdering Order>
|
||||
class Atomic<bool, Order>
|
||||
: protected detail::AtomicBase<uint32_t, Order>
|
||||
{
|
||||
typedef typename detail::AtomicBase<uint32_t, Order> Base;
|
||||
|
||||
public:
|
||||
constexpr Atomic() : Base() {}
|
||||
explicit constexpr Atomic(bool aInit) : Base(aInit) {}
|
||||
|
||||
// We provide boolean wrappers for the underlying AtomicBase methods.
|
||||
MOZ_IMPLICIT operator bool() const
|
||||
{
|
||||
return Base::Intrinsics::load(Base::mValue);
|
||||
}
|
||||
|
||||
bool operator=(bool aVal)
|
||||
{
|
||||
return Base::operator=(aVal);
|
||||
}
|
||||
|
||||
bool exchange(bool aVal)
|
||||
{
|
||||
return Base::exchange(aVal);
|
||||
}
|
||||
|
||||
bool compareExchange(bool aOldValue, bool aNewValue)
|
||||
{
|
||||
return Base::compareExchange(aOldValue, aNewValue);
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic(Atomic<bool, Order>& aOther) = delete;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Atomics_h */
|
||||
604
cocos2d-x/external/win32/include/spidermonkey/mozilla/Attributes.h
vendored
Executable file
604
cocos2d-x/external/win32/include/spidermonkey/mozilla/Attributes.h
vendored
Executable file
@@ -0,0 +1,604 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implementations of various class and method modifier attributes. */
|
||||
|
||||
#ifndef mozilla_Attributes_h
|
||||
#define mozilla_Attributes_h
|
||||
|
||||
#include "mozilla/Compiler.h"
|
||||
|
||||
/*
|
||||
* MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
|
||||
* method decorated with it must be inlined, even if the compiler thinks
|
||||
* otherwise. This is only a (much) stronger version of the inline hint:
|
||||
* compilers are not guaranteed to respect it (although they're much more likely
|
||||
* to do so).
|
||||
*
|
||||
* The MOZ_ALWAYS_INLINE_EVEN_DEBUG macro is yet stronger. It tells the
|
||||
* compiler to inline even in DEBUG builds. It should be used very rarely.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
# define MOZ_ALWAYS_INLINE_EVEN_DEBUG __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
# define MOZ_ALWAYS_INLINE_EVEN_DEBUG __attribute__((always_inline)) inline
|
||||
#else
|
||||
# define MOZ_ALWAYS_INLINE_EVEN_DEBUG inline
|
||||
#endif
|
||||
|
||||
#if !defined(DEBUG)
|
||||
# define MOZ_ALWAYS_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
#elif defined(_MSC_VER) && !defined(__cplusplus)
|
||||
# define MOZ_ALWAYS_INLINE __inline
|
||||
#else
|
||||
# define MOZ_ALWAYS_INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/*
|
||||
* g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality
|
||||
* without warnings (functionality used by the macros below). These modes are
|
||||
* detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, more
|
||||
* standardly, by checking whether __cplusplus has a C++11 or greater value.
|
||||
* Current versions of g++ do not correctly set __cplusplus, so we check both
|
||||
* for forward compatibility.
|
||||
*/
|
||||
# define MOZ_HAVE_NEVER_INLINE __declspec(noinline)
|
||||
# define MOZ_HAVE_NORETURN __declspec(noreturn)
|
||||
#elif defined(__clang__)
|
||||
/*
|
||||
* Per Clang documentation, "Note that marketing version numbers should not
|
||||
* be used to check for language features, as different vendors use different
|
||||
* numbering schemes. Instead, use the feature checking macros."
|
||||
*/
|
||||
# ifndef __has_extension
|
||||
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||
# endif
|
||||
# if __has_attribute(noinline)
|
||||
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
|
||||
# endif
|
||||
# if __has_attribute(noreturn)
|
||||
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
|
||||
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When built with clang analyzer (a.k.a scan-build), define MOZ_HAVE_NORETURN
|
||||
* to mark some false positives
|
||||
*/
|
||||
#ifdef __clang_analyzer__
|
||||
# if __has_extension(attribute_analyzer_noreturn)
|
||||
# define MOZ_HAVE_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
|
||||
* method decorated with it must never be inlined, even if the compiler would
|
||||
* otherwise choose to inline the method. Compilers aren't absolutely
|
||||
* guaranteed to support this, but most do.
|
||||
*/
|
||||
#if defined(MOZ_HAVE_NEVER_INLINE)
|
||||
# define MOZ_NEVER_INLINE MOZ_HAVE_NEVER_INLINE
|
||||
#else
|
||||
# define MOZ_NEVER_INLINE /* no support */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_NORETURN, specified at the start of a function declaration, indicates
|
||||
* that the given function does not return. (The function definition does not
|
||||
* need to be annotated.)
|
||||
*
|
||||
* MOZ_NORETURN void abort(const char* msg);
|
||||
*
|
||||
* This modifier permits the compiler to optimize code assuming a call to such a
|
||||
* function will never return. It also enables the compiler to avoid spurious
|
||||
* warnings about not initializing variables, or about any other seemingly-dodgy
|
||||
* operations performed after the function returns.
|
||||
*
|
||||
* This modifier does not affect the corresponding function's linking behavior.
|
||||
*/
|
||||
#if defined(MOZ_HAVE_NORETURN)
|
||||
# define MOZ_NORETURN MOZ_HAVE_NORETURN
|
||||
#else
|
||||
# define MOZ_NORETURN /* no support */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_COLD tells the compiler that a function is "cold", meaning infrequently
|
||||
* executed. This may lead it to optimize for size more aggressively than speed,
|
||||
* or to allocate the body of the function in a distant part of the text segment
|
||||
* to help keep it from taking up unnecessary icache when it isn't in use.
|
||||
*
|
||||
* Place this attribute at the very beginning of a function definition. For
|
||||
* example, write
|
||||
*
|
||||
* MOZ_COLD int foo();
|
||||
*
|
||||
* or
|
||||
*
|
||||
* MOZ_COLD int foo() { return 42; }
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define MOZ_COLD __attribute__ ((cold))
|
||||
#else
|
||||
# define MOZ_COLD
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_NONNULL tells the compiler that some of the arguments to a function are
|
||||
* known to be non-null. The arguments are a list of 1-based argument indexes
|
||||
* identifying arguments which are known to be non-null.
|
||||
*
|
||||
* Place this attribute at the very beginning of a function definition. For
|
||||
* example, write
|
||||
*
|
||||
* MOZ_NONNULL(1, 2) int foo(char *p, char *q);
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define MOZ_NONNULL(...) __attribute__ ((nonnull(__VA_ARGS__)))
|
||||
#else
|
||||
# define MOZ_NONNULL(...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS, specified at the end of a function
|
||||
* declaration, indicates that for the purposes of static analysis, this
|
||||
* function does not return. (The function definition does not need to be
|
||||
* annotated.)
|
||||
*
|
||||
* MOZ_ReportCrash(const char* s, const char* file, int ln)
|
||||
* MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
|
||||
*
|
||||
* Some static analyzers, like scan-build from clang, can use this information
|
||||
* to eliminate false positives. From the upstream documentation of scan-build:
|
||||
* "This attribute is useful for annotating assertion handlers that actually
|
||||
* can return, but for the purpose of using the analyzer we want to pretend
|
||||
* that such functions do not return."
|
||||
*
|
||||
*/
|
||||
#if defined(MOZ_HAVE_ANALYZER_NORETURN)
|
||||
# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS MOZ_HAVE_ANALYZER_NORETURN
|
||||
#else
|
||||
# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS /* no support */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
|
||||
* instrumentation shipped with Clang and GCC) to not instrument the annotated
|
||||
* function. Furthermore, it will prevent the compiler from inlining the
|
||||
* function because inlining currently breaks the blacklisting mechanism of
|
||||
* AddressSanitizer.
|
||||
*/
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define MOZ_HAVE_ASAN_BLACKLIST
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(__SANITIZE_ADDRESS__)
|
||||
# define MOZ_HAVE_ASAN_BLACKLIST
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_HAVE_ASAN_BLACKLIST)
|
||||
# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_address))
|
||||
#else
|
||||
# define MOZ_ASAN_BLACKLIST /* nothing */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_TSAN_BLACKLIST is a macro to tell ThreadSanitizer (a compile-time
|
||||
* instrumentation shipped with Clang) to not instrument the annotated function.
|
||||
* Furthermore, it will prevent the compiler from inlining the function because
|
||||
* inlining currently breaks the blacklisting mechanism of ThreadSanitizer.
|
||||
*/
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(thread_sanitizer)
|
||||
# define MOZ_TSAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_thread))
|
||||
# else
|
||||
# define MOZ_TSAN_BLACKLIST /* nothing */
|
||||
# endif
|
||||
#else
|
||||
# define MOZ_TSAN_BLACKLIST /* nothing */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_ALLOCATOR tells the compiler that the function it marks returns either a
|
||||
* "fresh", "pointer-free" block of memory, or nullptr. "Fresh" means that the
|
||||
* block is not pointed to by any other reachable pointer in the program.
|
||||
* "Pointer-free" means that the block contains no pointers to any valid object
|
||||
* in the program. It may be initialized with other (non-pointer) values.
|
||||
*
|
||||
* Placing this attribute on appropriate functions helps GCC analyze pointer
|
||||
* aliasing more accurately in their callers.
|
||||
*
|
||||
* GCC warns if a caller ignores the value returned by a function marked with
|
||||
* MOZ_ALLOCATOR: it is hard to imagine cases where dropping the value returned
|
||||
* by a function that meets the criteria above would be intentional.
|
||||
*
|
||||
* Place this attribute after the argument list and 'this' qualifiers of a
|
||||
* function definition. For example, write
|
||||
*
|
||||
* void *my_allocator(size_t) MOZ_ALLOCATOR;
|
||||
*
|
||||
* or
|
||||
*
|
||||
* void *my_allocator(size_t bytes) MOZ_ALLOCATOR { ... }
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define MOZ_ALLOCATOR __attribute__ ((malloc, warn_unused_result))
|
||||
#else
|
||||
# define MOZ_ALLOCATOR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_MUST_USE tells the compiler to emit a warning if a function's
|
||||
* return value is not used by the caller.
|
||||
*
|
||||
* Place this attribute at the very beginning of a function declaration. For
|
||||
* example, write
|
||||
*
|
||||
* MOZ_MUST_USE int foo();
|
||||
*
|
||||
* or
|
||||
*
|
||||
* MOZ_MUST_USE int foo() { return 42; }
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define MOZ_MUST_USE __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
# define MOZ_MUST_USE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_FALLTHROUGH is an annotation to suppress compiler warnings about switch
|
||||
* cases that fall through without a break or return statement. MOZ_FALLTHROUGH
|
||||
* is only needed on cases that have code.
|
||||
*
|
||||
* MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
|
||||
* switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
|
||||
* debug builds, but intentionally fall through in release builds. See comment
|
||||
* in Assertions.h for more details.
|
||||
*
|
||||
* switch (foo) {
|
||||
* case 1: // These cases have no code. No fallthrough annotations are needed.
|
||||
* case 2:
|
||||
* case 3: // This case has code, so a fallthrough annotation is needed!
|
||||
* foo++;
|
||||
* MOZ_FALLTHROUGH;
|
||||
* case 4:
|
||||
* return foo;
|
||||
*
|
||||
* default:
|
||||
* // This case asserts in debug builds, falls through in release.
|
||||
* MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
|
||||
* case 5:
|
||||
* return 5;
|
||||
* }
|
||||
*/
|
||||
#if defined(__clang__) && __cplusplus >= 201103L
|
||||
/* clang's fallthrough annotations are only available starting in C++11. */
|
||||
# define MOZ_FALLTHROUGH [[clang::fallthrough]]
|
||||
#elif defined(_MSC_VER)
|
||||
/*
|
||||
* MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
|
||||
* https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
|
||||
*/
|
||||
# include <sal.h>
|
||||
# define MOZ_FALLTHROUGH __fallthrough
|
||||
#else
|
||||
# define MOZ_FALLTHROUGH /* FALLTHROUGH */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
* The following macros are attributes that support the static analysis plugin
|
||||
* included with Mozilla, and will be implemented (when such support is enabled)
|
||||
* as C++11 attributes. Since such attributes are legal pretty much everywhere
|
||||
* and have subtly different semantics depending on their placement, the
|
||||
* following is a guide on where to place the attributes.
|
||||
*
|
||||
* Attributes that apply to a struct or class precede the name of the class:
|
||||
* (Note that this is different from the placement of final for classes!)
|
||||
*
|
||||
* class MOZ_CLASS_ATTRIBUTE SomeClass {};
|
||||
*
|
||||
* Attributes that apply to functions follow the parentheses and const
|
||||
* qualifiers but precede final, override and the function body:
|
||||
*
|
||||
* void DeclaredFunction() MOZ_FUNCTION_ATTRIBUTE;
|
||||
* void SomeFunction() MOZ_FUNCTION_ATTRIBUTE {}
|
||||
* void PureFunction() const MOZ_FUNCTION_ATTRIBUTE = 0;
|
||||
* void OverriddenFunction() MOZ_FUNCTION_ATTIRBUTE override;
|
||||
*
|
||||
* Attributes that apply to variables or parameters follow the variable's name:
|
||||
*
|
||||
* int variable MOZ_VARIABLE_ATTRIBUTE;
|
||||
*
|
||||
* Attributes that apply to types follow the type name:
|
||||
*
|
||||
* typedef int MOZ_TYPE_ATTRIBUTE MagicInt;
|
||||
* int MOZ_TYPE_ATTRIBUTE someVariable;
|
||||
* int* MOZ_TYPE_ATTRIBUTE magicPtrInt;
|
||||
* int MOZ_TYPE_ATTRIBUTE* ptrToMagicInt;
|
||||
*
|
||||
* Attributes that apply to statements precede the statement:
|
||||
*
|
||||
* MOZ_IF_ATTRIBUTE if (x == 0)
|
||||
* MOZ_DO_ATTRIBUTE do { } while (0);
|
||||
*
|
||||
* Attributes that apply to labels precede the label:
|
||||
*
|
||||
* MOZ_LABEL_ATTRIBUTE target:
|
||||
* goto target;
|
||||
* MOZ_CASE_ATTRIBUTE case 5:
|
||||
* MOZ_DEFAULT_ATTRIBUTE default:
|
||||
*
|
||||
* The static analyses that are performed by the plugin are as follows:
|
||||
*
|
||||
* MOZ_MUST_OVERRIDE: Applies to all C++ member functions. All immediate
|
||||
* subclasses must provide an exact override of this method; if a subclass
|
||||
* does not override this method, the compiler will emit an error. This
|
||||
* attribute is not limited to virtual methods, so if it is applied to a
|
||||
* nonvirtual method and the subclass does not provide an equivalent
|
||||
* definition, the compiler will emit an error.
|
||||
* MOZ_STACK_CLASS: Applies to all classes. Any class with this annotation is
|
||||
* expected to live on the stack, so it is a compile-time error to use it, or
|
||||
* an array of such objects, as a global or static variable, or as the type of
|
||||
* a new expression (unless placement new is being used). If a member of
|
||||
* another class uses this class, or if another class inherits from this
|
||||
* class, then it is considered to be a stack class as well, although this
|
||||
* attribute need not be provided in such cases.
|
||||
* MOZ_NONHEAP_CLASS: Applies to all classes. Any class with this annotation is
|
||||
* expected to live on the stack or in static storage, so it is a compile-time
|
||||
* error to use it, or an array of such objects, as the type of a new
|
||||
* expression. If a member of another class uses this class, or if another
|
||||
* class inherits from this class, then it is considered to be a non-heap class
|
||||
* as well, although this attribute need not be provided in such cases.
|
||||
* MOZ_HEAP_CLASS: Applies to all classes. Any class with this annotation is
|
||||
* expected to live on the heap, so it is a compile-time error to use it, or
|
||||
* an array of such objects, as the type of a variable declaration, or as a
|
||||
* temporary object. If a member of another class uses this class, or if
|
||||
* another class inherits from this class, then it is considered to be a heap
|
||||
* class as well, although this attribute need not be provided in such cases.
|
||||
* MOZ_NON_TEMPORARY_CLASS: Applies to all classes. Any class with this
|
||||
* annotation is expected not to live in a temporary. If a member of another
|
||||
* class uses this class or if another class inherits from this class, then it
|
||||
* is considered to be a non-temporary class as well, although this attribute
|
||||
* need not be provided in such cases.
|
||||
* MOZ_RAII: Applies to all classes. Any class with this annotation is assumed
|
||||
* to be a RAII guard, which is expected to live on the stack in an automatic
|
||||
* allocation. It is prohibited from being allocated in a temporary, static
|
||||
* storage, or on the heap. This is a combination of MOZ_STACK_CLASS and
|
||||
* MOZ_NON_TEMPORARY_CLASS.
|
||||
* MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS: Applies to all classes that are
|
||||
* intended to prevent introducing static initializers. This attribute
|
||||
* currently makes it a compile-time error to instantiate these classes
|
||||
* anywhere other than at the global scope, or as a static member of a class.
|
||||
* In non-debug mode, it also prohibits non-trivial constructors and
|
||||
* destructors.
|
||||
* MOZ_TRIVIAL_CTOR_DTOR: Applies to all classes that must have both a trivial
|
||||
* or constexpr constructor and a trivial destructor. Setting this attribute
|
||||
* on a class makes it a compile-time error for that class to get a
|
||||
* non-trivial constructor or destructor for any reason.
|
||||
* MOZ_HEAP_ALLOCATOR: Applies to any function. This indicates that the return
|
||||
* value is allocated on the heap, and will as a result check such allocations
|
||||
* during MOZ_STACK_CLASS and MOZ_NONHEAP_CLASS annotation checking.
|
||||
* MOZ_IMPLICIT: Applies to constructors. Implicit conversion constructors
|
||||
* are disallowed by default unless they are marked as MOZ_IMPLICIT. This
|
||||
* attribute must be used for constructors which intend to provide implicit
|
||||
* conversions.
|
||||
* MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT: Applies to functions. Makes it a compile
|
||||
* time error to pass arithmetic expressions on variables to the function.
|
||||
* MOZ_OWNING_REF: Applies to declarations of pointers to reference counted
|
||||
* types. This attribute tells the compiler that the raw pointer is a strong
|
||||
* reference, where ownership through methods such as AddRef and Release is
|
||||
* managed manually. This can make the compiler ignore these pointers when
|
||||
* validating the usage of pointers otherwise.
|
||||
*
|
||||
* Example uses include owned pointers inside of unions, and pointers stored
|
||||
* in POD types where a using a smart pointer class would make the object
|
||||
* non-POD.
|
||||
* MOZ_NON_OWNING_REF: Applies to declarations of pointers to reference counted
|
||||
* types. This attribute tells the compiler that the raw pointer is a weak
|
||||
* reference, which is ensured to be valid by a guarantee that the reference
|
||||
* will be nulled before the pointer becomes invalid. This can make the compiler
|
||||
* ignore these pointers when validating the usage of pointers otherwise.
|
||||
*
|
||||
* Examples include an mOwner pointer, which is nulled by the owning class's
|
||||
* destructor, and is null-checked before dereferencing.
|
||||
* MOZ_UNSAFE_REF: Applies to declarations of pointers to reference counted types.
|
||||
* Occasionally there are non-owning references which are valid, but do not take
|
||||
* the form of a MOZ_NON_OWNING_REF. Their safety may be dependent on the behaviour
|
||||
* of API consumers. The string argument passed to this macro documents the safety
|
||||
* conditions. This can make the compiler ignore these pointers when validating
|
||||
* the usage of pointers elsewhere.
|
||||
*
|
||||
* Examples include an nsIAtom* member which is known at compile time to point to a
|
||||
* static atom which is valid throughout the lifetime of the program, or an API which
|
||||
* stores a pointer, but doesn't take ownership over it, instead requiring the API
|
||||
* consumer to correctly null the value before it becomes invalid.
|
||||
*
|
||||
* Use of this annotation is discouraged when a strong reference or one of the above
|
||||
* two annotations can be used instead.
|
||||
* MOZ_NO_ADDREF_RELEASE_ON_RETURN: Applies to function declarations. Makes it
|
||||
* a compile time error to call AddRef or Release on the return value of a
|
||||
* function. This is intended to be used with operator->() of our smart
|
||||
* pointer classes to ensure that the refcount of an object wrapped in a
|
||||
* smart pointer is not manipulated directly.
|
||||
* MOZ_MUST_USE_TYPE: Applies to type declarations. Makes it a compile time
|
||||
* error to not use the return value of a function which has this type. This
|
||||
* is intended to be used with types which it is an error to not use.
|
||||
* MOZ_NEEDS_NO_VTABLE_TYPE: Applies to template class declarations. Makes it
|
||||
* a compile time error to instantiate this template with a type parameter which
|
||||
* has a VTable.
|
||||
* MOZ_NON_MEMMOVABLE: Applies to class declarations for types that are not safe
|
||||
* to be moved in memory using memmove().
|
||||
* MOZ_NEEDS_MEMMOVABLE_TYPE: Applies to template class declarations where the
|
||||
* template arguments are required to be safe to move in memory using
|
||||
* memmove(). Passing MOZ_NON_MEMMOVABLE types to these templates is a
|
||||
* compile time error.
|
||||
* MOZ_NEEDS_MEMMOVABLE_MEMBERS: Applies to class declarations where each member
|
||||
* must be safe to move in memory using memmove(). MOZ_NON_MEMMOVABLE types
|
||||
* used in members of these classes are compile time errors.
|
||||
* MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS: Applies to template class
|
||||
* declarations where an instance of the template should be considered, for
|
||||
* static analysis purposes, to inherit any type annotations (such as
|
||||
* MOZ_MUST_USE_TYPE and MOZ_STACK_CLASS) from its template arguments.
|
||||
* MOZ_INIT_OUTSIDE_CTOR: Applies to class member declarations. Occasionally
|
||||
* there are class members that are not initialized in the constructor,
|
||||
* but logic elsewhere in the class ensures they are initialized prior to use.
|
||||
* Using this attribute on a member disables the check that this member must be
|
||||
* initialized in constructors via list-initialization, in the constructor body,
|
||||
* or via functions called from the constructor body.
|
||||
* MOZ_IS_CLASS_INIT: Applies to class method declarations. Occasionally the
|
||||
* constructor doesn't initialize all of the member variables and another function
|
||||
* is used to initialize the rest. This marker is used to make the static analysis
|
||||
* tool aware that the marked function is part of the initialization process
|
||||
* and to include the marked function in the scan mechanism that determines witch
|
||||
* member variables still remain uninitialized.
|
||||
* MOZ_NON_PARAM: Applies to types. Makes it compile time error to use the type
|
||||
* in parameter without pointer or reference.
|
||||
* MOZ_NON_AUTOABLE: Applies to class declarations. Makes it a compile time error to
|
||||
* use `auto` in place of this type in variable declarations. This is intended to
|
||||
* be used with types which are intended to be implicitly constructed into other
|
||||
* other types before being assigned to variables.
|
||||
* MOZ_REQUIRED_BASE_METHOD: Applies to virtual class method declarations.
|
||||
* Sometimes derived classes override methods that need to be called by their
|
||||
* overridden counterparts. This marker indicates that the marked method must
|
||||
* be called by the method that it overrides.
|
||||
*/
|
||||
#ifdef MOZ_CLANG_PLUGIN
|
||||
# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
|
||||
# define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
|
||||
# define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
|
||||
# define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class")))
|
||||
# define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class")))
|
||||
# define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor")))
|
||||
# ifdef DEBUG
|
||||
/* in debug builds, these classes do have non-trivial constructors. */
|
||||
# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class")))
|
||||
# else
|
||||
# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class"))) \
|
||||
MOZ_TRIVIAL_CTOR_DTOR
|
||||
# endif
|
||||
# define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
|
||||
# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg")))
|
||||
# define MOZ_OWNING_REF __attribute__((annotate("moz_strong_ref")))
|
||||
# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref")))
|
||||
# define MOZ_UNSAFE_REF(reason) __attribute__((annotate("moz_weak_ref")))
|
||||
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
|
||||
# define MOZ_MUST_USE_TYPE __attribute__((annotate("moz_must_use_type")))
|
||||
# define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type")))
|
||||
# define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
|
||||
# define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
|
||||
# define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members")))
|
||||
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \
|
||||
__attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
|
||||
# define MOZ_NON_AUTOABLE __attribute__((annotate("moz_non_autoable")))
|
||||
# define MOZ_INIT_OUTSIDE_CTOR \
|
||||
__attribute__((annotate("moz_ignore_ctor_initialization")))
|
||||
# define MOZ_IS_CLASS_INIT \
|
||||
__attribute__((annotate("moz_is_class_init")))
|
||||
# define MOZ_NON_PARAM \
|
||||
__attribute__((annotate("moz_non_param")))
|
||||
# define MOZ_REQUIRED_BASE_METHOD \
|
||||
__attribute__((annotate("moz_required_base_method")))
|
||||
/*
|
||||
* It turns out that clang doesn't like void func() __attribute__ {} without a
|
||||
* warning, so use pragmas to disable the warning. This code won't work on GCC
|
||||
* anyways, so the warning is safe to ignore.
|
||||
*/
|
||||
# define MOZ_HEAP_ALLOCATOR \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
|
||||
__attribute__((annotate("moz_heap_allocator"))) \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#else
|
||||
# define MOZ_MUST_OVERRIDE /* nothing */
|
||||
# define MOZ_STACK_CLASS /* nothing */
|
||||
# define MOZ_NONHEAP_CLASS /* nothing */
|
||||
# define MOZ_HEAP_CLASS /* nothing */
|
||||
# define MOZ_NON_TEMPORARY_CLASS /* nothing */
|
||||
# define MOZ_TRIVIAL_CTOR_DTOR /* nothing */
|
||||
# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */
|
||||
# define MOZ_IMPLICIT /* nothing */
|
||||
# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT /* nothing */
|
||||
# define MOZ_HEAP_ALLOCATOR /* nothing */
|
||||
# define MOZ_OWNING_REF /* nothing */
|
||||
# define MOZ_NON_OWNING_REF /* nothing */
|
||||
# define MOZ_UNSAFE_REF(reason) /* nothing */
|
||||
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */
|
||||
# define MOZ_MUST_USE_TYPE /* nothing */
|
||||
# define MOZ_NEEDS_NO_VTABLE_TYPE /* nothing */
|
||||
# define MOZ_NON_MEMMOVABLE /* nothing */
|
||||
# define MOZ_NEEDS_MEMMOVABLE_TYPE /* nothing */
|
||||
# define MOZ_NEEDS_MEMMOVABLE_MEMBERS /* nothing */
|
||||
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */
|
||||
# define MOZ_INIT_OUTSIDE_CTOR /* nothing */
|
||||
# define MOZ_IS_CLASS_INIT /* nothing */
|
||||
# define MOZ_NON_PARAM /* nothing */
|
||||
# define MOZ_NON_AUTOABLE /* nothing */
|
||||
# define MOZ_REQUIRED_BASE_METHOD /* nothing */
|
||||
#endif /* MOZ_CLANG_PLUGIN */
|
||||
|
||||
#define MOZ_RAII MOZ_NON_TEMPORARY_CLASS MOZ_STACK_CLASS
|
||||
|
||||
/*
|
||||
* MOZ_HAVE_REF_QUALIFIERS is defined for compilers that support C++11's rvalue
|
||||
* qualifier, "&&".
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
# define MOZ_HAVE_REF_QUALIFIERS
|
||||
#elif defined(__clang__)
|
||||
// All supported Clang versions
|
||||
# define MOZ_HAVE_REF_QUALIFIERS
|
||||
#elif defined(__GNUC__)
|
||||
# include "mozilla/Compiler.h"
|
||||
# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 1)
|
||||
# define MOZ_HAVE_REF_QUALIFIERS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Printf style formats. MOZ_FORMAT_PRINTF can be used to annotate a
|
||||
* function or method that is "printf-like"; this will let (some)
|
||||
* compilers check that the arguments match the template string.
|
||||
*
|
||||
* This macro takes two arguments. The first argument is the argument
|
||||
* number of the template string. The second argument is the argument
|
||||
* number of the '...' argument holding the arguments.
|
||||
*
|
||||
* Argument numbers start at 1. Note that the implicit "this"
|
||||
* argument of a non-static member function counts as an argument.
|
||||
*
|
||||
* So, for a simple case like:
|
||||
* void print_something (int whatever, const char *fmt, ...);
|
||||
* The corresponding annotation would be
|
||||
* MOZ_FORMAT_PRINTF(2, 3)
|
||||
* However, if "print_something" were a non-static member function,
|
||||
* then the annotation would be:
|
||||
* MOZ_FORMAT_PRINTF(3, 4)
|
||||
*
|
||||
* Note that the checking is limited to standards-conforming
|
||||
* printf-likes, and in particular this should not be used for
|
||||
* PR_snprintf and friends, which are "printf-like" but which assign
|
||||
* different meanings to the various formats.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck) \
|
||||
__attribute__ ((format (printf, stringIndex, firstToCheck)))
|
||||
#else
|
||||
#define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck)
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Attributes_h */
|
||||
139
cocos2d-x/external/win32/include/spidermonkey/mozilla/BinarySearch.h
vendored
Executable file
139
cocos2d-x/external/win32/include/spidermonkey/mozilla/BinarySearch.h
vendored
Executable file
@@ -0,0 +1,139 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_BinarySearch_h
|
||||
#define mozilla_BinarySearch_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* The BinarySearch() algorithm searches the given container |aContainer| over
|
||||
* the sorted index range [aBegin, aEnd) for an index |i| where
|
||||
* |aContainer[i] == aTarget|.
|
||||
* If such an index |i| is found, BinarySearch returns |true| and the index is
|
||||
* returned via the outparam |aMatchOrInsertionPoint|. If no index is found,
|
||||
* BinarySearch returns |false| and the outparam returns the first index in
|
||||
* [aBegin, aEnd] where |aTarget| can be inserted to maintain sorted order.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Vector<int> sortedInts = ...
|
||||
*
|
||||
* size_t match;
|
||||
* if (BinarySearch(sortedInts, 0, sortedInts.length(), 13, &match)) {
|
||||
* printf("found 13 at %lu\n", match);
|
||||
* }
|
||||
*
|
||||
* The BinarySearchIf() version behaves similarly, but takes |aComparator|, a
|
||||
* functor to compare the values with, instead of a value to find.
|
||||
* That functor should take one argument - the value to compare - and return an
|
||||
* |int| with the comparison result:
|
||||
*
|
||||
* * 0, if the argument is equal to,
|
||||
* * less than 0, if the argument is greater than,
|
||||
* * greater than 0, if the argument is less than
|
||||
*
|
||||
* the value.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* struct Comparator {
|
||||
* int operator()(int aVal) const {
|
||||
* if (mTarget < aVal) { return -1; }
|
||||
* if (mTarget > aVal) { return 1; }
|
||||
* return 0;
|
||||
* }
|
||||
* explicit Comparator(int aTarget) : mTarget(aTarget) {}
|
||||
* const int mTarget;
|
||||
* };
|
||||
*
|
||||
* Vector<int> sortedInts = ...
|
||||
*
|
||||
* size_t match;
|
||||
* if (BinarySearchIf(sortedInts, 0, sortedInts.length(), Comparator(13), &match)) {
|
||||
* printf("found 13 at %lu\n", match);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
template<typename Container, typename Comparator>
|
||||
bool
|
||||
BinarySearchIf(const Container& aContainer, size_t aBegin, size_t aEnd,
|
||||
const Comparator& aCompare, size_t* aMatchOrInsertionPoint)
|
||||
{
|
||||
MOZ_ASSERT(aBegin <= aEnd);
|
||||
|
||||
size_t low = aBegin;
|
||||
size_t high = aEnd;
|
||||
while (high != low) {
|
||||
size_t middle = low + (high - low) / 2;
|
||||
|
||||
// Allow any intermediate type so long as it provides a suitable ordering
|
||||
// relation.
|
||||
const int result = aCompare(aContainer[middle]);
|
||||
|
||||
if (result == 0) {
|
||||
*aMatchOrInsertionPoint = middle;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
high = middle;
|
||||
} else {
|
||||
low = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*aMatchOrInsertionPoint = low;
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
class BinarySearchDefaultComparator
|
||||
{
|
||||
public:
|
||||
explicit BinarySearchDefaultComparator(const T& aTarget)
|
||||
: mTarget(aTarget)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
int operator()(const U& aVal) const {
|
||||
if (mTarget == aVal) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mTarget < aVal) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
const T& mTarget;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Container, typename T>
|
||||
bool
|
||||
BinarySearch(const Container& aContainer, size_t aBegin, size_t aEnd,
|
||||
T aTarget, size_t* aMatchOrInsertionPoint)
|
||||
{
|
||||
return BinarySearchIf(aContainer, aBegin, aEnd,
|
||||
detail::BinarySearchDefaultComparator<T>(aTarget),
|
||||
aMatchOrInsertionPoint);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_BinarySearch_h
|
||||
256
cocos2d-x/external/win32/include/spidermonkey/mozilla/BloomFilter.h
vendored
Executable file
256
cocos2d-x/external/win32/include/spidermonkey/mozilla/BloomFilter.h
vendored
Executable file
@@ -0,0 +1,256 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* A counting Bloom filter implementation. This allows consumers to
|
||||
* do fast probabilistic "is item X in set Y?" testing which will
|
||||
* never answer "no" when the correct answer is "yes" (but might
|
||||
* incorrectly answer "yes" when the correct answer is "no").
|
||||
*/
|
||||
|
||||
#ifndef mozilla_BloomFilter_h
|
||||
#define mozilla_BloomFilter_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* This class implements a counting Bloom filter as described at
|
||||
* <http://en.wikipedia.org/wiki/Bloom_filter#Counting_filters>, with
|
||||
* 8-bit counters. This allows quick probabilistic answers to the
|
||||
* question "is object X in set Y?" where the contents of Y might not
|
||||
* be time-invariant. The probabilistic nature of the test means that
|
||||
* sometimes the answer will be "yes" when it should be "no". If the
|
||||
* answer is "no", then X is guaranteed not to be in Y.
|
||||
*
|
||||
* The filter is parametrized on KeySize, which is the size of the key
|
||||
* generated by each of hash functions used by the filter, in bits,
|
||||
* and the type of object T being added and removed. T must implement
|
||||
* a |uint32_t hash() const| method which returns a uint32_t hash key
|
||||
* that will be used to generate the two separate hash functions for
|
||||
* the Bloom filter. This hash key MUST be well-distributed for good
|
||||
* results! KeySize is not allowed to be larger than 16.
|
||||
*
|
||||
* The filter uses exactly 2**KeySize bytes of memory. From now on we
|
||||
* will refer to the memory used by the filter as M.
|
||||
*
|
||||
* The expected rate of incorrect "yes" answers depends on M and on
|
||||
* the number N of objects in set Y. As long as N is small compared
|
||||
* to M, the rate of such answers is expected to be approximately
|
||||
* 4*(N/M)**2 for this filter. In practice, if Y has a few hundred
|
||||
* elements then using a KeySize of 12 gives a reasonably low
|
||||
* incorrect answer rate. A KeySize of 12 has the additional benefit
|
||||
* of using exactly one page for the filter in typical hardware
|
||||
* configurations.
|
||||
*/
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
class BloomFilter
|
||||
{
|
||||
/*
|
||||
* A counting Bloom filter with 8-bit counters. For now we assume
|
||||
* that having two hash functions is enough, but we may revisit that
|
||||
* decision later.
|
||||
*
|
||||
* The filter uses an array with 2**KeySize entries.
|
||||
*
|
||||
* Assuming a well-distributed hash function, a Bloom filter with
|
||||
* array size M containing N elements and
|
||||
* using k hash function has expected false positive rate exactly
|
||||
*
|
||||
* $ (1 - (1 - 1/M)^{kN})^k $
|
||||
*
|
||||
* because each array slot has a
|
||||
*
|
||||
* $ (1 - 1/M)^{kN} $
|
||||
*
|
||||
* chance of being 0, and the expected false positive rate is the
|
||||
* probability that all of the k hash functions will hit a nonzero
|
||||
* slot.
|
||||
*
|
||||
* For reasonable assumptions (M large, kN large, which should both
|
||||
* hold if we're worried about false positives) about M and kN this
|
||||
* becomes approximately
|
||||
*
|
||||
* $$ (1 - \exp(-kN/M))^k $$
|
||||
*
|
||||
* For our special case of k == 2, that's $(1 - \exp(-2N/M))^2$,
|
||||
* or in other words
|
||||
*
|
||||
* $$ N/M = -0.5 * \ln(1 - \sqrt(r)) $$
|
||||
*
|
||||
* where r is the false positive rate. This can be used to compute
|
||||
* the desired KeySize for a given load N and false positive rate r.
|
||||
*
|
||||
* If N/M is assumed small, then the false positive rate can
|
||||
* further be approximated as 4*N^2/M^2. So increasing KeySize by
|
||||
* 1, which doubles M, reduces the false positive rate by about a
|
||||
* factor of 4, and a false positive rate of 1% corresponds to
|
||||
* about M/N == 20.
|
||||
*
|
||||
* What this means in practice is that for a few hundred keys using a
|
||||
* KeySize of 12 gives false positive rates on the order of 0.25-4%.
|
||||
*
|
||||
* Similarly, using a KeySize of 10 would lead to a 4% false
|
||||
* positive rate for N == 100 and to quite bad false positive
|
||||
* rates for larger N.
|
||||
*/
|
||||
public:
|
||||
BloomFilter()
|
||||
{
|
||||
static_assert(KeySize <= kKeyShift, "KeySize too big");
|
||||
|
||||
// Should we have a custom operator new using calloc instead and
|
||||
// require that we're allocated via the operator?
|
||||
clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the filter. This should be done before reusing it, because
|
||||
* just removing all items doesn't clear counters that hit the upper
|
||||
* bound.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/*
|
||||
* Add an item to the filter.
|
||||
*/
|
||||
void add(const T* aValue);
|
||||
|
||||
/*
|
||||
* Remove an item from the filter.
|
||||
*/
|
||||
void remove(const T* aValue);
|
||||
|
||||
/*
|
||||
* Check whether the filter might contain an item. This can
|
||||
* sometimes return true even if the item is not in the filter,
|
||||
* but will never return false for items that are actually in the
|
||||
* filter.
|
||||
*/
|
||||
bool mightContain(const T* aValue) const;
|
||||
|
||||
/*
|
||||
* Methods for add/remove/contain when we already have a hash computed
|
||||
*/
|
||||
void add(uint32_t aHash);
|
||||
void remove(uint32_t aHash);
|
||||
bool mightContain(uint32_t aHash) const;
|
||||
|
||||
private:
|
||||
static const size_t kArraySize = (1 << KeySize);
|
||||
static const uint32_t kKeyMask = (1 << KeySize) - 1;
|
||||
static const uint32_t kKeyShift = 16;
|
||||
|
||||
static uint32_t hash1(uint32_t aHash)
|
||||
{
|
||||
return aHash & kKeyMask;
|
||||
}
|
||||
static uint32_t hash2(uint32_t aHash)
|
||||
{
|
||||
return (aHash >> kKeyShift) & kKeyMask;
|
||||
}
|
||||
|
||||
uint8_t& firstSlot(uint32_t aHash)
|
||||
{
|
||||
return mCounters[hash1(aHash)];
|
||||
}
|
||||
uint8_t& secondSlot(uint32_t aHash)
|
||||
{
|
||||
return mCounters[hash2(aHash)];
|
||||
}
|
||||
|
||||
const uint8_t& firstSlot(uint32_t aHash) const
|
||||
{
|
||||
return mCounters[hash1(aHash)];
|
||||
}
|
||||
const uint8_t& secondSlot(uint32_t aHash) const
|
||||
{
|
||||
return mCounters[hash2(aHash)];
|
||||
}
|
||||
|
||||
static bool full(const uint8_t& aSlot) { return aSlot == UINT8_MAX; }
|
||||
|
||||
uint8_t mCounters[kArraySize];
|
||||
};
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::clear()
|
||||
{
|
||||
memset(mCounters, 0, kArraySize);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::add(uint32_t aHash)
|
||||
{
|
||||
uint8_t& slot1 = firstSlot(aHash);
|
||||
if (MOZ_LIKELY(!full(slot1))) {
|
||||
++slot1;
|
||||
}
|
||||
uint8_t& slot2 = secondSlot(aHash);
|
||||
if (MOZ_LIKELY(!full(slot2))) {
|
||||
++slot2;
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
BloomFilter<KeySize, T>::add(const T* aValue)
|
||||
{
|
||||
uint32_t hash = aValue->hash();
|
||||
return add(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::remove(uint32_t aHash)
|
||||
{
|
||||
// If the slots are full, we don't know whether we bumped them to be
|
||||
// there when we added or not, so just leave them full.
|
||||
uint8_t& slot1 = firstSlot(aHash);
|
||||
if (MOZ_LIKELY(!full(slot1))) {
|
||||
--slot1;
|
||||
}
|
||||
uint8_t& slot2 = secondSlot(aHash);
|
||||
if (MOZ_LIKELY(!full(slot2))) {
|
||||
--slot2;
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
BloomFilter<KeySize, T>::remove(const T* aValue)
|
||||
{
|
||||
uint32_t hash = aValue->hash();
|
||||
remove(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
BloomFilter<KeySize, T>::mightContain(uint32_t aHash) const
|
||||
{
|
||||
// Check that all the slots for this hash contain something
|
||||
return firstSlot(aHash) && secondSlot(aHash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
BloomFilter<KeySize, T>::mightContain(const T* aValue) const
|
||||
{
|
||||
uint32_t hash = aValue->hash();
|
||||
return mightContain(hash);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_BloomFilter_h */
|
||||
517
cocos2d-x/external/win32/include/spidermonkey/mozilla/BufferList.h
vendored
Executable file
517
cocos2d-x/external/win32/include/spidermonkey/mozilla/BufferList.h
vendored
Executable file
@@ -0,0 +1,517 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_BufferList_h
|
||||
#define mozilla_BufferList_h
|
||||
|
||||
#include <algorithm>
|
||||
#include "mozilla/AllocPolicy.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include <string.h>
|
||||
|
||||
// BufferList represents a sequence of buffers of data. A BufferList can choose
|
||||
// to own its buffers or not. The class handles writing to the buffers,
|
||||
// iterating over them, and reading data out. Unlike SegmentedVector, the
|
||||
// buffers may be of unequal size. Like SegmentedVector, BufferList is a nice
|
||||
// way to avoid large contiguous allocations (which can trigger OOMs).
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename AllocPolicy>
|
||||
class BufferList : private AllocPolicy
|
||||
{
|
||||
// Each buffer in a BufferList has a size and a capacity. The first mSize
|
||||
// bytes are initialized and the remaining |mCapacity - mSize| bytes are free.
|
||||
struct Segment
|
||||
{
|
||||
char* mData;
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
|
||||
Segment(char* aData, size_t aSize, size_t aCapacity)
|
||||
: mData(aData),
|
||||
mSize(aSize),
|
||||
mCapacity(aCapacity)
|
||||
{
|
||||
}
|
||||
|
||||
Segment(const Segment&) = delete;
|
||||
Segment& operator=(const Segment&) = delete;
|
||||
|
||||
Segment(Segment&&) = default;
|
||||
Segment& operator=(Segment&&) = default;
|
||||
|
||||
char* Start() const { return mData; }
|
||||
char* End() const { return mData + mSize; }
|
||||
};
|
||||
|
||||
template<typename OtherAllocPolicy>
|
||||
friend class BufferList;
|
||||
|
||||
public:
|
||||
// For the convenience of callers, all segments are required to be a multiple
|
||||
// of 8 bytes in capacity. Also, every buffer except the last one is required
|
||||
// to be full (i.e., size == capacity). Therefore, a byte at offset N within
|
||||
// the BufferList and stored in memory at an address A will satisfy
|
||||
// (N % Align == A % Align) if Align == 2, 4, or 8.
|
||||
static const size_t kSegmentAlignment = 8;
|
||||
|
||||
// Allocate a BufferList. The BufferList will free all its buffers when it is
|
||||
// destroyed. An initial buffer of size aInitialSize and capacity
|
||||
// aInitialCapacity is allocated automatically. This data will be contiguous
|
||||
// an can be accessed via |Start()|. Subsequent buffers will be allocated with
|
||||
// capacity aStandardCapacity.
|
||||
BufferList(size_t aInitialSize,
|
||||
size_t aInitialCapacity,
|
||||
size_t aStandardCapacity,
|
||||
AllocPolicy aAP = AllocPolicy())
|
||||
: AllocPolicy(aAP),
|
||||
mOwning(true),
|
||||
mSegments(aAP),
|
||||
mSize(0),
|
||||
mStandardCapacity(aStandardCapacity)
|
||||
{
|
||||
MOZ_ASSERT(aInitialCapacity % kSegmentAlignment == 0);
|
||||
MOZ_ASSERT(aStandardCapacity % kSegmentAlignment == 0);
|
||||
|
||||
if (aInitialCapacity) {
|
||||
AllocateSegment(aInitialSize, aInitialCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
BufferList(const BufferList& aOther) = delete;
|
||||
|
||||
BufferList(BufferList&& aOther)
|
||||
: mOwning(aOther.mOwning),
|
||||
mSegments(Move(aOther.mSegments)),
|
||||
mSize(aOther.mSize),
|
||||
mStandardCapacity(aOther.mStandardCapacity)
|
||||
{
|
||||
aOther.mSegments.clear();
|
||||
aOther.mSize = 0;
|
||||
}
|
||||
|
||||
BufferList& operator=(const BufferList& aOther) = delete;
|
||||
|
||||
BufferList& operator=(BufferList&& aOther)
|
||||
{
|
||||
Clear();
|
||||
|
||||
mOwning = aOther.mOwning;
|
||||
mSegments = Move(aOther.mSegments);
|
||||
mSize = aOther.mSize;
|
||||
aOther.mSegments.clear();
|
||||
aOther.mSize = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~BufferList() { Clear(); }
|
||||
|
||||
// Returns the sum of the sizes of all the buffers.
|
||||
size_t Size() const { return mSize; }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if (mOwning) {
|
||||
for (Segment& segment : mSegments) {
|
||||
this->free_(segment.mData);
|
||||
}
|
||||
}
|
||||
mSegments.clear();
|
||||
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
// Iterates over bytes in the segments. You can advance it by as many bytes as
|
||||
// you choose.
|
||||
class IterImpl
|
||||
{
|
||||
// Invariants:
|
||||
// (0) mSegment <= bufferList.mSegments.size()
|
||||
// (1) mData <= mDataEnd
|
||||
// (2) If mSegment is not the last segment, mData < mDataEnd
|
||||
uintptr_t mSegment;
|
||||
char* mData;
|
||||
char* mDataEnd;
|
||||
|
||||
friend class BufferList;
|
||||
|
||||
public:
|
||||
explicit IterImpl(const BufferList& aBuffers)
|
||||
: mSegment(0),
|
||||
mData(nullptr),
|
||||
mDataEnd(nullptr)
|
||||
{
|
||||
if (!aBuffers.mSegments.empty()) {
|
||||
mData = aBuffers.mSegments[0].Start();
|
||||
mDataEnd = aBuffers.mSegments[0].End();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a pointer to the raw data. It is valid to access up to
|
||||
// RemainingInSegment bytes of this buffer.
|
||||
char* Data() const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!Done());
|
||||
return mData;
|
||||
}
|
||||
|
||||
// Returns true if the memory in the range [Data(), Data() + aBytes) is all
|
||||
// part of one contiguous buffer.
|
||||
bool HasRoomFor(size_t aBytes) const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mData <= mDataEnd);
|
||||
return size_t(mDataEnd - mData) >= aBytes;
|
||||
}
|
||||
|
||||
// Returns the maximum value aBytes for which HasRoomFor(aBytes) will be
|
||||
// true.
|
||||
size_t RemainingInSegment() const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mData <= mDataEnd);
|
||||
return mDataEnd - mData;
|
||||
}
|
||||
|
||||
// Advances the iterator by aBytes bytes. aBytes must be less than
|
||||
// RemainingInSegment(). If advancing by aBytes takes the iterator to the
|
||||
// end of a buffer, it will be moved to the beginning of the next buffer
|
||||
// unless it is the last buffer.
|
||||
void Advance(const BufferList& aBuffers, size_t aBytes)
|
||||
{
|
||||
const Segment& segment = aBuffers.mSegments[mSegment];
|
||||
MOZ_RELEASE_ASSERT(segment.Start() <= mData);
|
||||
MOZ_RELEASE_ASSERT(mData <= mDataEnd);
|
||||
MOZ_RELEASE_ASSERT(mDataEnd == segment.End());
|
||||
|
||||
MOZ_RELEASE_ASSERT(HasRoomFor(aBytes));
|
||||
mData += aBytes;
|
||||
|
||||
if (mData == mDataEnd && mSegment + 1 < aBuffers.mSegments.length()) {
|
||||
mSegment++;
|
||||
const Segment& nextSegment = aBuffers.mSegments[mSegment];
|
||||
mData = nextSegment.Start();
|
||||
mDataEnd = nextSegment.End();
|
||||
MOZ_RELEASE_ASSERT(mData < mDataEnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance the iterator by aBytes, possibly crossing segments. This function
|
||||
// returns false if it runs out of buffers to advance through. Otherwise it
|
||||
// returns true.
|
||||
bool AdvanceAcrossSegments(const BufferList& aBuffers, size_t aBytes)
|
||||
{
|
||||
size_t bytes = aBytes;
|
||||
while (bytes) {
|
||||
size_t toAdvance = std::min(bytes, RemainingInSegment());
|
||||
if (!toAdvance) {
|
||||
return false;
|
||||
}
|
||||
Advance(aBuffers, toAdvance);
|
||||
bytes -= toAdvance;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true when the iterator reaches the end of the BufferList.
|
||||
bool Done() const
|
||||
{
|
||||
return mData == mDataEnd;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Count the bytes we would need to advance in order to reach aTarget.
|
||||
size_t BytesUntil(const BufferList& aBuffers, const IterImpl& aTarget) const {
|
||||
size_t offset = 0;
|
||||
|
||||
MOZ_ASSERT(aTarget.IsIn(aBuffers));
|
||||
|
||||
char* data = mData;
|
||||
for (uintptr_t segment = mSegment; segment < aTarget.mSegment; segment++) {
|
||||
offset += aBuffers.mSegments[segment].End() - data;
|
||||
data = aBuffers.mSegments[segment].mData;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(IsIn(aBuffers));
|
||||
MOZ_RELEASE_ASSERT(aTarget.mData >= data);
|
||||
|
||||
offset += aTarget.mData - data;
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool IsIn(const BufferList& aBuffers) const {
|
||||
return mSegment < aBuffers.mSegments.length() &&
|
||||
mData >= aBuffers.mSegments[mSegment].mData &&
|
||||
mData < aBuffers.mSegments[mSegment].End();
|
||||
}
|
||||
};
|
||||
|
||||
// Special convenience method that returns Iter().Data().
|
||||
char* Start() { return mSegments[0].mData; }
|
||||
const char* Start() const { return mSegments[0].mData; }
|
||||
|
||||
IterImpl Iter() const { return IterImpl(*this); }
|
||||
|
||||
// Copies aSize bytes from aData into the BufferList. The storage for these
|
||||
// bytes may be split across multiple buffers. Size() is increased by aSize.
|
||||
inline bool WriteBytes(const char* aData, size_t aSize);
|
||||
|
||||
// Copies possibly non-contiguous byte range starting at aIter into
|
||||
// aData. aIter is advanced by aSize bytes. Returns false if it runs out of
|
||||
// data before aSize.
|
||||
inline bool ReadBytes(IterImpl& aIter, char* aData, size_t aSize) const;
|
||||
|
||||
// Return a new BufferList that shares storage with this BufferList. The new
|
||||
// BufferList is read-only. It allows iteration over aSize bytes starting at
|
||||
// aIter. Borrow can fail, in which case *aSuccess will be false upon
|
||||
// return. The borrowed BufferList can use a different AllocPolicy than the
|
||||
// original one. However, it is not responsible for freeing buffers, so the
|
||||
// AllocPolicy is only used for the buffer vector.
|
||||
template<typename BorrowingAllocPolicy>
|
||||
BufferList<BorrowingAllocPolicy> Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
|
||||
BorrowingAllocPolicy aAP = BorrowingAllocPolicy()) const;
|
||||
|
||||
// Return a new BufferList and move storage from this BufferList to it. The
|
||||
// new BufferList owns the buffers. Move can fail, in which case *aSuccess
|
||||
// will be false upon return. The new BufferList can use a different
|
||||
// AllocPolicy than the original one. The new OtherAllocPolicy is responsible
|
||||
// for freeing buffers, so the OtherAllocPolicy must use freeing method
|
||||
// compatible to the original one.
|
||||
template<typename OtherAllocPolicy>
|
||||
BufferList<OtherAllocPolicy> MoveFallible(bool* aSuccess, OtherAllocPolicy aAP = OtherAllocPolicy());
|
||||
|
||||
// Return a new BufferList that adopts the byte range starting at Iter so that
|
||||
// range [aIter, aIter + aSize) is transplanted to the returned BufferList.
|
||||
// Contents of the buffer before aIter + aSize is left undefined.
|
||||
// Extract can fail, in which case *aSuccess will be false upon return. The
|
||||
// moved buffers are erased from the original BufferList. In case of extract
|
||||
// fails, the original BufferList is intact. All other iterators except aIter
|
||||
// are invalidated.
|
||||
// This method requires aIter and aSize to be 8-byte aligned.
|
||||
BufferList Extract(IterImpl& aIter, size_t aSize, bool* aSuccess);
|
||||
|
||||
// Return the number of bytes from 'start' to 'end', two iterators within
|
||||
// this BufferList.
|
||||
size_t RangeLength(const IterImpl& start, const IterImpl& end) const {
|
||||
MOZ_ASSERT(start.IsIn(*this) && end.IsIn(*this));
|
||||
return start.BytesUntil(*this, end);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit BufferList(AllocPolicy aAP)
|
||||
: AllocPolicy(aAP),
|
||||
mOwning(false),
|
||||
mSize(0),
|
||||
mStandardCapacity(0)
|
||||
{
|
||||
}
|
||||
|
||||
void* AllocateSegment(size_t aSize, size_t aCapacity)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mOwning);
|
||||
|
||||
char* data = this->template pod_malloc<char>(aCapacity);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!mSegments.append(Segment(data, aSize, aCapacity))) {
|
||||
this->free_(data);
|
||||
return nullptr;
|
||||
}
|
||||
mSize += aSize;
|
||||
return data;
|
||||
}
|
||||
|
||||
bool mOwning;
|
||||
Vector<Segment, 1, AllocPolicy> mSegments;
|
||||
size_t mSize;
|
||||
size_t mStandardCapacity;
|
||||
};
|
||||
|
||||
template<typename AllocPolicy>
|
||||
bool
|
||||
BufferList<AllocPolicy>::WriteBytes(const char* aData, size_t aSize)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mOwning);
|
||||
MOZ_RELEASE_ASSERT(mStandardCapacity);
|
||||
|
||||
size_t copied = 0;
|
||||
size_t remaining = aSize;
|
||||
|
||||
if (!mSegments.empty()) {
|
||||
Segment& lastSegment = mSegments.back();
|
||||
|
||||
size_t toCopy = std::min(aSize, lastSegment.mCapacity - lastSegment.mSize);
|
||||
memcpy(lastSegment.mData + lastSegment.mSize, aData, toCopy);
|
||||
lastSegment.mSize += toCopy;
|
||||
mSize += toCopy;
|
||||
|
||||
copied += toCopy;
|
||||
remaining -= toCopy;
|
||||
}
|
||||
|
||||
while (remaining) {
|
||||
size_t toCopy = std::min(remaining, mStandardCapacity);
|
||||
|
||||
void* data = AllocateSegment(toCopy, mStandardCapacity);
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
memcpy(data, aData + copied, toCopy);
|
||||
|
||||
copied += toCopy;
|
||||
remaining -= toCopy;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename AllocPolicy>
|
||||
bool
|
||||
BufferList<AllocPolicy>::ReadBytes(IterImpl& aIter, char* aData, size_t aSize) const
|
||||
{
|
||||
size_t copied = 0;
|
||||
size_t remaining = aSize;
|
||||
while (remaining) {
|
||||
size_t toCopy = std::min(aIter.RemainingInSegment(), remaining);
|
||||
if (!toCopy) {
|
||||
// We've run out of data in the last segment.
|
||||
return false;
|
||||
}
|
||||
memcpy(aData + copied, aIter.Data(), toCopy);
|
||||
copied += toCopy;
|
||||
remaining -= toCopy;
|
||||
|
||||
aIter.Advance(*this, toCopy);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename AllocPolicy> template<typename BorrowingAllocPolicy>
|
||||
BufferList<BorrowingAllocPolicy>
|
||||
BufferList<AllocPolicy>::Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
|
||||
BorrowingAllocPolicy aAP) const
|
||||
{
|
||||
BufferList<BorrowingAllocPolicy> result(aAP);
|
||||
|
||||
size_t size = aSize;
|
||||
while (size) {
|
||||
size_t toAdvance = std::min(size, aIter.RemainingInSegment());
|
||||
|
||||
if (!toAdvance || !result.mSegments.append(typename BufferList<BorrowingAllocPolicy>::Segment(aIter.mData, toAdvance, toAdvance))) {
|
||||
*aSuccess = false;
|
||||
return result;
|
||||
}
|
||||
aIter.Advance(*this, toAdvance);
|
||||
size -= toAdvance;
|
||||
}
|
||||
|
||||
result.mSize = aSize;
|
||||
*aSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename AllocPolicy> template<typename OtherAllocPolicy>
|
||||
BufferList<OtherAllocPolicy>
|
||||
BufferList<AllocPolicy>::MoveFallible(bool* aSuccess, OtherAllocPolicy aAP)
|
||||
{
|
||||
BufferList<OtherAllocPolicy> result(0, 0, mStandardCapacity, aAP);
|
||||
|
||||
IterImpl iter = Iter();
|
||||
while (!iter.Done()) {
|
||||
size_t toAdvance = iter.RemainingInSegment();
|
||||
|
||||
if (!toAdvance || !result.mSegments.append(typename BufferList<OtherAllocPolicy>::Segment(iter.mData, toAdvance, toAdvance))) {
|
||||
*aSuccess = false;
|
||||
result.mSegments.clear();
|
||||
return result;
|
||||
}
|
||||
iter.Advance(*this, toAdvance);
|
||||
}
|
||||
|
||||
result.mSize = mSize;
|
||||
mSegments.clear();
|
||||
mSize = 0;
|
||||
*aSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename AllocPolicy>
|
||||
BufferList<AllocPolicy>
|
||||
BufferList<AllocPolicy>::Extract(IterImpl& aIter, size_t aSize, bool* aSuccess)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aSize);
|
||||
MOZ_RELEASE_ASSERT(mOwning);
|
||||
MOZ_ASSERT(aSize % kSegmentAlignment == 0);
|
||||
MOZ_ASSERT(intptr_t(aIter.mData) % kSegmentAlignment == 0);
|
||||
|
||||
IterImpl iter = aIter;
|
||||
size_t size = aSize;
|
||||
size_t toCopy = std::min(size, aIter.RemainingInSegment());
|
||||
MOZ_ASSERT(toCopy % kSegmentAlignment == 0);
|
||||
|
||||
BufferList result(0, toCopy, mStandardCapacity);
|
||||
BufferList error(0, 0, mStandardCapacity);
|
||||
|
||||
// Copy the head
|
||||
if (!result.WriteBytes(aIter.mData, toCopy)) {
|
||||
*aSuccess = false;
|
||||
return error;
|
||||
}
|
||||
iter.Advance(*this, toCopy);
|
||||
size -= toCopy;
|
||||
|
||||
// Move segments to result
|
||||
auto resultGuard = MakeScopeExit([&] {
|
||||
*aSuccess = false;
|
||||
result.mSegments.erase(result.mSegments.begin()+1, result.mSegments.end());
|
||||
});
|
||||
|
||||
size_t movedSize = 0;
|
||||
uintptr_t toRemoveStart = iter.mSegment;
|
||||
uintptr_t toRemoveEnd = iter.mSegment;
|
||||
while (!iter.Done() &&
|
||||
!iter.HasRoomFor(size)) {
|
||||
if (!result.mSegments.append(Segment(mSegments[iter.mSegment].mData,
|
||||
mSegments[iter.mSegment].mSize,
|
||||
mSegments[iter.mSegment].mCapacity))) {
|
||||
return error;
|
||||
}
|
||||
movedSize += iter.RemainingInSegment();
|
||||
size -= iter.RemainingInSegment();
|
||||
toRemoveEnd++;
|
||||
iter.Advance(*this, iter.RemainingInSegment());
|
||||
}
|
||||
|
||||
if (size) {
|
||||
if (!iter.HasRoomFor(size) ||
|
||||
!result.WriteBytes(iter.Data(), size)) {
|
||||
return error;
|
||||
}
|
||||
iter.Advance(*this, size);
|
||||
}
|
||||
|
||||
mSegments.erase(mSegments.begin() + toRemoveStart, mSegments.begin() + toRemoveEnd);
|
||||
mSize -= movedSize;
|
||||
aIter.mSegment = iter.mSegment - (toRemoveEnd - toRemoveStart);
|
||||
aIter.mData = iter.mData;
|
||||
aIter.mDataEnd = iter.mDataEnd;
|
||||
MOZ_ASSERT(aIter.mDataEnd == mSegments[aIter.mSegment].End());
|
||||
result.mSize = aSize;
|
||||
|
||||
resultGuard.release();
|
||||
*aSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_BufferList_h */
|
||||
243
cocos2d-x/external/win32/include/spidermonkey/mozilla/Casting.h
vendored
Executable file
243
cocos2d-x/external/win32/include/spidermonkey/mozilla/Casting.h
vendored
Executable file
@@ -0,0 +1,243 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Cast operations to supplement the built-in casting operations. */
|
||||
|
||||
#ifndef mozilla_Casting_h
|
||||
#define mozilla_Casting_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Sets the outparam value of type |To| with the same underlying bit pattern of
|
||||
* |aFrom|.
|
||||
*
|
||||
* |To| and |From| must be types of the same size; be careful of cross-platform
|
||||
* size differences, or this might fail to compile on some but not all
|
||||
* platforms.
|
||||
*
|
||||
* There is also a variant that returns the value directly. In most cases, the
|
||||
* two variants should be identical. However, in the specific case of x86
|
||||
* chips, the behavior differs: returning floating-point values directly is done
|
||||
* through the x87 stack, and x87 loads and stores turn signaling NaNs into
|
||||
* quiet NaNs... silently. Returning floating-point values via outparam,
|
||||
* however, is done entirely within the SSE registers when SSE2 floating-point
|
||||
* is enabled in the compiler, which has semantics-preserving behavior you would
|
||||
* expect.
|
||||
*
|
||||
* If preserving the distinction between signaling NaNs and quiet NaNs is
|
||||
* important to you, you should use the outparam version. In all other cases,
|
||||
* you should use the direct return version.
|
||||
*/
|
||||
template<typename To, typename From>
|
||||
inline void
|
||||
BitwiseCast(const From aFrom, To* aResult)
|
||||
{
|
||||
static_assert(sizeof(From) == sizeof(To),
|
||||
"To and From must have the same size");
|
||||
union
|
||||
{
|
||||
From mFrom;
|
||||
To mTo;
|
||||
} u;
|
||||
u.mFrom = aFrom;
|
||||
*aResult = u.mTo;
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
inline To
|
||||
BitwiseCast(const From aFrom)
|
||||
{
|
||||
To temp;
|
||||
BitwiseCast<To, From>(aFrom, &temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum ToSignedness { ToIsSigned, ToIsUnsigned };
|
||||
enum FromSignedness { FromIsSigned, FromIsUnsigned };
|
||||
|
||||
template<typename From,
|
||||
typename To,
|
||||
FromSignedness = IsSigned<From>::value ? FromIsSigned : FromIsUnsigned,
|
||||
ToSignedness = IsSigned<To>::value ? ToIsSigned : ToIsUnsigned>
|
||||
struct BoundsCheckImpl;
|
||||
|
||||
// Implicit conversions on operands to binary operations make this all a bit
|
||||
// hard to verify. Attempt to ease the pain below by *only* comparing values
|
||||
// that are obviously the same type (and will undergo no further conversions),
|
||||
// even when it's not strictly necessary, for explicitness.
|
||||
|
||||
enum UUComparison { FromIsBigger, FromIsNotBigger };
|
||||
|
||||
// Unsigned-to-unsigned range check
|
||||
|
||||
template<typename From, typename To,
|
||||
UUComparison = (sizeof(From) > sizeof(To))
|
||||
? FromIsBigger
|
||||
: FromIsNotBigger>
|
||||
struct UnsignedUnsignedCheck;
|
||||
|
||||
template<typename From, typename To>
|
||||
struct UnsignedUnsignedCheck<From, To, FromIsBigger>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
return aFrom <= From(To(-1));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
struct UnsignedUnsignedCheck<From, To, FromIsNotBigger>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
struct BoundsCheckImpl<From, To, FromIsUnsigned, ToIsUnsigned>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
return UnsignedUnsignedCheck<From, To>::checkBounds(aFrom);
|
||||
}
|
||||
};
|
||||
|
||||
// Signed-to-unsigned range check
|
||||
|
||||
template<typename From, typename To>
|
||||
struct BoundsCheckImpl<From, To, FromIsSigned, ToIsUnsigned>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
if (aFrom < 0) {
|
||||
return false;
|
||||
}
|
||||
if (sizeof(To) >= sizeof(From)) {
|
||||
return true;
|
||||
}
|
||||
return aFrom <= From(To(-1));
|
||||
}
|
||||
};
|
||||
|
||||
// Unsigned-to-signed range check
|
||||
|
||||
enum USComparison { FromIsSmaller, FromIsNotSmaller };
|
||||
|
||||
template<typename From, typename To,
|
||||
USComparison = (sizeof(From) < sizeof(To))
|
||||
? FromIsSmaller
|
||||
: FromIsNotSmaller>
|
||||
struct UnsignedSignedCheck;
|
||||
|
||||
template<typename From, typename To>
|
||||
struct UnsignedSignedCheck<From, To, FromIsSmaller>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
struct UnsignedSignedCheck<From, To, FromIsNotSmaller>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
const To MaxValue = To((1ULL << (CHAR_BIT * sizeof(To) - 1)) - 1);
|
||||
return aFrom <= From(MaxValue);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
struct BoundsCheckImpl<From, To, FromIsUnsigned, ToIsSigned>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
return UnsignedSignedCheck<From, To>::checkBounds(aFrom);
|
||||
}
|
||||
};
|
||||
|
||||
// Signed-to-signed range check
|
||||
|
||||
template<typename From, typename To>
|
||||
struct BoundsCheckImpl<From, To, FromIsSigned, ToIsSigned>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
if (sizeof(From) <= sizeof(To)) {
|
||||
return true;
|
||||
}
|
||||
const To MaxValue = To((1ULL << (CHAR_BIT * sizeof(To) - 1)) - 1);
|
||||
const To MinValue = -MaxValue - To(1);
|
||||
return From(MinValue) <= aFrom &&
|
||||
From(aFrom) <= From(MaxValue);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From, typename To,
|
||||
bool TypesAreIntegral = IsIntegral<From>::value &&
|
||||
IsIntegral<To>::value>
|
||||
class BoundsChecker;
|
||||
|
||||
template<typename From>
|
||||
class BoundsChecker<From, From, true>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom) { return true; }
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class BoundsChecker<From, To, true>
|
||||
{
|
||||
public:
|
||||
static bool checkBounds(const From aFrom)
|
||||
{
|
||||
return BoundsCheckImpl<From, To>::checkBounds(aFrom);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
inline bool
|
||||
IsInBounds(const From aFrom)
|
||||
{
|
||||
return BoundsChecker<From, To>::checkBounds(aFrom);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Cast a value of integral type |From| to a value of integral type |To|,
|
||||
* asserting that the cast will be a safe cast per C++ (that is, that |to| is in
|
||||
* the range of values permitted for the type |From|).
|
||||
*/
|
||||
template<typename To, typename From>
|
||||
inline To
|
||||
AssertedCast(const From aFrom)
|
||||
{
|
||||
MOZ_ASSERT((detail::IsInBounds<From, To>(aFrom)));
|
||||
return static_cast<To>(aFrom);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Casting_h */
|
||||
94
cocos2d-x/external/win32/include/spidermonkey/mozilla/ChaosMode.h
vendored
Executable file
94
cocos2d-x/external/win32/include/spidermonkey/mozilla/ChaosMode.h
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_ChaosMode_h
|
||||
#define mozilla_ChaosMode_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum ChaosFeature {
|
||||
None = 0x0,
|
||||
// Altering thread scheduling.
|
||||
ThreadScheduling = 0x1,
|
||||
// Altering network request scheduling.
|
||||
NetworkScheduling = 0x2,
|
||||
// Altering timer scheduling.
|
||||
TimerScheduling = 0x4,
|
||||
// Read and write less-than-requested amounts.
|
||||
IOAmounts = 0x8,
|
||||
// Iterate over hash tables in random order.
|
||||
HashTableIteration = 0x10,
|
||||
// Randomly refuse to use cached version of image (when allowed by spec).
|
||||
ImageCache = 0x20,
|
||||
Any = 0xffffffff,
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
extern MFBT_DATA Atomic<uint32_t> gChaosModeCounter;
|
||||
extern MFBT_DATA ChaosFeature gChaosFeatures;
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* When "chaos mode" is activated, code that makes implicitly nondeterministic
|
||||
* choices is encouraged to make random and extreme choices, to test more
|
||||
* code paths and uncover bugs.
|
||||
*/
|
||||
class ChaosMode
|
||||
{
|
||||
public:
|
||||
static void SetChaosFeature(ChaosFeature aChaosFeature)
|
||||
{
|
||||
detail::gChaosFeatures = aChaosFeature;
|
||||
}
|
||||
|
||||
static bool isActive(ChaosFeature aFeature)
|
||||
{
|
||||
if (detail::gChaosModeCounter > 0) {
|
||||
return true;
|
||||
}
|
||||
return detail::gChaosFeatures & aFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the chaos mode activation level. An equivalent number of
|
||||
* calls to leaveChaosMode must be made in order to restore the original
|
||||
* chaos mode state. If the activation level is nonzero all chaos mode
|
||||
* features are activated.
|
||||
*/
|
||||
static void enterChaosMode()
|
||||
{
|
||||
detail::gChaosModeCounter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the chaos mode activation level. See enterChaosMode().
|
||||
*/
|
||||
static void leaveChaosMode()
|
||||
{
|
||||
MOZ_ASSERT(detail::gChaosModeCounter > 0);
|
||||
detail::gChaosModeCounter--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a somewhat (but not uniformly) random uint32_t < aBound.
|
||||
* Not to be used for anything except ChaosMode, since it's not very random.
|
||||
*/
|
||||
static uint32_t randomUint32LessThan(uint32_t aBound)
|
||||
{
|
||||
MOZ_ASSERT(aBound != 0);
|
||||
return uint32_t(rand()) % aBound;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_ChaosMode_h */
|
||||
194
cocos2d-x/external/win32/include/spidermonkey/mozilla/Char16.h
vendored
Executable file
194
cocos2d-x/external/win32/include/spidermonkey/mozilla/Char16.h
vendored
Executable file
@@ -0,0 +1,194 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implements a UTF-16 character type. */
|
||||
|
||||
#ifndef mozilla_Char16_h
|
||||
#define mozilla_Char16_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
* C++11 introduces a char16_t type and support for UTF-16 string and character
|
||||
* literals. C++11's char16_t is a distinct builtin type. Technically, char16_t
|
||||
* is a 16-bit code unit of a Unicode code point, not a "character".
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
# define MOZ_USE_CHAR16_WRAPPER
|
||||
# include <cstdint>
|
||||
/**
|
||||
* Win32 API extensively uses wchar_t, which is represented by a separated
|
||||
* builtin type than char16_t per spec. It's not the case for MSVC prior to
|
||||
* MSVC 2015, but other compilers follow the spec. We want to mix wchar_t and
|
||||
* char16_t on Windows builds. This class is supposed to make it easier. It
|
||||
* stores char16_t const pointer, but provides implicit casts for wchar_t as
|
||||
* well. On other platforms, we simply use
|
||||
* |typedef const char16_t* char16ptr_t|. Here, we want to make the class as
|
||||
* similar to this typedef, including providing some casts that are allowed
|
||||
* by the typedef.
|
||||
*/
|
||||
class char16ptr_t
|
||||
{
|
||||
private:
|
||||
const char16_t* mPtr;
|
||||
static_assert(sizeof(char16_t) == sizeof(wchar_t),
|
||||
"char16_t and wchar_t sizes differ");
|
||||
|
||||
public:
|
||||
char16ptr_t(const char16_t* aPtr) : mPtr(aPtr) {}
|
||||
char16ptr_t(const wchar_t* aPtr) :
|
||||
mPtr(reinterpret_cast<const char16_t*>(aPtr))
|
||||
{}
|
||||
|
||||
/* Without this, nullptr assignment would be ambiguous. */
|
||||
constexpr char16ptr_t(decltype(nullptr)) : mPtr(nullptr) {}
|
||||
|
||||
operator const char16_t*() const
|
||||
{
|
||||
return mPtr;
|
||||
}
|
||||
operator const wchar_t*() const
|
||||
{
|
||||
return reinterpret_cast<const wchar_t*>(mPtr);
|
||||
}
|
||||
operator const void*() const
|
||||
{
|
||||
return mPtr;
|
||||
}
|
||||
operator bool() const
|
||||
{
|
||||
return mPtr != nullptr;
|
||||
}
|
||||
|
||||
/* Explicit cast operators to allow things like (char16_t*)str. */
|
||||
explicit operator char16_t*() const
|
||||
{
|
||||
return const_cast<char16_t*>(mPtr);
|
||||
}
|
||||
explicit operator wchar_t*() const
|
||||
{
|
||||
return const_cast<wchar_t*>(static_cast<const wchar_t*>(*this));
|
||||
}
|
||||
explicit operator int() const
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(mPtr);
|
||||
}
|
||||
explicit operator unsigned int() const
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(mPtr);
|
||||
}
|
||||
explicit operator long() const
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(mPtr);
|
||||
}
|
||||
explicit operator unsigned long() const
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(mPtr);
|
||||
}
|
||||
explicit operator long long() const
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(mPtr);
|
||||
}
|
||||
explicit operator unsigned long long() const
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(mPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some Windows API calls accept BYTE* but require that data actually be
|
||||
* WCHAR*. Supporting this requires explicit operators to support the
|
||||
* requisite explicit casts.
|
||||
*/
|
||||
explicit operator const char*() const
|
||||
{
|
||||
return reinterpret_cast<const char*>(mPtr);
|
||||
}
|
||||
explicit operator const unsigned char*() const
|
||||
{
|
||||
return reinterpret_cast<const unsigned char*>(mPtr);
|
||||
}
|
||||
explicit operator unsigned char*() const
|
||||
{
|
||||
return
|
||||
const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(mPtr));
|
||||
}
|
||||
explicit operator void*() const
|
||||
{
|
||||
return const_cast<char16_t*>(mPtr);
|
||||
}
|
||||
|
||||
/* Some operators used on pointers. */
|
||||
char16_t operator[](size_t aIndex) const
|
||||
{
|
||||
return mPtr[aIndex];
|
||||
}
|
||||
bool operator==(const char16ptr_t& aOther) const
|
||||
{
|
||||
return mPtr == aOther.mPtr;
|
||||
}
|
||||
bool operator==(decltype(nullptr)) const
|
||||
{
|
||||
return mPtr == nullptr;
|
||||
}
|
||||
bool operator!=(const char16ptr_t& aOther) const
|
||||
{
|
||||
return mPtr != aOther.mPtr;
|
||||
}
|
||||
bool operator!=(decltype(nullptr)) const
|
||||
{
|
||||
return mPtr != nullptr;
|
||||
}
|
||||
char16ptr_t operator+(int aValue) const
|
||||
{
|
||||
return char16ptr_t(mPtr + aValue);
|
||||
}
|
||||
char16ptr_t operator+(unsigned int aValue) const
|
||||
{
|
||||
return char16ptr_t(mPtr + aValue);
|
||||
}
|
||||
char16ptr_t operator+(long aValue) const
|
||||
{
|
||||
return char16ptr_t(mPtr + aValue);
|
||||
}
|
||||
char16ptr_t operator+(unsigned long aValue) const
|
||||
{
|
||||
return char16ptr_t(mPtr + aValue);
|
||||
}
|
||||
char16ptr_t operator+(long long aValue) const
|
||||
{
|
||||
return char16ptr_t(mPtr + aValue);
|
||||
}
|
||||
char16ptr_t operator+(unsigned long long aValue) const
|
||||
{
|
||||
return char16ptr_t(mPtr + aValue);
|
||||
}
|
||||
ptrdiff_t operator-(const char16ptr_t& aOther) const
|
||||
{
|
||||
return mPtr - aOther.mPtr;
|
||||
}
|
||||
};
|
||||
|
||||
inline decltype((char*)0-(char*)0)
|
||||
operator-(const char16_t* aX, const char16ptr_t aY)
|
||||
{
|
||||
return aX - static_cast<const char16_t*>(aY);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef const char16_t* char16ptr_t;
|
||||
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(char16_t) == 2, "Is char16_t type 16 bits?");
|
||||
static_assert(char16_t(-1) > char16_t(0), "Is char16_t type unsigned?");
|
||||
static_assert(sizeof(u'A') == 2, "Is unicode char literal 16 bits?");
|
||||
static_assert(sizeof(u""[0]) == 2, "Is unicode string char 16 bits?");
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Char16_h */
|
||||
791
cocos2d-x/external/win32/include/spidermonkey/mozilla/CheckedInt.h
vendored
Executable file
791
cocos2d-x/external/win32/include/spidermonkey/mozilla/CheckedInt.h
vendored
Executable file
@@ -0,0 +1,791 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Provides checked integers, detecting integer overflow and divide-by-0. */
|
||||
|
||||
#ifndef mozilla_CheckedInt_h
|
||||
#define mozilla_CheckedInt_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T> class CheckedInt;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* Step 1: manually record supported types
|
||||
*
|
||||
* What's nontrivial here is that there are different families of integer
|
||||
* types: basic integer types and stdint types. It is merrily undefined which
|
||||
* types from one family may be just typedefs for a type from another family.
|
||||
*
|
||||
* For example, on GCC 4.6, aside from the basic integer types, the only other
|
||||
* type that isn't just a typedef for some of them, is int8_t.
|
||||
*/
|
||||
|
||||
struct UnsupportedType {};
|
||||
|
||||
template<typename IntegerType>
|
||||
struct IsSupportedPass2
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename IntegerType>
|
||||
struct IsSupported
|
||||
{
|
||||
static const bool value = IsSupportedPass2<IntegerType>::value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct IsSupported<int8_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<uint8_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<int16_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<uint16_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<int32_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<uint32_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<int64_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupported<uint64_t>
|
||||
{ static const bool value = true; };
|
||||
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<char>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<signed char>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<unsigned char>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<short>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<unsigned short>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<int>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<unsigned int>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<long>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<unsigned long>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<long long>
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<>
|
||||
struct IsSupportedPass2<unsigned long long>
|
||||
{ static const bool value = true; };
|
||||
|
||||
/*
|
||||
* Step 2: Implement the actual validity checks.
|
||||
*
|
||||
* Ideas taken from IntegerLib, code different.
|
||||
*/
|
||||
|
||||
template<typename IntegerType, size_t Size = sizeof(IntegerType)>
|
||||
struct TwiceBiggerType
|
||||
{
|
||||
typedef typename detail::StdintTypeForSizeAndSignedness<
|
||||
sizeof(IntegerType) * 2,
|
||||
IsSigned<IntegerType>::value
|
||||
>::Type Type;
|
||||
};
|
||||
|
||||
template<typename IntegerType>
|
||||
struct TwiceBiggerType<IntegerType, 8>
|
||||
{
|
||||
typedef UnsupportedType Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
HasSignBit(T aX)
|
||||
{
|
||||
// In C++, right bit shifts on negative values is undefined by the standard.
|
||||
// Notice that signed-to-unsigned conversions are always well-defined in the
|
||||
// standard, as the value congruent modulo 2**n as expected. By contrast,
|
||||
// unsigned-to-signed is only well-defined if the value is representable.
|
||||
return bool(typename MakeUnsigned<T>::Type(aX) >>
|
||||
PositionOfSignBit<T>::value);
|
||||
}
|
||||
|
||||
// Bitwise ops may return a larger type, so it's good to use this inline
|
||||
// helper guaranteeing that the result is really of type T.
|
||||
template<typename T>
|
||||
inline T
|
||||
BinaryComplement(T aX)
|
||||
{
|
||||
return ~aX;
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename U,
|
||||
bool IsTSigned = IsSigned<T>::value,
|
||||
bool IsUSigned = IsSigned<U>::value>
|
||||
struct DoesRangeContainRange
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T, typename U, bool Signedness>
|
||||
struct DoesRangeContainRange<T, U, Signedness, Signedness>
|
||||
{
|
||||
static const bool value = sizeof(T) >= sizeof(U);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct DoesRangeContainRange<T, U, true, false>
|
||||
{
|
||||
static const bool value = sizeof(T) > sizeof(U);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct DoesRangeContainRange<T, U, false, true>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T,
|
||||
typename U,
|
||||
bool IsTSigned = IsSigned<T>::value,
|
||||
bool IsUSigned = IsSigned<U>::value,
|
||||
bool DoesTRangeContainURange = DoesRangeContainRange<T, U>::value>
|
||||
struct IsInRangeImpl {};
|
||||
|
||||
template<typename T, typename U, bool IsTSigned, bool IsUSigned>
|
||||
struct IsInRangeImpl<T, U, IsTSigned, IsUSigned, true>
|
||||
{
|
||||
static bool run(U)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsInRangeImpl<T, U, true, true, false>
|
||||
{
|
||||
static bool run(U aX)
|
||||
{
|
||||
return aX <= MaxValue<T>::value && aX >= MinValue<T>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsInRangeImpl<T, U, false, false, false>
|
||||
{
|
||||
static bool run(U aX)
|
||||
{
|
||||
return aX <= MaxValue<T>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsInRangeImpl<T, U, true, false, false>
|
||||
{
|
||||
static bool run(U aX)
|
||||
{
|
||||
return sizeof(T) > sizeof(U) || aX <= U(MaxValue<T>::value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsInRangeImpl<T, U, false, true, false>
|
||||
{
|
||||
static bool run(U aX)
|
||||
{
|
||||
return sizeof(T) >= sizeof(U)
|
||||
? aX >= 0
|
||||
: aX >= 0 && aX <= U(MaxValue<T>::value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool
|
||||
IsInRange(U aX)
|
||||
{
|
||||
return IsInRangeImpl<T, U>::run(aX);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsAddValid(T aX, T aY)
|
||||
{
|
||||
// Addition is valid if the sign of aX+aY is equal to either that of aX or
|
||||
// that of aY. Since the value of aX+aY is undefined if we have a signed
|
||||
// type, we compute it using the unsigned type of the same size. Beware!
|
||||
// These bitwise operations can return a larger integer type, if T was a
|
||||
// small type like int8_t, so we explicitly cast to T.
|
||||
|
||||
typename MakeUnsigned<T>::Type ux = aX;
|
||||
typename MakeUnsigned<T>::Type uy = aY;
|
||||
typename MakeUnsigned<T>::Type result = ux + uy;
|
||||
return IsSigned<T>::value
|
||||
? HasSignBit(BinaryComplement(T((result ^ aX) & (result ^ aY))))
|
||||
: BinaryComplement(aX) >= aY;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsSubValid(T aX, T aY)
|
||||
{
|
||||
// Subtraction is valid if either aX and aY have same sign, or aX-aY and aX
|
||||
// have same sign. Since the value of aX-aY is undefined if we have a signed
|
||||
// type, we compute it using the unsigned type of the same size.
|
||||
typename MakeUnsigned<T>::Type ux = aX;
|
||||
typename MakeUnsigned<T>::Type uy = aY;
|
||||
typename MakeUnsigned<T>::Type result = ux - uy;
|
||||
|
||||
return IsSigned<T>::value
|
||||
? HasSignBit(BinaryComplement(T((result ^ aX) & (aX ^ aY))))
|
||||
: aX >= aY;
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
bool IsTSigned = IsSigned<T>::value,
|
||||
bool TwiceBiggerTypeIsSupported =
|
||||
IsSupported<typename TwiceBiggerType<T>::Type>::value>
|
||||
struct IsMulValidImpl {};
|
||||
|
||||
template<typename T, bool IsTSigned>
|
||||
struct IsMulValidImpl<T, IsTSigned, true>
|
||||
{
|
||||
static bool run(T aX, T aY)
|
||||
{
|
||||
typedef typename TwiceBiggerType<T>::Type TwiceBiggerType;
|
||||
TwiceBiggerType product = TwiceBiggerType(aX) * TwiceBiggerType(aY);
|
||||
return IsInRange<T>(product);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsMulValidImpl<T, true, false>
|
||||
{
|
||||
static bool run(T aX, T aY)
|
||||
{
|
||||
const T max = MaxValue<T>::value;
|
||||
const T min = MinValue<T>::value;
|
||||
|
||||
if (aX == 0 || aY == 0) {
|
||||
return true;
|
||||
}
|
||||
if (aX > 0) {
|
||||
return aY > 0
|
||||
? aX <= max / aY
|
||||
: aY >= min / aX;
|
||||
}
|
||||
|
||||
// If we reach this point, we know that aX < 0.
|
||||
return aY > 0
|
||||
? aX >= min / aY
|
||||
: aY >= max / aX;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsMulValidImpl<T, false, false>
|
||||
{
|
||||
static bool run(T aX, T aY)
|
||||
{
|
||||
return aY == 0 || aX <= MaxValue<T>::value / aY;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsMulValid(T aX, T aY)
|
||||
{
|
||||
return IsMulValidImpl<T>::run(aX, aY);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsDivValid(T aX, T aY)
|
||||
{
|
||||
// Keep in mind that in the signed case, min/-1 is invalid because
|
||||
// abs(min)>max.
|
||||
return aY != 0 &&
|
||||
!(IsSigned<T>::value && aX == MinValue<T>::value && aY == T(-1));
|
||||
}
|
||||
|
||||
template<typename T, bool IsTSigned = IsSigned<T>::value>
|
||||
struct IsModValidImpl;
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsModValid(T aX, T aY)
|
||||
{
|
||||
return IsModValidImpl<T>::run(aX, aY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mod is pretty simple.
|
||||
* For now, let's just use the ANSI C definition:
|
||||
* If aX or aY are negative, the results are implementation defined.
|
||||
* Consider these invalid.
|
||||
* Undefined for aY=0.
|
||||
* The result will never exceed either aX or aY.
|
||||
*
|
||||
* Checking that aX>=0 is a warning when T is unsigned.
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
struct IsModValidImpl<T, false>
|
||||
{
|
||||
static inline bool run(T aX, T aY)
|
||||
{
|
||||
return aY >= 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsModValidImpl<T, true>
|
||||
{
|
||||
static inline bool run(T aX, T aY)
|
||||
{
|
||||
if (aX < 0) {
|
||||
return false;
|
||||
}
|
||||
return aY >= 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool IsSigned = IsSigned<T>::value>
|
||||
struct NegateImpl;
|
||||
|
||||
template<typename T>
|
||||
struct NegateImpl<T, false>
|
||||
{
|
||||
static CheckedInt<T> negate(const CheckedInt<T>& aVal)
|
||||
{
|
||||
// Handle negation separately for signed/unsigned, for simpler code and to
|
||||
// avoid an MSVC warning negating an unsigned value.
|
||||
return CheckedInt<T>(0, aVal.isValid() && aVal.mValue == 0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct NegateImpl<T, true>
|
||||
{
|
||||
static CheckedInt<T> negate(const CheckedInt<T>& aVal)
|
||||
{
|
||||
// Watch out for the min-value, which (with twos-complement) can't be
|
||||
// negated as -min-value is then (max-value + 1).
|
||||
if (!aVal.isValid() || aVal.mValue == MinValue<T>::value) {
|
||||
return CheckedInt<T>(aVal.mValue, false);
|
||||
}
|
||||
return CheckedInt<T>(-aVal.mValue, true);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/*
|
||||
* Step 3: Now define the CheckedInt class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class CheckedInt
|
||||
* @brief Integer wrapper class checking for integer overflow and other errors
|
||||
* @param T the integer type to wrap. Can be any type among the following:
|
||||
* - any basic integer type such as |int|
|
||||
* - any stdint type such as |int8_t|
|
||||
*
|
||||
* This class implements guarded integer arithmetic. Do a computation, check
|
||||
* that isValid() returns true, you then have a guarantee that no problem, such
|
||||
* as integer overflow, happened during this computation, and you can call
|
||||
* value() to get the plain integer value.
|
||||
*
|
||||
* The arithmetic operators in this class are guaranteed not to raise a signal
|
||||
* (e.g. in case of a division by zero).
|
||||
*
|
||||
* For example, suppose that you want to implement a function that computes
|
||||
* (aX+aY)/aZ, that doesn't crash if aZ==0, and that reports on error (divide by
|
||||
* zero or integer overflow). You could code it as follows:
|
||||
@code
|
||||
bool computeXPlusYOverZ(int aX, int aY, int aZ, int* aResult)
|
||||
{
|
||||
CheckedInt<int> checkedResult = (CheckedInt<int>(aX) + aY) / aZ;
|
||||
if (checkedResult.isValid()) {
|
||||
*aResult = checkedResult.value();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
*
|
||||
* Implicit conversion from plain integers to checked integers is allowed. The
|
||||
* plain integer is checked to be in range before being casted to the
|
||||
* destination type. This means that the following lines all compile, and the
|
||||
* resulting CheckedInts are correctly detected as valid or invalid:
|
||||
* @code
|
||||
// 1 is of type int, is found to be in range for uint8_t, x is valid
|
||||
CheckedInt<uint8_t> x(1);
|
||||
// -1 is of type int, is found not to be in range for uint8_t, x is invalid
|
||||
CheckedInt<uint8_t> x(-1);
|
||||
// -1 is of type int, is found to be in range for int8_t, x is valid
|
||||
CheckedInt<int8_t> x(-1);
|
||||
// 1000 is of type int16_t, is found not to be in range for int8_t,
|
||||
// x is invalid
|
||||
CheckedInt<int8_t> x(int16_t(1000));
|
||||
// 3123456789 is of type uint32_t, is found not to be in range for int32_t,
|
||||
// x is invalid
|
||||
CheckedInt<int32_t> x(uint32_t(3123456789));
|
||||
* @endcode
|
||||
* Implicit conversion from
|
||||
* checked integers to plain integers is not allowed. As shown in the
|
||||
* above example, to get the value of a checked integer as a normal integer,
|
||||
* call value().
|
||||
*
|
||||
* Arithmetic operations between checked and plain integers is allowed; the
|
||||
* result type is the type of the checked integer.
|
||||
*
|
||||
* Checked integers of different types cannot be used in the same arithmetic
|
||||
* expression.
|
||||
*
|
||||
* There are convenience typedefs for all stdint types, of the following form
|
||||
* (these are just 2 examples):
|
||||
@code
|
||||
typedef CheckedInt<int32_t> CheckedInt32;
|
||||
typedef CheckedInt<uint16_t> CheckedUint16;
|
||||
@endcode
|
||||
*/
|
||||
template<typename T>
|
||||
class CheckedInt
|
||||
{
|
||||
protected:
|
||||
T mValue;
|
||||
bool mIsValid;
|
||||
|
||||
template<typename U>
|
||||
CheckedInt(U aValue, bool aIsValid) : mValue(aValue), mIsValid(aIsValid)
|
||||
{
|
||||
static_assert(detail::IsSupported<T>::value &&
|
||||
detail::IsSupported<U>::value,
|
||||
"This type is not supported by CheckedInt");
|
||||
}
|
||||
|
||||
friend struct detail::NegateImpl<T>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a checked integer with given @a value. The checked integer is
|
||||
* initialized as valid or invalid depending on whether the @a value
|
||||
* is in range.
|
||||
*
|
||||
* This constructor is not explicit. Instead, the type of its argument is a
|
||||
* separate template parameter, ensuring that no conversion is performed
|
||||
* before this constructor is actually called. As explained in the above
|
||||
* documentation for class CheckedInt, this constructor checks that its
|
||||
* argument is valid.
|
||||
*/
|
||||
template<typename U>
|
||||
MOZ_IMPLICIT CheckedInt(U aValue) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT
|
||||
: mValue(T(aValue)),
|
||||
mIsValid(detail::IsInRange<T>(aValue))
|
||||
{
|
||||
static_assert(detail::IsSupported<T>::value &&
|
||||
detail::IsSupported<U>::value,
|
||||
"This type is not supported by CheckedInt");
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend class CheckedInt;
|
||||
|
||||
template<typename U>
|
||||
CheckedInt<U> toChecked() const
|
||||
{
|
||||
CheckedInt<U> ret(mValue);
|
||||
ret.mIsValid = ret.mIsValid && mIsValid;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Constructs a valid checked integer with initial value 0 */
|
||||
CheckedInt() : mValue(0), mIsValid(true)
|
||||
{
|
||||
static_assert(detail::IsSupported<T>::value,
|
||||
"This type is not supported by CheckedInt");
|
||||
}
|
||||
|
||||
/** @returns the actual value */
|
||||
T value() const
|
||||
{
|
||||
MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns true if the checked integer is valid, i.e. is not the result
|
||||
* of an invalid operation or of an operation involving an invalid checked
|
||||
* integer
|
||||
*/
|
||||
bool isValid() const
|
||||
{
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend CheckedInt<U> operator +(const CheckedInt<U>& aLhs,
|
||||
const CheckedInt<U>& aRhs);
|
||||
template<typename U>
|
||||
CheckedInt& operator +=(U aRhs);
|
||||
CheckedInt& operator +=(const CheckedInt<T>& aRhs);
|
||||
|
||||
template<typename U>
|
||||
friend CheckedInt<U> operator -(const CheckedInt<U>& aLhs,
|
||||
const CheckedInt<U>& aRhs);
|
||||
template<typename U>
|
||||
CheckedInt& operator -=(U aRhs);
|
||||
CheckedInt& operator -=(const CheckedInt<T>& aRhs);
|
||||
|
||||
template<typename U>
|
||||
friend CheckedInt<U> operator *(const CheckedInt<U>& aLhs,
|
||||
const CheckedInt<U>& aRhs);
|
||||
template<typename U>
|
||||
CheckedInt& operator *=(U aRhs);
|
||||
CheckedInt& operator *=(const CheckedInt<T>& aRhs);
|
||||
|
||||
template<typename U>
|
||||
friend CheckedInt<U> operator /(const CheckedInt<U>& aLhs,
|
||||
const CheckedInt<U>& aRhs);
|
||||
template<typename U>
|
||||
CheckedInt& operator /=(U aRhs);
|
||||
CheckedInt& operator /=(const CheckedInt<T>& aRhs);
|
||||
|
||||
template<typename U>
|
||||
friend CheckedInt<U> operator %(const CheckedInt<U>& aLhs,
|
||||
const CheckedInt<U>& aRhs);
|
||||
template<typename U>
|
||||
CheckedInt& operator %=(U aRhs);
|
||||
CheckedInt& operator %=(const CheckedInt<T>& aRhs);
|
||||
|
||||
CheckedInt operator -() const
|
||||
{
|
||||
return detail::NegateImpl<T>::negate(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns true if the left and right hand sides are valid
|
||||
* and have the same value.
|
||||
*
|
||||
* Note that these semantics are the reason why we don't offer
|
||||
* a operator!=. Indeed, we'd want to have a!=b be equivalent to !(a==b)
|
||||
* but that would mean that whenever a or b is invalid, a!=b
|
||||
* is always true, which would be very confusing.
|
||||
*
|
||||
* For similar reasons, operators <, >, <=, >= would be very tricky to
|
||||
* specify, so we just avoid offering them.
|
||||
*
|
||||
* Notice that these == semantics are made more reasonable by these facts:
|
||||
* 1. a==b implies equality at the raw data level
|
||||
* (the converse is false, as a==b is never true among invalids)
|
||||
* 2. This is similar to the behavior of IEEE floats, where a==b
|
||||
* means that a and b have the same value *and* neither is NaN.
|
||||
*/
|
||||
bool operator ==(const CheckedInt& aOther) const
|
||||
{
|
||||
return mIsValid && aOther.mIsValid && mValue == aOther.mValue;
|
||||
}
|
||||
|
||||
/** prefix ++ */
|
||||
CheckedInt& operator++()
|
||||
{
|
||||
*this += 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** postfix ++ */
|
||||
CheckedInt operator++(int)
|
||||
{
|
||||
CheckedInt tmp = *this;
|
||||
*this += 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/** prefix -- */
|
||||
CheckedInt& operator--()
|
||||
{
|
||||
*this -= 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** postfix -- */
|
||||
CheckedInt operator--(int)
|
||||
{
|
||||
CheckedInt tmp = *this;
|
||||
*this -= 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The !=, <, <=, >, >= operators are disabled:
|
||||
* see the comment on operator==.
|
||||
*/
|
||||
template<typename U> bool operator !=(U aOther) const = delete;
|
||||
template<typename U> bool operator < (U aOther) const = delete;
|
||||
template<typename U> bool operator <=(U aOther) const = delete;
|
||||
template<typename U> bool operator > (U aOther) const = delete;
|
||||
template<typename U> bool operator >=(U aOther) const = delete;
|
||||
};
|
||||
|
||||
#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
|
||||
template<typename T> \
|
||||
inline CheckedInt<T> \
|
||||
operator OP(const CheckedInt<T>& aLhs, const CheckedInt<T>& aRhs) \
|
||||
{ \
|
||||
if (!detail::Is##NAME##Valid(aLhs.mValue, aRhs.mValue)) { \
|
||||
return CheckedInt<T>(0, false); \
|
||||
} \
|
||||
return CheckedInt<T>(aLhs.mValue OP aRhs.mValue, \
|
||||
aLhs.mIsValid && aRhs.mIsValid); \
|
||||
}
|
||||
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mod, %)
|
||||
|
||||
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
|
||||
|
||||
// Implement castToCheckedInt<T>(x), making sure that
|
||||
// - it allows x to be either a CheckedInt<T> or any integer type
|
||||
// that can be casted to T
|
||||
// - if x is already a CheckedInt<T>, we just return a reference to it,
|
||||
// instead of copying it (optimization)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, typename U>
|
||||
struct CastToCheckedIntImpl
|
||||
{
|
||||
typedef CheckedInt<T> ReturnType;
|
||||
static CheckedInt<T> run(U aU) { return aU; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct CastToCheckedIntImpl<T, CheckedInt<T> >
|
||||
{
|
||||
typedef const CheckedInt<T>& ReturnType;
|
||||
static const CheckedInt<T>& run(const CheckedInt<T>& aU) { return aU; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T, typename U>
|
||||
inline typename detail::CastToCheckedIntImpl<T, U>::ReturnType
|
||||
castToCheckedInt(U aU)
|
||||
{
|
||||
static_assert(detail::IsSupported<T>::value &&
|
||||
detail::IsSupported<U>::value,
|
||||
"This type is not supported by CheckedInt");
|
||||
return detail::CastToCheckedIntImpl<T, U>::run(aU);
|
||||
}
|
||||
|
||||
#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
|
||||
template<typename T> \
|
||||
template<typename U> \
|
||||
CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U aRhs) \
|
||||
{ \
|
||||
*this = *this OP castToCheckedInt<T>(aRhs); \
|
||||
return *this; \
|
||||
} \
|
||||
template<typename T> \
|
||||
CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(const CheckedInt<T>& aRhs) \
|
||||
{ \
|
||||
*this = *this OP aRhs; \
|
||||
return *this; \
|
||||
} \
|
||||
template<typename T, typename U> \
|
||||
inline CheckedInt<T> operator OP(const CheckedInt<T>& aLhs, U aRhs) \
|
||||
{ \
|
||||
return aLhs OP castToCheckedInt<T>(aRhs); \
|
||||
} \
|
||||
template<typename T, typename U> \
|
||||
inline CheckedInt<T> operator OP(U aLhs, const CheckedInt<T>& aRhs) \
|
||||
{ \
|
||||
return castToCheckedInt<T>(aLhs) OP aRhs; \
|
||||
}
|
||||
|
||||
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
|
||||
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
|
||||
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
|
||||
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
|
||||
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(%, %=)
|
||||
|
||||
#undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool
|
||||
operator ==(const CheckedInt<T>& aLhs, U aRhs)
|
||||
{
|
||||
return aLhs == castToCheckedInt<T>(aRhs);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool
|
||||
operator ==(U aLhs, const CheckedInt<T>& aRhs)
|
||||
{
|
||||
return castToCheckedInt<T>(aLhs) == aRhs;
|
||||
}
|
||||
|
||||
// Convenience typedefs.
|
||||
typedef CheckedInt<int8_t> CheckedInt8;
|
||||
typedef CheckedInt<uint8_t> CheckedUint8;
|
||||
typedef CheckedInt<int16_t> CheckedInt16;
|
||||
typedef CheckedInt<uint16_t> CheckedUint16;
|
||||
typedef CheckedInt<int32_t> CheckedInt32;
|
||||
typedef CheckedInt<uint32_t> CheckedUint32;
|
||||
typedef CheckedInt<int64_t> CheckedInt64;
|
||||
typedef CheckedInt<uint64_t> CheckedUint64;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_CheckedInt_h */
|
||||
113
cocos2d-x/external/win32/include/spidermonkey/mozilla/Compiler.h
vendored
Executable file
113
cocos2d-x/external/win32/include/spidermonkey/mozilla/Compiler.h
vendored
Executable file
@@ -0,0 +1,113 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Various compiler checks. */
|
||||
|
||||
#ifndef mozilla_Compiler_h
|
||||
#define mozilla_Compiler_h
|
||||
|
||||
#define MOZ_IS_GCC 0
|
||||
#define MOZ_IS_MSVC 0
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__)
|
||||
|
||||
# undef MOZ_IS_GCC
|
||||
# define MOZ_IS_GCC 1
|
||||
/*
|
||||
* These macros should simplify gcc version checking. For example, to check
|
||||
* for gcc 4.7.1 or later, check `#if MOZ_GCC_VERSION_AT_LEAST(4, 7, 1)`.
|
||||
*/
|
||||
# define MOZ_GCC_VERSION_AT_LEAST(major, minor, patchlevel) \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
|
||||
>= ((major) * 10000 + (minor) * 100 + (patchlevel)))
|
||||
# define MOZ_GCC_VERSION_AT_MOST(major, minor, patchlevel) \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
|
||||
<= ((major) * 10000 + (minor) * 100 + (patchlevel)))
|
||||
# if !MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
|
||||
# error "mfbt (and Gecko) require at least gcc 4.8 to build."
|
||||
# endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
# undef MOZ_IS_MSVC
|
||||
# define MOZ_IS_MSVC 1
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The situation with standard libraries is a lot worse than with compilers,
|
||||
* particularly as clang and gcc could end up using one of three or so standard
|
||||
* libraries, and they may not be up-to-snuff with newer C++11 versions. To
|
||||
* detect the library, we're going to include cstddef (which is a small header
|
||||
* which will be transitively included by everybody else at some point) to grab
|
||||
* the version macros and deduce macros from there.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# include <cstddef>
|
||||
# ifdef _STLPORT_MAJOR
|
||||
# define MOZ_USING_STLPORT 1
|
||||
# define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) \
|
||||
(_STLPORT_VERSION >= ((major) << 8 | (minor) << 4 | (patch)))
|
||||
# elif defined(_LIBCPP_VERSION)
|
||||
/*
|
||||
* libc++, unfortunately, doesn't appear to have useful versioning macros.
|
||||
* Hopefully, the recommendations of N3694 with respect to standard libraries
|
||||
* will get applied instead and we won't need to worry about version numbers
|
||||
* here.
|
||||
*/
|
||||
# define MOZ_USING_LIBCXX 1
|
||||
# elif defined(__GLIBCXX__)
|
||||
# define MOZ_USING_LIBSTDCXX 1
|
||||
/*
|
||||
* libstdc++ is also annoying and doesn't give us useful versioning macros
|
||||
* for the library. If we're using gcc, then assume that libstdc++ matches
|
||||
* the compiler version. If we're using clang, we're going to have to fake
|
||||
* major/minor combinations by looking for newly-defined config macros.
|
||||
*/
|
||||
# if MOZ_IS_GCC
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
MOZ_GCC_VERSION_AT_LEAST(major, minor, patch)
|
||||
# elif defined(_GLIBCXX_THROW_OR_ABORT)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 8))
|
||||
# elif defined(_GLIBCXX_NOEXCEPT)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 7))
|
||||
# elif defined(_GLIBCXX_USE_DEPRECATED)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 6))
|
||||
# elif defined(_GLIBCXX_PSEUDO_VISIBILITY)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 5))
|
||||
# elif defined(_GLIBCXX_BEGIN_EXTERN_C)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 4))
|
||||
# elif defined(_GLIBCXX_VISIBILITY_ATTR)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 3))
|
||||
# elif defined(_GLIBCXX_VISIBILITY)
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
|
||||
((major) < 4 || ((major) == 4 && (minor) <= 2))
|
||||
# else
|
||||
# error "Your version of libstdc++ is unknown to us and is likely too old."
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// Flesh out the defines for everyone else
|
||||
# ifndef MOZ_USING_STLPORT
|
||||
# define MOZ_USING_STLPORT 0
|
||||
# define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) 0
|
||||
# endif
|
||||
# ifndef MOZ_USING_LIBCXX
|
||||
# define MOZ_USING_LIBCXX 0
|
||||
# endif
|
||||
# ifndef MOZ_USING_LIBSTDCXX
|
||||
# define MOZ_USING_LIBSTDCXX 0
|
||||
# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) 0
|
||||
# endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_Compiler_h */
|
||||
119
cocos2d-x/external/win32/include/spidermonkey/mozilla/Compression.h
vendored
Executable file
119
cocos2d-x/external/win32/include/spidermonkey/mozilla/Compression.h
vendored
Executable file
@@ -0,0 +1,119 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Various simple compression/decompression functions. */
|
||||
|
||||
#ifndef mozilla_Compression_h_
|
||||
#define mozilla_Compression_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace Compression {
|
||||
|
||||
/**
|
||||
* LZ4 is a very fast byte-wise compression algorithm.
|
||||
*
|
||||
* Compared to Google's Snappy it is faster to compress and decompress and
|
||||
* generally produces output of about the same size.
|
||||
*
|
||||
* Compared to zlib it compresses at about 10x the speed, decompresses at about
|
||||
* 4x the speed and produces output of about 1.5x the size.
|
||||
*/
|
||||
|
||||
class LZ4
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Compresses |aInputSize| bytes from |aSource| into |aDest|. Destination
|
||||
* buffer must be already allocated, and must be sized to handle worst cases
|
||||
* situations (input data not compressible). Worst case size evaluation is
|
||||
* provided by function maxCompressedSize()
|
||||
*
|
||||
* @param aInputSize is the input size. Max supported value is ~1.9GB
|
||||
* @return the number of bytes written in buffer |aDest|
|
||||
*/
|
||||
static MFBT_API size_t
|
||||
compress(const char* aSource, size_t aInputSize, char* aDest);
|
||||
|
||||
/**
|
||||
* Compress |aInputSize| bytes from |aSource| into an output buffer
|
||||
* |aDest| of maximum size |aMaxOutputSize|. If it cannot achieve it,
|
||||
* compression will stop, and result of the function will be zero,
|
||||
* |aDest| will still be written to, but since the number of input
|
||||
* bytes consumed is not returned the result is not usable.
|
||||
*
|
||||
* This function never writes outside of provided output buffer.
|
||||
*
|
||||
* @param aInputSize is the input size. Max supported value is ~1.9GB
|
||||
* @param aMaxOutputSize is the size of the destination buffer (which must
|
||||
* be already allocated)
|
||||
* @return the number of bytes written in buffer |aDest| or 0 if the
|
||||
* compression fails
|
||||
*/
|
||||
static MFBT_API size_t
|
||||
compressLimitedOutput(const char* aSource, size_t aInputSize, char* aDest,
|
||||
size_t aMaxOutputSize);
|
||||
|
||||
/**
|
||||
* If the source stream is malformed, the function will stop decoding
|
||||
* and return false.
|
||||
*
|
||||
* This function never writes outside of provided buffers, and never
|
||||
* modifies input buffer.
|
||||
*
|
||||
* Note: destination buffer must be already allocated, and its size must be a
|
||||
* minimum of |aOutputSize| bytes.
|
||||
*
|
||||
* @param aOutputSize is the output size, therefore the original size
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
static MFBT_API MOZ_MUST_USE bool
|
||||
decompress(const char* aSource, char* aDest, size_t aOutputSize);
|
||||
|
||||
/**
|
||||
* If the source stream is malformed, the function will stop decoding
|
||||
* and return false.
|
||||
*
|
||||
* This function never writes beyond aDest + aMaxOutputSize, and is
|
||||
* therefore protected against malicious data packets.
|
||||
*
|
||||
* Note: Destination buffer must be already allocated. This version is
|
||||
* slightly slower than the decompress without the aMaxOutputSize.
|
||||
*
|
||||
* @param aInputSize is the length of the input compressed data
|
||||
* @param aMaxOutputSize is the size of the destination buffer (which must be
|
||||
* already allocated)
|
||||
* @param aOutputSize the actual number of bytes decoded in the destination
|
||||
* buffer (necessarily <= aMaxOutputSize)
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
static MFBT_API MOZ_MUST_USE bool
|
||||
decompress(const char* aSource, size_t aInputSize, char* aDest,
|
||||
size_t aMaxOutputSize, size_t* aOutputSize);
|
||||
|
||||
/*
|
||||
* Provides the maximum size that LZ4 may output in a "worst case"
|
||||
* scenario (input data not compressible) primarily useful for memory
|
||||
* allocation of output buffer.
|
||||
* note : this function is limited by "int" range (2^31-1)
|
||||
*
|
||||
* @param aInputSize is the input size. Max supported value is ~1.9GB
|
||||
* @return maximum output size in a "worst case" scenario
|
||||
*/
|
||||
static inline size_t maxCompressedSize(size_t aInputSize)
|
||||
{
|
||||
size_t max = (aInputSize + (aInputSize / 255) + 16);
|
||||
MOZ_ASSERT(max > aInputSize);
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace Compression */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_Compression_h_ */
|
||||
92
cocos2d-x/external/win32/include/spidermonkey/mozilla/DebugOnly.h
vendored
Executable file
92
cocos2d-x/external/win32/include/spidermonkey/mozilla/DebugOnly.h
vendored
Executable file
@@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Provides DebugOnly, a type for variables used only in debug builds (i.e. by
|
||||
* assertions).
|
||||
*/
|
||||
|
||||
#ifndef mozilla_DebugOnly_h
|
||||
#define mozilla_DebugOnly_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* DebugOnly contains a value of type T, but only in debug builds. In release
|
||||
* builds, it does not contain a value. This helper is intended to be used with
|
||||
* MOZ_ASSERT()-style macros, allowing one to write:
|
||||
*
|
||||
* DebugOnly<bool> check = func();
|
||||
* MOZ_ASSERT(check);
|
||||
*
|
||||
* more concisely than declaring |check| conditional on #ifdef DEBUG.
|
||||
*
|
||||
* DebugOnly instances can only be coerced to T in debug builds. In release
|
||||
* builds they don't have a value, so type coercion is not well defined.
|
||||
*
|
||||
* NOTE: DebugOnly instances still take up one byte of space, plus padding, even
|
||||
* in optimized, non-DEBUG builds (see bug 1253094 comment 37 for more info).
|
||||
* For this reason the class is MOZ_STACK_CLASS to prevent consumers using
|
||||
* DebugOnly for struct/class members and unwittingly inflating the size of
|
||||
* their objects in release builds.
|
||||
*/
|
||||
template<typename T>
|
||||
class MOZ_STACK_CLASS DebugOnly
|
||||
{
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
T value;
|
||||
|
||||
DebugOnly() { }
|
||||
MOZ_IMPLICIT DebugOnly(const T& aOther) : value(aOther) { }
|
||||
DebugOnly(const DebugOnly& aOther) : value(aOther.value) { }
|
||||
DebugOnly& operator=(const T& aRhs) {
|
||||
value = aRhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator++(int) { value++; }
|
||||
void operator--(int) { value--; }
|
||||
|
||||
// Do not define operator+=(), etc. here. These will coerce via the
|
||||
// implicit cast and built-in operators. Defining explicit methods here
|
||||
// will create ambiguity the compiler can't deal with.
|
||||
|
||||
T* operator&() { return &value; }
|
||||
|
||||
operator T&() { return value; }
|
||||
operator const T&() const { return value; }
|
||||
|
||||
T& operator->() { return value; }
|
||||
const T& operator->() const { return value; }
|
||||
|
||||
#else
|
||||
DebugOnly() { }
|
||||
MOZ_IMPLICIT DebugOnly(const T&) { }
|
||||
DebugOnly(const DebugOnly&) { }
|
||||
DebugOnly& operator=(const T&) { return *this; }
|
||||
void operator++(int) { }
|
||||
void operator--(int) { }
|
||||
DebugOnly& operator+=(const T&) { return *this; }
|
||||
DebugOnly& operator-=(const T&) { return *this; }
|
||||
DebugOnly& operator&=(const T&) { return *this; }
|
||||
DebugOnly& operator|=(const T&) { return *this; }
|
||||
DebugOnly& operator^=(const T&) { return *this; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DebugOnly must always have a destructor or else it will
|
||||
* generate "unused variable" warnings, exactly what it's intended
|
||||
* to avoid!
|
||||
*/
|
||||
~DebugOnly() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_DebugOnly_h */
|
||||
221
cocos2d-x/external/win32/include/spidermonkey/mozilla/Decimal.h
vendored
Executable file
221
cocos2d-x/external/win32/include/spidermonkey/mozilla/Decimal.h
vendored
Executable file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Google Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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 COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Imported from:
|
||||
* https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/platform/Decimal.h
|
||||
* Check UPSTREAM-GIT-SHA for the commit ID of the last update from Blink core.
|
||||
*/
|
||||
|
||||
#ifndef Decimal_h
|
||||
#define Decimal_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include <stdint.h>
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef ASSERT
|
||||
#define DEFINED_ASSERT_FOR_DECIMAL_H 1
|
||||
#define ASSERT MOZ_ASSERT
|
||||
#endif
|
||||
|
||||
#define PLATFORM_EXPORT
|
||||
|
||||
// To use USING_FAST_MALLOC we'd need:
|
||||
// https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/wtf/Allocator.h
|
||||
// Since we don't allocate Decimal objects, no need.
|
||||
#define USING_FAST_MALLOC(type) \
|
||||
void ignore_this_dummy_method() = delete
|
||||
|
||||
#define DISALLOW_NEW() \
|
||||
private: \
|
||||
void* operator new(size_t) = delete; \
|
||||
void* operator new(size_t, void*) = delete; \
|
||||
public:
|
||||
|
||||
namespace blink {
|
||||
|
||||
namespace DecimalPrivate {
|
||||
class SpecialValueHandler;
|
||||
}
|
||||
|
||||
// This class represents decimal base floating point number.
|
||||
//
|
||||
// FIXME: Once all C++ compiler support decimal type, we should replace this
|
||||
// class to compiler supported one. See below URI for current status of decimal
|
||||
// type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
|
||||
class PLATFORM_EXPORT Decimal {
|
||||
USING_FAST_MALLOC(Decimal);
|
||||
public:
|
||||
enum Sign {
|
||||
Positive,
|
||||
Negative,
|
||||
};
|
||||
|
||||
// You should not use EncodedData other than unit testing.
|
||||
class EncodedData {
|
||||
DISALLOW_NEW();
|
||||
// For accessing FormatClass.
|
||||
friend class Decimal;
|
||||
friend class DecimalPrivate::SpecialValueHandler;
|
||||
public:
|
||||
EncodedData(Sign, int exponent, uint64_t coefficient);
|
||||
|
||||
bool operator==(const EncodedData&) const;
|
||||
bool operator!=(const EncodedData& another) const { return !operator==(another); }
|
||||
|
||||
uint64_t coefficient() const { return m_coefficient; }
|
||||
int countDigits() const;
|
||||
int exponent() const { return m_exponent; }
|
||||
bool isFinite() const { return !isSpecial(); }
|
||||
bool isInfinity() const { return m_formatClass == ClassInfinity; }
|
||||
bool isNaN() const { return m_formatClass == ClassNaN; }
|
||||
bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
|
||||
bool isZero() const { return m_formatClass == ClassZero; }
|
||||
Sign sign() const { return m_sign; }
|
||||
void setSign(Sign sign) { m_sign = sign; }
|
||||
|
||||
private:
|
||||
enum FormatClass {
|
||||
ClassInfinity,
|
||||
ClassNormal,
|
||||
ClassNaN,
|
||||
ClassZero,
|
||||
};
|
||||
|
||||
EncodedData(Sign, FormatClass);
|
||||
FormatClass formatClass() const { return m_formatClass; }
|
||||
|
||||
uint64_t m_coefficient;
|
||||
int16_t m_exponent;
|
||||
FormatClass m_formatClass;
|
||||
Sign m_sign;
|
||||
};
|
||||
|
||||
MFBT_API explicit Decimal(int32_t = 0);
|
||||
MFBT_API Decimal(Sign, int exponent, uint64_t coefficient);
|
||||
MFBT_API Decimal(const Decimal&);
|
||||
|
||||
MFBT_API Decimal& operator=(const Decimal&);
|
||||
MFBT_API Decimal& operator+=(const Decimal&);
|
||||
MFBT_API Decimal& operator-=(const Decimal&);
|
||||
MFBT_API Decimal& operator*=(const Decimal&);
|
||||
MFBT_API Decimal& operator/=(const Decimal&);
|
||||
|
||||
MFBT_API Decimal operator-() const;
|
||||
|
||||
MFBT_API bool operator==(const Decimal&) const;
|
||||
MFBT_API bool operator!=(const Decimal&) const;
|
||||
MFBT_API bool operator<(const Decimal&) const;
|
||||
MFBT_API bool operator<=(const Decimal&) const;
|
||||
MFBT_API bool operator>(const Decimal&) const;
|
||||
MFBT_API bool operator>=(const Decimal&) const;
|
||||
|
||||
MFBT_API Decimal operator+(const Decimal&) const;
|
||||
MFBT_API Decimal operator-(const Decimal&) const;
|
||||
MFBT_API Decimal operator*(const Decimal&) const;
|
||||
MFBT_API Decimal operator/(const Decimal&) const;
|
||||
|
||||
int exponent() const
|
||||
{
|
||||
ASSERT(isFinite());
|
||||
return m_data.exponent();
|
||||
}
|
||||
|
||||
bool isFinite() const { return m_data.isFinite(); }
|
||||
bool isInfinity() const { return m_data.isInfinity(); }
|
||||
bool isNaN() const { return m_data.isNaN(); }
|
||||
bool isNegative() const { return sign() == Negative; }
|
||||
bool isPositive() const { return sign() == Positive; }
|
||||
bool isSpecial() const { return m_data.isSpecial(); }
|
||||
bool isZero() const { return m_data.isZero(); }
|
||||
|
||||
MFBT_API Decimal abs() const;
|
||||
MFBT_API Decimal ceil() const;
|
||||
MFBT_API Decimal floor() const;
|
||||
MFBT_API Decimal remainder(const Decimal&) const;
|
||||
MFBT_API Decimal round() const;
|
||||
|
||||
MFBT_API double toDouble() const;
|
||||
// Note: toString method supports infinity and nan but fromString not.
|
||||
MFBT_API std::string toString() const;
|
||||
MFBT_API bool toString(char* strBuf, size_t bufLength) const;
|
||||
|
||||
static MFBT_API Decimal fromDouble(double);
|
||||
// fromString supports following syntax EBNF:
|
||||
// number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
|
||||
// | sign? '.' digit+ (exponent-marker sign? digit+)?
|
||||
// sign ::= '+' | '-'
|
||||
// exponent-marker ::= 'e' | 'E'
|
||||
// digit ::= '0' | '1' | ... | '9'
|
||||
// Note: fromString doesn't support "infinity" and "nan".
|
||||
static MFBT_API Decimal fromString(const std::string& aValue);
|
||||
static MFBT_API Decimal infinity(Sign);
|
||||
static MFBT_API Decimal nan();
|
||||
static MFBT_API Decimal zero(Sign);
|
||||
|
||||
// You should not use below methods. We expose them for unit testing.
|
||||
MFBT_API explicit Decimal(const EncodedData&);
|
||||
const EncodedData& value() const { return m_data; }
|
||||
|
||||
private:
|
||||
struct AlignedOperands {
|
||||
uint64_t lhsCoefficient;
|
||||
uint64_t rhsCoefficient;
|
||||
int exponent;
|
||||
};
|
||||
|
||||
MFBT_API explicit Decimal(double);
|
||||
MFBT_API Decimal compareTo(const Decimal&) const;
|
||||
|
||||
static MFBT_API AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs);
|
||||
static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; }
|
||||
|
||||
Sign sign() const { return m_data.sign(); }
|
||||
|
||||
EncodedData m_data;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
namespace mozilla {
|
||||
typedef blink::Decimal Decimal;
|
||||
} // namespace mozilla
|
||||
|
||||
#undef USING_FAST_MALLOC
|
||||
|
||||
#ifdef DEFINED_ASSERT_FOR_DECIMAL_H
|
||||
#undef DEFINED_ASSERT_FOR_DECIMAL_H
|
||||
#undef ASSERT
|
||||
#endif
|
||||
|
||||
#endif // Decimal_h
|
||||
695
cocos2d-x/external/win32/include/spidermonkey/mozilla/EndianUtils.h
vendored
Executable file
695
cocos2d-x/external/win32/include/spidermonkey/mozilla/EndianUtils.h
vendored
Executable file
@@ -0,0 +1,695 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Functions for reading and writing integers in various endiannesses. */
|
||||
|
||||
/*
|
||||
* The classes LittleEndian and BigEndian expose static methods for
|
||||
* reading and writing 16-, 32-, and 64-bit signed and unsigned integers
|
||||
* in their respective endianness. The naming scheme is:
|
||||
*
|
||||
* {Little,Big}Endian::{read,write}{Uint,Int}<bitsize>
|
||||
*
|
||||
* For instance, LittleEndian::readInt32 will read a 32-bit signed
|
||||
* integer from memory in little endian format. Similarly,
|
||||
* BigEndian::writeUint16 will write a 16-bit unsigned integer to memory
|
||||
* in big-endian format.
|
||||
*
|
||||
* The class NativeEndian exposes methods for conversion of existing
|
||||
* data to and from the native endianness. These methods are intended
|
||||
* for cases where data needs to be transferred, serialized, etc.
|
||||
* swap{To,From}{Little,Big}Endian byteswap a single value if necessary.
|
||||
* Bulk conversion functions are also provided which optimize the
|
||||
* no-conversion-needed case:
|
||||
*
|
||||
* - copyAndSwap{To,From}{Little,Big}Endian;
|
||||
* - swap{To,From}{Little,Big}EndianInPlace.
|
||||
*
|
||||
* The *From* variants are intended to be used for reading data and the
|
||||
* *To* variants for writing data.
|
||||
*
|
||||
* Methods on NativeEndian work with integer data of any type.
|
||||
* Floating-point data is not supported.
|
||||
*
|
||||
* For clarity in networking code, "Network" may be used as a synonym
|
||||
* for "Big" in any of the above methods or class names.
|
||||
*
|
||||
* As an example, reading a file format header whose fields are stored
|
||||
* in big-endian format might look like:
|
||||
*
|
||||
* class ExampleHeader
|
||||
* {
|
||||
* private:
|
||||
* uint32_t mMagic;
|
||||
* uint32_t mLength;
|
||||
* uint32_t mTotalRecords;
|
||||
* uint64_t mChecksum;
|
||||
*
|
||||
* public:
|
||||
* ExampleHeader(const void* data)
|
||||
* {
|
||||
* const uint8_t* ptr = static_cast<const uint8_t*>(data);
|
||||
* mMagic = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
|
||||
* mLength = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
|
||||
* mTotalRecords = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
|
||||
* mChecksum = BigEndian::readUint64(ptr);
|
||||
* }
|
||||
* ...
|
||||
* };
|
||||
*/
|
||||
|
||||
#ifndef mozilla_EndianUtils_h
|
||||
#define mozilla_EndianUtils_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <stdlib.h>
|
||||
# pragma intrinsic(_byteswap_ushort)
|
||||
# pragma intrinsic(_byteswap_ulong)
|
||||
# pragma intrinsic(_byteswap_uint64)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
# else
|
||||
# error "CPU type is unknown"
|
||||
# endif
|
||||
#elif defined(_WIN32)
|
||||
# if defined(_M_IX86)
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
# elif defined(_M_ARM)
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
# else
|
||||
# error "CPU type is unknown"
|
||||
# endif
|
||||
#elif defined(__APPLE__) || defined(__powerpc__) || defined(__ppc__)
|
||||
# if __LITTLE_ENDIAN__
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
# elif __BIG_ENDIAN__
|
||||
# define MOZ_BIG_ENDIAN 1
|
||||
# endif
|
||||
#elif defined(__GNUC__) && \
|
||||
defined(__BYTE_ORDER__) && \
|
||||
defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||
defined(__ORDER_BIG_ENDIAN__)
|
||||
/*
|
||||
* Some versions of GCC provide architecture-independent macros for
|
||||
* this. Yes, there are more than two values for __BYTE_ORDER__.
|
||||
*/
|
||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define MOZ_BIG_ENDIAN 1
|
||||
# else
|
||||
# error "Can't handle mixed-endian architectures"
|
||||
# endif
|
||||
/*
|
||||
* We can't include useful headers like <endian.h> or <sys/isa_defs.h>
|
||||
* here because they're not present on all platforms. Instead we have
|
||||
* this big conditional that ideally will catch all the interesting
|
||||
* cases.
|
||||
*/
|
||||
#elif defined(__sparc) || defined(__sparc__) || \
|
||||
defined(_POWER) || defined(__hppa) || \
|
||||
defined(_MIPSEB) || defined(__ARMEB__) || \
|
||||
defined(__s390__) || defined(__AARCH64EB__) || \
|
||||
(defined(__sh__) && defined(__LITTLE_ENDIAN__)) || \
|
||||
(defined(__ia64) && defined(__BIG_ENDIAN__))
|
||||
# define MOZ_BIG_ENDIAN 1
|
||||
#elif defined(__i386) || defined(__i386__) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_MIPSEL) || defined(__ARMEL__) || \
|
||||
defined(__alpha__) || defined(__AARCH64EL__) || \
|
||||
(defined(__sh__) && defined(__BIG_ENDIAN__)) || \
|
||||
(defined(__ia64) && !defined(__BIG_ENDIAN__))
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#if MOZ_BIG_ENDIAN
|
||||
# define MOZ_LITTLE_ENDIAN 0
|
||||
#elif MOZ_LITTLE_ENDIAN
|
||||
# define MOZ_BIG_ENDIAN 0
|
||||
#else
|
||||
# error "Cannot determine endianness"
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# if __has_builtin(__builtin_bswap16)
|
||||
# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_HAVE_BUILTIN_BYTESWAP16 _byteswap_ushort
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* We need wrappers here because free functions with default template
|
||||
* arguments and/or partial specialization of function templates are not
|
||||
* supported by all the compilers we use.
|
||||
*/
|
||||
template<typename T, size_t Size = sizeof(T)>
|
||||
struct Swapper;
|
||||
|
||||
template<typename T>
|
||||
struct Swapper<T, 2>
|
||||
{
|
||||
static T swap(T aValue)
|
||||
{
|
||||
#if defined(MOZ_HAVE_BUILTIN_BYTESWAP16)
|
||||
return MOZ_HAVE_BUILTIN_BYTESWAP16(aValue);
|
||||
#else
|
||||
return T(((aValue & 0x00ff) << 8) | ((aValue & 0xff00) >> 8));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Swapper<T, 4>
|
||||
{
|
||||
static T swap(T aValue)
|
||||
{
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
return T(__builtin_bswap32(aValue));
|
||||
#elif defined(_MSC_VER)
|
||||
return T(_byteswap_ulong(aValue));
|
||||
#else
|
||||
return T(((aValue & 0x000000ffU) << 24) |
|
||||
((aValue & 0x0000ff00U) << 8) |
|
||||
((aValue & 0x00ff0000U) >> 8) |
|
||||
((aValue & 0xff000000U) >> 24));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Swapper<T, 8>
|
||||
{
|
||||
static inline T swap(T aValue)
|
||||
{
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
return T(__builtin_bswap64(aValue));
|
||||
#elif defined(_MSC_VER)
|
||||
return T(_byteswap_uint64(aValue));
|
||||
#else
|
||||
return T(((aValue & 0x00000000000000ffULL) << 56) |
|
||||
((aValue & 0x000000000000ff00ULL) << 40) |
|
||||
((aValue & 0x0000000000ff0000ULL) << 24) |
|
||||
((aValue & 0x00000000ff000000ULL) << 8) |
|
||||
((aValue & 0x000000ff00000000ULL) >> 8) |
|
||||
((aValue & 0x0000ff0000000000ULL) >> 24) |
|
||||
((aValue & 0x00ff000000000000ULL) >> 40) |
|
||||
((aValue & 0xff00000000000000ULL) >> 56));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
enum Endianness { Little, Big };
|
||||
|
||||
#if MOZ_BIG_ENDIAN
|
||||
# define MOZ_NATIVE_ENDIANNESS detail::Big
|
||||
#else
|
||||
# define MOZ_NATIVE_ENDIANNESS detail::Little
|
||||
#endif
|
||||
|
||||
class EndianUtils
|
||||
{
|
||||
/**
|
||||
* Assert that the memory regions [aDest, aDest+aCount) and
|
||||
* [aSrc, aSrc+aCount] do not overlap. aCount is given in bytes.
|
||||
*/
|
||||
static void assertNoOverlap(const void* aDest, const void* aSrc,
|
||||
size_t aCount)
|
||||
{
|
||||
DebugOnly<const uint8_t*> byteDestPtr = static_cast<const uint8_t*>(aDest);
|
||||
DebugOnly<const uint8_t*> byteSrcPtr = static_cast<const uint8_t*>(aSrc);
|
||||
MOZ_ASSERT((byteDestPtr <= byteSrcPtr &&
|
||||
byteDestPtr + aCount <= byteSrcPtr) ||
|
||||
(byteSrcPtr <= byteDestPtr &&
|
||||
byteSrcPtr + aCount <= byteDestPtr));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void assertAligned(T* aPtr)
|
||||
{
|
||||
MOZ_ASSERT((uintptr_t(aPtr) % sizeof(T)) == 0, "Unaligned pointer!");
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Return |aValue| converted from SourceEndian encoding to DestEndian
|
||||
* encoding.
|
||||
*/
|
||||
template<Endianness SourceEndian, Endianness DestEndian, typename T>
|
||||
static inline T maybeSwap(T aValue)
|
||||
{
|
||||
if (SourceEndian == DestEndian) {
|
||||
return aValue;
|
||||
}
|
||||
return Swapper<T>::swap(aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert |aCount| elements at |aPtr| from SourceEndian encoding to
|
||||
* DestEndian encoding.
|
||||
*/
|
||||
template<Endianness SourceEndian, Endianness DestEndian, typename T>
|
||||
static inline void maybeSwapInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
assertAligned(aPtr);
|
||||
|
||||
if (SourceEndian == DestEndian) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < aCount; i++) {
|
||||
aPtr[i] = Swapper<T>::swap(aPtr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write |aCount| elements to the unaligned address |aDest| in DestEndian
|
||||
* format, using elements found at |aSrc| in SourceEndian format.
|
||||
*/
|
||||
template<Endianness SourceEndian, Endianness DestEndian, typename T>
|
||||
static void copyAndSwapTo(void* aDest, const T* aSrc, size_t aCount)
|
||||
{
|
||||
assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
|
||||
assertAligned(aSrc);
|
||||
|
||||
if (SourceEndian == DestEndian) {
|
||||
memcpy(aDest, aSrc, aCount * sizeof(T));
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* byteDestPtr = static_cast<uint8_t*>(aDest);
|
||||
for (size_t i = 0; i < aCount; ++i) {
|
||||
union
|
||||
{
|
||||
T mVal;
|
||||
uint8_t mBuffer[sizeof(T)];
|
||||
} u;
|
||||
u.mVal = maybeSwap<SourceEndian, DestEndian>(aSrc[i]);
|
||||
memcpy(byteDestPtr, u.mBuffer, sizeof(T));
|
||||
byteDestPtr += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write |aCount| elements to |aDest| in DestEndian format, using elements
|
||||
* found at the unaligned address |aSrc| in SourceEndian format.
|
||||
*/
|
||||
template<Endianness SourceEndian, Endianness DestEndian, typename T>
|
||||
static void copyAndSwapFrom(T* aDest, const void* aSrc, size_t aCount)
|
||||
{
|
||||
assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
|
||||
assertAligned(aDest);
|
||||
|
||||
if (SourceEndian == DestEndian) {
|
||||
memcpy(aDest, aSrc, aCount * sizeof(T));
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* byteSrcPtr = static_cast<const uint8_t*>(aSrc);
|
||||
for (size_t i = 0; i < aCount; ++i) {
|
||||
union
|
||||
{
|
||||
T mVal;
|
||||
uint8_t mBuffer[sizeof(T)];
|
||||
} u;
|
||||
memcpy(u.mBuffer, byteSrcPtr, sizeof(T));
|
||||
aDest[i] = maybeSwap<SourceEndian, DestEndian>(u.mVal);
|
||||
byteSrcPtr += sizeof(T);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<Endianness ThisEndian>
|
||||
class Endian : private EndianUtils
|
||||
{
|
||||
protected:
|
||||
/** Read a uint16_t in ThisEndian endianness from |aPtr| and return it. */
|
||||
static MOZ_MUST_USE uint16_t readUint16(const void* aPtr)
|
||||
{
|
||||
return read<uint16_t>(aPtr);
|
||||
}
|
||||
|
||||
/** Read a uint32_t in ThisEndian endianness from |aPtr| and return it. */
|
||||
static MOZ_MUST_USE uint32_t readUint32(const void* aPtr)
|
||||
{
|
||||
return read<uint32_t>(aPtr);
|
||||
}
|
||||
|
||||
/** Read a uint64_t in ThisEndian endianness from |aPtr| and return it. */
|
||||
static MOZ_MUST_USE uint64_t readUint64(const void* aPtr)
|
||||
{
|
||||
return read<uint64_t>(aPtr);
|
||||
}
|
||||
|
||||
/** Read an int16_t in ThisEndian endianness from |aPtr| and return it. */
|
||||
static MOZ_MUST_USE int16_t readInt16(const void* aPtr)
|
||||
{
|
||||
return read<int16_t>(aPtr);
|
||||
}
|
||||
|
||||
/** Read an int32_t in ThisEndian endianness from |aPtr| and return it. */
|
||||
static MOZ_MUST_USE int32_t readInt32(const void* aPtr)
|
||||
{
|
||||
return read<uint32_t>(aPtr);
|
||||
}
|
||||
|
||||
/** Read an int64_t in ThisEndian endianness from |aPtr| and return it. */
|
||||
static MOZ_MUST_USE int64_t readInt64(const void* aPtr)
|
||||
{
|
||||
return read<int64_t>(aPtr);
|
||||
}
|
||||
|
||||
/** Write |aValue| to |aPtr| using ThisEndian endianness. */
|
||||
static void writeUint16(void* aPtr, uint16_t aValue)
|
||||
{
|
||||
write(aPtr, aValue);
|
||||
}
|
||||
|
||||
/** Write |aValue| to |aPtr| using ThisEndian endianness. */
|
||||
static void writeUint32(void* aPtr, uint32_t aValue)
|
||||
{
|
||||
write(aPtr, aValue);
|
||||
}
|
||||
|
||||
/** Write |aValue| to |aPtr| using ThisEndian endianness. */
|
||||
static void writeUint64(void* aPtr, uint64_t aValue)
|
||||
{
|
||||
write(aPtr, aValue);
|
||||
}
|
||||
|
||||
/** Write |aValue| to |aPtr| using ThisEndian endianness. */
|
||||
static void writeInt16(void* aPtr, int16_t aValue)
|
||||
{
|
||||
write(aPtr, aValue);
|
||||
}
|
||||
|
||||
/** Write |aValue| to |aPtr| using ThisEndian endianness. */
|
||||
static void writeInt32(void* aPtr, int32_t aValue)
|
||||
{
|
||||
write(aPtr, aValue);
|
||||
}
|
||||
|
||||
/** Write |aValue| to |aPtr| using ThisEndian endianness. */
|
||||
static void writeInt64(void* aPtr, int64_t aValue)
|
||||
{
|
||||
write(aPtr, aValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a value of type T to little-endian format.
|
||||
*
|
||||
* This function is intended for cases where you have data in your
|
||||
* native-endian format and you need it to appear in little-endian
|
||||
* format for transmission.
|
||||
*/
|
||||
template<typename T>
|
||||
MOZ_MUST_USE static T swapToLittleEndian(T aValue)
|
||||
{
|
||||
return maybeSwap<ThisEndian, Little>(aValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||
* them to little-endian format if ThisEndian is Big.
|
||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||
*/
|
||||
template<typename T>
|
||||
static void copyAndSwapToLittleEndian(void* aDest, const T* aSrc,
|
||||
size_t aCount)
|
||||
{
|
||||
copyAndSwapTo<ThisEndian, Little>(aDest, aSrc, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise, but converts values in place.
|
||||
*/
|
||||
template<typename T>
|
||||
static void swapToLittleEndianInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
maybeSwapInPlace<ThisEndian, Little>(aPtr, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a value of type T to big-endian format.
|
||||
*/
|
||||
template<typename T>
|
||||
MOZ_MUST_USE static T swapToBigEndian(T aValue)
|
||||
{
|
||||
return maybeSwap<ThisEndian, Big>(aValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||
* them to big-endian format if ThisEndian is Little.
|
||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||
*/
|
||||
template<typename T>
|
||||
static void copyAndSwapToBigEndian(void* aDest, const T* aSrc,
|
||||
size_t aCount)
|
||||
{
|
||||
copyAndSwapTo<ThisEndian, Big>(aDest, aSrc, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise, but converts values in place.
|
||||
*/
|
||||
template<typename T>
|
||||
static void swapToBigEndianInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
maybeSwapInPlace<ThisEndian, Big>(aPtr, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Synonyms for the big-endian functions, for better readability
|
||||
* in network code.
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
MOZ_MUST_USE static T swapToNetworkOrder(T aValue)
|
||||
{
|
||||
return swapToBigEndian(aValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
copyAndSwapToNetworkOrder(void* aDest, const T* aSrc, size_t aCount)
|
||||
{
|
||||
copyAndSwapToBigEndian(aDest, aSrc, aCount);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
swapToNetworkOrderInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
swapToBigEndianInPlace(aPtr, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a value of type T from little-endian format.
|
||||
*/
|
||||
template<typename T>
|
||||
MOZ_MUST_USE static T swapFromLittleEndian(T aValue)
|
||||
{
|
||||
return maybeSwap<Little, ThisEndian>(aValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||
* them to little-endian format if ThisEndian is Big.
|
||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||
*/
|
||||
template<typename T>
|
||||
static void copyAndSwapFromLittleEndian(T* aDest, const void* aSrc,
|
||||
size_t aCount)
|
||||
{
|
||||
copyAndSwapFrom<Little, ThisEndian>(aDest, aSrc, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise, but converts values in place.
|
||||
*/
|
||||
template<typename T>
|
||||
static void swapFromLittleEndianInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
maybeSwapInPlace<Little, ThisEndian>(aPtr, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a value of type T from big-endian format.
|
||||
*/
|
||||
template<typename T>
|
||||
MOZ_MUST_USE static T swapFromBigEndian(T aValue)
|
||||
{
|
||||
return maybeSwap<Big, ThisEndian>(aValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||
* them to big-endian format if ThisEndian is Little.
|
||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||
*/
|
||||
template<typename T>
|
||||
static void copyAndSwapFromBigEndian(T* aDest, const void* aSrc,
|
||||
size_t aCount)
|
||||
{
|
||||
copyAndSwapFrom<Big, ThisEndian>(aDest, aSrc, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise, but converts values in place.
|
||||
*/
|
||||
template<typename T>
|
||||
static void swapFromBigEndianInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
maybeSwapInPlace<Big, ThisEndian>(aPtr, aCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Synonyms for the big-endian functions, for better readability
|
||||
* in network code.
|
||||
*/
|
||||
template<typename T>
|
||||
MOZ_MUST_USE static T swapFromNetworkOrder(T aValue)
|
||||
{
|
||||
return swapFromBigEndian(aValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void copyAndSwapFromNetworkOrder(T* aDest, const void* aSrc,
|
||||
size_t aCount)
|
||||
{
|
||||
copyAndSwapFromBigEndian(aDest, aSrc, aCount);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void swapFromNetworkOrderInPlace(T* aPtr, size_t aCount)
|
||||
{
|
||||
swapFromBigEndianInPlace(aPtr, aCount);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Read a value of type T, encoded in endianness ThisEndian from |aPtr|.
|
||||
* Return that value encoded in native endianness.
|
||||
*/
|
||||
template<typename T>
|
||||
static T read(const void* aPtr)
|
||||
{
|
||||
union
|
||||
{
|
||||
T mVal;
|
||||
uint8_t mBuffer[sizeof(T)];
|
||||
} u;
|
||||
memcpy(u.mBuffer, aPtr, sizeof(T));
|
||||
return maybeSwap<ThisEndian, MOZ_NATIVE_ENDIANNESS>(u.mVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value of type T, in native endianness, to |aPtr|, in ThisEndian
|
||||
* endianness.
|
||||
*/
|
||||
template<typename T>
|
||||
static void write(void* aPtr, T aValue)
|
||||
{
|
||||
T tmp = maybeSwap<MOZ_NATIVE_ENDIANNESS, ThisEndian>(aValue);
|
||||
memcpy(aPtr, &tmp, sizeof(T));
|
||||
}
|
||||
|
||||
Endian() = delete;
|
||||
Endian(const Endian& aTther) = delete;
|
||||
void operator=(const Endian& aOther) = delete;
|
||||
};
|
||||
|
||||
template<Endianness ThisEndian>
|
||||
class EndianReadWrite : public Endian<ThisEndian>
|
||||
{
|
||||
private:
|
||||
typedef Endian<ThisEndian> super;
|
||||
|
||||
public:
|
||||
using super::readUint16;
|
||||
using super::readUint32;
|
||||
using super::readUint64;
|
||||
using super::readInt16;
|
||||
using super::readInt32;
|
||||
using super::readInt64;
|
||||
using super::writeUint16;
|
||||
using super::writeUint32;
|
||||
using super::writeUint64;
|
||||
using super::writeInt16;
|
||||
using super::writeInt32;
|
||||
using super::writeInt64;
|
||||
};
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
class LittleEndian final : public detail::EndianReadWrite<detail::Little>
|
||||
{};
|
||||
|
||||
class BigEndian final : public detail::EndianReadWrite<detail::Big>
|
||||
{};
|
||||
|
||||
typedef BigEndian NetworkEndian;
|
||||
|
||||
class NativeEndian final : public detail::Endian<MOZ_NATIVE_ENDIANNESS>
|
||||
{
|
||||
private:
|
||||
typedef detail::Endian<MOZ_NATIVE_ENDIANNESS> super;
|
||||
|
||||
public:
|
||||
/*
|
||||
* These functions are intended for cases where you have data in your
|
||||
* native-endian format and you need the data to appear in the appropriate
|
||||
* endianness for transmission, serialization, etc.
|
||||
*/
|
||||
using super::swapToLittleEndian;
|
||||
using super::copyAndSwapToLittleEndian;
|
||||
using super::swapToLittleEndianInPlace;
|
||||
using super::swapToBigEndian;
|
||||
using super::copyAndSwapToBigEndian;
|
||||
using super::swapToBigEndianInPlace;
|
||||
using super::swapToNetworkOrder;
|
||||
using super::copyAndSwapToNetworkOrder;
|
||||
using super::swapToNetworkOrderInPlace;
|
||||
|
||||
/*
|
||||
* These functions are intended for cases where you have data in the
|
||||
* given endianness (e.g. reading from disk or a file-format) and you
|
||||
* need the data to appear in native-endian format for processing.
|
||||
*/
|
||||
using super::swapFromLittleEndian;
|
||||
using super::copyAndSwapFromLittleEndian;
|
||||
using super::swapFromLittleEndianInPlace;
|
||||
using super::swapFromBigEndian;
|
||||
using super::copyAndSwapFromBigEndian;
|
||||
using super::swapFromBigEndianInPlace;
|
||||
using super::swapFromNetworkOrder;
|
||||
using super::copyAndSwapFromNetworkOrder;
|
||||
using super::swapFromNetworkOrderInPlace;
|
||||
};
|
||||
|
||||
#undef MOZ_NATIVE_ENDIANNESS
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_EndianUtils_h */
|
||||
344
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumSet.h
vendored
Executable file
344
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumSet.h
vendored
Executable file
@@ -0,0 +1,344 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A set abstraction for enumeration values. */
|
||||
|
||||
#ifndef mozilla_EnumSet_h
|
||||
#define mozilla_EnumSet_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* EnumSet<T> is a set of values defined by an enumeration. It is implemented
|
||||
* using a 32 bit mask for each value so it will only work for enums with an int
|
||||
* representation less than 32. It works both for enum and enum class types.
|
||||
*/
|
||||
template<typename T>
|
||||
class EnumSet
|
||||
{
|
||||
public:
|
||||
EnumSet()
|
||||
: mBitField(0)
|
||||
{
|
||||
initVersion();
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT EnumSet(T aEnum)
|
||||
: mBitField(bitFor(aEnum))
|
||||
{ }
|
||||
|
||||
EnumSet(T aEnum1, T aEnum2)
|
||||
: mBitField(bitFor(aEnum1) |
|
||||
bitFor(aEnum2))
|
||||
{
|
||||
initVersion();
|
||||
}
|
||||
|
||||
EnumSet(T aEnum1, T aEnum2, T aEnum3)
|
||||
: mBitField(bitFor(aEnum1) |
|
||||
bitFor(aEnum2) |
|
||||
bitFor(aEnum3))
|
||||
{
|
||||
initVersion();
|
||||
}
|
||||
|
||||
EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4)
|
||||
: mBitField(bitFor(aEnum1) |
|
||||
bitFor(aEnum2) |
|
||||
bitFor(aEnum3) |
|
||||
bitFor(aEnum4))
|
||||
{
|
||||
initVersion();
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT EnumSet(std::initializer_list<T> list)
|
||||
: mBitField(0)
|
||||
{
|
||||
for (auto value : list) {
|
||||
(*this) += value;
|
||||
}
|
||||
initVersion();
|
||||
}
|
||||
|
||||
EnumSet(const EnumSet& aEnumSet)
|
||||
: mBitField(aEnumSet.mBitField)
|
||||
{
|
||||
initVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element
|
||||
*/
|
||||
void operator+=(T aEnum)
|
||||
{
|
||||
incVersion();
|
||||
mBitField |= bitFor(aEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element
|
||||
*/
|
||||
EnumSet<T> operator+(T aEnum) const
|
||||
{
|
||||
EnumSet<T> result(*this);
|
||||
result += aEnum;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Union
|
||||
*/
|
||||
void operator+=(const EnumSet<T> aEnumSet)
|
||||
{
|
||||
incVersion();
|
||||
mBitField |= aEnumSet.mBitField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Union
|
||||
*/
|
||||
EnumSet<T> operator+(const EnumSet<T> aEnumSet) const
|
||||
{
|
||||
EnumSet<T> result(*this);
|
||||
result += aEnumSet;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element
|
||||
*/
|
||||
void operator-=(T aEnum)
|
||||
{
|
||||
incVersion();
|
||||
mBitField &= ~(bitFor(aEnum));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element
|
||||
*/
|
||||
EnumSet<T> operator-(T aEnum) const
|
||||
{
|
||||
EnumSet<T> result(*this);
|
||||
result -= aEnum;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a set of elements
|
||||
*/
|
||||
void operator-=(const EnumSet<T> aEnumSet)
|
||||
{
|
||||
incVersion();
|
||||
mBitField &= ~(aEnumSet.mBitField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a set of elements
|
||||
*/
|
||||
EnumSet<T> operator-(const EnumSet<T> aEnumSet) const
|
||||
{
|
||||
EnumSet<T> result(*this);
|
||||
result -= aEnumSet;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
incVersion();
|
||||
mBitField = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection
|
||||
*/
|
||||
void operator&=(const EnumSet<T> aEnumSet)
|
||||
{
|
||||
incVersion();
|
||||
mBitField &= aEnumSet.mBitField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection
|
||||
*/
|
||||
EnumSet<T> operator&(const EnumSet<T> aEnumSet) const
|
||||
{
|
||||
EnumSet<T> result(*this);
|
||||
result &= aEnumSet;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equality
|
||||
*/
|
||||
bool operator==(const EnumSet<T> aEnumSet) const
|
||||
{
|
||||
return mBitField == aEnumSet.mBitField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test is an element is contained in the set.
|
||||
*/
|
||||
bool contains(T aEnum) const
|
||||
{
|
||||
return mBitField & bitFor(aEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of elements in the set.
|
||||
*/
|
||||
uint8_t size() const
|
||||
{
|
||||
uint8_t count = 0;
|
||||
for (uint32_t bitField = mBitField; bitField; bitField >>= 1) {
|
||||
if (bitField & 1) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return mBitField == 0;
|
||||
}
|
||||
|
||||
uint32_t serialize() const
|
||||
{
|
||||
return mBitField;
|
||||
}
|
||||
|
||||
void deserialize(uint32_t aValue)
|
||||
{
|
||||
incVersion();
|
||||
mBitField = aValue;
|
||||
}
|
||||
|
||||
class ConstIterator
|
||||
{
|
||||
const EnumSet<T>* mSet;
|
||||
uint32_t mPos;
|
||||
#ifdef DEBUG
|
||||
uint64_t mVersion;
|
||||
#endif
|
||||
|
||||
void checkVersion() {
|
||||
// Check that the set has not been modified while being iterated.
|
||||
MOZ_ASSERT_IF(mSet, mSet->mVersion == mVersion);
|
||||
}
|
||||
|
||||
public:
|
||||
ConstIterator(const EnumSet<T>& aSet, uint32_t aPos)
|
||||
: mSet(&aSet), mPos(aPos)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mVersion = mSet->mVersion;
|
||||
#endif
|
||||
MOZ_ASSERT(aPos <= kMaxBits);
|
||||
if (aPos != kMaxBits && !mSet->contains(T(mPos)))
|
||||
++*this;
|
||||
}
|
||||
|
||||
ConstIterator(const ConstIterator& aOther)
|
||||
: mSet(aOther.mSet), mPos(aOther.mPos)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mVersion = aOther.mVersion;
|
||||
checkVersion();
|
||||
#endif
|
||||
}
|
||||
|
||||
ConstIterator(ConstIterator&& aOther)
|
||||
: mSet(aOther.mSet), mPos(aOther.mPos)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mVersion = aOther.mVersion;
|
||||
checkVersion();
|
||||
#endif
|
||||
aOther.mSet = nullptr;
|
||||
}
|
||||
|
||||
~ConstIterator() {
|
||||
checkVersion();
|
||||
}
|
||||
|
||||
bool operator==(const ConstIterator& other) {
|
||||
MOZ_ASSERT(mSet == other.mSet);
|
||||
checkVersion();
|
||||
return mPos == other.mPos;
|
||||
}
|
||||
|
||||
bool operator!=(const ConstIterator& other) {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
MOZ_ASSERT(mSet);
|
||||
MOZ_ASSERT(mPos < kMaxBits);
|
||||
MOZ_ASSERT(mSet->contains(T(mPos)));
|
||||
checkVersion();
|
||||
return T(mPos);
|
||||
}
|
||||
|
||||
ConstIterator& operator++() {
|
||||
MOZ_ASSERT(mSet);
|
||||
MOZ_ASSERT(mPos < kMaxBits);
|
||||
checkVersion();
|
||||
do {
|
||||
mPos++;
|
||||
} while (mPos < kMaxBits && !mSet->contains(T(mPos)));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
ConstIterator begin() const {
|
||||
return ConstIterator(*this, 0);
|
||||
}
|
||||
|
||||
ConstIterator end() const {
|
||||
return ConstIterator(*this, kMaxBits);
|
||||
}
|
||||
|
||||
private:
|
||||
static uint32_t bitFor(T aEnum)
|
||||
{
|
||||
uint32_t bitNumber = (uint32_t)aEnum;
|
||||
MOZ_ASSERT(bitNumber < kMaxBits);
|
||||
return 1U << bitNumber;
|
||||
}
|
||||
|
||||
void initVersion() {
|
||||
#ifdef DEBUG
|
||||
mVersion = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void incVersion() {
|
||||
#ifdef DEBUG
|
||||
mVersion++;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const size_t kMaxBits = 32;
|
||||
uint32_t mBitField;
|
||||
|
||||
#ifdef DEBUG
|
||||
uint64_t mVersion;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_EnumSet_h_*/
|
||||
70
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumTypeTraits.h
vendored
Executable file
70
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumTypeTraits.h
vendored
Executable file
@@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Type traits for enums. */
|
||||
|
||||
#ifndef mozilla_EnumTypeTraits_h
|
||||
#define mozilla_EnumTypeTraits_h
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<size_t EnumSize, bool EnumSigned, size_t StorageSize, bool StorageSigned>
|
||||
struct EnumFitsWithinHelper;
|
||||
|
||||
// Signed enum, signed storage.
|
||||
template<size_t EnumSize, size_t StorageSize>
|
||||
struct EnumFitsWithinHelper<EnumSize, true, StorageSize, true>
|
||||
: public std::integral_constant<bool, (EnumSize <= StorageSize)>
|
||||
{};
|
||||
|
||||
// Signed enum, unsigned storage.
|
||||
template<size_t EnumSize, size_t StorageSize>
|
||||
struct EnumFitsWithinHelper<EnumSize, true, StorageSize, false>
|
||||
: public std::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
// Unsigned enum, signed storage.
|
||||
template<size_t EnumSize, size_t StorageSize>
|
||||
struct EnumFitsWithinHelper<EnumSize, false, StorageSize, true>
|
||||
: public std::integral_constant<bool, (EnumSize * 2 <= StorageSize)>
|
||||
{};
|
||||
|
||||
// Unsigned enum, unsigned storage.
|
||||
template<size_t EnumSize, size_t StorageSize>
|
||||
struct EnumFitsWithinHelper<EnumSize, false, StorageSize, false>
|
||||
: public std::integral_constant<bool, (EnumSize <= StorageSize)>
|
||||
{};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/*
|
||||
* Type trait that determines whether the enum type T can fit within the
|
||||
* integral type Storage without data loss. This trait should be used with
|
||||
* caution with an enum type whose underlying type has not been explicitly
|
||||
* specified: for such enums, the C++ implementation is free to choose a type
|
||||
* no smaller than int whose range encompasses all possible values of the enum.
|
||||
* So for an enum with only small non-negative values, the underlying type may
|
||||
* be either int or unsigned int, depending on the whims of the implementation.
|
||||
*/
|
||||
template<typename T, typename Storage>
|
||||
struct EnumTypeFitsWithin
|
||||
: public detail::EnumFitsWithinHelper<
|
||||
sizeof(T),
|
||||
std::is_signed<typename std::underlying_type<T>::type>::value,
|
||||
sizeof(Storage),
|
||||
std::is_signed<Storage>::value
|
||||
>
|
||||
{
|
||||
static_assert(std::is_enum<T>::value, "must provide an enum type");
|
||||
static_assert(std::is_integral<Storage>::value, "must provide an integral type");
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_EnumTypeTraits_h */
|
||||
110
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumeratedArray.h
vendored
Executable file
110
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumeratedArray.h
vendored
Executable file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* EnumeratedArray is like Array, but indexed by a typed enum. */
|
||||
|
||||
#ifndef mozilla_EnumeratedArray_h
|
||||
#define mozilla_EnumeratedArray_h
|
||||
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* EnumeratedArray is a fixed-size array container for use when an
|
||||
* array is indexed by a specific enum class.
|
||||
*
|
||||
* This provides type safety by guarding at compile time against accidentally
|
||||
* indexing such arrays with unrelated values. This also removes the need
|
||||
* for manual casting when using a typed enum value to index arrays.
|
||||
*
|
||||
* Aside from the typing of indices, EnumeratedArray is similar to Array.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* enum class AnimalSpecies {
|
||||
* Cow,
|
||||
* Sheep,
|
||||
* Count
|
||||
* };
|
||||
*
|
||||
* EnumeratedArray<AnimalSpecies, AnimalSpecies::Count, int> headCount;
|
||||
*
|
||||
* headCount[AnimalSpecies::Cow] = 17;
|
||||
* headCount[AnimalSpecies::Sheep] = 30;
|
||||
*
|
||||
*/
|
||||
template<typename IndexType,
|
||||
IndexType SizeAsEnumValue,
|
||||
typename ValueType>
|
||||
class EnumeratedArray
|
||||
{
|
||||
public:
|
||||
static const size_t kSize = size_t(SizeAsEnumValue);
|
||||
|
||||
private:
|
||||
typedef Array<ValueType, kSize> ArrayType;
|
||||
|
||||
ArrayType mArray;
|
||||
|
||||
public:
|
||||
EnumeratedArray() {}
|
||||
|
||||
template <typename... Args>
|
||||
MOZ_IMPLICIT EnumeratedArray(Args&&... aArgs)
|
||||
: mArray{mozilla::Forward<Args>(aArgs)...}
|
||||
{}
|
||||
|
||||
explicit EnumeratedArray(const EnumeratedArray& aOther)
|
||||
{
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
mArray[i] = aOther.mArray[i];
|
||||
}
|
||||
}
|
||||
|
||||
EnumeratedArray(EnumeratedArray&& aOther)
|
||||
{
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
mArray[i] = Move(aOther.mArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ValueType& operator[](IndexType aIndex)
|
||||
{
|
||||
return mArray[size_t(aIndex)];
|
||||
}
|
||||
|
||||
const ValueType& operator[](IndexType aIndex) const
|
||||
{
|
||||
return mArray[size_t(aIndex)];
|
||||
}
|
||||
|
||||
typedef typename ArrayType::iterator iterator;
|
||||
typedef typename ArrayType::const_iterator const_iterator;
|
||||
typedef typename ArrayType::reverse_iterator reverse_iterator;
|
||||
typedef typename ArrayType::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
// Methods for range-based for loops.
|
||||
iterator begin() { return mArray.begin(); }
|
||||
const_iterator begin() const { return mArray.begin(); }
|
||||
const_iterator cbegin() const { return mArray.cbegin(); }
|
||||
iterator end() { return mArray.end(); }
|
||||
const_iterator end() const { return mArray.end(); }
|
||||
const_iterator cend() const { return mArray.cend(); }
|
||||
|
||||
// Methods for reverse iterating.
|
||||
reverse_iterator rbegin() { return mArray.rbegin(); }
|
||||
const_reverse_iterator rbegin() const { return mArray.rbegin(); }
|
||||
const_reverse_iterator crbegin() const { return mArray.crbegin(); }
|
||||
reverse_iterator rend() { return mArray.rend(); }
|
||||
const_reverse_iterator rend() const { return mArray.rend(); }
|
||||
const_reverse_iterator crend() const { return mArray.crend(); }
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_EnumeratedArray_h
|
||||
201
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumeratedRange.h
vendored
Executable file
201
cocos2d-x/external/win32/include/spidermonkey/mozilla/EnumeratedRange.h
vendored
Executable file
@@ -0,0 +1,201 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Iterator over contiguous enum values */
|
||||
|
||||
/*
|
||||
* Implements generator functions that create a range to iterate over the values
|
||||
* of a scoped or unscoped enum. Unlike IntegerRange, which can only function on
|
||||
* the underlying integral type, the elements of the generated sequence will
|
||||
* have the type of the enum in question.
|
||||
*
|
||||
* Note that the enum values should be contiguous in the iterated range;
|
||||
* unfortunately there exists no way for EnumeratedRange to enforce this
|
||||
* either dynamically or at compile time.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_EnumeratedRange_h
|
||||
#define mozilla_EnumeratedRange_h
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "mozilla/ReverseIterator.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename EnumTypeT>
|
||||
class EnumeratedIterator
|
||||
{
|
||||
public:
|
||||
typedef typename std::underlying_type<EnumTypeT>::type IntTypeT;
|
||||
|
||||
template<typename EnumType>
|
||||
explicit EnumeratedIterator(EnumType aCurrent)
|
||||
: mCurrent(aCurrent) { }
|
||||
|
||||
template<typename EnumType>
|
||||
explicit EnumeratedIterator(const EnumeratedIterator<EnumType>& aOther)
|
||||
: mCurrent(aOther.mCurrent) { }
|
||||
|
||||
EnumTypeT operator*() const { return mCurrent; }
|
||||
|
||||
/* Increment and decrement operators */
|
||||
|
||||
EnumeratedIterator& operator++()
|
||||
{
|
||||
mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
|
||||
return *this;
|
||||
}
|
||||
EnumeratedIterator& operator--()
|
||||
{
|
||||
mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
|
||||
return *this;
|
||||
}
|
||||
EnumeratedIterator operator++(int)
|
||||
{
|
||||
auto ret = *this;
|
||||
mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
|
||||
return ret;
|
||||
}
|
||||
EnumeratedIterator operator--(int)
|
||||
{
|
||||
auto ret = *this;
|
||||
mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Comparison operators */
|
||||
|
||||
template<typename EnumType>
|
||||
friend bool operator==(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2);
|
||||
template<typename EnumType>
|
||||
friend bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2);
|
||||
template<typename EnumType>
|
||||
friend bool operator<(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2);
|
||||
template<typename EnumType>
|
||||
friend bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2);
|
||||
template<typename EnumType>
|
||||
friend bool operator>(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2);
|
||||
template<typename EnumType>
|
||||
friend bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2);
|
||||
|
||||
private:
|
||||
EnumTypeT mCurrent;
|
||||
};
|
||||
|
||||
template<typename EnumType>
|
||||
bool operator==(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent == aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent != aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
bool operator<(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent < aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent <= aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
bool operator>(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent > aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
|
||||
const EnumeratedIterator<EnumType>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent >= aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename EnumTypeT>
|
||||
class EnumeratedRange
|
||||
{
|
||||
public:
|
||||
typedef EnumeratedIterator<EnumTypeT> iterator;
|
||||
typedef EnumeratedIterator<EnumTypeT> const_iterator;
|
||||
typedef ReverseIterator<iterator> reverse_iterator;
|
||||
typedef ReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
template<typename EnumType>
|
||||
EnumeratedRange(EnumType aBegin, EnumType aEnd)
|
||||
: mBegin(aBegin), mEnd(aEnd) { }
|
||||
|
||||
iterator begin() const { return iterator(mBegin); }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() const { return iterator(mEnd); }
|
||||
const_iterator cend() const { return end(); }
|
||||
reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
reverse_iterator rend() const { return reverse_iterator(mBegin); }
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
|
||||
private:
|
||||
EnumTypeT mBegin;
|
||||
EnumTypeT mEnd;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Enums can have an unsigned underlying type, which makes some of the
|
||||
// comparisons below always true or always false. Temporarily disable
|
||||
// -Wtype-limits to avoid breaking -Werror builds.
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
#endif
|
||||
|
||||
// Create a range to iterate from aBegin to aEnd, exclusive.
|
||||
template<typename EnumType>
|
||||
inline detail::EnumeratedRange<EnumType>
|
||||
MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
|
||||
{
|
||||
MOZ_ASSERT(aBegin <= aEnd, "Cannot generate invalid, unbounded range!");
|
||||
return detail::EnumeratedRange<EnumType>(aBegin, aEnd);
|
||||
}
|
||||
|
||||
// Create a range to iterate from EnumType(0) to aEnd, exclusive. EnumType(0)
|
||||
// should exist, but note that there is no way for us to ensure that it does!
|
||||
template<typename EnumType>
|
||||
inline detail::EnumeratedRange<EnumType>
|
||||
MakeEnumeratedRange(EnumType aEnd)
|
||||
{
|
||||
return MakeEnumeratedRange(EnumType(0), aEnd);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_EnumeratedRange_h
|
||||
|
||||
379
cocos2d-x/external/win32/include/spidermonkey/mozilla/FastBernoulliTrial.h
vendored
Executable file
379
cocos2d-x/external/win32/include/spidermonkey/mozilla/FastBernoulliTrial.h
vendored
Executable file
@@ -0,0 +1,379 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_FastBernoulliTrial_h
|
||||
#define mozilla_FastBernoulliTrial_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/XorShift128PlusRNG.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* class FastBernoulliTrial: Efficient sampling with uniform probability
|
||||
*
|
||||
* When gathering statistics about a program's behavior, we may be observing
|
||||
* events that occur very frequently (e.g., function calls or memory
|
||||
* allocations) and we may be gathering information that is somewhat expensive
|
||||
* to produce (e.g., call stacks). Sampling all the events could have a
|
||||
* significant impact on the program's performance.
|
||||
*
|
||||
* Why not just sample every N'th event? This technique is called "systematic
|
||||
* sampling"; it's simple and efficient, and it's fine if we imagine a
|
||||
* patternless stream of events. But what if we're sampling allocations, and the
|
||||
* program happens to have a loop where each iteration does exactly N
|
||||
* allocations? You would end up sampling the same allocation every time through
|
||||
* the loop; the entire rest of the loop becomes invisible to your measurements!
|
||||
* More generally, if each iteration does M allocations, and M and N have any
|
||||
* common divisor at all, most allocation sites will never be sampled. If
|
||||
* they're both even, say, the odd-numbered allocations disappear from your
|
||||
* results.
|
||||
*
|
||||
* Ideally, we'd like each event to have some probability P of being sampled,
|
||||
* independent of its neighbors and of its position in the sequence. This is
|
||||
* called "Bernoulli sampling", and it doesn't suffer from any of the problems
|
||||
* mentioned above.
|
||||
*
|
||||
* One disadvantage of Bernoulli sampling is that you can't be sure exactly how
|
||||
* many samples you'll get: technically, it's possible that you might sample
|
||||
* none of them, or all of them. But if the number of events N is large, these
|
||||
* aren't likely outcomes; you can generally expect somewhere around P * N
|
||||
* events to be sampled.
|
||||
*
|
||||
* The other disadvantage of Bernoulli sampling is that you have to generate a
|
||||
* random number for every event, which can be slow.
|
||||
*
|
||||
* [significant pause]
|
||||
*
|
||||
* BUT NOT WITH THIS CLASS! FastBernoulliTrial lets you do true Bernoulli
|
||||
* sampling, while generating a fresh random number only when we do decide to
|
||||
* sample an event, not on every trial. When it decides not to sample, a call to
|
||||
* |FastBernoulliTrial::trial| is nothing but decrementing a counter and
|
||||
* comparing it to zero. So the lower your sampling probability is, the less
|
||||
* overhead FastBernoulliTrial imposes.
|
||||
*
|
||||
* Probabilities of 0 and 1 are handled efficiently. (In neither case need we
|
||||
* ever generate a random number at all.)
|
||||
*
|
||||
* The essential API:
|
||||
*
|
||||
* - FastBernoulliTrial(double P)
|
||||
* Construct an instance that selects events with probability P.
|
||||
*
|
||||
* - FastBernoulliTrial::trial()
|
||||
* Return true with probability P. Call this each time an event occurs, to
|
||||
* decide whether to sample it or not.
|
||||
*
|
||||
* - FastBernoulliTrial::trial(size_t n)
|
||||
* Equivalent to calling trial() |n| times, and returning true if any of those
|
||||
* calls do. However, like trial, this runs in fast constant time.
|
||||
*
|
||||
* What is this good for? In some applications, some events are "bigger" than
|
||||
* others. For example, large allocations are more significant than small
|
||||
* allocations. Perhaps we'd like to imagine that we're drawing allocations
|
||||
* from a stream of bytes, and performing a separate Bernoulli trial on every
|
||||
* byte from the stream. We can accomplish this by calling |t.trial(S)| for
|
||||
* the number of bytes S, and sampling the event if that returns true.
|
||||
*
|
||||
* Of course, this style of sampling needs to be paired with analysis and
|
||||
* presentation that makes the size of the event apparent, lest trials with
|
||||
* large values for |n| appear to be indistinguishable from those with small
|
||||
* values for |n|.
|
||||
*/
|
||||
class FastBernoulliTrial {
|
||||
/*
|
||||
* This comment should just read, "Generate skip counts with a geometric
|
||||
* distribution", and leave everyone to go look that up and see why it's the
|
||||
* right thing to do, if they don't know already.
|
||||
*
|
||||
* BUT IF YOU'RE CURIOUS, COMMENTS ARE FREE...
|
||||
*
|
||||
* Instead of generating a fresh random number for every trial, we can
|
||||
* randomly generate a count of how many times we should return false before
|
||||
* the next time we return true. We call this a "skip count". Once we've
|
||||
* returned true, we generate a fresh skip count, and begin counting down
|
||||
* again.
|
||||
*
|
||||
* Here's an awesome fact: by exercising a little care in the way we generate
|
||||
* skip counts, we can produce results indistinguishable from those we would
|
||||
* get "rolling the dice" afresh for every trial.
|
||||
*
|
||||
* In short, skip counts in Bernoulli trials of probability P obey a geometric
|
||||
* distribution. If a random variable X is uniformly distributed from [0..1),
|
||||
* then std::floor(std::log(X) / std::log(1-P)) has the appropriate geometric
|
||||
* distribution for the skip counts.
|
||||
*
|
||||
* Why that formula?
|
||||
*
|
||||
* Suppose we're to return |true| with some probability P, say, 0.3. Spread
|
||||
* all possible futures along a line segment of length 1. In portion P of
|
||||
* those cases, we'll return true on the next call to |trial|; the skip count
|
||||
* is 0. For the remaining portion 1-P of cases, the skip count is 1 or more.
|
||||
*
|
||||
* skip: 0 1 or more
|
||||
* |------------------^-----------------------------------------|
|
||||
* portion: 0.3 0.7
|
||||
* P 1-P
|
||||
*
|
||||
* But the "1 or more" section of the line is subdivided the same way: *within
|
||||
* that section*, in portion P the second call to |trial()| returns true, and in
|
||||
* portion 1-P it returns false a second time; the skip count is two or more.
|
||||
* So we return true on the second call in proportion 0.7 * 0.3, and skip at
|
||||
* least the first two in proportion 0.7 * 0.7.
|
||||
*
|
||||
* skip: 0 1 2 or more
|
||||
* |------------------^------------^----------------------------|
|
||||
* portion: 0.3 0.7 * 0.3 0.7 * 0.7
|
||||
* P (1-P)*P (1-P)^2
|
||||
*
|
||||
* We can continue to subdivide:
|
||||
*
|
||||
* skip >= 0: |------------------------------------------------- (1-P)^0 --|
|
||||
* skip >= 1: | ------------------------------- (1-P)^1 --|
|
||||
* skip >= 2: | ------------------ (1-P)^2 --|
|
||||
* skip >= 3: | ^ ---------- (1-P)^3 --|
|
||||
* skip >= 4: | . --- (1-P)^4 --|
|
||||
* .
|
||||
* ^X, see below
|
||||
*
|
||||
* In other words, the likelihood of the next n calls to |trial| returning
|
||||
* false is (1-P)^n. The longer a run we require, the more the likelihood
|
||||
* drops. Further calls may return false too, but this is the probability
|
||||
* we'll skip at least n.
|
||||
*
|
||||
* This is interesting, because we can pick a point along this line segment
|
||||
* and see which skip count's range it falls within; the point X above, for
|
||||
* example, is within the ">= 2" range, but not within the ">= 3" range, so it
|
||||
* designates a skip count of 2. So if we pick points on the line at random
|
||||
* and use the skip counts they fall under, that will be indistinguishable
|
||||
* from generating a fresh random number between 0 and 1 for each trial and
|
||||
* comparing it to P.
|
||||
*
|
||||
* So to find the skip count for a point X, we must ask: To what whole power
|
||||
* must we raise 1-P such that we include X, but the next power would exclude
|
||||
* it? This is exactly std::floor(std::log(X) / std::log(1-P)).
|
||||
*
|
||||
* Our algorithm is then, simply: When constructed, compute an initial skip
|
||||
* count. Return false from |trial| that many times, and then compute a new skip
|
||||
* count.
|
||||
*
|
||||
* For a call to |trial(n)|, if the skip count is greater than n, return false
|
||||
* and subtract n from the skip count. If the skip count is less than n,
|
||||
* return true and compute a new skip count. Since each trial is independent,
|
||||
* it doesn't matter by how much n overshoots the skip count; we can actually
|
||||
* compute a new skip count at *any* time without affecting the distribution.
|
||||
* This is really beautiful.
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Construct a fast Bernoulli trial generator. Calls to |trial()| return true
|
||||
* with probability |aProbability|. Use |aState0| and |aState1| to seed the
|
||||
* random number generator; both may not be zero.
|
||||
*/
|
||||
FastBernoulliTrial(double aProbability, uint64_t aState0, uint64_t aState1)
|
||||
: mProbability(0)
|
||||
, mInvLogNotProbability(0)
|
||||
, mGenerator(aState0, aState1)
|
||||
, mSkipCount(0)
|
||||
{
|
||||
setProbability(aProbability);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true with probability |mProbability|. Call this each time an event
|
||||
* occurs, to decide whether to sample it or not. The lower |mProbability| is,
|
||||
* the faster this function runs.
|
||||
*/
|
||||
bool trial() {
|
||||
if (mSkipCount) {
|
||||
mSkipCount--;
|
||||
return false;
|
||||
}
|
||||
|
||||
return chooseSkipCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to calling trial() |n| times, and returning true if any of those
|
||||
* calls do. However, like trial, this runs in fast constant time.
|
||||
*
|
||||
* What is this good for? In some applications, some events are "bigger" than
|
||||
* others. For example, large allocations are more significant than small
|
||||
* allocations. Perhaps we'd like to imagine that we're drawing allocations
|
||||
* from a stream of bytes, and performing a separate Bernoulli trial on every
|
||||
* byte from the stream. We can accomplish this by calling |t.trial(S)| for
|
||||
* the number of bytes S, and sampling the event if that returns true.
|
||||
*
|
||||
* Of course, this style of sampling needs to be paired with analysis and
|
||||
* presentation that makes the "size" of the event apparent, lest trials with
|
||||
* large values for |n| appear to be indistinguishable from those with small
|
||||
* values for |n|, despite being potentially much more likely to be sampled.
|
||||
*/
|
||||
bool trial(size_t aCount) {
|
||||
if (mSkipCount > aCount) {
|
||||
mSkipCount -= aCount;
|
||||
return false;
|
||||
}
|
||||
|
||||
return chooseSkipCount();
|
||||
}
|
||||
|
||||
void setRandomState(uint64_t aState0, uint64_t aState1) {
|
||||
mGenerator.setState(aState0, aState1);
|
||||
}
|
||||
|
||||
void setProbability(double aProbability) {
|
||||
MOZ_ASSERT(0 <= aProbability && aProbability <= 1);
|
||||
mProbability = aProbability;
|
||||
if (0 < mProbability && mProbability < 1) {
|
||||
/*
|
||||
* Let's look carefully at how this calculation plays out in floating-
|
||||
* point arithmetic. We'll assume IEEE, but the final C++ code we arrive
|
||||
* at would still be fine if our numbers were mathematically perfect. So,
|
||||
* while we've considered IEEE's edge cases, we haven't done anything that
|
||||
* should be actively bad when using other representations.
|
||||
*
|
||||
* (In the below, read comparisons as exact mathematical comparisons: when
|
||||
* we say something "equals 1", that means it's exactly equal to 1. We
|
||||
* treat approximation using intervals with open boundaries: saying a
|
||||
* value is in (0,1) doesn't specify how close to 0 or 1 the value gets.
|
||||
* When we use closed boundaries like [2**-53, 1], we're careful to ensure
|
||||
* the boundary values are actually representable.)
|
||||
*
|
||||
* - After the comparison above, we know mProbability is in (0,1).
|
||||
*
|
||||
* - The gaps below 1 are 2**-53, so that interval is (0, 1-2**-53].
|
||||
*
|
||||
* - Because the floating-point gaps near 1 are wider than those near
|
||||
* zero, there are many small positive doubles ε such that 1-ε rounds to
|
||||
* exactly 1. However, 2**-53 can be represented exactly. So
|
||||
* 1-mProbability is in [2**-53, 1].
|
||||
*
|
||||
* - log(1 - mProbability) is thus in (-37, 0].
|
||||
*
|
||||
* That range includes zero, but when we use mInvLogNotProbability, it
|
||||
* would be helpful if we could trust that it's negative. So when log(1
|
||||
* - mProbability) is 0, we'll just set mProbability to 0, so that
|
||||
* mInvLogNotProbability is not used in chooseSkipCount.
|
||||
*
|
||||
* - How much of the range of mProbability does this cause us to ignore?
|
||||
* The only value for which log returns 0 is exactly 1; the slope of log
|
||||
* at 1 is 1, so for small ε such that 1 - ε != 1, log(1 - ε) is -ε,
|
||||
* never 0. The gaps near one are larger than the gaps near zero, so if
|
||||
* 1 - ε wasn't 1, then -ε is representable. So if log(1 - mProbability)
|
||||
* isn't 0, then 1 - mProbability isn't 1, which means that mProbability
|
||||
* is at least 2**-53, as discussed earlier. This is a sampling
|
||||
* likelihood of roughly one in ten trillion, which is unlikely to be
|
||||
* distinguishable from zero in practice.
|
||||
*
|
||||
* So by forbidding zero, we've tightened our range to (-37, -2**-53].
|
||||
*
|
||||
* - Finally, 1 / log(1 - mProbability) is in [-2**53, -1/37). This all
|
||||
* falls readily within the range of an IEEE double.
|
||||
*
|
||||
* ALL THAT HAVING BEEN SAID: here are the five lines of actual code:
|
||||
*/
|
||||
double logNotProbability = std::log(1 - mProbability);
|
||||
if (logNotProbability == 0.0)
|
||||
mProbability = 0.0;
|
||||
else
|
||||
mInvLogNotProbability = 1 / logNotProbability;
|
||||
}
|
||||
|
||||
chooseSkipCount();
|
||||
}
|
||||
|
||||
private:
|
||||
/* The likelihood that any given call to |trial| should return true. */
|
||||
double mProbability;
|
||||
|
||||
/*
|
||||
* The value of 1/std::log(1 - mProbability), cached for repeated use.
|
||||
*
|
||||
* If mProbability is exactly 0 or exactly 1, we don't use this value.
|
||||
* Otherwise, we guarantee this value is in the range [-2**53, -1/37), i.e.
|
||||
* definitely negative, as required by chooseSkipCount. See setProbability for
|
||||
* the details.
|
||||
*/
|
||||
double mInvLogNotProbability;
|
||||
|
||||
/* Our random number generator. */
|
||||
non_crypto::XorShift128PlusRNG mGenerator;
|
||||
|
||||
/* The number of times |trial| should return false before next returning true. */
|
||||
size_t mSkipCount;
|
||||
|
||||
/*
|
||||
* Choose the next skip count. This also returns the value that |trial| should
|
||||
* return, since we have to check for the extreme values for mProbability
|
||||
* anyway, and |trial| should never return true at all when mProbability is 0.
|
||||
*/
|
||||
bool chooseSkipCount() {
|
||||
/*
|
||||
* If the probability is 1.0, every call to |trial| returns true. Make sure
|
||||
* mSkipCount is 0.
|
||||
*/
|
||||
if (mProbability == 1.0) {
|
||||
mSkipCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the probabilility is zero, |trial| never returns true. Don't bother us
|
||||
* for a while.
|
||||
*/
|
||||
if (mProbability == 0.0) {
|
||||
mSkipCount = SIZE_MAX;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* What sorts of values can this call to std::floor produce?
|
||||
*
|
||||
* Since mGenerator.nextDouble returns a value in [0, 1-2**-53], std::log
|
||||
* returns a value in the range [-infinity, -2**-53], all negative. Since
|
||||
* mInvLogNotProbability is negative (see its comments), the product is
|
||||
* positive and possibly infinite. std::floor returns +infinity unchanged.
|
||||
* So the result will always be positive.
|
||||
*
|
||||
* Converting a double to an integer that is out of range for that integer
|
||||
* is undefined behavior, so we must clamp our result to SIZE_MAX, to ensure
|
||||
* we get an acceptable value for mSkipCount.
|
||||
*
|
||||
* The clamp is written carefully. Note that if we had said:
|
||||
*
|
||||
* if (skipCount > SIZE_MAX)
|
||||
* skipCount = SIZE_MAX;
|
||||
*
|
||||
* that leads to undefined behavior 64-bit machines: SIZE_MAX coerced to
|
||||
* double is 2^64, not 2^64-1, so this doesn't actually set skipCount to a
|
||||
* value that can be safely assigned to mSkipCount.
|
||||
*
|
||||
* Jakub Oleson cleverly suggested flipping the sense of the comparison: if
|
||||
* we require that skipCount < SIZE_MAX, then because of the gaps (2048)
|
||||
* between doubles at that magnitude, the highest double less than 2^64 is
|
||||
* 2^64 - 2048, which is fine to store in a size_t.
|
||||
*
|
||||
* (On 32-bit machines, all size_t values can be represented exactly in
|
||||
* double, so all is well.)
|
||||
*/
|
||||
double skipCount = std::floor(std::log(mGenerator.nextDouble())
|
||||
* mInvLogNotProbability);
|
||||
if (skipCount < SIZE_MAX)
|
||||
mSkipCount = skipCount;
|
||||
else
|
||||
mSkipCount = SIZE_MAX;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_FastBernoulliTrial_h */
|
||||
479
cocos2d-x/external/win32/include/spidermonkey/mozilla/FloatingPoint.h
vendored
Executable file
479
cocos2d-x/external/win32/include/spidermonkey/mozilla/FloatingPoint.h
vendored
Executable file
@@ -0,0 +1,479 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Various predicates and operations on IEEE-754 floating point types. */
|
||||
|
||||
#ifndef mozilla_FloatingPoint_h
|
||||
#define mozilla_FloatingPoint_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* It's reasonable to ask why we have this header at all. Don't isnan,
|
||||
* copysign, the built-in comparison operators, and the like solve these
|
||||
* problems? Unfortunately, they don't. We've found that various compilers
|
||||
* (MSVC, MSVC when compiling with PGO, and GCC on OS X, at least) miscompile
|
||||
* the standard methods in various situations, so we can't use them. Some of
|
||||
* these compilers even have problems compiling seemingly reasonable bitwise
|
||||
* algorithms! But with some care we've found algorithms that seem to not
|
||||
* trigger those compiler bugs.
|
||||
*
|
||||
* For the aforementioned reasons, be very wary of making changes to any of
|
||||
* these algorithms. If you must make changes, keep a careful eye out for
|
||||
* compiler bustage, particularly PGO-specific bustage.
|
||||
*/
|
||||
|
||||
struct FloatTypeTraits
|
||||
{
|
||||
typedef uint32_t Bits;
|
||||
|
||||
static const unsigned kExponentBias = 127;
|
||||
static const unsigned kExponentShift = 23;
|
||||
|
||||
static const Bits kSignBit = 0x80000000UL;
|
||||
static const Bits kExponentBits = 0x7F800000UL;
|
||||
static const Bits kSignificandBits = 0x007FFFFFUL;
|
||||
};
|
||||
|
||||
struct DoubleTypeTraits
|
||||
{
|
||||
typedef uint64_t Bits;
|
||||
|
||||
static const unsigned kExponentBias = 1023;
|
||||
static const unsigned kExponentShift = 52;
|
||||
|
||||
static const Bits kSignBit = 0x8000000000000000ULL;
|
||||
static const Bits kExponentBits = 0x7ff0000000000000ULL;
|
||||
static const Bits kSignificandBits = 0x000fffffffffffffULL;
|
||||
};
|
||||
|
||||
template<typename T> struct SelectTrait;
|
||||
template<> struct SelectTrait<float> : public FloatTypeTraits {};
|
||||
template<> struct SelectTrait<double> : public DoubleTypeTraits {};
|
||||
|
||||
/*
|
||||
* This struct contains details regarding the encoding of floating-point
|
||||
* numbers that can be useful for direct bit manipulation. As of now, the
|
||||
* template parameter has to be float or double.
|
||||
*
|
||||
* The nested typedef |Bits| is the unsigned integral type with the same size
|
||||
* as T: uint32_t for float and uint64_t for double (static assertions
|
||||
* double-check these assumptions).
|
||||
*
|
||||
* kExponentBias is the offset that is subtracted from the exponent when
|
||||
* computing the value, i.e. one plus the opposite of the mininum possible
|
||||
* exponent.
|
||||
* kExponentShift is the shift that one needs to apply to retrieve the
|
||||
* exponent component of the value.
|
||||
*
|
||||
* kSignBit contains a bits mask. Bit-and-ing with this mask will result in
|
||||
* obtaining the sign bit.
|
||||
* kExponentBits contains the mask needed for obtaining the exponent bits and
|
||||
* kSignificandBits contains the mask needed for obtaining the significand
|
||||
* bits.
|
||||
*
|
||||
* Full details of how floating point number formats are encoded are beyond
|
||||
* the scope of this comment. For more information, see
|
||||
* http://en.wikipedia.org/wiki/IEEE_floating_point
|
||||
* http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
|
||||
*/
|
||||
template<typename T>
|
||||
struct FloatingPoint : public SelectTrait<T>
|
||||
{
|
||||
typedef SelectTrait<T> Base;
|
||||
typedef typename Base::Bits Bits;
|
||||
|
||||
static_assert((Base::kSignBit & Base::kExponentBits) == 0,
|
||||
"sign bit shouldn't overlap exponent bits");
|
||||
static_assert((Base::kSignBit & Base::kSignificandBits) == 0,
|
||||
"sign bit shouldn't overlap significand bits");
|
||||
static_assert((Base::kExponentBits & Base::kSignificandBits) == 0,
|
||||
"exponent bits shouldn't overlap significand bits");
|
||||
|
||||
static_assert((Base::kSignBit | Base::kExponentBits | Base::kSignificandBits) ==
|
||||
~Bits(0),
|
||||
"all bits accounted for");
|
||||
|
||||
/*
|
||||
* These implementations assume float/double are 32/64-bit single/double
|
||||
* format number types compatible with the IEEE-754 standard. C++ don't
|
||||
* require this to be the case. But we required this in implementations of
|
||||
* these algorithms that preceded this header, so we shouldn't break anything
|
||||
* if we keep doing so.
|
||||
*/
|
||||
static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
|
||||
};
|
||||
|
||||
/** Determines whether a float/double is NaN. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsNaN(T aValue)
|
||||
{
|
||||
/*
|
||||
* A float/double is NaN if all exponent bits are 1 and the significand
|
||||
* contains at least one non-zero bit.
|
||||
*/
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
return (BitwiseCast<Bits>(aValue) & Traits::kExponentBits) == Traits::kExponentBits &&
|
||||
(BitwiseCast<Bits>(aValue) & Traits::kSignificandBits) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a float/double is +Infinity or -Infinity. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsInfinite(T aValue)
|
||||
{
|
||||
/* Infinities have all exponent bits set to 1 and an all-0 significand. */
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
Bits bits = BitwiseCast<Bits>(aValue);
|
||||
return (bits & ~Traits::kSignBit) == Traits::kExponentBits;
|
||||
}
|
||||
|
||||
/** Determines whether a float/double is not NaN or infinite. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsFinite(T aValue)
|
||||
{
|
||||
/*
|
||||
* NaN and Infinities are the only non-finite floats/doubles, and both have
|
||||
* all exponent bits set to 1.
|
||||
*/
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
Bits bits = BitwiseCast<Bits>(aValue);
|
||||
return (bits & Traits::kExponentBits) != Traits::kExponentBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a float/double is negative or -0. It is an error
|
||||
* to call this method on a float/double which is NaN.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsNegative(T aValue)
|
||||
{
|
||||
MOZ_ASSERT(!IsNaN(aValue), "NaN does not have a sign");
|
||||
|
||||
/* The sign bit is set if the double is negative. */
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
Bits bits = BitwiseCast<Bits>(aValue);
|
||||
return (bits & Traits::kSignBit) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a float/double represents -0. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsNegativeZero(T aValue)
|
||||
{
|
||||
/* Only the sign bit is set if the value is -0. */
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
Bits bits = BitwiseCast<Bits>(aValue);
|
||||
return bits == Traits::kSignBit;
|
||||
}
|
||||
|
||||
/** Determines wether a float/double represents +0. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsPositiveZero(T aValue)
|
||||
{
|
||||
/* All bits are zero if the value is +0. */
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
Bits bits = BitwiseCast<Bits>(aValue);
|
||||
return bits == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 if a float/double is NaN or infinite;
|
||||
* otherwise, the float/double is returned.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE T
|
||||
ToZeroIfNonfinite(T aValue)
|
||||
{
|
||||
return IsFinite(aValue) ? aValue : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exponent portion of the float/double.
|
||||
*
|
||||
* Zero is not special-cased, so ExponentComponent(0.0) is
|
||||
* -int_fast16_t(Traits::kExponentBias).
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE int_fast16_t
|
||||
ExponentComponent(T aValue)
|
||||
{
|
||||
/*
|
||||
* The exponent component of a float/double is an unsigned number, biased
|
||||
* from its actual value. Subtract the bias to retrieve the actual exponent.
|
||||
*/
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
Bits bits = BitwiseCast<Bits>(aValue);
|
||||
return int_fast16_t((bits & Traits::kExponentBits) >> Traits::kExponentShift) -
|
||||
int_fast16_t(Traits::kExponentBias);
|
||||
}
|
||||
|
||||
/** Returns +Infinity. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE T
|
||||
PositiveInfinity()
|
||||
{
|
||||
/*
|
||||
* Positive infinity has all exponent bits set, sign bit set to 0, and no
|
||||
* significand.
|
||||
*/
|
||||
typedef FloatingPoint<T> Traits;
|
||||
return BitwiseCast<T>(Traits::kExponentBits);
|
||||
}
|
||||
|
||||
/** Returns -Infinity. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE T
|
||||
NegativeInfinity()
|
||||
{
|
||||
/*
|
||||
* Negative infinity has all exponent bits set, sign bit set to 1, and no
|
||||
* significand.
|
||||
*/
|
||||
typedef FloatingPoint<T> Traits;
|
||||
return BitwiseCast<T>(Traits::kSignBit | Traits::kExponentBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the bit pattern for a NaN with the specified sign bit and
|
||||
* significand bits.
|
||||
*/
|
||||
template<typename T,
|
||||
int SignBit,
|
||||
typename FloatingPoint<T>::Bits Significand>
|
||||
struct SpecificNaNBits
|
||||
{
|
||||
using Traits = FloatingPoint<T>;
|
||||
|
||||
static_assert(SignBit == 0 || SignBit == 1, "bad sign bit");
|
||||
static_assert((Significand & ~Traits::kSignificandBits) == 0,
|
||||
"significand must only have significand bits set");
|
||||
static_assert(Significand & Traits::kSignificandBits,
|
||||
"significand must be nonzero");
|
||||
|
||||
static constexpr typename Traits::Bits value =
|
||||
(SignBit * Traits::kSignBit) | Traits::kExponentBits | Significand;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a NaN value with the specified sign bit and significand bits.
|
||||
*
|
||||
* There is also a variant that returns the value directly. In most cases, the
|
||||
* two variants should be identical. However, in the specific case of x86
|
||||
* chips, the behavior differs: returning floating-point values directly is done
|
||||
* through the x87 stack, and x87 loads and stores turn signaling NaNs into
|
||||
* quiet NaNs... silently. Returning floating-point values via outparam,
|
||||
* however, is done entirely within the SSE registers when SSE2 floating-point
|
||||
* is enabled in the compiler, which has semantics-preserving behavior you would
|
||||
* expect.
|
||||
*
|
||||
* If preserving the distinction between signaling NaNs and quiet NaNs is
|
||||
* important to you, you should use the outparam version. In all other cases,
|
||||
* you should use the direct return version.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand, T* result)
|
||||
{
|
||||
typedef FloatingPoint<T> Traits;
|
||||
MOZ_ASSERT(signbit == 0 || signbit == 1);
|
||||
MOZ_ASSERT((significand & ~Traits::kSignificandBits) == 0);
|
||||
MOZ_ASSERT(significand & Traits::kSignificandBits);
|
||||
|
||||
BitwiseCast<T>((signbit ? Traits::kSignBit : 0) |
|
||||
Traits::kExponentBits |
|
||||
significand,
|
||||
result);
|
||||
MOZ_ASSERT(IsNaN(*result));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE T
|
||||
SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand)
|
||||
{
|
||||
T t;
|
||||
SpecificNaN(signbit, significand, &t);
|
||||
return t;
|
||||
}
|
||||
|
||||
/** Computes the smallest non-zero positive float/double value. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE T
|
||||
MinNumberValue()
|
||||
{
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
return BitwiseCast<T>(Bits(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* If aValue is equal to some int32_t value, set *aInt32 to that value and
|
||||
* return true; otherwise return false.
|
||||
*
|
||||
* Note that negative zero is "equal" to zero here. To test whether a value can
|
||||
* be losslessly converted to int32_t and back, use NumberIsInt32 instead.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
NumberEqualsInt32(T aValue, int32_t* aInt32)
|
||||
{
|
||||
/*
|
||||
* XXX Casting a floating-point value that doesn't truncate to int32_t, to
|
||||
* int32_t, induces undefined behavior. We should definitely fix this
|
||||
* (bug 744965), but as apparently it "works" in practice, it's not a
|
||||
* pressing concern now.
|
||||
*/
|
||||
return aValue == (*aInt32 = int32_t(aValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* If d can be converted to int32_t and back to an identical double value,
|
||||
* set *aInt32 to that value and return true; otherwise return false.
|
||||
*
|
||||
* The difference between this and NumberEqualsInt32 is that this method returns
|
||||
* false for negative zero.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
NumberIsInt32(T aValue, int32_t* aInt32)
|
||||
{
|
||||
return !IsNegativeZero(aValue) && NumberEqualsInt32(aValue, aInt32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a NaN value. Do not use this method if you depend upon a particular
|
||||
* NaN value being returned.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE T
|
||||
UnspecifiedNaN()
|
||||
{
|
||||
/*
|
||||
* If we can use any quiet NaN, we might as well use the all-ones NaN,
|
||||
* since it's cheap to materialize on common platforms (such as x64, where
|
||||
* this value can be represented in a 32-bit signed immediate field, allowing
|
||||
* it to be stored to memory in a single instruction).
|
||||
*/
|
||||
typedef FloatingPoint<T> Traits;
|
||||
return SpecificNaN<T>(1, Traits::kSignificandBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two doubles for equality, *without* equating -0 to +0, and equating
|
||||
* any NaN value to any other NaN value. (The normal equality operators equate
|
||||
* -0 with +0, and they equate NaN to no other value.)
|
||||
*/
|
||||
template<typename T>
|
||||
static inline bool
|
||||
NumbersAreIdentical(T aValue1, T aValue2)
|
||||
{
|
||||
typedef FloatingPoint<T> Traits;
|
||||
typedef typename Traits::Bits Bits;
|
||||
if (IsNaN(aValue1)) {
|
||||
return IsNaN(aValue2);
|
||||
}
|
||||
return BitwiseCast<Bits>(aValue1) == BitwiseCast<Bits>(aValue2);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct FuzzyEqualsEpsilon;
|
||||
|
||||
template<>
|
||||
struct FuzzyEqualsEpsilon<float>
|
||||
{
|
||||
// A number near 1e-5 that is exactly representable in a float.
|
||||
static float value() { return 1.0f / (1 << 17); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FuzzyEqualsEpsilon<double>
|
||||
{
|
||||
// A number near 1e-12 that is exactly representable in a double.
|
||||
static double value() { return 1.0 / (1LL << 40); }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Compare two floating point values for equality, modulo rounding error. That
|
||||
* is, the two values are considered equal if they are both not NaN and if they
|
||||
* are less than or equal to aEpsilon apart. The default value of aEpsilon is
|
||||
* near 1e-5.
|
||||
*
|
||||
* For most scenarios you will want to use FuzzyEqualsMultiplicative instead,
|
||||
* as it is more reasonable over the entire range of floating point numbers.
|
||||
* This additive version should only be used if you know the range of the
|
||||
* numbers you are dealing with is bounded and stays around the same order of
|
||||
* magnitude.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
FuzzyEqualsAdditive(T aValue1, T aValue2,
|
||||
T aEpsilon = detail::FuzzyEqualsEpsilon<T>::value())
|
||||
{
|
||||
static_assert(IsFloatingPoint<T>::value, "floating point type required");
|
||||
return Abs(aValue1 - aValue2) <= aEpsilon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two floating point values for equality, allowing for rounding error
|
||||
* relative to the magnitude of the values. That is, the two values are
|
||||
* considered equal if they are both not NaN and they are less than or equal to
|
||||
* some aEpsilon apart, where the aEpsilon is scaled by the smaller of the two
|
||||
* argument values.
|
||||
*
|
||||
* In most cases you will want to use this rather than FuzzyEqualsAdditive, as
|
||||
* this function effectively masks out differences in the bottom few bits of
|
||||
* the floating point numbers being compared, regardless of what order of
|
||||
* magnitude those numbers are at.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
FuzzyEqualsMultiplicative(T aValue1, T aValue2,
|
||||
T aEpsilon = detail::FuzzyEqualsEpsilon<T>::value())
|
||||
{
|
||||
static_assert(IsFloatingPoint<T>::value, "floating point type required");
|
||||
// can't use std::min because of bug 965340
|
||||
T smaller = Abs(aValue1) < Abs(aValue2) ? Abs(aValue1) : Abs(aValue2);
|
||||
return Abs(aValue1 - aValue2) <= aEpsilon * smaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given value can be losslessly represented as an IEEE-754
|
||||
* single format number, false otherwise. All NaN values are considered
|
||||
* representable (notwithstanding that the exact bit pattern of a double format
|
||||
* NaN value can't be exactly represented in single format).
|
||||
*
|
||||
* This function isn't inlined to avoid buggy optimizations by MSVC.
|
||||
*/
|
||||
MOZ_MUST_USE
|
||||
extern MFBT_API bool
|
||||
IsFloat32Representable(double aFloat32);
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_FloatingPoint_h */
|
||||
223
cocos2d-x/external/win32/include/spidermonkey/mozilla/Function.h
vendored
Executable file
223
cocos2d-x/external/win32/include/spidermonkey/mozilla/Function.h
vendored
Executable file
@@ -0,0 +1,223 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A type-erased callable wrapper. */
|
||||
|
||||
#ifndef mozilla_Function_h
|
||||
#define mozilla_Function_h
|
||||
|
||||
#include "mozilla/Attributes.h" // for MOZ_IMPLICIT
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
// |function<Signature>| is a wrapper that can hold any type of callable
|
||||
// object that can be invoked in a way that's compatible with |Signature|.
|
||||
// The standard "type erasure" technique is used to avoid the type of the
|
||||
// wrapper depending on the concrete type of the wrapped callable.
|
||||
//
|
||||
// Supported callable types include non-member functions, static member
|
||||
// functions, and function objects (that is to say, objects with an overloaded
|
||||
// call operator; this includes C++11 lambdas). Member functions aren't
|
||||
// directly supported; they first need to be wrapped into a function object
|
||||
// using |std::mem_fn()| or an equivalent.
|
||||
//
|
||||
// |Signature| is a type of the form |ReturnType(Arguments...)|. Syntactically,
|
||||
// this is a function type; it's not used in any way other than serving as a
|
||||
// vehicle to encode the return and argument types into a single type.
|
||||
//
|
||||
// |function| is default-constructible. A default-constructed instance is
|
||||
// considered "empty". Invoking an empty instance is undefined behaviour.
|
||||
// An empty instance can be populated with a callable by assigning to it.
|
||||
//
|
||||
// This class is intended to provide functionality similar to the C++11
|
||||
// standard library class |std::function|.
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename ReturnType, typename... Arguments>
|
||||
class FunctionImplBase : public mozilla::RefCounted<FunctionImplBase<ReturnType, Arguments...>>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(FunctionImplBase)
|
||||
|
||||
virtual ~FunctionImplBase() {}
|
||||
virtual ReturnType call(Arguments... aArguments) = 0;
|
||||
};
|
||||
|
||||
// Normal Callable Object.
|
||||
template <typename Callable, typename ReturnType, typename... Arguments>
|
||||
class FunctionImpl : public FunctionImplBase<ReturnType, Arguments...>
|
||||
{
|
||||
public:
|
||||
explicit FunctionImpl(const Callable& aCallable)
|
||||
: mCallable(aCallable) {}
|
||||
|
||||
ReturnType call(Arguments... aArguments) override
|
||||
{
|
||||
return mCallable(Forward<Arguments>(aArguments)...);
|
||||
}
|
||||
private:
|
||||
Callable mCallable;
|
||||
};
|
||||
|
||||
// Base class for passing pointer to member function.
|
||||
template <typename Callable, typename ReturnType, typename... Arguments>
|
||||
class MemberFunctionImplBase : public FunctionImplBase<ReturnType, Arguments...>
|
||||
{
|
||||
public:
|
||||
explicit MemberFunctionImplBase(const Callable& aCallable)
|
||||
: mCallable(aCallable) {}
|
||||
|
||||
ReturnType call(Arguments... aArguments) override
|
||||
{
|
||||
return callInternal(Forward<Arguments>(aArguments)...);
|
||||
}
|
||||
private:
|
||||
template<typename ThisType, typename... Args>
|
||||
ReturnType callInternal(ThisType* aThis, Args&&... aArguments)
|
||||
{
|
||||
return (aThis->*mCallable)(Forward<Args>(aArguments)...);
|
||||
}
|
||||
|
||||
template<typename ThisType, typename... Args>
|
||||
ReturnType callInternal(ThisType&& aThis, Args&&... aArguments)
|
||||
{
|
||||
return (aThis.*mCallable)(Forward<Args>(aArguments)...);
|
||||
}
|
||||
Callable mCallable;
|
||||
};
|
||||
|
||||
// For non-const member function specialization of FunctionImpl.
|
||||
template <typename ThisType, typename... Args, typename ReturnType, typename... Arguments>
|
||||
class FunctionImpl<ReturnType(ThisType::*)(Args...),
|
||||
ReturnType, Arguments...>
|
||||
: public MemberFunctionImplBase<ReturnType(ThisType::*)(Args...),
|
||||
ReturnType, Arguments...>
|
||||
{
|
||||
public:
|
||||
explicit FunctionImpl(ReturnType(ThisType::*aMemberFunc)(Args...))
|
||||
: MemberFunctionImplBase<ReturnType(ThisType::*)(Args...),
|
||||
ReturnType, Arguments...>(aMemberFunc)
|
||||
{}
|
||||
};
|
||||
|
||||
// For const member function specialization of FunctionImpl.
|
||||
template <typename ThisType, typename... Args, typename ReturnType, typename... Arguments>
|
||||
class FunctionImpl<ReturnType(ThisType::*)(Args...) const,
|
||||
ReturnType, Arguments...>
|
||||
: public MemberFunctionImplBase<ReturnType(ThisType::*)(Args...) const,
|
||||
ReturnType, Arguments...>
|
||||
{
|
||||
public:
|
||||
explicit FunctionImpl(ReturnType(ThisType::*aConstMemberFunc)(Args...) const)
|
||||
: MemberFunctionImplBase<ReturnType(ThisType::*)(Args...) const,
|
||||
ReturnType, Arguments...>(aConstMemberFunc)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// The primary template is never defined. As |Signature| is required to be
|
||||
// of the form |ReturnType(Arguments...)|, we only define a partial
|
||||
// specialization that matches this form. This allows us to use |ReturnType|
|
||||
// and |Arguments| in the definition of the specialization without having to
|
||||
// introspect |Signature|.
|
||||
template<typename Signature>
|
||||
class function;
|
||||
|
||||
template<typename ReturnType, typename... Arguments>
|
||||
class function<ReturnType(Arguments...)>
|
||||
{
|
||||
public:
|
||||
function() {}
|
||||
|
||||
// This constructor is implicit to match the interface of |std::function|.
|
||||
template <typename Callable>
|
||||
MOZ_IMPLICIT function(const Callable& aCallable)
|
||||
: mImpl(new detail::FunctionImpl<Callable, ReturnType, Arguments...>(aCallable))
|
||||
{}
|
||||
MOZ_IMPLICIT function(const function& aFunction)
|
||||
: mImpl(aFunction.mImpl)
|
||||
{}
|
||||
MOZ_IMPLICIT function(decltype(nullptr))
|
||||
{}
|
||||
|
||||
// Move constructor and move assingment operator.
|
||||
// These should be generated automatically, but MSVC doesn't do that yet.
|
||||
function(function&& aOther) : mImpl(Move(aOther.mImpl)) {}
|
||||
function& operator=(function&& aOther) {
|
||||
mImpl = Move(aOther.mImpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Callable>
|
||||
function& operator=(const Callable& aCallable)
|
||||
{
|
||||
mImpl = new detail::FunctionImpl<Callable, ReturnType, Arguments...>(aCallable);
|
||||
return *this;
|
||||
}
|
||||
function& operator=(const function& aFunction)
|
||||
{
|
||||
mImpl = aFunction.mImpl;
|
||||
return *this;
|
||||
}
|
||||
function& operator=(decltype(nullptr))
|
||||
{
|
||||
mImpl = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
ReturnType operator()(Args&&... aArguments) const
|
||||
{
|
||||
MOZ_ASSERT(mImpl);
|
||||
return mImpl->call(Forward<Args>(aArguments)...);
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return bool(mImpl);
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO: Consider implementing a small object optimization.
|
||||
RefPtr<detail::FunctionImplBase<ReturnType, Arguments...>> mImpl;
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
bool
|
||||
operator==(const function<Signature>& aX, decltype(nullptr))
|
||||
{
|
||||
return !aX;
|
||||
}
|
||||
|
||||
template<typename Signature>
|
||||
bool
|
||||
operator==(decltype(nullptr), const function<Signature>& aX)
|
||||
{
|
||||
return !aX;
|
||||
}
|
||||
|
||||
template<typename Signature>
|
||||
bool
|
||||
operator!=(const function<Signature>& aX, decltype(nullptr))
|
||||
{
|
||||
return bool(aX);
|
||||
}
|
||||
|
||||
template<typename Signature>
|
||||
bool
|
||||
operator!=(decltype(nullptr), const function<Signature>& aX)
|
||||
{
|
||||
return bool(aX);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Function_h */
|
||||
167
cocos2d-x/external/win32/include/spidermonkey/mozilla/GuardObjects.h
vendored
Executable file
167
cocos2d-x/external/win32/include/spidermonkey/mozilla/GuardObjects.h
vendored
Executable file
@@ -0,0 +1,167 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implementation of macros to ensure correct use of RAII Auto* objects. */
|
||||
|
||||
#ifndef mozilla_GuardObjects_h
|
||||
#define mozilla_GuardObjects_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/**
|
||||
* A custom define is used rather than |mozPoisonValue()| due to cascading
|
||||
* build failures relating to how mfbt is linked on different operating
|
||||
* systems. See bug 1160253.
|
||||
*/
|
||||
#define MOZ_POISON uintptr_t(-1)
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* The following classes are designed to cause assertions to detect
|
||||
* inadvertent use of guard objects as temporaries. In other words,
|
||||
* when we have a guard object whose only purpose is its constructor and
|
||||
* destructor (and is never otherwise referenced), the intended use
|
||||
* might be:
|
||||
*
|
||||
* AutoRestore savePainting(mIsPainting);
|
||||
*
|
||||
* but is is easy to accidentally write:
|
||||
*
|
||||
* AutoRestore(mIsPainting);
|
||||
*
|
||||
* which compiles just fine, but runs the destructor well before the
|
||||
* intended time.
|
||||
*
|
||||
* They work by adding (#ifdef DEBUG) an additional parameter to the
|
||||
* guard object's constructor, with a default value, so that users of
|
||||
* the guard object's API do not need to do anything. The default value
|
||||
* of this parameter is a temporary object. C++ (ISO/IEC 14882:1998),
|
||||
* section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
|
||||
* guarantee that temporaries are destroyed in the reverse of their
|
||||
* construction order, but I actually can't find a statement that that
|
||||
* is true in the general case (beyond the two specific cases mentioned
|
||||
* there). However, it seems to be true.
|
||||
*
|
||||
* These classes are intended to be used only via the macros immediately
|
||||
* below them:
|
||||
*
|
||||
* MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
|
||||
* variable, and should be put where a declaration of a private
|
||||
* member variable would be placed.
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
|
||||
* parameters to each constructor of the guard object; it declares
|
||||
* (ifdef DEBUG) an additional parameter. (But use the *_ONLY_PARAM
|
||||
* variant for constructors that take no other parameters.)
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL should likewise be used in
|
||||
* the implementation of such constructors when they are not inline.
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT should be used in
|
||||
* the implementation of such constructors to pass the parameter to
|
||||
* a base class that also uses these macros
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
|
||||
* constructor. It uses the parameter declared by
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM.
|
||||
*
|
||||
* For more details, and examples of using these macros, see
|
||||
* https://developer.mozilla.org/en/Using_RAII_classes_in_Mozilla
|
||||
*/
|
||||
class GuardObjectNotifier
|
||||
{
|
||||
private:
|
||||
bool* mStatementDone;
|
||||
|
||||
public:
|
||||
GuardObjectNotifier()
|
||||
: mStatementDone(reinterpret_cast<bool*>(MOZ_POISON))
|
||||
{
|
||||
}
|
||||
|
||||
~GuardObjectNotifier()
|
||||
{
|
||||
// Assert that the GuardObjectNotifier has been properly initialized by
|
||||
// using the |MOZ_GUARD_OBJECT_NOTIFIER_INIT| macro. A poison value is
|
||||
// used rather than a null check to appease static analyzers that were
|
||||
// (incorrectly) detecting null pointer dereferences.
|
||||
MOZ_ASSERT(mStatementDone != reinterpret_cast<bool*>(MOZ_POISON));
|
||||
*mStatementDone = true;
|
||||
}
|
||||
|
||||
void setStatementDone(bool* aStatementIsDone)
|
||||
{
|
||||
mStatementDone = aStatementIsDone;
|
||||
}
|
||||
};
|
||||
|
||||
class GuardObjectNotificationReceiver
|
||||
{
|
||||
private:
|
||||
bool mStatementDone;
|
||||
|
||||
public:
|
||||
GuardObjectNotificationReceiver() : mStatementDone(false) { }
|
||||
|
||||
~GuardObjectNotificationReceiver() {
|
||||
/*
|
||||
* Assert that the guard object was not used as a temporary. (Note that
|
||||
* this assert might also fire if init is not called because the guard
|
||||
* object's implementation is not using the above macros correctly.)
|
||||
*/
|
||||
MOZ_ASSERT(mStatementDone);
|
||||
}
|
||||
|
||||
void init(GuardObjectNotifier& aNotifier)
|
||||
{
|
||||
aNotifier.setStatementDone(&mStatementDone);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#undef MOZ_POISON
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef DEBUG
|
||||
# define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER \
|
||||
mozilla::detail::GuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM \
|
||||
, mozilla::detail::GuardObjectNotifier&& _notifier = \
|
||||
mozilla::detail::GuardObjectNotifier()
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM \
|
||||
mozilla::detail::GuardObjectNotifier&& _notifier = \
|
||||
mozilla::detail::GuardObjectNotifier()
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL \
|
||||
, mozilla::detail::GuardObjectNotifier&& _notifier
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL \
|
||||
mozilla::detail::GuardObjectNotifier&& _notifier
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT \
|
||||
, mozilla::Move(_notifier)
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT \
|
||||
mozilla::Move(_notifier)
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_INIT \
|
||||
do { _mCheckNotUsedAsTemporary.init(_notifier); } while (0)
|
||||
#else
|
||||
# define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_INIT do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_GuardObjects_h */
|
||||
389
cocos2d-x/external/win32/include/spidermonkey/mozilla/HashFunctions.h
vendored
Executable file
389
cocos2d-x/external/win32/include/spidermonkey/mozilla/HashFunctions.h
vendored
Executable file
@@ -0,0 +1,389 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Utilities for hashing. */
|
||||
|
||||
/*
|
||||
* This file exports functions for hashing data down to a 32-bit value,
|
||||
* including:
|
||||
*
|
||||
* - HashString Hash a char* or char16_t/wchar_t* of known or unknown
|
||||
* length.
|
||||
*
|
||||
* - HashBytes Hash a byte array of known length.
|
||||
*
|
||||
* - HashGeneric Hash one or more values. Currently, we support uint32_t,
|
||||
* types which can be implicitly cast to uint32_t, data
|
||||
* pointers, and function pointers.
|
||||
*
|
||||
* - AddToHash Add one or more values to the given hash. This supports the
|
||||
* same list of types as HashGeneric.
|
||||
*
|
||||
*
|
||||
* You can chain these functions together to hash complex objects. For example:
|
||||
*
|
||||
* class ComplexObject
|
||||
* {
|
||||
* char* mStr;
|
||||
* uint32_t mUint1, mUint2;
|
||||
* void (*mCallbackFn)();
|
||||
*
|
||||
* public:
|
||||
* uint32_t hash()
|
||||
* {
|
||||
* uint32_t hash = HashString(mStr);
|
||||
* hash = AddToHash(hash, mUint1, mUint2);
|
||||
* return AddToHash(hash, mCallbackFn);
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* If you want to hash an nsAString or nsACString, use the HashString functions
|
||||
* in nsHashKeys.h.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_HashFunctions_h
|
||||
#define mozilla_HashFunctions_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Char16.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* The golden ratio as a 32-bit fixed-point value.
|
||||
*/
|
||||
static const uint32_t kGoldenRatioU32 = 0x9E3779B9U;
|
||||
|
||||
inline uint32_t
|
||||
RotateBitsLeft32(uint32_t aValue, uint8_t aBits)
|
||||
{
|
||||
MOZ_ASSERT(aBits < 32);
|
||||
return (aValue << aBits) | (aValue >> (32 - aBits));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline uint32_t
|
||||
AddU32ToHash(uint32_t aHash, uint32_t aValue)
|
||||
{
|
||||
/*
|
||||
* This is the meat of all our hash routines. This hash function is not
|
||||
* particularly sophisticated, but it seems to work well for our mostly
|
||||
* plain-text inputs. Implementation notes follow.
|
||||
*
|
||||
* Our use of the golden ratio here is arbitrary; we could pick almost any
|
||||
* number which:
|
||||
*
|
||||
* * is odd (because otherwise, all our hash values will be even)
|
||||
*
|
||||
* * has a reasonably-even mix of 1's and 0's (consider the extreme case
|
||||
* where we multiply by 0x3 or 0xeffffff -- this will not produce good
|
||||
* mixing across all bits of the hash).
|
||||
*
|
||||
* The rotation length of 5 is also arbitrary, although an odd number is again
|
||||
* preferable so our hash explores the whole universe of possible rotations.
|
||||
*
|
||||
* Finally, we multiply by the golden ratio *after* xor'ing, not before.
|
||||
* Otherwise, if |aHash| is 0 (as it often is for the beginning of a
|
||||
* message), the expression
|
||||
*
|
||||
* (kGoldenRatioU32 * RotateBitsLeft(aHash, 5)) |xor| aValue
|
||||
*
|
||||
* evaluates to |aValue|.
|
||||
*
|
||||
* (Number-theoretic aside: Because any odd number |m| is relatively prime to
|
||||
* our modulus (2^32), the list
|
||||
*
|
||||
* [x * m (mod 2^32) for 0 <= x < 2^32]
|
||||
*
|
||||
* has no duplicate elements. This means that multiplying by |m| does not
|
||||
* cause us to skip any possible hash values.
|
||||
*
|
||||
* It's also nice if |m| has large-ish order mod 2^32 -- that is, if the
|
||||
* smallest k such that m^k == 1 (mod 2^32) is large -- so we can safely
|
||||
* multiply our hash value by |m| a few times without negating the
|
||||
* multiplicative effect. Our golden ratio constant has order 2^29, which is
|
||||
* more than enough for our purposes.)
|
||||
*/
|
||||
return kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* AddUintptrToHash takes sizeof(uintptr_t) as a template parameter.
|
||||
*/
|
||||
template<size_t PtrSize>
|
||||
inline uint32_t
|
||||
AddUintptrToHash(uint32_t aHash, uintptr_t aValue);
|
||||
|
||||
template<>
|
||||
inline uint32_t
|
||||
AddUintptrToHash<4>(uint32_t aHash, uintptr_t aValue)
|
||||
{
|
||||
return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint32_t
|
||||
AddUintptrToHash<8>(uint32_t aHash, uintptr_t aValue)
|
||||
{
|
||||
/*
|
||||
* The static cast to uint64_t below is necessary because this function
|
||||
* sometimes gets compiled on 32-bit platforms (yes, even though it's a
|
||||
* template and we never call this particular override in a 32-bit build). If
|
||||
* we do aValue >> 32 on a 32-bit machine, we're shifting a 32-bit uintptr_t
|
||||
* right 32 bits, and the compiler throws an error.
|
||||
*/
|
||||
uint32_t v1 = static_cast<uint32_t>(aValue);
|
||||
uint32_t v2 = static_cast<uint32_t>(static_cast<uint64_t>(aValue) >> 32);
|
||||
return AddU32ToHash(AddU32ToHash(aHash, v1), v2);
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/**
|
||||
* AddToHash takes a hash and some values and returns a new hash based on the
|
||||
* inputs.
|
||||
*
|
||||
* Currently, we support hashing uint32_t's, values which we can implicitly
|
||||
* convert to uint32_t, data pointers, and function pointers.
|
||||
*/
|
||||
template<typename A>
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
AddToHash(uint32_t aHash, A aA)
|
||||
{
|
||||
/*
|
||||
* Try to convert |A| to uint32_t implicitly. If this works, great. If not,
|
||||
* we'll error out.
|
||||
*/
|
||||
return detail::AddU32ToHash(aHash, aA);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
AddToHash(uint32_t aHash, A* aA)
|
||||
{
|
||||
/*
|
||||
* You might think this function should just take a void*. But then we'd only
|
||||
* catch data pointers and couldn't handle function pointers.
|
||||
*/
|
||||
|
||||
static_assert(sizeof(aA) == sizeof(uintptr_t), "Strange pointer!");
|
||||
|
||||
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA));
|
||||
}
|
||||
|
||||
template<>
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
AddToHash(uint32_t aHash, uintptr_t aA)
|
||||
{
|
||||
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, aA);
|
||||
}
|
||||
|
||||
template<typename A, typename... Args>
|
||||
MOZ_MUST_USE uint32_t
|
||||
AddToHash(uint32_t aHash, A aArg, Args... aArgs)
|
||||
{
|
||||
return AddToHash(AddToHash(aHash, aArg), aArgs...);
|
||||
}
|
||||
|
||||
/**
|
||||
* The HashGeneric class of functions let you hash one or more values.
|
||||
*
|
||||
* If you want to hash together two values x and y, calling HashGeneric(x, y) is
|
||||
* much better than calling AddToHash(x, y), because AddToHash(x, y) assumes
|
||||
* that x has already been hashed.
|
||||
*/
|
||||
template<typename... Args>
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashGeneric(Args... aArgs)
|
||||
{
|
||||
return AddToHash(0, aArgs...);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
uint32_t
|
||||
HashUntilZero(const T* aStr)
|
||||
{
|
||||
uint32_t hash = 0;
|
||||
for (T c; (c = *aStr); aStr++) {
|
||||
hash = AddToHash(hash, c);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
uint32_t
|
||||
HashKnownLength(const T* aStr, size_t aLength)
|
||||
{
|
||||
uint32_t hash = 0;
|
||||
for (size_t i = 0; i < aLength; i++) {
|
||||
hash = AddToHash(hash, aStr[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/**
|
||||
* The HashString overloads below do just what you'd expect.
|
||||
*
|
||||
* If you have the string's length, you might as well call the overload which
|
||||
* includes the length. It may be marginally faster.
|
||||
*/
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashString(const char* aStr)
|
||||
{
|
||||
return detail::HashUntilZero(reinterpret_cast<const unsigned char*>(aStr));
|
||||
}
|
||||
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashString(const char* aStr, size_t aLength)
|
||||
{
|
||||
return detail::HashKnownLength(reinterpret_cast<const unsigned char*>(aStr), aLength);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE
|
||||
inline uint32_t
|
||||
HashString(const unsigned char* aStr, size_t aLength)
|
||||
{
|
||||
return detail::HashKnownLength(aStr, aLength);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashString(const char16_t* aStr)
|
||||
{
|
||||
return detail::HashUntilZero(aStr);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashString(const char16_t* aStr, size_t aLength)
|
||||
{
|
||||
return detail::HashKnownLength(aStr, aLength);
|
||||
}
|
||||
|
||||
/*
|
||||
* On Windows, wchar_t is not the same as char16_t, even though it's
|
||||
* the same width!
|
||||
*/
|
||||
#ifdef WIN32
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashString(const wchar_t* aStr)
|
||||
{
|
||||
return detail::HashUntilZero(aStr);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE inline uint32_t
|
||||
HashString(const wchar_t* aStr, size_t aLength)
|
||||
{
|
||||
return detail::HashKnownLength(aStr, aLength);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Hash some number of bytes.
|
||||
*
|
||||
* This hash walks word-by-word, rather than byte-by-byte, so you won't get the
|
||||
* same result out of HashBytes as you would out of HashString.
|
||||
*/
|
||||
MOZ_MUST_USE extern MFBT_API uint32_t
|
||||
HashBytes(const void* bytes, size_t aLength);
|
||||
|
||||
/**
|
||||
* A pseudorandom function mapping 32-bit integers to 32-bit integers.
|
||||
*
|
||||
* This is for when you're feeding private data (like pointer values or credit
|
||||
* card numbers) to a non-crypto hash function (like HashBytes) and then using
|
||||
* the hash code for something that untrusted parties could observe (like a JS
|
||||
* Map). Plug in a HashCodeScrambler before that last step to avoid leaking the
|
||||
* private data.
|
||||
*
|
||||
* By itself, this does not prevent hash-flooding DoS attacks, because an
|
||||
* attacker can still generate many values with exactly equal hash codes by
|
||||
* attacking the non-crypto hash function alone. Equal hash codes will, of
|
||||
* course, still be equal however much you scramble them.
|
||||
*
|
||||
* The algorithm is SipHash-1-3. See <https://131002.net/siphash/>.
|
||||
*/
|
||||
class HashCodeScrambler
|
||||
{
|
||||
struct SipHasher;
|
||||
|
||||
uint64_t mK0, mK1;
|
||||
|
||||
public:
|
||||
/** Creates a new scrambler with the given 128-bit key. */
|
||||
constexpr HashCodeScrambler(uint64_t aK0, uint64_t aK1) : mK0(aK0), mK1(aK1) {}
|
||||
|
||||
/**
|
||||
* Scramble a hash code. Always produces the same result for the same
|
||||
* combination of key and hash code.
|
||||
*/
|
||||
uint32_t scramble(uint32_t aHashCode) const
|
||||
{
|
||||
SipHasher hasher(mK0, mK1);
|
||||
return uint32_t(hasher.sipHash(aHashCode));
|
||||
}
|
||||
|
||||
private:
|
||||
struct SipHasher
|
||||
{
|
||||
SipHasher(uint64_t aK0, uint64_t aK1)
|
||||
{
|
||||
// 1. Initialization.
|
||||
mV0 = aK0 ^ UINT64_C(0x736f6d6570736575);
|
||||
mV1 = aK1 ^ UINT64_C(0x646f72616e646f6d);
|
||||
mV2 = aK0 ^ UINT64_C(0x6c7967656e657261);
|
||||
mV3 = aK1 ^ UINT64_C(0x7465646279746573);
|
||||
}
|
||||
|
||||
uint64_t sipHash(uint64_t aM)
|
||||
{
|
||||
// 2. Compression.
|
||||
mV3 ^= aM;
|
||||
sipRound();
|
||||
mV0 ^= aM;
|
||||
|
||||
// 3. Finalization.
|
||||
mV2 ^= 0xff;
|
||||
for (int i = 0; i < 3; i++)
|
||||
sipRound();
|
||||
return mV0 ^ mV1 ^ mV2 ^ mV3;
|
||||
}
|
||||
|
||||
void sipRound()
|
||||
{
|
||||
mV0 += mV1;
|
||||
mV1 = RotateLeft(mV1, 13);
|
||||
mV1 ^= mV0;
|
||||
mV0 = RotateLeft(mV0, 32);
|
||||
mV2 += mV3;
|
||||
mV3 = RotateLeft(mV3, 16);
|
||||
mV3 ^= mV2;
|
||||
mV0 += mV3;
|
||||
mV3 = RotateLeft(mV3, 21);
|
||||
mV3 ^= mV0;
|
||||
mV2 += mV1;
|
||||
mV1 = RotateLeft(mV1, 17);
|
||||
mV1 ^= mV2;
|
||||
mV2 = RotateLeft(mV2, 32);
|
||||
}
|
||||
|
||||
uint64_t mV0, mV1, mV2, mV3;
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_HashFunctions_h */
|
||||
143
cocos2d-x/external/win32/include/spidermonkey/mozilla/IndexSequence.h
vendored
Executable file
143
cocos2d-x/external/win32/include/spidermonkey/mozilla/IndexSequence.h
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A utility for expanding a tuple into a variadic argument list.
|
||||
* Based on std::index_sequence. */
|
||||
|
||||
/**
|
||||
* Example usage:
|
||||
*
|
||||
* Problem:
|
||||
*
|
||||
* You have a variadic function Foo:
|
||||
*
|
||||
* template <typename... Args> void Foo(Args...);
|
||||
*
|
||||
* And a variadic function Bar, which contains a tuple:
|
||||
*
|
||||
* template <typename... Args>
|
||||
* void Bar() {
|
||||
* // ...
|
||||
* Tuple<Args...> t;
|
||||
* }
|
||||
*
|
||||
* And inside Bar, you want to call Foo with the elements of the tuple as
|
||||
* arguments to Foo.
|
||||
*
|
||||
* You want to write:
|
||||
*
|
||||
* Foo(Get<0>(t), Get<1>(t), ..., Get<N>(t))
|
||||
*
|
||||
* but you can't literally write that, because N is different for different
|
||||
* instantiations of Bar.
|
||||
*
|
||||
* Solution:
|
||||
*
|
||||
* Write a helper function which takes the tuple, and an index sequence
|
||||
* containing indices corresponding to the tuple indices.
|
||||
*
|
||||
* template <typename... Args, size_t... Indices>
|
||||
* void Helper(const Tuple<Args...>& t, IndexSequence<Indices>)
|
||||
* {
|
||||
* Foo(Get<Indices>(t)...);
|
||||
* }
|
||||
*
|
||||
* Assuming 'Indices...' are 0, 1, ..., N - 1, where N is the size of the
|
||||
* tuple, pack expansion will expand the pack 'Get<Indices>(t)...' to
|
||||
* 'Get<0>(t), Get<1>(t), ..., Get<N>(t)'.
|
||||
*
|
||||
* Finally, call the helper, creating the index sequence to pass in like so:
|
||||
*
|
||||
* template <typename... Args>
|
||||
* void Bar() {
|
||||
* // ...
|
||||
* Tuple<Args...> t;
|
||||
* Helper(t, typename IndexSequenceFor<Args...>::Type());
|
||||
* }
|
||||
*/
|
||||
|
||||
#ifndef mozilla_IndexSequence_h
|
||||
#define mozilla_IndexSequence_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Represents a compile-time sequence of integer indices.
|
||||
*/
|
||||
template<size_t... Indices>
|
||||
struct IndexSequence
|
||||
{
|
||||
static constexpr size_t Size() { return sizeof...(Indices); }
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Helpers used by MakeIndexSequence.
|
||||
|
||||
template<size_t... Indices>
|
||||
struct IndexTuple
|
||||
{
|
||||
typedef IndexTuple<Indices..., sizeof...(Indices)> Next;
|
||||
};
|
||||
|
||||
// Builds IndexTuple<0, 1, ..., N - 1>.
|
||||
template<size_t N>
|
||||
struct BuildIndexTuple
|
||||
{
|
||||
typedef typename BuildIndexTuple<N - 1>::Type::Next Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BuildIndexTuple<0>
|
||||
{
|
||||
typedef IndexTuple<> Type;
|
||||
};
|
||||
|
||||
template<size_t N, typename IndexTuple>
|
||||
struct MakeIndexSequenceImpl;
|
||||
|
||||
template<size_t N, size_t... Indices>
|
||||
struct MakeIndexSequenceImpl<N, IndexTuple<Indices...>>
|
||||
{
|
||||
typedef IndexSequence<Indices...> Type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* A utility for building an IndexSequence of consecutive indices.
|
||||
* MakeIndexSequence<N>::Type evaluates to IndexSequence<0, 1, .., N - 1>.
|
||||
* Note: unlike std::make_index_sequence, this is not an alias template
|
||||
* to work around bugs in MSVC 2013.
|
||||
*/
|
||||
template<size_t N>
|
||||
struct MakeIndexSequence
|
||||
{
|
||||
typedef typename detail::MakeIndexSequenceImpl<N,
|
||||
typename detail::BuildIndexTuple<N>::Type>::Type Type;
|
||||
};
|
||||
|
||||
/**
|
||||
* A utility for building an IndexSequence of consecutive indices
|
||||
* corresponding to a variadic argument list.
|
||||
* IndexSequenceFor<Types...> evaluates to IndexSequence<0, 1, ..., N - 1>
|
||||
* where N is the number of types in Types.
|
||||
* Note: unlike std::index_sequence_for, this is not an alias template
|
||||
* to work around bugs in MSVC 2013.
|
||||
*/
|
||||
template<typename... Types>
|
||||
struct IndexSequenceFor
|
||||
{
|
||||
typedef typename MakeIndexSequence<sizeof...(Types)>::Type Type;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_IndexSequence_h */
|
||||
52
cocos2d-x/external/win32/include/spidermonkey/mozilla/IntegerPrintfMacros.h
vendored
Executable file
52
cocos2d-x/external/win32/include/spidermonkey/mozilla/IntegerPrintfMacros.h
vendored
Executable file
@@ -0,0 +1,52 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implements the C99 <inttypes.h> interface. */
|
||||
|
||||
#ifndef mozilla_IntegerPrintfMacros_h_
|
||||
#define mozilla_IntegerPrintfMacros_h_
|
||||
|
||||
/*
|
||||
* These macros should not be used with the NSPR printf-like functions or their
|
||||
* users, e.g. mozilla/Logging.h. If you need to use NSPR's facilities, see the
|
||||
* comment on supported formats at the top of nsprpub/pr/include/prprf.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* scanf is a footgun: if the input number exceeds the bounds of the target
|
||||
* type, behavior is undefined (in the compiler sense: that is, this code
|
||||
* could overwrite your hard drive with zeroes):
|
||||
*
|
||||
* uint8_t u;
|
||||
* sscanf("256", "%" SCNu8, &u); // BAD
|
||||
*
|
||||
* For this reason, *never* use the SCN* macros provided by this header!
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
* Fix up Android's broken [u]intptr_t inttype macros. Android's PRI*PTR
|
||||
* macros are defined as "ld", but sizeof(long) is 8 and sizeof(intptr_t)
|
||||
* is 4 on 32-bit Android. TestTypeTraits.cpp asserts that these new macro
|
||||
* definitions match the actual type sizes seen at compile time.
|
||||
*/
|
||||
#if defined(ANDROID) && !defined(__LP64__)
|
||||
# undef PRIdPTR /* intptr_t */
|
||||
# define PRIdPTR "d" /* intptr_t */
|
||||
# undef PRIiPTR /* intptr_t */
|
||||
# define PRIiPTR "i" /* intptr_t */
|
||||
# undef PRIoPTR /* uintptr_t */
|
||||
# define PRIoPTR "o" /* uintptr_t */
|
||||
# undef PRIuPTR /* uintptr_t */
|
||||
# define PRIuPTR "u" /* uintptr_t */
|
||||
# undef PRIxPTR /* uintptr_t */
|
||||
# define PRIxPTR "x" /* uintptr_t */
|
||||
# undef PRIXPTR /* uintptr_t */
|
||||
# define PRIXPTR "X" /* uintptr_t */
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_IntegerPrintfMacros_h_ */
|
||||
181
cocos2d-x/external/win32/include/spidermonkey/mozilla/IntegerRange.h
vendored
Executable file
181
cocos2d-x/external/win32/include/spidermonkey/mozilla/IntegerRange.h
vendored
Executable file
@@ -0,0 +1,181 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Iterator over ranges of integers */
|
||||
|
||||
#ifndef mozilla_IntegerRange_h
|
||||
#define mozilla_IntegerRange_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ReverseIterator.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename IntTypeT>
|
||||
class IntegerIterator
|
||||
{
|
||||
public:
|
||||
template<typename IntType>
|
||||
explicit IntegerIterator(IntType aCurrent)
|
||||
: mCurrent(aCurrent) { }
|
||||
|
||||
template<typename IntType>
|
||||
explicit IntegerIterator(const IntegerIterator<IntType>& aOther)
|
||||
: mCurrent(aOther.mCurrent) { }
|
||||
|
||||
IntTypeT operator*() const { return mCurrent; }
|
||||
|
||||
/* Increment and decrement operators */
|
||||
|
||||
IntegerIterator& operator++() { ++mCurrent; return *this; }
|
||||
IntegerIterator& operator--() { --mCurrent; return *this; }
|
||||
IntegerIterator operator++(int) { auto ret = *this; ++mCurrent; return ret; }
|
||||
IntegerIterator operator--(int) { auto ret = *this; --mCurrent; return ret; }
|
||||
|
||||
/* Comparison operators */
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
friend bool operator==(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2);
|
||||
template<typename IntType1, typename IntType2>
|
||||
friend bool operator!=(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2);
|
||||
template<typename IntType1, typename IntType2>
|
||||
friend bool operator<(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2);
|
||||
template<typename IntType1, typename IntType2>
|
||||
friend bool operator<=(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2);
|
||||
template<typename IntType1, typename IntType2>
|
||||
friend bool operator>(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2);
|
||||
template<typename IntType1, typename IntType2>
|
||||
friend bool operator>=(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2);
|
||||
|
||||
private:
|
||||
IntTypeT mCurrent;
|
||||
};
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
bool operator==(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent == aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
bool operator!=(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent != aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
bool operator<(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent < aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
bool operator<=(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent <= aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
bool operator>(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent > aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
bool operator>=(const IntegerIterator<IntType1>& aIter1,
|
||||
const IntegerIterator<IntType2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent >= aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename IntTypeT>
|
||||
class IntegerRange
|
||||
{
|
||||
public:
|
||||
typedef IntegerIterator<IntTypeT> iterator;
|
||||
typedef IntegerIterator<IntTypeT> const_iterator;
|
||||
typedef ReverseIterator<IntegerIterator<IntTypeT>> reverse_iterator;
|
||||
typedef ReverseIterator<IntegerIterator<IntTypeT>> const_reverse_iterator;
|
||||
|
||||
template<typename IntType>
|
||||
explicit IntegerRange(IntType aEnd)
|
||||
: mBegin(0), mEnd(aEnd) { }
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
IntegerRange(IntType1 aBegin, IntType2 aEnd)
|
||||
: mBegin(aBegin), mEnd(aEnd) { }
|
||||
|
||||
iterator begin() const { return iterator(mBegin); }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() const { return iterator(mEnd); }
|
||||
const_iterator cend() const { return end(); }
|
||||
reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
reverse_iterator rend() const { return reverse_iterator(mBegin); }
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
|
||||
private:
|
||||
IntTypeT mBegin;
|
||||
IntTypeT mEnd;
|
||||
};
|
||||
|
||||
template<typename T, bool = IsUnsigned<T>::value>
|
||||
struct GeqZero
|
||||
{
|
||||
static bool check(T t) {
|
||||
return t >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct GeqZero<T, true>
|
||||
{
|
||||
static bool check(T t) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename IntType>
|
||||
detail::IntegerRange<IntType>
|
||||
MakeRange(IntType aEnd)
|
||||
{
|
||||
static_assert(IsIntegral<IntType>::value, "value must be integral");
|
||||
MOZ_ASSERT(detail::GeqZero<IntType>::check(aEnd),
|
||||
"Should never have negative value here");
|
||||
return detail::IntegerRange<IntType>(aEnd);
|
||||
}
|
||||
|
||||
template<typename IntType1, typename IntType2>
|
||||
detail::IntegerRange<IntType2>
|
||||
MakeRange(IntType1 aBegin, IntType2 aEnd)
|
||||
{
|
||||
static_assert(IsIntegral<IntType1>::value && IsIntegral<IntType2>::value,
|
||||
"values must both be integral");
|
||||
static_assert(IsSigned<IntType1>::value == IsSigned<IntType2>::value,
|
||||
"signed/unsigned mismatch");
|
||||
MOZ_ASSERT(aEnd >= aBegin, "End value should be larger than begin value");
|
||||
return detail::IntegerRange<IntType2>(aBegin, aEnd);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_IntegerRange_h
|
||||
143
cocos2d-x/external/win32/include/spidermonkey/mozilla/IntegerTypeTraits.h
vendored
Executable file
143
cocos2d-x/external/win32/include/spidermonkey/mozilla/IntegerTypeTraits.h
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Helpers to manipulate integer types that don't fit in TypeTraits.h */
|
||||
|
||||
#ifndef mozilla_IntegerTypeTraits_h
|
||||
#define mozilla_IntegerTypeTraits_h
|
||||
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* StdintTypeForSizeAndSignedness returns the stdint integer type
|
||||
* of given size (can be 1, 2, 4 or 8) and given signedness
|
||||
* (false means unsigned, true means signed).
|
||||
*/
|
||||
template<size_t Size, bool Signedness>
|
||||
struct StdintTypeForSizeAndSignedness;
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<1, true>
|
||||
{
|
||||
typedef int8_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<1, false>
|
||||
{
|
||||
typedef uint8_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<2, true>
|
||||
{
|
||||
typedef int16_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<2, false>
|
||||
{
|
||||
typedef uint16_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<4, true>
|
||||
{
|
||||
typedef int32_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<4, false>
|
||||
{
|
||||
typedef uint32_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<8, true>
|
||||
{
|
||||
typedef int64_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct StdintTypeForSizeAndSignedness<8, false>
|
||||
{
|
||||
typedef uint64_t Type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<size_t Size>
|
||||
struct UnsignedStdintTypeForSize
|
||||
: detail::StdintTypeForSizeAndSignedness<Size, false>
|
||||
{};
|
||||
|
||||
template<size_t Size>
|
||||
struct SignedStdintTypeForSize
|
||||
: detail::StdintTypeForSizeAndSignedness<Size, true>
|
||||
{};
|
||||
|
||||
template<typename IntegerType>
|
||||
struct PositionOfSignBit
|
||||
{
|
||||
static_assert(IsIntegral<IntegerType>::value,
|
||||
"PositionOfSignBit is only for integral types");
|
||||
// 8 here should be CHAR_BIT from limits.h, but the world has moved on.
|
||||
static const size_t value = 8 * sizeof(IntegerType) - 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* MinValue returns the minimum value of the given integer type as a
|
||||
* compile-time constant, which std::numeric_limits<IntegerType>::min()
|
||||
* cannot do in c++98.
|
||||
*/
|
||||
template<typename IntegerType>
|
||||
struct MinValue
|
||||
{
|
||||
private:
|
||||
static_assert(IsIntegral<IntegerType>::value,
|
||||
"MinValue is only for integral types");
|
||||
|
||||
typedef typename MakeUnsigned<IntegerType>::Type UnsignedIntegerType;
|
||||
static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;
|
||||
|
||||
public:
|
||||
// Bitwise ops may return a larger type, that's why we cast explicitly.
|
||||
// In C++, left bit shifts on signed values is undefined by the standard
|
||||
// unless the shifted value is representable.
|
||||
// Notice that signed-to-unsigned conversions are always well-defined in
|
||||
// the standard as the value congruent to 2**n, as expected. By contrast,
|
||||
// unsigned-to-signed is only well-defined if the value is representable.
|
||||
static const IntegerType value =
|
||||
IsSigned<IntegerType>::value
|
||||
? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
|
||||
: IntegerType(0);
|
||||
};
|
||||
|
||||
/**
|
||||
* MaxValue returns the maximum value of the given integer type as a
|
||||
* compile-time constant, which std::numeric_limits<IntegerType>::max()
|
||||
* cannot do in c++98.
|
||||
*/
|
||||
template<typename IntegerType>
|
||||
struct MaxValue
|
||||
{
|
||||
static_assert(IsIntegral<IntegerType>::value,
|
||||
"MaxValue is only for integral types");
|
||||
|
||||
// Tricksy, but covered by the CheckedInt unit test.
|
||||
// Relies on the type of MinValue<IntegerType>::value
|
||||
// being IntegerType.
|
||||
static const IntegerType value = ~MinValue<IntegerType>::value;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_IntegerTypeTraits_h
|
||||
460
cocos2d-x/external/win32/include/spidermonkey/mozilla/JSONWriter.h
vendored
Executable file
460
cocos2d-x/external/win32/include/spidermonkey/mozilla/JSONWriter.h
vendored
Executable file
@@ -0,0 +1,460 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A JSON pretty-printer class. */
|
||||
|
||||
// A typical JSON-writing library requires you to first build up a data
|
||||
// structure that represents a JSON object and then serialize it (to file, or
|
||||
// somewhere else). This approach makes for a clean API, but building the data
|
||||
// structure takes up memory. Sometimes that isn't desirable, such as when the
|
||||
// JSON data is produced for memory reporting.
|
||||
//
|
||||
// The JSONWriter class instead allows JSON data to be written out
|
||||
// incrementally without building up large data structures.
|
||||
//
|
||||
// The API is slightly uglier than you would see in a typical JSON-writing
|
||||
// library, but still fairly easy to use. It's possible to generate invalid
|
||||
// JSON with JSONWriter, but typically the most basic testing will identify any
|
||||
// such problems.
|
||||
//
|
||||
// Similarly, there are no RAII facilities for automatically closing objects
|
||||
// and arrays. These would be nice if you are generating all your code within
|
||||
// nested functions, but in other cases you'd have to maintain an explicit
|
||||
// stack of RAII objects and manually unwind it, which is no better than just
|
||||
// calling "end" functions. Furthermore, the consequences of forgetting to
|
||||
// close an object or array are obvious and, again, will be identified via
|
||||
// basic testing, unlike other cases where RAII is typically used (e.g. smart
|
||||
// pointers) and the consequences of defects are more subtle.
|
||||
//
|
||||
// Importantly, the class does solve the two hard problems of JSON
|
||||
// pretty-printing, which are (a) correctly escaping strings, and (b) adding
|
||||
// appropriate indentation and commas between items.
|
||||
//
|
||||
// By default, every property is placed on its own line. However, it is
|
||||
// possible to request that objects and arrays be placed entirely on a single
|
||||
// line, which can reduce output size significantly in some cases.
|
||||
//
|
||||
// Strings used (for property names and string property values) are |const
|
||||
// char*| throughout, and can be ASCII or UTF-8.
|
||||
//
|
||||
// EXAMPLE
|
||||
// -------
|
||||
// Assume that |MyWriteFunc| is a class that implements |JSONWriteFunc|. The
|
||||
// following code:
|
||||
//
|
||||
// JSONWriter w(MakeUnique<MyWriteFunc>());
|
||||
// w.Start();
|
||||
// {
|
||||
// w.NullProperty("null");
|
||||
// w.BoolProperty("bool", true);
|
||||
// w.IntProperty("int", 1);
|
||||
// w.StartArrayProperty("array");
|
||||
// {
|
||||
// w.StringElement("string");
|
||||
// w.StartObjectElement();
|
||||
// {
|
||||
// w.DoubleProperty("double", 3.4);
|
||||
// w.StartArrayProperty("single-line array", w.SingleLineStyle);
|
||||
// {
|
||||
// w.IntElement(1);
|
||||
// w.StartObjectElement(); // SingleLineStyle is inherited from
|
||||
// w.EndObjectElement(); // above for this collection
|
||||
// }
|
||||
// w.EndArray();
|
||||
// }
|
||||
// w.EndObjectElement();
|
||||
// }
|
||||
// w.EndArrayProperty();
|
||||
// }
|
||||
// w.End();
|
||||
//
|
||||
// will produce pretty-printed output for the following JSON object:
|
||||
//
|
||||
// {
|
||||
// "null": null,
|
||||
// "bool": true,
|
||||
// "int": 1,
|
||||
// "array": [
|
||||
// "string",
|
||||
// {
|
||||
// "double": 3.4,
|
||||
// "single-line array": [1, {}]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
// The nesting in the example code is obviously optional, but can aid
|
||||
// readability.
|
||||
|
||||
#ifndef mozilla_JSONWriter_h
|
||||
#define mozilla_JSONWriter_h
|
||||
|
||||
#include "mozilla/double-conversion.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// A quasi-functor for JSONWriter. We don't use a true functor because that
|
||||
// requires templatizing JSONWriter, and the templatization seeps to lots of
|
||||
// places we don't want it to.
|
||||
class JSONWriteFunc
|
||||
{
|
||||
public:
|
||||
virtual void Write(const char* aStr) = 0;
|
||||
virtual ~JSONWriteFunc() {}
|
||||
};
|
||||
|
||||
// Ideally this would be within |EscapedString| but when compiling with GCC
|
||||
// on Linux that caused link errors, whereas this formulation didn't.
|
||||
namespace detail {
|
||||
extern MFBT_DATA const char gTwoCharEscapes[256];
|
||||
} // namespace detail
|
||||
|
||||
class JSONWriter
|
||||
{
|
||||
// From http://www.ietf.org/rfc/rfc4627.txt:
|
||||
//
|
||||
// "All Unicode characters may be placed within the quotation marks except
|
||||
// for the characters that must be escaped: quotation mark, reverse
|
||||
// solidus, and the control characters (U+0000 through U+001F)."
|
||||
//
|
||||
// This implementation uses two-char escape sequences where possible, namely:
|
||||
//
|
||||
// \", \\, \b, \f, \n, \r, \t
|
||||
//
|
||||
// All control characters not in the above list are represented with a
|
||||
// six-char escape sequence, e.g. '\u000b' (a.k.a. '\v').
|
||||
//
|
||||
class EscapedString
|
||||
{
|
||||
// Only one of |mUnownedStr| and |mOwnedStr| are ever non-null. |mIsOwned|
|
||||
// indicates which one is in use. They're not within a union because that
|
||||
// wouldn't work with UniquePtr.
|
||||
bool mIsOwned;
|
||||
const char* mUnownedStr;
|
||||
UniquePtr<char[]> mOwnedStr;
|
||||
|
||||
void SanityCheck() const
|
||||
{
|
||||
MOZ_ASSERT_IF( mIsOwned, mOwnedStr.get() && !mUnownedStr);
|
||||
MOZ_ASSERT_IF(!mIsOwned, !mOwnedStr.get() && mUnownedStr);
|
||||
}
|
||||
|
||||
static char hexDigitToAsciiChar(uint8_t u)
|
||||
{
|
||||
u = u & 0xf;
|
||||
return u < 10 ? '0' + u : 'a' + (u - 10);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit EscapedString(const char* aStr)
|
||||
: mUnownedStr(nullptr)
|
||||
, mOwnedStr(nullptr)
|
||||
{
|
||||
const char* p;
|
||||
|
||||
// First, see if we need to modify the string.
|
||||
size_t nExtra = 0;
|
||||
p = aStr;
|
||||
while (true) {
|
||||
uint8_t u = *p; // ensure it can't be interpreted as negative
|
||||
if (u == 0) {
|
||||
break;
|
||||
}
|
||||
if (detail::gTwoCharEscapes[u]) {
|
||||
nExtra += 1;
|
||||
} else if (u <= 0x1f) {
|
||||
nExtra += 5;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (nExtra == 0) {
|
||||
// No escapes needed. Easy.
|
||||
mIsOwned = false;
|
||||
mUnownedStr = aStr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Escapes are needed. We'll create a new string.
|
||||
mIsOwned = true;
|
||||
size_t len = (p - aStr) + nExtra;
|
||||
mOwnedStr = MakeUnique<char[]>(len + 1);
|
||||
|
||||
p = aStr;
|
||||
size_t i = 0;
|
||||
|
||||
while (true) {
|
||||
uint8_t u = *p; // ensure it can't be interpreted as negative
|
||||
if (u == 0) {
|
||||
mOwnedStr[i] = 0;
|
||||
break;
|
||||
}
|
||||
if (detail::gTwoCharEscapes[u]) {
|
||||
mOwnedStr[i++] = '\\';
|
||||
mOwnedStr[i++] = detail::gTwoCharEscapes[u];
|
||||
} else if (u <= 0x1f) {
|
||||
mOwnedStr[i++] = '\\';
|
||||
mOwnedStr[i++] = 'u';
|
||||
mOwnedStr[i++] = '0';
|
||||
mOwnedStr[i++] = '0';
|
||||
mOwnedStr[i++] = hexDigitToAsciiChar((u & 0x00f0) >> 4);
|
||||
mOwnedStr[i++] = hexDigitToAsciiChar(u & 0x000f);
|
||||
} else {
|
||||
mOwnedStr[i++] = u;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
~EscapedString()
|
||||
{
|
||||
SanityCheck();
|
||||
}
|
||||
|
||||
const char* get() const
|
||||
{
|
||||
SanityCheck();
|
||||
return mIsOwned ? mOwnedStr.get() : mUnownedStr;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
// Collections (objects and arrays) are printed in a multi-line style by
|
||||
// default. This can be changed to a single-line style if SingleLineStyle is
|
||||
// specified. If a collection is printed in single-line style, every nested
|
||||
// collection within it is also printed in single-line style, even if
|
||||
// multi-line style is requested.
|
||||
enum CollectionStyle {
|
||||
MultiLineStyle, // the default
|
||||
SingleLineStyle
|
||||
};
|
||||
|
||||
protected:
|
||||
const UniquePtr<JSONWriteFunc> mWriter;
|
||||
Vector<bool, 8> mNeedComma; // do we need a comma at depth N?
|
||||
Vector<bool, 8> mNeedNewlines; // do we need newlines at depth N?
|
||||
size_t mDepth; // the current nesting depth
|
||||
|
||||
void Indent()
|
||||
{
|
||||
for (size_t i = 0; i < mDepth; i++) {
|
||||
mWriter->Write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
// Adds whatever is necessary (maybe a comma, and then a newline and
|
||||
// whitespace) to separate an item (property or element) from what's come
|
||||
// before.
|
||||
void Separator()
|
||||
{
|
||||
if (mNeedComma[mDepth]) {
|
||||
mWriter->Write(",");
|
||||
}
|
||||
if (mDepth > 0 && mNeedNewlines[mDepth]) {
|
||||
mWriter->Write("\n");
|
||||
Indent();
|
||||
} else if (mNeedComma[mDepth]) {
|
||||
mWriter->Write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyNameAndColon(const char* aName)
|
||||
{
|
||||
EscapedString escapedName(aName);
|
||||
mWriter->Write("\"");
|
||||
mWriter->Write(escapedName.get());
|
||||
mWriter->Write("\": ");
|
||||
}
|
||||
|
||||
void Scalar(const char* aMaybePropertyName, const char* aStringValue)
|
||||
{
|
||||
Separator();
|
||||
if (aMaybePropertyName) {
|
||||
PropertyNameAndColon(aMaybePropertyName);
|
||||
}
|
||||
mWriter->Write(aStringValue);
|
||||
mNeedComma[mDepth] = true;
|
||||
}
|
||||
|
||||
void QuotedScalar(const char* aMaybePropertyName, const char* aStringValue)
|
||||
{
|
||||
Separator();
|
||||
if (aMaybePropertyName) {
|
||||
PropertyNameAndColon(aMaybePropertyName);
|
||||
}
|
||||
mWriter->Write("\"");
|
||||
mWriter->Write(aStringValue);
|
||||
mWriter->Write("\"");
|
||||
mNeedComma[mDepth] = true;
|
||||
}
|
||||
|
||||
void NewVectorEntries()
|
||||
{
|
||||
// If these tiny allocations OOM we might as well just crash because we
|
||||
// must be in serious memory trouble.
|
||||
MOZ_RELEASE_ASSERT(mNeedComma.resizeUninitialized(mDepth + 1));
|
||||
MOZ_RELEASE_ASSERT(mNeedNewlines.resizeUninitialized(mDepth + 1));
|
||||
mNeedComma[mDepth] = false;
|
||||
mNeedNewlines[mDepth] = true;
|
||||
}
|
||||
|
||||
void StartCollection(const char* aMaybePropertyName, const char* aStartChar,
|
||||
CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
Separator();
|
||||
if (aMaybePropertyName) {
|
||||
mWriter->Write("\"");
|
||||
mWriter->Write(aMaybePropertyName);
|
||||
mWriter->Write("\": ");
|
||||
}
|
||||
mWriter->Write(aStartChar);
|
||||
mNeedComma[mDepth] = true;
|
||||
mDepth++;
|
||||
NewVectorEntries();
|
||||
mNeedNewlines[mDepth] =
|
||||
mNeedNewlines[mDepth - 1] && aStyle == MultiLineStyle;
|
||||
}
|
||||
|
||||
// Adds the whitespace and closing char necessary to end a collection.
|
||||
void EndCollection(const char* aEndChar)
|
||||
{
|
||||
if (mNeedNewlines[mDepth]) {
|
||||
mWriter->Write("\n");
|
||||
mDepth--;
|
||||
Indent();
|
||||
} else {
|
||||
mDepth--;
|
||||
}
|
||||
mWriter->Write(aEndChar);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit JSONWriter(UniquePtr<JSONWriteFunc> aWriter)
|
||||
: mWriter(Move(aWriter))
|
||||
, mNeedComma()
|
||||
, mNeedNewlines()
|
||||
, mDepth(0)
|
||||
{
|
||||
NewVectorEntries();
|
||||
}
|
||||
|
||||
// Returns the JSONWriteFunc passed in at creation, for temporary use. The
|
||||
// JSONWriter object still owns the JSONWriteFunc.
|
||||
JSONWriteFunc* WriteFunc() const { return mWriter.get(); }
|
||||
|
||||
// For all the following functions, the "Prints:" comment indicates what the
|
||||
// basic output looks like. However, it doesn't indicate the whitespace and
|
||||
// trailing commas, which are automatically added as required.
|
||||
//
|
||||
// All property names and string properties are escaped as necessary.
|
||||
|
||||
// Prints: {
|
||||
void Start(CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartCollection(nullptr, "{", aStyle);
|
||||
}
|
||||
|
||||
// Prints: }
|
||||
void End() { EndCollection("}\n"); }
|
||||
|
||||
// Prints: "<aName>": null
|
||||
void NullProperty(const char* aName)
|
||||
{
|
||||
Scalar(aName, "null");
|
||||
}
|
||||
|
||||
// Prints: null
|
||||
void NullElement() { NullProperty(nullptr); }
|
||||
|
||||
// Prints: "<aName>": <aBool>
|
||||
void BoolProperty(const char* aName, bool aBool)
|
||||
{
|
||||
Scalar(aName, aBool ? "true" : "false");
|
||||
}
|
||||
|
||||
// Prints: <aBool>
|
||||
void BoolElement(bool aBool) { BoolProperty(nullptr, aBool); }
|
||||
|
||||
// Prints: "<aName>": <aInt>
|
||||
void IntProperty(const char* aName, int64_t aInt)
|
||||
{
|
||||
char buf[64];
|
||||
SprintfLiteral(buf, "%" PRId64, aInt);
|
||||
Scalar(aName, buf);
|
||||
}
|
||||
|
||||
// Prints: <aInt>
|
||||
void IntElement(int64_t aInt) { IntProperty(nullptr, aInt); }
|
||||
|
||||
// Prints: "<aName>": <aDouble>
|
||||
void DoubleProperty(const char* aName, double aDouble)
|
||||
{
|
||||
static const size_t buflen = 64;
|
||||
char buf[buflen];
|
||||
const double_conversion::DoubleToStringConverter &converter =
|
||||
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
|
||||
double_conversion::StringBuilder builder(buf, buflen);
|
||||
converter.ToShortest(aDouble, &builder);
|
||||
Scalar(aName, builder.Finalize());
|
||||
}
|
||||
|
||||
// Prints: <aDouble>
|
||||
void DoubleElement(double aDouble) { DoubleProperty(nullptr, aDouble); }
|
||||
|
||||
// Prints: "<aName>": "<aStr>"
|
||||
void StringProperty(const char* aName, const char* aStr)
|
||||
{
|
||||
EscapedString escapedStr(aStr);
|
||||
QuotedScalar(aName, escapedStr.get());
|
||||
}
|
||||
|
||||
// Prints: "<aStr>"
|
||||
void StringElement(const char* aStr) { StringProperty(nullptr, aStr); }
|
||||
|
||||
// Prints: "<aName>": [
|
||||
void StartArrayProperty(const char* aName,
|
||||
CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartCollection(aName, "[", aStyle);
|
||||
}
|
||||
|
||||
// Prints: [
|
||||
void StartArrayElement(CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartArrayProperty(nullptr, aStyle);
|
||||
}
|
||||
|
||||
// Prints: ]
|
||||
void EndArray() { EndCollection("]"); }
|
||||
|
||||
// Prints: "<aName>": {
|
||||
void StartObjectProperty(const char* aName,
|
||||
CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartCollection(aName, "{", aStyle);
|
||||
}
|
||||
|
||||
// Prints: {
|
||||
void StartObjectElement(CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartObjectProperty(nullptr, aStyle);
|
||||
}
|
||||
|
||||
// Prints: }
|
||||
void EndObject() { EndCollection("}"); }
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_JSONWriter_h */
|
||||
|
||||
23
cocos2d-x/external/win32/include/spidermonkey/mozilla/Likely.h
vendored
Executable file
23
cocos2d-x/external/win32/include/spidermonkey/mozilla/Likely.h
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* MOZ_LIKELY and MOZ_UNLIKELY macros to hint to the compiler how a
|
||||
* boolean predicate should be branch-predicted.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_Likely_h
|
||||
#define mozilla_Likely_h
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
# define MOZ_LIKELY(x) (__builtin_expect(!!(x), 1))
|
||||
# define MOZ_UNLIKELY(x) (__builtin_expect(!!(x), 0))
|
||||
#else
|
||||
# define MOZ_LIKELY(x) (!!(x))
|
||||
# define MOZ_UNLIKELY(x) (!!(x))
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Likely_h */
|
||||
659
cocos2d-x/external/win32/include/spidermonkey/mozilla/LinkedList.h
vendored
Executable file
659
cocos2d-x/external/win32/include/spidermonkey/mozilla/LinkedList.h
vendored
Executable file
@@ -0,0 +1,659 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A type-safe doubly-linked list class. */
|
||||
|
||||
/*
|
||||
* The classes LinkedList<T> and LinkedListElement<T> together form a
|
||||
* convenient, type-safe doubly-linked list implementation.
|
||||
*
|
||||
* The class T which will be inserted into the linked list must inherit from
|
||||
* LinkedListElement<T>. A given object may be in only one linked list at a
|
||||
* time.
|
||||
*
|
||||
* A LinkedListElement automatically removes itself from the list upon
|
||||
* destruction, and a LinkedList will fatally assert in debug builds if it's
|
||||
* non-empty when it's destructed.
|
||||
*
|
||||
* For example, you might use LinkedList in a simple observer list class as
|
||||
* follows.
|
||||
*
|
||||
* class Observer : public LinkedListElement<Observer>
|
||||
* {
|
||||
* public:
|
||||
* void observe(char* aTopic) { ... }
|
||||
* };
|
||||
*
|
||||
* class ObserverContainer
|
||||
* {
|
||||
* private:
|
||||
* LinkedList<Observer> list;
|
||||
*
|
||||
* public:
|
||||
* void addObserver(Observer* aObserver)
|
||||
* {
|
||||
* // Will assert if |aObserver| is part of another list.
|
||||
* list.insertBack(aObserver);
|
||||
* }
|
||||
*
|
||||
* void removeObserver(Observer* aObserver)
|
||||
* {
|
||||
* // Will assert if |aObserver| is not part of some list.
|
||||
* aObserver.remove();
|
||||
* // Or, will assert if |aObserver| is not part of |list| specifically.
|
||||
* // aObserver.removeFrom(list);
|
||||
* }
|
||||
*
|
||||
* void notifyObservers(char* aTopic)
|
||||
* {
|
||||
* for (Observer* o = list.getFirst(); o != nullptr; o = o->getNext()) {
|
||||
* o->observe(aTopic);
|
||||
* }
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* Additionally, the class AutoCleanLinkedList<T> is a LinkedList<T> that will
|
||||
* remove and delete each element still within itself upon destruction. Note
|
||||
* that because each element is deleted, elements must have been allocated
|
||||
* using |new|.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_LinkedList_h
|
||||
#define mozilla_LinkedList_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T>
|
||||
class LinkedListElement;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* LinkedList supports refcounted elements using this adapter class. Clients
|
||||
* using LinkedList<RefPtr<T>> will get a data structure that holds a strong
|
||||
* reference to T as long as T is in the list.
|
||||
*/
|
||||
template<typename T>
|
||||
struct LinkedListElementTraits
|
||||
{
|
||||
typedef T* RawType;
|
||||
typedef const T* ConstRawType;
|
||||
typedef T* ClientType;
|
||||
typedef const T* ConstClientType;
|
||||
|
||||
// These static methods are called when an element is added to or removed from
|
||||
// a linked list. It can be used to keep track ownership in lists that are
|
||||
// supposed to own their elements. If elements are transferred from one list
|
||||
// to another, no enter or exit calls happen since the elements still belong
|
||||
// to a list.
|
||||
static void enterList(LinkedListElement<T>* elt) {}
|
||||
static void exitList(LinkedListElement<T>* elt) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LinkedListElementTraits<RefPtr<T>>
|
||||
{
|
||||
typedef T* RawType;
|
||||
typedef const T* ConstRawType;
|
||||
typedef RefPtr<T> ClientType;
|
||||
typedef RefPtr<const T> ConstClientType;
|
||||
|
||||
static void enterList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->AddRef(); }
|
||||
static void exitList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->Release(); }
|
||||
};
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T>
|
||||
class LinkedList;
|
||||
|
||||
template<typename T>
|
||||
class LinkedListElement
|
||||
{
|
||||
typedef typename detail::LinkedListElementTraits<T> Traits;
|
||||
typedef typename Traits::RawType RawType;
|
||||
typedef typename Traits::ConstRawType ConstRawType;
|
||||
typedef typename Traits::ClientType ClientType;
|
||||
typedef typename Traits::ConstClientType ConstClientType;
|
||||
|
||||
/*
|
||||
* It's convenient that we return nullptr when getNext() or getPrevious()
|
||||
* hits the end of the list, but doing so costs an extra word of storage in
|
||||
* each linked list node (to keep track of whether |this| is the sentinel
|
||||
* node) and a branch on this value in getNext/getPrevious.
|
||||
*
|
||||
* We could get rid of the extra word of storage by shoving the "is
|
||||
* sentinel" bit into one of the pointers, although this would, of course,
|
||||
* have performance implications of its own.
|
||||
*
|
||||
* But the goal here isn't to win an award for the fastest or slimmest
|
||||
* linked list; rather, we want a *convenient* linked list. So we won't
|
||||
* waste time guessing which micro-optimization strategy is best.
|
||||
*
|
||||
*
|
||||
* Speaking of unnecessary work, it's worth addressing here why we wrote
|
||||
* mozilla::LinkedList in the first place, instead of using stl::list.
|
||||
*
|
||||
* The key difference between mozilla::LinkedList and stl::list is that
|
||||
* mozilla::LinkedList stores the mPrev/mNext pointers in the object itself,
|
||||
* while stl::list stores the mPrev/mNext pointers in a list element which
|
||||
* itself points to the object being stored.
|
||||
*
|
||||
* mozilla::LinkedList's approach makes it harder to store an object in more
|
||||
* than one list. But the upside is that you can call next() / prev() /
|
||||
* remove() directly on the object. With stl::list, you'd need to store a
|
||||
* pointer to its iterator in the object in order to accomplish this. Not
|
||||
* only would this waste space, but you'd have to remember to update that
|
||||
* pointer every time you added or removed the object from a list.
|
||||
*
|
||||
* In-place, constant-time removal is a killer feature of doubly-linked
|
||||
* lists, and supporting this painlessly was a key design criterion.
|
||||
*/
|
||||
|
||||
private:
|
||||
LinkedListElement* mNext;
|
||||
LinkedListElement* mPrev;
|
||||
const bool mIsSentinel;
|
||||
|
||||
public:
|
||||
LinkedListElement()
|
||||
: mNext(this),
|
||||
mPrev(this),
|
||||
mIsSentinel(false)
|
||||
{ }
|
||||
|
||||
/*
|
||||
* Moves |aOther| into |*this|. If |aOther| is already in a list, then
|
||||
* |aOther| is removed from the list and replaced by |*this|.
|
||||
*/
|
||||
LinkedListElement(LinkedListElement<T>&& aOther)
|
||||
: mIsSentinel(aOther.mIsSentinel)
|
||||
{
|
||||
adjustLinkForMove(Move(aOther));
|
||||
}
|
||||
|
||||
LinkedListElement& operator=(LinkedListElement<T>&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(mIsSentinel == aOther.mIsSentinel, "Mismatch NodeKind!");
|
||||
MOZ_ASSERT(!isInList(),
|
||||
"Assigning to an element in a list messes up that list!");
|
||||
adjustLinkForMove(Move(aOther));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~LinkedListElement()
|
||||
{
|
||||
if (!mIsSentinel && isInList()) {
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next element in the list, or nullptr if this is the last element
|
||||
* in the list.
|
||||
*/
|
||||
RawType getNext() { return mNext->asT(); }
|
||||
ConstRawType getNext() const { return mNext->asT(); }
|
||||
|
||||
/*
|
||||
* Get the previous element in the list, or nullptr if this is the first
|
||||
* element in the list.
|
||||
*/
|
||||
RawType getPrevious() { return mPrev->asT(); }
|
||||
ConstRawType getPrevious() const { return mPrev->asT(); }
|
||||
|
||||
/*
|
||||
* Insert aElem after this element in the list. |this| must be part of a
|
||||
* linked list when you call setNext(); otherwise, this method will assert.
|
||||
*/
|
||||
void setNext(RawType aElem)
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
setNextUnsafe(aElem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert aElem before this element in the list. |this| must be part of a
|
||||
* linked list when you call setPrevious(); otherwise, this method will
|
||||
* assert.
|
||||
*/
|
||||
void setPrevious(RawType aElem)
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
setPreviousUnsafe(aElem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove this element from the list which contains it. If this element is
|
||||
* not currently part of a linked list, this method asserts.
|
||||
*/
|
||||
void remove()
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
|
||||
mPrev->mNext = mNext;
|
||||
mNext->mPrev = mPrev;
|
||||
mNext = this;
|
||||
mPrev = this;
|
||||
|
||||
Traits::exitList(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove this element from the list containing it. Returns a pointer to the
|
||||
* element that follows this element (before it was removed). This method
|
||||
* asserts if the element does not belong to a list.
|
||||
*/
|
||||
ClientType removeAndGetNext()
|
||||
{
|
||||
ClientType r = getNext();
|
||||
remove();
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove this element from the list containing it. Returns a pointer to the
|
||||
* previous element in the containing list (before the removal). This method
|
||||
* asserts if the element does not belong to a list.
|
||||
*/
|
||||
ClientType removeAndGetPrevious()
|
||||
{
|
||||
ClientType r = getPrevious();
|
||||
remove();
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identical to remove(), but also asserts in debug builds that this element
|
||||
* is in aList.
|
||||
*/
|
||||
void removeFrom(const LinkedList<T>& aList)
|
||||
{
|
||||
aList.assertContains(asT());
|
||||
remove();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if |this| part is of a linked list, and false otherwise.
|
||||
*/
|
||||
bool isInList() const
|
||||
{
|
||||
MOZ_ASSERT((mNext == this) == (mPrev == this));
|
||||
return mNext != this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LinkedList<T>;
|
||||
friend struct detail::LinkedListElementTraits<T>;
|
||||
|
||||
enum class NodeKind {
|
||||
Normal,
|
||||
Sentinel
|
||||
};
|
||||
|
||||
explicit LinkedListElement(NodeKind nodeKind)
|
||||
: mNext(this),
|
||||
mPrev(this),
|
||||
mIsSentinel(nodeKind == NodeKind::Sentinel)
|
||||
{ }
|
||||
|
||||
/*
|
||||
* Return |this| cast to T* if we're a normal node, or return nullptr if
|
||||
* we're a sentinel node.
|
||||
*/
|
||||
RawType asT()
|
||||
{
|
||||
return mIsSentinel ? nullptr : static_cast<RawType>(this);
|
||||
}
|
||||
ConstRawType asT() const
|
||||
{
|
||||
return mIsSentinel ? nullptr : static_cast<ConstRawType>(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert aElem after this element, but don't check that this element is in
|
||||
* the list. This is called by LinkedList::insertFront().
|
||||
*/
|
||||
void setNextUnsafe(RawType aElem)
|
||||
{
|
||||
LinkedListElement *listElem = static_cast<LinkedListElement*>(aElem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
|
||||
listElem->mNext = this->mNext;
|
||||
listElem->mPrev = this;
|
||||
this->mNext->mPrev = listElem;
|
||||
this->mNext = listElem;
|
||||
|
||||
Traits::enterList(aElem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert aElem before this element, but don't check that this element is in
|
||||
* the list. This is called by LinkedList::insertBack().
|
||||
*/
|
||||
void setPreviousUnsafe(RawType aElem)
|
||||
{
|
||||
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(aElem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
|
||||
listElem->mNext = this;
|
||||
listElem->mPrev = this->mPrev;
|
||||
this->mPrev->mNext = listElem;
|
||||
this->mPrev = listElem;
|
||||
|
||||
Traits::enterList(aElem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust mNext and mPrev for implementing move constructor and move
|
||||
* assignment.
|
||||
*/
|
||||
void adjustLinkForMove(LinkedListElement<T>&& aOther)
|
||||
{
|
||||
if (!aOther.isInList()) {
|
||||
mNext = this;
|
||||
mPrev = this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mIsSentinel) {
|
||||
Traits::enterList(this);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aOther.mNext->mPrev == &aOther);
|
||||
MOZ_ASSERT(aOther.mPrev->mNext == &aOther);
|
||||
|
||||
/*
|
||||
* Initialize |this| with |aOther|'s mPrev/mNext pointers, and adjust those
|
||||
* element to point to this one.
|
||||
*/
|
||||
mNext = aOther.mNext;
|
||||
mPrev = aOther.mPrev;
|
||||
|
||||
mNext->mPrev = this;
|
||||
mPrev->mNext = this;
|
||||
|
||||
/*
|
||||
* Adjust |aOther| so it doesn't think it's in a list. This makes it
|
||||
* safely destructable.
|
||||
*/
|
||||
aOther.mNext = &aOther;
|
||||
aOther.mPrev = &aOther;
|
||||
|
||||
if (!mIsSentinel) {
|
||||
Traits::exitList(&aOther);
|
||||
}
|
||||
}
|
||||
|
||||
LinkedListElement& operator=(const LinkedListElement<T>& aOther) = delete;
|
||||
LinkedListElement(const LinkedListElement<T>& aOther) = delete;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class LinkedList
|
||||
{
|
||||
private:
|
||||
typedef typename detail::LinkedListElementTraits<T> Traits;
|
||||
typedef typename Traits::RawType RawType;
|
||||
typedef typename Traits::ConstRawType ConstRawType;
|
||||
typedef typename Traits::ClientType ClientType;
|
||||
typedef typename Traits::ConstClientType ConstClientType;
|
||||
|
||||
LinkedListElement<T> sentinel;
|
||||
|
||||
public:
|
||||
class Iterator {
|
||||
RawType mCurrent;
|
||||
|
||||
public:
|
||||
explicit Iterator(RawType aCurrent) : mCurrent(aCurrent) {}
|
||||
|
||||
RawType operator *() const {
|
||||
return mCurrent;
|
||||
}
|
||||
|
||||
const Iterator& operator++() {
|
||||
mCurrent = mCurrent->getNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(Iterator& aOther) const {
|
||||
return mCurrent != aOther.mCurrent;
|
||||
}
|
||||
};
|
||||
|
||||
LinkedList() : sentinel(LinkedListElement<T>::NodeKind::Sentinel) { }
|
||||
|
||||
LinkedList(LinkedList<T>&& aOther)
|
||||
: sentinel(mozilla::Move(aOther.sentinel))
|
||||
{ }
|
||||
|
||||
LinkedList& operator=(LinkedList<T>&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(isEmpty(), "Assigning to a non-empty list leaks elements in that list!");
|
||||
sentinel = mozilla::Move(aOther.sentinel);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~LinkedList() {
|
||||
MOZ_ASSERT(isEmpty(),
|
||||
"failing this assertion means this LinkedList's creator is "
|
||||
"buggy: it should have removed all this list's elements before "
|
||||
"the list's destruction");
|
||||
}
|
||||
|
||||
/*
|
||||
* Add aElem to the front of the list.
|
||||
*/
|
||||
void insertFront(RawType aElem)
|
||||
{
|
||||
/* Bypass setNext()'s this->isInList() assertion. */
|
||||
sentinel.setNextUnsafe(aElem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add aElem to the back of the list.
|
||||
*/
|
||||
void insertBack(RawType aElem)
|
||||
{
|
||||
sentinel.setPreviousUnsafe(aElem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the first element of the list, or nullptr if the list is empty.
|
||||
*/
|
||||
RawType getFirst() { return sentinel.getNext(); }
|
||||
ConstRawType getFirst() const { return sentinel.getNext(); }
|
||||
|
||||
/*
|
||||
* Get the last element of the list, or nullptr if the list is empty.
|
||||
*/
|
||||
RawType getLast() { return sentinel.getPrevious(); }
|
||||
ConstRawType getLast() const { return sentinel.getPrevious(); }
|
||||
|
||||
/*
|
||||
* Get and remove the first element of the list. If the list is empty,
|
||||
* return nullptr.
|
||||
*/
|
||||
ClientType popFirst()
|
||||
{
|
||||
ClientType ret = sentinel.getNext();
|
||||
if (ret) {
|
||||
static_cast<LinkedListElement<T>*>(RawType(ret))->remove();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and remove the last element of the list. If the list is empty,
|
||||
* return nullptr.
|
||||
*/
|
||||
ClientType popLast()
|
||||
{
|
||||
ClientType ret = sentinel.getPrevious();
|
||||
if (ret) {
|
||||
static_cast<LinkedListElement<T>*>(RawType(ret))->remove();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the list is empty, or false otherwise.
|
||||
*/
|
||||
bool isEmpty() const
|
||||
{
|
||||
return !sentinel.isInList();
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all the elements from the list.
|
||||
*
|
||||
* This runs in time linear to the list's length, because we have to mark
|
||||
* each element as not in the list.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
while (popFirst()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow range-based iteration:
|
||||
*
|
||||
* for (MyElementType* elt : myList) { ... }
|
||||
*/
|
||||
Iterator begin() {
|
||||
return Iterator(getFirst());
|
||||
}
|
||||
Iterator end() {
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Measures the memory consumption of the list excluding |this|. Note that
|
||||
* it only measures the list elements themselves. If the list elements
|
||||
* contain pointers to other memory blocks, those blocks must be measured
|
||||
* separately during a subsequent iteration over the list.
|
||||
*/
|
||||
size_t sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
for (const T* t = getFirst(); t; t = t->getNext()) {
|
||||
n += aMallocSizeOf(t);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Like sizeOfExcludingThis(), but measures |this| as well.
|
||||
*/
|
||||
size_t sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/*
|
||||
* In a debug build, make sure that the list is sane (no cycles, consistent
|
||||
* mNext/mPrev pointers, only one sentinel). Has no effect in release builds.
|
||||
*/
|
||||
void debugAssertIsSane() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
const LinkedListElement<T>* slow;
|
||||
const LinkedListElement<T>* fast1;
|
||||
const LinkedListElement<T>* fast2;
|
||||
|
||||
/*
|
||||
* Check for cycles in the forward singly-linked list using the
|
||||
* tortoise/hare algorithm.
|
||||
*/
|
||||
for (slow = sentinel.mNext,
|
||||
fast1 = sentinel.mNext->mNext,
|
||||
fast2 = sentinel.mNext->mNext->mNext;
|
||||
slow != &sentinel && fast1 != &sentinel && fast2 != &sentinel;
|
||||
slow = slow->mNext, fast1 = fast2->mNext, fast2 = fast1->mNext) {
|
||||
MOZ_ASSERT(slow != fast1);
|
||||
MOZ_ASSERT(slow != fast2);
|
||||
}
|
||||
|
||||
/* Check for cycles in the backward singly-linked list. */
|
||||
for (slow = sentinel.mPrev,
|
||||
fast1 = sentinel.mPrev->mPrev,
|
||||
fast2 = sentinel.mPrev->mPrev->mPrev;
|
||||
slow != &sentinel && fast1 != &sentinel && fast2 != &sentinel;
|
||||
slow = slow->mPrev, fast1 = fast2->mPrev, fast2 = fast1->mPrev) {
|
||||
MOZ_ASSERT(slow != fast1);
|
||||
MOZ_ASSERT(slow != fast2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that |sentinel| is the only node in the list with
|
||||
* mIsSentinel == true.
|
||||
*/
|
||||
for (const LinkedListElement<T>* elem = sentinel.mNext;
|
||||
elem != &sentinel;
|
||||
elem = elem->mNext) {
|
||||
MOZ_ASSERT(!elem->mIsSentinel);
|
||||
}
|
||||
|
||||
/* Check that the mNext/mPrev pointers match up. */
|
||||
const LinkedListElement<T>* prev = &sentinel;
|
||||
const LinkedListElement<T>* cur = sentinel.mNext;
|
||||
do {
|
||||
MOZ_ASSERT(cur->mPrev == prev);
|
||||
MOZ_ASSERT(prev->mNext == cur);
|
||||
|
||||
prev = cur;
|
||||
cur = cur->mNext;
|
||||
} while (cur != &sentinel);
|
||||
#endif /* ifdef DEBUG */
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LinkedListElement<T>;
|
||||
|
||||
void assertContains(const RawType aValue) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (ConstRawType elem = getFirst(); elem; elem = elem->getNext()) {
|
||||
if (elem == aValue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
MOZ_CRASH("element wasn't found in this list!");
|
||||
#endif
|
||||
}
|
||||
|
||||
LinkedList& operator=(const LinkedList<T>& aOther) = delete;
|
||||
LinkedList(const LinkedList<T>& aOther) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class AutoCleanLinkedList : public LinkedList<T>
|
||||
{
|
||||
public:
|
||||
~AutoCleanLinkedList()
|
||||
{
|
||||
while (T* element = this->popFirst()) {
|
||||
delete element;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_LinkedList_h */
|
||||
109
cocos2d-x/external/win32/include/spidermonkey/mozilla/MacroArgs.h
vendored
Executable file
109
cocos2d-x/external/win32/include/spidermonkey/mozilla/MacroArgs.h
vendored
Executable file
@@ -0,0 +1,109 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Implements various macros meant to ease the use of variadic macros.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_MacroArgs_h
|
||||
#define mozilla_MacroArgs_h
|
||||
|
||||
// Concatenates pre-processor tokens in a way that can be used with __LINE__.
|
||||
#define MOZ_CONCAT2(x, y) x ## y
|
||||
#define MOZ_CONCAT(x, y) MOZ_CONCAT2(x, y)
|
||||
|
||||
/*
|
||||
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) counts the number of variadic
|
||||
* arguments and prefixes it with |aPrefix|. For example:
|
||||
*
|
||||
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(, foo, 42) expands to 2
|
||||
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(A, foo, 42, bar) expands to A3
|
||||
*
|
||||
* You must pass in between 1 and 50 (inclusive) variadic arguments, past
|
||||
* |aPrefix|. It is not legal to do
|
||||
*
|
||||
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(prefix)
|
||||
*
|
||||
* (that is, pass in 0 variadic arguments). To ensure that a compile-time
|
||||
* error occurs when these constraints are violated, use the
|
||||
* MOZ_STATIC_ASSERT_VALID_ARG_COUNT macro with the same variaidc arguments
|
||||
* wherever this macro is used.
|
||||
*
|
||||
* Passing (__VA_ARGS__, <rest of arguments>) rather than simply calling
|
||||
* MOZ_MACROARGS_ARG_COUNT_HELPER2(__VA_ARGS__, <rest of arguments>) very
|
||||
* carefully tiptoes around a MSVC bug where it improperly expands __VA_ARGS__
|
||||
* as a single token in argument lists. For details, see:
|
||||
*
|
||||
* http://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement
|
||||
* http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/#comment-644
|
||||
*/
|
||||
#define MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) \
|
||||
MOZ_MACROARGS_ARG_COUNT_HELPER((__VA_ARGS__, \
|
||||
aPrefix##50, aPrefix##49, aPrefix##48, aPrefix##47, aPrefix##46, \
|
||||
aPrefix##45, aPrefix##44, aPrefix##43, aPrefix##42, aPrefix##41, \
|
||||
aPrefix##40, aPrefix##39, aPrefix##38, aPrefix##37, aPrefix##36, \
|
||||
aPrefix##35, aPrefix##34, aPrefix##33, aPrefix##32, aPrefix##31, \
|
||||
aPrefix##30, aPrefix##29, aPrefix##28, aPrefix##27, aPrefix##26, \
|
||||
aPrefix##25, aPrefix##24, aPrefix##23, aPrefix##22, aPrefix##21, \
|
||||
aPrefix##20, aPrefix##19, aPrefix##18, aPrefix##17, aPrefix##16, \
|
||||
aPrefix##15, aPrefix##14, aPrefix##13, aPrefix##12, aPrefix##11, \
|
||||
aPrefix##10, aPrefix##9, aPrefix##8, aPrefix##7, aPrefix##6, \
|
||||
aPrefix##5, aPrefix##4, aPrefix##3, aPrefix##2, aPrefix##1, aPrefix##0))
|
||||
|
||||
#define MOZ_MACROARGS_ARG_COUNT_HELPER(aArgs) \
|
||||
MOZ_MACROARGS_ARG_COUNT_HELPER2 aArgs
|
||||
|
||||
#define MOZ_MACROARGS_ARG_COUNT_HELPER2( \
|
||||
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
|
||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, \
|
||||
a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, \
|
||||
a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, \
|
||||
a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, \
|
||||
a51, ...) a51
|
||||
|
||||
/*
|
||||
* MOZ_STATIC_ASSERT_VALID_ARG_COUNT ensures that a compile-time error occurs
|
||||
* when the argument count constraints of MOZ_PASTE_PREFIX_AND_ARG_COUNT are
|
||||
* violated. Use this macro wherever MOZ_PASTE_PREFIX_AND_ARG_COUNT is used
|
||||
* and pass it the same variadic arguments.
|
||||
*
|
||||
* This macro employs a few dirty tricks to function. To detect the zero
|
||||
* argument case, |(__VA_ARGS__)| is stringified, sizeof-ed, and compared to
|
||||
* what it should be in the absence of arguments.
|
||||
*
|
||||
* Detecting too many arguments is a little trickier. With a valid argument
|
||||
* count and a prefix of 1, MOZ_PASTE_PREFIX_AND_ARG_COUNT expands to e.g. 14.
|
||||
* With a prefix of 0.0, it expands to e.g. 0.04. If there are too many
|
||||
* arguments, it expands to the first argument over the limit. If this
|
||||
* exceeding argument is a number, the assertion will fail as there is no
|
||||
* number than can simultaneously be both > 10 and == 0. If the exceeding
|
||||
* argument is not a number, a compile-time error should still occur due to
|
||||
* the operations performed on it.
|
||||
*/
|
||||
#define MOZ_MACROARGS_STRINGIFY_HELPER(x) #x
|
||||
#define MOZ_STATIC_ASSERT_VALID_ARG_COUNT(...) \
|
||||
static_assert( \
|
||||
sizeof(MOZ_MACROARGS_STRINGIFY_HELPER((__VA_ARGS__))) != sizeof("()") && \
|
||||
(MOZ_PASTE_PREFIX_AND_ARG_COUNT(1, __VA_ARGS__)) > 10 && \
|
||||
(int)(MOZ_PASTE_PREFIX_AND_ARG_COUNT(0.0, __VA_ARGS__)) == 0, \
|
||||
"MOZ_STATIC_ASSERT_VALID_ARG_COUNT requires 1 to 50 arguments") /* ; */
|
||||
|
||||
/*
|
||||
* MOZ_ARGS_AFTER_N expands to its arguments excluding the first |N|
|
||||
* arguments. For example:
|
||||
*
|
||||
* MOZ_ARGS_AFTER_2(a, b, c, d) expands to: c, d
|
||||
*/
|
||||
#define MOZ_ARGS_AFTER_1(a1, ...) __VA_ARGS__
|
||||
#define MOZ_ARGS_AFTER_2(a1, a2, ...) __VA_ARGS__
|
||||
|
||||
/*
|
||||
* MOZ_ARG_N expands to its |N|th argument.
|
||||
*/
|
||||
#define MOZ_ARG_1(a1, ...) a1
|
||||
#define MOZ_ARG_2(a1, a2, ...) a2
|
||||
|
||||
#endif /* mozilla_MacroArgs_h */
|
||||
158
cocos2d-x/external/win32/include/spidermonkey/mozilla/MacroForEach.h
vendored
Executable file
158
cocos2d-x/external/win32/include/spidermonkey/mozilla/MacroForEach.h
vendored
Executable file
@@ -0,0 +1,158 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Implements a higher-order macro for iteratively calling another macro with
|
||||
* fixed leading arguments, plus a trailing element picked from a second list
|
||||
* of arguments.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_MacroForEach_h
|
||||
#define mozilla_MacroForEach_h
|
||||
|
||||
#include "mozilla/MacroArgs.h"
|
||||
|
||||
/*
|
||||
* MOZ_FOR_EACH(aMacro, aFixedArgs, aArgs) expands to N calls to the macro
|
||||
* |aMacro| where N is equal the number of items in the list |aArgs|. The
|
||||
* arguments for each |aMacro| call are composed of *all* arguments in the list
|
||||
* |aFixedArgs| as well as a single argument in the list |aArgs|. For example:
|
||||
*
|
||||
* #define MACRO_A(x) x +
|
||||
* int a = MOZ_FOR_EACH(MACRO_A, (), (1, 2, 3)) 0;
|
||||
* // Expands to: MACRO_A(1) MACRO_A(2) MACRO_A(3) 0;
|
||||
* // And further to: 1 + 2 + 3 + 0;
|
||||
*
|
||||
* #define MACRO_B(k, x) (k + x) +
|
||||
* int b = MOZ_FOR_EACH(MACRO_B, (5,), (1, 2)) 0;
|
||||
* // Expands to: MACRO_B(5, 1) MACRO_B(5, 2) 0;
|
||||
*
|
||||
* #define MACRO_C(k1, k2, x) (k1 + k2 + x) +
|
||||
* int c = MOZ_FOR_EACH(MACRO_C, (5, 8,), (1, 2)) 0;
|
||||
* // Expands to: MACRO_B(5, 8, 1) MACRO_B(5, 8, 2) 0;
|
||||
*
|
||||
* If the |aFixedArgs| list is not empty, a trailing comma must be included.
|
||||
*
|
||||
* The |aArgs| list must be not be empty and may be up to 50 items long. Use
|
||||
* MOZ_STATIC_ASSERT_VALID_ARG_COUNT to ensure that violating this constraint
|
||||
* results in a compile-time error.
|
||||
*/
|
||||
#define MOZ_FOR_EACH_EXPAND_HELPER(...) __VA_ARGS__
|
||||
#define MOZ_FOR_EACH_GLUE(a, b) a b
|
||||
#define MOZ_FOR_EACH(aMacro, aFixedArgs, aArgs) \
|
||||
MOZ_FOR_EACH_GLUE( \
|
||||
MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_FOR_EACH_, \
|
||||
MOZ_FOR_EACH_EXPAND_HELPER aArgs), \
|
||||
(aMacro, aFixedArgs, aArgs))
|
||||
|
||||
#define MOZ_FOR_EACH_HELPER_GLUE(a, b) a b
|
||||
#define MOZ_FOR_EACH_HELPER(aMacro, aFixedArgs, aArgs) \
|
||||
MOZ_FOR_EACH_HELPER_GLUE( \
|
||||
aMacro, \
|
||||
(MOZ_FOR_EACH_EXPAND_HELPER aFixedArgs MOZ_ARG_1 aArgs))
|
||||
|
||||
#define MOZ_FOR_EACH_1(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a)
|
||||
#define MOZ_FOR_EACH_2(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_1(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_3(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_2(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_4(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_3(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_5(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_4(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_6(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_5(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_7(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_6(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_8(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_7(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_9(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_8(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_10(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_9(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_11(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_10(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_12(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_11(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_13(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_12(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_14(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_13(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_15(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_14(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_16(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_15(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_17(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_16(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_18(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_17(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_19(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_18(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_20(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_19(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_21(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_20(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_22(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_21(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_23(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_22(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_24(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_23(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_25(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_24(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_26(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_25(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_27(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_26(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_28(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_27(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_29(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_28(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_30(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_29(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_31(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_30(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_32(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_31(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_33(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_32(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_34(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_33(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_35(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_34(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_36(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_35(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_37(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_36(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_38(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_37(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_39(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_38(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_40(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_39(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_41(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_40(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_42(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_41(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_43(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_42(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_44(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_43(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_45(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_44(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_46(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_45(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_47(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_46(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_48(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_47(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_49(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_48(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
#define MOZ_FOR_EACH_50(m, fa, a) \
|
||||
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_49(m, fa, (MOZ_ARGS_AFTER_1 a))
|
||||
|
||||
#endif /* mozilla_MacroForEach_h */
|
||||
547
cocos2d-x/external/win32/include/spidermonkey/mozilla/MathAlgorithms.h
vendored
Executable file
547
cocos2d-x/external/win32/include/spidermonkey/mozilla/MathAlgorithms.h
vendored
Executable file
@@ -0,0 +1,547 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* mfbt maths algorithms. */
|
||||
|
||||
#ifndef mozilla_MathAlgorithms_h
|
||||
#define mozilla_MathAlgorithms_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Greatest Common Divisor
|
||||
template<typename IntegerType>
|
||||
MOZ_ALWAYS_INLINE IntegerType
|
||||
EuclidGCD(IntegerType aA, IntegerType aB)
|
||||
{
|
||||
// Euclid's algorithm; O(N) in the worst case. (There are better
|
||||
// ways, but we don't need them for the current use of this algo.)
|
||||
MOZ_ASSERT(aA > IntegerType(0));
|
||||
MOZ_ASSERT(aB > IntegerType(0));
|
||||
|
||||
while (aA != aB) {
|
||||
if (aA > aB) {
|
||||
aA = aA - aB;
|
||||
} else {
|
||||
aB = aB - aA;
|
||||
}
|
||||
}
|
||||
|
||||
return aA;
|
||||
}
|
||||
|
||||
// Least Common Multiple
|
||||
template<typename IntegerType>
|
||||
MOZ_ALWAYS_INLINE IntegerType
|
||||
EuclidLCM(IntegerType aA, IntegerType aB)
|
||||
{
|
||||
// Divide first to reduce overflow risk.
|
||||
return (aA / EuclidGCD(aA, aB)) * aB;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct AllowDeprecatedAbsFixed : FalseType {};
|
||||
|
||||
template<> struct AllowDeprecatedAbsFixed<int32_t> : TrueType {};
|
||||
template<> struct AllowDeprecatedAbsFixed<int64_t> : TrueType {};
|
||||
|
||||
template<typename T>
|
||||
struct AllowDeprecatedAbs : AllowDeprecatedAbsFixed<T> {};
|
||||
|
||||
template<> struct AllowDeprecatedAbs<int> : TrueType {};
|
||||
template<> struct AllowDeprecatedAbs<long> : TrueType {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// DO NOT USE DeprecatedAbs. It exists only until its callers can be converted
|
||||
// to Abs below, and it will be removed when all callers have been changed.
|
||||
template<typename T>
|
||||
inline typename mozilla::EnableIf<detail::AllowDeprecatedAbs<T>::value, T>::Type
|
||||
DeprecatedAbs(const T aValue)
|
||||
{
|
||||
// The absolute value of the smallest possible value of a signed-integer type
|
||||
// won't fit in that type (on twos-complement systems -- and we're blithely
|
||||
// assuming we're on such systems, for the non-<stdint.h> types listed above),
|
||||
// so assert that the input isn't that value.
|
||||
//
|
||||
// This is the case if: the value is non-negative; or if adding one (giving a
|
||||
// value in the range [-maxvalue, 0]), then negating (giving a value in the
|
||||
// range [0, maxvalue]), doesn't produce maxvalue (because in twos-complement,
|
||||
// (minvalue + 1) == -maxvalue).
|
||||
MOZ_ASSERT(aValue >= 0 ||
|
||||
-(aValue + 1) != T((1ULL << (CHAR_BIT * sizeof(T) - 1)) - 1),
|
||||
"You can't negate the smallest possible negative integer!");
|
||||
return aValue >= 0 ? aValue : -aValue;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// For now mozilla::Abs only takes intN_T, the signed natural types, and
|
||||
// float/double/long double. Feel free to add overloads for other standard,
|
||||
// signed types if you need them.
|
||||
|
||||
template<typename T>
|
||||
struct AbsReturnTypeFixed;
|
||||
|
||||
template<> struct AbsReturnTypeFixed<int8_t> { typedef uint8_t Type; };
|
||||
template<> struct AbsReturnTypeFixed<int16_t> { typedef uint16_t Type; };
|
||||
template<> struct AbsReturnTypeFixed<int32_t> { typedef uint32_t Type; };
|
||||
template<> struct AbsReturnTypeFixed<int64_t> { typedef uint64_t Type; };
|
||||
|
||||
template<typename T>
|
||||
struct AbsReturnType : AbsReturnTypeFixed<T> {};
|
||||
|
||||
template<> struct AbsReturnType<char> :
|
||||
EnableIf<char(-1) < char(0), unsigned char> {};
|
||||
template<> struct AbsReturnType<signed char> { typedef unsigned char Type; };
|
||||
template<> struct AbsReturnType<short> { typedef unsigned short Type; };
|
||||
template<> struct AbsReturnType<int> { typedef unsigned int Type; };
|
||||
template<> struct AbsReturnType<long> { typedef unsigned long Type; };
|
||||
template<> struct AbsReturnType<long long> { typedef unsigned long long Type; };
|
||||
template<> struct AbsReturnType<float> { typedef float Type; };
|
||||
template<> struct AbsReturnType<double> { typedef double Type; };
|
||||
template<> struct AbsReturnType<long double> { typedef long double Type; };
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
inline typename detail::AbsReturnType<T>::Type
|
||||
Abs(const T aValue)
|
||||
{
|
||||
typedef typename detail::AbsReturnType<T>::Type ReturnType;
|
||||
return aValue >= 0 ? ReturnType(aValue) : ~ReturnType(aValue) + 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float
|
||||
Abs<float>(const float aFloat)
|
||||
{
|
||||
return std::fabs(aFloat);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double
|
||||
Abs<double>(const double aDouble)
|
||||
{
|
||||
return std::fabs(aDouble);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline long double
|
||||
Abs<long double>(const long double aLongDouble)
|
||||
{
|
||||
return std::fabs(aLongDouble);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#if defined(_MSC_VER) && \
|
||||
(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
|
||||
# define MOZ_BITSCAN_WINDOWS
|
||||
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_BitScanForward, _BitScanReverse)
|
||||
|
||||
# if defined(_M_AMD64) || defined(_M_X64)
|
||||
# define MOZ_BITSCAN_WINDOWS64
|
||||
# pragma intrinsic(_BitScanForward64, _BitScanReverse64)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if defined(MOZ_BITSCAN_WINDOWS)
|
||||
|
||||
inline uint_fast8_t
|
||||
CountLeadingZeroes32(uint32_t aValue)
|
||||
{
|
||||
unsigned long index;
|
||||
if (!_BitScanReverse(&index, static_cast<unsigned long>(aValue)))
|
||||
return 32;
|
||||
return uint_fast8_t(31 - index);
|
||||
}
|
||||
|
||||
|
||||
inline uint_fast8_t
|
||||
CountTrailingZeroes32(uint32_t aValue)
|
||||
{
|
||||
unsigned long index;
|
||||
if (!_BitScanForward(&index, static_cast<unsigned long>(aValue)))
|
||||
return 32;
|
||||
return uint_fast8_t(index);
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountPopulation32(uint32_t aValue)
|
||||
{
|
||||
uint32_t x = aValue - ((aValue >> 1) & 0x55555555);
|
||||
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
||||
return (((x + (x >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||
}
|
||||
inline uint_fast8_t
|
||||
CountPopulation64(uint64_t aValue)
|
||||
{
|
||||
return uint_fast8_t(CountPopulation32(aValue & 0xffffffff) +
|
||||
CountPopulation32(aValue >> 32));
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountLeadingZeroes64(uint64_t aValue)
|
||||
{
|
||||
#if defined(MOZ_BITSCAN_WINDOWS64)
|
||||
unsigned long index;
|
||||
if (!_BitScanReverse64(&index, static_cast<unsigned __int64>(aValue)))
|
||||
return 64;
|
||||
return uint_fast8_t(63 - index);
|
||||
#else
|
||||
uint32_t hi = uint32_t(aValue >> 32);
|
||||
if (hi != 0) {
|
||||
return CountLeadingZeroes32(hi);
|
||||
}
|
||||
return 32u + CountLeadingZeroes32(uint32_t(aValue));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountTrailingZeroes64(uint64_t aValue)
|
||||
{
|
||||
#if defined(MOZ_BITSCAN_WINDOWS64)
|
||||
unsigned long index;
|
||||
if (!_BitScanForward64(&index, static_cast<unsigned __int64>(aValue)))
|
||||
return 64;
|
||||
return uint_fast8_t(index);
|
||||
#else
|
||||
uint32_t lo = uint32_t(aValue);
|
||||
if (lo != 0) {
|
||||
return CountTrailingZeroes32(lo);
|
||||
}
|
||||
return 32u + CountTrailingZeroes32(uint32_t(aValue >> 32));
|
||||
#endif
|
||||
}
|
||||
|
||||
# ifdef MOZ_HAVE_BITSCAN64
|
||||
# undef MOZ_HAVE_BITSCAN64
|
||||
# endif
|
||||
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
|
||||
# if defined(__clang__)
|
||||
# if !__has_builtin(__builtin_ctz) || !__has_builtin(__builtin_clz)
|
||||
# error "A clang providing __builtin_c[lt]z is required to build"
|
||||
# endif
|
||||
# else
|
||||
// gcc has had __builtin_clz and friends since 3.4: no need to check.
|
||||
# endif
|
||||
|
||||
inline uint_fast8_t
|
||||
CountLeadingZeroes32(uint32_t aValue)
|
||||
{
|
||||
return __builtin_clz(aValue);
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountTrailingZeroes32(uint32_t aValue)
|
||||
{
|
||||
return __builtin_ctz(aValue);
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountPopulation32(uint32_t aValue)
|
||||
{
|
||||
return __builtin_popcount(aValue);
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountPopulation64(uint64_t aValue)
|
||||
{
|
||||
return __builtin_popcountll(aValue);
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountLeadingZeroes64(uint64_t aValue)
|
||||
{
|
||||
return __builtin_clzll(aValue);
|
||||
}
|
||||
|
||||
inline uint_fast8_t
|
||||
CountTrailingZeroes64(uint64_t aValue)
|
||||
{
|
||||
return __builtin_ctzll(aValue);
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Implement these!"
|
||||
inline uint_fast8_t CountLeadingZeroes32(uint32_t aValue) = delete;
|
||||
inline uint_fast8_t CountTrailingZeroes32(uint32_t aValue) = delete;
|
||||
inline uint_fast8_t CountPopulation32(uint32_t aValue) = delete;
|
||||
inline uint_fast8_t CountPopulation64(uint64_t aValue) = delete;
|
||||
inline uint_fast8_t CountLeadingZeroes64(uint64_t aValue) = delete;
|
||||
inline uint_fast8_t CountTrailingZeroes64(uint64_t aValue) = delete;
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Compute the number of high-order zero bits in the NON-ZERO number |aValue|.
|
||||
* That is, looking at the bitwise representation of the number, with the
|
||||
* highest- valued bits at the start, return the number of zeroes before the
|
||||
* first one is observed.
|
||||
*
|
||||
* CountLeadingZeroes32(0xF0FF1000) is 0;
|
||||
* CountLeadingZeroes32(0x7F8F0001) is 1;
|
||||
* CountLeadingZeroes32(0x3FFF0100) is 2;
|
||||
* CountLeadingZeroes32(0x1FF50010) is 3; and so on.
|
||||
*/
|
||||
inline uint_fast8_t
|
||||
CountLeadingZeroes32(uint32_t aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue != 0);
|
||||
return detail::CountLeadingZeroes32(aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of low-order zero bits in the NON-ZERO number |aValue|.
|
||||
* That is, looking at the bitwise representation of the number, with the
|
||||
* lowest- valued bits at the start, return the number of zeroes before the
|
||||
* first one is observed.
|
||||
*
|
||||
* CountTrailingZeroes32(0x0100FFFF) is 0;
|
||||
* CountTrailingZeroes32(0x7000FFFE) is 1;
|
||||
* CountTrailingZeroes32(0x0080FFFC) is 2;
|
||||
* CountTrailingZeroes32(0x0080FFF8) is 3; and so on.
|
||||
*/
|
||||
inline uint_fast8_t
|
||||
CountTrailingZeroes32(uint32_t aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue != 0);
|
||||
return detail::CountTrailingZeroes32(aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of one bits in the number |aValue|,
|
||||
*/
|
||||
inline uint_fast8_t
|
||||
CountPopulation32(uint32_t aValue)
|
||||
{
|
||||
return detail::CountPopulation32(aValue);
|
||||
}
|
||||
|
||||
/** Analogous to CountPopulation32, but for 64-bit numbers */
|
||||
inline uint_fast8_t
|
||||
CountPopulation64(uint64_t aValue)
|
||||
{
|
||||
return detail::CountPopulation64(aValue);
|
||||
}
|
||||
|
||||
/** Analogous to CountLeadingZeroes32, but for 64-bit numbers. */
|
||||
inline uint_fast8_t
|
||||
CountLeadingZeroes64(uint64_t aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue != 0);
|
||||
return detail::CountLeadingZeroes64(aValue);
|
||||
}
|
||||
|
||||
/** Analogous to CountTrailingZeroes32, but for 64-bit numbers. */
|
||||
inline uint_fast8_t
|
||||
CountTrailingZeroes64(uint64_t aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue != 0);
|
||||
return detail::CountTrailingZeroes64(aValue);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, size_t Size = sizeof(T)>
|
||||
class CeilingLog2;
|
||||
|
||||
template<typename T>
|
||||
class CeilingLog2<T, 4>
|
||||
{
|
||||
public:
|
||||
static uint_fast8_t compute(const T aValue)
|
||||
{
|
||||
// Check for <= 1 to avoid the == 0 undefined case.
|
||||
return aValue <= 1 ? 0u : 32u - CountLeadingZeroes32(aValue - 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CeilingLog2<T, 8>
|
||||
{
|
||||
public:
|
||||
static uint_fast8_t compute(const T aValue)
|
||||
{
|
||||
// Check for <= 1 to avoid the == 0 undefined case.
|
||||
return aValue <= 1 ? 0u : 64u - CountLeadingZeroes64(aValue - 1);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Compute the log of the least power of 2 greater than or equal to |aValue|.
|
||||
*
|
||||
* CeilingLog2(0..1) is 0;
|
||||
* CeilingLog2(2) is 1;
|
||||
* CeilingLog2(3..4) is 2;
|
||||
* CeilingLog2(5..8) is 3;
|
||||
* CeilingLog2(9..16) is 4; and so on.
|
||||
*/
|
||||
template<typename T>
|
||||
inline uint_fast8_t
|
||||
CeilingLog2(const T aValue)
|
||||
{
|
||||
return detail::CeilingLog2<T>::compute(aValue);
|
||||
}
|
||||
|
||||
/** A CeilingLog2 variant that accepts only size_t. */
|
||||
inline uint_fast8_t
|
||||
CeilingLog2Size(size_t aValue)
|
||||
{
|
||||
return CeilingLog2(aValue);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, size_t Size = sizeof(T)>
|
||||
class FloorLog2;
|
||||
|
||||
template<typename T>
|
||||
class FloorLog2<T, 4>
|
||||
{
|
||||
public:
|
||||
static uint_fast8_t compute(const T aValue)
|
||||
{
|
||||
return 31u - CountLeadingZeroes32(aValue | 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class FloorLog2<T, 8>
|
||||
{
|
||||
public:
|
||||
static uint_fast8_t compute(const T aValue)
|
||||
{
|
||||
return 63u - CountLeadingZeroes64(aValue | 1);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Compute the log of the greatest power of 2 less than or equal to |aValue|.
|
||||
*
|
||||
* FloorLog2(0..1) is 0;
|
||||
* FloorLog2(2..3) is 1;
|
||||
* FloorLog2(4..7) is 2;
|
||||
* FloorLog2(8..15) is 3; and so on.
|
||||
*/
|
||||
template<typename T>
|
||||
inline uint_fast8_t
|
||||
FloorLog2(const T aValue)
|
||||
{
|
||||
return detail::FloorLog2<T>::compute(aValue);
|
||||
}
|
||||
|
||||
/** A FloorLog2 variant that accepts only size_t. */
|
||||
inline uint_fast8_t
|
||||
FloorLog2Size(size_t aValue)
|
||||
{
|
||||
return FloorLog2(aValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the smallest power of 2 greater than or equal to |x|. |x| must not
|
||||
* be so great that the computed value would overflow |size_t|.
|
||||
*/
|
||||
inline size_t
|
||||
RoundUpPow2(size_t aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue <= (size_t(1) << (sizeof(size_t) * CHAR_BIT - 1)),
|
||||
"can't round up -- will overflow!");
|
||||
return size_t(1) << CeilingLog2(aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the bits of the given value left by the amount of the shift width.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T
|
||||
RotateLeft(const T aValue, uint_fast8_t aShift)
|
||||
{
|
||||
MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
|
||||
MOZ_ASSERT(aShift > 0,
|
||||
"Rotation by value length is undefined behavior, but compilers "
|
||||
"do not currently fold a test into the rotate instruction. "
|
||||
"Please remove this restriction when compilers optimize the "
|
||||
"zero case (http://blog.regehr.org/archives/1063).");
|
||||
static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
|
||||
return (aValue << aShift) | (aValue >> (sizeof(T) * CHAR_BIT - aShift));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the bits of the given value right by the amount of the shift width.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T
|
||||
RotateRight(const T aValue, uint_fast8_t aShift)
|
||||
{
|
||||
MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
|
||||
MOZ_ASSERT(aShift > 0,
|
||||
"Rotation by value length is undefined behavior, but compilers "
|
||||
"do not currently fold a test into the rotate instruction. "
|
||||
"Please remove this restriction when compilers optimize the "
|
||||
"zero case (http://blog.regehr.org/archives/1063).");
|
||||
static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
|
||||
return (aValue >> aShift) | (aValue << (sizeof(T) * CHAR_BIT - aShift));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if |x| is a power of two.
|
||||
* Zero is not an integer power of two. (-Inf is not an integer)
|
||||
*/
|
||||
template<typename T>
|
||||
constexpr bool
|
||||
IsPowerOfTwo(T x)
|
||||
{
|
||||
static_assert(IsUnsigned<T>::value,
|
||||
"IsPowerOfTwo requires unsigned values");
|
||||
return x && (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T
|
||||
Clamp(const T aValue, const T aMin, const T aMax)
|
||||
{
|
||||
static_assert(IsIntegral<T>::value,
|
||||
"Clamp accepts only integral types, so that it doesn't have"
|
||||
" to distinguish differently-signed zeroes (which users may"
|
||||
" or may not care to distinguish, likely at a perf cost) or"
|
||||
" to decide how to clamp NaN or a range with a NaN"
|
||||
" endpoint.");
|
||||
MOZ_ASSERT(aMin <= aMax);
|
||||
|
||||
if (aValue <= aMin)
|
||||
return aMin;
|
||||
if (aValue >= aMax)
|
||||
return aMax;
|
||||
return aValue;
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_MathAlgorithms_h */
|
||||
551
cocos2d-x/external/win32/include/spidermonkey/mozilla/Maybe.h
vendored
Executable file
551
cocos2d-x/external/win32/include/spidermonkey/mozilla/Maybe.h
vendored
Executable file
@@ -0,0 +1,551 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A class for optional values and in-place lazy construction. */
|
||||
|
||||
#ifndef mozilla_Maybe_h
|
||||
#define mozilla_Maybe_h
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <new> // for placement new
|
||||
#include <type_traits>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct Nothing { };
|
||||
|
||||
/*
|
||||
* Maybe is a container class which contains either zero or one elements. It
|
||||
* serves two roles. It can represent values which are *semantically* optional,
|
||||
* augmenting a type with an explicit 'Nothing' value. In this role, it provides
|
||||
* methods that make it easy to work with values that may be missing, along with
|
||||
* equality and comparison operators so that Maybe values can be stored in
|
||||
* containers. Maybe values can be constructed conveniently in expressions using
|
||||
* type inference, as follows:
|
||||
*
|
||||
* void doSomething(Maybe<Foo> aFoo) {
|
||||
* if (aFoo) // Make sure that aFoo contains a value...
|
||||
* aFoo->takeAction(); // and then use |aFoo->| to access it.
|
||||
* } // |*aFoo| also works!
|
||||
*
|
||||
* doSomething(Nothing()); // Passes a Maybe<Foo> containing no value.
|
||||
* doSomething(Some(Foo(100))); // Passes a Maybe<Foo> containing |Foo(100)|.
|
||||
*
|
||||
* You'll note that it's important to check whether a Maybe contains a value
|
||||
* before using it, using conversion to bool, |isSome()|, or |isNothing()|. You
|
||||
* can avoid these checks, and sometimes write more readable code, using
|
||||
* |valueOr()|, |ptrOr()|, and |refOr()|, which allow you to retrieve the value
|
||||
* in the Maybe and provide a default for the 'Nothing' case. You can also use
|
||||
* |apply()| to call a function only if the Maybe holds a value, and |map()| to
|
||||
* transform the value in the Maybe, returning another Maybe with a possibly
|
||||
* different type.
|
||||
*
|
||||
* Maybe's other role is to support lazily constructing objects without using
|
||||
* dynamic storage. A Maybe directly contains storage for a value, but it's
|
||||
* empty by default. |emplace()|, as mentioned above, can be used to construct a
|
||||
* value in Maybe's storage. The value a Maybe contains can be destroyed by
|
||||
* calling |reset()|; this will happen automatically if a Maybe is destroyed
|
||||
* while holding a value.
|
||||
*
|
||||
* It's a common idiom in C++ to use a pointer as a 'Maybe' type, with a null
|
||||
* value meaning 'Nothing' and any other value meaning 'Some'. You can convert
|
||||
* from such a pointer to a Maybe value using 'ToMaybe()'.
|
||||
*
|
||||
* Maybe is inspired by similar types in the standard library of many other
|
||||
* languages (e.g. Haskell's Maybe and Rust's Option). In the C++ world it's
|
||||
* very similar to std::optional, which was proposed for C++14 and originated in
|
||||
* Boost. The most important differences between Maybe and std::optional are:
|
||||
*
|
||||
* - std::optional<T> may be compared with T. We deliberately forbid that.
|
||||
* - std::optional allows in-place construction without a separate call to
|
||||
* |emplace()| by using a dummy |in_place_t| value to tag the appropriate
|
||||
* constructor.
|
||||
* - std::optional has |valueOr()|, equivalent to Maybe's |valueOr()|, but
|
||||
* lacks corresponding methods for |refOr()| and |ptrOr()|.
|
||||
* - std::optional lacks |map()| and |apply()|, making it less suitable for
|
||||
* functional-style code.
|
||||
* - std::optional lacks many convenience functions that Maybe has. Most
|
||||
* unfortunately, it lacks equivalents of the type-inferred constructor
|
||||
* functions |Some()| and |Nothing()|.
|
||||
*
|
||||
* N.B. GCC has missed optimizations with Maybe in the past and may generate
|
||||
* extra branches/loads/stores. Use with caution on hot paths; it's not known
|
||||
* whether or not this is still a problem.
|
||||
*/
|
||||
template<class T>
|
||||
class Maybe
|
||||
{
|
||||
bool mIsSome;
|
||||
AlignedStorage2<T> mStorage;
|
||||
|
||||
public:
|
||||
typedef T ValueType;
|
||||
|
||||
Maybe() : mIsSome(false) { }
|
||||
~Maybe() { reset(); }
|
||||
|
||||
MOZ_IMPLICIT Maybe(Nothing) : mIsSome(false) { }
|
||||
|
||||
Maybe(const Maybe& aOther)
|
||||
: mIsSome(false)
|
||||
{
|
||||
if (aOther.mIsSome) {
|
||||
emplace(*aOther);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe<T*> can be copy-constructed from a Maybe<U*> if U* and T* are
|
||||
* compatible, or from Maybe<decltype(nullptr)>.
|
||||
*/
|
||||
template<typename U,
|
||||
typename =
|
||||
typename std::enable_if<std::is_pointer<T>::value &&
|
||||
(std::is_same<U, decltype(nullptr)>::value ||
|
||||
(std::is_pointer<U>::value &&
|
||||
std::is_base_of<typename std::remove_pointer<T>::type,
|
||||
typename std::remove_pointer<U>::type>::value))>::type>
|
||||
MOZ_IMPLICIT
|
||||
Maybe(const Maybe<U>& aOther)
|
||||
: mIsSome(false)
|
||||
{
|
||||
if (aOther.isSome()) {
|
||||
emplace(*aOther);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe(Maybe&& aOther)
|
||||
: mIsSome(false)
|
||||
{
|
||||
if (aOther.mIsSome) {
|
||||
emplace(Move(*aOther));
|
||||
aOther.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe<T*> can be move-constructed from a Maybe<U*> if U* and T* are
|
||||
* compatible, or from Maybe<decltype(nullptr)>.
|
||||
*/
|
||||
template<typename U,
|
||||
typename =
|
||||
typename std::enable_if<std::is_pointer<T>::value &&
|
||||
(std::is_same<U, decltype(nullptr)>::value ||
|
||||
(std::is_pointer<U>::value &&
|
||||
std::is_base_of<typename std::remove_pointer<T>::type,
|
||||
typename std::remove_pointer<U>::type>::value))>::type>
|
||||
MOZ_IMPLICIT
|
||||
Maybe(Maybe<U>&& aOther)
|
||||
: mIsSome(false)
|
||||
{
|
||||
if (aOther.isSome()) {
|
||||
emplace(Move(*aOther));
|
||||
aOther.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Maybe& operator=(const Maybe& aOther)
|
||||
{
|
||||
if (&aOther != this) {
|
||||
if (aOther.mIsSome) {
|
||||
if (mIsSome) {
|
||||
// XXX(seth): The correct code for this branch, below, can't be used
|
||||
// due to a bug in Visual Studio 2010. See bug 1052940.
|
||||
/*
|
||||
ref() = aOther.ref();
|
||||
*/
|
||||
reset();
|
||||
emplace(*aOther);
|
||||
} else {
|
||||
emplace(*aOther);
|
||||
}
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Maybe& operator=(Maybe&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
|
||||
|
||||
if (aOther.mIsSome) {
|
||||
if (mIsSome) {
|
||||
ref() = Move(aOther.ref());
|
||||
} else {
|
||||
emplace(Move(*aOther));
|
||||
}
|
||||
aOther.reset();
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Methods that check whether this Maybe contains a value */
|
||||
explicit operator bool() const { return isSome(); }
|
||||
bool isSome() const { return mIsSome; }
|
||||
bool isNothing() const { return !mIsSome; }
|
||||
|
||||
/* Returns the contents of this Maybe<T> by value. Unsafe unless |isSome()|. */
|
||||
T value() const
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return ref();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of this Maybe<T> by value. If |isNothing()|, returns
|
||||
* the default value provided.
|
||||
*/
|
||||
template<typename V>
|
||||
T valueOr(V&& aDefault) const
|
||||
{
|
||||
if (isSome()) {
|
||||
return ref();
|
||||
}
|
||||
return Forward<V>(aDefault);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of this Maybe<T> by value. If |isNothing()|, returns
|
||||
* the value returned from the function or functor provided.
|
||||
*/
|
||||
template<typename F>
|
||||
T valueOrFrom(F&& aFunc) const
|
||||
{
|
||||
if (isSome()) {
|
||||
return ref();
|
||||
}
|
||||
return aFunc();
|
||||
}
|
||||
|
||||
/* Returns the contents of this Maybe<T> by pointer. Unsafe unless |isSome()|. */
|
||||
T* ptr()
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return &ref();
|
||||
}
|
||||
|
||||
const T* ptr() const
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return &ref();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of this Maybe<T> by pointer. If |isNothing()|,
|
||||
* returns the default value provided.
|
||||
*/
|
||||
T* ptrOr(T* aDefault)
|
||||
{
|
||||
if (isSome()) {
|
||||
return ptr();
|
||||
}
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
const T* ptrOr(const T* aDefault) const
|
||||
{
|
||||
if (isSome()) {
|
||||
return ptr();
|
||||
}
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of this Maybe<T> by pointer. If |isNothing()|,
|
||||
* returns the value returned from the function or functor provided.
|
||||
*/
|
||||
template<typename F>
|
||||
T* ptrOrFrom(F&& aFunc)
|
||||
{
|
||||
if (isSome()) {
|
||||
return ptr();
|
||||
}
|
||||
return aFunc();
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const T* ptrOrFrom(F&& aFunc) const
|
||||
{
|
||||
if (isSome()) {
|
||||
return ptr();
|
||||
}
|
||||
return aFunc();
|
||||
}
|
||||
|
||||
T* operator->()
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return ptr();
|
||||
}
|
||||
|
||||
const T* operator->() const
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return ptr();
|
||||
}
|
||||
|
||||
/* Returns the contents of this Maybe<T> by ref. Unsafe unless |isSome()|. */
|
||||
T& ref()
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return *mStorage.addr();
|
||||
}
|
||||
|
||||
const T& ref() const
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return *mStorage.addr();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of this Maybe<T> by ref. If |isNothing()|, returns
|
||||
* the default value provided.
|
||||
*/
|
||||
T& refOr(T& aDefault)
|
||||
{
|
||||
if (isSome()) {
|
||||
return ref();
|
||||
}
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
const T& refOr(const T& aDefault) const
|
||||
{
|
||||
if (isSome()) {
|
||||
return ref();
|
||||
}
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of this Maybe<T> by ref. If |isNothing()|, returns the
|
||||
* value returned from the function or functor provided.
|
||||
*/
|
||||
template<typename F>
|
||||
T& refOrFrom(F&& aFunc)
|
||||
{
|
||||
if (isSome()) {
|
||||
return ref();
|
||||
}
|
||||
return aFunc();
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const T& refOrFrom(F&& aFunc) const
|
||||
{
|
||||
if (isSome()) {
|
||||
return ref();
|
||||
}
|
||||
return aFunc();
|
||||
}
|
||||
|
||||
T& operator*()
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return ref();
|
||||
}
|
||||
|
||||
const T& operator*() const
|
||||
{
|
||||
MOZ_ASSERT(mIsSome);
|
||||
return ref();
|
||||
}
|
||||
|
||||
/* If |isSome()|, runs the provided function or functor on the contents of
|
||||
* this Maybe. */
|
||||
template<typename Func>
|
||||
Maybe& apply(Func aFunc)
|
||||
{
|
||||
if (isSome()) {
|
||||
aFunc(ref());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
const Maybe& apply(Func aFunc) const
|
||||
{
|
||||
if (isSome()) {
|
||||
aFunc(ref());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* If |isSome()|, runs the provided function and returns the result wrapped
|
||||
* in a Maybe. If |isNothing()|, returns an empty Maybe value.
|
||||
*/
|
||||
template<typename Func>
|
||||
auto map(Func aFunc) -> Maybe<decltype(aFunc(DeclVal<Maybe<T>>().ref()))>
|
||||
{
|
||||
using ReturnType = decltype(aFunc(ref()));
|
||||
if (isSome()) {
|
||||
Maybe<ReturnType> val;
|
||||
val.emplace(aFunc(ref()));
|
||||
return val;
|
||||
}
|
||||
return Maybe<ReturnType>();
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
auto map(Func aFunc) const -> Maybe<decltype(aFunc(DeclVal<Maybe<T>>().ref()))>
|
||||
{
|
||||
using ReturnType = decltype(aFunc(ref()));
|
||||
if (isSome()) {
|
||||
Maybe<ReturnType> val;
|
||||
val.emplace(aFunc(ref()));
|
||||
return val;
|
||||
}
|
||||
return Maybe<ReturnType>();
|
||||
}
|
||||
|
||||
/* If |isSome()|, empties this Maybe and destroys its contents. */
|
||||
void reset()
|
||||
{
|
||||
if (isSome()) {
|
||||
ref().T::~T();
|
||||
mIsSome = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructs a T value in-place in this empty Maybe<T>'s storage. The
|
||||
* arguments to |emplace()| are the parameters to T's constructor.
|
||||
*/
|
||||
template<typename... Args>
|
||||
void emplace(Args&&... aArgs)
|
||||
{
|
||||
MOZ_ASSERT(!mIsSome);
|
||||
::new (mStorage.addr()) T(Forward<Args>(aArgs)...);
|
||||
mIsSome = true;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Some() creates a Maybe<T> value containing the provided T value. If T has a
|
||||
* move constructor, it's used to make this as efficient as possible.
|
||||
*
|
||||
* Some() selects the type of Maybe it returns by removing any const, volatile,
|
||||
* or reference qualifiers from the type of the value you pass to it. This gives
|
||||
* it more intuitive behavior when used in expressions, but it also means that
|
||||
* if you need to construct a Maybe value that holds a const, volatile, or
|
||||
* reference value, you need to use emplace() instead.
|
||||
*/
|
||||
template<typename T>
|
||||
Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type>
|
||||
Some(T&& aValue)
|
||||
{
|
||||
typedef typename RemoveCV<typename RemoveReference<T>::Type>::Type U;
|
||||
Maybe<U> value;
|
||||
value.emplace(Forward<T>(aValue));
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type>
|
||||
ToMaybe(T* aPtr)
|
||||
{
|
||||
if (aPtr) {
|
||||
return Some(*aPtr);
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
/*
|
||||
* Two Maybe<T> values are equal if
|
||||
* - both are Nothing, or
|
||||
* - both are Some, and the values they contain are equal.
|
||||
*/
|
||||
template<typename T> bool
|
||||
operator==(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
if (aLHS.isNothing() != aRHS.isNothing()) {
|
||||
return false;
|
||||
}
|
||||
return aLHS.isNothing() || *aLHS == *aRHS;
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator!=(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
return !(aLHS == aRHS);
|
||||
}
|
||||
|
||||
/*
|
||||
* We support comparison to Nothing to allow reasonable expressions like:
|
||||
* if (maybeValue == Nothing()) { ... }
|
||||
*/
|
||||
template<typename T> bool
|
||||
operator==(const Maybe<T>& aLHS, const Nothing& aRHS)
|
||||
{
|
||||
return aLHS.isNothing();
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator!=(const Maybe<T>& aLHS, const Nothing& aRHS)
|
||||
{
|
||||
return !(aLHS == aRHS);
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator==(const Nothing& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
return aRHS.isNothing();
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator!=(const Nothing& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
return !(aLHS == aRHS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maybe<T> values are ordered in the same way T values are ordered, except that
|
||||
* Nothing comes before anything else.
|
||||
*/
|
||||
template<typename T> bool
|
||||
operator<(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
if (aLHS.isNothing()) {
|
||||
return aRHS.isSome();
|
||||
}
|
||||
if (aRHS.isNothing()) {
|
||||
return false;
|
||||
}
|
||||
return *aLHS < *aRHS;
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator>(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
return !(aLHS < aRHS || aLHS == aRHS);
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator<=(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
return aLHS < aRHS || aLHS == aRHS;
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
operator>=(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||
{
|
||||
return !(aLHS < aRHS);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Maybe_h */
|
||||
143
cocos2d-x/external/win32/include/spidermonkey/mozilla/MaybeOneOf.h
vendored
Executable file
143
cocos2d-x/external/win32/include/spidermonkey/mozilla/MaybeOneOf.h
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_MaybeOneOf_h
|
||||
#define mozilla_MaybeOneOf_h
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TemplateLib.h"
|
||||
|
||||
#include <new> // For placement new
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* MaybeOneOf<T1, T2> is like Maybe, but it supports constructing either T1
|
||||
* or T2. When a MaybeOneOf<T1, T2> is constructed, it is |empty()|, i.e.,
|
||||
* no value has been constructed and no destructor will be called when the
|
||||
* MaybeOneOf<T1, T2> is destroyed. Upon calling |construct<T1>()| or
|
||||
* |construct<T2>()|, a T1 or T2 object will be constructed with the given
|
||||
* arguments and that object will be destroyed when the owning MaybeOneOf is
|
||||
* destroyed.
|
||||
*/
|
||||
template<class T1, class T2>
|
||||
class MaybeOneOf
|
||||
{
|
||||
AlignedStorage<tl::Max<sizeof(T1), sizeof(T2)>::value> storage;
|
||||
|
||||
enum State { None, SomeT1, SomeT2 } state;
|
||||
template <class T, class Ignored = void> struct Type2State {};
|
||||
|
||||
template <class T>
|
||||
T& as()
|
||||
{
|
||||
MOZ_ASSERT(state == Type2State<T>::result);
|
||||
return *(T*)storage.addr();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T& as() const
|
||||
{
|
||||
MOZ_ASSERT(state == Type2State<T>::result);
|
||||
return *(T*)storage.addr();
|
||||
}
|
||||
|
||||
public:
|
||||
MaybeOneOf() : state(None) {}
|
||||
~MaybeOneOf() { destroyIfConstructed(); }
|
||||
|
||||
MaybeOneOf(MaybeOneOf&& rhs)
|
||||
: state(None)
|
||||
{
|
||||
if (!rhs.empty()) {
|
||||
if (rhs.constructed<T1>()) {
|
||||
construct<T1>(Move(rhs.as<T1>()));
|
||||
rhs.as<T1>().~T1();
|
||||
} else {
|
||||
construct<T2>(Move(rhs.as<T2>()));
|
||||
rhs.as<T2>().~T2();
|
||||
}
|
||||
rhs.state = None;
|
||||
}
|
||||
}
|
||||
|
||||
MaybeOneOf &operator=(MaybeOneOf&& rhs)
|
||||
{
|
||||
MOZ_ASSERT(this != &rhs, "Self-move is prohibited");
|
||||
this->~MaybeOneOf();
|
||||
new(this) MaybeOneOf(Move(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return state == None; }
|
||||
|
||||
template <class T>
|
||||
bool constructed() const { return state == Type2State<T>::result; }
|
||||
|
||||
template <class T, class... Args>
|
||||
void construct(Args&&... aArgs)
|
||||
{
|
||||
MOZ_ASSERT(state == None);
|
||||
state = Type2State<T>::result;
|
||||
::new (storage.addr()) T(Forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T& ref()
|
||||
{
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T& ref() const
|
||||
{
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
MOZ_ASSERT(state == SomeT1 || state == SomeT2);
|
||||
if (state == SomeT1) {
|
||||
as<T1>().~T1();
|
||||
} else if (state == SomeT2) {
|
||||
as<T2>().~T2();
|
||||
}
|
||||
state = None;
|
||||
}
|
||||
|
||||
void destroyIfConstructed()
|
||||
{
|
||||
if (!empty()) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MaybeOneOf(const MaybeOneOf& aOther) = delete;
|
||||
const MaybeOneOf& operator=(const MaybeOneOf& aOther) = delete;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
template <class Ignored>
|
||||
struct MaybeOneOf<T1, T2>::Type2State<T1, Ignored>
|
||||
{
|
||||
typedef MaybeOneOf<T1, T2> Enclosing;
|
||||
static const typename Enclosing::State result = Enclosing::SomeT1;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
template <class Ignored>
|
||||
struct MaybeOneOf<T1, T2>::Type2State<T2, Ignored>
|
||||
{
|
||||
typedef MaybeOneOf<T1, T2> Enclosing;
|
||||
static const typename Enclosing::State result = Enclosing::SomeT2;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_MaybeOneOf_h */
|
||||
129
cocos2d-x/external/win32/include/spidermonkey/mozilla/MemoryChecking.h
vendored
Executable file
129
cocos2d-x/external/win32/include/spidermonkey/mozilla/MemoryChecking.h
vendored
Executable file
@@ -0,0 +1,129 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Provides a common interface to the ASan (AddressSanitizer) and Valgrind
|
||||
* functions used to mark memory in certain ways. In detail, the following
|
||||
* three macros are provided:
|
||||
*
|
||||
* MOZ_MAKE_MEM_NOACCESS - Mark memory as unsafe to access (e.g. freed)
|
||||
* MOZ_MAKE_MEM_UNDEFINED - Mark memory as accessible, with content undefined
|
||||
* MOZ_MAKE_MEM_DEFINED - Mark memory as accessible, with content defined
|
||||
*
|
||||
* With Valgrind in use, these directly map to the three respective Valgrind
|
||||
* macros. With ASan in use, the NOACCESS macro maps to poisoning the memory,
|
||||
* while the UNDEFINED/DEFINED macros unpoison memory.
|
||||
*
|
||||
* With no memory checker available, all macros expand to the empty statement.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_MemoryChecking_h
|
||||
#define mozilla_MemoryChecking_h
|
||||
|
||||
#if defined(MOZ_VALGRIND)
|
||||
#include "valgrind/memcheck.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_ASAN) || defined(MOZ_VALGRIND)
|
||||
#define MOZ_HAVE_MEM_CHECKS 1
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_ASAN)
|
||||
#include <stddef.h>
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// In clang-cl based ASAN, we link against the memory poisoning functions
|
||||
// statically.
|
||||
#define MOZ_ASAN_VISIBILITY
|
||||
#else
|
||||
#define MOZ_ASAN_VISIBILITY MOZ_EXPORT
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
/* These definitions are usually provided through the
|
||||
* sanitizer/asan_interface.h header installed by ASan.
|
||||
*/
|
||||
void MOZ_ASAN_VISIBILITY
|
||||
__asan_poison_memory_region(void const volatile *addr, size_t size);
|
||||
void MOZ_ASAN_VISIBILITY
|
||||
__asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
||||
|
||||
#define MOZ_MAKE_MEM_NOACCESS(addr, size) \
|
||||
__asan_poison_memory_region((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
|
||||
__asan_unpoison_memory_region((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_DEFINED(addr, size) \
|
||||
__asan_unpoison_memory_region((addr), (size))
|
||||
|
||||
/*
|
||||
* These definitions are usually provided through the
|
||||
* sanitizer/lsan_interface.h header installed by LSan.
|
||||
*/
|
||||
void MOZ_EXPORT
|
||||
__lsan_ignore_object(const void *p);
|
||||
|
||||
}
|
||||
#elif defined(MOZ_MSAN)
|
||||
#include <stddef.h>
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
extern "C" {
|
||||
/* These definitions are usually provided through the
|
||||
* sanitizer/msan_interface.h header installed by MSan.
|
||||
*/
|
||||
void MOZ_EXPORT
|
||||
__msan_poison(void const volatile *addr, size_t size);
|
||||
void MOZ_EXPORT
|
||||
__msan_unpoison(void const volatile *addr, size_t size);
|
||||
|
||||
#define MOZ_MAKE_MEM_NOACCESS(addr, size) \
|
||||
__msan_poison((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
|
||||
__msan_poison((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_DEFINED(addr, size) \
|
||||
__msan_unpoison((addr), (size))
|
||||
}
|
||||
#elif defined(MOZ_VALGRIND)
|
||||
#define MOZ_MAKE_MEM_NOACCESS(addr, size) \
|
||||
VALGRIND_MAKE_MEM_NOACCESS((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
|
||||
VALGRIND_MAKE_MEM_UNDEFINED((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_DEFINED(addr, size) \
|
||||
VALGRIND_MAKE_MEM_DEFINED((addr), (size))
|
||||
#else
|
||||
|
||||
#define MOZ_MAKE_MEM_NOACCESS(addr, size) do {} while (0)
|
||||
#define MOZ_MAKE_MEM_UNDEFINED(addr, size) do {} while (0)
|
||||
#define MOZ_MAKE_MEM_DEFINED(addr, size) do {} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_LSAN_INTENTIONAL_LEAK(X) is a macro to tell LeakSanitizer that X
|
||||
* points to a value that will intentionally never be deallocated during
|
||||
* the execution of the process.
|
||||
*
|
||||
* Additional uses of this macro should be reviewed by people
|
||||
* conversant in leak-checking and/or MFBT peers.
|
||||
*/
|
||||
#if defined(MOZ_ASAN)
|
||||
# define MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(X) __lsan_ignore_object(X)
|
||||
#else
|
||||
# define MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(X) /* nothing */
|
||||
#endif // defined(MOZ_ASAN)
|
||||
|
||||
|
||||
#endif /* mozilla_MemoryChecking_h */
|
||||
30
cocos2d-x/external/win32/include/spidermonkey/mozilla/MemoryReporting.h
vendored
Executable file
30
cocos2d-x/external/win32/include/spidermonkey/mozilla/MemoryReporting.h
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Memory reporting infrastructure. */
|
||||
|
||||
#ifndef mozilla_MemoryReporting_h
|
||||
#define mozilla_MemoryReporting_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* This is for functions that are like malloc_usable_size. Such functions are
|
||||
* used for measuring the size of data structures.
|
||||
*/
|
||||
typedef size_t (*MallocSizeOf)(const void* p);
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef size_t (*MozMallocSizeOf)(const void* p);
|
||||
|
||||
#endif /* mozilla_MemoryReporting_h */
|
||||
238
cocos2d-x/external/win32/include/spidermonkey/mozilla/Move.h
vendored
Executable file
238
cocos2d-x/external/win32/include/spidermonkey/mozilla/Move.h
vendored
Executable file
@@ -0,0 +1,238 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* C++11-style, but C++98-usable, "move references" implementation. */
|
||||
|
||||
#ifndef mozilla_Move_h
|
||||
#define mozilla_Move_h
|
||||
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* "Move" References
|
||||
*
|
||||
* Some types can be copied much more efficiently if we know the original's
|
||||
* value need not be preserved --- that is, if we are doing a "move", not a
|
||||
* "copy". For example, if we have:
|
||||
*
|
||||
* Vector<T> u;
|
||||
* Vector<T> v(u);
|
||||
*
|
||||
* the constructor for v must apply a copy constructor to each element of u ---
|
||||
* taking time linear in the length of u. However, if we know we will not need u
|
||||
* any more once v has been initialized, then we could initialize v very
|
||||
* efficiently simply by stealing u's dynamically allocated buffer and giving it
|
||||
* to v --- a constant-time operation, regardless of the size of u.
|
||||
*
|
||||
* Moves often appear in container implementations. For example, when we append
|
||||
* to a vector, we may need to resize its buffer. This entails moving each of
|
||||
* its extant elements from the old, smaller buffer to the new, larger buffer.
|
||||
* But once the elements have been migrated, we're just going to throw away the
|
||||
* old buffer; we don't care if they still have their values. So if the vector's
|
||||
* element type can implement "move" more efficiently than "copy", the vector
|
||||
* resizing should by all means use a "move" operation. Hash tables should also
|
||||
* use moves when resizing their internal array as entries are added and
|
||||
* removed.
|
||||
*
|
||||
* The details of the optimization, and whether it's worth applying, vary
|
||||
* from one type to the next: copying an 'int' is as cheap as moving it, so
|
||||
* there's no benefit in distinguishing 'int' moves from copies. And while
|
||||
* some constructor calls for complex types are moves, many really have to
|
||||
* be copies, and can't be optimized this way. So we need:
|
||||
*
|
||||
* 1) a way for a type (like Vector) to announce that it can be moved more
|
||||
* efficiently than it can be copied, and provide an implementation of that
|
||||
* move operation; and
|
||||
*
|
||||
* 2) a way for a particular invocation of a copy constructor to say that it's
|
||||
* really a move, not a copy, and that the value of the original isn't
|
||||
* important afterwards (although it must still be safe to destroy).
|
||||
*
|
||||
* If a constructor has a single argument of type 'T&&' (an 'rvalue reference
|
||||
* to T'), that indicates that it is a 'move constructor'. That's 1). It should
|
||||
* move, not copy, its argument into the object being constructed. It may leave
|
||||
* the original in any safely-destructible state.
|
||||
*
|
||||
* If a constructor's argument is an rvalue, as in 'C(f(x))' or 'C(x + y)', as
|
||||
* opposed to an lvalue, as in 'C(x)', then overload resolution will prefer the
|
||||
* move constructor, if there is one. The 'mozilla::Move' function, defined in
|
||||
* this file, is an identity function you can use in a constructor invocation to
|
||||
* make any argument into an rvalue, like this: C(Move(x)). That's 2). (You
|
||||
* could use any function that works, but 'Move' indicates your intention
|
||||
* clearly.)
|
||||
*
|
||||
* Where we might define a copy constructor for a class C like this:
|
||||
*
|
||||
* C(const C& rhs) { ... copy rhs to this ... }
|
||||
*
|
||||
* we would declare a move constructor like this:
|
||||
*
|
||||
* C(C&& rhs) { .. move rhs to this ... }
|
||||
*
|
||||
* And where we might perform a copy like this:
|
||||
*
|
||||
* C c2(c1);
|
||||
*
|
||||
* we would perform a move like this:
|
||||
*
|
||||
* C c2(Move(c1));
|
||||
*
|
||||
* Note that 'T&&' implicitly converts to 'T&'. So you can pass a 'T&&' to an
|
||||
* ordinary copy constructor for a type that doesn't support a special move
|
||||
* constructor, and you'll just get a copy. This means that templates can use
|
||||
* Move whenever they know they won't use the original value any more, even if
|
||||
* they're not sure whether the type at hand has a specialized move constructor.
|
||||
* If it doesn't, the 'T&&' will just convert to a 'T&', and the ordinary copy
|
||||
* constructor will apply.
|
||||
*
|
||||
* A class with a move constructor can also provide a move assignment operator.
|
||||
* A generic definition would run this's destructor, and then apply the move
|
||||
* constructor to *this's memory. A typical definition:
|
||||
*
|
||||
* C& operator=(C&& rhs) {
|
||||
* MOZ_ASSERT(&rhs != this, "self-moves are prohibited");
|
||||
* this->~C();
|
||||
* new(this) C(Move(rhs));
|
||||
* return *this;
|
||||
* }
|
||||
*
|
||||
* With that in place, one can write move assignments like this:
|
||||
*
|
||||
* c2 = Move(c1);
|
||||
*
|
||||
* This destroys c2, moves c1's value to c2, and leaves c1 in an undefined but
|
||||
* destructible state.
|
||||
*
|
||||
* As we say, a move must leave the original in a "destructible" state. The
|
||||
* original's destructor will still be called, so if a move doesn't
|
||||
* actually steal all its resources, that's fine. We require only that the
|
||||
* move destination must take on the original's value; and that destructing
|
||||
* the original must not break the move destination.
|
||||
*
|
||||
* (Opinions differ on whether move assignment operators should deal with move
|
||||
* assignment of an object onto itself. It seems wise to either handle that
|
||||
* case, or assert that it does not occur.)
|
||||
*
|
||||
* Forwarding:
|
||||
*
|
||||
* Sometimes we want copy construction or assignment if we're passed an ordinary
|
||||
* value, but move construction if passed an rvalue reference. For example, if
|
||||
* our constructor takes two arguments and either could usefully be a move, it
|
||||
* seems silly to write out all four combinations:
|
||||
*
|
||||
* C::C(X& x, Y& y) : x(x), y(y) { }
|
||||
* C::C(X& x, Y&& y) : x(x), y(Move(y)) { }
|
||||
* C::C(X&& x, Y& y) : x(Move(x)), y(y) { }
|
||||
* C::C(X&& x, Y&& y) : x(Move(x)), y(Move(y)) { }
|
||||
*
|
||||
* To avoid this, C++11 has tweaks to make it possible to write what you mean.
|
||||
* The four constructor overloads above can be written as one constructor
|
||||
* template like so[0]:
|
||||
*
|
||||
* template <typename XArg, typename YArg>
|
||||
* C::C(XArg&& x, YArg&& y) : x(Forward<XArg>(x)), y(Forward<YArg>(y)) { }
|
||||
*
|
||||
* ("'Don't Repeat Yourself'? What's that?")
|
||||
*
|
||||
* This takes advantage of two new rules in C++11:
|
||||
*
|
||||
* - First, when a function template takes an argument that is an rvalue
|
||||
* reference to a template argument (like 'XArg&& x' and 'YArg&& y' above),
|
||||
* then when the argument is applied to an lvalue, the template argument
|
||||
* resolves to 'T&'; and when it is applied to an rvalue, the template
|
||||
* argument resolves to 'T'. Thus, in a call to C::C like:
|
||||
*
|
||||
* X foo(int);
|
||||
* Y yy;
|
||||
*
|
||||
* C(foo(5), yy)
|
||||
*
|
||||
* XArg would resolve to 'X', and YArg would resolve to 'Y&'.
|
||||
*
|
||||
* - Second, Whereas C++ used to forbid references to references, C++11 defines
|
||||
* 'collapsing rules': 'T& &', 'T&& &', and 'T& &&' (that is, any combination
|
||||
* involving an lvalue reference) now collapse to simply 'T&'; and 'T&& &&'
|
||||
* collapses to 'T&&'.
|
||||
*
|
||||
* Thus, in the call above, 'XArg&&' is 'X&&'; and 'YArg&&' is 'Y& &&', which
|
||||
* collapses to 'Y&'. Because the arguments are declared as rvalue references
|
||||
* to template arguments, the lvalue-ness "shines through" where present.
|
||||
*
|
||||
* Then, the 'Forward<T>' function --- you must invoke 'Forward' with its type
|
||||
* argument --- returns an lvalue reference or an rvalue reference to its
|
||||
* argument, depending on what T is. In our unified constructor definition, that
|
||||
* means that we'll invoke either the copy or move constructors for x and y,
|
||||
* depending on what we gave C's constructor. In our call, we'll move 'foo()'
|
||||
* into 'x', but copy 'yy' into 'y'.
|
||||
*
|
||||
* This header file defines Move and Forward in the mozilla namespace. It's up
|
||||
* to individual containers to annotate moves as such, by calling Move; and it's
|
||||
* up to individual types to define move constructors and assignment operators
|
||||
* when valuable.
|
||||
*
|
||||
* (C++11 says that the <utility> header file should define 'std::move' and
|
||||
* 'std::forward', which are just like our 'Move' and 'Forward'; but those
|
||||
* definitions aren't available in that header on all our platforms, so we
|
||||
* define them ourselves here.)
|
||||
*
|
||||
* 0. This pattern is known as "perfect forwarding". Interestingly, it is not
|
||||
* actually perfect, and it can't forward all possible argument expressions!
|
||||
* There is a C++11 issue: you can't form a reference to a bit-field. As a
|
||||
* workaround, assign the bit-field to a local variable and use that:
|
||||
*
|
||||
* // C is as above
|
||||
* struct S { int x : 1; } s;
|
||||
* C(s.x, 0); // BAD: s.x is a reference to a bit-field, can't form those
|
||||
* int tmp = s.x;
|
||||
* C(tmp, 0); // OK: tmp not a bit-field
|
||||
*/
|
||||
|
||||
/**
|
||||
* Identical to std::Move(); this is necessary until our stlport supports
|
||||
* std::move().
|
||||
*/
|
||||
template<typename T>
|
||||
inline typename RemoveReference<T>::Type&&
|
||||
Move(T&& aX)
|
||||
{
|
||||
return static_cast<typename RemoveReference<T>::Type&&>(aX);
|
||||
}
|
||||
|
||||
/**
|
||||
* These two overloads are identical to std::forward(); they are necessary until
|
||||
* our stlport supports std::forward().
|
||||
*/
|
||||
template<typename T>
|
||||
inline T&&
|
||||
Forward(typename RemoveReference<T>::Type& aX)
|
||||
{
|
||||
return static_cast<T&&>(aX);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T&&
|
||||
Forward(typename RemoveReference<T>::Type&& aX)
|
||||
{
|
||||
static_assert(!IsLvalueReference<T>::value,
|
||||
"misuse of Forward detected! try the other overload");
|
||||
return static_cast<T&&>(aX);
|
||||
}
|
||||
|
||||
/** Swap |aX| and |aY| using move-construction if possible. */
|
||||
template<typename T>
|
||||
inline void
|
||||
Swap(T& aX, T& aY)
|
||||
{
|
||||
T tmp(Move(aX));
|
||||
aX = Move(aY);
|
||||
aY = Move(tmp);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Move_h */
|
||||
209
cocos2d-x/external/win32/include/spidermonkey/mozilla/NotNull.h
vendored
Executable file
209
cocos2d-x/external/win32/include/spidermonkey/mozilla/NotNull.h
vendored
Executable file
@@ -0,0 +1,209 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_NotNull_h
|
||||
#define mozilla_NotNull_h
|
||||
|
||||
// It's often unclear if a particular pointer, be it raw (T*) or smart
|
||||
// (RefPtr<T>, nsCOMPtr<T>, etc.) can be null. This leads to missing null
|
||||
// checks (which can cause crashes) and unnecessary null checks (which clutter
|
||||
// the code).
|
||||
//
|
||||
// C++ has a built-in alternative that avoids these problems: references. This
|
||||
// module defines another alternative, NotNull, which can be used in cases
|
||||
// where references are not suitable.
|
||||
//
|
||||
// In the comments below we use the word "handle" to cover all varieties of
|
||||
// pointers and references.
|
||||
//
|
||||
// References
|
||||
// ----------
|
||||
// References are always non-null. (You can do |T& r = *p;| where |p| is null,
|
||||
// but that's undefined behaviour. C++ doesn't provide any built-in, ironclad
|
||||
// guarantee of non-nullness.)
|
||||
//
|
||||
// A reference works well when you need a temporary handle to an existing
|
||||
// single object, e.g. for passing a handle to a function, or as a local handle
|
||||
// within another object. (In Rust parlance, this is a "borrow".)
|
||||
//
|
||||
// A reference is less appropriate in the following cases.
|
||||
//
|
||||
// - As a primary handle to an object. E.g. code such as this is possible but
|
||||
// strange: |T& t = *new T(); ...; delete &t;|
|
||||
//
|
||||
// - As a handle to an array. It's common for |T*| to refer to either a single
|
||||
// |T| or an array of |T|, but |T&| cannot refer to an array of |T| because
|
||||
// you can't index off a reference (at least, not without first converting it
|
||||
// to a pointer).
|
||||
//
|
||||
// - When the handle identity is meaningful, e.g. if you have a hashtable of
|
||||
// handles, because you have to use |&| on the reference to convert it to a
|
||||
// pointer.
|
||||
//
|
||||
// - Some people don't like using non-const references as function parameters,
|
||||
// because it is not clear at the call site that the argument might be
|
||||
// modified.
|
||||
//
|
||||
// - When you need "smart" behaviour. E.g. we lack reference equivalents to
|
||||
// RefPtr and nsCOMPtr.
|
||||
//
|
||||
// - When interfacing with code that uses pointers a lot, sometimes using a
|
||||
// reference just feels like an odd fit.
|
||||
//
|
||||
// Furthermore, a reference is impossible in the following cases.
|
||||
//
|
||||
// - When the handle is rebound to another object. References don't allow this.
|
||||
//
|
||||
// - When the handle has type |void|. |void&| is not allowed.
|
||||
//
|
||||
// NotNull is an alternative that can be used in any of the above cases except
|
||||
// for the last one, where the handle type is |void|. See below.
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// NotNull can be used to wrap a "base" pointer (raw or smart) to indicate it
|
||||
// is not null. Some examples:
|
||||
//
|
||||
// - NotNull<char*>
|
||||
// - NotNull<RefPtr<Event>>
|
||||
// - NotNull<nsCOMPtr<Event>>
|
||||
//
|
||||
// NotNull has the following notable properties.
|
||||
//
|
||||
// - It has zero space overhead.
|
||||
//
|
||||
// - It must be initialized explicitly. There is no default initialization.
|
||||
//
|
||||
// - It auto-converts to the base pointer type.
|
||||
//
|
||||
// - It does not auto-convert from a base pointer. Implicit conversion from a
|
||||
// less-constrained type (e.g. T*) to a more-constrained type (e.g.
|
||||
// NotNull<T*>) is dangerous. Creation and assignment from a base pointer can
|
||||
// only be done with WrapNotNull(), which makes them impossible to overlook,
|
||||
// both when writing and reading code.
|
||||
//
|
||||
// - When initialized (or assigned) it is checked, and if it is null we abort.
|
||||
// This guarantees that it cannot be null.
|
||||
//
|
||||
// - |operator bool()| is deleted. This means you cannot check a NotNull in a
|
||||
// boolean context, which eliminates the possibility of unnecessary null
|
||||
// checks.
|
||||
//
|
||||
// NotNull currently doesn't work with UniquePtr. See
|
||||
// https://github.com/Microsoft/GSL/issues/89 for some discussion.
|
||||
//
|
||||
template <typename T>
|
||||
class NotNull
|
||||
{
|
||||
template <typename U> friend NotNull<U> WrapNotNull(U aBasePtr);
|
||||
|
||||
T mBasePtr;
|
||||
|
||||
// This constructor is only used by WrapNotNull().
|
||||
template <typename U>
|
||||
explicit NotNull(U aBasePtr) : mBasePtr(aBasePtr) {}
|
||||
|
||||
public:
|
||||
// Disallow default construction.
|
||||
NotNull() = delete;
|
||||
|
||||
// Construct/assign from another NotNull with a compatible base pointer type.
|
||||
template <typename U>
|
||||
MOZ_IMPLICIT NotNull(const NotNull<U>& aOther) : mBasePtr(aOther.get()) {}
|
||||
|
||||
// Default copy/move construction and assignment.
|
||||
NotNull(const NotNull<T>&) = default;
|
||||
NotNull<T>& operator=(const NotNull<T>&) = default;
|
||||
NotNull(NotNull<T>&&) = default;
|
||||
NotNull<T>& operator=(NotNull<T>&&) = default;
|
||||
|
||||
// Disallow null checks, which are unnecessary for this type.
|
||||
explicit operator bool() const = delete;
|
||||
|
||||
// Explicit conversion to a base pointer. Use only to resolve ambiguity or to
|
||||
// get a castable pointer.
|
||||
const T& get() const { return mBasePtr; }
|
||||
|
||||
// Implicit conversion to a base pointer. Preferable to get().
|
||||
operator const T&() const { return get(); }
|
||||
|
||||
// Dereference operators.
|
||||
const T& operator->() const { return get(); }
|
||||
decltype(*mBasePtr) operator*() const { return *mBasePtr; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
NotNull<T>
|
||||
WrapNotNull(const T aBasePtr)
|
||||
{
|
||||
NotNull<T> notNull(aBasePtr);
|
||||
MOZ_RELEASE_ASSERT(aBasePtr);
|
||||
return notNull;
|
||||
}
|
||||
|
||||
// Compare two NotNulls.
|
||||
template <typename T, typename U>
|
||||
inline bool
|
||||
operator==(const NotNull<T>& aLhs, const NotNull<U>& aRhs)
|
||||
{
|
||||
return aLhs.get() == aRhs.get();
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline bool
|
||||
operator!=(const NotNull<T>& aLhs, const NotNull<U>& aRhs)
|
||||
{
|
||||
return aLhs.get() != aRhs.get();
|
||||
}
|
||||
|
||||
// Compare a NotNull to a base pointer.
|
||||
template <typename T, typename U>
|
||||
inline bool
|
||||
operator==(const NotNull<T>& aLhs, const U& aRhs)
|
||||
{
|
||||
return aLhs.get() == aRhs;
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline bool
|
||||
operator!=(const NotNull<T>& aLhs, const U& aRhs)
|
||||
{
|
||||
return aLhs.get() != aRhs;
|
||||
}
|
||||
|
||||
// Compare a base pointer to a NotNull.
|
||||
template <typename T, typename U>
|
||||
inline bool
|
||||
operator==(const T& aLhs, const NotNull<U>& aRhs)
|
||||
{
|
||||
return aLhs == aRhs.get();
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline bool
|
||||
operator!=(const T& aLhs, const NotNull<U>& aRhs)
|
||||
{
|
||||
return aLhs != aRhs.get();
|
||||
}
|
||||
|
||||
// Disallow comparing a NotNull to a nullptr.
|
||||
template <typename T>
|
||||
bool
|
||||
operator==(const NotNull<T>&, decltype(nullptr)) = delete;
|
||||
template <typename T>
|
||||
bool
|
||||
operator!=(const NotNull<T>&, decltype(nullptr)) = delete;
|
||||
|
||||
// Disallow comparing a nullptr to a NotNull.
|
||||
template <typename T>
|
||||
bool
|
||||
operator==(decltype(nullptr), const NotNull<T>&) = delete;
|
||||
template <typename T>
|
||||
bool
|
||||
operator!=(decltype(nullptr), const NotNull<T>&) = delete;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_NotNull_h */
|
||||
31
cocos2d-x/external/win32/include/spidermonkey/mozilla/NullPtr.h
vendored
Executable file
31
cocos2d-x/external/win32/include/spidermonkey/mozilla/NullPtr.h
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implements a mozilla::IsNullPointer<T> type trait. */
|
||||
|
||||
#ifndef mozilla_NullPtr_h
|
||||
#define mozilla_NullPtr_h
|
||||
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* IsNullPointer<T>::value is true iff T is decltype(nullptr).
|
||||
*
|
||||
* Ideally this would be in TypeTraits.h, but C++11 omitted std::is_null_pointer
|
||||
* (fixed in C++14), so in the interests of easing a switch to <type_traits>,
|
||||
* this trait lives elsewhere.
|
||||
*/
|
||||
template<typename T>
|
||||
struct IsNullPointer : FalseType {};
|
||||
|
||||
template<>
|
||||
struct IsNullPointer<decltype(nullptr)> : TrueType {};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_NullPtr_h */
|
||||
44
cocos2d-x/external/win32/include/spidermonkey/mozilla/Opaque.h
vendored
Executable file
44
cocos2d-x/external/win32/include/spidermonkey/mozilla/Opaque.h
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* An opaque integral type supporting only comparison operators. */
|
||||
|
||||
#ifndef mozilla_Opaque_h
|
||||
#define mozilla_Opaque_h
|
||||
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Opaque<T> is a replacement for integral T in cases where only comparisons
|
||||
* must be supported, and it's desirable to prevent accidental dependency on
|
||||
* exact values.
|
||||
*/
|
||||
template<typename T>
|
||||
class Opaque final
|
||||
{
|
||||
static_assert(mozilla::IsIntegral<T>::value,
|
||||
"mozilla::Opaque only supports integral types");
|
||||
|
||||
T mValue;
|
||||
|
||||
public:
|
||||
Opaque() {}
|
||||
explicit Opaque(T aValue) : mValue(aValue) {}
|
||||
|
||||
bool operator==(const Opaque& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
|
||||
bool operator!=(const Opaque& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Opaque_h */
|
||||
52
cocos2d-x/external/win32/include/spidermonkey/mozilla/OperatorNewExtensions.h
vendored
Executable file
52
cocos2d-x/external/win32/include/spidermonkey/mozilla/OperatorNewExtensions.h
vendored
Executable file
@@ -0,0 +1,52 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A version of |operator new| that eschews mandatory null-checks. */
|
||||
|
||||
#ifndef mozilla_OperatorNewExtensions_h
|
||||
#define mozilla_OperatorNewExtensions_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
// Credit goes to WebKit for this implementation, cf.
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=74676
|
||||
namespace mozilla {
|
||||
enum NotNullTag {
|
||||
KnownNotNull,
|
||||
};
|
||||
} // namespace mozilla
|
||||
|
||||
/*
|
||||
* The logic here is a little subtle. [expr.new] states that if the allocation
|
||||
* function being called returns null, then object initialization must not be
|
||||
* done, and the entirety of the new expression must return null. Non-throwing
|
||||
* (noexcept) functions are defined to return null to indicate failure. The
|
||||
* standard placement operator new is defined in such a way, and so it requires
|
||||
* a null check, even when that null check would be extraneous. Functions
|
||||
* declared without such a specification are defined to throw std::bad_alloc if
|
||||
* they fail, and return a non-null pointer otherwise. We compile without
|
||||
* exceptions, so any placement new overload we define that doesn't declare
|
||||
* itself as noexcept must therefore avoid generating a null check. Below is
|
||||
* just such an overload.
|
||||
*
|
||||
* You might think that MOZ_NONNULL might perform the same function, but
|
||||
* MOZ_NONNULL isn't supported on all of our compilers, and even when it is
|
||||
* supported, doesn't work on all the versions we support. And even keeping
|
||||
* those limitations in mind, we can't put MOZ_NONNULL on the global,
|
||||
* standardized placement new function in any event.
|
||||
*
|
||||
* We deliberately don't add MOZ_NONNULL(3) to tag |p| as non-null, to benefit
|
||||
* hypothetical static analyzers. Doing so makes |MOZ_ASSERT(p)|'s internal
|
||||
* test vacuous, and some compilers warn about such vacuous tests.
|
||||
*/
|
||||
inline void*
|
||||
operator new(size_t, mozilla::NotNullTag, void* p)
|
||||
{
|
||||
MOZ_ASSERT(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif // mozilla_OperatorNewExtensions_h
|
||||
219
cocos2d-x/external/win32/include/spidermonkey/mozilla/Pair.h
vendored
Executable file
219
cocos2d-x/external/win32/include/spidermonkey/mozilla/Pair.h
vendored
Executable file
@@ -0,0 +1,219 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A class holding a pair of objects that tries to conserve storage space. */
|
||||
|
||||
#ifndef mozilla_Pair_h
|
||||
#define mozilla_Pair_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum StorageType { AsBase, AsMember };
|
||||
|
||||
// Optimize storage using the Empty Base Optimization -- that empty base classes
|
||||
// don't take up space -- to optimize size when one or the other class is
|
||||
// stateless and can be used as a base class.
|
||||
//
|
||||
// The extra conditions on storage for B are necessary so that PairHelper won't
|
||||
// ambiguously inherit from either A or B, such that one or the other base class
|
||||
// would be inaccessible.
|
||||
template<typename A, typename B,
|
||||
detail::StorageType =
|
||||
IsEmpty<A>::value ? detail::AsBase : detail::AsMember,
|
||||
detail::StorageType =
|
||||
IsEmpty<B>::value && !IsBaseOf<A, B>::value && !IsBaseOf<B, A>::value
|
||||
? detail::AsBase
|
||||
: detail::AsMember>
|
||||
struct PairHelper;
|
||||
|
||||
template<typename A, typename B>
|
||||
struct PairHelper<A, B, AsMember, AsMember>
|
||||
{
|
||||
protected:
|
||||
template<typename AArg, typename BArg>
|
||||
PairHelper(AArg&& aA, BArg&& aB)
|
||||
: mFirstA(Forward<AArg>(aA)),
|
||||
mSecondB(Forward<BArg>(aB))
|
||||
{}
|
||||
|
||||
A& first() { return mFirstA; }
|
||||
const A& first() const { return mFirstA; }
|
||||
B& second() { return mSecondB; }
|
||||
const B& second() const { return mSecondB; }
|
||||
|
||||
void swap(PairHelper& aOther)
|
||||
{
|
||||
Swap(mFirstA, aOther.mFirstA);
|
||||
Swap(mSecondB, aOther.mSecondB);
|
||||
}
|
||||
|
||||
private:
|
||||
A mFirstA;
|
||||
B mSecondB;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct PairHelper<A, B, AsMember, AsBase> : private B
|
||||
{
|
||||
protected:
|
||||
template<typename AArg, typename BArg>
|
||||
PairHelper(AArg&& aA, BArg&& aB)
|
||||
: B(Forward<BArg>(aB)),
|
||||
mFirstA(Forward<AArg>(aA))
|
||||
{}
|
||||
|
||||
A& first() { return mFirstA; }
|
||||
const A& first() const { return mFirstA; }
|
||||
B& second() { return *this; }
|
||||
const B& second() const { return *this; }
|
||||
|
||||
void swap(PairHelper& aOther)
|
||||
{
|
||||
Swap(mFirstA, aOther.mFirstA);
|
||||
Swap(static_cast<B&>(*this), static_cast<B&>(aOther));
|
||||
}
|
||||
|
||||
private:
|
||||
A mFirstA;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct PairHelper<A, B, AsBase, AsMember> : private A
|
||||
{
|
||||
protected:
|
||||
template<typename AArg, typename BArg>
|
||||
PairHelper(AArg&& aA, BArg&& aB)
|
||||
: A(Forward<AArg>(aA)),
|
||||
mSecondB(Forward<BArg>(aB))
|
||||
{}
|
||||
|
||||
A& first() { return *this; }
|
||||
const A& first() const { return *this; }
|
||||
B& second() { return mSecondB; }
|
||||
const B& second() const { return mSecondB; }
|
||||
|
||||
void swap(PairHelper& aOther)
|
||||
{
|
||||
Swap(static_cast<A&>(*this), static_cast<A&>(aOther));
|
||||
Swap(mSecondB, aOther.mSecondB);
|
||||
}
|
||||
|
||||
private:
|
||||
B mSecondB;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct PairHelper<A, B, AsBase, AsBase> : private A, private B
|
||||
{
|
||||
protected:
|
||||
template<typename AArg, typename BArg>
|
||||
PairHelper(AArg&& aA, BArg&& aB)
|
||||
: A(Forward<AArg>(aA)),
|
||||
B(Forward<BArg>(aB))
|
||||
{}
|
||||
|
||||
A& first() { return static_cast<A&>(*this); }
|
||||
const A& first() const { return static_cast<A&>(*this); }
|
||||
B& second() { return static_cast<B&>(*this); }
|
||||
const B& second() const { return static_cast<B&>(*this); }
|
||||
|
||||
void swap(PairHelper& aOther)
|
||||
{
|
||||
Swap(static_cast<A&>(*this), static_cast<A&>(aOther));
|
||||
Swap(static_cast<B&>(*this), static_cast<B&>(aOther));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Pair is the logical concatenation of an instance of A with an instance B.
|
||||
* Space is conserved when possible. Neither A nor B may be a final class.
|
||||
*
|
||||
* It's typically clearer to have individual A and B member fields. Except if
|
||||
* you want the space-conserving qualities of Pair, you're probably better off
|
||||
* not using this!
|
||||
*
|
||||
* No guarantees are provided about the memory layout of A and B, the order of
|
||||
* initialization or destruction of A and B, and so on. (This is approximately
|
||||
* required to optimize space usage.) The first/second names are merely
|
||||
* conceptual!
|
||||
*/
|
||||
template<typename A, typename B>
|
||||
struct Pair
|
||||
: private detail::PairHelper<A, B>
|
||||
{
|
||||
typedef typename detail::PairHelper<A, B> Base;
|
||||
|
||||
public:
|
||||
template<typename AArg, typename BArg>
|
||||
Pair(AArg&& aA, BArg&& aB)
|
||||
: Base(Forward<AArg>(aA), Forward<BArg>(aB))
|
||||
{}
|
||||
|
||||
Pair(Pair&& aOther)
|
||||
: Base(Move(aOther.first()), Move(aOther.second()))
|
||||
{ }
|
||||
|
||||
Pair(const Pair& aOther) = default;
|
||||
|
||||
Pair& operator=(Pair&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
|
||||
|
||||
first() = Move(aOther.first());
|
||||
second() = Move(aOther.second());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Pair& operator=(const Pair& aOther) = default;
|
||||
|
||||
/** The A instance. */
|
||||
using Base::first;
|
||||
/** The B instance. */
|
||||
using Base::second;
|
||||
|
||||
/** Swap this pair with another pair. */
|
||||
void swap(Pair& aOther) { Base::swap(aOther); }
|
||||
};
|
||||
|
||||
template<typename A, class B>
|
||||
void
|
||||
Swap(Pair<A, B>& aX, Pair<A, B>& aY)
|
||||
{
|
||||
aX.swap(aY);
|
||||
}
|
||||
|
||||
/**
|
||||
* MakePair allows you to construct a Pair instance using type inference. A call
|
||||
* like this:
|
||||
*
|
||||
* MakePair(Foo(), Bar())
|
||||
*
|
||||
* will return a Pair<Foo, Bar>.
|
||||
*/
|
||||
template<typename A, typename B>
|
||||
Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
|
||||
typename RemoveCV<typename RemoveReference<B>::Type>::Type>
|
||||
MakePair(A&& aA, B&& aB)
|
||||
{
|
||||
return
|
||||
Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
|
||||
typename RemoveCV<typename RemoveReference<B>::Type>::Type>(
|
||||
Forward<A>(aA),
|
||||
Forward<B>(aB));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Pair_h */
|
||||
196
cocos2d-x/external/win32/include/spidermonkey/mozilla/PodOperations.h
vendored
Executable file
196
cocos2d-x/external/win32/include/spidermonkey/mozilla/PodOperations.h
vendored
Executable file
@@ -0,0 +1,196 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Operations for zeroing POD types, arrays, and so on.
|
||||
*
|
||||
* These operations are preferable to memset, memcmp, and the like because they
|
||||
* don't require remembering to multiply by sizeof(T), array lengths, and so on
|
||||
* everywhere.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_PodOperations_h
|
||||
#define mozilla_PodOperations_h
|
||||
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/** Set the contents of |aT| to 0. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodZero(T* aT)
|
||||
{
|
||||
memset(aT, 0, sizeof(T));
|
||||
}
|
||||
|
||||
/** Set the contents of |aNElem| elements starting at |aT| to 0. */
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodZero(T* aT, size_t aNElem)
|
||||
{
|
||||
/*
|
||||
* This function is often called with 'aNElem' small; we use an inline loop
|
||||
* instead of calling 'memset' with a non-constant length. The compiler
|
||||
* should inline the memset call with constant size, though.
|
||||
*/
|
||||
for (T* end = aT + aNElem; aT < end; aT++) {
|
||||
memset(aT, 0, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Arrays implicitly convert to pointers to their first element, which is
|
||||
* dangerous when combined with the above PodZero definitions. Adding an
|
||||
* overload for arrays is ambiguous, so we need another identifier. The
|
||||
* ambiguous overload is left to catch mistaken uses of PodZero; if you get a
|
||||
* compile error involving PodZero and array types, use PodArrayZero instead.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
static void PodZero(T (&aT)[N]) = delete;
|
||||
template<typename T, size_t N>
|
||||
static void PodZero(T (&aT)[N], size_t aNElem) = delete;
|
||||
|
||||
/** Set the contents of the array |aT| to zero. */
|
||||
template <class T, size_t N>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodArrayZero(T (&aT)[N])
|
||||
{
|
||||
memset(aT, 0, N * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodArrayZero(Array<T, N>& aArr)
|
||||
{
|
||||
memset(&aArr[0], 0, N * sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign |*aSrc| to |*aDst|. The locations must not be the same and must not
|
||||
* overlap.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodAssign(T* aDst, const T* aSrc)
|
||||
{
|
||||
MOZ_ASSERT(aDst + 1 <= aSrc || aSrc + 1 <= aDst,
|
||||
"destination and source must not overlap");
|
||||
memcpy(reinterpret_cast<char*>(aDst), reinterpret_cast<const char*>(aSrc),
|
||||
sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy |aNElem| T elements from |aSrc| to |aDst|. The two memory ranges must
|
||||
* not overlap!
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodCopy(T* aDst, const T* aSrc, size_t aNElem)
|
||||
{
|
||||
MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst,
|
||||
"destination and source must not overlap");
|
||||
if (aNElem < 128) {
|
||||
/*
|
||||
* Avoid using operator= in this loop, as it may have been
|
||||
* intentionally deleted by the POD type.
|
||||
*/
|
||||
for (const T* srcend = aSrc + aNElem; aSrc < srcend; aSrc++, aDst++) {
|
||||
PodAssign(aDst, aSrc);
|
||||
}
|
||||
} else {
|
||||
memcpy(aDst, aSrc, aNElem * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodCopy(volatile T* aDst, const volatile T* aSrc, size_t aNElem)
|
||||
{
|
||||
MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst,
|
||||
"destination and source must not overlap");
|
||||
|
||||
/*
|
||||
* Volatile |aDst| requires extra work, because it's undefined behavior to
|
||||
* modify volatile objects using the mem* functions. Just write out the
|
||||
* loops manually, using operator= rather than memcpy for the same reason,
|
||||
* and let the compiler optimize to the extent it can.
|
||||
*/
|
||||
for (const volatile T* srcend = aSrc + aNElem;
|
||||
aSrc < srcend;
|
||||
aSrc++, aDst++) {
|
||||
*aDst = *aSrc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the contents of the array |aSrc| into the array |aDst|, both of size N.
|
||||
* The arrays must not overlap!
|
||||
*/
|
||||
template <class T, size_t N>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodArrayCopy(T (&aDst)[N], const T (&aSrc)[N])
|
||||
{
|
||||
PodCopy(aDst, aSrc, N);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the memory for |aNElem| T elements from |aSrc| to |aDst|. If the two
|
||||
* memory ranges overlap, then the effect is as if the |aNElem| elements are
|
||||
* first copied from |aSrc| to a temporary array, and then from the temporary
|
||||
* array to |aDst|.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
PodMove(T* aDst, const T* aSrc, size_t aNElem)
|
||||
{
|
||||
MOZ_ASSERT(aNElem <= SIZE_MAX / sizeof(T),
|
||||
"trying to move an impossible number of elements");
|
||||
memmove(aDst, aSrc, aNElem * sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the |len| elements at |one| are memory-identical to the
|
||||
* |len| elements at |two|.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
PodEqual(const T* one, const T* two, size_t len)
|
||||
{
|
||||
if (len < 128) {
|
||||
const T* p1end = one + len;
|
||||
const T* p1 = one;
|
||||
const T* p2 = two;
|
||||
for (; p1 < p1end; p1++, p2++) {
|
||||
if (*p1 != *p2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return !memcmp(one, two, len * sizeof(T));
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether the |N| elements at |one| are memory-identical to the
|
||||
* |N| elements at |two|.
|
||||
*/
|
||||
template <class T, size_t N>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
PodEqual(const T (&one)[N], const T (&two)[N])
|
||||
{
|
||||
return PodEqual(one, two, N);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_PodOperations_h */
|
||||
108
cocos2d-x/external/win32/include/spidermonkey/mozilla/Poison.h
vendored
Executable file
108
cocos2d-x/external/win32/include/spidermonkey/mozilla/Poison.h
vendored
Executable file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* A poison value that can be used to fill a memory space with
|
||||
* an address that leads to a safe crash when dereferenced.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_Poison_h
|
||||
#define mozilla_Poison_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
MOZ_BEGIN_EXTERN_C
|
||||
|
||||
extern MFBT_DATA uintptr_t gMozillaPoisonValue;
|
||||
|
||||
/**
|
||||
* @return the poison value.
|
||||
*/
|
||||
inline uintptr_t mozPoisonValue()
|
||||
{
|
||||
return gMozillaPoisonValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the memory block of aSize bytes at aPtr with the poison value.
|
||||
* aPtr MUST be aligned at a sizeof(uintptr_t) boundary.
|
||||
* Only an even number of sizeof(uintptr_t) bytes are overwritten, the last
|
||||
* few bytes (if any) is not overwritten.
|
||||
*/
|
||||
inline void mozWritePoison(void* aPtr, size_t aSize)
|
||||
{
|
||||
const uintptr_t POISON = mozPoisonValue();
|
||||
char* p = (char*)aPtr;
|
||||
char* limit = p + aSize;
|
||||
MOZ_ASSERT((uintptr_t)aPtr % sizeof(uintptr_t) == 0, "bad alignment");
|
||||
MOZ_ASSERT(aSize >= sizeof(uintptr_t), "poisoning this object has no effect");
|
||||
for (; p < limit; p += sizeof(uintptr_t)) {
|
||||
*((uintptr_t*)p) = POISON;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the poison value.
|
||||
* This should only be called once.
|
||||
*/
|
||||
extern MFBT_API void mozPoisonValueInit();
|
||||
|
||||
/* Values annotated by CrashReporter */
|
||||
extern MFBT_DATA uintptr_t gMozillaPoisonBase;
|
||||
extern MFBT_DATA uintptr_t gMozillaPoisonSize;
|
||||
|
||||
MOZ_END_EXTERN_C
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* This class is designed to cause crashes when various kinds of memory
|
||||
* corruption are observed. For instance, let's say we have a class C where we
|
||||
* suspect out-of-bounds writes to some members. We can insert a member of type
|
||||
* Poison near the members we suspect are being corrupted by out-of-bounds
|
||||
* writes. Or perhaps we have a class K we suspect is subject to use-after-free
|
||||
* violations, in which case it doesn't particularly matter where in the class
|
||||
* we add the member of type Poison.
|
||||
*
|
||||
* In either case, we then insert calls to Check() throughout the code. Doing
|
||||
* so enables us to narrow down the location where the corruption is occurring.
|
||||
* A pleasant side-effect of these additional Check() calls is that crash
|
||||
* signatures may become more regular, as crashes will ideally occur
|
||||
* consolidated at the point of a Check(), rather than scattered about at
|
||||
* various uses of the corrupted memory.
|
||||
*/
|
||||
class CorruptionCanary {
|
||||
public:
|
||||
CorruptionCanary() {
|
||||
mValue = kCanarySet;
|
||||
}
|
||||
|
||||
~CorruptionCanary() {
|
||||
Check();
|
||||
mValue = mozPoisonValue();
|
||||
}
|
||||
|
||||
void Check() const {
|
||||
if (mValue != kCanarySet) {
|
||||
MOZ_CRASH("Canary check failed, check lifetime");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const uintptr_t kCanarySet = 0x0f0b0f0b;
|
||||
uintptr_t mValue;
|
||||
};
|
||||
|
||||
} // mozilla
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Poison_h */
|
||||
58
cocos2d-x/external/win32/include/spidermonkey/mozilla/Range.h
vendored
Executable file
58
cocos2d-x/external/win32/include/spidermonkey/mozilla/Range.h
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_Range_h
|
||||
#define mozilla_Range_h
|
||||
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Range<T> is a tuple containing a pointer and a length.
|
||||
template <typename T>
|
||||
class Range
|
||||
{
|
||||
const RangedPtr<T> mStart;
|
||||
const RangedPtr<T> mEnd;
|
||||
|
||||
public:
|
||||
Range() : mStart(nullptr, 0), mEnd(nullptr, 0) {}
|
||||
Range(T* aPtr, size_t aLength)
|
||||
: mStart(aPtr, aPtr, aPtr + aLength),
|
||||
mEnd(aPtr + aLength, aPtr, aPtr + aLength)
|
||||
{}
|
||||
Range(const RangedPtr<T>& aStart, const RangedPtr<T>& aEnd)
|
||||
: mStart(aStart.get(), aStart.get(), aEnd.get()),
|
||||
mEnd(aEnd.get(), aStart.get(), aEnd.get())
|
||||
{
|
||||
// Only accept two RangedPtrs within the same range.
|
||||
aStart.checkIdenticalRange(aEnd);
|
||||
MOZ_ASSERT(aStart <= aEnd);
|
||||
}
|
||||
|
||||
template<typename U,
|
||||
class = typename EnableIf<IsConvertible<U (*)[], T (*)[]>::value,
|
||||
int>::Type>
|
||||
MOZ_IMPLICIT Range(const Range<U>& aOther)
|
||||
: mStart(aOther.mStart),
|
||||
mEnd(aOther.mEnd)
|
||||
{}
|
||||
|
||||
RangedPtr<T> begin() const { return mStart; }
|
||||
RangedPtr<T> end() const { return mEnd; }
|
||||
size_t length() const { return mEnd - mStart; }
|
||||
|
||||
T& operator[](size_t aOffset) const { return mStart[aOffset]; }
|
||||
|
||||
explicit operator bool() const { return mStart != nullptr; }
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Range_h */
|
||||
66
cocos2d-x/external/win32/include/spidermonkey/mozilla/RangedArray.h
vendored
Executable file
66
cocos2d-x/external/win32/include/spidermonkey/mozilla/RangedArray.h
vendored
Executable file
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* A compile-time constant-length array, with bounds-checking assertions -- but
|
||||
* unlike mozilla::Array, with indexes biased by a constant.
|
||||
*
|
||||
* Thus where mozilla::Array<int, 3> is a three-element array indexed by [0, 3),
|
||||
* mozilla::RangedArray<int, 8, 3> is a three-element array indexed by [8, 11).
|
||||
*/
|
||||
|
||||
#ifndef mozilla_RangedArray_h
|
||||
#define mozilla_RangedArray_h
|
||||
|
||||
#include "mozilla/Array.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T, size_t MinIndex, size_t Length>
|
||||
class RangedArray
|
||||
{
|
||||
private:
|
||||
typedef Array<T, Length> ArrayType;
|
||||
ArrayType mArr;
|
||||
|
||||
public:
|
||||
T& operator[](size_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex == MinIndex || aIndex > MinIndex);
|
||||
return mArr[aIndex - MinIndex];
|
||||
}
|
||||
|
||||
const T& operator[](size_t aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(aIndex == MinIndex || aIndex > MinIndex);
|
||||
return mArr[aIndex - MinIndex];
|
||||
}
|
||||
|
||||
typedef typename ArrayType::iterator iterator;
|
||||
typedef typename ArrayType::const_iterator const_iterator;
|
||||
typedef typename ArrayType::reverse_iterator reverse_iterator;
|
||||
typedef typename ArrayType::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
// Methods for range-based for loops.
|
||||
iterator begin() { return mArr.begin(); }
|
||||
const_iterator begin() const { return mArr.begin(); }
|
||||
const_iterator cbegin() const { return mArr.cbegin(); }
|
||||
iterator end() { return mArr.end(); }
|
||||
const_iterator end() const { return mArr.end(); }
|
||||
const_iterator cend() const { return mArr.cend(); }
|
||||
|
||||
// Methods for reverse iterating.
|
||||
reverse_iterator rbegin() { return mArr.rbegin(); }
|
||||
const_reverse_iterator rbegin() const { return mArr.rbegin(); }
|
||||
const_reverse_iterator crbegin() const { return mArr.crbegin(); }
|
||||
reverse_iterator rend() { return mArr.rend(); }
|
||||
const_reverse_iterator rend() const { return mArr.rend(); }
|
||||
const_reverse_iterator crend() const { return mArr.crend(); }
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_RangedArray_h
|
||||
292
cocos2d-x/external/win32/include/spidermonkey/mozilla/RangedPtr.h
vendored
Executable file
292
cocos2d-x/external/win32/include/spidermonkey/mozilla/RangedPtr.h
vendored
Executable file
@@ -0,0 +1,292 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Implements a smart pointer asserted to remain within a range specified at
|
||||
* construction.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_RangedPtr_h
|
||||
#define mozilla_RangedPtr_h
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* RangedPtr is a smart pointer restricted to an address range specified at
|
||||
* creation. The pointer (and any smart pointers derived from it) must remain
|
||||
* within the range [start, end] (inclusive of end to facilitate use as
|
||||
* sentinels). Dereferencing or indexing into the pointer (or pointers derived
|
||||
* from it) must remain within the range [start, end). All the standard pointer
|
||||
* operators are defined on it; in debug builds these operations assert that the
|
||||
* range specified at construction is respected.
|
||||
*
|
||||
* In theory passing a smart pointer instance as an argument can be slightly
|
||||
* slower than passing a T* (due to ABI requirements for passing structs versus
|
||||
* passing pointers), if the method being called isn't inlined. If you are in
|
||||
* extremely performance-critical code, you may want to be careful using this
|
||||
* smart pointer as an argument type.
|
||||
*
|
||||
* RangedPtr<T> intentionally does not implicitly convert to T*. Use get() to
|
||||
* explicitly convert to T*. Keep in mind that the raw pointer of course won't
|
||||
* implement bounds checking in debug builds.
|
||||
*/
|
||||
template<typename T>
|
||||
class RangedPtr
|
||||
{
|
||||
T* mPtr;
|
||||
|
||||
#ifdef DEBUG
|
||||
T* const mRangeStart;
|
||||
T* const mRangeEnd;
|
||||
#endif
|
||||
|
||||
void checkSanity()
|
||||
{
|
||||
MOZ_ASSERT(mRangeStart <= mPtr);
|
||||
MOZ_ASSERT(mPtr <= mRangeEnd);
|
||||
}
|
||||
|
||||
/* Creates a new pointer for |aPtr|, restricted to this pointer's range. */
|
||||
RangedPtr<T> create(T* aPtr) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
return RangedPtr<T>(aPtr, mRangeStart, mRangeEnd);
|
||||
#else
|
||||
return RangedPtr<T>(aPtr, nullptr, size_t(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
uintptr_t asUintptr() const { return reinterpret_cast<uintptr_t>(mPtr); }
|
||||
|
||||
public:
|
||||
RangedPtr(T* aPtr, T* aStart, T* aEnd)
|
||||
: mPtr(aPtr)
|
||||
#ifdef DEBUG
|
||||
, mRangeStart(aStart), mRangeEnd(aEnd)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(mRangeStart <= mRangeEnd);
|
||||
checkSanity();
|
||||
}
|
||||
RangedPtr(T* aPtr, T* aStart, size_t aLength)
|
||||
: mPtr(aPtr)
|
||||
#ifdef DEBUG
|
||||
, mRangeStart(aStart), mRangeEnd(aStart + aLength)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(aLength <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(mRangeStart) + aLength * sizeof(T) >=
|
||||
reinterpret_cast<uintptr_t>(mRangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(aPtr, aPtr, aLength). */
|
||||
RangedPtr(T* aPtr, size_t aLength)
|
||||
: mPtr(aPtr)
|
||||
#ifdef DEBUG
|
||||
, mRangeStart(aPtr), mRangeEnd(aPtr + aLength)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(aLength <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(mRangeStart) + aLength * sizeof(T) >=
|
||||
reinterpret_cast<uintptr_t>(mRangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(aArr, aArr, N). */
|
||||
template<size_t N>
|
||||
explicit RangedPtr(T (&aArr)[N])
|
||||
: mPtr(aArr)
|
||||
#ifdef DEBUG
|
||||
, mRangeStart(aArr), mRangeEnd(aArr + N)
|
||||
#endif
|
||||
{
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
T* get() const { return mPtr; }
|
||||
|
||||
explicit operator bool() const { return mPtr != nullptr; }
|
||||
|
||||
void checkIdenticalRange(const RangedPtr<T>& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(mRangeStart == aOther.mRangeStart);
|
||||
MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
|
||||
}
|
||||
|
||||
/*
|
||||
* You can only assign one RangedPtr into another if the two pointers have
|
||||
* the same valid range:
|
||||
*
|
||||
* char arr1[] = "hi";
|
||||
* char arr2[] = "bye";
|
||||
* RangedPtr<char> p1(arr1, 2);
|
||||
* p1 = RangedPtr<char>(arr1 + 1, arr1, arr1 + 2); // works
|
||||
* p1 = RangedPtr<char>(arr2, 3); // asserts
|
||||
*/
|
||||
RangedPtr<T>& operator=(const RangedPtr<T>& aOther)
|
||||
{
|
||||
checkIdenticalRange(aOther);
|
||||
mPtr = aOther.mPtr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T> operator+(size_t aInc) const
|
||||
{
|
||||
MOZ_ASSERT(aInc <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(asUintptr() + aInc * sizeof(T) >= asUintptr());
|
||||
return create(mPtr + aInc);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator-(size_t aDec) const
|
||||
{
|
||||
MOZ_ASSERT(aDec <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(asUintptr() - aDec * sizeof(T) <= asUintptr());
|
||||
return create(mPtr - aDec);
|
||||
}
|
||||
|
||||
/*
|
||||
* You can assign a raw pointer into a RangedPtr if the raw pointer is
|
||||
* within the range specified at creation.
|
||||
*/
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(U* aPtr)
|
||||
{
|
||||
*this = create(aPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(const RangedPtr<U>& aPtr)
|
||||
{
|
||||
MOZ_ASSERT(mRangeStart <= aPtr.mPtr);
|
||||
MOZ_ASSERT(aPtr.mPtr <= mRangeEnd);
|
||||
mPtr = aPtr.mPtr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator++()
|
||||
{
|
||||
return (*this += 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator++(int)
|
||||
{
|
||||
RangedPtr<T> rcp = *this;
|
||||
++*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator--()
|
||||
{
|
||||
return (*this -= 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator--(int)
|
||||
{
|
||||
RangedPtr<T> rcp = *this;
|
||||
--*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator+=(size_t aInc)
|
||||
{
|
||||
*this = *this + aInc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator-=(size_t aDec)
|
||||
{
|
||||
*this = *this - aDec;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator[](int aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(size_t(aIndex > 0 ? aIndex : -aIndex) <= size_t(-1) / sizeof(T));
|
||||
return *create(mPtr + aIndex);
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
MOZ_ASSERT(mPtr >= mRangeStart);
|
||||
MOZ_ASSERT(mPtr < mRangeEnd);
|
||||
return *mPtr;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
MOZ_ASSERT(mPtr >= mRangeStart);
|
||||
MOZ_ASSERT(mPtr < mRangeEnd);
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator==(const RangedPtr<U>& aOther) const
|
||||
{
|
||||
return mPtr == aOther.mPtr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator!=(const RangedPtr<U>& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
bool operator==(const U* u) const
|
||||
{
|
||||
return mPtr == u;
|
||||
}
|
||||
template<typename U>
|
||||
bool operator!=(const U* u) const
|
||||
{
|
||||
return !(*this == u);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator<(const RangedPtr<U>& aOther) const
|
||||
{
|
||||
return mPtr < aOther.mPtr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator<=(const RangedPtr<U>& aOther) const
|
||||
{
|
||||
return mPtr <= aOther.mPtr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator>(const RangedPtr<U>& aOther) const
|
||||
{
|
||||
return mPtr > aOther.mPtr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator>=(const RangedPtr<U>& aOther) const
|
||||
{
|
||||
return mPtr >= aOther.mPtr;
|
||||
}
|
||||
|
||||
size_t operator-(const RangedPtr<T>& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(mPtr >= aOther.mPtr);
|
||||
return PointerRangeSize(aOther.mPtr, mPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
RangedPtr() = delete;
|
||||
T* operator&() = delete;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_RangedPtr_h */
|
||||
57
cocos2d-x/external/win32/include/spidermonkey/mozilla/ReentrancyGuard.h
vendored
Executable file
57
cocos2d-x/external/win32/include/spidermonkey/mozilla/ReentrancyGuard.h
vendored
Executable file
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Small helper class for asserting uses of a class are non-reentrant. */
|
||||
|
||||
#ifndef mozilla_ReentrancyGuard_h
|
||||
#define mozilla_ReentrancyGuard_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/* Useful for implementing containers that assert non-reentrancy */
|
||||
class MOZ_RAII ReentrancyGuard
|
||||
{
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
#ifdef DEBUG
|
||||
bool& mEntered;
|
||||
#endif
|
||||
|
||||
public:
|
||||
template<class T>
|
||||
#ifdef DEBUG
|
||||
explicit ReentrancyGuard(T& aObj
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mEntered(aObj.mEntered)
|
||||
#else
|
||||
explicit ReentrancyGuard(T&
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
#endif
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!mEntered);
|
||||
mEntered = true;
|
||||
#endif
|
||||
}
|
||||
~ReentrancyGuard()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mEntered = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
ReentrancyGuard(const ReentrancyGuard&) = delete;
|
||||
void operator=(const ReentrancyGuard&) = delete;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_ReentrancyGuard_h */
|
||||
37
cocos2d-x/external/win32/include/spidermonkey/mozilla/RefCountType.h
vendored
Executable file
37
cocos2d-x/external/win32/include/spidermonkey/mozilla/RefCountType.h
vendored
Executable file
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_RefCountType_h
|
||||
#define mozilla_RefCountType_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* MozRefCountType is Mozilla's reference count type.
|
||||
*
|
||||
* We use the same type to represent the refcount of RefCounted objects
|
||||
* as well, in order to be able to use the leak detection facilities
|
||||
* that are implemented by XPCOM.
|
||||
*
|
||||
* Note that this type is not in the mozilla namespace so that it is
|
||||
* usable for both C and C++ code.
|
||||
*/
|
||||
typedef uintptr_t MozRefCountType;
|
||||
|
||||
/*
|
||||
* This is the return type for AddRef() and Release() in nsISupports.
|
||||
* IUnknown of COM returns an unsigned long from equivalent functions.
|
||||
*
|
||||
* The following ifdef exists to maintain binary compatibility with
|
||||
* IUnknown, the base interface in Microsoft COM.
|
||||
*/
|
||||
#ifdef XP_WIN
|
||||
typedef unsigned long MozExternalRefCountType;
|
||||
#else
|
||||
typedef uint32_t MozExternalRefCountType;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
210
cocos2d-x/external/win32/include/spidermonkey/mozilla/RefCounted.h
vendored
Executable file
210
cocos2d-x/external/win32/include/spidermonkey/mozilla/RefCounted.h
vendored
Executable file
@@ -0,0 +1,210 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* CRTP refcounting templates. Do not use unless you are an Expert. */
|
||||
|
||||
#ifndef mozilla_RefCounted_h
|
||||
#define mozilla_RefCounted_h
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/RefCountType.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#include "nsXPCOM.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && \
|
||||
(defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
|
||||
#define MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* RefCounted<T> is a sort of a "mixin" for a class T. RefCounted
|
||||
* manages, well, refcounting for T, and because RefCounted is
|
||||
* parameterized on T, RefCounted<T> can call T's destructor directly.
|
||||
* This means T doesn't need to have a virtual dtor and so doesn't
|
||||
* need a vtable.
|
||||
*
|
||||
* RefCounted<T> is created with refcount == 0. Newly-allocated
|
||||
* RefCounted<T> must immediately be assigned to a RefPtr to make the
|
||||
* refcount > 0. It's an error to allocate and free a bare
|
||||
* RefCounted<T>, i.e. outside of the RefPtr machinery. Attempts to
|
||||
* do so will abort DEBUG builds.
|
||||
*
|
||||
* Live RefCounted<T> have refcount > 0. The lifetime (refcounts) of
|
||||
* live RefCounted<T> are controlled by RefPtr<T> and
|
||||
* RefPtr<super/subclass of T>. Upon a transition from refcounted==1
|
||||
* to 0, the RefCounted<T> "dies" and is destroyed. The "destroyed"
|
||||
* state is represented in DEBUG builds by refcount==0xffffdead. This
|
||||
* state distinguishes use-before-ref (refcount==0) from
|
||||
* use-after-destroy (refcount==0xffffdead).
|
||||
*
|
||||
* Note that when deriving from RefCounted or AtomicRefCounted, you
|
||||
* should add MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public
|
||||
* section of your class, where ClassName is the name of your class.
|
||||
*/
|
||||
namespace detail {
|
||||
const MozRefCountType DEAD = 0xffffdead;
|
||||
|
||||
// When building code that gets compiled into Gecko, try to use the
|
||||
// trace-refcount leak logging facilities.
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
class RefCountLogger
|
||||
{
|
||||
public:
|
||||
static void logAddRef(const void* aPointer, MozRefCountType aRefCount,
|
||||
const char* aTypeName, uint32_t aInstanceSize)
|
||||
{
|
||||
MOZ_ASSERT(aRefCount != DEAD);
|
||||
NS_LogAddRef(const_cast<void*>(aPointer), aRefCount, aTypeName,
|
||||
aInstanceSize);
|
||||
}
|
||||
|
||||
static void logRelease(const void* aPointer, MozRefCountType aRefCount,
|
||||
const char* aTypeName)
|
||||
{
|
||||
MOZ_ASSERT(aRefCount != DEAD);
|
||||
NS_LogRelease(const_cast<void*>(aPointer), aRefCount, aTypeName);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// This is used WeakPtr.h as well as this file.
|
||||
enum RefCountAtomicity
|
||||
{
|
||||
AtomicRefCount,
|
||||
NonAtomicRefCount
|
||||
};
|
||||
|
||||
template<typename T, RefCountAtomicity Atomicity>
|
||||
class RefCounted
|
||||
{
|
||||
protected:
|
||||
RefCounted() : mRefCnt(0) {}
|
||||
~RefCounted() { MOZ_ASSERT(mRefCnt == detail::DEAD); }
|
||||
|
||||
public:
|
||||
// Compatibility with nsRefPtr.
|
||||
void AddRef() const
|
||||
{
|
||||
// Note: this method must be thread safe for AtomicRefCounted.
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0);
|
||||
#ifndef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
++mRefCnt;
|
||||
#else
|
||||
const char* type = static_cast<const T*>(this)->typeName();
|
||||
uint32_t size = static_cast<const T*>(this)->typeSize();
|
||||
const void* ptr = static_cast<const T*>(this);
|
||||
MozRefCountType cnt = ++mRefCnt;
|
||||
detail::RefCountLogger::logAddRef(ptr, cnt, type, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Release() const
|
||||
{
|
||||
// Note: this method must be thread safe for AtomicRefCounted.
|
||||
MOZ_ASSERT(int32_t(mRefCnt) > 0);
|
||||
#ifndef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
MozRefCountType cnt = --mRefCnt;
|
||||
#else
|
||||
const char* type = static_cast<const T*>(this)->typeName();
|
||||
const void* ptr = static_cast<const T*>(this);
|
||||
MozRefCountType cnt = --mRefCnt;
|
||||
// Note: it's not safe to touch |this| after decrementing the refcount,
|
||||
// except for below.
|
||||
detail::RefCountLogger::logRelease(ptr, cnt, type);
|
||||
#endif
|
||||
if (0 == cnt) {
|
||||
// Because we have atomically decremented the refcount above, only
|
||||
// one thread can get a 0 count here, so as long as we can assume that
|
||||
// everything else in the system is accessing this object through
|
||||
// RefPtrs, it's safe to access |this| here.
|
||||
#ifdef DEBUG
|
||||
mRefCnt = detail::DEAD;
|
||||
#endif
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility with wtf::RefPtr.
|
||||
void ref() { AddRef(); }
|
||||
void deref() { Release(); }
|
||||
MozRefCountType refCount() const { return mRefCnt; }
|
||||
bool hasOneRef() const
|
||||
{
|
||||
MOZ_ASSERT(mRefCnt > 0);
|
||||
return mRefCnt == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable typename Conditional<Atomicity == AtomicRefCount,
|
||||
Atomic<MozRefCountType>,
|
||||
MozRefCountType>::Type mRefCnt;
|
||||
};
|
||||
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
// Passing override for the optional argument marks the typeName and
|
||||
// typeSize functions defined by this macro as overrides.
|
||||
#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...) \
|
||||
virtual const char* typeName() const __VA_ARGS__ { return #T; } \
|
||||
virtual size_t typeSize() const __VA_ARGS__ { return sizeof(*this); }
|
||||
#else
|
||||
#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...)
|
||||
#endif
|
||||
|
||||
// Note that this macro is expanded unconditionally because it declares only
|
||||
// two small inline functions which will hopefully get eliminated by the linker
|
||||
// in non-leak-checking builds.
|
||||
#define MOZ_DECLARE_REFCOUNTED_TYPENAME(T) \
|
||||
const char* typeName() const { return #T; } \
|
||||
size_t typeSize() const { return sizeof(*this); }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
|
||||
{
|
||||
public:
|
||||
~RefCounted()
|
||||
{
|
||||
static_assert(IsBaseOf<RefCounted, T>::value,
|
||||
"T must derive from RefCounted<T>");
|
||||
}
|
||||
};
|
||||
|
||||
namespace external {
|
||||
|
||||
/**
|
||||
* AtomicRefCounted<T> is like RefCounted<T>, with an atomically updated
|
||||
* reference counter.
|
||||
*
|
||||
* NOTE: Please do not use this class, use NS_INLINE_DECL_THREADSAFE_REFCOUNTING
|
||||
* instead.
|
||||
*/
|
||||
template<typename T>
|
||||
class AtomicRefCounted :
|
||||
public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount>
|
||||
{
|
||||
public:
|
||||
~AtomicRefCounted()
|
||||
{
|
||||
static_assert(IsBaseOf<AtomicRefCounted, T>::value,
|
||||
"T must derive from AtomicRefCounted<T>");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace external
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_RefCounted_h
|
||||
656
cocos2d-x/external/win32/include/spidermonkey/mozilla/RefPtr.h
vendored
Executable file
656
cocos2d-x/external/win32/include/spidermonkey/mozilla/RefPtr.h
vendored
Executable file
@@ -0,0 +1,656 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_RefPtr_h
|
||||
#define mozilla_RefPtr_h
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// template <class T> class RefPtrGetterAddRefs;
|
||||
|
||||
class nsCOMPtr_helper;
|
||||
|
||||
namespace mozilla {
|
||||
template<class T> class OwningNonNull;
|
||||
template<class T> class StaticRefPtr;
|
||||
|
||||
// Traditionally, RefPtr supports automatic refcounting of any pointer type
|
||||
// with AddRef() and Release() methods that follow the traditional semantics.
|
||||
//
|
||||
// This traits class can be specialized to operate on other pointer types. For
|
||||
// example, we specialize this trait for opaque FFI types that represent
|
||||
// refcounted objects in Rust.
|
||||
//
|
||||
// Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
|
||||
// qualified type.
|
||||
template<class U>
|
||||
struct RefPtrTraits
|
||||
{
|
||||
static void AddRef(U* aPtr) {
|
||||
aPtr->AddRef();
|
||||
}
|
||||
static void Release(U* aPtr) {
|
||||
aPtr->Release();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
template <class T>
|
||||
class RefPtr
|
||||
{
|
||||
private:
|
||||
void
|
||||
assign_with_AddRef(T* aRawPtr)
|
||||
{
|
||||
if (aRawPtr) {
|
||||
ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
|
||||
}
|
||||
assign_assuming_AddRef(aRawPtr);
|
||||
}
|
||||
|
||||
void
|
||||
assign_assuming_AddRef(T* aNewPtr)
|
||||
{
|
||||
T* oldPtr = mRawPtr;
|
||||
mRawPtr = aNewPtr;
|
||||
if (oldPtr) {
|
||||
ConstRemovingRefPtrTraits<T>::Release(oldPtr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T* MOZ_OWNING_REF mRawPtr;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
~RefPtr()
|
||||
{
|
||||
if (mRawPtr) {
|
||||
ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
|
||||
}
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
RefPtr()
|
||||
: mRawPtr(nullptr)
|
||||
// default constructor
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr(const RefPtr<T>& aSmartPtr)
|
||||
: mRawPtr(aSmartPtr.mRawPtr)
|
||||
// copy-constructor
|
||||
{
|
||||
if (mRawPtr) {
|
||||
ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr(RefPtr<T>&& aRefPtr)
|
||||
: mRawPtr(aRefPtr.mRawPtr)
|
||||
{
|
||||
aRefPtr.mRawPtr = nullptr;
|
||||
}
|
||||
|
||||
// construct from a raw pointer (of the right type)
|
||||
|
||||
MOZ_IMPLICIT RefPtr(T* aRawPtr)
|
||||
: mRawPtr(aRawPtr)
|
||||
{
|
||||
if (mRawPtr) {
|
||||
ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT RefPtr(decltype(nullptr))
|
||||
: mRawPtr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
|
||||
: mRawPtr(aSmartPtr.take())
|
||||
// construct from |already_AddRefed|
|
||||
{
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr)
|
||||
: mRawPtr(aSmartPtr.take())
|
||||
// construct from |otherRefPtr.forget()|
|
||||
{
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr)
|
||||
: mRawPtr(aSmartPtr.get())
|
||||
// copy-construct from a smart pointer with a related pointer type
|
||||
{
|
||||
if (mRawPtr) {
|
||||
ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr)
|
||||
: mRawPtr(aSmartPtr.forget().take())
|
||||
// construct from |Move(RefPtr<SomeSubclassOfT>)|.
|
||||
{
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
|
||||
|
||||
// Defined in OwningNonNull.h
|
||||
template<class U>
|
||||
MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
|
||||
|
||||
// Defined in StaticPtr.h
|
||||
template<class U>
|
||||
MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
|
||||
|
||||
// Assignment operators
|
||||
|
||||
RefPtr<T>&
|
||||
operator=(decltype(nullptr))
|
||||
{
|
||||
assign_assuming_AddRef(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>&
|
||||
operator=(const RefPtr<T>& aRhs)
|
||||
// copy assignment operator
|
||||
{
|
||||
assign_with_AddRef(aRhs.mRawPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
RefPtr<T>&
|
||||
operator=(const RefPtr<I>& aRhs)
|
||||
// assign from an RefPtr of a related pointer type
|
||||
{
|
||||
assign_with_AddRef(aRhs.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>&
|
||||
operator=(T* aRhs)
|
||||
// assign from a raw pointer (of the right type)
|
||||
{
|
||||
assign_with_AddRef(aRhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
RefPtr<T>&
|
||||
operator=(already_AddRefed<I>& aRhs)
|
||||
// assign from |already_AddRefed|
|
||||
{
|
||||
assign_assuming_AddRef(aRhs.take());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
RefPtr<T>&
|
||||
operator=(already_AddRefed<I> && aRhs)
|
||||
// assign from |otherRefPtr.forget()|
|
||||
{
|
||||
assign_assuming_AddRef(aRhs.take());
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
|
||||
|
||||
RefPtr<T>&
|
||||
operator=(RefPtr<T> && aRefPtr)
|
||||
{
|
||||
assign_assuming_AddRef(aRefPtr.mRawPtr);
|
||||
aRefPtr.mRawPtr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Defined in OwningNonNull.h
|
||||
template<class U>
|
||||
RefPtr<T>&
|
||||
operator=(const mozilla::OwningNonNull<U>& aOther);
|
||||
|
||||
// Defined in StaticPtr.h
|
||||
template<class U>
|
||||
RefPtr<T>&
|
||||
operator=(const mozilla::StaticRefPtr<U>& aOther);
|
||||
|
||||
// Other pointer operators
|
||||
|
||||
void
|
||||
swap(RefPtr<T>& aRhs)
|
||||
// ...exchange ownership with |aRhs|; can save a pair of refcount operations
|
||||
{
|
||||
T* temp = aRhs.mRawPtr;
|
||||
aRhs.mRawPtr = mRawPtr;
|
||||
mRawPtr = temp;
|
||||
}
|
||||
|
||||
void
|
||||
swap(T*& aRhs)
|
||||
// ...exchange ownership with |aRhs|; can save a pair of refcount operations
|
||||
{
|
||||
T* temp = aRhs;
|
||||
aRhs = mRawPtr;
|
||||
mRawPtr = temp;
|
||||
}
|
||||
|
||||
already_AddRefed<T>
|
||||
forget()
|
||||
// return the value of mRawPtr and null out mRawPtr. Useful for
|
||||
// already_AddRefed return values.
|
||||
{
|
||||
T* temp = nullptr;
|
||||
swap(temp);
|
||||
return already_AddRefed<T>(temp);
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
void
|
||||
forget(I** aRhs)
|
||||
// Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
|
||||
// Useful to avoid unnecessary AddRef/Release pairs with "out"
|
||||
// parameters where aRhs bay be a T** or an I** where I is a base class
|
||||
// of T.
|
||||
{
|
||||
MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
|
||||
*aRhs = mRawPtr;
|
||||
mRawPtr = nullptr;
|
||||
}
|
||||
|
||||
T*
|
||||
get() const
|
||||
/*
|
||||
Prefer the implicit conversion provided automatically by |operator T*() const|.
|
||||
Use |get()| to resolve ambiguity or to get a castable pointer.
|
||||
*/
|
||||
{
|
||||
return const_cast<T*>(mRawPtr);
|
||||
}
|
||||
|
||||
operator T*() const
|
||||
#ifdef MOZ_HAVE_REF_QUALIFIERS
|
||||
&
|
||||
#endif
|
||||
/*
|
||||
...makes an |RefPtr| act like its underlying raw pointer type whenever it
|
||||
is used in a context where a raw pointer is expected. It is this operator
|
||||
that makes an |RefPtr| substitutable for a raw pointer.
|
||||
|
||||
Prefer the implicit use of this operator to calling |get()|, except where
|
||||
necessary to resolve ambiguity.
|
||||
*/
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
#ifdef MOZ_HAVE_REF_QUALIFIERS
|
||||
// Don't allow implicit conversion of temporary RefPtr to raw pointer,
|
||||
// because the refcount might be one and the pointer will immediately become
|
||||
// invalid.
|
||||
operator T*() const && = delete;
|
||||
|
||||
// These are needed to avoid the deleted operator above. XXX Why is operator!
|
||||
// needed separately? Shouldn't the compiler prefer using the non-deleted
|
||||
// operator bool instead of the deleted operator T*?
|
||||
explicit operator bool() const { return !!mRawPtr; }
|
||||
bool operator!() const { return !mRawPtr; }
|
||||
#endif
|
||||
|
||||
T*
|
||||
operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
|
||||
{
|
||||
MOZ_ASSERT(mRawPtr != nullptr,
|
||||
"You can't dereference a NULL RefPtr with operator->().");
|
||||
return get();
|
||||
}
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class Proxy
|
||||
{
|
||||
typedef R (T::*member_function)(Args...);
|
||||
T* mRawPtr;
|
||||
member_function mFunction;
|
||||
public:
|
||||
Proxy(T* aRawPtr, member_function aFunction)
|
||||
: mRawPtr(aRawPtr),
|
||||
mFunction(aFunction)
|
||||
{
|
||||
}
|
||||
template<typename... ActualArgs>
|
||||
R operator()(ActualArgs&&... aArgs)
|
||||
{
|
||||
return ((*mRawPtr).*mFunction)(mozilla::Forward<ActualArgs>(aArgs)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const
|
||||
{
|
||||
MOZ_ASSERT(mRawPtr != nullptr,
|
||||
"You can't dereference a NULL RefPtr with operator->*().");
|
||||
return Proxy<R, Args...>(get(), aFptr);
|
||||
}
|
||||
|
||||
RefPtr<T>*
|
||||
get_address()
|
||||
// This is not intended to be used by clients. See |address_of|
|
||||
// below.
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
const RefPtr<T>*
|
||||
get_address() const
|
||||
// This is not intended to be used by clients. See |address_of|
|
||||
// below.
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public:
|
||||
T&
|
||||
operator*() const
|
||||
{
|
||||
MOZ_ASSERT(mRawPtr != nullptr,
|
||||
"You can't dereference a NULL RefPtr with operator*().");
|
||||
return *get();
|
||||
}
|
||||
|
||||
T**
|
||||
StartAssignment()
|
||||
{
|
||||
assign_assuming_AddRef(nullptr);
|
||||
return reinterpret_cast<T**>(&mRawPtr);
|
||||
}
|
||||
private:
|
||||
// This helper class makes |RefPtr<const T>| possible by casting away
|
||||
// the constness from the pointer when calling AddRef() and Release().
|
||||
//
|
||||
// This is necessary because AddRef() and Release() implementations can't
|
||||
// generally expected to be const themselves (without heavy use of |mutable|
|
||||
// and |const_cast| in their own implementations).
|
||||
//
|
||||
// This should be sound because while |RefPtr<const T>| provides a
|
||||
// const view of an object, the object itself should not be const (it
|
||||
// would have to be allocated as |new const T| or similar to be const).
|
||||
template<class U>
|
||||
struct ConstRemovingRefPtrTraits
|
||||
{
|
||||
static void AddRef(U* aPtr) {
|
||||
mozilla::RefPtrTraits<U>::AddRef(aPtr);
|
||||
}
|
||||
static void Release(U* aPtr) {
|
||||
mozilla::RefPtrTraits<U>::Release(aPtr);
|
||||
}
|
||||
};
|
||||
template<class U>
|
||||
struct ConstRemovingRefPtrTraits<const U>
|
||||
{
|
||||
static void AddRef(const U* aPtr) {
|
||||
mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
|
||||
}
|
||||
static void Release(const U* aPtr) {
|
||||
mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class nsCycleCollectionTraversalCallback;
|
||||
template <typename T>
|
||||
void
|
||||
CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback,
|
||||
T* aChild, const char* aName, uint32_t aFlags);
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(RefPtr<T>& aField)
|
||||
{
|
||||
aField = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
RefPtr<T>& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline RefPtr<T>*
|
||||
address_of(RefPtr<T>& aPtr)
|
||||
{
|
||||
return aPtr.get_address();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const RefPtr<T>*
|
||||
address_of(const RefPtr<T>& aPtr)
|
||||
{
|
||||
return aPtr.get_address();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class RefPtrGetterAddRefs
|
||||
/*
|
||||
...
|
||||
|
||||
This class is designed to be used for anonymous temporary objects in the
|
||||
argument list of calls that return COM interface pointers, e.g.,
|
||||
|
||||
RefPtr<IFoo> fooP;
|
||||
...->GetAddRefedPointer(getter_AddRefs(fooP))
|
||||
|
||||
DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
|
||||
|
||||
When initialized with a |RefPtr|, as in the example above, it returns
|
||||
a |void**|, a |T**|, or an |nsISupports**| as needed, that the
|
||||
outer call (|GetAddRefedPointer| in this case) can fill in.
|
||||
|
||||
This type should be a nested class inside |RefPtr<T>|.
|
||||
*/
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr)
|
||||
: mTargetSmartPtr(aSmartPtr)
|
||||
{
|
||||
// nothing else to do
|
||||
}
|
||||
|
||||
operator void**()
|
||||
{
|
||||
return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
|
||||
}
|
||||
|
||||
operator T**()
|
||||
{
|
||||
return mTargetSmartPtr.StartAssignment();
|
||||
}
|
||||
|
||||
T*&
|
||||
operator*()
|
||||
{
|
||||
return *(mTargetSmartPtr.StartAssignment());
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<T>& mTargetSmartPtr;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline RefPtrGetterAddRefs<T>
|
||||
getter_AddRefs(RefPtr<T>& aSmartPtr)
|
||||
/*
|
||||
Used around a |RefPtr| when
|
||||
...makes the class |RefPtrGetterAddRefs<T>| invisible.
|
||||
*/
|
||||
{
|
||||
return RefPtrGetterAddRefs<T>(aSmartPtr);
|
||||
}
|
||||
|
||||
|
||||
// Comparing two |RefPtr|s
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator==(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs)
|
||||
{
|
||||
return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
|
||||
}
|
||||
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator!=(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs)
|
||||
{
|
||||
return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
|
||||
}
|
||||
|
||||
|
||||
// Comparing an |RefPtr| to a raw pointer
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator==(const RefPtr<T>& aLhs, const U* aRhs)
|
||||
{
|
||||
return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator==(const U* aLhs, const RefPtr<T>& aRhs)
|
||||
{
|
||||
return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator!=(const RefPtr<T>& aLhs, const U* aRhs)
|
||||
{
|
||||
return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator!=(const U* aLhs, const RefPtr<T>& aRhs)
|
||||
{
|
||||
return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator==(const RefPtr<T>& aLhs, U* aRhs)
|
||||
{
|
||||
return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator==(U* aLhs, const RefPtr<T>& aRhs)
|
||||
{
|
||||
return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator!=(const RefPtr<T>& aLhs, U* aRhs)
|
||||
{
|
||||
return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool
|
||||
operator!=(U* aLhs, const RefPtr<T>& aRhs)
|
||||
{
|
||||
return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
|
||||
}
|
||||
|
||||
// Comparing an |RefPtr| to |nullptr|
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
operator==(const RefPtr<T>& aLhs, decltype(nullptr))
|
||||
{
|
||||
return aLhs.get() == nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
operator==(decltype(nullptr), const RefPtr<T>& aRhs)
|
||||
{
|
||||
return nullptr == aRhs.get();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
operator!=(const RefPtr<T>& aLhs, decltype(nullptr))
|
||||
{
|
||||
return aLhs.get() != nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
operator!=(decltype(nullptr), const RefPtr<T>& aRhs)
|
||||
{
|
||||
return nullptr != aRhs.get();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
template <class T>
|
||||
inline already_AddRefed<T>
|
||||
do_AddRef(T* aObj)
|
||||
{
|
||||
RefPtr<T> ref(aObj);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline already_AddRefed<T>
|
||||
do_AddRef(const RefPtr<T>& aObj)
|
||||
{
|
||||
RefPtr<T> ref(aObj);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Helper function to be able to conveniently write things like:
|
||||
*
|
||||
* already_AddRefed<T>
|
||||
* f(...)
|
||||
* {
|
||||
* return MakeAndAddRef<T>(...);
|
||||
* }
|
||||
*/
|
||||
template<typename T, typename... Args>
|
||||
already_AddRefed<T>
|
||||
MakeAndAddRef(Args&&... aArgs)
|
||||
{
|
||||
RefPtr<T> p(new T(Forward<Args>(aArgs)...));
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_RefPtr_h */
|
||||
168
cocos2d-x/external/win32/include/spidermonkey/mozilla/ReverseIterator.h
vendored
Executable file
168
cocos2d-x/external/win32/include/spidermonkey/mozilla/ReverseIterator.h
vendored
Executable file
@@ -0,0 +1,168 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* An iterator that acts like another iterator, but iterating in
|
||||
* the negative direction. (Note that not all iterators can iterate
|
||||
* in the negative direction.) */
|
||||
|
||||
#ifndef mozilla_ReverseIterator_h
|
||||
#define mozilla_ReverseIterator_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename IteratorT>
|
||||
class ReverseIterator
|
||||
{
|
||||
public:
|
||||
template<typename Iterator>
|
||||
explicit ReverseIterator(Iterator aIter)
|
||||
: mCurrent(aIter) { }
|
||||
|
||||
template<typename Iterator>
|
||||
MOZ_IMPLICIT ReverseIterator(const ReverseIterator<Iterator>& aOther)
|
||||
: mCurrent(aOther.mCurrent) { }
|
||||
|
||||
decltype(*DeclVal<IteratorT>()) operator*() const
|
||||
{
|
||||
IteratorT tmp = mCurrent;
|
||||
return *--tmp;
|
||||
}
|
||||
|
||||
/* Increments and decrements operators */
|
||||
|
||||
ReverseIterator& operator++() { --mCurrent; return *this; }
|
||||
ReverseIterator& operator--() { ++mCurrent; return *this; }
|
||||
ReverseIterator operator++(int) { auto ret = *this; mCurrent--; return ret; }
|
||||
ReverseIterator operator--(int) { auto ret = *this; mCurrent++; return ret; }
|
||||
|
||||
/* Comparison operators */
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
friend bool operator==(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2);
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
friend bool operator!=(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2);
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
friend bool operator<(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2);
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
friend bool operator<=(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2);
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
friend bool operator>(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2);
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
friend bool operator>=(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2);
|
||||
|
||||
private:
|
||||
IteratorT mCurrent;
|
||||
};
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
bool
|
||||
operator==(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent == aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
bool
|
||||
operator!=(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent != aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
bool
|
||||
operator<(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent > aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
bool
|
||||
operator<=(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent >= aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
bool
|
||||
operator>(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent < aIter2.mCurrent;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
bool
|
||||
operator>=(const ReverseIterator<Iterator1>& aIter1,
|
||||
const ReverseIterator<Iterator2>& aIter2)
|
||||
{
|
||||
return aIter1.mCurrent <= aIter2.mCurrent;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename IteratorT>
|
||||
class IteratorRange
|
||||
{
|
||||
public:
|
||||
typedef IteratorT iterator;
|
||||
typedef IteratorT const_iterator;
|
||||
typedef ReverseIterator<IteratorT> reverse_iterator;
|
||||
typedef ReverseIterator<IteratorT> const_reverse_iterator;
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
MOZ_IMPLICIT IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd)
|
||||
: mIterBegin(aIterBegin), mIterEnd(aIterEnd) { }
|
||||
|
||||
template<typename Iterator>
|
||||
MOZ_IMPLICIT IteratorRange(const IteratorRange<Iterator>& aOther)
|
||||
: mIterBegin(aOther.mIterBegin), mIterEnd(aOther.mIterEnd) { }
|
||||
|
||||
iterator begin() const { return mIterBegin; }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() const { return mIterEnd; }
|
||||
const_iterator cend() const { return end(); }
|
||||
reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); }
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
reverse_iterator rend() const { return reverse_iterator(mIterBegin); }
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
|
||||
private:
|
||||
IteratorT mIterBegin;
|
||||
IteratorT mIterEnd;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename Range>
|
||||
detail::IteratorRange<typename Range::reverse_iterator>
|
||||
Reversed(Range& aRange)
|
||||
{
|
||||
return {aRange.rbegin(), aRange.rend()};
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
detail::IteratorRange<typename Range::const_reverse_iterator>
|
||||
Reversed(const Range& aRange)
|
||||
{
|
||||
return {aRange.rbegin(), aRange.rend()};
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ReverseIterator_h
|
||||
115
cocos2d-x/external/win32/include/spidermonkey/mozilla/RollingMean.h
vendored
Executable file
115
cocos2d-x/external/win32/include/spidermonkey/mozilla/RollingMean.h
vendored
Executable file
@@ -0,0 +1,115 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A set abstraction for enumeration values. */
|
||||
|
||||
#ifndef mozilla_RollingMean_h_
|
||||
#define mozilla_RollingMean_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* RollingMean<T> calculates a rolling mean of the values it is given. It
|
||||
* accumulates the total as values are added and removed. The second type
|
||||
* argument S specifies the type of the total. This may need to be a bigger
|
||||
* type in order to maintain that the sum of all values in the average doesn't
|
||||
* exceed the maximum input value.
|
||||
*
|
||||
* WARNING: Float types are not supported due to rounding errors.
|
||||
*/
|
||||
template<typename T, typename S>
|
||||
class RollingMean
|
||||
{
|
||||
private:
|
||||
size_t mInsertIndex;
|
||||
size_t mMaxValues;
|
||||
Vector<T> mValues;
|
||||
S mTotal;
|
||||
|
||||
public:
|
||||
static_assert(!IsFloatingPoint<T>::value,
|
||||
"floating-point types are unsupported due to rounding "
|
||||
"errors");
|
||||
|
||||
explicit RollingMean(size_t aMaxValues)
|
||||
: mInsertIndex(0),
|
||||
mMaxValues(aMaxValues),
|
||||
mTotal(0)
|
||||
{
|
||||
MOZ_ASSERT(aMaxValues > 0);
|
||||
}
|
||||
|
||||
RollingMean& operator=(RollingMean&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(this != &aOther, "self-assignment is forbidden");
|
||||
this->~RollingMean();
|
||||
new(this) RollingMean(aOther.mMaxValues);
|
||||
mInsertIndex = aOther.mInsertIndex;
|
||||
mTotal = aOther.mTotal;
|
||||
mValues.swap(aOther.mValues);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a value into the rolling mean.
|
||||
*/
|
||||
bool insert(T aValue)
|
||||
{
|
||||
MOZ_ASSERT(mValues.length() <= mMaxValues);
|
||||
|
||||
if (mValues.length() == mMaxValues) {
|
||||
mTotal = mTotal - mValues[mInsertIndex] + aValue;
|
||||
mValues[mInsertIndex] = aValue;
|
||||
} else {
|
||||
if (!mValues.append(aValue)) {
|
||||
return false;
|
||||
}
|
||||
mTotal = mTotal + aValue;
|
||||
}
|
||||
|
||||
mInsertIndex = (mInsertIndex + 1) % mMaxValues;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the rolling mean.
|
||||
*/
|
||||
T mean()
|
||||
{
|
||||
MOZ_ASSERT(!empty());
|
||||
return T(mTotal / int64_t(mValues.length()));
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return mValues.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all values from the rolling mean.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
mValues.clear();
|
||||
mInsertIndex = 0;
|
||||
mTotal = T(0);
|
||||
}
|
||||
|
||||
size_t maxValues()
|
||||
{
|
||||
return mMaxValues;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_RollingMean_h_
|
||||
63
cocos2d-x/external/win32/include/spidermonkey/mozilla/SHA1.h
vendored
Executable file
63
cocos2d-x/external/win32/include/spidermonkey/mozilla/SHA1.h
vendored
Executable file
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Simple class for computing SHA1. */
|
||||
|
||||
#ifndef mozilla_SHA1_h
|
||||
#define mozilla_SHA1_h
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* This class computes the SHA1 hash of a byte sequence, or of the concatenation
|
||||
* of multiple sequences. For example, computing the SHA1 of two sequences of
|
||||
* bytes could be done as follows:
|
||||
*
|
||||
* void SHA1(const uint8_t* buf1, uint32_t size1,
|
||||
* const uint8_t* buf2, uint32_t size2,
|
||||
* SHA1Sum::Hash& hash)
|
||||
* {
|
||||
* SHA1Sum s;
|
||||
* s.update(buf1, size1);
|
||||
* s.update(buf2, size2);
|
||||
* s.finish(hash);
|
||||
* }
|
||||
*
|
||||
* The finish method may only be called once and cannot be followed by calls
|
||||
* to update.
|
||||
*/
|
||||
class SHA1Sum
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t mW[16]; /* input buffer */
|
||||
uint8_t mB[64];
|
||||
} mU;
|
||||
uint64_t mSize; /* count of hashed bytes. */
|
||||
unsigned mH[22]; /* 5 state variables, 16 tmp values, 1 extra */
|
||||
bool mDone;
|
||||
|
||||
public:
|
||||
MFBT_API SHA1Sum();
|
||||
|
||||
static const size_t kHashSize = 20;
|
||||
typedef uint8_t Hash[kHashSize];
|
||||
|
||||
/* Add len bytes of dataIn to the data sequence being hashed. */
|
||||
MFBT_API void update(const void* aData, uint32_t aLength);
|
||||
|
||||
/* Compute the final hash of all data into hashOut. */
|
||||
MFBT_API void finish(SHA1Sum::Hash& aHashOut);
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_SHA1_h */
|
||||
288
cocos2d-x/external/win32/include/spidermonkey/mozilla/Saturate.h
vendored
Executable file
288
cocos2d-x/external/win32/include/spidermonkey/mozilla/Saturate.h
vendored
Executable file
@@ -0,0 +1,288 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Provides saturation arithmetics for scalar types. */
|
||||
|
||||
#ifndef mozilla_Saturate_h
|
||||
#define mozilla_Saturate_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* |SaturateOp<T>| wraps scalar values for saturation arithmetics. Usage:
|
||||
*
|
||||
* uint32_t value = 1;
|
||||
*
|
||||
* ++SaturateOp<uint32_t>(value); // value is 2
|
||||
* --SaturateOp<uint32_t>(value); // value is 1
|
||||
* --SaturateOp<uint32_t>(value); // value is 0
|
||||
* --SaturateOp<uint32_t>(value); // value is still 0
|
||||
*
|
||||
* Please add new operators when required.
|
||||
*
|
||||
* |SaturateOp<T>| will saturate at the minimum and maximum values of
|
||||
* type T. If you need other bounds, implement a clamped-type class and
|
||||
* specialize the type traits accordingly.
|
||||
*/
|
||||
template <typename T>
|
||||
class SaturateOp
|
||||
{
|
||||
public:
|
||||
explicit SaturateOp(T& aValue)
|
||||
: mValue(aValue)
|
||||
{
|
||||
// We should actually check for |std::is_scalar<T>::value| to be
|
||||
// true, but this type trait is not available everywhere. Relax
|
||||
// this assertion if you want to use floating point values as well.
|
||||
static_assert(IsIntegral<T>::value,
|
||||
"Integral type required in instantiation");
|
||||
}
|
||||
|
||||
// Add and subtract operators
|
||||
|
||||
T operator+(const T& aRhs) const
|
||||
{
|
||||
return T(mValue) += aRhs;
|
||||
}
|
||||
|
||||
T operator-(const T& aRhs) const
|
||||
{
|
||||
return T(mValue) -= aRhs;
|
||||
}
|
||||
|
||||
// Compound operators
|
||||
|
||||
const T& operator+=(const T& aRhs) const
|
||||
{
|
||||
const T min = std::numeric_limits<T>::min();
|
||||
const T max = std::numeric_limits<T>::max();
|
||||
|
||||
if (aRhs > static_cast<T>(0)) {
|
||||
mValue = (max - aRhs) < mValue ? max : mValue + aRhs;
|
||||
} else {
|
||||
mValue = (min - aRhs) > mValue ? min : mValue + aRhs;
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
|
||||
const T& operator-=(const T& aRhs) const
|
||||
{
|
||||
const T min = std::numeric_limits<T>::min();
|
||||
const T max = std::numeric_limits<T>::max();
|
||||
|
||||
if (aRhs > static_cast<T>(0)) {
|
||||
mValue = (min + aRhs) > mValue ? min : mValue - aRhs;
|
||||
} else {
|
||||
mValue = (max + aRhs) < mValue ? max : mValue - aRhs;
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
|
||||
// Increment and decrement operators
|
||||
|
||||
const T& operator++() const // prefix
|
||||
{
|
||||
return operator+=(static_cast<T>(1));
|
||||
}
|
||||
|
||||
T operator++(int) const // postfix
|
||||
{
|
||||
const T value(mValue);
|
||||
operator++();
|
||||
return value;
|
||||
}
|
||||
|
||||
const T& operator--() const // prefix
|
||||
{
|
||||
return operator-=(static_cast<T>(1));
|
||||
}
|
||||
|
||||
T operator--(int) const // postfix
|
||||
{
|
||||
const T value(mValue);
|
||||
operator--();
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
SaturateOp(const SaturateOp<T>&) = delete;
|
||||
SaturateOp(SaturateOp<T>&&) = delete;
|
||||
SaturateOp& operator=(const SaturateOp<T>&) = delete;
|
||||
SaturateOp& operator=(SaturateOp<T>&&) = delete;
|
||||
|
||||
T& mValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* |Saturate<T>| is a value type for saturation arithmetics. It's
|
||||
* build on top of |SaturateOp<T>|.
|
||||
*/
|
||||
template <typename T>
|
||||
class Saturate
|
||||
{
|
||||
public:
|
||||
Saturate() = default;
|
||||
MOZ_IMPLICIT Saturate(const Saturate<T>&) = default;
|
||||
|
||||
MOZ_IMPLICIT Saturate(Saturate<T>&& aValue)
|
||||
{
|
||||
mValue = Move(aValue.mValue);
|
||||
}
|
||||
|
||||
explicit Saturate(const T& aValue)
|
||||
: mValue(aValue)
|
||||
{ }
|
||||
|
||||
const T& value() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
// Compare operators
|
||||
|
||||
bool operator==(const Saturate<T>& aRhs) const
|
||||
{
|
||||
return mValue == aRhs.mValue;
|
||||
}
|
||||
|
||||
bool operator!=(const Saturate<T>& aRhs) const
|
||||
{
|
||||
return !operator==(aRhs);
|
||||
}
|
||||
|
||||
bool operator==(const T& aRhs) const
|
||||
{
|
||||
return mValue == aRhs;
|
||||
}
|
||||
|
||||
bool operator!=(const T& aRhs) const
|
||||
{
|
||||
return !operator==(aRhs);
|
||||
}
|
||||
|
||||
// Assignment operators
|
||||
|
||||
Saturate<T>& operator=(const Saturate<T>&) = default;
|
||||
|
||||
Saturate<T>& operator=(Saturate<T>&& aRhs)
|
||||
{
|
||||
mValue = Move(aRhs.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Add and subtract operators
|
||||
|
||||
Saturate<T> operator+(const Saturate<T>& aRhs) const
|
||||
{
|
||||
Saturate<T> lhs(mValue);
|
||||
return lhs += aRhs.mValue;
|
||||
}
|
||||
|
||||
Saturate<T> operator+(const T& aRhs) const
|
||||
{
|
||||
Saturate<T> lhs(mValue);
|
||||
return lhs += aRhs;
|
||||
}
|
||||
|
||||
Saturate<T> operator-(const Saturate<T>& aRhs) const
|
||||
{
|
||||
Saturate<T> lhs(mValue);
|
||||
return lhs -= aRhs.mValue;
|
||||
}
|
||||
|
||||
Saturate<T> operator-(const T& aRhs) const
|
||||
{
|
||||
Saturate<T> lhs(mValue);
|
||||
return lhs -= aRhs;
|
||||
}
|
||||
|
||||
// Compound operators
|
||||
|
||||
Saturate<T>& operator+=(const Saturate<T>& aRhs)
|
||||
{
|
||||
SaturateOp<T>(mValue) += aRhs.mValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Saturate<T>& operator+=(const T& aRhs)
|
||||
{
|
||||
SaturateOp<T>(mValue) += aRhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Saturate<T>& operator-=(const Saturate<T>& aRhs)
|
||||
{
|
||||
SaturateOp<T>(mValue) -= aRhs.mValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Saturate<T>& operator-=(const T& aRhs)
|
||||
{
|
||||
SaturateOp<T>(mValue) -= aRhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Increment and decrement operators
|
||||
|
||||
Saturate<T>& operator++() // prefix
|
||||
{
|
||||
++SaturateOp<T>(mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Saturate<T> operator++(int) // postfix
|
||||
{
|
||||
return Saturate<T>(SaturateOp<T>(mValue)++);
|
||||
}
|
||||
|
||||
Saturate<T>& operator--() // prefix
|
||||
{
|
||||
--SaturateOp<T>(mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Saturate<T> operator--(int) // postfix
|
||||
{
|
||||
return Saturate<T>(SaturateOp<T>(mValue)--);
|
||||
}
|
||||
|
||||
private:
|
||||
T mValue;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
typedef detail::Saturate<int8_t> SaturateInt8;
|
||||
typedef detail::Saturate<int16_t> SaturateInt16;
|
||||
typedef detail::Saturate<int32_t> SaturateInt32;
|
||||
typedef detail::Saturate<uint8_t> SaturateUint8;
|
||||
typedef detail::Saturate<uint16_t> SaturateUint16;
|
||||
typedef detail::Saturate<uint32_t> SaturateUint32;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
bool
|
||||
operator==(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
|
||||
{
|
||||
return aRhs.operator==(static_cast<RhsT>(aLhs));
|
||||
}
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
bool
|
||||
operator!=(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
|
||||
{
|
||||
return !(aLhs == aRhs);
|
||||
}
|
||||
|
||||
#endif // mozilla_Saturate_h
|
||||
135
cocos2d-x/external/win32/include/spidermonkey/mozilla/ScopeExit.h
vendored
Executable file
135
cocos2d-x/external/win32/include/spidermonkey/mozilla/ScopeExit.h
vendored
Executable file
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* RAII class for executing arbitrary actions at scope end. */
|
||||
|
||||
#ifndef mozilla_ScopeExit_h
|
||||
#define mozilla_ScopeExit_h
|
||||
|
||||
/*
|
||||
* See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189.pdf for a
|
||||
* standards-track version of this.
|
||||
*
|
||||
* Error handling can be complex when various actions need to be performed that
|
||||
* need to be undone if an error occurs midway. This can be handled with a
|
||||
* collection of boolean state variables and gotos, which can get clunky and
|
||||
* error-prone:
|
||||
*
|
||||
* {
|
||||
* if (!a.setup())
|
||||
* goto fail;
|
||||
* isASetup = true;
|
||||
*
|
||||
* if (!b.setup())
|
||||
* goto fail;
|
||||
* isBSetup = true;
|
||||
*
|
||||
* ...
|
||||
* return true;
|
||||
*
|
||||
* fail:
|
||||
* if (isASetup)
|
||||
* a.teardown();
|
||||
* if (isBSetup)
|
||||
* b.teardown();
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* ScopeExit is a mechanism to simplify this pattern by keeping an RAII guard
|
||||
* class that will perform the teardown on destruction, unless released. So the
|
||||
* above would become:
|
||||
*
|
||||
* {
|
||||
* if (!a.setup()) {
|
||||
* return false;
|
||||
* }
|
||||
* auto guardA = MakeScopeExit([&] {
|
||||
* a.teardown();
|
||||
* });
|
||||
*
|
||||
* if (!b.setup()) {
|
||||
* return false;
|
||||
* }
|
||||
* auto guardB = MakeScopeExit([&] {
|
||||
* b.teardown();
|
||||
* });
|
||||
*
|
||||
* ...
|
||||
* guardA.release();
|
||||
* guardB.release();
|
||||
* return true;
|
||||
* }
|
||||
*
|
||||
* This header provides:
|
||||
*
|
||||
* - |ScopeExit| - a container for a cleanup call, automically called at the
|
||||
* end of the scope;
|
||||
* - |MakeScopeExit| - a convenience function for constructing a |ScopeExit|
|
||||
* with a given cleanup routine, commonly used with a lambda function.
|
||||
*
|
||||
* Note that the RAII classes defined in this header do _not_ perform any form
|
||||
* of reference-counting or garbage-collection. These classes have exactly two
|
||||
* behaviors:
|
||||
*
|
||||
* - if |release()| has not been called, the cleanup is always performed at
|
||||
* the end of the scope;
|
||||
* - if |release()| has been called, nothing will happen at the end of the
|
||||
* scope.
|
||||
*/
|
||||
|
||||
#include "mozilla/GuardObjects.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename ExitFunction>
|
||||
class MOZ_STACK_CLASS ScopeExit {
|
||||
ExitFunction mExitFunction;
|
||||
bool mExecuteOnDestruction;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit ScopeExit(ExitFunction&& cleanup
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mExitFunction(cleanup)
|
||||
, mExecuteOnDestruction(true)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
ScopeExit(ScopeExit&& rhs)
|
||||
: mExitFunction(mozilla::Move(rhs.mExitFunction))
|
||||
, mExecuteOnDestruction(rhs.mExecuteOnDestruction)
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
|
||||
~ScopeExit() {
|
||||
if (mExecuteOnDestruction) {
|
||||
mExitFunction();
|
||||
}
|
||||
}
|
||||
|
||||
void release() {
|
||||
mExecuteOnDestruction = false;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit ScopeExit(const ScopeExit&) = delete;
|
||||
ScopeExit& operator=(const ScopeExit&) = delete;
|
||||
ScopeExit& operator=(ScopeExit&&) = delete;
|
||||
};
|
||||
|
||||
template <typename ExitFunction>
|
||||
ScopeExit<ExitFunction>
|
||||
MakeScopeExit(ExitFunction&& exitFunction)
|
||||
{
|
||||
return ScopeExit<ExitFunction>(mozilla::Move(exitFunction));
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_ScopeExit_h */
|
||||
255
cocos2d-x/external/win32/include/spidermonkey/mozilla/Scoped.h
vendored
Executable file
255
cocos2d-x/external/win32/include/spidermonkey/mozilla/Scoped.h
vendored
Executable file
@@ -0,0 +1,255 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* DEPRECATED: Use UniquePtr.h instead. */
|
||||
|
||||
#ifndef mozilla_Scoped_h
|
||||
#define mozilla_Scoped_h
|
||||
|
||||
/*
|
||||
* DEPRECATED: Use UniquePtr.h instead.
|
||||
*
|
||||
* Resource Acquisition Is Initialization is a programming idiom used
|
||||
* to write robust code that is able to deallocate resources properly,
|
||||
* even in presence of execution errors or exceptions that need to be
|
||||
* propagated. The Scoped* classes defined via the |SCOPED_TEMPLATE|
|
||||
* and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLTE| macros perform the
|
||||
* deallocation of the resource they hold once program execution
|
||||
* reaches the end of the scope for which they have been defined.
|
||||
* These macros have been used to automatically close file
|
||||
* descriptors/file handles when reaching the end of the scope,
|
||||
* graphics contexts, etc.
|
||||
*
|
||||
* The general scenario for RAII classes created by the above macros
|
||||
* is the following:
|
||||
*
|
||||
* ScopedClass foo(create_value());
|
||||
* // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()|
|
||||
* to access the value.
|
||||
* // ... In case of |return| or |throw|, |foo| is deallocated automatically.
|
||||
* // ... If |foo| needs to be returned or stored, use |foo.forget()|
|
||||
*
|
||||
* Note that the RAII classes defined in this header do _not_ perform any form
|
||||
* of reference-counting or garbage-collection. These classes have exactly two
|
||||
* behaviors:
|
||||
*
|
||||
* - if |forget()| has not been called, the resource is always deallocated at
|
||||
* the end of the scope;
|
||||
* - if |forget()| has been called, any control on the resource is unbound
|
||||
* and the resource is not deallocated by the class.
|
||||
*/
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* Scoped is a helper to create RAII wrappers
|
||||
* Type argument |Traits| is expected to have the following structure:
|
||||
*
|
||||
* struct Traits
|
||||
* {
|
||||
* // Define the type of the value stored in the wrapper
|
||||
* typedef value_type type;
|
||||
* // Returns the value corresponding to the uninitialized or freed state
|
||||
* const static type empty();
|
||||
* // Release resources corresponding to the wrapped value
|
||||
* // This function is responsible for not releasing an |empty| value
|
||||
* const static void release(type);
|
||||
* }
|
||||
*/
|
||||
template<typename Traits>
|
||||
class MOZ_NON_TEMPORARY_CLASS Scoped
|
||||
{
|
||||
public:
|
||||
typedef typename Traits::type Resource;
|
||||
|
||||
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||
: mValue(Traits::empty())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
explicit Scoped(const Resource& aValue
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mValue(aValue)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
/* Move constructor. */
|
||||
Scoped(Scoped&& aOther
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mValue(Move(aOther.mValue))
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
aOther.mValue = Traits::empty();
|
||||
}
|
||||
|
||||
~Scoped() { Traits::release(mValue); }
|
||||
|
||||
// Constant getter
|
||||
operator const Resource&() const { return mValue; }
|
||||
const Resource& operator->() const { return mValue; }
|
||||
const Resource& get() const { return mValue; }
|
||||
// Non-constant getter.
|
||||
Resource& rwget() { return mValue; }
|
||||
|
||||
/*
|
||||
* Forget the resource.
|
||||
*
|
||||
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
|
||||
* have no effect at destruction (unless it is reset to another resource by
|
||||
* |operator=|).
|
||||
*
|
||||
* @return The original resource.
|
||||
*/
|
||||
Resource forget()
|
||||
{
|
||||
Resource tmp = mValue;
|
||||
mValue = Traits::empty();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform immediate clean-up of this |Scoped|.
|
||||
*
|
||||
* If this |Scoped| is currently empty, this method has no effect.
|
||||
*/
|
||||
void dispose()
|
||||
{
|
||||
Traits::release(mValue);
|
||||
mValue = Traits::empty();
|
||||
}
|
||||
|
||||
bool operator==(const Resource& aOther) const { return mValue == aOther; }
|
||||
|
||||
/*
|
||||
* Replace the resource with another resource.
|
||||
*
|
||||
* Calling |operator=| has the side-effect of triggering clean-up. If you do
|
||||
* not want to trigger clean-up, you should first invoke |forget|.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
Scoped& operator=(const Resource& aOther) { return reset(aOther); }
|
||||
|
||||
Scoped& reset(const Resource& aOther)
|
||||
{
|
||||
Traits::release(mValue);
|
||||
mValue = aOther;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Move assignment operator. */
|
||||
Scoped& operator=(Scoped&& aRhs)
|
||||
{
|
||||
MOZ_ASSERT(&aRhs != this, "self-move-assignment not allowed");
|
||||
this->~Scoped();
|
||||
new(this) Scoped(Move(aRhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Scoped(const Scoped& aValue) = delete;
|
||||
Scoped& operator=(const Scoped& aValue) = delete;
|
||||
|
||||
private:
|
||||
Resource mValue;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/*
|
||||
* SCOPED_TEMPLATE defines a templated class derived from Scoped
|
||||
* This allows to implement templates such as ScopedFreePtr.
|
||||
*
|
||||
* @param name The name of the class to define.
|
||||
* @param Traits A struct implementing clean-up. See the implementations
|
||||
* for more details.
|
||||
*/
|
||||
#define SCOPED_TEMPLATE(name, Traits) \
|
||||
template<typename Type> \
|
||||
struct MOZ_NON_TEMPORARY_CLASS name : public mozilla::Scoped<Traits<Type> > \
|
||||
{ \
|
||||
typedef mozilla::Scoped<Traits<Type> > Super; \
|
||||
typedef typename Super::Resource Resource; \
|
||||
name& operator=(Resource aRhs) \
|
||||
{ \
|
||||
Super::operator=(aRhs); \
|
||||
return *this; \
|
||||
} \
|
||||
name& operator=(name&& aRhs) \
|
||||
{ \
|
||||
Super::operator=(Move(aRhs)); \
|
||||
return *this; \
|
||||
} \
|
||||
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
|
||||
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
explicit name(Resource aRhs \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
||||
: Super(aRhs \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
name(name&& aRhs \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
||||
: Super(Move(aRhs) \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
private: \
|
||||
explicit name(name&) = delete; \
|
||||
name& operator=(name&) = delete; \
|
||||
};
|
||||
|
||||
/*
|
||||
* MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE makes it easy to create scoped
|
||||
* pointers for types with custom deleters; just overload
|
||||
* TypeSpecificDelete(T*) in the same namespace as T to call the deleter for
|
||||
* type T.
|
||||
*
|
||||
* @param name The name of the class to define.
|
||||
* @param Type A struct implementing clean-up. See the implementations
|
||||
* for more details.
|
||||
* *param Deleter The function that is used to delete/destroy/free a
|
||||
* non-null value of Type*.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc, \
|
||||
* PR_Close)
|
||||
* ...
|
||||
* {
|
||||
* ScopedPRFileDesc file(PR_OpenFile(...));
|
||||
* ...
|
||||
* } // file is closed with PR_Close here
|
||||
*/
|
||||
#define MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(name, Type, Deleter) \
|
||||
template <> inline void TypeSpecificDelete(Type* aValue) { Deleter(aValue); } \
|
||||
typedef ::mozilla::TypeSpecificScopedPointer<Type> name;
|
||||
|
||||
template <typename T> void TypeSpecificDelete(T* aValue);
|
||||
|
||||
template <typename T>
|
||||
struct TypeSpecificScopedPointerTraits
|
||||
{
|
||||
typedef T* type;
|
||||
static type empty() { return nullptr; }
|
||||
static void release(type aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
TypeSpecificDelete(aValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SCOPED_TEMPLATE(TypeSpecificScopedPointer, TypeSpecificScopedPointerTraits)
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_Scoped_h */
|
||||
339
cocos2d-x/external/win32/include/spidermonkey/mozilla/SegmentedVector.h
vendored
Executable file
339
cocos2d-x/external/win32/include/spidermonkey/mozilla/SegmentedVector.h
vendored
Executable file
@@ -0,0 +1,339 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// A simple segmented vector class.
|
||||
//
|
||||
// This class should be used in preference to mozilla::Vector or nsTArray when
|
||||
// you are simply gathering items in order to later iterate over them.
|
||||
//
|
||||
// - In the case where you don't know the final size in advance, using
|
||||
// SegmentedVector avoids the need to repeatedly allocate increasingly large
|
||||
// buffers and copy the data into them.
|
||||
//
|
||||
// - In the case where you know the final size in advance and so can set the
|
||||
// capacity appropriately, using SegmentedVector still avoids the need for
|
||||
// large allocations (which can trigger OOMs).
|
||||
|
||||
#ifndef mozilla_SegmentedVector_h
|
||||
#define mozilla_SegmentedVector_h
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/AllocPolicy.h"
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <new> // for placement new
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// |IdealSegmentSize| specifies how big each segment will be in bytes (or as
|
||||
// close as is possible). Use the following guidelines to choose a size.
|
||||
//
|
||||
// - It should be a power-of-two, to avoid slop.
|
||||
//
|
||||
// - It should not be too small, so that segment allocations are infrequent,
|
||||
// and so that per-segment bookkeeping overhead is low. Typically each
|
||||
// segment should be able to hold hundreds of elements, at least.
|
||||
//
|
||||
// - It should not be too large, so that OOMs are unlikely when allocating
|
||||
// segments, and so that not too much space is wasted when the final segment
|
||||
// is not full.
|
||||
//
|
||||
// The ideal size depends on how the SegmentedVector is used and the size of
|
||||
// |T|, but reasonable sizes include 1024, 4096 (the default), 8192, and 16384.
|
||||
//
|
||||
template<typename T,
|
||||
size_t IdealSegmentSize = 4096,
|
||||
typename AllocPolicy = MallocAllocPolicy>
|
||||
class SegmentedVector : private AllocPolicy
|
||||
{
|
||||
template<size_t SegmentCapacity>
|
||||
struct SegmentImpl
|
||||
: public mozilla::LinkedListElement<SegmentImpl<SegmentCapacity>>
|
||||
{
|
||||
SegmentImpl() : mLength(0) {}
|
||||
|
||||
~SegmentImpl()
|
||||
{
|
||||
for (uint32_t i = 0; i < mLength; i++) {
|
||||
(*this)[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Length() const { return mLength; }
|
||||
|
||||
T* Elems() { return reinterpret_cast<T*>(&mStorage.mBuf); }
|
||||
|
||||
T& operator[](size_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex < mLength);
|
||||
return Elems()[aIndex];
|
||||
}
|
||||
|
||||
const T& operator[](size_t aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(aIndex < mLength);
|
||||
return Elems()[aIndex];
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void Append(U&& aU)
|
||||
{
|
||||
MOZ_ASSERT(mLength < SegmentCapacity);
|
||||
// Pre-increment mLength so that the bounds-check in operator[] passes.
|
||||
mLength++;
|
||||
T* elem = &(*this)[mLength - 1];
|
||||
new (elem) T(mozilla::Forward<U>(aU));
|
||||
}
|
||||
|
||||
void PopLast()
|
||||
{
|
||||
MOZ_ASSERT(mLength > 0);
|
||||
(*this)[mLength - 1].~T();
|
||||
mLength--;
|
||||
}
|
||||
|
||||
uint32_t mLength;
|
||||
|
||||
// The union ensures that the elements are appropriately aligned.
|
||||
union Storage
|
||||
{
|
||||
char mBuf[sizeof(T) * SegmentCapacity];
|
||||
mozilla::AlignedElem<MOZ_ALIGNOF(T)> mAlign;
|
||||
} mStorage;
|
||||
|
||||
static_assert(MOZ_ALIGNOF(T) == MOZ_ALIGNOF(Storage),
|
||||
"SegmentedVector provides incorrect alignment");
|
||||
};
|
||||
|
||||
// See how many we elements we can fit in a segment of IdealSegmentSize. If
|
||||
// IdealSegmentSize is too small, it'll be just one. The +1 is because
|
||||
// kSingleElementSegmentSize already accounts for one element.
|
||||
static const size_t kSingleElementSegmentSize = sizeof(SegmentImpl<1>);
|
||||
static const size_t kSegmentCapacity =
|
||||
kSingleElementSegmentSize <= IdealSegmentSize
|
||||
? (IdealSegmentSize - kSingleElementSegmentSize) / sizeof(T) + 1
|
||||
: 1;
|
||||
|
||||
typedef SegmentImpl<kSegmentCapacity> Segment;
|
||||
|
||||
public:
|
||||
// The |aIdealSegmentSize| is only for sanity checking. If it's specified, we
|
||||
// check that the actual segment size is as close as possible to it. This
|
||||
// serves as a sanity check for SegmentedVectorCapacity's capacity
|
||||
// computation.
|
||||
explicit SegmentedVector(size_t aIdealSegmentSize = 0)
|
||||
{
|
||||
// The difference between the actual segment size and the ideal segment
|
||||
// size should be less than the size of a single element... unless the
|
||||
// ideal size was too small, in which case the capacity should be one.
|
||||
MOZ_ASSERT_IF(
|
||||
aIdealSegmentSize != 0,
|
||||
(sizeof(Segment) > aIdealSegmentSize && kSegmentCapacity == 1) ||
|
||||
aIdealSegmentSize - sizeof(Segment) < sizeof(T));
|
||||
}
|
||||
|
||||
~SegmentedVector() { Clear(); }
|
||||
|
||||
bool IsEmpty() const { return !mSegments.getFirst(); }
|
||||
|
||||
// Note that this is O(n) rather than O(1), but the constant factor is very
|
||||
// small because it only has to do one addition per segment.
|
||||
size_t Length() const
|
||||
{
|
||||
size_t n = 0;
|
||||
for (auto segment = mSegments.getFirst();
|
||||
segment;
|
||||
segment = segment->getNext()) {
|
||||
n += segment->Length();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// Returns false if the allocation failed. (If you are using an infallible
|
||||
// allocation policy, use InfallibleAppend() instead.)
|
||||
template<typename U>
|
||||
MOZ_MUST_USE bool Append(U&& aU)
|
||||
{
|
||||
Segment* last = mSegments.getLast();
|
||||
if (!last || last->Length() == kSegmentCapacity) {
|
||||
last = this->template pod_malloc<Segment>(1);
|
||||
if (!last) {
|
||||
return false;
|
||||
}
|
||||
new (last) Segment();
|
||||
mSegments.insertBack(last);
|
||||
}
|
||||
last->Append(mozilla::Forward<U>(aU));
|
||||
return true;
|
||||
}
|
||||
|
||||
// You should probably only use this instead of Append() if you are using an
|
||||
// infallible allocation policy. It will crash if the allocation fails.
|
||||
template<typename U>
|
||||
void InfallibleAppend(U&& aU)
|
||||
{
|
||||
bool ok = Append(mozilla::Forward<U>(aU));
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Segment* segment;
|
||||
while ((segment = mSegments.popFirst())) {
|
||||
segment->~Segment();
|
||||
this->free_(segment);
|
||||
}
|
||||
}
|
||||
|
||||
T& GetLast()
|
||||
{
|
||||
MOZ_ASSERT(!IsEmpty());
|
||||
Segment* last = mSegments.getLast();
|
||||
return (*last)[last->Length() - 1];
|
||||
}
|
||||
|
||||
const T& GetLast() const
|
||||
{
|
||||
MOZ_ASSERT(!IsEmpty());
|
||||
Segment* last = mSegments.getLast();
|
||||
return (*last)[last->Length() - 1];
|
||||
}
|
||||
|
||||
void PopLast()
|
||||
{
|
||||
MOZ_ASSERT(!IsEmpty());
|
||||
Segment* last = mSegments.getLast();
|
||||
last->PopLast();
|
||||
if (!last->Length()) {
|
||||
mSegments.popLast();
|
||||
last->~Segment();
|
||||
this->free_(last);
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent to calling |PopLast| |aNumElements| times, but potentially
|
||||
// more efficient.
|
||||
void PopLastN(uint32_t aNumElements)
|
||||
{
|
||||
MOZ_ASSERT(aNumElements <= Length());
|
||||
|
||||
Segment* last;
|
||||
|
||||
// Pop full segments for as long as we can. Note that this loop
|
||||
// cleanly handles the case when the initial last segment is not
|
||||
// full and we are popping more elements than said segment contains.
|
||||
do {
|
||||
last = mSegments.getLast();
|
||||
|
||||
// The list is empty. We're all done.
|
||||
if (!last) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if the list contains too many elements. Handle
|
||||
// that in the epilogue.
|
||||
uint32_t segmentLen = last->Length();
|
||||
if (segmentLen > aNumElements) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Destroying the segment destroys all elements contained therein.
|
||||
mSegments.popLast();
|
||||
last->~Segment();
|
||||
this->free_(last);
|
||||
|
||||
MOZ_ASSERT(aNumElements >= segmentLen);
|
||||
aNumElements -= segmentLen;
|
||||
if (aNumElements == 0) {
|
||||
return;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
// Handle the case where the last segment contains more elements
|
||||
// than we want to pop.
|
||||
MOZ_ASSERT(last);
|
||||
MOZ_ASSERT(last == mSegments.getLast());
|
||||
MOZ_ASSERT(aNumElements != 0);
|
||||
MOZ_ASSERT(aNumElements < last->Length());
|
||||
for (uint32_t i = 0; i < aNumElements; ++i) {
|
||||
last->PopLast();
|
||||
}
|
||||
MOZ_ASSERT(last->Length() != 0);
|
||||
}
|
||||
|
||||
// Use this class to iterate over a SegmentedVector, like so:
|
||||
//
|
||||
// for (auto iter = v.Iter(); !iter.Done(); iter.Next()) {
|
||||
// MyElem& elem = iter.Get();
|
||||
// f(elem);
|
||||
// }
|
||||
//
|
||||
class IterImpl
|
||||
{
|
||||
friend class SegmentedVector;
|
||||
|
||||
Segment* mSegment;
|
||||
size_t mIndex;
|
||||
|
||||
explicit IterImpl(SegmentedVector* aVector)
|
||||
: mSegment(aVector->mSegments.getFirst())
|
||||
, mIndex(0)
|
||||
{}
|
||||
|
||||
public:
|
||||
bool Done() const { return !mSegment; }
|
||||
|
||||
T& Get()
|
||||
{
|
||||
MOZ_ASSERT(!Done());
|
||||
return (*mSegment)[mIndex];
|
||||
}
|
||||
|
||||
const T& Get() const
|
||||
{
|
||||
MOZ_ASSERT(!Done());
|
||||
return (*mSegment)[mIndex];
|
||||
}
|
||||
|
||||
void Next()
|
||||
{
|
||||
MOZ_ASSERT(!Done());
|
||||
mIndex++;
|
||||
if (mIndex == mSegment->Length()) {
|
||||
mSegment = mSegment->getNext();
|
||||
mIndex = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IterImpl Iter() { return IterImpl(this); }
|
||||
|
||||
// Measure the memory consumption of the vector excluding |this|. Note that
|
||||
// it only measures the vector itself. If the vector elements contain
|
||||
// pointers to other memory blocks, those blocks must be measured separately
|
||||
// during a subsequent iteration over the vector.
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mSegments.sizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Like sizeOfExcludingThis(), but measures |this| as well.
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::LinkedList<Segment> mSegments;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_SegmentedVector_h */
|
||||
33
cocos2d-x/external/win32/include/spidermonkey/mozilla/SizePrintfMacros.h
vendored
Executable file
33
cocos2d-x/external/win32/include/spidermonkey/mozilla/SizePrintfMacros.h
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implements (nonstandard) PRI{ouxX}SIZE format macros for size_t types. */
|
||||
|
||||
#ifndef mozilla_SizePrintfMacros_h_
|
||||
#define mozilla_SizePrintfMacros_h_
|
||||
|
||||
/*
|
||||
* MSVC's libc does not support C99's %z format length modifier for size_t
|
||||
* types. Instead, we use Microsoft's nonstandard %I modifier for size_t, which
|
||||
* is unsigned __int32 on 32-bit platforms and unsigned __int64 on 64-bit
|
||||
* platforms:
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx
|
||||
*/
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# define PRIoSIZE "Io"
|
||||
# define PRIuSIZE "Iu"
|
||||
# define PRIxSIZE "Ix"
|
||||
# define PRIXSIZE "IX"
|
||||
#else
|
||||
# define PRIoSIZE "zo"
|
||||
# define PRIuSIZE "zu"
|
||||
# define PRIxSIZE "zx"
|
||||
# define PRIXSIZE "zX"
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_SizePrintfMacros_h_ */
|
||||
330
cocos2d-x/external/win32/include/spidermonkey/mozilla/SplayTree.h
vendored
Executable file
330
cocos2d-x/external/win32/include/spidermonkey/mozilla/SplayTree.h
vendored
Executable file
@@ -0,0 +1,330 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* A sorted tree with optimal access times, where recently-accessed elements
|
||||
* are faster to access again.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_SplayTree_h
|
||||
#define mozilla_SplayTree_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<class T, class C>
|
||||
class SplayTree;
|
||||
|
||||
template<typename T>
|
||||
class SplayTreeNode
|
||||
{
|
||||
public:
|
||||
template<class A, class B>
|
||||
friend class SplayTree;
|
||||
|
||||
SplayTreeNode()
|
||||
: mLeft(nullptr)
|
||||
, mRight(nullptr)
|
||||
, mParent(nullptr)
|
||||
{}
|
||||
|
||||
private:
|
||||
T* mLeft;
|
||||
T* mRight;
|
||||
T* mParent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class which represents a splay tree.
|
||||
* Splay trees are balanced binary search trees for which search, insert and
|
||||
* remove are all amortized O(log n), but where accessing a node makes it
|
||||
* faster to access that node in the future.
|
||||
*
|
||||
* T indicates the type of tree elements, Comparator must have a static
|
||||
* compare(const T&, const T&) method ordering the elements. The compare
|
||||
* method must be free from side effects.
|
||||
*/
|
||||
template<typename T, class Comparator>
|
||||
class SplayTree
|
||||
{
|
||||
T* mRoot;
|
||||
|
||||
public:
|
||||
constexpr SplayTree()
|
||||
: mRoot(nullptr)
|
||||
{}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return !mRoot;
|
||||
}
|
||||
|
||||
T* find(const T& aValue)
|
||||
{
|
||||
if (empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T* last = lookup(aValue);
|
||||
splay(last);
|
||||
return Comparator::compare(aValue, *last) == 0 ? last : nullptr;
|
||||
}
|
||||
|
||||
void insert(T* aValue)
|
||||
{
|
||||
MOZ_ASSERT(!find(*aValue), "Duplicate elements are not allowed.");
|
||||
|
||||
if (!mRoot) {
|
||||
mRoot = aValue;
|
||||
return;
|
||||
}
|
||||
T* last = lookup(*aValue);
|
||||
int cmp = Comparator::compare(*aValue, *last);
|
||||
|
||||
finishInsertion(last, cmp, aValue);
|
||||
return;
|
||||
}
|
||||
|
||||
T* findOrInsert(const T& aValue);
|
||||
|
||||
T* remove(const T& aValue)
|
||||
{
|
||||
T* last = lookup(aValue);
|
||||
MOZ_ASSERT(last, "This tree must contain the element being removed.");
|
||||
MOZ_ASSERT(Comparator::compare(aValue, *last) == 0);
|
||||
|
||||
// Splay the tree so that the item to remove is the root.
|
||||
splay(last);
|
||||
MOZ_ASSERT(last == mRoot);
|
||||
|
||||
// Find another node which can be swapped in for the root: either the
|
||||
// rightmost child of the root's left, or the leftmost child of the
|
||||
// root's right.
|
||||
T* swap;
|
||||
T* swapChild;
|
||||
if (mRoot->mLeft) {
|
||||
swap = mRoot->mLeft;
|
||||
while (swap->mRight) {
|
||||
swap = swap->mRight;
|
||||
}
|
||||
swapChild = swap->mLeft;
|
||||
} else if (mRoot->mRight) {
|
||||
swap = mRoot->mRight;
|
||||
while (swap->mLeft) {
|
||||
swap = swap->mLeft;
|
||||
}
|
||||
swapChild = swap->mRight;
|
||||
} else {
|
||||
T* result = mRoot;
|
||||
mRoot = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The selected node has at most one child, in swapChild. Detach it
|
||||
// from the subtree by replacing it with that child.
|
||||
if (swap == swap->mParent->mLeft) {
|
||||
swap->mParent->mLeft = swapChild;
|
||||
} else {
|
||||
swap->mParent->mRight = swapChild;
|
||||
}
|
||||
if (swapChild) {
|
||||
swapChild->mParent = swap->mParent;
|
||||
}
|
||||
|
||||
// Make the selected node the new root.
|
||||
mRoot = swap;
|
||||
mRoot->mParent = nullptr;
|
||||
mRoot->mLeft = last->mLeft;
|
||||
mRoot->mRight = last->mRight;
|
||||
if (mRoot->mLeft) {
|
||||
mRoot->mLeft->mParent = mRoot;
|
||||
}
|
||||
if (mRoot->mRight) {
|
||||
mRoot->mRight->mParent = mRoot;
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
T* removeMin()
|
||||
{
|
||||
MOZ_ASSERT(mRoot, "No min to remove!");
|
||||
|
||||
T* min = mRoot;
|
||||
while (min->mLeft) {
|
||||
min = min->mLeft;
|
||||
}
|
||||
return remove(*min);
|
||||
}
|
||||
|
||||
// For testing purposes only.
|
||||
void checkCoherency()
|
||||
{
|
||||
checkCoherency(mRoot, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns the node in this comparing equal to |aValue|, or a node just
|
||||
* greater or just less than |aValue| if there is no such node.
|
||||
*/
|
||||
T* lookup(const T& aValue)
|
||||
{
|
||||
MOZ_ASSERT(!empty());
|
||||
|
||||
T* node = mRoot;
|
||||
T* parent;
|
||||
do {
|
||||
parent = node;
|
||||
int c = Comparator::compare(aValue, *node);
|
||||
if (c == 0) {
|
||||
return node;
|
||||
} else if (c < 0) {
|
||||
node = node->mLeft;
|
||||
} else {
|
||||
node = node->mRight;
|
||||
}
|
||||
} while (node);
|
||||
return parent;
|
||||
}
|
||||
|
||||
void finishInsertion(T* aLast, int32_t aCmp, T* aNew)
|
||||
{
|
||||
MOZ_ASSERT(aCmp, "Nodes shouldn't be equal!");
|
||||
|
||||
T** parentPointer = (aCmp < 0) ? &aLast->mLeft : &aLast->mRight;
|
||||
MOZ_ASSERT(!*parentPointer);
|
||||
*parentPointer = aNew;
|
||||
aNew->mParent = aLast;
|
||||
|
||||
splay(aNew);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the tree until |node| is at the root of the tree. Performing
|
||||
* the rotations in this fashion preserves the amortized balancing of
|
||||
* the tree.
|
||||
*/
|
||||
void splay(T* aNode)
|
||||
{
|
||||
MOZ_ASSERT(aNode);
|
||||
|
||||
while (aNode != mRoot) {
|
||||
T* parent = aNode->mParent;
|
||||
if (parent == mRoot) {
|
||||
// Zig rotation.
|
||||
rotate(aNode);
|
||||
MOZ_ASSERT(aNode == mRoot);
|
||||
return;
|
||||
}
|
||||
T* grandparent = parent->mParent;
|
||||
if ((parent->mLeft == aNode) == (grandparent->mLeft == parent)) {
|
||||
// Zig-zig rotation.
|
||||
rotate(parent);
|
||||
rotate(aNode);
|
||||
} else {
|
||||
// Zig-zag rotation.
|
||||
rotate(aNode);
|
||||
rotate(aNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rotate(T* aNode)
|
||||
{
|
||||
// Rearrange nodes so that aNode becomes the parent of its current
|
||||
// parent, while preserving the sortedness of the tree.
|
||||
T* parent = aNode->mParent;
|
||||
if (parent->mLeft == aNode) {
|
||||
// x y
|
||||
// y c ==> a x
|
||||
// a b b c
|
||||
parent->mLeft = aNode->mRight;
|
||||
if (aNode->mRight) {
|
||||
aNode->mRight->mParent = parent;
|
||||
}
|
||||
aNode->mRight = parent;
|
||||
} else {
|
||||
MOZ_ASSERT(parent->mRight == aNode);
|
||||
// x y
|
||||
// a y ==> x c
|
||||
// b c a b
|
||||
parent->mRight = aNode->mLeft;
|
||||
if (aNode->mLeft) {
|
||||
aNode->mLeft->mParent = parent;
|
||||
}
|
||||
aNode->mLeft = parent;
|
||||
}
|
||||
aNode->mParent = parent->mParent;
|
||||
parent->mParent = aNode;
|
||||
if (T* grandparent = aNode->mParent) {
|
||||
if (grandparent->mLeft == parent) {
|
||||
grandparent->mLeft = aNode;
|
||||
} else {
|
||||
grandparent->mRight = aNode;
|
||||
}
|
||||
} else {
|
||||
mRoot = aNode;
|
||||
}
|
||||
}
|
||||
|
||||
T* checkCoherency(T* aNode, T* aMinimum)
|
||||
{
|
||||
if (mRoot) {
|
||||
MOZ_RELEASE_ASSERT(!mRoot->mParent);
|
||||
}
|
||||
if (!aNode) {
|
||||
MOZ_RELEASE_ASSERT(!mRoot);
|
||||
return nullptr;
|
||||
}
|
||||
if (!aNode->mParent) {
|
||||
MOZ_RELEASE_ASSERT(aNode == mRoot);
|
||||
}
|
||||
if (aMinimum) {
|
||||
MOZ_RELEASE_ASSERT(Comparator::compare(*aMinimum, *aNode) < 0);
|
||||
}
|
||||
if (aNode->mLeft) {
|
||||
MOZ_RELEASE_ASSERT(aNode->mLeft->mParent == aNode);
|
||||
T* leftMaximum = checkCoherency(aNode->mLeft, aMinimum);
|
||||
MOZ_RELEASE_ASSERT(Comparator::compare(*leftMaximum, *aNode) < 0);
|
||||
}
|
||||
if (aNode->mRight) {
|
||||
MOZ_RELEASE_ASSERT(aNode->mRight->mParent == aNode);
|
||||
return checkCoherency(aNode->mRight, aNode);
|
||||
}
|
||||
return aNode;
|
||||
}
|
||||
|
||||
SplayTree(const SplayTree&) = delete;
|
||||
void operator=(const SplayTree&) = delete;
|
||||
};
|
||||
|
||||
template<typename T, class Comparator>
|
||||
T*
|
||||
SplayTree<T, Comparator>::findOrInsert(const T& aValue)
|
||||
{
|
||||
if (!mRoot) {
|
||||
mRoot = new T(aValue);
|
||||
return mRoot;
|
||||
}
|
||||
|
||||
T* last = lookup(aValue);
|
||||
int cmp = Comparator::compare(aValue, *last);
|
||||
if (!cmp) {
|
||||
return last;
|
||||
}
|
||||
|
||||
T* t = new T(aValue);
|
||||
finishInsertion(last, cmp, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_SplayTree_h */
|
||||
41
cocos2d-x/external/win32/include/spidermonkey/mozilla/Sprintf.h
vendored
Executable file
41
cocos2d-x/external/win32/include/spidermonkey/mozilla/Sprintf.h
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Provides a safer sprintf for printing to fixed-size character arrays. */
|
||||
|
||||
#ifndef mozilla_Sprintf_h_
|
||||
#define mozilla_Sprintf_h_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
template <size_t N>
|
||||
int VsprintfLiteral(char (&buffer)[N], const char* format, va_list args)
|
||||
{
|
||||
MOZ_ASSERT(format != buffer);
|
||||
int result = vsnprintf(buffer, N, format, args);
|
||||
buffer[N - 1] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
MOZ_FORMAT_PRINTF(2, 3)
|
||||
int SprintfLiteral(char (&buffer)[N], const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int result = VsprintfLiteral(buffer, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* mozilla_Sprintf_h_ */
|
||||
163
cocos2d-x/external/win32/include/spidermonkey/mozilla/StackWalk.h
vendored
Executable file
163
cocos2d-x/external/win32/include/spidermonkey/mozilla/StackWalk.h
vendored
Executable file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* API for getting a stack trace of the C/C++ stack on the current thread */
|
||||
|
||||
#ifndef mozilla_StackWalk_h
|
||||
#define mozilla_StackWalk_h
|
||||
|
||||
/* WARNING: This file is intended to be included from C or C++ files. */
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* The callback for MozStackWalk.
|
||||
*
|
||||
* @param aFrameNumber The frame number (starts at 1, not 0).
|
||||
* @param aPC The program counter value.
|
||||
* @param aSP The best approximation possible of what the stack
|
||||
* pointer will be pointing to when the execution returns
|
||||
* to executing that at aPC. If no approximation can
|
||||
* be made it will be nullptr.
|
||||
* @param aClosure Extra data passed in via MozStackWalk().
|
||||
*/
|
||||
typedef void
|
||||
(*MozWalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP,
|
||||
void* aClosure);
|
||||
|
||||
/**
|
||||
* Call aCallback for the C/C++ stack frames on the current thread, from
|
||||
* the caller of MozStackWalk to main (or above).
|
||||
*
|
||||
* @param aCallback Callback function, called once per frame.
|
||||
* @param aSkipFrames Number of initial frames to skip. 0 means that
|
||||
* the first callback will be for the caller of
|
||||
* MozStackWalk.
|
||||
* @param aMaxFrames Maximum number of frames to trace. 0 means no limit.
|
||||
* @param aClosure Caller-supplied data passed through to aCallback.
|
||||
* @param aThread The thread for which the stack is to be retrieved.
|
||||
* Passing null causes us to walk the stack of the
|
||||
* current thread. On Windows, this is a thread HANDLE.
|
||||
* It is currently not supported on any other platform.
|
||||
* @param aPlatformData Platform specific data that can help in walking the
|
||||
* stack, this should be nullptr unless you really know
|
||||
* what you're doing! This needs to be a pointer to a
|
||||
* CONTEXT on Windows and should not be passed on other
|
||||
* platforms.
|
||||
*
|
||||
* May skip some stack frames due to compiler optimizations or code
|
||||
* generation.
|
||||
*
|
||||
*/
|
||||
MFBT_API bool
|
||||
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
|
||||
void* aPlatformData);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* The name of the shared library or executable containing an
|
||||
* address and the address's offset within that library, or empty
|
||||
* string and zero if unknown.
|
||||
*/
|
||||
char library[256];
|
||||
ptrdiff_t loffset;
|
||||
/*
|
||||
* The name of the file name and line number of the code
|
||||
* corresponding to the address, or empty string and zero if
|
||||
* unknown.
|
||||
*/
|
||||
char filename[256];
|
||||
unsigned long lineno;
|
||||
/*
|
||||
* The name of the function containing an address and the address's
|
||||
* offset within that function, or empty string and zero if unknown.
|
||||
*/
|
||||
char function[256];
|
||||
ptrdiff_t foffset;
|
||||
} MozCodeAddressDetails;
|
||||
|
||||
/**
|
||||
* For a given pointer to code, fill in the pieces of information used
|
||||
* when printing a stack trace.
|
||||
*
|
||||
* @param aPC The code address.
|
||||
* @param aDetails A structure to be filled in with the result.
|
||||
*/
|
||||
MFBT_API bool
|
||||
MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails);
|
||||
|
||||
/**
|
||||
* Format the information about a code address in a format suitable for
|
||||
* stack traces on the current platform. When available, this string
|
||||
* should contain the function name, source file, and line number. When
|
||||
* these are not available, library and offset should be reported, if
|
||||
* possible.
|
||||
*
|
||||
* Note that this output is parsed by several scripts including the fix*.py and
|
||||
* make-tree.pl scripts in tools/rb/. It should only be change with care, and
|
||||
* in conjunction with those scripts.
|
||||
*
|
||||
* @param aBuffer A string to be filled in with the description.
|
||||
* The string will always be null-terminated.
|
||||
* @param aBufferSize The size, in bytes, of aBuffer, including
|
||||
* room for the terminating null. If the information
|
||||
* to be printed would be larger than aBuffer, it
|
||||
* will be truncated so that aBuffer[aBufferSize-1]
|
||||
* is the terminating null.
|
||||
* @param aFrameNumber The frame number.
|
||||
* @param aPC The code address.
|
||||
* @param aFunction The function name. Possibly null or the empty string.
|
||||
* @param aLibrary The library name. Possibly null or the empty string.
|
||||
* @param aLOffset The library offset.
|
||||
* @param aFileName The filename. Possibly null or the empty string.
|
||||
* @param aLineNo The line number. Possibly zero.
|
||||
*/
|
||||
MFBT_API void
|
||||
MozFormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
|
||||
const void* aPC, const char* aFunction,
|
||||
const char* aLibrary, ptrdiff_t aLOffset,
|
||||
const char* aFileName, uint32_t aLineNo);
|
||||
|
||||
/**
|
||||
* Format the information about a code address in the same fashion as
|
||||
* MozFormatCodeAddress.
|
||||
*
|
||||
* @param aBuffer A string to be filled in with the description.
|
||||
* The string will always be null-terminated.
|
||||
* @param aBufferSize The size, in bytes, of aBuffer, including
|
||||
* room for the terminating null. If the information
|
||||
* to be printed would be larger than aBuffer, it
|
||||
* will be truncated so that aBuffer[aBufferSize-1]
|
||||
* is the terminating null.
|
||||
* @param aFrameNumber The frame number.
|
||||
* @param aPC The code address.
|
||||
* @param aDetails The value filled in by MozDescribeCodeAddress(aPC).
|
||||
*/
|
||||
MFBT_API void
|
||||
MozFormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
|
||||
uint32_t aFrameNumber, void* aPC,
|
||||
const MozCodeAddressDetails* aDetails);
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MFBT_API bool
|
||||
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
uint32_t aMaxFrames, void* aClosure, void** aBp,
|
||||
void* aStackEnd);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Initialize the critical sections for this platform so that we can
|
||||
* abort stack walks when needed.
|
||||
*/
|
||||
MFBT_API void
|
||||
StackWalkInitCriticalAddress(void);
|
||||
|
||||
#endif
|
||||
21
cocos2d-x/external/win32/include/spidermonkey/mozilla/StackWalk_windows.h
vendored
Executable file
21
cocos2d-x/external/win32/include/spidermonkey/mozilla/StackWalk_windows.h
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#ifndef mozilla_StackWalk_windows_h
|
||||
#define mozilla_StackWalk_windows_h
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
/**
|
||||
* Allow stack walkers to work around the egregious win64 dynamic lookup table
|
||||
* list API by locking around SuspendThread to avoid deadlock.
|
||||
*
|
||||
* See comment in StackWalk.cpp
|
||||
*/
|
||||
MFBT_API void
|
||||
AcquireStackWalkWorkaroundLock();
|
||||
|
||||
MFBT_API bool
|
||||
TryAcquireStackWalkWorkaroundLock();
|
||||
|
||||
MFBT_API void
|
||||
ReleaseStackWalkWorkaroundLock();
|
||||
|
||||
#endif // mozilla_StackWalk_windows_h
|
||||
49
cocos2d-x/external/win32/include/spidermonkey/mozilla/StaticAnalysisFunctions.h
vendored
Executable file
49
cocos2d-x/external/win32/include/spidermonkey/mozilla/StaticAnalysisFunctions.h
vendored
Executable file
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_StaticAnalysisFunctions_h
|
||||
#define mozilla_StaticAnalysisFunctions_h
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef bool
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* Functions that are used as markers in Gecko code for static analysis. Their
|
||||
* purpose is to have different AST nodes generated during compile time and to
|
||||
* match them based on different checkers implemented in build/clang-plugin
|
||||
*/
|
||||
|
||||
#ifdef MOZ_CLANG_PLUGIN
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_AssertAssignmentTest - used in MOZ_ASSERT in order to test the possible
|
||||
* presence of assignment instead of logical comparisons.
|
||||
*
|
||||
* Example:
|
||||
* MOZ_ASSERT(retVal = true);
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE bool MOZ_AssertAssignmentTest(bool exprResult) {
|
||||
return exprResult;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) MOZ_AssertAssignmentTest(!!(expr))
|
||||
|
||||
#else
|
||||
|
||||
#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) (!!(expr))
|
||||
|
||||
#endif /* MOZ_CLANG_PLUGIN */
|
||||
#endif /* StaticAnalysisFunctions_h */
|
||||
86
cocos2d-x/external/win32/include/spidermonkey/mozilla/TaggedAnonymousMemory.h
vendored
Executable file
86
cocos2d-x/external/win32/include/spidermonkey/mozilla/TaggedAnonymousMemory.h
vendored
Executable file
@@ -0,0 +1,86 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Some Linux kernels -- specifically, newer versions of Android and
|
||||
// some B2G devices -- have a feature for assigning names to ranges of
|
||||
// anonymous memory (i.e., memory that doesn't have a "name" in the
|
||||
// form of an underlying mapped file). These names are reported in
|
||||
// /proc/<pid>/smaps alongside system-level memory usage information
|
||||
// such as Proportional Set Size (memory usage adjusted for sharing
|
||||
// between processes), which allows reporting this information at a
|
||||
// finer granularity than would otherwise be possible (e.g.,
|
||||
// separating malloc() heap from JS heap).
|
||||
//
|
||||
// Existing memory can be tagged with MozTagAnonymousMemory(); it will
|
||||
// tag the range of complete pages containing the given interval, so
|
||||
// the results may be inexact if the range isn't page-aligned.
|
||||
// MozTaggedAnonymousMmap() can be used like mmap() with an extra
|
||||
// parameter, and will tag the returned memory if the mapping was
|
||||
// successful (and if it was in fact anonymous).
|
||||
//
|
||||
// NOTE: The pointer given as the "tag" argument MUST remain valid as
|
||||
// long as the mapping exists. The referenced string is read when
|
||||
// /proc/<pid>/smaps or /proc/<pid>/maps is read, not when the tag is
|
||||
// established, so freeing it or changing its contents will have
|
||||
// unexpected results. Using a static string is probably best.
|
||||
//
|
||||
// Also note that this header can be used by both C and C++ code.
|
||||
|
||||
#ifndef mozilla_TaggedAnonymousMemory_h
|
||||
#define mozilla_TaggedAnonymousMemory_h
|
||||
|
||||
#ifndef XP_WIN
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
MFBT_API void
|
||||
MozTagAnonymousMemory(const void* aPtr, size_t aLength, const char* aTag);
|
||||
|
||||
MFBT_API void*
|
||||
MozTaggedAnonymousMmap(void* aAddr, size_t aLength, int aProt, int aFlags,
|
||||
int aFd, off_t aOffset, const char* aTag);
|
||||
|
||||
MFBT_API int
|
||||
MozTaggedMemoryIsSupported(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#else // ANDROID
|
||||
|
||||
static inline void
|
||||
MozTagAnonymousMemory(const void* aPtr, size_t aLength, const char* aTag)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void*
|
||||
MozTaggedAnonymousMmap(void* aAddr, size_t aLength, int aProt, int aFlags,
|
||||
int aFd, off_t aOffset, const char* aTag)
|
||||
{
|
||||
return mmap(aAddr, aLength, aProt, aFlags, aFd, aOffset);
|
||||
}
|
||||
|
||||
static inline int
|
||||
MozTaggedMemoryIsSupported(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
||||
|
||||
#endif // !XP_WIN
|
||||
|
||||
#endif // mozilla_TaggedAnonymousMemory_h
|
||||
133
cocos2d-x/external/win32/include/spidermonkey/mozilla/TemplateLib.h
vendored
Executable file
133
cocos2d-x/external/win32/include/spidermonkey/mozilla/TemplateLib.h
vendored
Executable file
@@ -0,0 +1,133 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Reusable template meta-functions on types and compile-time values. Meta-
|
||||
* functions are placed inside the 'tl' namespace to avoid conflict with non-
|
||||
* meta functions of the same name (e.g., mozilla::tl::FloorLog2 vs.
|
||||
* mozilla::FloorLog2).
|
||||
*
|
||||
* When constexpr support becomes universal, we should probably use that instead
|
||||
* of some of these templates, for simplicity.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_TemplateLib_h
|
||||
#define mozilla_TemplateLib_h
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace tl {
|
||||
|
||||
/** Compute min/max. */
|
||||
template<size_t I, size_t J>
|
||||
struct Min
|
||||
{
|
||||
static const size_t value = I < J ? I : J;
|
||||
};
|
||||
template<size_t I, size_t J>
|
||||
struct Max
|
||||
{
|
||||
static const size_t value = I > J ? I : J;
|
||||
};
|
||||
|
||||
/** Compute floor(log2(i)). */
|
||||
template<size_t I>
|
||||
struct FloorLog2
|
||||
{
|
||||
static const size_t value = 1 + FloorLog2<I / 2>::value;
|
||||
};
|
||||
template<> struct FloorLog2<0> { /* Error */ };
|
||||
template<> struct FloorLog2<1> { static const size_t value = 0; };
|
||||
|
||||
/** Compute ceiling(log2(i)). */
|
||||
template<size_t I>
|
||||
struct CeilingLog2
|
||||
{
|
||||
static const size_t value = FloorLog2<2 * I - 1>::value;
|
||||
};
|
||||
|
||||
/** Round up to the nearest power of 2. */
|
||||
template<size_t I>
|
||||
struct RoundUpPow2
|
||||
{
|
||||
static const size_t value = size_t(1) << CeilingLog2<I>::value;
|
||||
};
|
||||
template<>
|
||||
struct RoundUpPow2<0>
|
||||
{
|
||||
static const size_t value = 1;
|
||||
};
|
||||
|
||||
/** Compute the number of bits in the given unsigned type. */
|
||||
template<typename T>
|
||||
struct BitSize
|
||||
{
|
||||
static const size_t value = sizeof(T) * CHAR_BIT;
|
||||
};
|
||||
|
||||
/**
|
||||
* Produce an N-bit mask, where N <= BitSize<size_t>::value. Handle the
|
||||
* language-undefined edge case when N = BitSize<size_t>::value.
|
||||
*/
|
||||
template<size_t N>
|
||||
struct NBitMask
|
||||
{
|
||||
// Assert the precondition. On success this evaluates to 0. Otherwise it
|
||||
// triggers divide-by-zero at compile time: a guaranteed compile error in
|
||||
// C++11, and usually one in C++98. Add this value to |value| to assure
|
||||
// its computation.
|
||||
static const size_t checkPrecondition =
|
||||
0 / size_t(N < BitSize<size_t>::value);
|
||||
static const size_t value = (size_t(1) << N) - 1 + checkPrecondition;
|
||||
};
|
||||
template<>
|
||||
struct NBitMask<BitSize<size_t>::value>
|
||||
{
|
||||
static const size_t value = size_t(-1);
|
||||
};
|
||||
|
||||
/**
|
||||
* For the unsigned integral type size_t, compute a mask M for N such that
|
||||
* for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
|
||||
*/
|
||||
template<size_t N>
|
||||
struct MulOverflowMask
|
||||
{
|
||||
static const size_t value =
|
||||
~NBitMask<BitSize<size_t>::value - CeilingLog2<N>::value>::value;
|
||||
};
|
||||
template<> struct MulOverflowMask<0> { /* Error */ };
|
||||
template<> struct MulOverflowMask<1> { static const size_t value = 0; };
|
||||
|
||||
/**
|
||||
* And<bool...> computes the logical 'and' of its argument booleans.
|
||||
*
|
||||
* Examples:
|
||||
* mozilla::t1::And<true, true>::value is true.
|
||||
* mozilla::t1::And<true, false>::value is false.
|
||||
* mozilla::t1::And<>::value is true.
|
||||
*/
|
||||
|
||||
template<bool...>
|
||||
struct And;
|
||||
|
||||
template<>
|
||||
struct And<> : public TrueType { };
|
||||
|
||||
template<bool C1, bool... Cn>
|
||||
struct And<C1, Cn...>
|
||||
: public Conditional<C1, And<Cn...>, FalseType>::Type { };
|
||||
|
||||
} // namespace tl
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_TemplateLib_h */
|
||||
222
cocos2d-x/external/win32/include/spidermonkey/mozilla/ThreadLocal.h
vendored
Executable file
222
cocos2d-x/external/win32/include/spidermonkey/mozilla/ThreadLocal.h
vendored
Executable file
@@ -0,0 +1,222 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Cross-platform lightweight thread local data wrappers. */
|
||||
|
||||
#ifndef mozilla_ThreadLocal_h
|
||||
#define mozilla_ThreadLocal_h
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// This file will get included in any file that wants to add a profiler mark.
|
||||
// In order to not bring <windows.h> together we could include windef.h and
|
||||
// winbase.h which are sufficient to get the prototypes for the Tls* functions.
|
||||
// # include <windef.h>
|
||||
// # include <winbase.h>
|
||||
// Unfortunately, even including these headers causes us to add a bunch of ugly
|
||||
// stuff to our namespace e.g #define CreateEvent CreateEventW
|
||||
extern "C" {
|
||||
__declspec(dllimport) void* __stdcall TlsGetValue(unsigned long);
|
||||
__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void*);
|
||||
__declspec(dllimport) unsigned long __stdcall TlsAlloc();
|
||||
}
|
||||
#else
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// sig_safe_t denotes an atomic type which can be read or stored in a single
|
||||
// instruction. This means that data of this type is safe to be manipulated
|
||||
// from a signal handler, or other similar asynchronous execution contexts.
|
||||
#if defined(XP_WIN)
|
||||
typedef unsigned long sig_safe_t;
|
||||
#else
|
||||
typedef sig_atomic_t sig_safe_t;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if defined(HAVE_THREAD_TLS_KEYWORD)
|
||||
#define MOZ_HAS_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Thread Local Storage helpers.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* Do not directly instantiate this class. Instead, use the
|
||||
* MOZ_THREAD_LOCAL macro to declare or define instances. The macro
|
||||
* takes a type name as its argument.
|
||||
*
|
||||
* Declare like this:
|
||||
* extern MOZ_THREAD_LOCAL(int) tlsInt;
|
||||
* Define like this:
|
||||
* MOZ_THREAD_LOCAL(int) tlsInt;
|
||||
* or:
|
||||
* static MOZ_THREAD_LOCAL(int) tlsInt;
|
||||
*
|
||||
* Only static-storage-duration (e.g. global variables, or static class members)
|
||||
* objects of this class should be instantiated. This class relies on
|
||||
* zero-initialization, which is implicit for static-storage-duration objects.
|
||||
* It doesn't have a custom default constructor, to avoid static initializers.
|
||||
*
|
||||
* API usage:
|
||||
*
|
||||
* // Create a TLS item.
|
||||
* //
|
||||
* // Note that init() should be invoked before the first use of set()
|
||||
* // or get(). It is ok to call it multiple times. This must be
|
||||
* // called in a way that avoids possible races with other threads.
|
||||
* MOZ_THREAD_LOCAL(int) tlsKey;
|
||||
* if (!tlsKey.init()) {
|
||||
* // deal with the error
|
||||
* }
|
||||
*
|
||||
* // Set the TLS value
|
||||
* tlsKey.set(123);
|
||||
*
|
||||
* // Get the TLS value
|
||||
* int value = tlsKey.get();
|
||||
*/
|
||||
template<typename T>
|
||||
class ThreadLocal
|
||||
{
|
||||
#ifndef MOZ_HAS_THREAD_LOCAL
|
||||
#if defined(XP_WIN)
|
||||
typedef unsigned long key_t;
|
||||
#else
|
||||
typedef pthread_key_t key_t;
|
||||
#endif
|
||||
|
||||
// Integral types narrower than void* must be extended to avoid
|
||||
// warnings from valgrind on some platforms. This helper type
|
||||
// achieves that without penalizing the common case of ThreadLocals
|
||||
// instantiated using a pointer type.
|
||||
template<typename S>
|
||||
struct Helper
|
||||
{
|
||||
typedef uintptr_t Type;
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
struct Helper<S *>
|
||||
{
|
||||
typedef S *Type;
|
||||
};
|
||||
#endif
|
||||
|
||||
bool initialized() const {
|
||||
#ifdef MOZ_HAS_THREAD_LOCAL
|
||||
return true;
|
||||
#else
|
||||
return mInited;
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
// __thread does not allow non-trivial constructors, but we can
|
||||
// instead rely on zero-initialization.
|
||||
#ifndef MOZ_HAS_THREAD_LOCAL
|
||||
ThreadLocal()
|
||||
: mKey(0), mInited(false)
|
||||
{}
|
||||
#endif
|
||||
|
||||
MOZ_MUST_USE inline bool init();
|
||||
|
||||
inline T get() const;
|
||||
|
||||
inline void set(const T aValue);
|
||||
|
||||
private:
|
||||
#ifdef MOZ_HAS_THREAD_LOCAL
|
||||
T mValue;
|
||||
#else
|
||||
key_t mKey;
|
||||
bool mInited;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
ThreadLocal<T>::init()
|
||||
{
|
||||
static_assert(mozilla::IsPointer<T>::value || mozilla::IsIntegral<T>::value,
|
||||
"mozilla::ThreadLocal must be used with a pointer or "
|
||||
"integral type");
|
||||
static_assert(sizeof(T) <= sizeof(void*),
|
||||
"mozilla::ThreadLocal can't be used for types larger than "
|
||||
"a pointer");
|
||||
|
||||
#ifdef MOZ_HAS_THREAD_LOCAL
|
||||
return true;
|
||||
#else
|
||||
if (!initialized()) {
|
||||
#ifdef XP_WIN
|
||||
mKey = TlsAlloc();
|
||||
mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
|
||||
#else
|
||||
mInited = !pthread_key_create(&mKey, nullptr);
|
||||
#endif
|
||||
}
|
||||
return mInited;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T
|
||||
ThreadLocal<T>::get() const
|
||||
{
|
||||
#ifdef MOZ_HAS_THREAD_LOCAL
|
||||
return mValue;
|
||||
#else
|
||||
MOZ_ASSERT(initialized());
|
||||
void* h;
|
||||
#ifdef XP_WIN
|
||||
h = TlsGetValue(mKey);
|
||||
#else
|
||||
h = pthread_getspecific(mKey);
|
||||
#endif
|
||||
return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
ThreadLocal<T>::set(const T aValue)
|
||||
{
|
||||
#ifdef MOZ_HAS_THREAD_LOCAL
|
||||
mValue = aValue;
|
||||
#else
|
||||
MOZ_ASSERT(initialized());
|
||||
void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
|
||||
#ifdef XP_WIN
|
||||
bool succeeded = TlsSetValue(mKey, h);
|
||||
#else
|
||||
bool succeeded = !pthread_setspecific(mKey, h);
|
||||
#endif
|
||||
if (!succeeded) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_HAS_THREAD_LOCAL
|
||||
#define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE>
|
||||
#else
|
||||
#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_ThreadLocal_h */
|
||||
609
cocos2d-x/external/win32/include/spidermonkey/mozilla/TimeStamp.h
vendored
Executable file
609
cocos2d-x/external/win32/include/spidermonkey/mozilla/TimeStamp.h
vendored
Executable file
@@ -0,0 +1,609 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_TimeStamp_h
|
||||
#define mozilla_TimeStamp_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
namespace IPC {
|
||||
template<typename T> struct ParamTraits;
|
||||
} // namespace IPC
|
||||
|
||||
#ifdef XP_WIN
|
||||
// defines TimeStampValue as a complex value keeping both
|
||||
// GetTickCount and QueryPerformanceCounter values
|
||||
#include "TimeStamp_windows.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifndef XP_WIN
|
||||
typedef uint64_t TimeStampValue;
|
||||
#endif
|
||||
|
||||
class TimeStamp;
|
||||
|
||||
/**
|
||||
* Platform-specific implementation details of BaseTimeDuration.
|
||||
*/
|
||||
class BaseTimeDurationPlatformUtils
|
||||
{
|
||||
public:
|
||||
static MFBT_API double ToSeconds(int64_t aTicks);
|
||||
static MFBT_API double ToSecondsSigDigits(int64_t aTicks);
|
||||
static MFBT_API int64_t TicksFromMilliseconds(double aMilliseconds);
|
||||
static MFBT_API int64_t ResolutionInTicks();
|
||||
};
|
||||
|
||||
/**
|
||||
* Instances of this class represent the length of an interval of time.
|
||||
* Negative durations are allowed, meaning the end is before the start.
|
||||
*
|
||||
* Internally the duration is stored as a int64_t in units of
|
||||
* PR_TicksPerSecond() when building with NSPR interval timers, or a
|
||||
* system-dependent unit when building with system clocks. The
|
||||
* system-dependent unit must be constant, otherwise the semantics of
|
||||
* this class would be broken.
|
||||
*
|
||||
* The ValueCalculator template parameter determines how arithmetic
|
||||
* operations are performed on the integer count of ticks (mValue).
|
||||
*/
|
||||
template <typename ValueCalculator>
|
||||
class BaseTimeDuration
|
||||
{
|
||||
public:
|
||||
// The default duration is 0.
|
||||
constexpr BaseTimeDuration() : mValue(0) {}
|
||||
// Allow construction using '0' as the initial value, for readability,
|
||||
// but no other numbers (so we don't have any implicit unit conversions).
|
||||
struct _SomethingVeryRandomHere;
|
||||
MOZ_IMPLICIT BaseTimeDuration(_SomethingVeryRandomHere* aZero) : mValue(0)
|
||||
{
|
||||
MOZ_ASSERT(!aZero, "Who's playing funny games here?");
|
||||
}
|
||||
// Default copy-constructor and assignment are OK
|
||||
|
||||
// Converting copy-constructor and assignment operator
|
||||
template <typename E>
|
||||
explicit BaseTimeDuration(const BaseTimeDuration<E>& aOther)
|
||||
: mValue(aOther.mValue)
|
||||
{ }
|
||||
|
||||
template <typename E>
|
||||
BaseTimeDuration& operator=(const BaseTimeDuration<E>& aOther)
|
||||
{
|
||||
mValue = aOther.mValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double ToSeconds() const
|
||||
{
|
||||
if (mValue == INT64_MAX) {
|
||||
return PositiveInfinity<double>();
|
||||
}
|
||||
if (mValue == INT64_MIN) {
|
||||
return NegativeInfinity<double>();
|
||||
}
|
||||
return BaseTimeDurationPlatformUtils::ToSeconds(mValue);
|
||||
}
|
||||
// Return a duration value that includes digits of time we think to
|
||||
// be significant. This method should be used when displaying a
|
||||
// time to humans.
|
||||
double ToSecondsSigDigits() const
|
||||
{
|
||||
if (mValue == INT64_MAX) {
|
||||
return PositiveInfinity<double>();
|
||||
}
|
||||
if (mValue == INT64_MIN) {
|
||||
return NegativeInfinity<double>();
|
||||
}
|
||||
return BaseTimeDurationPlatformUtils::ToSecondsSigDigits(mValue);
|
||||
}
|
||||
double ToMilliseconds() const { return ToSeconds() * 1000.0; }
|
||||
double ToMicroseconds() const { return ToMilliseconds() * 1000.0; }
|
||||
|
||||
// Using a double here is safe enough; with 53 bits we can represent
|
||||
// durations up to over 280,000 years exactly. If the units of
|
||||
// mValue do not allow us to represent durations of that length,
|
||||
// long durations are clamped to the max/min representable value
|
||||
// instead of overflowing.
|
||||
static inline BaseTimeDuration FromSeconds(double aSeconds)
|
||||
{
|
||||
return FromMilliseconds(aSeconds * 1000.0);
|
||||
}
|
||||
static BaseTimeDuration FromMilliseconds(double aMilliseconds)
|
||||
{
|
||||
if (aMilliseconds == PositiveInfinity<double>()) {
|
||||
return Forever();
|
||||
}
|
||||
if (aMilliseconds == NegativeInfinity<double>()) {
|
||||
return FromTicks(INT64_MIN);
|
||||
}
|
||||
return FromTicks(
|
||||
BaseTimeDurationPlatformUtils::TicksFromMilliseconds(aMilliseconds));
|
||||
}
|
||||
static inline BaseTimeDuration FromMicroseconds(double aMicroseconds)
|
||||
{
|
||||
return FromMilliseconds(aMicroseconds / 1000.0);
|
||||
}
|
||||
|
||||
static BaseTimeDuration Forever()
|
||||
{
|
||||
return FromTicks(INT64_MAX);
|
||||
}
|
||||
|
||||
BaseTimeDuration operator+(const BaseTimeDuration& aOther) const
|
||||
{
|
||||
return FromTicks(ValueCalculator::Add(mValue, aOther.mValue));
|
||||
}
|
||||
BaseTimeDuration operator-(const BaseTimeDuration& aOther) const
|
||||
{
|
||||
return FromTicks(ValueCalculator::Subtract(mValue, aOther.mValue));
|
||||
}
|
||||
BaseTimeDuration& operator+=(const BaseTimeDuration& aOther)
|
||||
{
|
||||
mValue = ValueCalculator::Add(mValue, aOther.mValue);
|
||||
return *this;
|
||||
}
|
||||
BaseTimeDuration& operator-=(const BaseTimeDuration& aOther)
|
||||
{
|
||||
mValue = ValueCalculator::Subtract(mValue, aOther.mValue);
|
||||
return *this;
|
||||
}
|
||||
BaseTimeDuration operator-() const
|
||||
{
|
||||
// We don't just use FromTicks(ValueCalculator::Subtract(0, mValue))
|
||||
// since that won't give the correct result for -TimeDuration::Forever().
|
||||
int64_t ticks;
|
||||
if (mValue == INT64_MAX) {
|
||||
ticks = INT64_MIN;
|
||||
} else if (mValue == INT64_MIN) {
|
||||
ticks = INT64_MAX;
|
||||
} else {
|
||||
ticks = -mValue;
|
||||
}
|
||||
|
||||
return FromTicks(ticks);
|
||||
}
|
||||
|
||||
private:
|
||||
// Block double multiplier (slower, imprecise if long duration) - Bug 853398.
|
||||
// If required, use MultDouble explicitly and with care.
|
||||
BaseTimeDuration operator*(const double aMultiplier) const = delete;
|
||||
|
||||
// Block double divisor (for the same reason, and because dividing by
|
||||
// fractional values would otherwise invoke the int64_t variant, and rounding
|
||||
// the passed argument can then cause divide-by-zero) - Bug 1147491.
|
||||
BaseTimeDuration operator/(const double aDivisor) const = delete;
|
||||
|
||||
public:
|
||||
BaseTimeDuration MultDouble(double aMultiplier) const
|
||||
{
|
||||
return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
|
||||
}
|
||||
BaseTimeDuration operator*(const int32_t aMultiplier) const
|
||||
{
|
||||
return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
|
||||
}
|
||||
BaseTimeDuration operator*(const uint32_t aMultiplier) const
|
||||
{
|
||||
return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
|
||||
}
|
||||
BaseTimeDuration operator*(const int64_t aMultiplier) const
|
||||
{
|
||||
return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
|
||||
}
|
||||
BaseTimeDuration operator*(const uint64_t aMultiplier) const
|
||||
{
|
||||
if (aMultiplier > INT64_MAX) {
|
||||
return Forever();
|
||||
}
|
||||
return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
|
||||
}
|
||||
BaseTimeDuration operator/(const int64_t aDivisor) const
|
||||
{
|
||||
MOZ_ASSERT(aDivisor != 0, "Division by zero");
|
||||
return FromTicks(ValueCalculator::Divide(mValue, aDivisor));
|
||||
}
|
||||
double operator/(const BaseTimeDuration& aOther) const
|
||||
{
|
||||
#ifndef MOZ_B2G
|
||||
// Bug 1066388 - This fails on B2G ICS Emulator
|
||||
MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
|
||||
#endif
|
||||
return ValueCalculator::DivideDouble(mValue, aOther.mValue);
|
||||
}
|
||||
BaseTimeDuration operator%(const BaseTimeDuration& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
|
||||
return FromTicks(ValueCalculator::Modulo(mValue, aOther.mValue));
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
bool operator<(const BaseTimeDuration<E>& aOther) const
|
||||
{
|
||||
return mValue < aOther.mValue;
|
||||
}
|
||||
template<typename E>
|
||||
bool operator<=(const BaseTimeDuration<E>& aOther) const
|
||||
{
|
||||
return mValue <= aOther.mValue;
|
||||
}
|
||||
template<typename E>
|
||||
bool operator>=(const BaseTimeDuration<E>& aOther) const
|
||||
{
|
||||
return mValue >= aOther.mValue;
|
||||
}
|
||||
template<typename E>
|
||||
bool operator>(const BaseTimeDuration<E>& aOther) const
|
||||
{
|
||||
return mValue > aOther.mValue;
|
||||
}
|
||||
template<typename E>
|
||||
bool operator==(const BaseTimeDuration<E>& aOther) const
|
||||
{
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
template<typename E>
|
||||
bool operator!=(const BaseTimeDuration<E>& aOther) const
|
||||
{
|
||||
return mValue != aOther.mValue;
|
||||
}
|
||||
bool IsZero() const
|
||||
{
|
||||
return mValue == 0;
|
||||
}
|
||||
explicit operator bool() const
|
||||
{
|
||||
return mValue != 0;
|
||||
}
|
||||
|
||||
// Return a best guess at the system's current timing resolution,
|
||||
// which might be variable. BaseTimeDurations below this order of
|
||||
// magnitude are meaningless, and those at the same order of
|
||||
// magnitude or just above are suspect.
|
||||
static BaseTimeDuration Resolution() {
|
||||
return FromTicks(BaseTimeDurationPlatformUtils::ResolutionInTicks());
|
||||
}
|
||||
|
||||
// We could define additional operators here:
|
||||
// -- convert to/from other time units
|
||||
// -- scale duration by a float
|
||||
// but let's do that on demand.
|
||||
// Comparing durations for equality will only lead to bugs on
|
||||
// platforms with high-resolution timers.
|
||||
|
||||
private:
|
||||
friend class TimeStamp;
|
||||
friend struct IPC::ParamTraits<mozilla::BaseTimeDuration<ValueCalculator>>;
|
||||
template <typename>
|
||||
friend class BaseTimeDuration;
|
||||
|
||||
static BaseTimeDuration FromTicks(int64_t aTicks)
|
||||
{
|
||||
BaseTimeDuration t;
|
||||
t.mValue = aTicks;
|
||||
return t;
|
||||
}
|
||||
|
||||
static BaseTimeDuration FromTicks(double aTicks)
|
||||
{
|
||||
// NOTE: this MUST be a >= test, because int64_t(double(INT64_MAX))
|
||||
// overflows and gives INT64_MIN.
|
||||
if (aTicks >= double(INT64_MAX)) {
|
||||
return FromTicks(INT64_MAX);
|
||||
}
|
||||
|
||||
// This MUST be a <= test.
|
||||
if (aTicks <= double(INT64_MIN)) {
|
||||
return FromTicks(INT64_MIN);
|
||||
}
|
||||
|
||||
return FromTicks(int64_t(aTicks));
|
||||
}
|
||||
|
||||
// Duration, result is implementation-specific difference of two TimeStamps
|
||||
int64_t mValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform arithmetic operations on the value of a BaseTimeDuration without
|
||||
* doing strict checks on the range of values.
|
||||
*/
|
||||
class TimeDurationValueCalculator
|
||||
{
|
||||
public:
|
||||
static int64_t Add(int64_t aA, int64_t aB) { return aA + aB; }
|
||||
static int64_t Subtract(int64_t aA, int64_t aB) { return aA - aB; }
|
||||
|
||||
template <typename T>
|
||||
static int64_t Multiply(int64_t aA, T aB)
|
||||
{
|
||||
static_assert(IsIntegral<T>::value,
|
||||
"Using integer multiplication routine with non-integer type."
|
||||
" Further specialization required");
|
||||
return aA * static_cast<int64_t>(aB);
|
||||
}
|
||||
|
||||
static int64_t Divide(int64_t aA, int64_t aB) { return aA / aB; }
|
||||
static double DivideDouble(int64_t aA, int64_t aB)
|
||||
{
|
||||
return static_cast<double>(aA) / aB;
|
||||
}
|
||||
static int64_t Modulo(int64_t aA, int64_t aB) { return aA % aB; }
|
||||
};
|
||||
|
||||
template <>
|
||||
inline int64_t
|
||||
TimeDurationValueCalculator::Multiply<double>(int64_t aA, double aB)
|
||||
{
|
||||
return static_cast<int64_t>(aA * aB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of BaseTimeDuration that uses TimeDurationValueCalculator for
|
||||
* arithmetic on the mValue member.
|
||||
*
|
||||
* Use this class for time durations that are *not* expected to hold values of
|
||||
* Forever (or the negative equivalent) or when such time duration are *not*
|
||||
* expected to be used in arithmetic operations.
|
||||
*/
|
||||
typedef BaseTimeDuration<TimeDurationValueCalculator> TimeDuration;
|
||||
|
||||
/**
|
||||
* Instances of this class represent moments in time, or a special
|
||||
* "null" moment. We do not use the non-monotonic system clock or
|
||||
* local time, since they can be reset, causing apparent backward
|
||||
* travel in time, which can confuse algorithms. Instead we measure
|
||||
* elapsed time according to the system. This time can never go
|
||||
* backwards (i.e. it never wraps around, at least not in less than
|
||||
* five million years of system elapsed time). It might not advance
|
||||
* while the system is sleeping. If TimeStamp::SetNow() is not called
|
||||
* at all for hours or days, we might not notice the passage of some
|
||||
* of that time.
|
||||
*
|
||||
* We deliberately do not expose a way to convert TimeStamps to some
|
||||
* particular unit. All you can do is compute a difference between two
|
||||
* TimeStamps to get a TimeDuration. You can also add a TimeDuration
|
||||
* to a TimeStamp to get a new TimeStamp. You can't do something
|
||||
* meaningless like add two TimeStamps.
|
||||
*
|
||||
* Internally this is implemented as either a wrapper around
|
||||
* - high-resolution, monotonic, system clocks if they exist on this
|
||||
* platform
|
||||
* - PRIntervalTime otherwise. We detect wraparounds of
|
||||
* PRIntervalTime and work around them.
|
||||
*
|
||||
* This class is similar to C++11's time_point, however it is
|
||||
* explicitly nullable and provides an IsNull() method. time_point
|
||||
* is initialized to the clock's epoch and provides a
|
||||
* time_since_epoch() method that functions similiarly. i.e.
|
||||
* t.IsNull() is equivalent to t.time_since_epoch() == decltype(t)::duration::zero();
|
||||
*/
|
||||
class TimeStamp
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initialize to the "null" moment
|
||||
*/
|
||||
constexpr TimeStamp() : mValue(0) {}
|
||||
// Default copy-constructor and assignment are OK
|
||||
|
||||
/**
|
||||
* The system timestamps are the same as the TimeStamp
|
||||
* retrieved by mozilla::TimeStamp. Since we need this for
|
||||
* vsync timestamps, we enable the creation of mozilla::TimeStamps
|
||||
* on platforms that support vsync aligned refresh drivers / compositors
|
||||
* Verified true as of Jan 31, 2015: B2G and OS X
|
||||
* False on Windows 7
|
||||
* UNTESTED ON OTHER PLATFORMS
|
||||
*/
|
||||
#if defined(MOZ_WIDGET_GONK) || defined(XP_DARWIN)
|
||||
static TimeStamp FromSystemTime(int64_t aSystemTime)
|
||||
{
|
||||
static_assert(sizeof(aSystemTime) == sizeof(TimeStampValue),
|
||||
"System timestamp should be same units as TimeStampValue");
|
||||
return TimeStamp(aSystemTime);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return true if this is the "null" moment
|
||||
*/
|
||||
bool IsNull() const { return mValue == 0; }
|
||||
|
||||
/**
|
||||
* Return true if this is not the "null" moment, may be used in tests, e.g.:
|
||||
* |if (timestamp) { ... }|
|
||||
*/
|
||||
explicit operator bool() const
|
||||
{
|
||||
return mValue != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a timestamp reflecting the current elapsed system time. This
|
||||
* is monotonically increasing (i.e., does not decrease) over the
|
||||
* lifetime of this process' XPCOM session.
|
||||
*
|
||||
* Now() is trying to ensure the best possible precision on each platform,
|
||||
* at least one millisecond.
|
||||
*
|
||||
* NowLoRes() has been introduced to workaround performance problems of
|
||||
* QueryPerformanceCounter on the Windows platform. NowLoRes() is giving
|
||||
* lower precision, usually 15.6 ms, but with very good performance benefit.
|
||||
* Use it for measurements of longer times, like >200ms timeouts.
|
||||
*/
|
||||
static TimeStamp Now() { return Now(true); }
|
||||
static TimeStamp NowLoRes() { return Now(false); }
|
||||
|
||||
/**
|
||||
* Return a timestamp representing the time when the current process was
|
||||
* created which will be comparable with other timestamps taken with this
|
||||
* class. If the actual process creation time is detected to be inconsistent
|
||||
* the @a aIsInconsistent parameter will be set to true, the returned
|
||||
* timestamp however will still be valid though inaccurate.
|
||||
*
|
||||
* @param aIsInconsistent Set to true if an inconsistency was detected in the
|
||||
* process creation time
|
||||
* @returns A timestamp representing the time when the process was created,
|
||||
* this timestamp is always valid even when errors are reported
|
||||
*/
|
||||
static MFBT_API TimeStamp ProcessCreation(bool& aIsInconsistent);
|
||||
|
||||
/**
|
||||
* Records a process restart. After this call ProcessCreation() will return
|
||||
* the time when the browser was restarted instead of the actual time when
|
||||
* the process was created.
|
||||
*/
|
||||
static MFBT_API void RecordProcessRestart();
|
||||
|
||||
/**
|
||||
* Compute the difference between two timestamps. Both must be non-null.
|
||||
*/
|
||||
TimeDuration operator-(const TimeStamp& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
|
||||
static_assert(-INT64_MAX > INT64_MIN, "int64_t sanity check");
|
||||
int64_t ticks = int64_t(mValue - aOther.mValue);
|
||||
// Check for overflow.
|
||||
if (mValue > aOther.mValue) {
|
||||
if (ticks < 0) {
|
||||
ticks = INT64_MAX;
|
||||
}
|
||||
} else {
|
||||
if (ticks > 0) {
|
||||
ticks = INT64_MIN;
|
||||
}
|
||||
}
|
||||
return TimeDuration::FromTicks(ticks);
|
||||
}
|
||||
|
||||
TimeStamp operator+(const TimeDuration& aOther) const
|
||||
{
|
||||
TimeStamp result = *this;
|
||||
result += aOther;
|
||||
return result;
|
||||
}
|
||||
TimeStamp operator-(const TimeDuration& aOther) const
|
||||
{
|
||||
TimeStamp result = *this;
|
||||
result -= aOther;
|
||||
return result;
|
||||
}
|
||||
TimeStamp& operator+=(const TimeDuration& aOther)
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
TimeStampValue value = mValue + aOther.mValue;
|
||||
// Check for underflow.
|
||||
// (We don't check for overflow because it's not obvious what the error
|
||||
// behavior should be in that case.)
|
||||
if (aOther.mValue < 0 && value > mValue) {
|
||||
value = 0;
|
||||
}
|
||||
mValue = value;
|
||||
return *this;
|
||||
}
|
||||
TimeStamp& operator-=(const TimeDuration& aOther)
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
TimeStampValue value = mValue - aOther.mValue;
|
||||
// Check for underflow.
|
||||
// (We don't check for overflow because it's not obvious what the error
|
||||
// behavior should be in that case.)
|
||||
if (aOther.mValue > 0 && value > mValue) {
|
||||
value = 0;
|
||||
}
|
||||
mValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator<(const TimeStamp& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
|
||||
return mValue < aOther.mValue;
|
||||
}
|
||||
bool operator<=(const TimeStamp& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
|
||||
return mValue <= aOther.mValue;
|
||||
}
|
||||
bool operator>=(const TimeStamp& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
|
||||
return mValue >= aOther.mValue;
|
||||
}
|
||||
bool operator>(const TimeStamp& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
|
||||
MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
|
||||
return mValue > aOther.mValue;
|
||||
}
|
||||
bool operator==(const TimeStamp& aOther) const
|
||||
{
|
||||
return IsNull()
|
||||
? aOther.IsNull()
|
||||
: !aOther.IsNull() && mValue == aOther.mValue;
|
||||
}
|
||||
bool operator!=(const TimeStamp& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
// Comparing TimeStamps for equality should be discouraged. Adding
|
||||
// two TimeStamps, or scaling TimeStamps, is nonsense and must never
|
||||
// be allowed.
|
||||
|
||||
static MFBT_API void Startup();
|
||||
static MFBT_API void Shutdown();
|
||||
|
||||
private:
|
||||
friend struct IPC::ParamTraits<mozilla::TimeStamp>;
|
||||
friend void StartupTimelineRecordExternal(int, uint64_t);
|
||||
|
||||
MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
|
||||
|
||||
static MFBT_API TimeStamp Now(bool aHighResolution);
|
||||
|
||||
/**
|
||||
* Computes the uptime of the current process in microseconds. The result
|
||||
* is platform-dependent and needs to be checked against existing timestamps
|
||||
* for consistency.
|
||||
*
|
||||
* @returns The number of microseconds since the calling process was started
|
||||
* or 0 if an error was encountered while computing the uptime
|
||||
*/
|
||||
static MFBT_API uint64_t ComputeProcessUptime();
|
||||
|
||||
/**
|
||||
* When built with PRIntervalTime, a value of 0 means this instance
|
||||
* is "null". Otherwise, the low 32 bits represent a PRIntervalTime,
|
||||
* and the high 32 bits represent a counter of the number of
|
||||
* rollovers of PRIntervalTime that we've seen. This counter starts
|
||||
* at 1 to avoid a real time colliding with the "null" value.
|
||||
*
|
||||
* PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum
|
||||
* time to wrap around is about 2^64/100000 seconds, i.e. about
|
||||
* 5,849,424 years.
|
||||
*
|
||||
* When using a system clock, a value is system dependent.
|
||||
*/
|
||||
TimeStampValue mValue;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_TimeStamp_h */
|
||||
83
cocos2d-x/external/win32/include/spidermonkey/mozilla/TimeStamp_windows.h
vendored
Executable file
83
cocos2d-x/external/win32/include/spidermonkey/mozilla/TimeStamp_windows.h
vendored
Executable file
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_TimeStamp_windows_h
|
||||
#define mozilla_TimeStamp_windows_h
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class TimeStamp;
|
||||
|
||||
class TimeStampValue
|
||||
{
|
||||
friend struct IPC::ParamTraits<mozilla::TimeStampValue>;
|
||||
friend class TimeStamp;
|
||||
friend void StartupTimelineRecordExternal(int, uint64_t);
|
||||
|
||||
// Both QPC and GTC are kept in [mt] units.
|
||||
uint64_t mGTC;
|
||||
uint64_t mQPC;
|
||||
bool mHasQPC;
|
||||
bool mIsNull;
|
||||
|
||||
MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC);
|
||||
|
||||
MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const;
|
||||
|
||||
struct _SomethingVeryRandomHere;
|
||||
constexpr TimeStampValue(_SomethingVeryRandomHere* aNullValue)
|
||||
: mGTC(0)
|
||||
, mQPC(0)
|
||||
, mHasQPC(false)
|
||||
, mIsNull(true)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
MFBT_API uint64_t operator-(const TimeStampValue& aOther) const;
|
||||
|
||||
TimeStampValue operator+(const int64_t aOther) const
|
||||
{
|
||||
return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC);
|
||||
}
|
||||
TimeStampValue operator-(const int64_t aOther) const
|
||||
{
|
||||
return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC);
|
||||
}
|
||||
MFBT_API TimeStampValue& operator+=(const int64_t aOther);
|
||||
MFBT_API TimeStampValue& operator-=(const int64_t aOther);
|
||||
|
||||
bool operator<(const TimeStampValue& aOther) const
|
||||
{
|
||||
return int64_t(*this - aOther) < 0;
|
||||
}
|
||||
bool operator>(const TimeStampValue& aOther) const
|
||||
{
|
||||
return int64_t(*this - aOther) > 0;
|
||||
}
|
||||
bool operator<=(const TimeStampValue& aOther) const
|
||||
{
|
||||
return int64_t(*this - aOther) <= 0;
|
||||
}
|
||||
bool operator>=(const TimeStampValue& aOther) const
|
||||
{
|
||||
return int64_t(*this - aOther) >= 0;
|
||||
}
|
||||
bool operator==(const TimeStampValue& aOther) const
|
||||
{
|
||||
return int64_t(*this - aOther) == 0;
|
||||
}
|
||||
bool operator!=(const TimeStampValue& aOther) const
|
||||
{
|
||||
return int64_t(*this - aOther) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* mozilla_TimeStamp_h */
|
||||
32
cocos2d-x/external/win32/include/spidermonkey/mozilla/ToString.h
vendored
Executable file
32
cocos2d-x/external/win32/include/spidermonkey/mozilla/ToString.h
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Utilities for converting an object to a string representation. */
|
||||
|
||||
#ifndef mozilla_ToString_h
|
||||
#define mozilla_ToString_h
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* A convenience function for converting an object to a string representation.
|
||||
* Supports any object which can be streamed to an std::ostream.
|
||||
*/
|
||||
template<typename T>
|
||||
std::string
|
||||
ToString(const T& aValue)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << aValue;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_ToString_h */
|
||||
461
cocos2d-x/external/win32/include/spidermonkey/mozilla/Tuple.h
vendored
Executable file
461
cocos2d-x/external/win32/include/spidermonkey/mozilla/Tuple.h
vendored
Executable file
@@ -0,0 +1,461 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A variadic tuple class. */
|
||||
|
||||
#ifndef mozilla_Tuple_h
|
||||
#define mozilla_Tuple_h
|
||||
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "mozilla/TemplateLib.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <utility>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* A helper class that allows passing around multiple variadic argument lists
|
||||
* by grouping them.
|
||||
*/
|
||||
template<typename... Ts>
|
||||
struct Group;
|
||||
|
||||
/*
|
||||
* CheckConvertibility checks whether each type in a source pack of types
|
||||
* is convertible to the corresponding type in a target pack of types.
|
||||
*
|
||||
* It is intended to be invoked like this:
|
||||
* CheckConvertibility<Group<SourceTypes...>, Group<TargetTypes...>>
|
||||
* 'Group' is used to separate types in the two packs (otherwise if we just
|
||||
* wrote 'CheckConvertibility<SourceTypes..., TargetTypes...', it couldn't
|
||||
* know where the first pack ends and the second begins).
|
||||
*
|
||||
* Note that we need to check explicitly that the two packs are of the same
|
||||
* size, because attempting to simultaneously expand two parameter packs
|
||||
* is an error (and it would be a hard error, because it wouldn't be in the
|
||||
* immediate context of the caller).
|
||||
*/
|
||||
|
||||
template<typename Source, typename Target, bool SameSize>
|
||||
struct CheckConvertibilityImpl;
|
||||
|
||||
template<typename Source, typename Target>
|
||||
struct CheckConvertibilityImpl<Source, Target, false>
|
||||
: FalseType {};
|
||||
|
||||
template<typename... SourceTypes, typename... TargetTypes>
|
||||
struct CheckConvertibilityImpl<Group<SourceTypes...>, Group<TargetTypes...>, true>
|
||||
: IntegralConstant<bool, tl::And<IsConvertible<SourceTypes, TargetTypes>::value...>::value> { };
|
||||
|
||||
template<typename Source, typename Target>
|
||||
struct CheckConvertibility;
|
||||
|
||||
template<typename... SourceTypes, typename... TargetTypes>
|
||||
struct CheckConvertibility<Group<SourceTypes...>, Group<TargetTypes...>>
|
||||
: CheckConvertibilityImpl<Group<SourceTypes...>, Group<TargetTypes...>,
|
||||
sizeof...(SourceTypes) == sizeof...(TargetTypes)> { };
|
||||
|
||||
/*
|
||||
* TupleImpl is a helper class used to implement mozilla::Tuple.
|
||||
* It represents one node in a recursive inheritance hierarchy.
|
||||
* 'Index' is the 0-based index of the tuple element stored in this node;
|
||||
* 'Elements...' are the types of the elements stored in this node and its
|
||||
* base classes.
|
||||
*
|
||||
* Example:
|
||||
* Tuple<int, float, char> inherits from
|
||||
* TupleImpl<0, int, float, char>, which stores the 'int' and inherits from
|
||||
* TupleImpl<1, float, char>, which stores the 'float' and inherits from
|
||||
* TupleImpl<2, char>, which stores the 'char' and inherits from
|
||||
* TupleImpl<3>, which stores nothing and terminates the recursion.
|
||||
*
|
||||
* The purpose of the 'Index' parameter is to allow efficient index-based
|
||||
* access to a tuple element: given a tuple, and an index 'I' that we wish to
|
||||
* access, we can cast the tuple to the base which stores the I'th element
|
||||
* by performing template argument deduction against 'TupleImpl<I, E...>',
|
||||
* where 'I' is specified explicitly and 'E...' is deduced (this is what the
|
||||
* non-member 'Get<N>(t)' function does).
|
||||
*
|
||||
* This implementation strategy is borrowed from libstdc++'s std::tuple
|
||||
* implementation.
|
||||
*/
|
||||
template<std::size_t Index, typename... Elements>
|
||||
struct TupleImpl;
|
||||
|
||||
/*
|
||||
* The base case of the inheritance recursion (and also the implementation
|
||||
* of an empty tuple).
|
||||
*/
|
||||
template<std::size_t Index>
|
||||
struct TupleImpl<Index> {
|
||||
bool operator==(const TupleImpl<Index>& aOther) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* One node of the recursive inheritance hierarchy. It stores the element at
|
||||
* index 'Index' of a tuple, of type 'HeadT', and inherits from the nodes
|
||||
* that store the remaining elements, of types 'TailT...'.
|
||||
*/
|
||||
template<std::size_t Index, typename HeadT, typename... TailT>
|
||||
struct TupleImpl<Index, HeadT, TailT...>
|
||||
: public TupleImpl<Index + 1, TailT...>
|
||||
{
|
||||
typedef TupleImpl<Index + 1, TailT...> Base;
|
||||
|
||||
// Accessors for the head and the tail.
|
||||
// These are static, because the intended usage is for the caller to,
|
||||
// given a tuple, obtain the type B of the base class which stores the
|
||||
// element of interest, and then call B::Head(tuple) to access it.
|
||||
// (Tail() is mostly for internal use, but is exposed for consistency.)
|
||||
static HeadT& Head(TupleImpl& aTuple) { return aTuple.mHead; }
|
||||
static const HeadT& Head(const TupleImpl& aTuple) { return aTuple.mHead; }
|
||||
static Base& Tail(TupleImpl& aTuple) { return aTuple; }
|
||||
static const Base& Tail(const TupleImpl& aTuple) { return aTuple; }
|
||||
|
||||
TupleImpl() : Base(), mHead() { }
|
||||
|
||||
// Construct from const references to the elements.
|
||||
explicit TupleImpl(const HeadT& aHead, const TailT&... aTail)
|
||||
: Base(aTail...), mHead(aHead) { }
|
||||
|
||||
// Construct from objects that are convertible to the elements.
|
||||
// This constructor is enabled only when the argument types are actually
|
||||
// convertible to the element types, otherwise it could become a better
|
||||
// match for certain invocations than the copy constructor.
|
||||
template <typename OtherHeadT, typename... OtherTailT,
|
||||
typename = typename EnableIf<
|
||||
CheckConvertibility<
|
||||
Group<OtherHeadT, OtherTailT...>,
|
||||
Group<HeadT, TailT...>>::value>::Type>
|
||||
explicit TupleImpl(OtherHeadT&& aHead, OtherTailT&&... aTail)
|
||||
: Base(Forward<OtherTailT>(aTail)...), mHead(Forward<OtherHeadT>(aHead)) { }
|
||||
|
||||
// Copy and move constructors.
|
||||
// We'd like to use '= default' to implement these, but MSVC 2013's support
|
||||
// for '= default' is incomplete and this doesn't work.
|
||||
TupleImpl(const TupleImpl& aOther)
|
||||
: Base(Tail(aOther))
|
||||
, mHead(Head(aOther)) {}
|
||||
TupleImpl(TupleImpl&& aOther)
|
||||
: Base(Move(Tail(aOther)))
|
||||
, mHead(Forward<HeadT>(Head(aOther))) {}
|
||||
|
||||
// Assign from a tuple whose elements are convertible to the elements
|
||||
// of this tuple.
|
||||
template <typename... OtherElements,
|
||||
typename = typename EnableIf<
|
||||
sizeof...(OtherElements) == sizeof...(TailT) + 1>::Type>
|
||||
TupleImpl& operator=(const TupleImpl<Index, OtherElements...>& aOther)
|
||||
{
|
||||
typedef TupleImpl<Index, OtherElements...> OtherT;
|
||||
Head(*this) = OtherT::Head(aOther);
|
||||
Tail(*this) = OtherT::Tail(aOther);
|
||||
return *this;
|
||||
}
|
||||
template <typename... OtherElements,
|
||||
typename = typename EnableIf<
|
||||
sizeof...(OtherElements) == sizeof...(TailT) + 1>::Type>
|
||||
TupleImpl& operator=(TupleImpl<Index, OtherElements...>&& aOther)
|
||||
{
|
||||
typedef TupleImpl<Index, OtherElements...> OtherT;
|
||||
Head(*this) = Move(OtherT::Head(aOther));
|
||||
Tail(*this) = Move(OtherT::Tail(aOther));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy and move assignment operators.
|
||||
TupleImpl& operator=(const TupleImpl& aOther)
|
||||
{
|
||||
Head(*this) = Head(aOther);
|
||||
Tail(*this) = Tail(aOther);
|
||||
return *this;
|
||||
}
|
||||
TupleImpl& operator=(TupleImpl&& aOther)
|
||||
{
|
||||
Head(*this) = Move(Head(aOther));
|
||||
Tail(*this) = Move(Tail(aOther));
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const TupleImpl& aOther) const
|
||||
{
|
||||
return Head(*this) == Head(aOther) && Tail(*this) == Tail(aOther);
|
||||
}
|
||||
private:
|
||||
HeadT mHead; // The element stored at this index in the tuple.
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Tuple is a class that stores zero or more objects, whose types are specified
|
||||
* as template parameters. It can be thought of as a generalization of Pair,
|
||||
* (which can be thought of as a 2-tuple).
|
||||
*
|
||||
* Tuple allows index-based access to its elements (with the index having to be
|
||||
* known at compile time) via the non-member function 'Get<N>(tuple)'.
|
||||
*/
|
||||
template<typename... Elements>
|
||||
class Tuple : public detail::TupleImpl<0, Elements...>
|
||||
{
|
||||
typedef detail::TupleImpl<0, Elements...> Impl;
|
||||
public:
|
||||
// The constructors and assignment operators here are simple wrappers
|
||||
// around those in TupleImpl.
|
||||
|
||||
Tuple() : Impl() { }
|
||||
explicit Tuple(const Elements&... aElements) : Impl(aElements...) { }
|
||||
// Here, we can't just use 'typename... OtherElements' because MSVC will give
|
||||
// a warning "C4520: multiple default constructors specified" (even if no one
|
||||
// actually instantiates the constructor with an empty parameter pack -
|
||||
// that's probably a bug) and we compile with warnings-as-errors.
|
||||
template <typename OtherHead, typename... OtherTail,
|
||||
typename = typename EnableIf<
|
||||
detail::CheckConvertibility<
|
||||
detail::Group<OtherHead, OtherTail...>,
|
||||
detail::Group<Elements...>>::value>::Type>
|
||||
explicit Tuple(OtherHead&& aHead, OtherTail&&... aTail)
|
||||
: Impl(Forward<OtherHead>(aHead), Forward<OtherTail>(aTail)...) { }
|
||||
Tuple(const Tuple& aOther) : Impl(aOther) { }
|
||||
Tuple(Tuple&& aOther) : Impl(Move(aOther)) { }
|
||||
|
||||
template <typename... OtherElements,
|
||||
typename = typename EnableIf<
|
||||
sizeof...(OtherElements) == sizeof...(Elements)>::Type>
|
||||
Tuple& operator=(const Tuple<OtherElements...>& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = aOther;
|
||||
return *this;
|
||||
}
|
||||
template <typename... OtherElements,
|
||||
typename = typename EnableIf<
|
||||
sizeof...(OtherElements) == sizeof...(Elements)>::Type>
|
||||
Tuple& operator=(Tuple<OtherElements...>&& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = Move(aOther);
|
||||
return *this;
|
||||
}
|
||||
Tuple& operator=(const Tuple& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = aOther;
|
||||
return *this;
|
||||
}
|
||||
Tuple& operator=(Tuple&& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = Move(aOther);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const Tuple& aOther) const
|
||||
{
|
||||
return static_cast<const Impl&>(*this) == static_cast<const Impl&>(aOther);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization of Tuple for two elements.
|
||||
* This is created to support construction and assignment from a Pair or std::pair.
|
||||
*/
|
||||
template <typename A, typename B>
|
||||
class Tuple<A, B> : public detail::TupleImpl<0, A, B>
|
||||
{
|
||||
typedef detail::TupleImpl<0, A, B> Impl;
|
||||
|
||||
public:
|
||||
// The constructors and assignment operators here are simple wrappers
|
||||
// around those in TupleImpl.
|
||||
|
||||
Tuple() : Impl() { }
|
||||
explicit Tuple(const A& aA, const B& aB) : Impl(aA, aB) { }
|
||||
template <typename AArg, typename BArg,
|
||||
typename = typename EnableIf<
|
||||
detail::CheckConvertibility<
|
||||
detail::Group<AArg, BArg>,
|
||||
detail::Group<A, B>>::value>::Type>
|
||||
explicit Tuple(AArg&& aA, BArg&& aB)
|
||||
: Impl(Forward<AArg>(aA), Forward<BArg>(aB)) { }
|
||||
Tuple(const Tuple& aOther) : Impl(aOther) { }
|
||||
Tuple(Tuple&& aOther) : Impl(Move(aOther)) { }
|
||||
explicit Tuple(const Pair<A, B>& aOther)
|
||||
: Impl(aOther.first(), aOther.second()) { }
|
||||
explicit Tuple(Pair<A, B>&& aOther) : Impl(Forward<A>(aOther.first()),
|
||||
Forward<B>(aOther.second())) { }
|
||||
explicit Tuple(const std::pair<A, B>& aOther)
|
||||
: Impl(aOther.first, aOther.second) { }
|
||||
explicit Tuple(std::pair<A, B>&& aOther) : Impl(Forward<A>(aOther.first),
|
||||
Forward<B>(aOther.second)) { }
|
||||
|
||||
template <typename AArg, typename BArg>
|
||||
Tuple& operator=(const Tuple<AArg, BArg>& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = aOther;
|
||||
return *this;
|
||||
}
|
||||
template <typename AArg, typename BArg>
|
||||
Tuple& operator=(Tuple<AArg, BArg>&& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = Move(aOther);
|
||||
return *this;
|
||||
}
|
||||
Tuple& operator=(const Tuple& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = aOther;
|
||||
return *this;
|
||||
}
|
||||
Tuple& operator=(Tuple&& aOther)
|
||||
{
|
||||
static_cast<Impl&>(*this) = Move(aOther);
|
||||
return *this;
|
||||
}
|
||||
template <typename AArg, typename BArg>
|
||||
Tuple& operator=(const Pair<AArg, BArg>& aOther)
|
||||
{
|
||||
Impl::Head(*this) = aOther.first();
|
||||
Impl::Tail(*this).Head(*this) = aOther.second();
|
||||
return *this;
|
||||
}
|
||||
template <typename AArg, typename BArg>
|
||||
Tuple& operator=(Pair<AArg, BArg>&& aOther)
|
||||
{
|
||||
Impl::Head(*this) = Forward<AArg>(aOther.first());
|
||||
Impl::Tail(*this).Head(*this) = Forward<BArg>(aOther.second());
|
||||
return *this;
|
||||
}
|
||||
template <typename AArg, typename BArg>
|
||||
Tuple& operator=(const std::pair<AArg, BArg>& aOther)
|
||||
{
|
||||
Impl::Head(*this) = aOther.first;
|
||||
Impl::Tail(*this).Head(*this) = aOther.second;
|
||||
return *this;
|
||||
}
|
||||
template <typename AArg, typename BArg>
|
||||
Tuple& operator=(std::pair<AArg, BArg>&& aOther)
|
||||
{
|
||||
Impl::Head(*this) = Forward<AArg>(aOther.first);
|
||||
Impl::Tail(*this).Head(*this) = Forward<BArg>(aOther.second);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization of Tuple for zero arguments.
|
||||
* This is necessary because if the primary template were instantiated with
|
||||
* an empty parameter pack, the 'Tuple(Elements...)' constructors would
|
||||
* become illegal overloads of the default constructor.
|
||||
*/
|
||||
template <>
|
||||
class Tuple<> {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* Helper functions for implementing Get<N>(tuple).
|
||||
* These functions take a TupleImpl<Index, Elements...>, with Index being
|
||||
* explicitly specified, and Elements being deduced. By passing a Tuple
|
||||
* object as argument, template argument deduction will do its magic and
|
||||
* cast the tuple to the base class which stores the element at Index.
|
||||
*/
|
||||
|
||||
// Const reference version.
|
||||
template<std::size_t Index, typename... Elements>
|
||||
auto TupleGetHelper(TupleImpl<Index, Elements...>& aTuple)
|
||||
-> decltype(TupleImpl<Index, Elements...>::Head(aTuple))
|
||||
{
|
||||
return TupleImpl<Index, Elements...>::Head(aTuple);
|
||||
}
|
||||
|
||||
// Non-const reference version.
|
||||
template<std::size_t Index, typename... Elements>
|
||||
auto TupleGetHelper(const TupleImpl<Index, Elements...>& aTuple)
|
||||
-> decltype(TupleImpl<Index, Elements...>::Head(aTuple))
|
||||
{
|
||||
return TupleImpl<Index, Elements...>::Head(aTuple);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Index-based access to an element of a tuple.
|
||||
* The syntax is Get<Index>(tuple). The index is zero-based.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Tuple<int, float, char> t;
|
||||
* ...
|
||||
* float f = Get<1>(t);
|
||||
*/
|
||||
|
||||
// Non-const reference version.
|
||||
template<std::size_t Index, typename... Elements>
|
||||
auto Get(Tuple<Elements...>& aTuple)
|
||||
-> decltype(detail::TupleGetHelper<Index>(aTuple))
|
||||
{
|
||||
return detail::TupleGetHelper<Index>(aTuple);
|
||||
}
|
||||
|
||||
// Const reference version.
|
||||
template<std::size_t Index, typename... Elements>
|
||||
auto Get(const Tuple<Elements...>& aTuple)
|
||||
-> decltype(detail::TupleGetHelper<Index>(aTuple))
|
||||
{
|
||||
return detail::TupleGetHelper<Index>(aTuple);
|
||||
}
|
||||
|
||||
// Rvalue reference version.
|
||||
template<std::size_t Index, typename... Elements>
|
||||
auto Get(Tuple<Elements...>&& aTuple)
|
||||
-> decltype(Move(mozilla::Get<Index>(aTuple)))
|
||||
{
|
||||
// We need a 'mozilla::' qualification here to avoid
|
||||
// name lookup only finding the current function.
|
||||
return Move(mozilla::Get<Index>(aTuple));
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for constructing a tuple out of a sequence of
|
||||
* values without specifying the type of the tuple.
|
||||
* The type of the tuple is deduced from the types of its elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* auto tuple = MakeTuple(42, 0.5f, 'c'); // has type Tuple<int, float, char>
|
||||
*/
|
||||
template<typename... Elements>
|
||||
inline Tuple<typename Decay<Elements>::Type...>
|
||||
MakeTuple(Elements&&... aElements)
|
||||
{
|
||||
return Tuple<typename Decay<Elements>::Type...>(Forward<Elements>(aElements)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for constructing a tuple of references to a
|
||||
* sequence of variables. Since assignments to the elements of the tuple
|
||||
* "go through" to the referenced variables, this can be used to "unpack"
|
||||
* a tuple into individual variables.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* int i;
|
||||
* float f;
|
||||
* char c;
|
||||
* Tie(i, f, c) = FunctionThatReturnsATuple();
|
||||
*/
|
||||
template<typename... Elements>
|
||||
inline Tuple<Elements&...>
|
||||
Tie(Elements&... aVariables)
|
||||
{
|
||||
return Tuple<Elements&...>(aVariables...);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Tuple_h */
|
||||
1262
cocos2d-x/external/win32/include/spidermonkey/mozilla/TypeTraits.h
vendored
Executable file
1262
cocos2d-x/external/win32/include/spidermonkey/mozilla/TypeTraits.h
vendored
Executable file
File diff suppressed because it is too large
Load Diff
156
cocos2d-x/external/win32/include/spidermonkey/mozilla/TypedEnumBits.h
vendored
Executable file
156
cocos2d-x/external/win32/include/spidermonkey/mozilla/TypedEnumBits.h
vendored
Executable file
@@ -0,0 +1,156 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS allows using a typed enum as bit flags.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_TypedEnumBits_h
|
||||
#define mozilla_TypedEnumBits_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* The problem that CastableTypedEnumResult aims to solve is that
|
||||
* typed enums are not convertible to bool, and there is no way to make them
|
||||
* be, yet user code wants to be able to write
|
||||
*
|
||||
* if (myFlags & Flags::SOME_PARTICULAR_FLAG) (1)
|
||||
*
|
||||
* There are different approaches to solving this. Most of them require
|
||||
* adapting user code. For example, we could implement operator! and have
|
||||
* the user write
|
||||
*
|
||||
* if (!!(myFlags & Flags::SOME_PARTICULAR_FLAG)) (2)
|
||||
*
|
||||
* Or we could supply a IsNonZero() or Any() function returning whether
|
||||
* an enum value is nonzero, and have the user write
|
||||
*
|
||||
* if (Any(Flags & Flags::SOME_PARTICULAR_FLAG)) (3)
|
||||
*
|
||||
* But instead, we choose to preserve the original user syntax (1) as it
|
||||
* is inherently more readable, and to ease porting existing code to typed
|
||||
* enums. We achieve this by having operator& and other binary bitwise
|
||||
* operators have as return type a class, CastableTypedEnumResult,
|
||||
* that wraps a typed enum but adds bool convertibility.
|
||||
*/
|
||||
template<typename E>
|
||||
class CastableTypedEnumResult
|
||||
{
|
||||
private:
|
||||
const E mValue;
|
||||
|
||||
public:
|
||||
explicit constexpr CastableTypedEnumResult(E aValue)
|
||||
: mValue(aValue)
|
||||
{}
|
||||
|
||||
constexpr operator E() const { return mValue; }
|
||||
|
||||
template<typename DestinationType>
|
||||
explicit constexpr
|
||||
operator DestinationType() const { return DestinationType(mValue); }
|
||||
|
||||
constexpr bool operator !() const { return !bool(mValue); }
|
||||
};
|
||||
|
||||
#define MOZ_CASTABLETYPEDENUMRESULT_BINOP(Op, OtherType, ReturnType) \
|
||||
template<typename E> \
|
||||
constexpr ReturnType \
|
||||
operator Op(const OtherType& aE, const CastableTypedEnumResult<E>& aR) \
|
||||
{ \
|
||||
return ReturnType(aE Op OtherType(aR)); \
|
||||
} \
|
||||
template<typename E> \
|
||||
constexpr ReturnType \
|
||||
operator Op(const CastableTypedEnumResult<E>& aR, const OtherType& aE) \
|
||||
{ \
|
||||
return ReturnType(OtherType(aR) Op aE); \
|
||||
} \
|
||||
template<typename E> \
|
||||
constexpr ReturnType \
|
||||
operator Op(const CastableTypedEnumResult<E>& aR1, \
|
||||
const CastableTypedEnumResult<E>& aR2) \
|
||||
{ \
|
||||
return ReturnType(OtherType(aR1) Op OtherType(aR2)); \
|
||||
}
|
||||
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(|, E, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(&, E, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(^, E, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(==, E, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(!=, E, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(||, bool, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(&&, bool, bool)
|
||||
|
||||
template <typename E>
|
||||
constexpr CastableTypedEnumResult<E>
|
||||
operator ~(const CastableTypedEnumResult<E>& aR)
|
||||
{
|
||||
return CastableTypedEnumResult<E>(~(E(aR)));
|
||||
}
|
||||
|
||||
#define MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(Op) \
|
||||
template<typename E> \
|
||||
E& \
|
||||
operator Op(E& aR1, \
|
||||
const CastableTypedEnumResult<E>& aR2) \
|
||||
{ \
|
||||
return aR1 Op E(aR2); \
|
||||
}
|
||||
|
||||
MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(&=)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(|=)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(^=)
|
||||
|
||||
#undef MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP
|
||||
|
||||
#undef MOZ_CASTABLETYPEDENUMRESULT_BINOP
|
||||
|
||||
namespace detail {
|
||||
template<typename E>
|
||||
struct UnsignedIntegerTypeForEnum
|
||||
: UnsignedStdintTypeForSize<sizeof(E)>
|
||||
{};
|
||||
} // namespace detail
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#define MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, Op) \
|
||||
inline constexpr mozilla::CastableTypedEnumResult<Name> \
|
||||
operator Op(Name a, Name b) \
|
||||
{ \
|
||||
typedef mozilla::CastableTypedEnumResult<Name> Result; \
|
||||
typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
|
||||
return Result(Name(U(a) Op U(b))); \
|
||||
} \
|
||||
\
|
||||
inline Name& \
|
||||
operator Op##=(Name& a, Name b) \
|
||||
{ \
|
||||
return a = a Op b; \
|
||||
}
|
||||
|
||||
/**
|
||||
* MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS generates standard bitwise operators
|
||||
* for the given enum type. Use this to enable using an enum type as bit-field.
|
||||
*/
|
||||
#define MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Name) \
|
||||
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, |) \
|
||||
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, &) \
|
||||
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, ^) \
|
||||
inline constexpr mozilla::CastableTypedEnumResult<Name> \
|
||||
operator~(Name a) \
|
||||
{ \
|
||||
typedef mozilla::CastableTypedEnumResult<Name> Result; \
|
||||
typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
|
||||
return Result(Name(~(U(a)))); \
|
||||
}
|
||||
|
||||
#endif // mozilla_TypedEnumBits_h
|
||||
134
cocos2d-x/external/win32/include/spidermonkey/mozilla/Types.h
vendored
Executable file
134
cocos2d-x/external/win32/include/spidermonkey/mozilla/Types.h
vendored
Executable file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* mfbt foundational types and macros. */
|
||||
|
||||
#ifndef mozilla_Types_h
|
||||
#define mozilla_Types_h
|
||||
|
||||
/*
|
||||
* This header must be valid C and C++, includable by code embedding either
|
||||
* SpiderMonkey or Gecko.
|
||||
*/
|
||||
|
||||
/* Expose all <stdint.h> types and size_t. */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Implement compiler and linker macros needed for APIs. */
|
||||
|
||||
/*
|
||||
* MOZ_EXPORT is used to declare and define a symbol or type which is externally
|
||||
* visible to users of the current library. It encapsulates various decorations
|
||||
* needed to properly export the method's symbol.
|
||||
*
|
||||
* api.h:
|
||||
* extern MOZ_EXPORT int MeaningOfLife(void);
|
||||
* extern MOZ_EXPORT int LuggageCombination;
|
||||
*
|
||||
* api.c:
|
||||
* int MeaningOfLife(void) { return 42; }
|
||||
* int LuggageCombination = 12345;
|
||||
*
|
||||
* If you are merely sharing a method across files, just use plain |extern|.
|
||||
* These macros are designed for use by library interfaces -- not for normal
|
||||
* methods or data used cross-file.
|
||||
*/
|
||||
#if defined(WIN32)
|
||||
# define MOZ_EXPORT __declspec(dllexport)
|
||||
#else /* Unix */
|
||||
# ifdef HAVE_VISIBILITY_ATTRIBUTE
|
||||
# define MOZ_EXPORT __attribute__((visibility("default")))
|
||||
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# define MOZ_EXPORT __global
|
||||
# else
|
||||
# define MOZ_EXPORT /* nothing */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Whereas implementers use MOZ_EXPORT to declare and define library symbols,
|
||||
* users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to access them. Most often the
|
||||
* implementer of the library will expose an API macro which expands to either
|
||||
* the export or import version of the macro, depending upon the compilation
|
||||
* mode.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
# if defined(__MWERKS__)
|
||||
# define MOZ_IMPORT_API /* nothing */
|
||||
# else
|
||||
# define MOZ_IMPORT_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define MOZ_IMPORT_API MOZ_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__MWERKS__)
|
||||
# define MOZ_IMPORT_DATA __declspec(dllimport)
|
||||
#else
|
||||
# define MOZ_IMPORT_DATA MOZ_EXPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Consistent with the above comment, the MFBT_API and MFBT_DATA macros expose
|
||||
* export mfbt declarations when building mfbt, and they expose import mfbt
|
||||
* declarations when using mfbt.
|
||||
*/
|
||||
#if defined(IMPL_MFBT)
|
||||
# define MFBT_API MOZ_EXPORT
|
||||
# define MFBT_DATA MOZ_EXPORT
|
||||
#else
|
||||
/*
|
||||
* On linux mozglue is linked in the program and we link libxul.so with
|
||||
* -z,defs. Normally that causes the linker to reject undefined references in
|
||||
* libxul.so, but as a loophole it allows undefined references to weak
|
||||
* symbols. We add the weak attribute to the import version of the MFBT API
|
||||
* macros to exploit this.
|
||||
*/
|
||||
# if defined(MOZ_GLUE_IN_PROGRAM)
|
||||
# define MFBT_API __attribute__((weak)) MOZ_IMPORT_API
|
||||
# define MFBT_DATA __attribute__((weak)) MOZ_IMPORT_DATA
|
||||
# else
|
||||
# define MFBT_API MOZ_IMPORT_API
|
||||
# define MFBT_DATA MOZ_IMPORT_DATA
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C symbols in C++ code must be declared immediately within |extern "C"|
|
||||
* blocks. However, in C code, they need not be declared specially. This
|
||||
* difference is abstracted behind the MOZ_BEGIN_EXTERN_C and MOZ_END_EXTERN_C
|
||||
* macros, so that the user need not know whether he is being used in C or C++
|
||||
* code.
|
||||
*
|
||||
* MOZ_BEGIN_EXTERN_C
|
||||
*
|
||||
* extern MOZ_EXPORT int MostRandomNumber(void);
|
||||
* ...other declarations...
|
||||
*
|
||||
* MOZ_END_EXTERN_C
|
||||
*
|
||||
* This said, it is preferable to just use |extern "C"| in C++ header files for
|
||||
* its greater clarity.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# define MOZ_BEGIN_EXTERN_C extern "C" {
|
||||
# define MOZ_END_EXTERN_C }
|
||||
#else
|
||||
# define MOZ_BEGIN_EXTERN_C
|
||||
# define MOZ_END_EXTERN_C
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GCC's typeof is available when decltype is not.
|
||||
*/
|
||||
#if defined(__GNUC__) && defined(__cplusplus) && \
|
||||
!defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L
|
||||
# define decltype __typeof__
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Types_h */
|
||||
697
cocos2d-x/external/win32/include/spidermonkey/mozilla/UniquePtr.h
vendored
Executable file
697
cocos2d-x/external/win32/include/spidermonkey/mozilla/UniquePtr.h
vendored
Executable file
@@ -0,0 +1,697 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Smart pointer managing sole ownership of a resource. */
|
||||
|
||||
#ifndef mozilla_UniquePtr_h
|
||||
#define mozilla_UniquePtr_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T> class DefaultDelete;
|
||||
template<typename T, class D = DefaultDelete<T>> class UniquePtr;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct HasPointerTypeHelper
|
||||
{
|
||||
template <class U> static double Test(...);
|
||||
template <class U> static char Test(typename U::pointer* = 0);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class HasPointerType : public IntegralConstant<bool, sizeof(HasPointerTypeHelper::Test<T>(0)) == 1>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T, class D, bool = HasPointerType<D>::value>
|
||||
struct PointerTypeImpl
|
||||
{
|
||||
typedef typename D::pointer Type;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
struct PointerTypeImpl<T, D, false>
|
||||
{
|
||||
typedef T* Type;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
struct PointerType
|
||||
{
|
||||
typedef typename PointerTypeImpl<T, typename RemoveReference<D>::Type>::Type Type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* UniquePtr is a smart pointer that wholly owns a resource. Ownership may be
|
||||
* transferred out of a UniquePtr through explicit action, but otherwise the
|
||||
* resource is destroyed when the UniquePtr is destroyed.
|
||||
*
|
||||
* UniquePtr is similar to C++98's std::auto_ptr, but it improves upon auto_ptr
|
||||
* in one crucial way: it's impossible to copy a UniquePtr. Copying an auto_ptr
|
||||
* obviously *can't* copy ownership of its singly-owned resource. So what
|
||||
* happens if you try to copy one? Bizarrely, ownership is implicitly
|
||||
* *transferred*, preserving single ownership but breaking code that assumes a
|
||||
* copy of an object is identical to the original. (This is why auto_ptr is
|
||||
* prohibited in STL containers.)
|
||||
*
|
||||
* UniquePtr solves this problem by being *movable* rather than copyable.
|
||||
* Instead of passing a |UniquePtr u| directly to the constructor or assignment
|
||||
* operator, you pass |Move(u)|. In doing so you indicate that you're *moving*
|
||||
* ownership out of |u|, into the target of the construction/assignment. After
|
||||
* the transfer completes, |u| contains |nullptr| and may be safely destroyed.
|
||||
* This preserves single ownership but also allows UniquePtr to be moved by
|
||||
* algorithms that have been made move-safe. (Note: if |u| is instead a
|
||||
* temporary expression, don't use |Move()|: just pass the expression, because
|
||||
* it's already move-ready. For more information see Move.h.)
|
||||
*
|
||||
* UniquePtr is also better than std::auto_ptr in that the deletion operation is
|
||||
* customizable. An optional second template parameter specifies a class that
|
||||
* (through its operator()(T*)) implements the desired deletion policy. If no
|
||||
* policy is specified, mozilla::DefaultDelete<T> is used -- which will either
|
||||
* |delete| or |delete[]| the resource, depending whether the resource is an
|
||||
* array. Custom deletion policies ideally should be empty classes (no member
|
||||
* fields, no member fields in base classes, no virtual methods/inheritance),
|
||||
* because then UniquePtr can be just as efficient as a raw pointer.
|
||||
*
|
||||
* Use of UniquePtr proceeds like so:
|
||||
*
|
||||
* UniquePtr<int> g1; // initializes to nullptr
|
||||
* g1.reset(new int); // switch resources using reset()
|
||||
* g1 = nullptr; // clears g1, deletes the int
|
||||
*
|
||||
* UniquePtr<int> g2(new int); // owns that int
|
||||
* int* p = g2.release(); // g2 leaks its int -- still requires deletion
|
||||
* delete p; // now freed
|
||||
*
|
||||
* struct S { int x; S(int x) : x(x) {} };
|
||||
* UniquePtr<S> g3, g4(new S(5));
|
||||
* g3 = Move(g4); // g3 owns the S, g4 cleared
|
||||
* S* p = g3.get(); // g3 still owns |p|
|
||||
* assert(g3->x == 5); // operator-> works (if .get() != nullptr)
|
||||
* assert((*g3).x == 5); // also operator* (again, if not cleared)
|
||||
* Swap(g3, g4); // g4 now owns the S, g3 cleared
|
||||
* g3.swap(g4); // g3 now owns the S, g4 cleared
|
||||
* UniquePtr<S> g5(Move(g3)); // g5 owns the S, g3 cleared
|
||||
* g5.reset(); // deletes the S, g5 cleared
|
||||
*
|
||||
* struct FreePolicy { void operator()(void* p) { free(p); } };
|
||||
* UniquePtr<int, FreePolicy> g6(static_cast<int*>(malloc(sizeof(int))));
|
||||
* int* ptr = g6.get();
|
||||
* g6 = nullptr; // calls free(ptr)
|
||||
*
|
||||
* Now, carefully note a few things you *can't* do:
|
||||
*
|
||||
* UniquePtr<int> b1;
|
||||
* b1 = new int; // BAD: can only assign another UniquePtr
|
||||
* int* ptr = b1; // BAD: no auto-conversion to pointer, use get()
|
||||
*
|
||||
* UniquePtr<int> b2(b1); // BAD: can't copy a UniquePtr
|
||||
* UniquePtr<int> b3 = b1; // BAD: can't copy-assign a UniquePtr
|
||||
*
|
||||
* (Note that changing a UniquePtr to store a direct |new| expression is
|
||||
* permitted, but usually you should use MakeUnique, defined at the end of this
|
||||
* header.)
|
||||
*
|
||||
* A few miscellaneous notes:
|
||||
*
|
||||
* UniquePtr, when not instantiated for an array type, can be move-constructed
|
||||
* and move-assigned, not only from itself but from "derived" UniquePtr<U, E>
|
||||
* instantiations where U converts to T and E converts to D. If you want to use
|
||||
* this, you're going to have to specify a deletion policy for both UniquePtr
|
||||
* instantations, and T pretty much has to have a virtual destructor. In other
|
||||
* words, this doesn't work:
|
||||
*
|
||||
* struct Base { virtual ~Base() {} };
|
||||
* struct Derived : Base {};
|
||||
*
|
||||
* UniquePtr<Base> b1;
|
||||
* // BAD: DefaultDelete<Base> and DefaultDelete<Derived> don't interconvert
|
||||
* UniquePtr<Derived> d1(Move(b));
|
||||
*
|
||||
* UniquePtr<Base> b2;
|
||||
* UniquePtr<Derived, DefaultDelete<Base>> d2(Move(b2)); // okay
|
||||
*
|
||||
* UniquePtr is specialized for array types. Specializing with an array type
|
||||
* creates a smart-pointer version of that array -- not a pointer to such an
|
||||
* array.
|
||||
*
|
||||
* UniquePtr<int[]> arr(new int[5]);
|
||||
* arr[0] = 4;
|
||||
*
|
||||
* What else is different? Deletion of course uses |delete[]|. An operator[]
|
||||
* is provided. Functionality that doesn't make sense for arrays is removed.
|
||||
* The constructors and mutating methods only accept array pointers (not T*, U*
|
||||
* that converts to T*, or UniquePtr<U[]> or UniquePtr<U>) or |nullptr|.
|
||||
*
|
||||
* It's perfectly okay for a function to return a UniquePtr. This transfers
|
||||
* the UniquePtr's sole ownership of the data, to the fresh UniquePtr created
|
||||
* in the calling function, that will then solely own that data. Such functions
|
||||
* can return a local variable UniquePtr, |nullptr|, |UniquePtr(ptr)| where
|
||||
* |ptr| is a |T*|, or a UniquePtr |Move()|'d from elsewhere.
|
||||
*
|
||||
* UniquePtr will commonly be a member of a class, with lifetime equivalent to
|
||||
* that of that class. If you want to expose the related resource, you could
|
||||
* expose a raw pointer via |get()|, but ownership of a raw pointer is
|
||||
* inherently unclear. So it's better to expose a |const UniquePtr&| instead.
|
||||
* This prohibits mutation but still allows use of |get()| when needed (but
|
||||
* operator-> is preferred). Of course, you can only use this smart pointer as
|
||||
* long as the enclosing class instance remains live -- no different than if you
|
||||
* exposed the |get()| raw pointer.
|
||||
*
|
||||
* To pass a UniquePtr-managed resource as a pointer, use a |const UniquePtr&|
|
||||
* argument. To specify an inout parameter (where the method may or may not
|
||||
* take ownership of the resource, or reset it), or to specify an out parameter
|
||||
* (where simply returning a |UniquePtr| isn't possible), use a |UniquePtr&|
|
||||
* argument. To unconditionally transfer ownership of a UniquePtr
|
||||
* into a method, use a |UniquePtr| argument. To conditionally transfer
|
||||
* ownership of a resource into a method, should the method want it, use a
|
||||
* |UniquePtr&&| argument.
|
||||
*/
|
||||
template<typename T, class D>
|
||||
class UniquePtr
|
||||
{
|
||||
public:
|
||||
typedef T ElementType;
|
||||
typedef D DeleterType;
|
||||
typedef typename detail::PointerType<T, DeleterType>::Type Pointer;
|
||||
|
||||
private:
|
||||
Pair<Pointer, DeleterType> mTuple;
|
||||
|
||||
Pointer& ptr() { return mTuple.first(); }
|
||||
const Pointer& ptr() const { return mTuple.first(); }
|
||||
|
||||
DeleterType& del() { return mTuple.second(); }
|
||||
const DeleterType& del() const { return mTuple.second(); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a UniquePtr containing |nullptr|.
|
||||
*/
|
||||
constexpr UniquePtr()
|
||||
: mTuple(static_cast<Pointer>(nullptr), DeleterType())
|
||||
{
|
||||
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
|
||||
static_assert(!IsReference<D>::value, "must provide a deleter instance");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a UniquePtr containing |aPtr|.
|
||||
*/
|
||||
explicit UniquePtr(Pointer aPtr)
|
||||
: mTuple(aPtr, DeleterType())
|
||||
{
|
||||
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
|
||||
static_assert(!IsReference<D>::value, "must provide a deleter instance");
|
||||
}
|
||||
|
||||
UniquePtr(Pointer aPtr,
|
||||
typename Conditional<IsReference<D>::value,
|
||||
D,
|
||||
const D&>::Type aD1)
|
||||
: mTuple(aPtr, aD1)
|
||||
{}
|
||||
|
||||
// If you encounter an error with MSVC10 about RemoveReference below, along
|
||||
// the lines that "more than one partial specialization matches the template
|
||||
// argument list": don't use UniquePtr<T, reference to function>! Ideally
|
||||
// you should make deletion use the same function every time, using a
|
||||
// deleter policy:
|
||||
//
|
||||
// // BAD, won't compile with MSVC10, deleter doesn't need to be a
|
||||
// // variable at all
|
||||
// typedef void (&FreeSignature)(void*);
|
||||
// UniquePtr<int, FreeSignature> ptr((int*) malloc(sizeof(int)), free);
|
||||
//
|
||||
// // GOOD, compiles with MSVC10, deletion behavior statically known and
|
||||
// // optimizable
|
||||
// struct DeleteByFreeing
|
||||
// {
|
||||
// void operator()(void* aPtr) { free(aPtr); }
|
||||
// };
|
||||
//
|
||||
// If deletion really, truly, must be a variable: you might be able to work
|
||||
// around this with a deleter class that contains the function reference.
|
||||
// But this workaround is untried and untested, because variable deletion
|
||||
// behavior really isn't something you should use.
|
||||
UniquePtr(Pointer aPtr,
|
||||
typename RemoveReference<D>::Type&& aD2)
|
||||
: mTuple(aPtr, Move(aD2))
|
||||
{
|
||||
static_assert(!IsReference<D>::value,
|
||||
"rvalue deleter can't be stored by reference");
|
||||
}
|
||||
|
||||
UniquePtr(UniquePtr&& aOther)
|
||||
: mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
|
||||
{}
|
||||
|
||||
MOZ_IMPLICIT
|
||||
UniquePtr(decltype(nullptr))
|
||||
: mTuple(nullptr, DeleterType())
|
||||
{
|
||||
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
|
||||
static_assert(!IsReference<D>::value, "must provide a deleter instance");
|
||||
}
|
||||
|
||||
template<typename U, class E>
|
||||
MOZ_IMPLICIT
|
||||
UniquePtr(UniquePtr<U, E>&& aOther,
|
||||
typename EnableIf<IsConvertible<typename UniquePtr<U, E>::Pointer,
|
||||
Pointer>::value &&
|
||||
!IsArray<U>::value &&
|
||||
(IsReference<D>::value
|
||||
? IsSame<D, E>::value
|
||||
: IsConvertible<E, D>::value),
|
||||
int>::Type aDummy = 0)
|
||||
: mTuple(aOther.release(), Forward<E>(aOther.get_deleter()))
|
||||
{
|
||||
}
|
||||
|
||||
~UniquePtr() { reset(nullptr); }
|
||||
|
||||
UniquePtr& operator=(UniquePtr&& aOther)
|
||||
{
|
||||
reset(aOther.release());
|
||||
get_deleter() = Forward<DeleterType>(aOther.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U, typename E>
|
||||
UniquePtr& operator=(UniquePtr<U, E>&& aOther)
|
||||
{
|
||||
static_assert(IsConvertible<typename UniquePtr<U, E>::Pointer,
|
||||
Pointer>::value,
|
||||
"incompatible UniquePtr pointees");
|
||||
static_assert(!IsArray<U>::value,
|
||||
"can't assign from UniquePtr holding an array");
|
||||
|
||||
reset(aOther.release());
|
||||
get_deleter() = Forward<E>(aOther.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr& operator=(decltype(nullptr))
|
||||
{
|
||||
reset(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator*() const { return *get(); }
|
||||
Pointer operator->() const
|
||||
{
|
||||
MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr");
|
||||
return get();
|
||||
}
|
||||
|
||||
explicit operator bool() const { return get() != nullptr; }
|
||||
|
||||
Pointer get() const { return ptr(); }
|
||||
|
||||
DeleterType& get_deleter() { return del(); }
|
||||
const DeleterType& get_deleter() const { return del(); }
|
||||
|
||||
MOZ_MUST_USE Pointer release()
|
||||
{
|
||||
Pointer p = ptr();
|
||||
ptr() = nullptr;
|
||||
return p;
|
||||
}
|
||||
|
||||
void reset(Pointer aPtr = Pointer())
|
||||
{
|
||||
Pointer old = ptr();
|
||||
ptr() = aPtr;
|
||||
if (old != nullptr) {
|
||||
get_deleter()(old);
|
||||
}
|
||||
}
|
||||
|
||||
void swap(UniquePtr& aOther)
|
||||
{
|
||||
mTuple.swap(aOther.mTuple);
|
||||
}
|
||||
|
||||
UniquePtr(const UniquePtr& aOther) = delete; // construct using Move()!
|
||||
void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
|
||||
};
|
||||
|
||||
// In case you didn't read the comment by the main definition (you should!): the
|
||||
// UniquePtr<T[]> specialization exists to manage array pointers. It deletes
|
||||
// such pointers using delete[], it will reject construction and modification
|
||||
// attempts using U* or U[]. Otherwise it works like the normal UniquePtr.
|
||||
template<typename T, class D>
|
||||
class UniquePtr<T[], D>
|
||||
{
|
||||
public:
|
||||
typedef T* Pointer;
|
||||
typedef T ElementType;
|
||||
typedef D DeleterType;
|
||||
|
||||
private:
|
||||
Pair<Pointer, DeleterType> mTuple;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a UniquePtr containing nullptr.
|
||||
*/
|
||||
constexpr UniquePtr()
|
||||
: mTuple(static_cast<Pointer>(nullptr), DeleterType())
|
||||
{
|
||||
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
|
||||
static_assert(!IsReference<D>::value, "must provide a deleter instance");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a UniquePtr containing |aPtr|.
|
||||
*/
|
||||
explicit UniquePtr(Pointer aPtr)
|
||||
: mTuple(aPtr, DeleterType())
|
||||
{
|
||||
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
|
||||
static_assert(!IsReference<D>::value, "must provide a deleter instance");
|
||||
}
|
||||
|
||||
// delete[] knows how to handle *only* an array of a single class type. For
|
||||
// delete[] to work correctly, it must know the size of each element, the
|
||||
// fields and base classes of each element requiring destruction, and so on.
|
||||
// So forbid all overloads which would end up invoking delete[] on a pointer
|
||||
// of the wrong type.
|
||||
template<typename U>
|
||||
UniquePtr(U&& aU,
|
||||
typename EnableIf<IsPointer<U>::value &&
|
||||
IsConvertible<U, Pointer>::value,
|
||||
int>::Type aDummy = 0)
|
||||
= delete;
|
||||
|
||||
UniquePtr(Pointer aPtr,
|
||||
typename Conditional<IsReference<D>::value,
|
||||
D,
|
||||
const D&>::Type aD1)
|
||||
: mTuple(aPtr, aD1)
|
||||
{}
|
||||
|
||||
// If you encounter an error with MSVC10 about RemoveReference below, along
|
||||
// the lines that "more than one partial specialization matches the template
|
||||
// argument list": don't use UniquePtr<T[], reference to function>! See the
|
||||
// comment by this constructor in the non-T[] specialization above.
|
||||
UniquePtr(Pointer aPtr,
|
||||
typename RemoveReference<D>::Type&& aD2)
|
||||
: mTuple(aPtr, Move(aD2))
|
||||
{
|
||||
static_assert(!IsReference<D>::value,
|
||||
"rvalue deleter can't be stored by reference");
|
||||
}
|
||||
|
||||
// Forbidden for the same reasons as stated above.
|
||||
template<typename U, typename V>
|
||||
UniquePtr(U&& aU, V&& aV,
|
||||
typename EnableIf<IsPointer<U>::value &&
|
||||
IsConvertible<U, Pointer>::value,
|
||||
int>::Type aDummy = 0)
|
||||
= delete;
|
||||
|
||||
UniquePtr(UniquePtr&& aOther)
|
||||
: mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
|
||||
{}
|
||||
|
||||
MOZ_IMPLICIT
|
||||
UniquePtr(decltype(nullptr))
|
||||
: mTuple(nullptr, DeleterType())
|
||||
{
|
||||
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
|
||||
static_assert(!IsReference<D>::value, "must provide a deleter instance");
|
||||
}
|
||||
|
||||
~UniquePtr() { reset(nullptr); }
|
||||
|
||||
UniquePtr& operator=(UniquePtr&& aOther)
|
||||
{
|
||||
reset(aOther.release());
|
||||
get_deleter() = Forward<DeleterType>(aOther.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr& operator=(decltype(nullptr))
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return get() != nullptr; }
|
||||
|
||||
T& operator[](decltype(sizeof(int)) aIndex) const { return get()[aIndex]; }
|
||||
Pointer get() const { return mTuple.first(); }
|
||||
|
||||
DeleterType& get_deleter() { return mTuple.second(); }
|
||||
const DeleterType& get_deleter() const { return mTuple.second(); }
|
||||
|
||||
MOZ_MUST_USE Pointer release()
|
||||
{
|
||||
Pointer p = mTuple.first();
|
||||
mTuple.first() = nullptr;
|
||||
return p;
|
||||
}
|
||||
|
||||
void reset(Pointer aPtr = Pointer())
|
||||
{
|
||||
Pointer old = mTuple.first();
|
||||
mTuple.first() = aPtr;
|
||||
if (old != nullptr) {
|
||||
mTuple.second()(old);
|
||||
}
|
||||
}
|
||||
|
||||
void reset(decltype(nullptr))
|
||||
{
|
||||
Pointer old = mTuple.first();
|
||||
mTuple.first() = nullptr;
|
||||
if (old != nullptr) {
|
||||
mTuple.second()(old);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void reset(U) = delete;
|
||||
|
||||
void swap(UniquePtr& aOther) { mTuple.swap(aOther.mTuple); }
|
||||
|
||||
UniquePtr(const UniquePtr& aOther) = delete; // construct using Move()!
|
||||
void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
|
||||
};
|
||||
|
||||
/**
|
||||
* A default deletion policy using plain old operator delete.
|
||||
*
|
||||
* Note that this type can be specialized, but authors should beware of the risk
|
||||
* that the specialization may at some point cease to match (either because it
|
||||
* gets moved to a different compilation unit or the signature changes). If the
|
||||
* non-specialized (|delete|-based) version compiles for that type but does the
|
||||
* wrong thing, bad things could happen.
|
||||
*
|
||||
* This is a non-issue for types which are always incomplete (i.e. opaque handle
|
||||
* types), since |delete|-ing such a type will always trigger a compilation
|
||||
* error.
|
||||
*/
|
||||
template<typename T>
|
||||
class DefaultDelete
|
||||
{
|
||||
public:
|
||||
constexpr DefaultDelete() {}
|
||||
|
||||
template<typename U>
|
||||
MOZ_IMPLICIT DefaultDelete(const DefaultDelete<U>& aOther,
|
||||
typename EnableIf<mozilla::IsConvertible<U*, T*>::value,
|
||||
int>::Type aDummy = 0)
|
||||
{}
|
||||
|
||||
void operator()(T* aPtr) const
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "T must be complete");
|
||||
delete aPtr;
|
||||
}
|
||||
};
|
||||
|
||||
/** A default deletion policy using operator delete[]. */
|
||||
template<typename T>
|
||||
class DefaultDelete<T[]>
|
||||
{
|
||||
public:
|
||||
constexpr DefaultDelete() {}
|
||||
|
||||
void operator()(T* aPtr) const
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "T must be complete");
|
||||
delete[] aPtr;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void operator()(U* aPtr) const = delete;
|
||||
};
|
||||
|
||||
template<typename T, class D>
|
||||
void
|
||||
Swap(UniquePtr<T, D>& aX, UniquePtr<T, D>& aY)
|
||||
{
|
||||
aX.swap(aY);
|
||||
}
|
||||
|
||||
template<typename T, class D, typename U, class E>
|
||||
bool
|
||||
operator==(const UniquePtr<T, D>& aX, const UniquePtr<U, E>& aY)
|
||||
{
|
||||
return aX.get() == aY.get();
|
||||
}
|
||||
|
||||
template<typename T, class D, typename U, class E>
|
||||
bool
|
||||
operator!=(const UniquePtr<T, D>& aX, const UniquePtr<U, E>& aY)
|
||||
{
|
||||
return aX.get() != aY.get();
|
||||
}
|
||||
|
||||
template<typename T, class D>
|
||||
bool
|
||||
operator==(const UniquePtr<T, D>& aX, decltype(nullptr))
|
||||
{
|
||||
return !aX;
|
||||
}
|
||||
|
||||
template<typename T, class D>
|
||||
bool
|
||||
operator==(decltype(nullptr), const UniquePtr<T, D>& aX)
|
||||
{
|
||||
return !aX;
|
||||
}
|
||||
|
||||
template<typename T, class D>
|
||||
bool
|
||||
operator!=(const UniquePtr<T, D>& aX, decltype(nullptr))
|
||||
{
|
||||
return bool(aX);
|
||||
}
|
||||
|
||||
template<typename T, class D>
|
||||
bool
|
||||
operator!=(decltype(nullptr), const UniquePtr<T, D>& aX)
|
||||
{
|
||||
return bool(aX);
|
||||
}
|
||||
|
||||
// No operator<, operator>, operator<=, operator>= for now because simplicity.
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct UniqueSelector
|
||||
{
|
||||
typedef UniquePtr<T> SingleObject;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct UniqueSelector<T[]>
|
||||
{
|
||||
typedef UniquePtr<T[]> UnknownBound;
|
||||
};
|
||||
|
||||
template<typename T, decltype(sizeof(int)) N>
|
||||
struct UniqueSelector<T[N]>
|
||||
{
|
||||
typedef UniquePtr<T[N]> KnownBound;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* MakeUnique is a helper function for allocating new'd objects and arrays,
|
||||
* returning a UniquePtr containing the resulting pointer. The semantics of
|
||||
* MakeUnique<Type>(...) are as follows.
|
||||
*
|
||||
* If Type is an array T[n]:
|
||||
* Disallowed, deleted, no overload for you!
|
||||
* If Type is an array T[]:
|
||||
* MakeUnique<T[]>(size_t) is the only valid overload. The pointer returned
|
||||
* is as if by |new T[n]()|, which value-initializes each element. (If T
|
||||
* isn't a class type, this will zero each element. If T is a class type,
|
||||
* then roughly speaking, each element will be constructed using its default
|
||||
* constructor. See C++11 [dcl.init]p7 for the full gory details.)
|
||||
* If Type is non-array T:
|
||||
* The arguments passed to MakeUnique<T>(...) are forwarded into a
|
||||
* |new T(...)| call, initializing the T as would happen if executing
|
||||
* |T(...)|.
|
||||
*
|
||||
* There are various benefits to using MakeUnique instead of |new| expressions.
|
||||
*
|
||||
* First, MakeUnique eliminates use of |new| from code entirely. If objects are
|
||||
* only created through UniquePtr, then (assuming all explicit release() calls
|
||||
* are safe, including transitively, and no type-safety casting funniness)
|
||||
* correctly maintained ownership of the UniquePtr guarantees no leaks are
|
||||
* possible. (This pays off best if a class is only ever created through a
|
||||
* factory method on the class, using a private constructor.)
|
||||
*
|
||||
* Second, initializing a UniquePtr using a |new| expression requires repeating
|
||||
* the name of the new'd type, whereas MakeUnique in concert with the |auto|
|
||||
* keyword names it only once:
|
||||
*
|
||||
* UniquePtr<char> ptr1(new char()); // repetitive
|
||||
* auto ptr2 = MakeUnique<char>(); // shorter
|
||||
*
|
||||
* Of course this assumes the reader understands the operation MakeUnique
|
||||
* performs. In the long run this is probably a reasonable assumption. In the
|
||||
* short run you'll have to use your judgment about what readers can be expected
|
||||
* to know, or to quickly look up.
|
||||
*
|
||||
* Third, a call to MakeUnique can be assigned directly to a UniquePtr. In
|
||||
* contrast you can't assign a pointer into a UniquePtr without using the
|
||||
* cumbersome reset().
|
||||
*
|
||||
* UniquePtr<char> p;
|
||||
* p = new char; // ERROR
|
||||
* p.reset(new char); // works, but fugly
|
||||
* p = MakeUnique<char>(); // preferred
|
||||
*
|
||||
* (And third, although not relevant to Mozilla: MakeUnique is exception-safe.
|
||||
* An exception thrown after |new T| succeeds will leak that memory, unless the
|
||||
* pointer is assigned to an object that will manage its ownership. UniquePtr
|
||||
* ably serves this function.)
|
||||
*/
|
||||
|
||||
template<typename T, typename... Args>
|
||||
typename detail::UniqueSelector<T>::SingleObject
|
||||
MakeUnique(Args&&... aArgs)
|
||||
{
|
||||
return UniquePtr<T>(new T(Forward<Args>(aArgs)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename detail::UniqueSelector<T>::UnknownBound
|
||||
MakeUnique(decltype(sizeof(int)) aN)
|
||||
{
|
||||
typedef typename RemoveExtent<T>::Type ArrayType;
|
||||
return UniquePtr<T>(new ArrayType[aN]());
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
typename detail::UniqueSelector<T>::KnownBound
|
||||
MakeUnique(Args&&... aArgs) = delete;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_UniquePtr_h */
|
||||
57
cocos2d-x/external/win32/include/spidermonkey/mozilla/UniquePtrExtensions.h
vendored
Executable file
57
cocos2d-x/external/win32/include/spidermonkey/mozilla/UniquePtrExtensions.h
vendored
Executable file
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Useful extensions to UniquePtr. */
|
||||
|
||||
#ifndef mozilla_UniquePtrExtensions_h
|
||||
#define mozilla_UniquePtrExtensions_h
|
||||
|
||||
#include "mozilla/fallible.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* MakeUniqueFallible works exactly like MakeUnique, except that the memory
|
||||
* allocation performed is done fallibly, i.e. it can return nullptr.
|
||||
*/
|
||||
template<typename T, typename... Args>
|
||||
typename detail::UniqueSelector<T>::SingleObject
|
||||
MakeUniqueFallible(Args&&... aArgs)
|
||||
{
|
||||
return UniquePtr<T>(new (fallible) T(Forward<Args>(aArgs)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename detail::UniqueSelector<T>::UnknownBound
|
||||
MakeUniqueFallible(decltype(sizeof(int)) aN)
|
||||
{
|
||||
typedef typename RemoveExtent<T>::Type ArrayType;
|
||||
return UniquePtr<T>(new (fallible) ArrayType[aN]());
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
typename detail::UniqueSelector<T>::KnownBound
|
||||
MakeUniqueFallible(Args&&... aArgs) = delete;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct FreePolicy
|
||||
{
|
||||
void operator()(const void* ptr) {
|
||||
free(const_cast<void*>(ptr));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
using UniqueFreePtr = UniquePtr<T, detail::FreePolicy<T>>;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_UniquePtrExtensions_h
|
||||
38
cocos2d-x/external/win32/include/spidermonkey/mozilla/Unused.h
vendored
Executable file
38
cocos2d-x/external/win32/include/spidermonkey/mozilla/Unused.h
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_unused_h
|
||||
#define mozilla_unused_h
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
//
|
||||
// Suppress GCC warnings about unused return values with
|
||||
// Unused << SomeFuncDeclaredWarnUnusedReturnValue();
|
||||
//
|
||||
struct unused_t
|
||||
{
|
||||
template<typename T>
|
||||
inline void
|
||||
operator<<(const T& /*unused*/) const {}
|
||||
};
|
||||
|
||||
extern MFBT_DATA const unused_t Unused;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
// An alternative to mozilla::Unused for use in (a) C code and (b) code where
|
||||
// linking with unused.o is difficult.
|
||||
#define MOZ_UNUSED(expr) \
|
||||
do { if (expr) { (void)0; } } while (0)
|
||||
|
||||
#endif // mozilla_unused_h
|
||||
625
cocos2d-x/external/win32/include/spidermonkey/mozilla/Variant.h
vendored
Executable file
625
cocos2d-x/external/win32/include/spidermonkey/mozilla/Variant.h
vendored
Executable file
@@ -0,0 +1,625 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A template class for tagged unions. */
|
||||
|
||||
#include <new>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#ifndef mozilla_Variant_h
|
||||
#define mozilla_Variant_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename... Ts>
|
||||
class Variant;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// MaxSizeOf computes the maximum sizeof(T) for each T in Ts.
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct MaxSizeOf
|
||||
{
|
||||
static const size_t size = sizeof(T) > MaxSizeOf<Ts...>::size
|
||||
? sizeof(T)
|
||||
: MaxSizeOf<Ts...>::size;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MaxSizeOf<T>
|
||||
{
|
||||
static const size_t size = sizeof(T);
|
||||
};
|
||||
|
||||
// The `IsVariant` helper is used in conjunction with static_assert and
|
||||
// `mozilla::EnableIf` to catch passing non-variant types to `Variant::is<T>()`
|
||||
// and friends at compile time, rather than at runtime. It ensures that the
|
||||
// given type `Needle` is one of the types in the set of types `Haystack`.
|
||||
|
||||
template<typename Needle, typename... Haystack>
|
||||
struct IsVariant;
|
||||
|
||||
template<typename Needle>
|
||||
struct IsVariant<Needle>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename Needle, typename... Haystack>
|
||||
struct IsVariant<Needle, Needle, Haystack...>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename Needle, typename T, typename... Haystack>
|
||||
struct IsVariant<Needle, T, Haystack...> : public IsVariant<Needle, Haystack...> { };
|
||||
|
||||
/// SelectVariantTypeHelper is used in the implementation of SelectVariantType.
|
||||
template<typename T, typename... Variants>
|
||||
struct SelectVariantTypeHelper;
|
||||
|
||||
template<typename T>
|
||||
struct SelectVariantTypeHelper<T>
|
||||
{ };
|
||||
|
||||
template<typename T, typename... Variants>
|
||||
struct SelectVariantTypeHelper<T, T, Variants...>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template<typename T, typename... Variants>
|
||||
struct SelectVariantTypeHelper<T, const T, Variants...>
|
||||
{
|
||||
typedef const T Type;
|
||||
};
|
||||
|
||||
template<typename T, typename... Variants>
|
||||
struct SelectVariantTypeHelper<T, const T&, Variants...>
|
||||
{
|
||||
typedef const T& Type;
|
||||
};
|
||||
|
||||
template<typename T, typename... Variants>
|
||||
struct SelectVariantTypeHelper<T, T&&, Variants...>
|
||||
{
|
||||
typedef T&& Type;
|
||||
};
|
||||
|
||||
template<typename T, typename Head, typename... Variants>
|
||||
struct SelectVariantTypeHelper<T, Head, Variants...>
|
||||
: public SelectVariantTypeHelper<T, Variants...>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* SelectVariantType takes a type T and a list of variant types Variants and
|
||||
* yields a type Type, selected from Variants, that can store a value of type T
|
||||
* or a reference to type T. If no such type was found, Type is not defined.
|
||||
*/
|
||||
template <typename T, typename... Variants>
|
||||
struct SelectVariantType
|
||||
: public SelectVariantTypeHelper<typename RemoveConst<typename RemoveReference<T>::Type>::Type,
|
||||
Variants...>
|
||||
{ };
|
||||
|
||||
// Compute a fast, compact type that can be used to hold integral values that
|
||||
// distinctly map to every type in Ts.
|
||||
template<typename... Ts>
|
||||
struct VariantTag
|
||||
{
|
||||
private:
|
||||
static const size_t TypeCount = sizeof...(Ts);
|
||||
|
||||
public:
|
||||
using Type =
|
||||
typename Conditional<TypeCount < 3,
|
||||
bool,
|
||||
typename Conditional<TypeCount < (1 << 8),
|
||||
uint_fast8_t,
|
||||
size_t // stop caring past a certain point :-)
|
||||
>::Type
|
||||
>::Type;
|
||||
};
|
||||
|
||||
// TagHelper gets the given sentinel tag value for the given type T. This has to
|
||||
// be split out from VariantImplementation because you can't nest a partial
|
||||
// template specialization within a template class.
|
||||
|
||||
template<typename Tag, size_t N, typename T, typename U, typename Next, bool isMatch>
|
||||
struct TagHelper;
|
||||
|
||||
// In the case where T != U, we continue recursion.
|
||||
template<typename Tag, size_t N, typename T, typename U, typename Next>
|
||||
struct TagHelper<Tag, N, T, U, Next, false>
|
||||
{
|
||||
static Tag tag() { return Next::template tag<U>(); }
|
||||
};
|
||||
|
||||
// In the case where T == U, return the tag number.
|
||||
template<typename Tag, size_t N, typename T, typename U, typename Next>
|
||||
struct TagHelper<Tag, N, T, U, Next, true>
|
||||
{
|
||||
static Tag tag() { return Tag(N); }
|
||||
};
|
||||
|
||||
// The VariantImplementation template provides the guts of mozilla::Variant. We
|
||||
// create a VariantImplementation for each T in Ts... which handles
|
||||
// construction, destruction, etc for when the Variant's type is T. If the
|
||||
// Variant's type isn't T, it punts the request on to the next
|
||||
// VariantImplementation.
|
||||
|
||||
template<typename Tag, size_t N, typename... Ts>
|
||||
struct VariantImplementation;
|
||||
|
||||
// The singly typed Variant / recursion base case.
|
||||
template<typename Tag, size_t N, typename T>
|
||||
struct VariantImplementation<Tag, N, T>
|
||||
{
|
||||
template<typename U>
|
||||
static Tag tag() {
|
||||
static_assert(mozilla::IsSame<T, U>::value,
|
||||
"mozilla::Variant: tag: bad type!");
|
||||
return Tag(N);
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static void copyConstruct(void* aLhs, const Variant& aRhs) {
|
||||
new (aLhs) T(aRhs.template as<T>());
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static void moveConstruct(void* aLhs, Variant&& aRhs) {
|
||||
new (aLhs) T(aRhs.template extract<T>());
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static void destroy(Variant& aV) {
|
||||
aV.template as<T>().~T();
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static bool
|
||||
equal(const Variant& aLhs, const Variant& aRhs) {
|
||||
return aLhs.template as<T>() == aRhs.template as<T>();
|
||||
}
|
||||
|
||||
template<typename Matcher, typename ConcreteVariant>
|
||||
static auto
|
||||
match(Matcher&& aMatcher, ConcreteVariant& aV)
|
||||
-> decltype(aMatcher.match(aV.template as<T>()))
|
||||
{
|
||||
return aMatcher.match(aV.template as<T>());
|
||||
}
|
||||
};
|
||||
|
||||
// VariantImplementation for some variant type T.
|
||||
template<typename Tag, size_t N, typename T, typename... Ts>
|
||||
struct VariantImplementation<Tag, N, T, Ts...>
|
||||
{
|
||||
// The next recursive VariantImplementation.
|
||||
using Next = VariantImplementation<Tag, N + 1, Ts...>;
|
||||
|
||||
template<typename U>
|
||||
static Tag tag() {
|
||||
return TagHelper<Tag, N, T, U, Next, IsSame<T, U>::value>::tag();
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static void copyConstruct(void* aLhs, const Variant& aRhs) {
|
||||
if (aRhs.template is<T>()) {
|
||||
new (aLhs) T(aRhs.template as<T>());
|
||||
} else {
|
||||
Next::copyConstruct(aLhs, aRhs);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static void moveConstruct(void* aLhs, Variant&& aRhs) {
|
||||
if (aRhs.template is<T>()) {
|
||||
new (aLhs) T(aRhs.template extract<T>());
|
||||
} else {
|
||||
Next::moveConstruct(aLhs, aRhs);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static void destroy(Variant& aV) {
|
||||
if (aV.template is<T>()) {
|
||||
aV.template as<T>().~T();
|
||||
} else {
|
||||
Next::destroy(aV);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Variant>
|
||||
static bool equal(const Variant& aLhs, const Variant& aRhs) {
|
||||
if (aLhs.template is<T>()) {
|
||||
MOZ_ASSERT(aRhs.template is<T>());
|
||||
return aLhs.template as<T>() == aRhs.template as<T>();
|
||||
} else {
|
||||
return Next::equal(aLhs, aRhs);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Matcher, typename ConcreteVariant>
|
||||
static auto
|
||||
match(Matcher&& aMatcher, ConcreteVariant& aV)
|
||||
-> decltype(aMatcher.match(aV.template as<T>()))
|
||||
{
|
||||
if (aV.template is<T>()) {
|
||||
return aMatcher.match(aV.template as<T>());
|
||||
} else {
|
||||
// If you're seeing compilation errors here like "no matching
|
||||
// function for call to 'match'" then that means that the
|
||||
// Matcher doesn't exhaust all variant types. There must exist a
|
||||
// Matcher::match(T&) for every variant type T.
|
||||
//
|
||||
// If you're seeing compilation errors here like "cannot
|
||||
// initialize return object of type <...> with an rvalue of type
|
||||
// <...>" then that means that the Matcher::match(T&) overloads
|
||||
// are returning different types. They must all return the same
|
||||
// Matcher::ReturnType type.
|
||||
return Next::match(aMatcher, aV);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* AsVariantTemporary stores a value of type T to allow construction of a
|
||||
* Variant value via type inference. Because T is copied and there's no
|
||||
* guarantee that the copy can be elided, AsVariantTemporary is best used with
|
||||
* primitive or very small types.
|
||||
*/
|
||||
template <typename T>
|
||||
struct AsVariantTemporary
|
||||
{
|
||||
explicit AsVariantTemporary(const T& aValue)
|
||||
: mValue(aValue)
|
||||
{}
|
||||
|
||||
template<typename U>
|
||||
explicit AsVariantTemporary(U&& aValue)
|
||||
: mValue(Forward<U>(aValue))
|
||||
{}
|
||||
|
||||
AsVariantTemporary(const AsVariantTemporary& aOther)
|
||||
: mValue(aOther.mValue)
|
||||
{}
|
||||
|
||||
AsVariantTemporary(AsVariantTemporary&& aOther)
|
||||
: mValue(Move(aOther.mValue))
|
||||
{}
|
||||
|
||||
AsVariantTemporary() = delete;
|
||||
void operator=(const AsVariantTemporary&) = delete;
|
||||
void operator=(AsVariantTemporary&&) = delete;
|
||||
|
||||
typename RemoveConst<typename RemoveReference<T>::Type>::Type mValue;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* # mozilla::Variant
|
||||
*
|
||||
* A variant / tagged union / heterogenous disjoint union / sum-type template
|
||||
* class. Similar in concept to (but not derived from) `boost::variant`.
|
||||
*
|
||||
* Sometimes, you may wish to use a C union with non-POD types. However, this is
|
||||
* forbidden in C++ because it is not clear which type in the union should have
|
||||
* its constructor and destructor run on creation and deletion
|
||||
* respectively. This is the problem that `mozilla::Variant` solves.
|
||||
*
|
||||
* ## Usage
|
||||
*
|
||||
* A `mozilla::Variant` instance is constructed (via move or copy) from one of
|
||||
* its variant types (ignoring const and references). It does *not* support
|
||||
* construction from subclasses of variant types or types that coerce to one of
|
||||
* the variant types.
|
||||
*
|
||||
* Variant<char, uint32_t> v1('a');
|
||||
* Variant<UniquePtr<A>, B, C> v2(MakeUnique<A>());
|
||||
*
|
||||
* Because specifying the full type of a Variant value is often verbose,
|
||||
* AsVariant() can be used to construct a Variant value using type inference in
|
||||
* contexts such as expressions or when returning values from functions. Because
|
||||
* AsVariant() must copy or move the value into a temporary and this cannot
|
||||
* necessarily be elided by the compiler, it's mostly appropriate only for use
|
||||
* with primitive or very small types.
|
||||
*
|
||||
*
|
||||
* Variant<char, uint32_t> Foo() { return AsVariant('x'); }
|
||||
* // ...
|
||||
* Variant<char, uint32_t> v1 = Foo(); // v1 holds char('x').
|
||||
*
|
||||
* All access to the contained value goes through type-safe accessors.
|
||||
*
|
||||
* void
|
||||
* Foo(Variant<A, B, C> v)
|
||||
* {
|
||||
* if (v.is<A>()) {
|
||||
* A& ref = v.as<A>();
|
||||
* ...
|
||||
* } else {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Attempting to use the contained value as type `T1` when the `Variant`
|
||||
* instance contains a value of type `T2` causes an assertion failure.
|
||||
*
|
||||
* A a;
|
||||
* Variant<A, B, C> v(a);
|
||||
* v.as<B>(); // <--- Assertion failure!
|
||||
*
|
||||
* Trying to use a `Variant<Ts...>` instance as some type `U` that is not a
|
||||
* member of the set of `Ts...` is a compiler error.
|
||||
*
|
||||
* A a;
|
||||
* Variant<A, B, C> v(a);
|
||||
* v.as<SomeRandomType>(); // <--- Compiler error!
|
||||
*
|
||||
* Additionally, you can turn a `Variant` that `is<T>` into a `T` by moving it
|
||||
* out of the containing `Variant` instance with the `extract<T>` method:
|
||||
*
|
||||
* Variant<UniquePtr<A>, B, C> v(MakeUnique<A>());
|
||||
* auto ptr = v.extract<UniquePtr<A>>();
|
||||
*
|
||||
* Finally, you can exhaustively match on the contained variant and branch into
|
||||
* different code paths depending which type is contained. This is preferred to
|
||||
* manually checking every variant type T with is<T>() because it provides
|
||||
* compile-time checking that you handled every type, rather than runtime
|
||||
* assertion failures.
|
||||
*
|
||||
* // Bad!
|
||||
* char* foo(Variant<A, B, C, D>& v) {
|
||||
* if (v.is<A>()) {
|
||||
* return ...;
|
||||
* } else if (v.is<B>()) {
|
||||
* return ...;
|
||||
* } else {
|
||||
* return doSomething(v.as<C>()); // Forgot about case D!
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Good!
|
||||
* struct FooMatcher
|
||||
* {
|
||||
* // The return type of all matchers must be identical.
|
||||
* char* match(A& a) { ... }
|
||||
* char* match(B& b) { ... }
|
||||
* char* match(C& c) { ... }
|
||||
* char* match(D& d) { ... } // Compile-time error to forget D!
|
||||
* }
|
||||
* char* foo(Variant<A, B, C, D>& v) {
|
||||
* return v.match(FooMatcher());
|
||||
* }
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* A tree is either an empty leaf, or a node with a value and two children:
|
||||
*
|
||||
* struct Leaf { };
|
||||
*
|
||||
* template<typename T>
|
||||
* struct Node
|
||||
* {
|
||||
* T value;
|
||||
* Tree<T>* left;
|
||||
* Tree<T>* right;
|
||||
* };
|
||||
*
|
||||
* template<typename T>
|
||||
* using Tree = Variant<Leaf, Node<T>>;
|
||||
*
|
||||
* A copy-on-write string is either a non-owning reference to some existing
|
||||
* string, or an owning reference to our copy:
|
||||
*
|
||||
* class CopyOnWriteString
|
||||
* {
|
||||
* Variant<const char*, UniquePtr<char[]>> string;
|
||||
*
|
||||
* ...
|
||||
* };
|
||||
*/
|
||||
template<typename... Ts>
|
||||
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Variant
|
||||
{
|
||||
using Tag = typename detail::VariantTag<Ts...>::Type;
|
||||
using Impl = detail::VariantImplementation<Tag, 0, Ts...>;
|
||||
using RawData = AlignedStorage<detail::MaxSizeOf<Ts...>::size>;
|
||||
|
||||
// Raw storage for the contained variant value.
|
||||
RawData raw;
|
||||
|
||||
// Each type is given a unique tag value that lets us keep track of the
|
||||
// contained variant value's type.
|
||||
Tag tag;
|
||||
|
||||
void* ptr() {
|
||||
return reinterpret_cast<void*>(&raw);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Perfect forwarding construction for some variant type T. */
|
||||
template<typename RefT,
|
||||
// RefT captures both const& as well as && (as intended, to support
|
||||
// perfect forwarding), so we have to remove those qualifiers here
|
||||
// when ensuring that T is a variant of this type, and getting T's
|
||||
// tag, etc.
|
||||
typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
|
||||
explicit Variant(RefT&& aT)
|
||||
: tag(Impl::template tag<T>())
|
||||
{
|
||||
new (ptr()) T(Forward<RefT>(aT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs this Variant from an AsVariantTemporary<T> such that T can be
|
||||
* stored in one of the types allowable in this Variant. This is used in the
|
||||
* implementation of AsVariant().
|
||||
*/
|
||||
template<typename RefT,
|
||||
typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
|
||||
MOZ_IMPLICIT Variant(detail::AsVariantTemporary<RefT>&& aValue)
|
||||
: tag(Impl::template tag<T>())
|
||||
{
|
||||
new (ptr()) T(Move(aValue.mValue));
|
||||
}
|
||||
|
||||
/** Copy construction. */
|
||||
Variant(const Variant& aRhs)
|
||||
: tag(aRhs.tag)
|
||||
{
|
||||
Impl::copyConstruct(ptr(), aRhs);
|
||||
}
|
||||
|
||||
/** Move construction. */
|
||||
Variant(Variant&& aRhs)
|
||||
: tag(aRhs.tag)
|
||||
{
|
||||
Impl::moveConstruct(ptr(), Move(aRhs));
|
||||
}
|
||||
|
||||
/** Copy assignment. */
|
||||
Variant& operator=(const Variant& aRhs) {
|
||||
MOZ_ASSERT(&aRhs != this, "self-assign disallowed");
|
||||
this->~Variant();
|
||||
new (this) Variant(aRhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Move assignment. */
|
||||
Variant& operator=(Variant&& aRhs) {
|
||||
MOZ_ASSERT(&aRhs != this, "self-assign disallowed");
|
||||
this->~Variant();
|
||||
new (this) Variant(Move(aRhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Move assignment from AsVariant(). */
|
||||
template <typename T>
|
||||
Variant& operator=(detail::AsVariantTemporary<T>&& aValue)
|
||||
{
|
||||
this->~Variant();
|
||||
new (this) Variant(Move(aValue));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Variant()
|
||||
{
|
||||
Impl::destroy(*this);
|
||||
}
|
||||
|
||||
/** Check which variant type is currently contained. */
|
||||
template<typename T>
|
||||
bool is() const {
|
||||
static_assert(detail::IsVariant<T, Ts...>::value,
|
||||
"provided a type not found in this Variant's type list");
|
||||
return Impl::template tag<T>() == tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator == overload that defers to the variant type's operator==
|
||||
* implementation if the rhs is tagged as the same type as this one.
|
||||
*/
|
||||
bool operator==(const Variant& aRhs) const {
|
||||
return tag == aRhs.tag && Impl::equal(*this, aRhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator != overload that defers to the negation of the variant type's
|
||||
* operator== implementation if the rhs is tagged as the same type as this
|
||||
* one.
|
||||
*/
|
||||
bool operator!=(const Variant& aRhs) const {
|
||||
return !(*this == aRhs);
|
||||
}
|
||||
|
||||
// Accessors for working with the contained variant value.
|
||||
|
||||
/** Mutable reference. */
|
||||
template<typename T>
|
||||
T& as() {
|
||||
static_assert(detail::IsVariant<T, Ts...>::value,
|
||||
"provided a type not found in this Variant's type list");
|
||||
MOZ_ASSERT(is<T>());
|
||||
return *reinterpret_cast<T*>(&raw);
|
||||
}
|
||||
|
||||
/** Immutable const reference. */
|
||||
template<typename T>
|
||||
const T& as() const {
|
||||
static_assert(detail::IsVariant<T, Ts...>::value,
|
||||
"provided a type not found in this Variant's type list");
|
||||
MOZ_ASSERT(is<T>());
|
||||
return *reinterpret_cast<const T*>(&raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the contained variant value from this container into a temporary
|
||||
* value. On completion, the value in the variant will be in a
|
||||
* safely-destructible state, as determined by the behavior of T's move
|
||||
* constructor when provided the variant's internal value.
|
||||
*/
|
||||
template<typename T>
|
||||
T extract() {
|
||||
static_assert(detail::IsVariant<T, Ts...>::value,
|
||||
"provided a type not found in this Variant's type list");
|
||||
MOZ_ASSERT(is<T>());
|
||||
return T(Move(as<T>()));
|
||||
}
|
||||
|
||||
// Exhaustive matching of all variant types on the contained value.
|
||||
|
||||
/** Match on an immutable const reference. */
|
||||
template<typename Matcher>
|
||||
auto
|
||||
match(Matcher&& aMatcher) const
|
||||
-> decltype(Impl::match(aMatcher, *this))
|
||||
{
|
||||
return Impl::match(aMatcher, *this);
|
||||
}
|
||||
|
||||
/** Match on a mutable non-const reference. */
|
||||
template<typename Matcher>
|
||||
auto
|
||||
match(Matcher&& aMatcher)
|
||||
-> decltype(Impl::match(aMatcher, *this))
|
||||
{
|
||||
return Impl::match(aMatcher, *this);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* AsVariant() is used to construct a Variant<T,...> value containing the
|
||||
* provided T value using type inference. It can be used to construct Variant
|
||||
* values in expressions or return them from functions without specifying the
|
||||
* entire Variant type.
|
||||
*
|
||||
* Because AsVariant() must copy or move the value into a temporary and this
|
||||
* cannot necessarily be elided by the compiler, it's mostly appropriate only
|
||||
* for use with primitive or very small types.
|
||||
*
|
||||
* AsVariant() returns a AsVariantTemporary value which is implicitly
|
||||
* convertible to any Variant that can hold a value of type T.
|
||||
*/
|
||||
template<typename T>
|
||||
detail::AsVariantTemporary<T>
|
||||
AsVariant(T&& aValue)
|
||||
{
|
||||
return detail::AsVariantTemporary<T>(Forward<T>(aValue));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_Variant_h */
|
||||
1491
cocos2d-x/external/win32/include/spidermonkey/mozilla/Vector.h
vendored
Executable file
1491
cocos2d-x/external/win32/include/spidermonkey/mozilla/Vector.h
vendored
Executable file
File diff suppressed because it is too large
Load Diff
283
cocos2d-x/external/win32/include/spidermonkey/mozilla/WeakPtr.h
vendored
Executable file
283
cocos2d-x/external/win32/include/spidermonkey/mozilla/WeakPtr.h
vendored
Executable file
@@ -0,0 +1,283 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Weak pointer functionality, implemented as a mixin for use with any class. */
|
||||
|
||||
/**
|
||||
* SupportsWeakPtr lets you have a pointer to an object 'Foo' without affecting
|
||||
* its lifetime. It works by creating a single shared reference counted object
|
||||
* (WeakReference) that each WeakPtr will access 'Foo' through. This lets 'Foo'
|
||||
* clear the pointer in the WeakReference without having to know about all of
|
||||
* the WeakPtrs to it and allows the WeakReference to live beyond the lifetime
|
||||
* of 'Foo'.
|
||||
*
|
||||
* PLEASE NOTE: This weak pointer implementation is not thread-safe.
|
||||
*
|
||||
* Note that when deriving from SupportsWeakPtr you should add
|
||||
* MOZ_DECLARE_WEAKREFERENCE_TYPENAME(ClassName) to the public section of your
|
||||
* class, where ClassName is the name of your class.
|
||||
*
|
||||
* The overhead of WeakPtr is that accesses to 'Foo' becomes an additional
|
||||
* dereference, and an additional heap allocated pointer sized object shared
|
||||
* between all of the WeakPtrs.
|
||||
*
|
||||
* Example of usage:
|
||||
*
|
||||
* // To have a class C support weak pointers, inherit from
|
||||
* // SupportsWeakPtr<C>.
|
||||
* class C : public SupportsWeakPtr<C>
|
||||
* {
|
||||
* public:
|
||||
* MOZ_DECLARE_WEAKREFERENCE_TYPENAME(C)
|
||||
* int mNum;
|
||||
* void act();
|
||||
* };
|
||||
*
|
||||
* C* ptr = new C();
|
||||
*
|
||||
* // Get weak pointers to ptr. The first time a weak pointer
|
||||
* // is obtained, a reference counted WeakReference object is created that
|
||||
* // can live beyond the lifetime of 'ptr'. The WeakReference
|
||||
* // object will be notified of 'ptr's destruction.
|
||||
* WeakPtr<C> weak = ptr;
|
||||
* WeakPtr<C> other = ptr;
|
||||
*
|
||||
* // Test a weak pointer for validity before using it.
|
||||
* if (weak) {
|
||||
* weak->mNum = 17;
|
||||
* weak->act();
|
||||
* }
|
||||
*
|
||||
* // Destroying the underlying object clears weak pointers to it.
|
||||
* delete ptr;
|
||||
*
|
||||
* MOZ_ASSERT(!weak, "Deleting |ptr| clears weak pointers to it.");
|
||||
* MOZ_ASSERT(!other, "Deleting |ptr| clears all weak pointers to it.");
|
||||
*
|
||||
* WeakPtr is typesafe and may be used with any class. It is not required that
|
||||
* the class be reference-counted or allocated in any particular way.
|
||||
*
|
||||
* The API was loosely inspired by Chromium's weak_ptr.h:
|
||||
* http://src.chromium.org/svn/trunk/src/base/memory/weak_ptr.h
|
||||
*/
|
||||
|
||||
#ifndef mozilla_WeakPtr_h
|
||||
#define mozilla_WeakPtr_h
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Weak referencing is not implemeted as thread safe. When a WeakPtr
|
||||
// is created or dereferenced on thread A but the real object is just
|
||||
// being Released() on thread B, there is a possibility of a race
|
||||
// when the proxy object (detail::WeakReference) is notified about
|
||||
// the real object destruction just between when thread A is storing
|
||||
// the object pointer locally and is about to add a reference to it.
|
||||
//
|
||||
// Hence, a non-null weak proxy object is considered to have a single
|
||||
// "owning thread". It means that each query for a weak reference,
|
||||
// its dereference, and destruction of the real object must all happen
|
||||
// on a single thread. The following macros implement assertions for
|
||||
// checking these conditions.
|
||||
//
|
||||
// We disable this on MinGW. MinGW has two threading models: win32
|
||||
// API based, which disables std::thread; and POSIX based which
|
||||
// enables it but requires an emulation library (winpthreads).
|
||||
// Rather than attempting to switch to pthread emulation at this point,
|
||||
// we are disabling the std::thread based assertion checking.
|
||||
//
|
||||
// In the future, to enable it we could
|
||||
// a. have libgcc/stdc++ support win32 threads natively
|
||||
// b. switch to POSIX-based threading in MinGW with pthread emulation
|
||||
// c. refactor it to not use std::thread
|
||||
|
||||
#if !defined(__MINGW32__) && (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING)))
|
||||
|
||||
#include <thread>
|
||||
#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK \
|
||||
std::thread::id _owningThread; \
|
||||
bool _empty; // If it was initialized as a placeholder with mPtr = nullptr.
|
||||
#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() \
|
||||
do { \
|
||||
_owningThread = std::this_thread::get_id(); \
|
||||
_empty = !p; \
|
||||
} while (false)
|
||||
#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() \
|
||||
MOZ_DIAGNOSTIC_ASSERT(_empty || _owningThread == std::this_thread::get_id(), \
|
||||
"WeakPtr used on multiple threads")
|
||||
#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(that) \
|
||||
(that)->AssertThreadSafety();
|
||||
|
||||
#define MOZ_WEAKPTR_THREAD_SAFETY_CHECKING 1
|
||||
|
||||
#else
|
||||
|
||||
#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK
|
||||
#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() do { } while (false)
|
||||
#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() do { } while (false)
|
||||
#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(that) do { } while (false)
|
||||
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename T> class WeakPtr;
|
||||
template <typename T> class SupportsWeakPtr;
|
||||
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
#define MOZ_DECLARE_WEAKREFERENCE_TYPENAME(T) \
|
||||
static const char* weakReferenceTypeName() { return "WeakReference<" #T ">"; }
|
||||
#else
|
||||
#define MOZ_DECLARE_WEAKREFERENCE_TYPENAME(T)
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This can live beyond the lifetime of the class derived from
|
||||
// SupportsWeakPtr.
|
||||
template<class T>
|
||||
class WeakReference : public ::mozilla::RefCounted<WeakReference<T> >
|
||||
{
|
||||
public:
|
||||
explicit WeakReference(T* p) : mPtr(p)
|
||||
{
|
||||
MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK();
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
MOZ_WEAKPTR_ASSERT_THREAD_SAFETY();
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
const char* typeName() const
|
||||
{
|
||||
// The first time this is called mPtr is null, so don't
|
||||
// invoke any methods on mPtr.
|
||||
return T::weakReferenceTypeName();
|
||||
}
|
||||
size_t typeSize() const { return sizeof(*this); }
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEAKPTR_THREAD_SAFETY_CHECKING
|
||||
void AssertThreadSafety() { MOZ_WEAKPTR_ASSERT_THREAD_SAFETY(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class mozilla::SupportsWeakPtr<T>;
|
||||
|
||||
void detach() {
|
||||
MOZ_WEAKPTR_ASSERT_THREAD_SAFETY();
|
||||
mPtr = nullptr;
|
||||
}
|
||||
|
||||
T* MOZ_NON_OWNING_REF mPtr;
|
||||
MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class SupportsWeakPtr
|
||||
{
|
||||
protected:
|
||||
~SupportsWeakPtr()
|
||||
{
|
||||
static_assert(IsBaseOf<SupportsWeakPtr<T>, T>::value,
|
||||
"T must derive from SupportsWeakPtr<T>");
|
||||
if (mSelfReferencingWeakPtr) {
|
||||
mSelfReferencingWeakPtr.mRef->detach();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const WeakPtr<T>& SelfReferencingWeakPtr()
|
||||
{
|
||||
if (!mSelfReferencingWeakPtr) {
|
||||
mSelfReferencingWeakPtr.mRef = new detail::WeakReference<T>(static_cast<T*>(this));
|
||||
} else {
|
||||
MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mSelfReferencingWeakPtr.mRef);
|
||||
}
|
||||
return mSelfReferencingWeakPtr;
|
||||
}
|
||||
|
||||
const WeakPtr<const T>& SelfReferencingWeakPtr() const
|
||||
{
|
||||
const WeakPtr<T>& p = const_cast<SupportsWeakPtr*>(this)->SelfReferencingWeakPtr();
|
||||
return reinterpret_cast<const WeakPtr<const T>&>(p);
|
||||
}
|
||||
|
||||
friend class WeakPtr<T>;
|
||||
friend class WeakPtr<const T>;
|
||||
|
||||
WeakPtr<T> mSelfReferencingWeakPtr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class WeakPtr
|
||||
{
|
||||
typedef detail::WeakReference<T> WeakReference;
|
||||
|
||||
public:
|
||||
WeakPtr& operator=(const WeakPtr& aOther)
|
||||
{
|
||||
mRef = aOther.mRef;
|
||||
MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mRef);
|
||||
return *this;
|
||||
}
|
||||
|
||||
WeakPtr(const WeakPtr& aOther)
|
||||
{
|
||||
// The thread safety check is performed inside of the operator= method.
|
||||
*this = aOther;
|
||||
}
|
||||
|
||||
WeakPtr& operator=(T* aOther)
|
||||
{
|
||||
if (aOther) {
|
||||
*this = aOther->SelfReferencingWeakPtr();
|
||||
} else if (!mRef || mRef->get()) {
|
||||
// Ensure that mRef is dereferenceable in the uninitialized state.
|
||||
mRef = new WeakReference(nullptr);
|
||||
}
|
||||
// The thread safety check happens inside SelfReferencingWeakPtr
|
||||
// or is initialized in the WeakReference constructor.
|
||||
return *this;
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT WeakPtr(T* aOther)
|
||||
{
|
||||
*this = aOther;
|
||||
MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mRef);
|
||||
}
|
||||
|
||||
// Ensure that mRef is dereferenceable in the uninitialized state.
|
||||
WeakPtr() : mRef(new WeakReference(nullptr)) {}
|
||||
|
||||
operator T*() const { return mRef->get(); }
|
||||
T& operator*() const { return *mRef->get(); }
|
||||
|
||||
T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mRef->get(); }
|
||||
|
||||
T* get() const { return mRef->get(); }
|
||||
|
||||
private:
|
||||
friend class SupportsWeakPtr<T>;
|
||||
|
||||
explicit WeakPtr(const RefPtr<WeakReference>& aOther) : mRef(aOther) {}
|
||||
|
||||
RefPtr<WeakReference> mRef;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_WeakPtr_h */
|
||||
195
cocos2d-x/external/win32/include/spidermonkey/mozilla/WindowsVersion.h
vendored
Executable file
195
cocos2d-x/external/win32/include/spidermonkey/mozilla/WindowsVersion.h
vendored
Executable file
@@ -0,0 +1,195 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_WindowsVersion_h
|
||||
#define mozilla_WindowsVersion_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
inline bool
|
||||
IsWindowsVersionOrLater(uint32_t aVersion)
|
||||
{
|
||||
static uint32_t minVersion = 0;
|
||||
static uint32_t maxVersion = UINT32_MAX;
|
||||
|
||||
if (minVersion >= aVersion) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aVersion >= maxVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OSVERSIONINFOEX info;
|
||||
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
info.dwMajorVersion = aVersion >> 24;
|
||||
info.dwMinorVersion = (aVersion >> 16) & 0xFF;
|
||||
info.wServicePackMajor = (aVersion >> 8) & 0xFF;
|
||||
info.wServicePackMinor = aVersion & 0xFF;
|
||||
|
||||
DWORDLONG conditionMask = 0;
|
||||
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
|
||||
|
||||
if (VerifyVersionInfo(&info,
|
||||
VER_MAJORVERSION | VER_MINORVERSION |
|
||||
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
||||
conditionMask)) {
|
||||
minVersion = aVersion;
|
||||
return true;
|
||||
}
|
||||
|
||||
maxVersion = aVersion;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsWindowsBuildOrLater(uint32_t aBuild)
|
||||
{
|
||||
static uint32_t minBuild = 0;
|
||||
static uint32_t maxBuild = UINT32_MAX;
|
||||
|
||||
if (minBuild >= aBuild) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aBuild >= maxBuild) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OSVERSIONINFOEX info;
|
||||
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
info.dwBuildNumber = aBuild;
|
||||
|
||||
DWORDLONG conditionMask = 0;
|
||||
VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
|
||||
if (VerifyVersionInfo(&info, VER_BUILDNUMBER, conditionMask)) {
|
||||
minBuild = aBuild;
|
||||
return true;
|
||||
}
|
||||
|
||||
maxBuild = aBuild;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_M_X64) || defined(_M_AMD64)
|
||||
// We support only Win7 or later on Win64.
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsXPSP3OrLater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin2003OrLater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin2003SP2OrLater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsVistaOrLater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsVistaSP1OrLater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin7OrLater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsXPSP3OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x05010300ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin2003OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x05020000ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin2003SP2OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x05020200ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsVistaOrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x06000000ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsVistaSP1OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x06000100ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin7OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x06010000ul);
|
||||
}
|
||||
#endif
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin7SP1OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x06010100ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin8OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x06020000ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin8Point1OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x06030000ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin10OrLater()
|
||||
{
|
||||
return IsWindowsVersionOrLater(0x0a000000ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsNotWin7PreRTM()
|
||||
{
|
||||
return IsWin7SP1OrLater() || !IsWin7OrLater() ||
|
||||
IsWindowsBuildOrLater(7600);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_WindowsVersion_h */
|
||||
121
cocos2d-x/external/win32/include/spidermonkey/mozilla/XorShift128PlusRNG.h
vendored
Executable file
121
cocos2d-x/external/win32/include/spidermonkey/mozilla/XorShift128PlusRNG.h
vendored
Executable file
@@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* The xorshift128+ pseudo-random number generator. */
|
||||
|
||||
#ifndef mozilla_XorShift128Plus_h
|
||||
#define mozilla_XorShift128Plus_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace non_crypto {
|
||||
|
||||
/*
|
||||
* A stream of pseudo-random numbers generated using the xorshift+ technique
|
||||
* described here:
|
||||
*
|
||||
* Vigna, Sebastiano (2014). "Further scramblings of Marsaglia's xorshift
|
||||
* generators". arXiv:1404.0390 (http://arxiv.org/abs/1404.0390)
|
||||
*
|
||||
* That paper says:
|
||||
*
|
||||
* In particular, we propose a tightly coded xorshift128+ generator that
|
||||
* does not fail systematically any test from the BigCrush suite of TestU01
|
||||
* (even reversed) and generates 64 pseudorandom bits in 1.10 ns on an
|
||||
* Intel(R) Core(TM) i7-4770 CPU @3.40GHz (Haswell). It is the fastest
|
||||
* generator we are aware of with such empirical statistical properties.
|
||||
*
|
||||
* The stream of numbers produced by this method repeats every 2**128 - 1 calls
|
||||
* (i.e. never, for all practical purposes). Zero appears 2**64 - 1 times in
|
||||
* this period; all other numbers appear 2**64 times. Additionally, each *bit*
|
||||
* in the produced numbers repeats every 2**128 - 1 calls.
|
||||
*
|
||||
* This generator is not suitable as a cryptographically secure random number
|
||||
* generator.
|
||||
*/
|
||||
class XorShift128PlusRNG {
|
||||
uint64_t mState[2];
|
||||
|
||||
public:
|
||||
/*
|
||||
* Construct a xorshift128+ pseudo-random number stream using |aInitial0| and
|
||||
* |aInitial1| as the initial state. These MUST NOT both be zero.
|
||||
*
|
||||
* If the initial states contain many zeros, for a few iterations you'll see
|
||||
* many zeroes in the generated numbers. It's suggested to seed a SplitMix64
|
||||
* generator <http://xorshift.di.unimi.it/splitmix64.c> and use its first two
|
||||
* outputs to seed xorshift128+.
|
||||
*/
|
||||
XorShift128PlusRNG(uint64_t aInitial0, uint64_t aInitial1) {
|
||||
setState(aInitial0, aInitial1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pseudo-random 64-bit number.
|
||||
*/
|
||||
uint64_t next() {
|
||||
/*
|
||||
* The offsetOfState*() methods below are provided so that exceedingly-rare
|
||||
* callers that want to observe or poke at RNG state in C++ type-system-
|
||||
* ignoring means can do so. Don't change the next() or nextDouble()
|
||||
* algorithms without altering code that uses offsetOfState*()!
|
||||
*/
|
||||
uint64_t s1 = mState[0];
|
||||
const uint64_t s0 = mState[1];
|
||||
mState[0] = s0;
|
||||
s1 ^= s1 << 23;
|
||||
mState[1] = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26);
|
||||
return mState[1] + s0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a pseudo-random floating-point value in the range [0, 1). More
|
||||
* precisely, choose an integer in the range [0, 2**53) and divide it by
|
||||
* 2**53. Given the 2**128 - 1 period noted above, the produced doubles are
|
||||
* all but uniformly distributed in this range.
|
||||
*/
|
||||
double nextDouble() {
|
||||
/*
|
||||
* Because the IEEE 64-bit floating point format stores the leading '1' bit
|
||||
* of the mantissa implicitly, it effectively represents a mantissa in the
|
||||
* range [0, 2**53) in only 52 bits. FloatingPoint<double>::kExponentShift
|
||||
* is the width of the bitfield in the in-memory format, so we must add one
|
||||
* to get the mantissa's range.
|
||||
*/
|
||||
static constexpr int kMantissaBits =
|
||||
mozilla::FloatingPoint<double>::kExponentShift + 1;
|
||||
uint64_t mantissa = next() & ((UINT64_C(1) << kMantissaBits) - 1);
|
||||
return double(mantissa) / (UINT64_C(1) << kMantissaBits);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the stream's current state to |aState0| and |aState1|. These must not
|
||||
* both be zero; ideally, they should have an almost even mix of zero and one
|
||||
* bits.
|
||||
*/
|
||||
void setState(uint64_t aState0, uint64_t aState1) {
|
||||
MOZ_ASSERT(aState0 || aState1);
|
||||
mState[0] = aState0;
|
||||
mState[1] = aState1;
|
||||
}
|
||||
|
||||
static size_t offsetOfState0() {
|
||||
return offsetof(XorShift128PlusRNG, mState[0]);
|
||||
}
|
||||
static size_t offsetOfState1() {
|
||||
return offsetof(XorShift128PlusRNG, mState[1]);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace non_crypto
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_XorShift128Plus_h
|
||||
538
cocos2d-x/external/win32/include/spidermonkey/mozilla/double-conversion.h
vendored
Executable file
538
cocos2d-x/external/win32/include/spidermonkey/mozilla/double-conversion.h
vendored
Executable file
@@ -0,0 +1,538 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "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 COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS 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.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
class DoubleToStringConverter {
|
||||
public:
|
||||
// When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
|
||||
// or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
|
||||
// function returns false.
|
||||
static const int kMaxFixedDigitsBeforePoint = 60;
|
||||
static const int kMaxFixedDigitsAfterPoint = 60;
|
||||
|
||||
// When calling ToExponential with a requested_digits
|
||||
// parameter > kMaxExponentialDigits then the function returns false.
|
||||
static const int kMaxExponentialDigits = 120;
|
||||
|
||||
// When calling ToPrecision with a requested_digits
|
||||
// parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
|
||||
// then the function returns false.
|
||||
static const int kMinPrecisionDigits = 1;
|
||||
static const int kMaxPrecisionDigits = 120;
|
||||
|
||||
enum Flags {
|
||||
NO_FLAGS = 0,
|
||||
EMIT_POSITIVE_EXPONENT_SIGN = 1,
|
||||
EMIT_TRAILING_DECIMAL_POINT = 2,
|
||||
EMIT_TRAILING_ZERO_AFTER_POINT = 4,
|
||||
UNIQUE_ZERO = 8
|
||||
};
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
|
||||
// form, emits a '+' for positive exponents. Example: 1.2e+2.
|
||||
// - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
|
||||
// converted into decimal format then a trailing decimal point is appended.
|
||||
// Example: 2345.0 is converted to "2345.".
|
||||
// - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
|
||||
// emits a trailing '0'-character. This flag requires the
|
||||
// EXMIT_TRAILING_DECIMAL_POINT flag.
|
||||
// Example: 2345.0 is converted to "2345.0".
|
||||
// - UNIQUE_ZERO: "-0.0" is converted to "0.0".
|
||||
//
|
||||
// Infinity symbol and nan_symbol provide the string representation for these
|
||||
// special values. If the string is NULL and the special value is encountered
|
||||
// then the conversion functions return false.
|
||||
//
|
||||
// The exponent_character is used in exponential representations. It is
|
||||
// usually 'e' or 'E'.
|
||||
//
|
||||
// When converting to the shortest representation the converter will
|
||||
// represent input numbers in decimal format if they are in the interval
|
||||
// [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
|
||||
// (lower boundary included, greater boundary excluded).
|
||||
// Example: with decimal_in_shortest_low = -6 and
|
||||
// decimal_in_shortest_high = 21:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
// ToShortest(100000000000000000000.0) -> "100000000000000000000"
|
||||
// ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
|
||||
//
|
||||
// When converting to precision mode the converter may add
|
||||
// max_leading_padding_zeroes before returning the number in exponential
|
||||
// format.
|
||||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarily the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
|
||||
// ToPrecision(230.0, 2) -> "230"
|
||||
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
|
||||
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
DoubleToStringConverter(int flags,
|
||||
const char* infinity_symbol,
|
||||
const char* nan_symbol,
|
||||
char exponent_character,
|
||||
int decimal_in_shortest_low,
|
||||
int decimal_in_shortest_high,
|
||||
int max_leading_padding_zeroes_in_precision_mode,
|
||||
int max_trailing_padding_zeroes_in_precision_mode)
|
||||
: flags_(flags),
|
||||
infinity_symbol_(infinity_symbol),
|
||||
nan_symbol_(nan_symbol),
|
||||
exponent_character_(exponent_character),
|
||||
decimal_in_shortest_low_(decimal_in_shortest_low),
|
||||
decimal_in_shortest_high_(decimal_in_shortest_high),
|
||||
max_leading_padding_zeroes_in_precision_mode_(
|
||||
max_leading_padding_zeroes_in_precision_mode),
|
||||
max_trailing_padding_zeroes_in_precision_mode_(
|
||||
max_trailing_padding_zeroes_in_precision_mode) {
|
||||
// When 'trailing zero after the point' is set, then 'trailing point'
|
||||
// must be set too.
|
||||
ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
|
||||
!((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
|
||||
}
|
||||
|
||||
// Returns a converter following the EcmaScript specification.
|
||||
static MFBT_API const DoubleToStringConverter& EcmaScriptConverter();
|
||||
|
||||
// Computes the shortest string of digits that correctly represent the input
|
||||
// number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
|
||||
// (see constructor) it then either returns a decimal representation, or an
|
||||
// exponential representation.
|
||||
// Example with decimal_in_shortest_low = -6,
|
||||
// decimal_in_shortest_high = 21,
|
||||
// EMIT_POSITIVE_EXPONENT_SIGN activated, and
|
||||
// EMIT_TRAILING_DECIMAL_POINT deactived:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
// ToShortest(100000000000000000000.0) -> "100000000000000000000"
|
||||
// ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
|
||||
//
|
||||
// Note: the conversion may round the output if the returned string
|
||||
// is accurate enough to uniquely identify the input-number.
|
||||
// For example the most precise representation of the double 9e59 equals
|
||||
// "899999999999999918767229449717619953810131273674690656206848", but
|
||||
// the converter will return the shorter (but still correct) "9e59".
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except when the input value is special and no infinity_symbol or
|
||||
// nan_symbol has been given to the constructor.
|
||||
bool ToShortest(double value, StringBuilder* result_builder) const {
|
||||
return ToShortestIeeeNumber(value, result_builder, SHORTEST);
|
||||
}
|
||||
|
||||
// Same as ToShortest, but for single-precision floats.
|
||||
bool ToShortestSingle(float value, StringBuilder* result_builder) const {
|
||||
return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
// Computes a decimal representation with a fixed number of digits after the
|
||||
// decimal point. The last emitted digit is rounded.
|
||||
//
|
||||
// Examples:
|
||||
// ToFixed(3.12, 1) -> "3.1"
|
||||
// ToFixed(3.1415, 3) -> "3.142"
|
||||
// ToFixed(1234.56789, 4) -> "1234.5679"
|
||||
// ToFixed(1.23, 5) -> "1.23000"
|
||||
// ToFixed(0.1, 4) -> "0.1000"
|
||||
// ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
|
||||
// ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
|
||||
// ToFixed(0.1, 17) -> "0.10000000000000001"
|
||||
//
|
||||
// If requested_digits equals 0, then the tail of the result depends on
|
||||
// the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
// Examples, for requested_digits == 0,
|
||||
// let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
|
||||
// - false and false: then 123.45 -> 123
|
||||
// 0.678 -> 1
|
||||
// - true and false: then 123.45 -> 123.
|
||||
// 0.678 -> 1.
|
||||
// - true and true: then 123.45 -> 123.0
|
||||
// 0.678 -> 1.0
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - 'value' > 10^kMaxFixedDigitsBeforePoint, or
|
||||
// - 'requested_digits' > kMaxFixedDigitsAfterPoint.
|
||||
// The last two conditions imply that the result will never contain more than
|
||||
// 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
|
||||
// (one additional character for the sign, and one for the decimal point).
|
||||
MFBT_API bool ToFixed(double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
// Computes a representation in exponential format with requested_digits
|
||||
// after the decimal point. The last emitted digit is rounded.
|
||||
// If requested_digits equals -1, then the shortest exponential representation
|
||||
// is computed.
|
||||
//
|
||||
// Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
|
||||
// exponent_character set to 'e'.
|
||||
// ToExponential(3.12, 1) -> "3.1e0"
|
||||
// ToExponential(5.0, 3) -> "5.000e0"
|
||||
// ToExponential(0.001, 2) -> "1.00e-3"
|
||||
// ToExponential(3.1415, -1) -> "3.1415e0"
|
||||
// ToExponential(3.1415, 4) -> "3.1415e0"
|
||||
// ToExponential(3.1415, 3) -> "3.142e0"
|
||||
// ToExponential(123456789000000, 3) -> "1.235e14"
|
||||
// ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
|
||||
// ToExponential(1000000000000000019884624838656.0, 32) ->
|
||||
// "1.00000000000000001988462483865600e30"
|
||||
// ToExponential(1234, 0) -> "1e3"
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - 'requested_digits' > kMaxExponentialDigits.
|
||||
// The last condition implies that the result will never contain more than
|
||||
// kMaxExponentialDigits + 8 characters (the sign, the digit before the
|
||||
// decimal point, the decimal point, the exponent character, the
|
||||
// exponent's sign, and at most 3 exponent digits).
|
||||
MFBT_API bool ToExponential(double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
// Computes 'precision' leading digits of the given 'value' and returns them
|
||||
// either in exponential or decimal format, depending on
|
||||
// max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
|
||||
// constructor).
|
||||
// The last computed digit is rounded.
|
||||
//
|
||||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarily the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
|
||||
// ToPrecision(230.0, 2) -> "230"
|
||||
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
|
||||
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT:
|
||||
// ToPrecision(123450.0, 6) -> "123450"
|
||||
// ToPrecision(123450.0, 5) -> "123450"
|
||||
// ToPrecision(123450.0, 4) -> "123500"
|
||||
// ToPrecision(123450.0, 3) -> "123000"
|
||||
// ToPrecision(123450.0, 2) -> "1.2e5"
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - precision < kMinPericisionDigits
|
||||
// - precision > kMaxPrecisionDigits
|
||||
// The last condition implies that the result will never contain more than
|
||||
// kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
|
||||
// exponent character, the exponent's sign, and at most 3 exponent digits).
|
||||
MFBT_API bool ToPrecision(double value,
|
||||
int precision,
|
||||
bool* used_exponential_notation,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
enum DtoaMode {
|
||||
// Produce the shortest correct representation.
|
||||
// For example the output of 0.299999999999999988897 is (the less accurate
|
||||
// but correct) 0.3.
|
||||
SHORTEST,
|
||||
// Same as SHORTEST, but for single-precision floats.
|
||||
SHORTEST_SINGLE,
|
||||
// Produce a fixed number of digits after the decimal point.
|
||||
// For instance fixed(0.1, 4) becomes 0.1000
|
||||
// If the input number is big, the output will be big.
|
||||
FIXED,
|
||||
// Fixed number of digits (independent of the decimal point).
|
||||
PRECISION
|
||||
};
|
||||
|
||||
// The maximal number of digits that are needed to emit a double in base 10.
|
||||
// A higher precision can be achieved by using more digits, but the shortest
|
||||
// accurate representation of any double will never use more digits than
|
||||
// kBase10MaximalLength.
|
||||
// Note that DoubleToAscii null-terminates its input. So the given buffer
|
||||
// should be at least kBase10MaximalLength + 1 characters long.
|
||||
static const MFBT_DATA int kBase10MaximalLength = 17;
|
||||
|
||||
// Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
|
||||
// -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
|
||||
// after it has been casted to a single-precision float. That is, in this
|
||||
// mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
|
||||
//
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
// (together with the correct exponent) then reading this number will give
|
||||
// 'v' again. The buffer will choose the representation that is closest to
|
||||
// 'v'. If there are two at the same distance, than the one farther away
|
||||
// from 0 is chosen (halfway cases - ending with 5 - are rounded up).
|
||||
// In this mode the 'requested_digits' parameter is ignored.
|
||||
// - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
|
||||
// - FIXED: produces digits necessary to print a given number with
|
||||
// 'requested_digits' digits after the decimal point. The produced digits
|
||||
// might be too short in which case the caller has to fill the remainder
|
||||
// with '0's.
|
||||
// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
|
||||
// Halfway cases are rounded towards +/-Infinity (away from 0). The call
|
||||
// toFixed(0.15, 2) thus returns buffer="2", point=0.
|
||||
// The returned buffer may contain digits that would be truncated from the
|
||||
// shortest representation of the input.
|
||||
// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
|
||||
// Even though the length of produced digits usually equals
|
||||
// 'requested_digits', the function is allowed to return fewer digits, in
|
||||
// which case the caller has to fill the missing digits with '0's.
|
||||
// Halfway cases are again rounded away from 0.
|
||||
// DoubleToAscii expects the given buffer to be big enough to hold all
|
||||
// digits and a terminating null-character. In SHORTEST-mode it expects a
|
||||
// buffer of at least kBase10MaximalLength + 1. In all other modes the
|
||||
// requested_digits parameter and the padding-zeroes limit the size of the
|
||||
// output. Don't forget the decimal point, the exponent character and the
|
||||
// terminating null-character when computing the maximal output size.
|
||||
// The given length is only used in debug mode to ensure the buffer is big
|
||||
// enough.
|
||||
static MFBT_API void DoubleToAscii(double v,
|
||||
DtoaMode mode,
|
||||
int requested_digits,
|
||||
char* buffer,
|
||||
int buffer_length,
|
||||
bool* sign,
|
||||
int* length,
|
||||
int* point);
|
||||
|
||||
private:
|
||||
// Implementation for ToShortest and ToShortestSingle.
|
||||
MFBT_API bool ToShortestIeeeNumber(double value,
|
||||
StringBuilder* result_builder,
|
||||
DtoaMode mode) const;
|
||||
|
||||
// If the value is a special value (NaN or Infinity) constructs the
|
||||
// corresponding string using the configured infinity/nan-symbol.
|
||||
// If either of them is NULL or the value is not special then the
|
||||
// function returns false.
|
||||
MFBT_API bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
|
||||
// Constructs an exponential representation (i.e. 1.234e56).
|
||||
// The given exponent assumes a decimal point after the first decimal digit.
|
||||
MFBT_API void CreateExponentialRepresentation(const char* decimal_digits,
|
||||
int length,
|
||||
int exponent,
|
||||
StringBuilder* result_builder) const;
|
||||
// Creates a decimal representation (i.e 1234.5678).
|
||||
MFBT_API void CreateDecimalRepresentation(const char* decimal_digits,
|
||||
int length,
|
||||
int decimal_point,
|
||||
int digits_after_point,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
const int flags_;
|
||||
const char* const infinity_symbol_;
|
||||
const char* const nan_symbol_;
|
||||
const char exponent_character_;
|
||||
const int decimal_in_shortest_low_;
|
||||
const int decimal_in_shortest_high_;
|
||||
const int max_leading_padding_zeroes_in_precision_mode_;
|
||||
const int max_trailing_padding_zeroes_in_precision_mode_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
};
|
||||
|
||||
|
||||
class StringToDoubleConverter {
|
||||
public:
|
||||
// Enumeration for allowing octals and ignoring junk when converting
|
||||
// strings to numbers.
|
||||
enum Flags {
|
||||
NO_FLAGS = 0,
|
||||
ALLOW_HEX = 1,
|
||||
ALLOW_OCTALS = 2,
|
||||
ALLOW_TRAILING_JUNK = 4,
|
||||
ALLOW_LEADING_SPACES = 8,
|
||||
ALLOW_TRAILING_SPACES = 16,
|
||||
ALLOW_SPACES_AFTER_SIGN = 32
|
||||
};
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
|
||||
// Ex: StringToDouble("0x1234") -> 4660.0
|
||||
// In StringToDouble("0x1234.56") the characters ".56" are trailing
|
||||
// junk. The result of the call is hence dependent on
|
||||
// the ALLOW_TRAILING_JUNK flag and/or the junk value.
|
||||
// With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,
|
||||
// the string will not be parsed as "0" followed by junk.
|
||||
//
|
||||
// - ALLOW_OCTALS: recognizes the prefix "0" for octals:
|
||||
// If a sequence of octal digits starts with '0', then the number is
|
||||
// read as octal integer. Octal numbers may only be integers.
|
||||
// Ex: StringToDouble("01234") -> 668.0
|
||||
// StringToDouble("012349") -> 12349.0 // Not a sequence of octal
|
||||
// // digits.
|
||||
// In StringToDouble("01234.56") the characters ".56" are trailing
|
||||
// junk. The result of the call is hence dependent on
|
||||
// the ALLOW_TRAILING_JUNK flag and/or the junk value.
|
||||
// In StringToDouble("01234e56") the characters "e56" are trailing
|
||||
// junk, too.
|
||||
// - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
|
||||
// a double literal.
|
||||
// - ALLOW_LEADING_SPACES: skip over leading spaces.
|
||||
// - ALLOW_TRAILING_SPACES: ignore trailing spaces.
|
||||
// - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.
|
||||
// Ex: StringToDouble("- 123.2") -> -123.2.
|
||||
// StringToDouble("+ 123.2") -> 123.2
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
// containing only spaces is converted to the 'empty_string_value', too.
|
||||
//
|
||||
// junk_string_value is returned when
|
||||
// a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not
|
||||
// part of a double-literal) is found.
|
||||
// b) ALLOW_TRAILING_JUNK is set, but the string does not start with a
|
||||
// double literal.
|
||||
//
|
||||
// infinity_symbol and nan_symbol are strings that are used to detect
|
||||
// inputs that represent infinity and NaN. They can be null, in which case
|
||||
// they are ignored.
|
||||
// The conversion routine first reads any possible signs. Then it compares the
|
||||
// following character of the input-string with the first character of
|
||||
// the infinity, and nan-symbol. If either matches, the function assumes, that
|
||||
// a match has been found, and expects the following input characters to match
|
||||
// the remaining characters of the special-value symbol.
|
||||
// This means that the following restrictions apply to special-value symbols:
|
||||
// - they must not start with signs ('+', or '-'),
|
||||
// - they must not have the same first character.
|
||||
// - they must not start with digits.
|
||||
//
|
||||
// Examples:
|
||||
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
|
||||
// empty_string_value = 0.0,
|
||||
// junk_string_value = NaN,
|
||||
// infinity_symbol = "infinity",
|
||||
// nan_symbol = "nan":
|
||||
// StringToDouble("0x1234") -> 4660.0.
|
||||
// StringToDouble("0x1234K") -> 4660.0.
|
||||
// StringToDouble("") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" ") -> NaN // junk_string_value.
|
||||
// StringToDouble(" 1") -> NaN // junk_string_value.
|
||||
// StringToDouble("0x") -> NaN // junk_string_value.
|
||||
// StringToDouble("-123.45") -> -123.45.
|
||||
// StringToDouble("--123.45") -> NaN // junk_string_value.
|
||||
// StringToDouble("123e45") -> 123e45.
|
||||
// StringToDouble("123E45") -> 123e45.
|
||||
// StringToDouble("123e+45") -> 123e45.
|
||||
// StringToDouble("123E-45") -> 123e-45.
|
||||
// StringToDouble("123e") -> 123.0 // trailing junk ignored.
|
||||
// StringToDouble("123e-") -> 123.0 // trailing junk ignored.
|
||||
// StringToDouble("+NaN") -> NaN // NaN string literal.
|
||||
// StringToDouble("-infinity") -> -inf. // infinity literal.
|
||||
// StringToDouble("Infinity") -> NaN // junk_string_value.
|
||||
//
|
||||
// flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,
|
||||
// empty_string_value = 0.0,
|
||||
// junk_string_value = NaN,
|
||||
// infinity_symbol = NULL,
|
||||
// nan_symbol = NULL:
|
||||
// StringToDouble("0x1234") -> NaN // junk_string_value.
|
||||
// StringToDouble("01234") -> 668.0.
|
||||
// StringToDouble("") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" ") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" 1") -> 1.0
|
||||
// StringToDouble("0x") -> NaN // junk_string_value.
|
||||
// StringToDouble("0123e45") -> NaN // junk_string_value.
|
||||
// StringToDouble("01239E45") -> 1239e45.
|
||||
// StringToDouble("-infinity") -> NaN // junk_string_value.
|
||||
// StringToDouble("NaN") -> NaN // junk_string_value.
|
||||
StringToDoubleConverter(int flags,
|
||||
double empty_string_value,
|
||||
double junk_string_value,
|
||||
const char* infinity_symbol,
|
||||
const char* nan_symbol)
|
||||
: flags_(flags),
|
||||
empty_string_value_(empty_string_value),
|
||||
junk_string_value_(junk_string_value),
|
||||
infinity_symbol_(infinity_symbol),
|
||||
nan_symbol_(nan_symbol) {
|
||||
}
|
||||
|
||||
// Performs the conversion.
|
||||
// The output parameter 'processed_characters_count' is set to the number
|
||||
// of characters that have been processed to read the number.
|
||||
// Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included
|
||||
// in the 'processed_characters_count'. Trailing junk is never included.
|
||||
double StringToDouble(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToIeee(buffer, length, processed_characters_count, true);
|
||||
}
|
||||
|
||||
// Same as StringToDouble but reads a float.
|
||||
// Note that this is not equivalent to static_cast<float>(StringToDouble(...))
|
||||
// due to potential double-rounding.
|
||||
float StringToFloat(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return static_cast<float>(StringToIeee(buffer, length,
|
||||
processed_characters_count, false));
|
||||
}
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
const double empty_string_value_;
|
||||
const double junk_string_value_;
|
||||
const char* const infinity_symbol_;
|
||||
const char* const nan_symbol_;
|
||||
|
||||
double StringToIeee(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count,
|
||||
bool read_as_double) const;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
68
cocos2d-x/external/win32/include/spidermonkey/mozilla/fallible.h
vendored
Executable file
68
cocos2d-x/external/win32/include/spidermonkey/mozilla/fallible.h
vendored
Executable file
@@ -0,0 +1,68 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_fallible_h
|
||||
#define mozilla_fallible_h
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
/* Explicit fallible allocation
|
||||
*
|
||||
* Memory allocation (normally) defaults to abort in case of failed
|
||||
* allocation. That is, it never returns NULL, and crashes instead.
|
||||
*
|
||||
* Code can explicitely request for fallible memory allocation thanks
|
||||
* to the declarations below.
|
||||
*
|
||||
* The typical use of the mozilla::fallible const is with placement new,
|
||||
* like the following:
|
||||
*
|
||||
* foo = new (mozilla::fallible) Foo();
|
||||
*
|
||||
* The following forms, or derivatives, are also possible but deprecated:
|
||||
*
|
||||
* foo = new ((mozilla::fallible_t())) Foo();
|
||||
*
|
||||
* const mozilla::fallible_t fallible = mozilla::fallible_t();
|
||||
* bar = new (f) Bar();
|
||||
*
|
||||
* It is also possible to declare method overloads with fallible allocation
|
||||
* alternatives, like so:
|
||||
*
|
||||
* class Foo {
|
||||
* public:
|
||||
* void Method(void *);
|
||||
* void Method(void *, const mozilla::fallible_t&);
|
||||
* };
|
||||
*
|
||||
* Foo foo;
|
||||
* foo.Method(nullptr, mozilla::fallible);
|
||||
*
|
||||
* If that last method call is in a method that itself takes a const
|
||||
* fallible_t& argument, it is recommended to propagate that argument
|
||||
* instead of using mozilla::fallible:
|
||||
*
|
||||
* void Func(Foo &foo, const mozilla::fallible_t& aFallible) {
|
||||
* foo.Method(nullptr, aFallible);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
namespace mozilla {
|
||||
|
||||
struct fallible_t { };
|
||||
|
||||
/* This symbol is kept unexported, such that in corner cases where the
|
||||
* compiler can't remove its use (essentially, cross compilation-unit
|
||||
* calls), the smallest machine code is used.
|
||||
* Depending how the linker packs symbols, it will consume between 1 and
|
||||
* 8 bytes of read-only data in each executable or shared library, but
|
||||
* only in those where it's actually not optimized out by the compiler.
|
||||
*/
|
||||
extern const fallible_t fallible;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
#endif // mozilla_fallible_h
|
||||
361
cocos2d-x/external/win32/include/spidermonkey/mozilla/mozalloc.h
vendored
Executable file
361
cocos2d-x/external/win32/include/spidermonkey/mozilla/mozalloc.h
vendored
Executable file
@@ -0,0 +1,361 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_mozalloc_h
|
||||
#define mozilla_mozalloc_h
|
||||
|
||||
/*
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=427099
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# include <new>
|
||||
// Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
|
||||
// corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
|
||||
// using things defined there. Specifically, with stdlib.h, the use of abs()
|
||||
// in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include "mozilla/fallible.h"
|
||||
#include "mozilla/mozalloc_abort.h"
|
||||
#include "mozilla/TemplateLib.h"
|
||||
#endif
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#define MOZALLOC_HAVE_XMALLOC
|
||||
|
||||
#if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
|
||||
# define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
#elif defined(HAVE_FORCEINLINE)
|
||||
# define MOZALLOC_INLINE __forceinline
|
||||
#else
|
||||
# define MOZALLOC_INLINE inline
|
||||
#endif
|
||||
|
||||
/* Workaround build problem with Sun Studio 12 */
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# undef MOZ_MUST_USE
|
||||
# define MOZ_MUST_USE
|
||||
# undef MOZ_ALLOCATOR
|
||||
# define MOZ_ALLOCATOR
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* ifdef __cplusplus */
|
||||
|
||||
/*
|
||||
* We need to use malloc_impl and free_impl in this file when they are
|
||||
* defined, because of how mozglue.dll is linked on Windows, where using
|
||||
* malloc/free would end up using the symbols from the MSVCRT instead of
|
||||
* ours.
|
||||
*/
|
||||
#ifndef free_impl
|
||||
#define free_impl free
|
||||
#define free_impl_
|
||||
#endif
|
||||
#ifndef malloc_impl
|
||||
#define malloc_impl malloc
|
||||
#define malloc_impl_
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Each declaration below is analogous to a "standard" allocation
|
||||
* function, except that the out-of-memory handling is made explicit.
|
||||
* The |moz_x| versions will never return a NULL pointer; if memory
|
||||
* is exhausted, they abort. The |moz_| versions may return NULL
|
||||
* pointers if memory is exhausted: their return value must be checked.
|
||||
*
|
||||
* All these allocation functions are *guaranteed* to return a pointer
|
||||
* to memory allocated in such a way that that memory can be freed by
|
||||
* passing that pointer to |free()|.
|
||||
*/
|
||||
|
||||
MFBT_API void* moz_xmalloc(size_t size)
|
||||
MOZ_ALLOCATOR;
|
||||
|
||||
MFBT_API void* moz_xcalloc(size_t nmemb, size_t size)
|
||||
MOZ_ALLOCATOR;
|
||||
|
||||
MFBT_API void* moz_xrealloc(void* ptr, size_t size)
|
||||
MOZ_ALLOCATOR;
|
||||
|
||||
MFBT_API char* moz_xstrdup(const char* str)
|
||||
MOZ_ALLOCATOR;
|
||||
|
||||
MFBT_API size_t moz_malloc_usable_size(void *ptr);
|
||||
|
||||
MFBT_API size_t moz_malloc_size_of(const void *ptr);
|
||||
|
||||
#if defined(HAVE_STRNDUP)
|
||||
MFBT_API char* moz_xstrndup(const char* str, size_t strsize)
|
||||
MOZ_ALLOCATOR;
|
||||
#endif /* if defined(HAVE_STRNDUP) */
|
||||
|
||||
|
||||
#if defined(HAVE_POSIX_MEMALIGN)
|
||||
MFBT_API MOZ_MUST_USE
|
||||
int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
|
||||
|
||||
MFBT_API MOZ_MUST_USE
|
||||
int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
|
||||
#endif /* if defined(HAVE_POSIX_MEMALIGN) */
|
||||
|
||||
|
||||
#if defined(HAVE_MEMALIGN)
|
||||
MFBT_API void* moz_xmemalign(size_t boundary, size_t size)
|
||||
MOZ_ALLOCATOR;
|
||||
#endif /* if defined(HAVE_MEMALIGN) */
|
||||
|
||||
|
||||
#if defined(HAVE_VALLOC)
|
||||
MFBT_API void* moz_xvalloc(size_t size)
|
||||
MOZ_ALLOCATOR;
|
||||
#endif /* if defined(HAVE_VALLOC) */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* ifdef __cplusplus */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
* We implement the default operators new/delete as part of
|
||||
* libmozalloc, replacing their definitions in libstdc++. The
|
||||
* operator new* definitions in libmozalloc will never return a NULL
|
||||
* pointer.
|
||||
*
|
||||
* Each operator new immediately below returns a pointer to memory
|
||||
* that can be delete'd by any of
|
||||
*
|
||||
* (1) the matching infallible operator delete immediately below
|
||||
* (2) the matching "fallible" operator delete further below
|
||||
* (3) the matching system |operator delete(void*, std::nothrow)|
|
||||
* (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
|
||||
*
|
||||
* NB: these are declared |throw(std::bad_alloc)|, though they will never
|
||||
* throw that exception. This declaration is consistent with the rule
|
||||
* that |::operator new() throw(std::bad_alloc)| will never return NULL.
|
||||
*/
|
||||
|
||||
/* NB: This is defined just to silence vacuous warnings about symbol
|
||||
* visibility on OS X/gcc. These symbols are force-inline and not
|
||||
* exported. */
|
||||
#if defined(XP_MACOSX)
|
||||
# define MOZALLOC_EXPORT_NEW MFBT_API
|
||||
#else
|
||||
# define MOZALLOC_EXPORT_NEW
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
/*
|
||||
* It's important to always specify 'throw()' in GCC because it's used to tell
|
||||
* GCC that 'new' may return null. That makes GCC null-check the result before
|
||||
* potentially initializing the memory to zero.
|
||||
* Also, the Android minimalistic headers don't include std::bad_alloc.
|
||||
*/
|
||||
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
|
||||
#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
|
||||
#elif defined(_MSC_VER)
|
||||
/*
|
||||
* Suppress build warning spam (bug 578546).
|
||||
*/
|
||||
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
|
||||
#else
|
||||
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
|
||||
#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS throw(std::bad_alloc)
|
||||
#endif
|
||||
|
||||
#define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
|
||||
|
||||
MOZALLOC_EXPORT_NEW
|
||||
#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
|
||||
/* gcc's asan somehow doesn't like always_inline on this function. */
|
||||
__attribute__((gnu_inline)) inline
|
||||
#else
|
||||
MOZALLOC_INLINE
|
||||
#endif
|
||||
void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC
|
||||
{
|
||||
return moz_xmalloc(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC
|
||||
{
|
||||
return moz_xmalloc(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We also add a new allocator variant: "fallible operator new."
|
||||
* Unlike libmozalloc's implementations of the standard nofail
|
||||
* allocators, this allocator is allowed to return NULL. It can be used
|
||||
* as follows
|
||||
*
|
||||
* Foo* f = new (mozilla::fallible) Foo(...);
|
||||
*
|
||||
* operator delete(fallible) is defined for completeness only.
|
||||
*
|
||||
* Each operator new below returns a pointer to memory that can be
|
||||
* delete'd by any of
|
||||
*
|
||||
* (1) the matching "fallible" operator delete below
|
||||
* (2) the matching infallible operator delete above
|
||||
* (3) the matching system |operator delete(void*, std::nothrow)|
|
||||
* (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
|
||||
*/
|
||||
|
||||
MOZALLOC_INLINE
|
||||
void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_INLINE
|
||||
void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_INLINE
|
||||
void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_INLINE
|
||||
void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
free_impl(ptr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This policy is identical to MallocAllocPolicy, except it uses
|
||||
* moz_xmalloc/moz_xcalloc/moz_xrealloc instead of
|
||||
* malloc/calloc/realloc.
|
||||
*/
|
||||
class InfallibleAllocPolicy
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
T* maybe_pod_malloc(size_t aNumElems)
|
||||
{
|
||||
return pod_malloc<T>(aNumElems);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* maybe_pod_calloc(size_t aNumElems)
|
||||
{
|
||||
return pod_calloc<T>(aNumElems);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
|
||||
{
|
||||
return pod_realloc<T>(aPtr, aOldSize, aNewSize);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* pod_malloc(size_t aNumElems)
|
||||
{
|
||||
if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
|
||||
reportAllocOverflow();
|
||||
}
|
||||
return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* pod_calloc(size_t aNumElems)
|
||||
{
|
||||
return static_cast<T*>(moz_xcalloc(aNumElems, sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
|
||||
{
|
||||
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
|
||||
reportAllocOverflow();
|
||||
}
|
||||
return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
|
||||
}
|
||||
|
||||
void free_(void* aPtr)
|
||||
{
|
||||
free_impl(aPtr);
|
||||
}
|
||||
|
||||
void reportAllocOverflow() const
|
||||
{
|
||||
mozalloc_abort("alloc overflow");
|
||||
}
|
||||
|
||||
bool checkSimulatedOOM() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ifdef __cplusplus */
|
||||
|
||||
#ifdef malloc_impl_
|
||||
#undef malloc_impl_
|
||||
#undef malloc_impl
|
||||
#endif
|
||||
#ifdef free_impl_
|
||||
#undef free_impl_
|
||||
#undef free_impl
|
||||
#endif
|
||||
|
||||
#endif /* ifndef mozilla_mozalloc_h */
|
||||
28
cocos2d-x/external/win32/include/spidermonkey/mozilla/mozalloc_abort.h
vendored
Executable file
28
cocos2d-x/external/win32/include/spidermonkey/mozilla/mozalloc_abort.h
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_mozalloc_abort_h
|
||||
#define mozilla_mozalloc_abort_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
/**
|
||||
* Terminate this process in such a way that breakpad is triggered, if
|
||||
* at all possible.
|
||||
*
|
||||
* Note: MOZ_NORETURN seems to break crash stacks on ARM, so we don't
|
||||
* use that annotation there.
|
||||
*/
|
||||
MFBT_API
|
||||
#if !defined(__arm__)
|
||||
MOZ_NORETURN
|
||||
#endif
|
||||
void mozalloc_abort(const char* const msg);
|
||||
|
||||
|
||||
#endif /* ifndef mozilla_mozalloc_abort_h */
|
||||
31
cocos2d-x/external/win32/include/spidermonkey/mozilla/mozalloc_oom.h
vendored
Executable file
31
cocos2d-x/external/win32/include/spidermonkey/mozilla/mozalloc_oom.h
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_mozalloc_oom_h
|
||||
#define mozilla_mozalloc_oom_h
|
||||
|
||||
#include "mozalloc.h"
|
||||
|
||||
/**
|
||||
* Called when memory is critically low. Returns iff it was able to
|
||||
* remedy the critical memory situation; if not, it will abort().
|
||||
*/
|
||||
MFBT_API void mozalloc_handle_oom(size_t requestedSize);
|
||||
|
||||
/**
|
||||
* Called by embedders (specifically Mozilla breakpad) which wants to be
|
||||
* notified of an intentional abort, to annotate any crash report with
|
||||
* the size of the allocation on which we aborted.
|
||||
*/
|
||||
typedef void (*mozalloc_oom_abort_handler)(size_t size);
|
||||
MFBT_API void mozalloc_set_oom_abort_handler(mozalloc_oom_abort_handler handler);
|
||||
|
||||
/* TODO: functions to query system memory usage and register
|
||||
* critical-memory handlers. */
|
||||
|
||||
|
||||
#endif /* ifndef mozilla_mozalloc_oom_h */
|
||||
298
cocos2d-x/external/win32/include/spidermonkey/mozilla/utils.h
vendored
Executable file
298
cocos2d-x/external/win32/include/spidermonkey/mozilla/utils.h
vendored
Executable file
@@ -0,0 +1,298 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "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 COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS 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.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_UTILS_H_
|
||||
#define DOUBLE_CONVERSION_UTILS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(condition) MOZ_ASSERT(condition)
|
||||
#endif
|
||||
#ifndef UNIMPLEMENTED
|
||||
#define UNIMPLEMENTED() MOZ_CRASH()
|
||||
#endif
|
||||
#ifndef UNREACHABLE
|
||||
#define UNREACHABLE() MOZ_CRASH()
|
||||
#endif
|
||||
|
||||
// Double operations detection based on target architecture.
|
||||
// Linux uses a 80bit wide floating point stack on x86. This induces double
|
||||
// rounding, which in turn leads to wrong results.
|
||||
// An easy way to test if the floating-point operations are correct is to
|
||||
// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
|
||||
// the result is equal to 89255e-22.
|
||||
// The best way to test this, is to create a division-function and to compare
|
||||
// the output of the division with the expected result. (Inlining must be
|
||||
// disabled.)
|
||||
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
|
||||
#if defined(_M_X64) || defined(__x86_64__) || \
|
||||
defined(__ARMEL__) || defined(__avr32__) || \
|
||||
defined(__hppa__) || defined(__ia64__) || \
|
||||
defined(__mips__) || \
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
|
||||
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
|
||||
defined(__SH4__) || defined(__alpha__) || \
|
||||
defined(_MIPS_ARCH_MIPS32R2) || \
|
||||
defined(__AARCH64EL__) || defined(__aarch64__)
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
||||
#if defined(_WIN32)
|
||||
// Windows uses a 64bit wide floating point stack.
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#else
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#endif // _WIN32
|
||||
#else
|
||||
#error Target architecture was not detected as supported by Double-Conversion.
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// The following macro works on both 32 and 64-bit platforms.
|
||||
// Usage: instead of writing 0x1234567890123456
|
||||
// write UINT64_2PART_C(0x12345678,90123456);
|
||||
#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
|
||||
|
||||
|
||||
// The expression ARRAY_SIZE(a) is a compile-time constant of type
|
||||
// size_t which represents the number of elements of the given
|
||||
// array. You should only use ARRAY_SIZE on statically allocated
|
||||
// arrays.
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) \
|
||||
((sizeof(a) / sizeof(*(a))) / \
|
||||
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
#endif
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DISALLOW_COPY_AND_ASSIGN
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
#endif
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
static const int kCharSize = sizeof(char);
|
||||
|
||||
// Returns the maximum of the two parameters.
|
||||
template <typename T>
|
||||
static T Max(T a, T b) {
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
|
||||
// Returns the minimum of the two parameters.
|
||||
template <typename T>
|
||||
static T Min(T a, T b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
|
||||
inline int StrLength(const char* string) {
|
||||
size_t length = strlen(string);
|
||||
ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
|
||||
return static_cast<int>(length);
|
||||
}
|
||||
|
||||
// This is a simplified version of V8's Vector class.
|
||||
template <typename T>
|
||||
class Vector {
|
||||
public:
|
||||
Vector() : start_(NULL), length_(0) {}
|
||||
Vector(T* data, int len) : start_(data), length_(len) {
|
||||
ASSERT(len == 0 || (len > 0 && data != NULL));
|
||||
}
|
||||
|
||||
// Returns a vector using the same backing storage as this one,
|
||||
// spanning from and including 'from', to but not including 'to'.
|
||||
Vector<T> SubVector(int from, int to) {
|
||||
ASSERT(to <= length_);
|
||||
ASSERT(from < to);
|
||||
ASSERT(0 <= from);
|
||||
return Vector<T>(start() + from, to - from);
|
||||
}
|
||||
|
||||
// Returns the length of the vector.
|
||||
int length() const { return length_; }
|
||||
|
||||
// Returns whether or not the vector is empty.
|
||||
bool is_empty() const { return length_ == 0; }
|
||||
|
||||
// Returns the pointer to the start of the data in the vector.
|
||||
T* start() const { return start_; }
|
||||
|
||||
// Access individual vector elements - checks bounds in debug mode.
|
||||
T& operator[](int index) const {
|
||||
ASSERT(0 <= index && index < length_);
|
||||
return start_[index];
|
||||
}
|
||||
|
||||
T& first() { return start_[0]; }
|
||||
|
||||
T& last() { return start_[length_ - 1]; }
|
||||
|
||||
private:
|
||||
T* start_;
|
||||
int length_;
|
||||
};
|
||||
|
||||
|
||||
// Helper class for building result strings in a character buffer. The
|
||||
// purpose of the class is to use safe operations that checks the
|
||||
// buffer bounds on all operations in debug mode.
|
||||
class StringBuilder {
|
||||
public:
|
||||
StringBuilder(char* buffer, int buffer_size)
|
||||
: buffer_(buffer, buffer_size), position_(0) { }
|
||||
|
||||
~StringBuilder() { if (!is_finalized()) Finalize(); }
|
||||
|
||||
int size() const { return buffer_.length(); }
|
||||
|
||||
// Get the current position in the builder.
|
||||
int position() const {
|
||||
ASSERT(!is_finalized());
|
||||
return position_;
|
||||
}
|
||||
|
||||
// Reset the position.
|
||||
void Reset() { position_ = 0; }
|
||||
|
||||
// Add a single character to the builder. It is not allowed to add
|
||||
// 0-characters; use the Finalize() method to terminate the string
|
||||
// instead.
|
||||
void AddCharacter(char c) {
|
||||
ASSERT(c != '\0');
|
||||
ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_++] = c;
|
||||
}
|
||||
|
||||
// Add an entire string to the builder. Uses strlen() internally to
|
||||
// compute the length of the input string.
|
||||
void AddString(const char* s) {
|
||||
AddSubstring(s, StrLength(s));
|
||||
}
|
||||
|
||||
// Add the first 'n' characters of the given string 's' to the
|
||||
// builder. The input string must have enough characters.
|
||||
void AddSubstring(const char* s, int n) {
|
||||
ASSERT(!is_finalized() && position_ + n < buffer_.length());
|
||||
ASSERT(static_cast<size_t>(n) <= strlen(s));
|
||||
memmove(&buffer_[position_], s, n * kCharSize);
|
||||
position_ += n;
|
||||
}
|
||||
|
||||
|
||||
// Add character padding to the builder. If count is non-positive,
|
||||
// nothing is added to the builder.
|
||||
void AddPadding(char c, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
AddCharacter(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the string by 0-terminating it and returning the buffer.
|
||||
char* Finalize() {
|
||||
ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_] = '\0';
|
||||
// Make sure nobody managed to add a 0-character to the
|
||||
// buffer while building the string.
|
||||
ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
|
||||
position_ = -1;
|
||||
ASSERT(is_finalized());
|
||||
return buffer_.start();
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<char> buffer_;
|
||||
int position_;
|
||||
|
||||
bool is_finalized() const { return position_ < 0; }
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
};
|
||||
|
||||
// The type-based aliasing rule allows the compiler to assume that pointers of
|
||||
// different types (for some definition of different) never alias each other.
|
||||
// Thus the following code does not work:
|
||||
//
|
||||
// float f = foo();
|
||||
// int fbits = *(int*)(&f);
|
||||
//
|
||||
// The compiler 'knows' that the int pointer can't refer to f since the types
|
||||
// don't match, so the compiler may cache f in a register, leaving random data
|
||||
// in fbits. Using C++ style casts makes no difference, however a pointer to
|
||||
// char data is assumed to alias any other pointer. This is the 'memcpy
|
||||
// exception'.
|
||||
//
|
||||
// Bit_cast uses the memcpy exception to move the bits from a variable of one
|
||||
// type of a variable of another type. Of course the end result is likely to
|
||||
// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
|
||||
// will completely optimize BitCast away.
|
||||
//
|
||||
// There is an additional use for BitCast.
|
||||
// Recent gccs will warn when they see casts that may result in breakage due to
|
||||
// the type-based aliasing rule. If you have checked that there is no breakage
|
||||
// you can use BitCast to cast one pointer type to another. This confuses gcc
|
||||
// enough that it can no longer see that you have cast one pointer type to
|
||||
// another thus avoiding the warning.
|
||||
template <class Dest, class Source>
|
||||
inline Dest BitCast(const Source& source) {
|
||||
static_assert(sizeof(Dest) == sizeof(Source),
|
||||
"BitCast's source and destination types must be the same size");
|
||||
|
||||
Dest dest;
|
||||
memmove(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class Dest, class Source>
|
||||
inline Dest BitCast(Source* source) {
|
||||
return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_UTILS_H_
|
||||
Reference in New Issue
Block a user