--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -65,17 +65,17 @@ nsDOMMultipartFile::GetSize(PRUint64* aL
PRUint64 l = 0;
nsresult rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
length += l;
}
- NS_ENSURE_TRUE(length.valid(), NS_ERROR_FAILURE);
+ NS_ENSURE_TRUE(length.isValid(), NS_ERROR_FAILURE);
mLength = length.value();
}
*aLength = mLength;
return NS_OK;
}
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -34,19 +34,18 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMBlobBuilder_h
#define nsDOMBlobBuilder_h
#include "nsDOMFile.h"
-#include "CheckedInt.h"
-#include "mozilla/StandardInteger.h"
+#include "mozilla/CheckedInt.h"
using namespace mozilla;
class nsDOMMultipartFile : public nsDOMFileBase,
public nsIJSNativeInitializer
{
public:
// Create as a file
@@ -123,20 +122,20 @@ protected:
{
if (mDataBufferLen >= mDataLen + aSize) {
mDataLen += aSize;
return true;
}
// Start at 1 or we'll loop forever.
CheckedUint32 bufferLen = NS_MAX<PRUint32>(mDataBufferLen, 1);
- while (bufferLen.valid() && bufferLen.value() < mDataLen + aSize)
+ while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize)
bufferLen *= 2;
- if (!bufferLen.valid())
+ if (!bufferLen.isValid())
return false;
// PR_ memory functions are still fallible
void* data = PR_Realloc(mData, bufferLen.value());
if (!data)
return false;
mData = data;
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -56,18 +56,18 @@
#include "nsISeekableStream.h"
#include "nsIUnicharInputStream.h"
#include "nsIUnicodeDecoder.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIUUIDGenerator.h"
#include "nsBlobProtocolHandler.h"
#include "nsStringStream.h"
-#include "CheckedInt.h"
#include "nsJSUtils.h"
+#include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h"
#include "plbase64.h"
#include "prmem.h"
#include "dombindings.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -222,17 +222,17 @@ ParseSize(PRInt64 aSize, PRInt64& aStart
}
else if (aEnd < 0) {
newEndOffset += aSize;
}
else if (aEnd > aSize) {
newEndOffset = aSize;
}
- if (!newStartOffset.valid() || !newEndOffset.valid() ||
+ if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
newStartOffset.value() >= newEndOffset.value()) {
aStart = aEnd = 0;
}
else {
aStart = newStartOffset.value();
aEnd = newEndOffset.value();
}
}
--- a/content/canvas/src/CanvasUtils.h
+++ b/content/canvas/src/CanvasUtils.h
@@ -35,17 +35,17 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _CANVASUTILS_H_
#define _CANVASUTILS_H_
#include "prtypes.h"
-#include "CheckedInt.h"
+#include "mozilla/CheckedInt.h"
class nsHTMLCanvasElement;
class nsIPrincipal;
namespace mozilla {
namespace gfx {
class Matrix;
@@ -58,19 +58,19 @@ using namespace gfx;
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
inline bool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
PRInt32 realWidth, PRInt32 realHeight) {
CheckedInt32 checked_xmost = CheckedInt32(x) + w;
CheckedInt32 checked_ymost = CheckedInt32(y) + h;
return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
- checked_xmost.valid() &&
+ checked_xmost.isValid() &&
checked_xmost.value() <= realWidth &&
- checked_ymost.valid() &&
+ checked_ymost.isValid() &&
checked_ymost.value() <= realHeight;
}
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
// onto it would make it such.
void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -35,17 +35,17 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDOMError.h"
#include "nsIDOMCanvasRenderingContext2D.h"
-#include "CheckedInt.h"
+#include "mozilla/CheckedInt.h"
#include "nsMathUtils.h"
#include "CustomQS_Canvas.h"
#include "jsapi.h"
#include "jsfriendapi.h"
typedef NS_STDCALL_FUNCPROTO(nsresult, CanvasStyleSetterType, nsIDOMCanvasRenderingContext2D,
SetStrokeStyle_multi, (const nsAString &, nsISupports *));
@@ -164,17 +164,17 @@ CreateImageData(JSContext* cx, JSObject*
using mozilla::CheckedInt;
if (w == 0)
w = 1;
if (h == 0)
h = 1;
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(w) * h * 4;
- if (!len.valid()) {
+ if (!len.isValid()) {
return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
}
// Create the fast typed array; it's initialized to 0 by default.
JSObject* darray = JS_NewUint8ClampedArray(cx, len.value());
JS::AutoObjectRooter rd(cx, darray);
if (!darray) {
return false;
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -420,17 +420,17 @@ WebGLContext::SetDimensions(PRInt32 widt
// We're going to create an entirely new context. If our
// generation is not 0 right now (that is, if this isn't the first
// context we're creating), we may have to dispatch a context lost
// event.
// If incrementing the generation would cause overflow,
// don't allow it. Allowing this would allow us to use
// resource handles created from older context generations.
- if (!(mGeneration+1).valid())
+ if (!(mGeneration + 1).isValid())
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
gl::ContextFormat format(gl::ContextFormat::BasicRGBA32);
if (mOptions.depth) {
format.depth = 24;
format.minDepth = 16;
}
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -59,19 +59,19 @@
#include "nsIJSNativeInitializer.h"
#include "nsContentUtils.h"
#include "nsWrapperCache.h"
#include "nsIObserver.h"
#include "GLContextProvider.h"
#include "Layers.h"
-#include "CheckedInt.h"
#include "nsDataHashtable.h"
+#include "mozilla/CheckedInt.h"
#include "mozilla/dom/ImageData.h"
#ifdef XP_MACOSX
#include "ForceDiscreteGPUHelperCGL.h"
#endif
#include "angle/ShaderLang.h"
@@ -476,17 +476,17 @@ public:
{
mArray.RemoveElementSorted(Entry(ElementType(), monotonicHandle),
typename Entry::Comparator());
}
private:
WebGLMonotonicHandle NextMonotonicHandle() {
++mCurrentMonotonicHandle;
- if (!mCurrentMonotonicHandle.valid())
+ if (!mCurrentMonotonicHandle.isValid())
NS_RUNTIMEABORT("ran out of monotonic ids!");
return mCurrentMonotonicHandle.value();
}
nsTArray<Entry> mArray;
CheckedInt<WebGLMonotonicHandle> mCurrentMonotonicHandle;
};
@@ -1743,17 +1743,17 @@ public:
}
const ImageInfo& ImageInfoAt(size_t level, size_t face) const {
return const_cast<WebGLTexture*>(this)->ImageInfoAt(level, face);
}
bool HasImageInfoAt(size_t level, size_t face) const {
CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
- return checked_index.valid() &&
+ return checked_index.isValid() &&
checked_index.value() < mImageInfos.Length() &&
ImageInfoAt(level, face).mIsDefined;
}
static size_t FaceForTarget(WebGLenum target) {
return target == LOCAL_GL_TEXTURE_2D ? 0 : target - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
}
@@ -2323,17 +2323,17 @@ public:
bool HasBothShaderTypesAttached() {
return
HasAttachedShaderOfType(LOCAL_GL_VERTEX_SHADER) &&
HasAttachedShaderOfType(LOCAL_GL_FRAGMENT_SHADER);
}
bool NextGeneration()
{
- if (!(mGeneration+1).valid())
+ if (!(mGeneration + 1).isValid())
return false; // must exit without changing mGeneration
++mGeneration;
return true;
}
/* Called only after LinkProgram */
bool UpdateInfo();
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -682,17 +682,17 @@ WebGLContext::BufferSubData(GLenum targe
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
if (!boundBuffer)
return ErrorInvalidOperation("BufferData: no buffer bound!");
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data->mLength;
- if (!checked_neededByteLength.valid())
+ if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
return ErrorInvalidOperation("BufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
checked_neededByteLength.value(), boundBuffer->ByteLength());
MakeContextCurrent();
@@ -721,17 +721,17 @@ WebGLContext::BufferSubData(WebGLenum ta
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
if (!boundBuffer)
return ErrorInvalidOperation("BufferSubData: no buffer bound!");
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.mLength;
- if (!checked_neededByteLength.valid())
+ if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
return ErrorInvalidOperation("BufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
checked_neededByteLength.value(), boundBuffer->ByteLength());
MakeContextCurrent();
@@ -936,17 +936,17 @@ WebGLContext::CopyTexSubImage2D_base(Web
PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(internalformat, LOCAL_GL_UNSIGNED_BYTE, -1, &texelSize, info))
return;
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
- if (!checked_neededByteLength.valid())
+ if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("%s: integer overflow computing the needed buffer size", info);
PRUint32 bytesNeeded = checked_neededByteLength.value();
// now that the size is known, create the buffer
// We need some zero pages, because GL doesn't guarantee the
// contents of a texture allocated with NULL data.
@@ -1557,17 +1557,17 @@ WebGLContext::DoFakeVertexAttrib0(WebGLu
{
int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
return true;
CheckedUint32 checked_dataSize = CheckedUint32(vertexCount) * 4 * sizeof(WebGLfloat);
- if (!checked_dataSize.valid()) {
+ if (!checked_dataSize.isValid()) {
ErrorOutOfMemory("Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation "
"with %d vertices. Try reducing the number of vertices.", vertexCount);
return false;
}
WebGLuint dataSize = checked_dataSize.value();
if (!mFakeVertexAttrib0BufferObject) {
@@ -1774,17 +1774,17 @@ WebGLContext::DrawArrays(GLenum mode, We
return;
PRInt32 maxAllowedCount = 0;
if (!ValidateBuffers(&maxAllowedCount, "drawArrays"))
return;
CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
- if (!checked_firstPlusCount.valid())
+ if (!checked_firstPlusCount.isValid())
return ErrorInvalidOperation("drawArrays: overflow in first+count");
if (checked_firstPlusCount.value() > maxAllowedCount)
return ErrorInvalidOperation("drawArrays: bound vertex attribute buffers do not have sufficient size for given first and count");
MakeContextCurrent();
if (mBoundFramebuffer) {
@@ -1842,63 +1842,63 @@ WebGLContext::DrawElements(WebGLenum mod
if (byteOffset % 2 != 0)
return ErrorInvalidOperation("DrawElements: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)");
} else if (type == LOCAL_GL_UNSIGNED_BYTE) {
checked_byteCount = count;
} else {
return ErrorInvalidEnum("DrawElements: type must be UNSIGNED_SHORT or UNSIGNED_BYTE");
}
- if (!checked_byteCount.valid())
+ if (!checked_byteCount.isValid())
return ErrorInvalidValue("DrawElements: overflow in byteCount");
// If there is no current program, this is silently ignored.
// Any checks below this depend on a program being available.
if (!mCurrentProgram)
return;
if (!mBoundElementArrayBuffer)
return ErrorInvalidOperation("DrawElements: must have element array buffer binding");
if (!mBoundElementArrayBuffer->Data())
return ErrorInvalidOperation("drawElements: bound element array buffer doesn't have any data");
CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
- if (!checked_neededByteCount.valid())
+ if (!checked_neededByteCount.isValid())
return ErrorInvalidOperation("DrawElements: overflow in byteOffset+byteCount");
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
return ErrorInvalidOperation("DrawElements: bound element array buffer is too small for given count and offset");
PRInt32 maxAllowedCount = 0;
if (!ValidateBuffers(&maxAllowedCount, "drawElements"))
return;
PRInt32 maxIndex
= type == LOCAL_GL_UNSIGNED_SHORT
? mBoundElementArrayBuffer->FindMaxUshortElement()
: mBoundElementArrayBuffer->FindMaxUbyteElement();
CheckedInt32 checked_maxIndexPlusOne = CheckedInt32(maxIndex) + 1;
- if (!checked_maxIndexPlusOne.valid() ||
+ if (!checked_maxIndexPlusOne.isValid() ||
checked_maxIndexPlusOne.value() > maxAllowedCount)
{
// the index array contains invalid indices for the current drawing state, but they
// might not be used by the present drawElements call, depending on first and count.
PRInt32 maxIndexInSubArray
= type == LOCAL_GL_UNSIGNED_SHORT
? mBoundElementArrayBuffer->FindMaxElementInSubArray<GLushort>(count, byteOffset)
: mBoundElementArrayBuffer->FindMaxElementInSubArray<GLubyte>(count, byteOffset);
CheckedInt32 checked_maxIndexInSubArrayPlusOne = CheckedInt32(maxIndexInSubArray) + 1;
- if (!checked_maxIndexInSubArrayPlusOne.valid() ||
+ if (!checked_maxIndexInSubArrayPlusOne.isValid() ||
checked_maxIndexInSubArrayPlusOne.value() > maxAllowedCount)
{
return ErrorInvalidOperation(
"DrawElements: bound vertex attribute buffers do not have sufficient "
"size for given indices from the bound element array");
}
}
@@ -3878,17 +3878,17 @@ WebGLContext::ReadPixels(WebGLint x, Web
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, bytesPerPixel, mPixelStorePackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * bytesPerPixel;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize, mPixelStorePackAlignment);
- if (!checked_neededByteLength.valid())
+ if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
if (checked_neededByteLength.value() > dataByteLen)
return ErrorInvalidOperation("ReadPixels: buffer too small");
// Check the format and type params to assure they are an acceptable pair (as per spec)
switch (format) {
case LOCAL_GL_RGBA: {
@@ -5596,17 +5596,17 @@ WebGLContext::TexImage2D_base(WebGLenum
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
- if (!checked_neededByteLength.valid())
+ if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texImage2D: integer overflow computing the needed buffer size");
PRUint32 bytesNeeded = checked_neededByteLength.value();
if (byteLength && byteLength < bytesNeeded)
return ErrorInvalidOperation("TexImage2D: not enough data for operation (need %d, have %d)",
bytesNeeded, byteLength);
@@ -5837,17 +5837,17 @@ WebGLContext::TexSubImage2D_base(WebGLen
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
- if (!checked_neededByteLength.valid())
+ if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
PRUint32 bytesNeeded = checked_neededByteLength.value();
if (byteLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
WebGLTexture *tex = activeBoundTextureForTarget(target);
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -35,18 +35,17 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "WebGLContext.h"
#include "mozilla/Preferences.h"
-
-#include "CheckedInt.h"
+#include "mozilla/CheckedInt.h"
#include "jsfriendapi.h"
#if defined(USE_ANGLE)
#include "angle/ShaderLang.h"
#endif
#include <algorithm>
@@ -138,30 +137,30 @@ WebGLContext::ValidateBuffers(PRInt32 *m
continue;
// the base offset
CheckedInt32 checked_byteLength
= CheckedInt32(vd.buf->ByteLength()) - vd.byteOffset;
CheckedInt32 checked_sizeOfLastElement
= CheckedInt32(vd.componentSize()) * vd.size;
- if (!checked_byteLength.valid() ||
- !checked_sizeOfLastElement.valid())
+ if (!checked_byteLength.isValid() ||
+ !checked_sizeOfLastElement.isValid())
{
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return false;
}
if (checked_byteLength.value() < checked_sizeOfLastElement.value()) {
*maxAllowedCount = 0;
} else {
CheckedInt32 checked_maxAllowedCount
= ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
- if (!checked_maxAllowedCount.valid()) {
+ if (!checked_maxAllowedCount.isValid()) {
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return false;
}
if (*maxAllowedCount == -1 || *maxAllowedCount > checked_maxAllowedCount.value())
*maxAllowedCount = checked_maxAllowedCount.value();
}
}
@@ -396,37 +395,37 @@ bool WebGLContext::ValidateTexImage2DTar
return true;
}
bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width,
WebGLsizei height, uint32_t byteLength, const char* info)
{
CheckedUint32 calculated_byteLength = 0;
CheckedUint32 checked_byteLength = byteLength;
- if (!checked_byteLength.valid()) {
+ if (!checked_byteLength.isValid()) {
ErrorInvalidValue("%s: data length out of bounds", info);
return false;
}
switch (format) {
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
{
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
- if (!calculated_byteLength.valid() || !(checked_byteLength == calculated_byteLength)) {
+ if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
ErrorInvalidValue("%s: data size does not match dimensions", info);
return false;
}
break;
}
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
{
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
- if (!calculated_byteLength.valid() || !(checked_byteLength == calculated_byteLength)) {
+ if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
ErrorInvalidValue("%s: data size does not match dimensions", info);
return false;
}
break;
}
}
switch (format) {
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -103,24 +103,24 @@
#include "nsFrameLoader.h"
#include "nsBidi.h"
#include "nsBidiPresUtils.h"
#include "Layers.h"
#include "CanvasUtils.h"
#include "nsIMemoryReporter.h"
#include "nsStyleUtil.h"
#include "CanvasImageCache.h"
-#include "CheckedInt.h"
#include <algorithm>
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/Assertions.h"
+#include "mozilla/CheckedInt.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/PDocumentRendererParent.h"
// windows.h (included by chromium code) defines this, in its infinite wisdom
#undef DrawText
@@ -3921,24 +3921,24 @@ nsCanvasRenderingContext2D::GetImageData
int32_t aY,
uint32_t aWidth,
uint32_t aHeight,
JSObject** aRetval)
{
MOZ_ASSERT(aWidth && aHeight);
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
- if (!len.valid()) {
+ if (!len.isValid()) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
- if (!rightMost.valid() || !bottomMost.valid()) {
+ if (!rightMost.isValid() || !bottomMost.isValid()) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
if (!darray) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -4061,29 +4061,29 @@ nsCanvasRenderingContext2D::PutImageData
if (hasDirtyRect) {
// fix up negative dimensions
if (dirtyWidth < 0) {
NS_ENSURE_TRUE(dirtyWidth != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
CheckedInt32 checkedDirtyX = CheckedInt32(dirtyX) + dirtyWidth;
- if (!checkedDirtyX.valid())
+ if (!checkedDirtyX.isValid())
return NS_ERROR_DOM_INDEX_SIZE_ERR;
dirtyX = checkedDirtyX.value();
dirtyWidth = -(int32)dirtyWidth;
}
if (dirtyHeight < 0) {
NS_ENSURE_TRUE(dirtyHeight != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
CheckedInt32 checkedDirtyY = CheckedInt32(dirtyY) + dirtyHeight;
- if (!checkedDirtyY.valid())
+ if (!checkedDirtyY.isValid())
return NS_ERROR_DOM_INDEX_SIZE_ERR;
dirtyY = checkedDirtyY.value();
dirtyHeight = -(int32)dirtyHeight;
}
// bound the dirty rect within the imageData rectangle
dirtyRect = imageDataRect.Intersect(gfxRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight));
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -99,24 +99,24 @@
#include "nsFrameLoader.h"
#include "nsBidi.h"
#include "nsBidiPresUtils.h"
#include "Layers.h"
#include "CanvasUtils.h"
#include "nsIMemoryReporter.h"
#include "nsStyleUtil.h"
#include "CanvasImageCache.h"
-#include "CheckedInt.h"
#include <algorithm>
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/Assertions.h"
+#include "mozilla/CheckedInt.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/PDocumentRendererParent.h"
#include "mozilla/Preferences.h"
@@ -4090,24 +4090,24 @@ nsCanvasRenderingContext2DAzure::GetImag
int32_t aY,
uint32_t aWidth,
uint32_t aHeight,
JSObject** aRetval)
{
MOZ_ASSERT(aWidth && aHeight);
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
- if (!len.valid()) {
+ if (!len.isValid()) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
- if (!rightMost.valid() || !bottomMost.valid()) {
+ if (!rightMost.isValid() || !bottomMost.isValid()) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
if (!darray) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -4228,29 +4228,29 @@ nsCanvasRenderingContext2DAzure::PutImag
if (hasDirtyRect) {
// fix up negative dimensions
if (dirtyWidth < 0) {
NS_ENSURE_TRUE(dirtyWidth != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
CheckedInt32 checkedDirtyX = CheckedInt32(dirtyX) + dirtyWidth;
- if (!checkedDirtyX.valid())
+ if (!checkedDirtyX.isValid())
return NS_ERROR_DOM_INDEX_SIZE_ERR;
dirtyX = checkedDirtyX.value();
dirtyWidth = -(int32)dirtyWidth;
}
if (dirtyHeight < 0) {
NS_ENSURE_TRUE(dirtyHeight != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
CheckedInt32 checkedDirtyY = CheckedInt32(dirtyY) + dirtyHeight;
- if (!checkedDirtyY.valid())
+ if (!checkedDirtyY.isValid())
return NS_ERROR_DOM_INDEX_SIZE_ERR;
dirtyY = checkedDirtyY.value();
dirtyHeight = -(int32)dirtyHeight;
}
// bound the dirty rect within the imageData rectangle
dirtyRect = imageDataRect.Intersect(IntRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight));
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -33,20 +33,20 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLCanvasElement.h"
#include "mozilla/Base64.h"
+#include "mozilla/CheckedInt.h"
#include "nsNetUtil.h"
#include "prmem.h"
#include "nsDOMFile.h"
-#include "CheckedInt.h"
#include "nsIScriptSecurityManager.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsContentUtils.h"
#include "nsJSUtils.h"
#include "nsMathUtils.h"
#include "nsStreamUtils.h"
--- a/content/media/VideoUtils.h
+++ b/content/media/VideoUtils.h
@@ -35,23 +35,22 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef VideoUtils_h
#define VideoUtils_h
#include "mozilla/ReentrantMonitor.h"
+#include "mozilla/CheckedInt.h"
#include "nsRect.h"
#include "nsIThreadManager.h"
#include "nsThreadUtils.h"
-#include "CheckedInt.h"
-
using mozilla::CheckedInt64;
using mozilla::CheckedUint64;
using mozilla::CheckedInt32;
using mozilla::CheckedUint32;
// This file contains stuff we'd rather put elsewhere, but which is
// dependent on other changes which we don't want to wait for. We plan to
// remove this file in the near future.
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -159,18 +159,18 @@ VideoData* VideoData::Create(nsVideoInfo
NS_WARNING("Invalid plane size");
return nsnull;
}
// Ensure the picture size specified in the headers can be extracted out of
// the frame we've been supplied without indexing out of bounds.
CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
- if (!xLimit.valid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
- !yLimit.valid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
+ if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
+ !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
{
// The specified picture dimensions can't be contained inside the video
// frame, we'll stomp memory if we try to copy it. Fail.
NS_WARNING("Overflowing picture rect");
return nsnull;
}
nsAutoPtr<VideoData> v(new VideoData(aOffset,
@@ -341,17 +341,17 @@ nsresult nsBuiltinDecoderReader::DecodeT
}
}
}
const AudioData* audio = mAudioQueue.PeekFront();
if (!audio)
break;
CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudioRate);
CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudioRate);
- if (!startFrame.valid() || !targetFrame.valid()) {
+ if (!startFrame.isValid() || !targetFrame.isValid()) {
return NS_ERROR_FAILURE;
}
if (startFrame.value() + audio->mFrames <= targetFrame.value()) {
// Our seek target lies after the frames in this AudioData. Pop it
// off the queue, and keep decoding forwards.
delete mAudioQueue.PopFront();
audio = nsnull;
continue;
@@ -385,17 +385,17 @@ nsresult nsBuiltinDecoderReader::DecodeT
}
PRUint32 frames = audio->mFrames - static_cast<PRUint32>(framesToPrune);
PRUint32 channels = audio->mChannels;
nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[frames * channels]);
memcpy(audioData.get(),
audio->mAudioData.get() + (framesToPrune * channels),
frames * channels * sizeof(AudioDataValue));
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudioRate);
- if (!duration.valid()) {
+ if (!duration.isValid()) {
return NS_ERROR_FAILURE;
}
nsAutoPtr<AudioData> data(new AudioData(audio->mOffset,
aTarget,
duration.value(),
frames,
audioData.forget(),
channels));
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -542,17 +542,17 @@ void nsBuiltinDecoderStateMachine::SendO
NS_ASSERTION(aOutput->GetChannels() == aAudio->mChannels,
"Wrong number of channels");
// This logic has to mimic AudioLoop closely to make sure we write
// the exact same silences
CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudioRate,
aStream->mAudioFramesWrittenBaseTime + mStartTime) + aStream->mAudioFramesWritten;
CheckedInt64 frameOffset = UsecsToFrames(mInfo.mAudioRate, aAudio->mTime);
- if (!audioWrittenOffset.valid() || !frameOffset.valid())
+ if (!audioWrittenOffset.isValid() || !frameOffset.isValid())
return;
if (audioWrittenOffset.value() < frameOffset.value()) {
// Write silence to catch up
LOG(PR_LOG_DEBUG, ("%p Decoder writing %d frames of silence to MediaStream",
mDecoder.get(), PRInt32(frameOffset.value() - audioWrittenOffset.value())));
AudioSegment silence;
silence.InitFrom(*aOutput);
silence.InsertNullDataAtStart(frameOffset.value() - audioWrittenOffset.value());
@@ -1110,17 +1110,17 @@ void nsBuiltinDecoderStateMachine::Audio
// Calculate the number of frames that have been pushed onto the audio
// hardware.
CheckedInt64 playedFrames = UsecsToFrames(audioStartTime, rate) +
audioDuration;
// Calculate the timestamp of the next chunk of audio in numbers of
// samples.
CheckedInt64 sampleTime = UsecsToFrames(s->mTime, rate);
CheckedInt64 missingFrames = sampleTime - playedFrames;
- if (!missingFrames.valid() || !sampleTime.valid()) {
+ if (!missingFrames.isValid() || !sampleTime.isValid()) {
NS_WARNING("Int overflow adding in AudioLoop()");
break;
}
PRInt64 framesWritten = 0;
if (missingFrames.value() > 0) {
// The next audio chunk begins some time after the end of the last chunk
// we pushed to the audio hardware. We must push silence into the audio
@@ -1134,17 +1134,17 @@ void nsBuiltinDecoderStateMachine::Audio
channels, playedFrames.value());
} else {
framesWritten = PlayFromAudioQueue(sampleTime.value(), channels);
}
audioDuration += framesWritten;
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
CheckedInt64 playedUsecs = FramesToUsecs(audioDuration, rate) + audioStartTime;
- if (!playedUsecs.valid()) {
+ if (!playedUsecs.isValid()) {
NS_WARNING("Int overflow calculating audio end time");
break;
}
mAudioEndTime = playedUsecs.value();
}
}
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -348,28 +348,28 @@ PRInt64 nsTheoraState::Time(th_info* aIn
}
// Implementation of th_granule_frame inlined here to operate
// on the th_info structure instead of the theora_state.
int shift = aInfo->keyframe_granule_shift;
ogg_int64_t iframe = aGranulepos >> shift;
ogg_int64_t pframe = aGranulepos - (iframe << shift);
PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
CheckedInt64 t = ((CheckedInt64(frameno) + 1) * USECS_PER_S) * aInfo->fps_denominator;
- if (!t.valid())
+ if (!t.isValid())
return -1;
t /= aInfo->fps_numerator;
- return t.valid() ? t.value() : -1;
+ return t.isValid() ? t.value() : -1;
}
PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) {
return -1;
}
CheckedInt64 t = (CheckedInt64(th_granule_frame(mCtx, granulepos)) * USECS_PER_S) * mInfo.fps_denominator;
- if (!t.valid())
+ if (!t.isValid())
return -1;
return t.value() / mInfo.fps_numerator;
}
PRInt64
nsTheoraState::MaxKeyframeOffset()
{
// Determine the maximum time in microseconds by which a key frame could
@@ -617,17 +617,17 @@ PRInt64 nsVorbisState::Time(PRInt64 gran
}
PRInt64 nsVorbisState::Time(vorbis_info* aInfo, PRInt64 aGranulepos)
{
if (aGranulepos == -1 || aInfo->rate == 0) {
return -1;
}
CheckedInt64 t = CheckedInt64(aGranulepos) * USECS_PER_S;
- if (!t.valid())
+ if (!t.isValid())
t = 0;
return t.value() / aInfo->rate;
}
bool
nsVorbisState::IsHeader(ogg_packet* aPacket)
{
// The first byte in each Vorbis header packet is either 0x01, 0x03, or 0x05,
@@ -879,17 +879,17 @@ bool nsOpusState::DecodeHeader(ogg_packe
/* Return the timestamp (in microseconds) equivalent to a granulepos. */
PRInt64 nsOpusState::Time(PRInt64 granulepos)
{
if (!mActive || granulepos < 0)
return -1;
// Ogg Opus always runs at a granule rate of 48 kHz.
CheckedInt64 t = CheckedInt64(granulepos - mPreSkip) * USECS_PER_S;
- return t.valid() ? t.value() / mRate : -1;
+ return t.isValid() ? t.value() / mRate : -1;
}
bool nsOpusState::IsHeader(ogg_packet* aPacket)
{
return aPacket->bytes >= 16 &&
(!memcmp(aPacket->packet, "OpusHead\0", 9) ||
!memcmp(aPacket->packet, "OpusTags", 8));
}
@@ -1043,34 +1043,34 @@ bool nsSkeletonState::DecodeIndex(ogg_pa
if (timeDenom == 0) {
LOG(PR_LOG_DEBUG, ("Ogg Skeleton Index packet for stream %u has 0 "
"timestamp denominator.", serialno));
return (mActive = false);
}
// Extract the start time.
CheckedInt64 t = CheckedInt64(LEInt64(p + INDEX_FIRST_NUMER_OFFSET)) * USECS_PER_S;
- if (!t.valid()) {
+ if (!t.isValid()) {
return (mActive = false);
} else {
startTime = t.value() / timeDenom;
}
// Extract the end time.
t = LEInt64(p + INDEX_LAST_NUMER_OFFSET) * USECS_PER_S;
- if (!t.valid()) {
+ if (!t.isValid()) {
return (mActive = false);
} else {
endTime = t.value() / timeDenom;
}
// Check the numKeyPoints value read, ensure we're not going to run out of
// memory while trying to decode the index packet.
CheckedInt64 minPacketSize = (CheckedInt64(numKeyPoints) * MIN_KEY_POINT_SIZE) + INDEX_KEYPOINT_OFFSET;
- if (!minPacketSize.valid())
+ if (!minPacketSize.isValid())
{
return (mActive = false);
}
PRInt64 sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET;
PRInt64 maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE;
if (aPacket->bytes < minPacketSize.value() ||
numKeyPoints > maxNumKeyPoints ||
@@ -1098,32 +1098,32 @@ bool nsSkeletonState::DecodeIndex(ogg_pa
CheckedInt64 time = 0;
while (p < limit &&
numKeyPointsRead < numKeyPoints)
{
PRInt64 delta = 0;
p = ReadVariableLengthInt(p, limit, delta);
offset += delta;
if (p == limit ||
- !offset.valid() ||
+ !offset.isValid() ||
offset.value() > mLength ||
offset.value() < 0)
{
return (mActive = false);
}
p = ReadVariableLengthInt(p, limit, delta);
time += delta;
- if (!time.valid() ||
+ if (!time.isValid() ||
time.value() > endTime ||
time.value() < startTime)
{
return (mActive = false);
}
CheckedInt64 timeUsecs = time * USECS_PER_S;
- if (!timeUsecs.valid())
+ if (!timeUsecs.isValid())
return mActive = false;
timeUsecs /= timeDenom;
keyPoints->Add(offset.value(), timeUsecs.value());
numKeyPointsRead++;
}
PRInt32 keyPointsRead = keyPoints->Length();
if (keyPointsRead > 0) {
@@ -1223,18 +1223,18 @@ nsresult nsSkeletonState::GetDuration(co
endTime = index->mEndTime;
}
if (index->mStartTime < startTime) {
startTime = index->mStartTime;
}
}
NS_ASSERTION(endTime > startTime, "Duration must be positive");
CheckedInt64 duration = CheckedInt64(endTime) - startTime;
- aDuration = duration.valid() ? duration.value() : 0;
- return duration.valid() ? NS_OK : NS_ERROR_FAILURE;
+ aDuration = duration.isValid() ? duration.value() : 0;
+ return duration.isValid() ? NS_OK : NS_ERROR_FAILURE;
}
bool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
{
if (IsSkeletonBOS(aPacket)) {
PRUint16 verMajor = LEUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
PRUint16 verMinor = LEUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);
--- a/content/media/raw/nsRawReader.cpp
+++ b/content/media/raw/nsRawReader.cpp
@@ -82,17 +82,17 @@ nsresult nsRawReader::ReadMetadata(nsVid
if (!(mMetadata.headerPacketID == 0 /* Packet ID of 0 for the header*/ &&
mMetadata.codecID == RAW_ID /* "YUV" */ &&
mMetadata.majorVersion == 0 &&
mMetadata.minorVersion == 1))
return NS_ERROR_FAILURE;
CheckedUint32 dummy = CheckedUint32(static_cast<PRUint32>(mMetadata.frameWidth)) *
static_cast<PRUint32>(mMetadata.frameHeight);
- NS_ENSURE_TRUE(dummy.valid(), NS_ERROR_FAILURE);
+ NS_ENSURE_TRUE(dummy.isValid(), NS_ERROR_FAILURE);
if (mMetadata.aspectDenominator == 0 ||
mMetadata.framerateDenominator == 0)
return NS_ERROR_FAILURE; // Invalid data
// Determine and verify frame display size.
float pixelAspectRatio = static_cast<float>(mMetadata.aspectNumerator) /
mMetadata.aspectDenominator;
@@ -263,17 +263,17 @@ nsresult nsRawReader::Seek(PRInt64 aTime
PRUint32 frame = mCurrentFrame;
if (aTime >= UINT_MAX)
return NS_ERROR_FAILURE;
mCurrentFrame = aTime * mFrameRate / USECS_PER_S;
CheckedUint32 offset = CheckedUint32(mCurrentFrame) * mFrameSize;
offset += sizeof(nsRawVideoHeader);
- NS_ENSURE_TRUE(offset.valid(), NS_ERROR_FAILURE);
+ NS_ENSURE_TRUE(offset.isValid(), NS_ERROR_FAILURE);
nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset.value());
NS_ENSURE_SUCCESS(rv, rv);
mVideoQueue.Erase();
while(mVideoQueue.GetSize() == 0) {
bool keyframeSkip = false;
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -443,30 +443,30 @@ bool nsWebMReader::DecodeAudioPacket(nes
mAudioStartUsec = tstamp_usecs;
}
// If there's a gap between the start of this audio chunk and the end of
// the previous audio chunk, we need to increment the packet count so that
// the vorbis decode doesn't use data from before the gap to help decode
// from after the gap.
CheckedInt64 tstamp_frames = UsecsToFrames(tstamp_usecs, rate);
CheckedInt64 decoded_frames = UsecsToFrames(mAudioStartUsec, rate);
- if (!tstamp_frames.valid() || !decoded_frames.valid()) {
+ if (!tstamp_frames.isValid() || !decoded_frames.isValid()) {
NS_WARNING("Int overflow converting WebM times to frames");
return false;
}
decoded_frames += mAudioFrames;
- if (!decoded_frames.valid()) {
+ if (!decoded_frames.isValid()) {
NS_WARNING("Int overflow adding decoded_frames");
return false;
}
if (tstamp_frames.value() > decoded_frames.value()) {
#ifdef DEBUG
CheckedInt64 usecs = FramesToUsecs(tstamp_frames.value() - decoded_frames.value(), rate);
LOG(PR_LOG_DEBUG, ("WebMReader detected gap of %lld, %lld frames, in audio stream\n",
- usecs.valid() ? usecs.value(): -1,
+ usecs.isValid() ? usecs.value() : -1,
tstamp_frames.value() - decoded_frames.value()));
#endif
mPacketCount++;
mAudioStartUsec = tstamp_usecs;
mAudioFrames = 0;
}
PRInt32 total_frames = 0;
@@ -496,28 +496,28 @@ bool nsWebMReader::DecodeAudioPacket(nes
for (PRUint32 j = 0; j < mChannels; ++j) {
VorbisPCMValue* channel = pcm[j];
for (PRUint32 i = 0; i < PRUint32(frames); ++i) {
buffer[i*mChannels + j] = MOZ_CONVERT_VORBIS_SAMPLE(channel[i]);
}
}
CheckedInt64 duration = FramesToUsecs(frames, rate);
- if (!duration.valid()) {
+ if (!duration.isValid()) {
NS_WARNING("Int overflow converting WebM audio duration");
return false;
}
CheckedInt64 total_duration = FramesToUsecs(total_frames, rate);
- if (!total_duration.valid()) {
+ if (!total_duration.isValid()) {
NS_WARNING("Int overflow converting WebM audio total_duration");
return false;
}
CheckedInt64 time = total_duration + tstamp_usecs;
- if (!time.valid()) {
+ if (!time.isValid()) {
NS_WARNING("Int overflow adding total_duration and tstamp_usecs");
nestegg_free_packet(aPacket);
return false;
};
total_frames += frames;
mAudioQueue.Push(new AudioData(aOffset,
time.value(),
--- a/gfx/2d/Blur.cpp
+++ b/gfx/2d/Blur.cpp
@@ -34,17 +34,17 @@
* ***** END LICENSE BLOCK ***** */
#include "mozilla/gfx/Blur.h"
#include <algorithm>
#include <math.h>
#include <string.h>
-#include "CheckedInt.h"
+#include "mozilla/CheckedInt.h"
#include "mozilla/Util.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
using namespace std;
@@ -76,17 +76,17 @@ BoxBlurHorizontal(unsigned char* aInput,
int32_t boxSize = aLeftLobe + aRightLobe + 1;
bool skipRectCoversWholeRow = 0 >= aSkipRect.x &&
aWidth <= aSkipRect.XMost();
if (boxSize == 1) {
memcpy(aOutput, aInput, aWidth*aRows);
return;
}
- PRUint32 reciprocal = (PRUint64(1) << 32)/boxSize;
+ uint32_t reciprocal = (uint64_t(1) << 32) / boxSize;
for (int32_t y = 0; y < aRows; y++) {
// Check whether the skip rect intersects this row. If the skip
// rect covers the whole surface in this row, we can avoid
// this row entirely (and any others along the skip rect).
bool inSkipRectY = y >= aSkipRect.y &&
y < aSkipRect.YMost();
if (inSkipRectY && skipRectCoversWholeRow) {
@@ -123,17 +123,17 @@ BoxBlurHorizontal(unsigned char* aInput,
pos = min(pos, aWidth - 1);
alphaSum += aInput[aWidth * y + pos];
}
}
int32_t tmp = x - aLeftLobe;
int32_t last = max(tmp, 0);
int32_t next = min(tmp + boxSize, aWidth - 1);
- aOutput[aWidth * y + x] = (PRUint64(alphaSum)*reciprocal) >> 32;
+ aOutput[aWidth * y + x] = (uint64_t(alphaSum) * reciprocal) >> 32;
alphaSum += aInput[aWidth * y + next] -
aInput[aWidth * y + last];
}
}
}
/**
@@ -154,17 +154,17 @@ BoxBlurVertical(unsigned char* aInput,
int32_t boxSize = aTopLobe + aBottomLobe + 1;
bool skipRectCoversWholeColumn = 0 >= aSkipRect.y &&
aRows <= aSkipRect.YMost();
if (boxSize == 1) {
memcpy(aOutput, aInput, aWidth*aRows);
return;
}
- PRUint32 reciprocal = (PRUint64(1) << 32)/boxSize;
+ uint32_t reciprocal = (uint64_t(1) << 32) / boxSize;
for (int32_t x = 0; x < aWidth; x++) {
bool inSkipRectX = x >= aSkipRect.x &&
x < aSkipRect.XMost();
if (inSkipRectX && skipRectCoversWholeColumn) {
x = aSkipRect.XMost() - 1;
continue;
}
@@ -194,17 +194,17 @@ BoxBlurVertical(unsigned char* aInput,
pos = min(pos, aRows - 1);
alphaSum += aInput[aWidth * pos + x];
}
}
int32_t tmp = y - aTopLobe;
int32_t last = max(tmp, 0);
int32_t next = min(tmp + boxSize, aRows - 1);
- aOutput[aWidth * y + x] = (PRUint64(alphaSum)*reciprocal) >> 32;
+ aOutput[aWidth * y + x] = (uint64_t(alphaSum) * reciprocal) >> 32;
alphaSum += aInput[aWidth * next + x] -
aInput[aWidth * last + x];
}
}
}
static void ComputeLobes(int32_t aRadius, int32_t aLobes[3][2])
@@ -404,22 +404,22 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& a
mSkipRect -= shadowIntRect.TopLeft();
} else {
mSkipRect = IntRect(0, 0, 0, 0);
}
mRect = IntRect(rect.x, rect.y, rect.width, rect.height);
CheckedInt<int32_t> stride = RoundUpToMultipleOf4(mRect.width);
- if (stride.valid()) {
+ if (stride.isValid()) {
mStride = stride.value();
CheckedInt<int32_t> size = CheckedInt<int32_t>(mStride) * mRect.height *
sizeof(unsigned char);
- if (size.valid()) {
+ if (size.isValid()) {
mData = static_cast<unsigned char*>(malloc(size.value()));
memset(mData, 0, size.value());
}
}
}
AlphaBoxBlur::~AlphaBoxBlur()
{
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -33,17 +33,17 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIMemoryReporter.h"
#include "nsMemory.h"
-#include "CheckedInt.h"
+#include "mozilla/CheckedInt.h"
#include "gfxASurface.h"
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "nsRect.h"
#include "cairo.h"
@@ -373,25 +373,25 @@ gfxASurface::CheckSurfaceSize(const gfxI
NS_WARNING("Surface size too large (exceeds CoreGraphics limit)!");
return false;
}
#endif
// make sure the surface area doesn't overflow a PRInt32
CheckedInt<PRInt32> tmp = sz.width;
tmp *= sz.height;
- if (!tmp.valid()) {
+ if (!tmp.isValid()) {
NS_WARNING("Surface size too large (would overflow)!");
return false;
}
// assuming 4-byte stride, make sure the allocation size
// doesn't overflow a PRInt32 either
tmp *= 4;
- if (!tmp.valid()) {
+ if (!tmp.isValid()) {
NS_WARNING("Allocation too large (would overflow)!");
return false;
}
return true;
}
/* static */
rename from xpcom/ds/CheckedInt.h
rename to mfbt/CheckedInt.h
--- a/xpcom/ds/CheckedInt.h
+++ b/mfbt/CheckedInt.h
@@ -1,636 +1,789 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla code.
- *
- * The Initial Developer of the Original Code is the Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Benoit Jacob <bjacob@mozilla.com>
- * Jeff Muizelaar <jmuizelaar@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
+/* 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_
-#ifndef mozilla_CheckedInt_h
-#define mozilla_CheckedInt_h
-
-/*** Build options. Comment out these #defines to disable the corresponding optional feature.
- *** Disabling features may be useful for code using CheckedInt outside of Mozilla (e.g. WebKit)
- ***/
+/*
+ * Build options. Comment out these #defines to disable the corresponding
+ * optional feature. Disabling features may be useful for code using
+ * CheckedInt outside of Mozilla (e.g. WebKit)
+ */
-// enable usage of MOZ_STATIC_ASSERT to check for unsupported types.
-// If disabled, static asserts are just removed. You'll still get compile errors, just less helpful ones.
-#define CHECKEDINT_ENABLE_MOZ_ASSERTS
+// Enable usage of MOZ_STATIC_ASSERT to check for unsupported types.
+// If disabled, static asserts are replaced by regular assert().
+#define MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
-/*** End of build options
- ***/
+/*
+ * End of build options
+ */
-#ifdef CHECKEDINT_ENABLE_MOZ_ASSERTS
- #include "mozilla/Assertions.h"
+#ifdef MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
+# include "mozilla/Assertions.h"
#else
- #ifndef MOZ_STATIC_ASSERT
- #include <cassert>
- #define MOZ_STATIC_ASSERT(cond, reason) assert((cond) && reason)
- #endif
+# ifndef MOZ_STATIC_ASSERT
+# include <cassert>
+# define MOZ_STATIC_ASSERT(cond, reason) assert((cond) && reason)
+# define MOZ_ASSERT(cond, reason) assert((cond) && reason)
+# endif
#endif
#include "mozilla/StandardInteger.h"
+
#include <climits>
+#include <cstddef>
namespace mozilla {
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.
- ***/
+/*
+ * 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 unsupported_type {};
+struct UnsupportedType {};
-template<typename integer_type> struct is_supported_pass_2 {
- enum { value = 0 };
+template<typename IntegerType>
+struct IsSupportedPass2
+{
+ static const bool value = false;
};
-template<typename integer_type> struct is_supported {
- enum { value = is_supported_pass_2<integer_type>::value };
+
+template<typename IntegerType>
+struct IsSupported
+{
+ static const bool value = IsSupportedPass2<IntegerType>::value;
};
-template<> struct is_supported<int8_t> { enum { value = 1 }; };
-template<> struct is_supported<uint8_t> { enum { value = 1 }; };
-template<> struct is_supported<int16_t> { enum { value = 1 }; };
-template<> struct is_supported<uint16_t> { enum { value = 1 }; };
-template<> struct is_supported<int32_t> { enum { value = 1 }; };
-template<> struct is_supported<uint32_t> { enum { value = 1 }; };
-template<> struct is_supported<int64_t> { enum { value = 1 }; };
-template<> struct is_supported<uint64_t> { enum { value = 1 }; };
+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 is_supported_pass_2<char> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<unsigned char> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<short> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<unsigned short> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<int> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<unsigned int> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<long> { enum { value = 1 }; };
-template<> struct is_supported_pass_2<unsigned long> { enum { value = 1 }; };
+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<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; };
-/*** Step 2: some integer-traits kind of stuff. We're doing our own thing here rather than
- *** relying on std::numeric_limits mostly for historical reasons (we still support PR integer types
- *** which might still be different types e.g. typedefs for some built-in types). Eventually, a patch
- *** replacing some of that by std::numeric_limits should be welcome.
- ***/
+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; };
+
+
+/*
+ * Step 2: some integer-traits kind of stuff.
+ */
+
+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<int size, bool signedness> struct stdint_type_for_size_and_signedness {};
-template<> struct stdint_type_for_size_and_signedness<1, true> { typedef int8_t type; };
-template<> struct stdint_type_for_size_and_signedness<1, false> { typedef uint8_t type; };
-template<> struct stdint_type_for_size_and_signedness<2, true> { typedef int16_t type; };
-template<> struct stdint_type_for_size_and_signedness<2, false> { typedef uint16_t type; };
-template<> struct stdint_type_for_size_and_signedness<4, true> { typedef int32_t type; };
-template<> struct stdint_type_for_size_and_signedness<4, false> { typedef uint32_t type; };
-template<> struct stdint_type_for_size_and_signedness<8, true> { typedef int64_t type; };
-template<> struct stdint_type_for_size_and_signedness<8, false> { typedef uint64_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<typename integer_type> struct unsigned_type {
- typedef typename stdint_type_for_size_and_signedness<sizeof(integer_type), false>::type 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; };
+
+template<typename IntegerType>
+struct UnsignedType
+{
+ typedef typename StdintTypeForSizeAndSignedness<sizeof(IntegerType),
+ false>::Type Type;
};
-template<typename integer_type> struct is_signed {
- enum { value = integer_type(-1) <= integer_type(0) };
+template<typename IntegerType>
+struct IsSigned
+{
+ static const bool value = IntegerType(-1) <= IntegerType(0);
};
-template<typename integer_type, int size=sizeof(integer_type)>
-struct twice_bigger_type {
- typedef typename stdint_type_for_size_and_signedness<
- sizeof(integer_type) * 2,
- is_signed<integer_type>::value
- >::type type;
+template<typename IntegerType, size_t Size = sizeof(IntegerType)>
+struct TwiceBiggerType
+{
+ typedef typename StdintTypeForSizeAndSignedness<
+ sizeof(IntegerType) * 2,
+ IsSigned<IntegerType>::value
+ >::Type Type;
};
-template<typename integer_type>
-struct twice_bigger_type<integer_type, 8> {
- typedef unsupported_type type;
+template<typename IntegerType>
+struct TwiceBiggerType<IntegerType, 8>
+{
+ typedef UnsupportedType Type;
};
-template<typename integer_type> struct position_of_sign_bit
+template<typename IntegerType>
+struct PositionOfSignBit
{
- enum {
- value = CHAR_BIT * sizeof(integer_type) - 1
- };
+ static const size_t value = CHAR_BIT * sizeof(IntegerType) - 1;
};
-template<typename integer_type> struct min_value
+template<typename IntegerType>
+struct MinValue
{
- static integer_type value()
+ static IntegerType value()
{
- // bitwise ops may return a larger type, that's why we cast explicitly to T
- // 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.
- return is_signed<integer_type>::value
- ? integer_type(typename unsigned_type<integer_type>::type(1) << position_of_sign_bit<integer_type>::value)
- : integer_type(0);
+ // 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.
+ return IsSigned<IntegerType>::value
+ ? IntegerType(typename UnsignedType<IntegerType>::Type(1)
+ << PositionOfSignBit<IntegerType>::value)
+ : IntegerType(0);
}
};
-template<typename integer_type> struct max_value
+template<typename IntegerType>
+struct MaxValue
{
- static integer_type value()
+ static IntegerType value()
{
- return ~min_value<integer_type>::value();
+ // Tricksy, but covered by the unit test.
+ // Relies heavily on the return type of MinValue<IntegerType>::value()
+ // being IntegerType.
+ return ~MinValue<IntegerType>::value();
}
};
-/*** Step 3: Implement the actual validity checks --- ideas taken from IntegerLib, code different.
- ***/
+/*
+ * Step 3: Implement the actual validity checks.
+ *
+ * Ideas taken from IntegerLib, code different.
+ */
-// bitwise ops may return a larger type, so it's good to use these inline helpers guaranteeing that
-// the result is really of type T
+// Bitwise ops may return a larger type, so it's good to use these inline
+// helpers guaranteeing that the result is really of type T.
-template<typename T> inline T has_sign_bit(T x)
+template<typename T>
+inline T
+HasSignBit(T x)
{
- // 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. Here the unsigned-to-signed conversion is OK because the value (the result of the shift) is 0 or 1.
- return T(typename unsigned_type<T>::type(x) >> position_of_sign_bit<T>::value);
+ // 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.
+ // Here the unsigned-to-signed conversion is OK because the value
+ // (the result of the shift) is 0 or 1.
+ return T(typename UnsignedType<T>::Type(x)
+ >> PositionOfSignBit<T>::value);
}
-template<typename T> inline T binary_complement(T x)
+template<typename T>
+inline T
+BinaryComplement(T x)
{
- return ~x;
+ return ~x;
}
-template<typename T, typename U,
- bool is_T_signed = is_signed<T>::value,
- bool is_U_signed = is_signed<U>::value>
-struct is_in_range_impl {};
+template<typename T,
+ typename U,
+ bool IsTSigned = IsSigned<T>::value,
+ bool IsUSigned = IsSigned<U>::value>
+struct IsInRangeImpl {};
template<typename T, typename U>
-struct is_in_range_impl<T, U, true, true>
+struct IsInRangeImpl<T, U, true, true>
{
static bool run(U x)
{
- return (x <= max_value<T>::value()) &&
- (x >= min_value<T>::value());
- }
-};
-
-template<typename T, typename U>
-struct is_in_range_impl<T, U, false, false>
-{
- static bool run(U x)
- {
- return x <= max_value<T>::value();
- }
-};
-
-template<typename T, typename U>
-struct is_in_range_impl<T, U, true, false>
-{
- static bool run(U x)
- {
- if (sizeof(T) > sizeof(U))
- return 1;
- else
- return x <= U(max_value<T>::value());
+ return x <= MaxValue<T>::value() &&
+ x >= MinValue<T>::value();
}
};
template<typename T, typename U>
-struct is_in_range_impl<T, U, false, true>
+struct IsInRangeImpl<T, U, false, false>
+{
+ static bool run(U x)
+ {
+ return x <= MaxValue<T>::value();
+ }
+};
+
+template<typename T, typename U>
+struct IsInRangeImpl<T, U, true, false>
{
static bool run(U x)
{
- if (sizeof(T) >= sizeof(U))
- return x >= 0;
- else
- return (x >= 0) && (x <= U(max_value<T>::value()));
+ return sizeof(T) > sizeof(U)
+ ? true
+ : x <= U(MaxValue<T>::value());
+ }
+};
+
+template<typename T, typename U>
+struct IsInRangeImpl<T, U, false, true>
+{
+ static bool run(U x)
+ {
+ return sizeof(T) >= sizeof(U)
+ ? x >= 0
+ : x >= 0 && x <= U(MaxValue<T>::value());
}
};
-template<typename T, typename U> inline bool is_in_range(U x)
+template<typename T, typename U>
+inline bool
+IsInRange(U x)
{
- return is_in_range_impl<T, U>::run(x);
+ return IsInRangeImpl<T, U>::run(x);
}
-template<typename T> inline bool is_add_valid(T x, T y, T result)
+template<typename T>
+inline bool
+IsAddValid(T x, T y, T result)
{
- return is_signed<T>::value ?
- // addition is valid if the sign of x+y is equal to either that of x or that of y.
- // Beware! These bitwise operations can return a larger integer type, if T was a
- // small type like int8, so we explicitly cast to T.
- has_sign_bit(binary_complement(T((result^x) & (result^y))))
- :
- binary_complement(x) >= y;
+ // Addition is valid if the sign of x+y is equal to either that of x or that
+ // of y. 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.
+ return IsSigned<T>::value
+ ? HasSignBit(BinaryComplement(T((result ^ x) & (result ^ y))))
+ : BinaryComplement(x) >= y;
}
-template<typename T> inline bool is_sub_valid(T x, T y, T result)
+template<typename T>
+inline bool
+IsSubValid(T x, T y, T result)
{
- return is_signed<T>::value ?
- // substraction is valid if either x and y have same sign, or x-y and x have same sign
- has_sign_bit(binary_complement(T((result^x) & (x^y))))
- :
- x >= y;
+ // Subtraction is valid if either x and y have same sign, or x-y and x have
+ // same sign.
+ return IsSigned<T>::value
+ ? HasSignBit(BinaryComplement(T((result ^ x) & (x ^ y))))
+ : x >= y;
}
template<typename T,
- bool is_signed = is_signed<T>::value,
- bool twice_bigger_type_is_supported = is_supported<typename twice_bigger_type<T>::type>::value>
-struct is_mul_valid_impl {};
+ bool IsSigned = IsSigned<T>::value,
+ bool TwiceBiggerTypeIsSupported =
+ IsSupported<typename TwiceBiggerType<T>::Type>::value>
+struct IsMulValidImpl {};
-template<typename T, bool is_signed>
-struct is_mul_valid_impl<T, is_signed, true>
+template<typename T, bool IsSigned>
+struct IsMulValidImpl<T, IsSigned, true>
{
static bool run(T x, T y)
{
- typedef typename twice_bigger_type<T>::type twice_bigger_type;
- twice_bigger_type product = twice_bigger_type(x) * twice_bigger_type(y);
- return is_in_range<T>(product);
+ typedef typename TwiceBiggerType<T>::Type TwiceBiggerType;
+ TwiceBiggerType product = TwiceBiggerType(x) * TwiceBiggerType(y);
+ return IsInRange<T>(product);
}
};
template<typename T>
-struct is_mul_valid_impl<T, true, false>
+struct IsMulValidImpl<T, true, false>
{
static bool run(T x, T y)
{
- const T max = max_value<T>::value();
- const T min = min_value<T>::value();
+ const T max = MaxValue<T>::value();
+ const T min = MinValue<T>::value();
+
+ if (x == 0 || y == 0)
+ return true;
- if (x == 0 || y == 0) return true;
+ if (x > 0) {
+ return y > 0
+ ? x <= max / y
+ : y >= min / x;
+ }
- if (x > 0) {
- if (y > 0)
- return x <= max / y;
- else
- return y >= min / x;
- } else {
- if (y > 0)
- return x >= min / y;
- else
- return y >= max / x;
- }
+ // If we reach this point, we know that x < 0.
+ return y > 0
+ ? x >= min / y
+ : y >= max / x;
+ }
+};
+
+template<typename T>
+struct IsMulValidImpl<T, false, false>
+{
+ static bool run(T x, T y)
+ {
+ return y == 0 ||
+ x <= MaxValue<T>::value() / y;
}
};
template<typename T>
-struct is_mul_valid_impl<T, false, false>
+inline bool
+IsMulValid(T x, T y, T /* result not used */)
{
- static bool run(T x, T y)
- {
- const T max = max_value<T>::value();
- if (x == 0 || y == 0) return true;
- return x <= max / y;
- }
-};
-
-template<typename T> inline bool is_mul_valid(T x, T y, T /*result not used*/)
-{
- return is_mul_valid_impl<T>::run(x, y);
+ return IsMulValidImpl<T>::run(x, y);
}
-template<typename T> inline bool is_div_valid(T x, T y)
+template<typename T>
+inline bool
+IsDivValid(T x, T y)
{
- return is_signed<T>::value ?
- // keep in mind that min/-1 is invalid because abs(min)>max
- (y != 0) && (x != min_value<T>::value() || y != T(-1))
- :
- y != 0;
+ // Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max.
+ return IsSigned<T>::value
+ ? (y != 0) && (x != MinValue<T>::value() || y != T(-1))
+ : y != 0;
}
-// this is just to shut up msvc warnings about negating unsigned ints.
-template<typename T, bool is_signed = is_signed<T>::value>
-struct opposite_if_signed_impl
+// This is just to shut up msvc warnings about negating unsigned ints.
+template<typename T, bool IsSigned = IsSigned<T>::value>
+struct OppositeIfSignedImpl
{
static T run(T x) { return -x; }
};
template<typename T>
-struct opposite_if_signed_impl<T, false>
+struct OppositeIfSignedImpl<T, false>
{
static T run(T x) { return x; }
};
template<typename T>
-inline T opposite_if_signed(T x) { return opposite_if_signed_impl<T>::run(x); }
-
+inline T
+OppositeIfSigned(T x)
+{
+ return OppositeIfSignedImpl<T>::run(x);
+}
-
-} // end namespace detail
+} // namespace detail
-/*** Step 4: Now define the CheckedInt class.
- ***/
+/*
+ * Step 4: 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
- * valid() returns true, you then have a guarantee that no problem, such as integer overflow,
- * happened during this computation.
- *
- * 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 (x+y)/z,
- * that doesn't crash if z==0, and that reports on error (divide by zero or integer overflow).
- * You could code it as follows:
- \code
- bool compute_x_plus_y_over_z(int x, int y, int z, int *result)
- {
- CheckedInt<int> checked_result = (CheckedInt<int>(x) + y) / z;
- *result = checked_result.value();
- return checked_result.valid();
- }
- \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
- CheckedInt<uint8_t> x(1); // 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<int8_t> x(-1); // -1 is of type int, is found to be in range for int8_t, x is valid
- CheckedInt<int8_t> x(int16_t(1000)); // 1000 is of type int16_t, is found not to be in range for int8_t, x is invalid
- CheckedInt<int32_t> x(uint32_t(3123456789)); // 3123456789 is of type uint32_t, is found not to be in range
- // for int32_t, x is invalid
- * \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
- */
+/**
+ * @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
+ * (x+y)/z, that doesn't crash if z==0, and that reports on error (divide by
+ * zero or integer overflow). You could code it as follows:
+ @code
+ bool computeXPlusYOverZ(int x, int y, int z, int *result)
+ {
+ CheckedInt<int> checkedResult = (CheckedInt<int>(x) + y) / z;
+ if (checkedResult.isValid()) {
+ *result = 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:
+ protected:
T mValue;
bool mIsValid;
template<typename U>
CheckedInt(U value, bool isValid) : mValue(value), mIsValid(isValid)
{
- MOZ_STATIC_ASSERT(detail::is_supported<T>::value, "This type is not supported by CheckedInt");
+ MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
+ "This type is not supported by CheckedInt");
}
-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.
- */
+ 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>
CheckedInt(U value)
- : mValue(T(value)),
- mIsValid(detail::is_in_range<T>(value))
+ : mValue(T(value)),
+ mIsValid(detail::IsInRange<T>(value))
{
- MOZ_STATIC_ASSERT(detail::is_supported<T>::value, "This type is not supported by CheckedInt");
+ MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
+ "This type is not supported by CheckedInt");
}
/** Constructs a valid checked integer with initial value 0 */
CheckedInt() : mValue(0), mIsValid(true)
{
- MOZ_STATIC_ASSERT(detail::is_supported<T>::value, "This type is not supported by CheckedInt");
+ MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
+ "This type is not supported by CheckedInt");
}
- /** \returns the actual value */
- T value() const { return mValue; }
+ /** @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 valid() const
+ /**
+ * @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;
+ return mIsValid;
}
- /** \returns the sum. Checks for overflow. */
- template<typename U> friend CheckedInt<U> operator +(const CheckedInt<U>& lhs, const CheckedInt<U>& rhs);
- /** Adds. Checks for overflow. \returns self reference */
- template<typename U> CheckedInt& operator +=(U rhs);
- /** \returns the difference. Checks for overflow. */
- template<typename U> friend CheckedInt<U> operator -(const CheckedInt<U>& lhs, const CheckedInt<U> &rhs);
- /** Substracts. Checks for overflow. \returns self reference */
- template<typename U> CheckedInt& operator -=(U rhs);
- /** \returns the product. Checks for overflow. */
- template<typename U> friend CheckedInt<U> operator *(const CheckedInt<U>& lhs, const CheckedInt<U> &rhs);
- /** Multiplies. Checks for overflow. \returns self reference */
- template<typename U> CheckedInt& operator *=(U rhs);
- /** \returns the quotient. Checks for overflow and for divide-by-zero. */
- template<typename U> friend CheckedInt<U> operator /(const CheckedInt<U>& lhs, const CheckedInt<U> &rhs);
- /** Divides. Checks for overflow and for divide-by-zero. \returns self reference */
- template<typename U> CheckedInt& operator /=(U rhs);
+ template<typename U>
+ friend CheckedInt<U> operator +(const CheckedInt<U>& lhs,
+ const CheckedInt<U>& rhs);
+ template<typename U>
+ CheckedInt& operator +=(U rhs);
+ template<typename U>
+ friend CheckedInt<U> operator -(const CheckedInt<U>& lhs,
+ const CheckedInt<U> &rhs);
+ template<typename U>
+ CheckedInt& operator -=(U rhs);
+ template<typename U>
+ friend CheckedInt<U> operator *(const CheckedInt<U>& lhs,
+ const CheckedInt<U> &rhs);
+ template<typename U>
+ CheckedInt& operator *=(U rhs);
+ template<typename U>
+ friend CheckedInt<U> operator /(const CheckedInt<U>& lhs,
+ const CheckedInt<U> &rhs);
+ template<typename U>
+ CheckedInt& operator /=(U rhs);
- /** \returns the opposite value. Checks for overflow. */
CheckedInt operator -() const
{
- // circumvent msvc warning about - applied to unsigned int.
- // if we're unsigned, the only valid case anyway is 0 in which case - is a no-op.
- T result = detail::opposite_if_signed(value());
- /* give the compiler a good chance to perform RVO */
- return CheckedInt(result,
- valid() && detail::is_sub_valid(T(0), value(), result));
+ // Circumvent msvc warning about - applied to unsigned int.
+ // if we're unsigned, the only valid case anyway is 0
+ // in which case - is a no-op.
+ T result = detail::OppositeIfSigned(mValue);
+ /* Help the compiler perform RVO (return value optimization). */
+ return CheckedInt(result,
+ mIsValid && detail::IsSubValid(T(0),
+ mValue,
+ result));
}
- /** \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.
- */
+ /**
+ * @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& other) const
{
- return valid() && other.valid() && value() == other.value();
+ return mIsValid && other.mIsValid && mValue == other.mValue;
}
/** prefix ++ */
CheckedInt& operator++()
{
- *this = *this + 1;
- return *this;
+ *this += 1;
+ return *this;
}
/** postfix ++ */
CheckedInt operator++(int)
{
- CheckedInt tmp = *this;
- *this = *this + 1;
- return tmp;
+ CheckedInt tmp = *this;
+ *this += 1;
+ return tmp;
}
/** prefix -- */
CheckedInt& operator--()
{
- *this = *this - 1;
- return *this;
+ *this -= 1;
+ return *this;
}
/** postfix -- */
CheckedInt operator--(int)
{
- CheckedInt tmp = *this;
- *this = *this - 1;
- return tmp;
+ CheckedInt tmp = *this;
+ *this -= 1;
+ return tmp;
}
-private:
- /** operator!= is disabled. Indeed, (a!=b) should be the same as !(a==b) but that
- * would mean that if a or b is invalid, (a!=b) is always true, which is very tricky.
- */
+ private:
+ /**
+ * The !=, <, <=, >, >= operators are disabled:
+ * see the comment on operator==.
+ */
+ template<typename U>
+ bool operator !=(U other) const MOZ_DELETE;
template<typename U>
- bool operator !=(U other) const { return !(*this == other); }
+ bool operator <(U other) const MOZ_DELETE;
+ template<typename U>
+ bool operator <=(U other) const MOZ_DELETE;
+ template<typename U>
+ bool operator >(U other) const MOZ_DELETE;
+ template<typename U>
+ bool operator >=(U other) const MOZ_DELETE;
};
-#define CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
-template<typename T> \
-inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, const CheckedInt<T> &rhs) \
+#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
+template<typename T> \
+inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, \
+ const CheckedInt<T> &rhs) \
{ \
- T x = lhs.mValue; \
- T y = rhs.mValue; \
- T result = x OP y; \
- T is_op_valid \
- = detail::is_##NAME##_valid(x, y, result); \
- /* give the compiler a good chance to perform RVO */ \
- return CheckedInt<T>(result, \
- lhs.mIsValid & rhs.mIsValid & is_op_valid); \
+ T x = lhs.mValue; \
+ T y = rhs.mValue; \
+ T result = x OP y; \
+ T isOpValid \
+ = detail::Is##NAME##Valid(x, y, result); \
+ /* Help the compiler perform RVO (return value optimization). */ \
+ return CheckedInt<T>(result, \
+ lhs.mIsValid && rhs.mIsValid && isOpValid); \
}
-CHECKEDINT_BASIC_BINARY_OPERATOR(add, +)
-CHECKEDINT_BASIC_BINARY_OPERATOR(sub, -)
-CHECKEDINT_BASIC_BINARY_OPERATOR(mul, *)
+MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
+MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
+MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
-// division can't be implemented by CHECKEDINT_BASIC_BINARY_OPERATOR
+#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
+
+// Division can't be implemented by MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
// because if rhs == 0, we are not allowed to even try to compute the quotient.
template<typename T>
-inline CheckedInt<T> operator /(const CheckedInt<T> &lhs, const CheckedInt<T> &rhs)
+inline CheckedInt<T> operator /(const CheckedInt<T> &lhs,
+ const CheckedInt<T> &rhs)
{
- T x = lhs.mValue;
- T y = rhs.mValue;
- bool is_op_valid = detail::is_div_valid(x, y);
- T result = is_op_valid ? (x / y) : 0;
- /* give the compiler a good chance to perform RVO */
- return CheckedInt<T>(result,
- lhs.mIsValid & rhs.mIsValid & is_op_valid);
+ T x = lhs.mValue;
+ T y = rhs.mValue;
+ bool isOpValid = detail::IsDivValid(x, y);
+ T result = isOpValid ? (x / y) : 0;
+ /* give the compiler a good chance to perform RVO */
+ return CheckedInt<T>(result,
+ lhs.mIsValid && rhs.mIsValid && isOpValid);
}
-// implement cast_to_CheckedInt<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)
+// 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 cast_to_CheckedInt_impl
+struct CastToCheckedIntImpl
{
- typedef CheckedInt<T> return_type;
+ typedef CheckedInt<T> ReturnType;
static CheckedInt<T> run(U u) { return u; }
};
template<typename T>
-struct cast_to_CheckedInt_impl<T, CheckedInt<T> >
+struct CastToCheckedIntImpl<T, CheckedInt<T> >
{
- typedef const CheckedInt<T>& return_type;
+ typedef const CheckedInt<T>& ReturnType;
static const CheckedInt<T>& run(const CheckedInt<T>& u) { return u; }
};
+} // namespace detail
+
template<typename T, typename U>
-inline typename cast_to_CheckedInt_impl<T, U>::return_type
-cast_to_CheckedInt(U u)
+inline typename detail::CastToCheckedIntImpl<T, U>::ReturnType
+castToCheckedInt(U u)
{
- return cast_to_CheckedInt_impl<T, U>::run(u);
+ return detail::CastToCheckedIntImpl<T, U>::run(u);
}
-#define CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
-template<typename T> \
-template<typename U> \
-CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U rhs) \
-{ \
- *this = *this OP cast_to_CheckedInt<T>(rhs); \
- return *this; \
-} \
-template<typename T, typename U> \
+#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
+template<typename T> \
+template<typename U> \
+CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U rhs) \
+{ \
+ *this = *this OP castToCheckedInt<T>(rhs); \
+ return *this; \
+} \
+template<typename T, typename U> \
inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, U rhs) \
-{ \
- return lhs OP cast_to_CheckedInt<T>(rhs); \
-} \
-template<typename T, typename U> \
+{ \
+ return lhs OP castToCheckedInt<T>(rhs); \
+} \
+template<typename T, typename U> \
inline CheckedInt<T> operator OP(U lhs, const CheckedInt<T> &rhs) \
-{ \
- return cast_to_CheckedInt<T>(lhs) OP rhs; \
+{ \
+ return castToCheckedInt<T>(lhs) OP rhs; \
}
-CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
-CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
-CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
-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> &lhs, U rhs)
+inline bool
+operator ==(const CheckedInt<T> &lhs, U rhs)
{
- return lhs == cast_to_CheckedInt<T>(rhs);
+ return lhs == castToCheckedInt<T>(rhs);
}
template<typename T, typename U>
-inline bool operator ==(U lhs, const CheckedInt<T> &rhs)
+inline bool
+operator ==(U lhs, const CheckedInt<T> &rhs)
{
- return cast_to_CheckedInt<T>(lhs) == rhs;
+ return castToCheckedInt<T>(lhs) == rhs;
}
-// convenience typedefs.
+// 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;
-} // end namespace mozilla
+} // namespace mozilla
-#endif /* mozilla_CheckedInt_h */
+#endif /* mozilla_CheckedInt_h_ */
--- a/mfbt/Makefile.in
+++ b/mfbt/Makefile.in
@@ -42,17 +42,19 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = mozglue
LIBRARY_NAME = mfbt
FORCE_STATIC_LIB = 1
STL_FLAGS =
-DIRS =
+TEST_DIRS = \
+ tests \
+ $(NULL)
# exported_headers.mk defines the headers exported by mfbt. It is included by
# mfbt itself and by the JS engine, which, when built standalone, must do the
# work to install mfbt's exported headers itself.
include $(srcdir)/exported_headers.mk
# sources.mk defines the source files built for mfbt. It is included by mfbt
# itself and by the JS engine, which, when built standalone, must do the work
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -40,16 +40,17 @@
# mfbt's exported headers itself.
EXPORTS_NAMESPACES += mozilla
EXPORTS_mozilla += \
Assertions.h \
Attributes.h \
BloomFilter.h \
+ CheckedInt.h \
FloatingPoint.h \
GuardObjects.h \
HashFunctions.h \
Likely.h \
LinkedList.h \
MSStdInt.h \
RangedPtr.h \
RefPtr.h \
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/Makefile.in
@@ -0,0 +1,21 @@
+# 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/.
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+STL_FLAGS =
+
+CPP_UNIT_TESTS = \
+ TestCheckedInt.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+LIBS=
+MOZ_GLUE_PROGRAM_LDFLAGS=
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/TestCheckedInt.cpp
@@ -0,0 +1,492 @@
+/* -*- 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/. */
+
+#include "mozilla/CheckedInt.h"
+
+#include <iostream>
+#include <climits>
+
+#ifndef MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
+# error MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS should be defined by CheckedInt.h
+#endif
+
+using namespace mozilla;
+
+int gIntegerTypesTested = 0;
+int gTestsPassed = 0;
+int gTestsFailed = 0;
+
+void verifyImplFunction(bool x, bool expected,
+ const char* file, int line,
+ int size, bool isTSigned)
+{
+ if (x == expected) {
+ gTestsPassed++;
+ } else {
+ gTestsFailed++;
+ std::cerr << "Test failed at " << file << ":" << line;
+ std::cerr << " with T a ";
+ if (isTSigned)
+ std::cerr << "signed";
+ else
+ std::cerr << "unsigned";
+ std::cerr << " " << CHAR_BIT*size << "-bit integer type" << std::endl;
+ }
+}
+
+#define VERIFY_IMPL(x, expected) \
+ verifyImplFunction((x), \
+ (expected), \
+ __FILE__, \
+ __LINE__, \
+ sizeof(T), \
+ detail::IsSigned<T>::value)
+
+#define VERIFY(x) VERIFY_IMPL(x, true)
+#define VERIFY_IS_FALSE(x) VERIFY_IMPL(x, false)
+#define VERIFY_IS_VALID(x) VERIFY_IMPL((x).isValid(), true)
+#define VERIFY_IS_INVALID(x) VERIFY_IMPL((x).isValid(), false)
+#define VERIFY_IS_VALID_IF(x,condition) VERIFY_IMPL((x).isValid(), (condition))
+
+template<typename T, size_t Size = sizeof(T)>
+struct testTwiceBiggerType
+{
+ static void run()
+ {
+ VERIFY(detail::IsSupported<typename detail::TwiceBiggerType<T>::Type>::value);
+ VERIFY(sizeof(typename detail::TwiceBiggerType<T>::Type)
+ == 2 * sizeof(T));
+ VERIFY(bool(detail::IsSigned<typename detail::TwiceBiggerType<T>::Type>::value)
+ == bool(detail::IsSigned<T>::value));
+ }
+};
+
+template<typename T>
+struct testTwiceBiggerType<T, 8>
+{
+ static void run()
+ {
+ VERIFY_IS_FALSE(detail::IsSupported<
+ typename detail::TwiceBiggerType<T>::Type
+ >::value);
+ }
+};
+
+
+template<typename T>
+void test()
+{
+ static bool alreadyRun = false;
+ // Integer types from different families may just be typedefs for types from other families.
+ // e.g. int32_t might be just a typedef for int. No point re-running the same tests then.
+ if (alreadyRun)
+ return;
+ alreadyRun = true;
+
+ VERIFY(detail::IsSupported<T>::value);
+ const bool isTSigned = detail::IsSigned<T>::value;
+ VERIFY(bool(isTSigned) == !bool(T(-1) > T(0)));
+
+ testTwiceBiggerType<T>::run();
+
+ typedef typename detail::UnsignedType<T>::Type unsignedT;
+
+ VERIFY(sizeof(unsignedT) == sizeof(T));
+ VERIFY(detail::IsSigned<unsignedT>::value == false);
+
+ const CheckedInt<T> max(detail::MaxValue<T>::value());
+ const CheckedInt<T> min(detail::MinValue<T>::value());
+
+ // Check min() and max(), since they are custom implementations and a mistake there
+ // could potentially NOT be caught by any other tests... while making everything wrong!
+
+ T bit = 1;
+ for (size_t i = 0; i < sizeof(T) * CHAR_BIT - 1; i++)
+ {
+ VERIFY((min.value() & bit) == 0);
+ bit <<= 1;
+ }
+ VERIFY((min.value() & bit) == (isTSigned ? bit : T(0)));
+ VERIFY(max.value() == T(~(min.value())));
+
+ const CheckedInt<T> zero(0);
+ const CheckedInt<T> one(1);
+ const CheckedInt<T> two(2);
+ const CheckedInt<T> three(3);
+ const CheckedInt<T> four(4);
+
+ /* Addition / substraction checks */
+
+ VERIFY_IS_VALID(zero + zero);
+ VERIFY(zero + zero == zero);
+ VERIFY_IS_FALSE(zero + zero == one); // Check that == doesn't always return true
+ VERIFY_IS_VALID(zero + one);
+ VERIFY(zero + one == one);
+ VERIFY_IS_VALID(one + one);
+ VERIFY(one + one == two);
+
+ const CheckedInt<T> maxMinusOne = max - one;
+ const CheckedInt<T> maxMinusTwo = max - two;
+ VERIFY_IS_VALID(maxMinusOne);
+ VERIFY_IS_VALID(maxMinusTwo);
+ VERIFY_IS_VALID(maxMinusOne + one);
+ VERIFY_IS_VALID(maxMinusTwo + one);
+ VERIFY_IS_VALID(maxMinusTwo + two);
+ VERIFY(maxMinusOne + one == max);
+ VERIFY(maxMinusTwo + one == maxMinusOne);
+ VERIFY(maxMinusTwo + two == max);
+
+ VERIFY_IS_VALID(max + zero);
+ VERIFY_IS_VALID(max - zero);
+ VERIFY_IS_INVALID(max + one);
+ VERIFY_IS_INVALID(max + two);
+ VERIFY_IS_INVALID(max + maxMinusOne);
+ VERIFY_IS_INVALID(max + max);
+
+ const CheckedInt<T> minPlusOne = min + one;
+ const CheckedInt<T> minPlusTwo = min + two;
+ VERIFY_IS_VALID(minPlusOne);
+ VERIFY_IS_VALID(minPlusTwo);
+ VERIFY_IS_VALID(minPlusOne - one);
+ VERIFY_IS_VALID(minPlusTwo - one);
+ VERIFY_IS_VALID(minPlusTwo - two);
+ VERIFY(minPlusOne - one == min);
+ VERIFY(minPlusTwo - one == minPlusOne);
+ VERIFY(minPlusTwo - two == min);
+
+ const CheckedInt<T> minMinusOne = min - one;
+ VERIFY_IS_VALID(min + zero);
+ VERIFY_IS_VALID(min - zero);
+ VERIFY_IS_INVALID(min - one);
+ VERIFY_IS_INVALID(min - two);
+ VERIFY_IS_INVALID(min - minMinusOne);
+ VERIFY_IS_VALID(min - min);
+
+ const CheckedInt<T> maxOverTwo = max / two;
+ VERIFY_IS_VALID(maxOverTwo + maxOverTwo);
+ VERIFY_IS_VALID(maxOverTwo + one);
+ VERIFY((maxOverTwo + one) - one == maxOverTwo);
+ VERIFY_IS_VALID(maxOverTwo - maxOverTwo);
+ VERIFY(maxOverTwo - maxOverTwo == zero);
+
+ const CheckedInt<T> minOverTwo = min / two;
+ VERIFY_IS_VALID(minOverTwo + minOverTwo);
+ VERIFY_IS_VALID(minOverTwo + one);
+ VERIFY((minOverTwo + one) - one == minOverTwo);
+ VERIFY_IS_VALID(minOverTwo - minOverTwo);
+ VERIFY(minOverTwo - minOverTwo == zero);
+
+ VERIFY_IS_INVALID(min - one);
+ VERIFY_IS_INVALID(min - two);
+
+ if (isTSigned) {
+ VERIFY_IS_INVALID(min + min);
+ VERIFY_IS_INVALID(minOverTwo + minOverTwo + minOverTwo);
+ VERIFY_IS_INVALID(zero - min + min);
+ VERIFY_IS_INVALID(one - min + min);
+ }
+
+ /* Unary operator- checks */
+
+ const CheckedInt<T> negOne = -one;
+ const CheckedInt<T> negTwo = -two;
+
+ if (isTSigned) {
+ VERIFY_IS_VALID(-max);
+ VERIFY_IS_VALID(-max - one);
+ VERIFY_IS_VALID(negOne);
+ VERIFY_IS_VALID(-max + negOne);
+ VERIFY_IS_VALID(negOne + one);
+ VERIFY(negOne + one == zero);
+ VERIFY_IS_VALID(negTwo);
+ VERIFY_IS_VALID(negOne + negOne);
+ VERIFY(negOne + negOne == negTwo);
+ } else {
+ VERIFY_IS_INVALID(negOne);
+ }
+
+ /* multiplication checks */
+
+ VERIFY_IS_VALID(zero * zero);
+ VERIFY(zero * zero == zero);
+ VERIFY_IS_VALID(zero * one);
+ VERIFY(zero * one == zero);
+ VERIFY_IS_VALID(one * zero);
+ VERIFY(one * zero == zero);
+ VERIFY_IS_VALID(one * one);
+ VERIFY(one * one == one);
+ VERIFY_IS_VALID(one * three);
+ VERIFY(one * three == three);
+ VERIFY_IS_VALID(two * two);
+ VERIFY(two * two == four);
+
+ VERIFY_IS_INVALID(max * max);
+ VERIFY_IS_INVALID(maxOverTwo * max);
+ VERIFY_IS_INVALID(maxOverTwo * maxOverTwo);
+
+ const CheckedInt<T> maxApproxSqrt(T(T(1) << (CHAR_BIT*sizeof(T)/2)));
+
+ VERIFY_IS_VALID(maxApproxSqrt);
+ VERIFY_IS_VALID(maxApproxSqrt * two);
+ VERIFY_IS_INVALID(maxApproxSqrt * maxApproxSqrt);
+ VERIFY_IS_INVALID(maxApproxSqrt * maxApproxSqrt * maxApproxSqrt);
+
+ if (isTSigned) {
+ VERIFY_IS_INVALID(min * min);
+ VERIFY_IS_INVALID(minOverTwo * min);
+ VERIFY_IS_INVALID(minOverTwo * minOverTwo);
+
+ const CheckedInt<T> minApproxSqrt = -maxApproxSqrt;
+
+ VERIFY_IS_VALID(minApproxSqrt);
+ VERIFY_IS_VALID(minApproxSqrt * two);
+ VERIFY_IS_INVALID(minApproxSqrt * maxApproxSqrt);
+ VERIFY_IS_INVALID(minApproxSqrt * minApproxSqrt);
+ }
+
+ // make sure to check all 4 paths in signed multiplication validity check.
+ // test positive * positive
+ VERIFY_IS_VALID(max * one);
+ VERIFY(max * one == max);
+ VERIFY_IS_INVALID(max * two);
+ VERIFY_IS_VALID(maxOverTwo * two);
+ VERIFY((maxOverTwo + maxOverTwo) == (maxOverTwo * two));
+
+ if (isTSigned) {
+ // test positive * negative
+ VERIFY_IS_VALID(max * negOne);
+ VERIFY_IS_VALID(-max);
+ VERIFY(max * negOne == -max);
+ VERIFY_IS_VALID(one * min);
+ VERIFY_IS_INVALID(max * negTwo);
+ VERIFY_IS_VALID(maxOverTwo * negTwo);
+ VERIFY_IS_VALID(two * minOverTwo);
+ VERIFY_IS_VALID((maxOverTwo + one) * negTwo);
+ VERIFY_IS_INVALID((maxOverTwo + two) * negTwo);
+ VERIFY_IS_INVALID(two * (minOverTwo - one));
+
+ // test negative * positive
+ VERIFY_IS_VALID(min * one);
+ VERIFY_IS_VALID(minPlusOne * one);
+ VERIFY_IS_INVALID(min * two);
+ VERIFY_IS_VALID(minOverTwo * two);
+ VERIFY(minOverTwo * two == min);
+ VERIFY_IS_INVALID((minOverTwo - one) * negTwo);
+ VERIFY_IS_INVALID(negTwo * max);
+ VERIFY_IS_VALID(minOverTwo * two);
+ VERIFY(minOverTwo * two == min);
+ VERIFY_IS_VALID(negTwo * maxOverTwo);
+ VERIFY_IS_INVALID((minOverTwo - one) * two);
+ VERIFY_IS_VALID(negTwo * (maxOverTwo + one));
+ VERIFY_IS_INVALID(negTwo * (maxOverTwo + two));
+
+ // test negative * negative
+ VERIFY_IS_INVALID(min * negOne);
+ VERIFY_IS_VALID(minPlusOne * negOne);
+ VERIFY(minPlusOne * negOne == max);
+ VERIFY_IS_INVALID(min * negTwo);
+ VERIFY_IS_INVALID(minOverTwo * negTwo);
+ VERIFY_IS_INVALID(negOne * min);
+ VERIFY_IS_VALID(negOne * minPlusOne);
+ VERIFY(negOne * minPlusOne == max);
+ VERIFY_IS_INVALID(negTwo * min);
+ VERIFY_IS_INVALID(negTwo * minOverTwo);
+ }
+
+ /* Division checks */
+
+ VERIFY_IS_VALID(one / one);
+ VERIFY(one / one == one);
+ VERIFY_IS_VALID(three / three);
+ VERIFY(three / three == one);
+ VERIFY_IS_VALID(four / two);
+ VERIFY(four / two == two);
+ VERIFY((four*three)/four == three);
+
+ // Check that div by zero is invalid
+ VERIFY_IS_INVALID(zero / zero);
+ VERIFY_IS_INVALID(one / zero);
+ VERIFY_IS_INVALID(two / zero);
+ VERIFY_IS_INVALID(negOne / zero);
+ VERIFY_IS_INVALID(max / zero);
+ VERIFY_IS_INVALID(min / zero);
+
+ if (isTSigned) {
+ // Check that min / -1 is invalid
+ VERIFY_IS_INVALID(min / negOne);
+
+ // Check that the test for div by -1 isn't banning other numerators than min
+ VERIFY_IS_VALID(one / negOne);
+ VERIFY_IS_VALID(zero / negOne);
+ VERIFY_IS_VALID(negOne / negOne);
+ VERIFY_IS_VALID(max / negOne);
+ }
+
+ /* Check that invalidity is correctly preserved by arithmetic ops */
+
+ const CheckedInt<T> someInvalid = max + max;
+ VERIFY_IS_INVALID(someInvalid + zero);
+ VERIFY_IS_INVALID(someInvalid - zero);
+ VERIFY_IS_INVALID(zero + someInvalid);
+ VERIFY_IS_INVALID(zero - someInvalid);
+ VERIFY_IS_INVALID(-someInvalid);
+ VERIFY_IS_INVALID(someInvalid * zero);
+ VERIFY_IS_INVALID(someInvalid * one);
+ VERIFY_IS_INVALID(zero * someInvalid);
+ VERIFY_IS_INVALID(one * someInvalid);
+ VERIFY_IS_INVALID(someInvalid / zero);
+ VERIFY_IS_INVALID(someInvalid / one);
+ VERIFY_IS_INVALID(zero / someInvalid);
+ VERIFY_IS_INVALID(one / someInvalid);
+ VERIFY_IS_INVALID(someInvalid + someInvalid);
+ VERIFY_IS_INVALID(someInvalid - someInvalid);
+ VERIFY_IS_INVALID(someInvalid * someInvalid);
+ VERIFY_IS_INVALID(someInvalid / someInvalid);
+
+ /* Check that mixing checked integers with plain integers in expressions is allowed */
+
+ VERIFY(one + T(2) == three);
+ VERIFY(2 + one == three);
+ {
+ CheckedInt<T> x = one;
+ x += 2;
+ VERIFY(x == three);
+ }
+ VERIFY(two - 1 == one);
+ VERIFY(2 - one == one);
+ {
+ CheckedInt<T> x = two;
+ x -= 1;
+ VERIFY(x == one);
+ }
+ VERIFY(one * 2 == two);
+ VERIFY(2 * one == two);
+ {
+ CheckedInt<T> x = one;
+ x *= 2;
+ VERIFY(x == two);
+ }
+ VERIFY(four / 2 == two);
+ VERIFY(4 / two == two);
+ {
+ CheckedInt<T> x = four;
+ x /= 2;
+ VERIFY(x == two);
+ }
+
+ VERIFY(one == 1);
+ VERIFY(1 == one);
+ VERIFY_IS_FALSE(two == 1);
+ VERIFY_IS_FALSE(1 == two);
+ VERIFY_IS_FALSE(someInvalid == 1);
+ VERIFY_IS_FALSE(1 == someInvalid);
+
+ /* Check that construction of CheckedInt from an integer value of a mismatched type is checked */
+
+ #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
+ { \
+ bool isUSigned = detail::IsSigned<U>::value; \
+ VERIFY_IS_VALID(CheckedInt<T>(U(0))); \
+ VERIFY_IS_VALID(CheckedInt<T>(U(1))); \
+ VERIFY_IS_VALID(CheckedInt<T>(U(100))); \
+ if (isUSigned) \
+ VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \
+ if (sizeof(U) > sizeof(T)) \
+ VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value())+1)); \
+ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value()), \
+ (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \
+ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value()), \
+ isUSigned == false ? 1 : \
+ bool(isTSigned) == false ? 0 : \
+ sizeof(T) >= sizeof(U)); \
+ }
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint16_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int32_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint32_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int64_t)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint64_t)
+
+ typedef unsigned char unsignedChar;
+ typedef unsigned short unsignedShort;
+ typedef unsigned int unsignedInt;
+ typedef unsigned long unsignedLong;
+
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(char)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedChar)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(short)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedShort)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedInt)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(long)
+ VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedLong)
+
+ /* Test increment/decrement operators */
+
+ CheckedInt<T> x, y;
+ x = one;
+ y = x++;
+ VERIFY(x == two);
+ VERIFY(y == one);
+ x = one;
+ y = ++x;
+ VERIFY(x == two);
+ VERIFY(y == two);
+ x = one;
+ y = x--;
+ VERIFY(x == zero);
+ VERIFY(y == one);
+ x = one;
+ y = --x;
+ VERIFY(x == zero);
+ VERIFY(y == zero);
+ x = max;
+ VERIFY_IS_VALID(x++);
+ x = max;
+ VERIFY_IS_INVALID(++x);
+ x = min;
+ VERIFY_IS_VALID(x--);
+ x = min;
+ VERIFY_IS_INVALID(--x);
+
+ gIntegerTypesTested++;
+}
+
+int main()
+{
+ test<int8_t>();
+ test<uint8_t>();
+ test<int16_t>();
+ test<uint16_t>();
+ test<int32_t>();
+ test<uint32_t>();
+ test<int64_t>();
+ test<uint64_t>();
+
+ test<char>();
+ test<unsigned char>();
+ test<short>();
+ test<unsigned short>();
+ test<int>();
+ test<unsigned int>();
+ test<long>();
+ test<unsigned long>();
+
+ if (gIntegerTypesTested < 8) {
+ std::cerr << "Only " << gIntegerTypesTested << " have been tested. "
+ << "This should not be less than 8." << std::endl;
+ gTestsFailed++;
+ }
+
+ std::cerr << gTestsFailed << " tests failed, "
+ << gTestsPassed << " tests passed out of "
+ << gTestsFailed + gTestsPassed
+ << " tests, covering " << gIntegerTypesTested
+ << " distinct integer types." << std::endl;
+
+ return gTestsFailed > 0;
+}
--- a/xpcom/ds/Makefile.in
+++ b/xpcom/ds/Makefile.in
@@ -105,17 +105,16 @@ EXPORTS = \
nsStaticAtom.h \
nsSupportsArray.h \
nsSupportsPrimitives.h \
nsVariant.h \
nsStringEnumerator.h \
nsHashPropertyBag.h \
nsWhitespaceTokenizer.h \
nsCharSeparatedTokenizer.h \
- CheckedInt.h \
$(NULL)
XPIDLSRCS = \
nsIAtom.idl \
nsIAtomService.idl \
nsICollection.idl \
nsIEnumerator.idl \
nsIINIParser.idl \
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -100,17 +100,16 @@ CPP_UNIT_TESTS = \
TestHashtables.cpp \
TestID.cpp \
TestObserverArray.cpp \
TestObserverService.cpp \
TestPipe.cpp \
TestRefPtr.cpp \
TestSettingsAPI.cpp \
TestTextFormatter.cpp \
- TestCheckedInt.cpp \
TestTArray.cpp \
$(NULL)
ifdef MOZ_MEMORY
CPP_UNIT_TESTS += TestJemalloc.cpp
endif
# XXX Make this tests work in libxul builds.
deleted file mode 100644
--- a/xpcom/tests/TestCheckedInt.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla code.
- *
- * The Initial Developer of the Original Code is the Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Benoit Jacob <bjacob@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-#include "CheckedInt.h"
-#include <iostream>
-
-#ifndef CHECKEDINT_ENABLE_MOZ_ASSERTS
- #error CHECKEDINT_ENABLE_MOZ_ASSERTS should be defined by CheckedInt.h
-#endif
-
-namespace CheckedInt_test {
-
-using namespace mozilla::detail;
-using mozilla::CheckedInt;
-
-int g_integer_types_tested = 0;
-int g_tests_passed = 0;
-int g_tests_failed = 0;
-
-void verify_impl_function(bool x, bool expected,
- const char* file, int line,
- int T_size, bool T_is_T_signed)
-{
- if (x == expected) {
- g_tests_passed++;
- } else {
- g_tests_failed++;
- std::cerr << "Test failed at " << file << ":" << line;
- std::cerr << " with T a ";
- if(T_is_T_signed)
- std::cerr << "signed";
- else
- std::cerr << "unsigned";
- std::cerr << " " << CHAR_BIT*T_size << "-bit integer type" << std::endl;
- }
-}
-
-#define VERIFY_IMPL(x, expected) \
- verify_impl_function((x), (expected), __FILE__, __LINE__, sizeof(T), is_signed<T>::value)
-
-#define VERIFY(x) VERIFY_IMPL(x, true)
-#define VERIFY_IS_FALSE(x) VERIFY_IMPL(x, false)
-#define VERIFY_IS_VALID(x) VERIFY_IMPL((x).valid(), true)
-#define VERIFY_IS_INVALID(x) VERIFY_IMPL((x).valid(), false)
-#define VERIFY_IS_VALID_IF(x,condition) VERIFY_IMPL((x).valid(), (condition))
-
-template<typename T, unsigned int size = sizeof(T)>
-struct test_twice_bigger_type
-{
- static void run()
- {
- VERIFY(is_supported<typename twice_bigger_type<T>::type>::value);
- VERIFY(sizeof(typename twice_bigger_type<T>::type)
- == 2 * sizeof(T));
- VERIFY(bool(is_signed<typename twice_bigger_type<T>::type>::value)
- == bool(is_signed<T>::value));
- }
-};
-
-template<typename T>
-struct test_twice_bigger_type<T, 8>
-{
- static void run()
- {
- VERIFY_IS_FALSE(is_supported<typename twice_bigger_type<T>::type>::value);
- }
-};
-
-
-template<typename T>
-void test()
-{
- static bool already_run = false;
- // integer types from different families may just be typedefs for types from other families.
- // e.g. int32_t might be just a typedef for int. No point re-running the same tests then.
- if (already_run)
- return;
- already_run = true;
- g_integer_types_tested++;
-
- VERIFY(is_supported<T>::value);
- enum{ is_T_signed = is_signed<T>::value };
- VERIFY(bool(is_T_signed) == !bool(T(-1) > T(0)));
-
- test_twice_bigger_type<T>::run();
-
- typedef typename unsigned_type<T>::type unsigned_T;
-
- VERIFY(sizeof(unsigned_T) == sizeof(T));
- VERIFY(is_signed<unsigned_T>::value == false);
-
- const CheckedInt<T> max(max_value<T>::value());
- const CheckedInt<T> min(min_value<T>::value());
-
- // check min() and max(), since they are custom implementations and a mistake there
- // could potentially NOT be caught by any other tests... while making everything wrong!
-
- T bit = 1;
- for(unsigned int i = 0; i < sizeof(T) * CHAR_BIT - 1; i++)
- {
- VERIFY((min.value() & bit) == 0);
- bit <<= 1;
- }
- VERIFY((min.value() & bit) == (is_T_signed ? bit : T(0)));
- VERIFY(max.value() == T(~(min.value())));
-
- const CheckedInt<T> zero(0);
- const CheckedInt<T> one(1);
- const CheckedInt<T> two(2);
- const CheckedInt<T> three(3);
- const CheckedInt<T> four(4);
-
- /* addition / substraction checks */
-
- VERIFY_IS_VALID(zero+zero);
- VERIFY(zero+zero == zero);
- VERIFY_IS_FALSE(zero+zero == one); // check that == doesn't always return true
- VERIFY_IS_VALID(zero+one);
- VERIFY(zero+one == one);
- VERIFY_IS_VALID(one+one);
- VERIFY(one+one == two);
-
- const CheckedInt<T> max_minus_one = max - one;
- const CheckedInt<T> max_minus_two = max - two;
- VERIFY_IS_VALID(max_minus_one);
- VERIFY_IS_VALID(max_minus_two);
- VERIFY_IS_VALID(max_minus_one + one);
- VERIFY_IS_VALID(max_minus_two + one);
- VERIFY_IS_VALID(max_minus_two + two);
- VERIFY(max_minus_one + one == max);
- VERIFY(max_minus_two + one == max_minus_one);
- VERIFY(max_minus_two + two == max);
-
- VERIFY_IS_VALID(max + zero);
- VERIFY_IS_VALID(max - zero);
- VERIFY_IS_INVALID(max + one);
- VERIFY_IS_INVALID(max + two);
- VERIFY_IS_INVALID(max + max_minus_one);
- VERIFY_IS_INVALID(max + max);
-
- const CheckedInt<T> min_plus_one = min + one;
- const CheckedInt<T> min_plus_two = min + two;
- VERIFY_IS_VALID(min_plus_one);
- VERIFY_IS_VALID(min_plus_two);
- VERIFY_IS_VALID(min_plus_one - one);
- VERIFY_IS_VALID(min_plus_two - one);
- VERIFY_IS_VALID(min_plus_two - two);
- VERIFY(min_plus_one - one == min);
- VERIFY(min_plus_two - one == min_plus_one);
- VERIFY(min_plus_two - two == min);
-
- const CheckedInt<T> min_minus_one = min - one;
- VERIFY_IS_VALID(min + zero);
- VERIFY_IS_VALID(min - zero);
- VERIFY_IS_INVALID(min - one);
- VERIFY_IS_INVALID(min - two);
- VERIFY_IS_INVALID(min - min_minus_one);
- VERIFY_IS_VALID(min - min);
-
- const CheckedInt<T> max_over_two = max / two;
- VERIFY_IS_VALID(max_over_two + max_over_two);
- VERIFY_IS_VALID(max_over_two + one);
- VERIFY((max_over_two + one) - one == max_over_two);
- VERIFY_IS_VALID(max_over_two - max_over_two);
- VERIFY(max_over_two - max_over_two == zero);
-
- const CheckedInt<T> min_over_two = min / two;
- VERIFY_IS_VALID(min_over_two + min_over_two);
- VERIFY_IS_VALID(min_over_two + one);
- VERIFY((min_over_two + one) - one == min_over_two);
- VERIFY_IS_VALID(min_over_two - min_over_two);
- VERIFY(min_over_two - min_over_two == zero);
-
- VERIFY_IS_INVALID(min - one);
- VERIFY_IS_INVALID(min - two);
-
- if (is_T_signed) {
- VERIFY_IS_INVALID(min + min);
- VERIFY_IS_INVALID(min_over_two + min_over_two + min_over_two);
- VERIFY_IS_INVALID(zero - min + min);
- VERIFY_IS_INVALID(one - min + min);
- }
-
- /* unary operator- checks */
-
- const CheckedInt<T> neg_one = -one;
- const CheckedInt<T> neg_two = -two;
-
- if (is_T_signed) {
- VERIFY_IS_VALID(-max);
- VERIFY_IS_VALID(-max - one);
- VERIFY_IS_VALID(neg_one);
- VERIFY_IS_VALID(-max + neg_one);
- VERIFY_IS_VALID(neg_one + one);
- VERIFY(neg_one + one == zero);
- VERIFY_IS_VALID(neg_two);
- VERIFY_IS_VALID(neg_one + neg_one);
- VERIFY(neg_one + neg_one == neg_two);
- } else {
- VERIFY_IS_INVALID(neg_one);
- }
-
- /* multiplication checks */
-
- VERIFY_IS_VALID(zero*zero);
- VERIFY(zero*zero == zero);
- VERIFY_IS_VALID(zero*one);
- VERIFY(zero*one == zero);
- VERIFY_IS_VALID(one*zero);
- VERIFY(one*zero == zero);
- VERIFY_IS_VALID(one*one);
- VERIFY(one*one == one);
- VERIFY_IS_VALID(one*three);
- VERIFY(one*three == three);
- VERIFY_IS_VALID(two*two);
- VERIFY(two*two == four);
-
- VERIFY_IS_INVALID(max * max);
- VERIFY_IS_INVALID(max_over_two * max);
- VERIFY_IS_INVALID(max_over_two * max_over_two);
-
- const CheckedInt<T> max_approx_sqrt(T(T(1) << (CHAR_BIT*sizeof(T)/2)));
-
- VERIFY_IS_VALID(max_approx_sqrt);
- VERIFY_IS_VALID(max_approx_sqrt * two);
- VERIFY_IS_INVALID(max_approx_sqrt * max_approx_sqrt);
- VERIFY_IS_INVALID(max_approx_sqrt * max_approx_sqrt * max_approx_sqrt);
-
- if (is_T_signed) {
- VERIFY_IS_INVALID(min * min);
- VERIFY_IS_INVALID(min_over_two * min);
- VERIFY_IS_INVALID(min_over_two * min_over_two);
-
- const CheckedInt<T> min_approx_sqrt = -max_approx_sqrt;
-
- VERIFY_IS_VALID(min_approx_sqrt);
- VERIFY_IS_VALID(min_approx_sqrt * two);
- VERIFY_IS_INVALID(min_approx_sqrt * max_approx_sqrt);
- VERIFY_IS_INVALID(min_approx_sqrt * min_approx_sqrt);
- }
-
- // make sure to check all 4 paths in signed multiplication validity check.
- // test positive * positive
- VERIFY_IS_VALID(max * one);
- VERIFY(max * one == max);
- VERIFY_IS_INVALID(max * two);
- VERIFY_IS_VALID(max_over_two * two);
- VERIFY((max_over_two + max_over_two) == (max_over_two * two));
-
- if (is_T_signed) {
- // test positive * negative
- VERIFY_IS_VALID(max * neg_one);
- VERIFY_IS_VALID(-max);
- VERIFY(max * neg_one == -max);
- VERIFY_IS_VALID(one * min);
- VERIFY_IS_INVALID(max * neg_two);
- VERIFY_IS_VALID(max_over_two * neg_two);
- VERIFY_IS_VALID(two * min_over_two);
- VERIFY_IS_VALID((max_over_two + one) * neg_two);
- VERIFY_IS_INVALID((max_over_two + two) * neg_two);
- VERIFY_IS_INVALID(two * (min_over_two - one));
-
- // test negative * positive
- VERIFY_IS_VALID(min * one);
- VERIFY_IS_VALID(min_plus_one * one);
- VERIFY_IS_INVALID(min * two);
- VERIFY_IS_VALID(min_over_two * two);
- VERIFY(min_over_two * two == min);
- VERIFY_IS_INVALID((min_over_two - one) * neg_two);
- VERIFY_IS_INVALID(neg_two * max);
- VERIFY_IS_VALID(min_over_two * two);
- VERIFY(min_over_two * two == min);
- VERIFY_IS_VALID(neg_two * max_over_two);
- VERIFY_IS_INVALID((min_over_two - one) * two);
- VERIFY_IS_VALID(neg_two * (max_over_two + one));
- VERIFY_IS_INVALID(neg_two * (max_over_two + two));
-
- // test negative * negative
- VERIFY_IS_INVALID(min * neg_one);
- VERIFY_IS_VALID(min_plus_one * neg_one);
- VERIFY(min_plus_one * neg_one == max);
- VERIFY_IS_INVALID(min * neg_two);
- VERIFY_IS_INVALID(min_over_two * neg_two);
- VERIFY_IS_INVALID(neg_one * min);
- VERIFY_IS_VALID(neg_one * min_plus_one);
- VERIFY(neg_one * min_plus_one == max);
- VERIFY_IS_INVALID(neg_two * min);
- VERIFY_IS_INVALID(neg_two * min_over_two);
- }
-
- /* division checks */
-
- VERIFY_IS_VALID(one / one);
- VERIFY(one / one == one);
- VERIFY_IS_VALID(three / three);
- VERIFY(three / three == one);
- VERIFY_IS_VALID(four / two);
- VERIFY(four / two == two);
- VERIFY((four*three)/four == three);
-
- // check that div by zero is invalid
- VERIFY_IS_INVALID(zero / zero);
- VERIFY_IS_INVALID(one / zero);
- VERIFY_IS_INVALID(two / zero);
- VERIFY_IS_INVALID(neg_one / zero);
- VERIFY_IS_INVALID(max / zero);
- VERIFY_IS_INVALID(min / zero);
-
- if (is_T_signed) {
- // check that min / -1 is invalid
- VERIFY_IS_INVALID(min / neg_one);
-
- // check that the test for div by -1 isn't banning other numerators than min
- VERIFY_IS_VALID(one / neg_one);
- VERIFY_IS_VALID(zero / neg_one);
- VERIFY_IS_VALID(neg_one / neg_one);
- VERIFY_IS_VALID(max / neg_one);
- }
-
- /* check that invalidity is correctly preserved by arithmetic ops */
-
- const CheckedInt<T> some_invalid = max + max;
- VERIFY_IS_INVALID(some_invalid + zero);
- VERIFY_IS_INVALID(some_invalid - zero);
- VERIFY_IS_INVALID(zero + some_invalid);
- VERIFY_IS_INVALID(zero - some_invalid);
- VERIFY_IS_INVALID(-some_invalid);
- VERIFY_IS_INVALID(some_invalid * zero);
- VERIFY_IS_INVALID(some_invalid * one);
- VERIFY_IS_INVALID(zero * some_invalid);
- VERIFY_IS_INVALID(one * some_invalid);
- VERIFY_IS_INVALID(some_invalid / zero);
- VERIFY_IS_INVALID(some_invalid / one);
- VERIFY_IS_INVALID(zero / some_invalid);
- VERIFY_IS_INVALID(one / some_invalid);
- VERIFY_IS_INVALID(some_invalid + some_invalid);
- VERIFY_IS_INVALID(some_invalid - some_invalid);
- VERIFY_IS_INVALID(some_invalid * some_invalid);
- VERIFY_IS_INVALID(some_invalid / some_invalid);
-
- /* check that mixing checked integers with plain integers in expressions is allowed */
-
- VERIFY(one + T(2) == three);
- VERIFY(2 + one == three);
- {
- CheckedInt<T> x = one;
- x += 2;
- VERIFY(x == three);
- }
- VERIFY(two - 1 == one);
- VERIFY(2 - one == one);
- {
- CheckedInt<T> x = two;
- x -= 1;
- VERIFY(x == one);
- }
- VERIFY(one * 2 == two);
- VERIFY(2 * one == two);
- {
- CheckedInt<T> x = one;
- x *= 2;
- VERIFY(x == two);
- }
- VERIFY(four / 2 == two);
- VERIFY(4 / two == two);
- {
- CheckedInt<T> x = four;
- x /= 2;
- VERIFY(x == two);
- }
-
- VERIFY(one == 1);
- VERIFY(1 == one);
- VERIFY_IS_FALSE(two == 1);
- VERIFY_IS_FALSE(1 == two);
- VERIFY_IS_FALSE(some_invalid == 1);
- VERIFY_IS_FALSE(1 == some_invalid);
-
- /* Check that construction of CheckedInt from an integer value of a mismatched type is checked */
-
- #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
- { \
- bool is_U_signed = is_signed<U>::value; \
- VERIFY_IS_VALID(CheckedInt<T>(U(0))); \
- VERIFY_IS_VALID(CheckedInt<T>(U(1))); \
- VERIFY_IS_VALID(CheckedInt<T>(U(100))); \
- if (is_U_signed) \
- VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), is_T_signed); \
- if (sizeof(U) > sizeof(T)) \
- VERIFY_IS_INVALID(CheckedInt<T>(U(max_value<T>::value())+1)); \
- VERIFY_IS_VALID_IF(CheckedInt<T>(max_value<U>::value()), \
- (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (is_U_signed || !is_T_signed)))); \
- VERIFY_IS_VALID_IF(CheckedInt<T>(min_value<U>::value()), \
- is_U_signed == false ? 1 : \
- bool(is_T_signed) == false ? 0 : \
- sizeof(T) >= sizeof(U)); \
- }
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint16_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int32_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint32_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int64_t)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint64_t)
-
- typedef unsigned char unsigned_char;
- typedef unsigned short unsigned_short;
- typedef unsigned int unsigned_int;
- typedef unsigned long unsigned_long;
-
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(char)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsigned_char)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(short)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsigned_short)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsigned_int)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(long)
- VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsigned_long)
-
- /* Test increment/decrement operators */
-
- CheckedInt<T> x, y;
- x = one;
- y = x++;
- VERIFY(x == two);
- VERIFY(y == one);
- x = one;
- y = ++x;
- VERIFY(x == two);
- VERIFY(y == two);
- x = one;
- y = x--;
- VERIFY(x == zero);
- VERIFY(y == one);
- x = one;
- y = --x;
- VERIFY(x == zero);
- VERIFY(y == zero);
- x = max;
- VERIFY_IS_VALID(x++);
- x = max;
- VERIFY_IS_INVALID(++x);
- x = min;
- VERIFY_IS_VALID(x--);
- x = min;
- VERIFY_IS_INVALID(--x);
-}
-
-} // end namespace CheckedInt_test
-
-int main()
-{
- CheckedInt_test::test<int8_t>();
- CheckedInt_test::test<uint8_t>();
- CheckedInt_test::test<int16_t>();
- CheckedInt_test::test<uint16_t>();
- CheckedInt_test::test<int32_t>();
- CheckedInt_test::test<uint32_t>();
- CheckedInt_test::test<int64_t>();
- CheckedInt_test::test<uint64_t>();
-
- CheckedInt_test::test<char>();
- CheckedInt_test::test<unsigned char>();
- CheckedInt_test::test<short>();
- CheckedInt_test::test<unsigned short>();
- CheckedInt_test::test<int>();
- CheckedInt_test::test<unsigned int>();
- CheckedInt_test::test<long>();
- CheckedInt_test::test<unsigned long>();
-
- std::cerr << CheckedInt_test::g_tests_failed << " tests failed, "
- << CheckedInt_test::g_tests_passed << " tests passed out of "
- << CheckedInt_test::g_tests_failed + CheckedInt_test::g_tests_passed
- << " tests, covering " << CheckedInt_test::g_integer_types_tested
- << " distinct integer types." << std::endl;
-
- return CheckedInt_test::g_tests_failed > 0
- || CheckedInt_test::g_integer_types_tested < 8;
-}