mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Merge mozilla-central to autoland
This commit is contained in:
commit
415f86e41d
@ -73,10 +73,10 @@ this.ContentWebRTC = {
|
||||
let devices = contentWindow.pendingGetUserMediaRequests.get(callID);
|
||||
forgetGUMRequest(contentWindow, callID);
|
||||
|
||||
let allowedDevices = Cc["@mozilla.org/array;1"]
|
||||
.createInstance(Ci.nsIMutableArray);
|
||||
let allowedDevices = Cc["@mozilla.org/supports-array;1"]
|
||||
.createInstance(Ci.nsISupportsArray);
|
||||
for (let deviceIndex of aMessage.data.devices)
|
||||
allowedDevices.appendElement(devices[deviceIndex], /*weak =*/ false);
|
||||
allowedDevices.AppendElement(devices[deviceIndex]);
|
||||
|
||||
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", callID);
|
||||
break;
|
||||
@ -261,8 +261,8 @@ function forgetPendingListsEventually(aContentWindow) {
|
||||
}
|
||||
|
||||
function updateIndicators() {
|
||||
let contentWindowArray = MediaManagerService.activeMediaCaptureWindows;
|
||||
let count = contentWindowArray.length;
|
||||
let contentWindowSupportsArray = MediaManagerService.activeMediaCaptureWindows;
|
||||
let count = contentWindowSupportsArray.Count();
|
||||
|
||||
let state = {
|
||||
showGlobalIndicator: count > 0,
|
||||
@ -280,7 +280,7 @@ function updateIndicators() {
|
||||
// sending duplicate notifications.
|
||||
let contentWindows = new Set();
|
||||
for (let i = 0; i < count; ++i) {
|
||||
contentWindows.add(contentWindowArray.queryElementAt(i, Ci.nsISupports).top);
|
||||
contentWindows.add(contentWindowSupportsArray.GetElementAt(i).top);
|
||||
}
|
||||
|
||||
for (let contentWindow of contentWindows) {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/dom/MediaStreamTrack.h"
|
||||
#include "GetUserMediaRequest.h"
|
||||
#include "MediaStreamListener.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -21,6 +20,7 @@
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPopupWindowManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
@ -2406,10 +2406,14 @@ if (privileged) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMutableArray> devicesCopy = nsArray::Create(); // before we give up devices below
|
||||
nsCOMPtr<nsISupportsArray> devicesCopy; // before we give up devices below
|
||||
if (!askPermission) {
|
||||
nsresult rv = NS_NewISupportsArray(getter_AddRefs(devicesCopy));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
for (auto& device : **devices) {
|
||||
nsresult rv = devicesCopy->AppendElement(device, /*weak =*/ false);
|
||||
rv = devicesCopy->AppendElement(device);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
@ -3027,15 +3031,15 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
if (aSubject) {
|
||||
// A particular device or devices were chosen by the user.
|
||||
// NOTE: does not allow setting a device to null; assumes nullptr
|
||||
nsCOMPtr<nsIArray> array(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsISupportsArray> array(do_QueryInterface(aSubject));
|
||||
MOZ_ASSERT(array);
|
||||
uint32_t len = 0;
|
||||
array->GetLength(&len);
|
||||
array->Count(&len);
|
||||
bool videoFound = false, audioFound = false;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsIMediaDevice> device;
|
||||
array->QueryElementAt(i, NS_GET_IID(nsIMediaDevice),
|
||||
getter_AddRefs(device));
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
array->GetElementAt(i,getter_AddRefs(supports));
|
||||
nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supports));
|
||||
MOZ_ASSERT(device); // shouldn't be returning anything else...
|
||||
if (device) {
|
||||
nsString type;
|
||||
@ -3129,11 +3133,14 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray)
|
||||
MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray** aArray)
|
||||
{
|
||||
MOZ_ASSERT(aArray);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
|
||||
nsISupportsArray* array;
|
||||
nsresult rv = NS_NewISupportsArray(&array); // AddRefs
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
for (auto iter = mActiveWindows.Iter(); !iter.Done(); iter.Next()) {
|
||||
const uint64_t& id = iter.Key();
|
||||
@ -3164,11 +3171,11 @@ MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray)
|
||||
}
|
||||
}
|
||||
if (capturing) {
|
||||
array->AppendElement(window, /*weak =*/ false);
|
||||
array->AppendElement(window);
|
||||
}
|
||||
}
|
||||
|
||||
array.forget(aArray);
|
||||
*aArray = array;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3327,14 +3334,14 @@ MediaManager::IterateWindowListeners(nsPIDOMWindowInner* aWindow,
|
||||
void
|
||||
MediaManager::StopMediaStreams()
|
||||
{
|
||||
nsCOMPtr<nsIArray> array;
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
GetActiveMediaCaptureWindows(getter_AddRefs(array));
|
||||
uint32_t len;
|
||||
array->GetLength(&len);
|
||||
array->Count(&len);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> win;
|
||||
array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner),
|
||||
getter_AddRefs(win));
|
||||
nsCOMPtr<nsISupports> window;
|
||||
array->GetElementAt(i, getter_AddRefs(window));
|
||||
nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(window));
|
||||
if (win) {
|
||||
OnNavigation(win->WindowID());
|
||||
}
|
||||
@ -3346,14 +3353,14 @@ MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId)
|
||||
{
|
||||
// Does page currently have a gUM stream active?
|
||||
|
||||
nsCOMPtr<nsIArray> array;
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
GetActiveMediaCaptureWindows(getter_AddRefs(array));
|
||||
uint32_t len;
|
||||
array->GetLength(&len);
|
||||
array->Count(&len);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> win;
|
||||
array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner),
|
||||
getter_AddRefs(win));
|
||||
nsCOMPtr<nsISupports> window;
|
||||
array->GetElementAt(i, getter_AddRefs(window));
|
||||
nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(window));
|
||||
if (win && win->WindowID() == aWindowId) {
|
||||
return true;
|
||||
}
|
||||
|
@ -5,12 +5,12 @@
|
||||
#include "MediaManager.h"
|
||||
#include "MediaPermissionGonk.h"
|
||||
|
||||
#include "nsArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMNavigatorUserMedia.h"
|
||||
#include "nsIStringEnumerator.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
@ -67,10 +67,12 @@ static nsresult
|
||||
NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(array));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (uint32_t i = 0; i < aDevices.Length(); ++i) {
|
||||
rv = array->AppendElement(aDevices.ElementAt(i), /*weak =*/ false);
|
||||
rv = array->AppendElement(aDevices.ElementAt(i));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsISupportsArray;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
%{C++
|
||||
@ -16,7 +16,7 @@ interface nsIDOMWindow;
|
||||
interface nsIMediaManagerService : nsISupports
|
||||
{
|
||||
/* return a array of inner windows that have active captures */
|
||||
readonly attribute nsIArray activeMediaCaptureWindows;
|
||||
readonly attribute nsISupportsArray activeMediaCaptureWindows;
|
||||
|
||||
/* Get the capture state for the given window and all descendant windows (iframes, etc) */
|
||||
void mediaCaptureWindowState(in nsIDOMWindow aWindow, out boolean aVideo, out boolean aAudio,
|
||||
|
@ -58,7 +58,7 @@ var WebrtcUI = {
|
||||
|
||||
notify: function() {
|
||||
let windows = MediaManagerService.activeMediaCaptureWindows;
|
||||
let count = windows.length;
|
||||
let count = windows.Count();
|
||||
let msg = {};
|
||||
if (count == 0) {
|
||||
if (this._notificationId) {
|
||||
@ -76,7 +76,7 @@ var WebrtcUI = {
|
||||
let cameraActive = false;
|
||||
let audioActive = false;
|
||||
for (let i = 0; i < count; i++) {
|
||||
let win = windows.queryElementAt(i, Ci.nsIDOMWindow);
|
||||
let win = windows.GetElementAt(i);
|
||||
let hasAudio = {};
|
||||
let hasVideo = {};
|
||||
MediaManagerService.mediaCaptureWindowState(win, hasVideo, hasAudio);
|
||||
@ -150,19 +150,19 @@ var WebrtcUI = {
|
||||
{
|
||||
label: Strings.browser.GetStringFromName("getUserMedia.shareRequest.label"),
|
||||
callback: function(checked /* ignored */, inputs) {
|
||||
let allowedDevices = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
let allowedDevices = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
|
||||
|
||||
let audioId = 0;
|
||||
if (inputs && inputs.audioDevice != undefined)
|
||||
audioId = inputs.audioDevice;
|
||||
if (audioDevices[audioId])
|
||||
allowedDevices.appendElement(audioDevices[audioId], /*weak =*/ false);
|
||||
allowedDevices.AppendElement(audioDevices[audioId]);
|
||||
|
||||
let videoId = 0;
|
||||
if (inputs && inputs.videoSource != undefined)
|
||||
videoId = inputs.videoSource;
|
||||
if (videoDevices[videoId]) {
|
||||
allowedDevices.appendElement(videoDevices[videoId], /*weak =*/ false);
|
||||
allowedDevices.AppendElement(videoDevices[videoId]);
|
||||
let perms = Services.perms;
|
||||
// Although the lifetime is "session" it will be removed upon
|
||||
// use so it's more of a one-shot.
|
||||
|
@ -33,11 +33,17 @@ class nsISupportsArray;
|
||||
[scriptable, uuid(241addc8-3608-4e73-8083-2fd6fa09eba2)]
|
||||
interface nsISupportsArray : nsICollection {
|
||||
|
||||
[notxpcom] boolean Equals([const] in nsISupportsArray other);
|
||||
|
||||
[notxpcom] long IndexOf([const] in nsISupports aPossibleElement);
|
||||
[notxpcom] long IndexOfStartingAt([const] in nsISupports aPossibleElement,
|
||||
in unsigned long aStartIndex);
|
||||
[notxpcom] long LastIndexOf([const] in nsISupports aPossibleElement);
|
||||
|
||||
// xpcom-compatible versions
|
||||
long GetIndexOf(in nsISupports aPossibleElement);
|
||||
long GetIndexOfStartingAt(in nsISupports aPossibleElement,
|
||||
in unsigned long aStartIndex);
|
||||
long GetLastIndexOf(in nsISupports aPossibleElement);
|
||||
|
||||
[notxpcom] boolean InsertElementAt(in nsISupports aElement,
|
||||
@ -46,14 +52,25 @@ interface nsISupportsArray : nsICollection {
|
||||
in unsigned long aIndex);
|
||||
|
||||
[notxpcom] boolean RemoveElementAt(in unsigned long aIndex);
|
||||
[notxpcom] boolean RemoveLastElement([const] in nsISupports aElement);
|
||||
|
||||
// xpcom-compatible versions
|
||||
void DeleteLastElement(in nsISupports aElement);
|
||||
void DeleteElementAt(in unsigned long aIndex);
|
||||
|
||||
void Compact();
|
||||
|
||||
|
||||
nsISupportsArray clone();
|
||||
|
||||
[notxpcom] boolean MoveElement(in long aFrom,
|
||||
in long aTo);
|
||||
|
||||
[notxpcom] boolean RemoveElementsAt(in unsigned long aIndex,
|
||||
in unsigned long aCount);
|
||||
|
||||
[notxpcom] boolean SizeTo(in long aSize);
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -6,11 +6,79 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsSupportsArrayEnumerator.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
#define MAXSUPPORTS 20
|
||||
|
||||
class SupportsStats
|
||||
{
|
||||
public:
|
||||
SupportsStats();
|
||||
~SupportsStats();
|
||||
|
||||
};
|
||||
|
||||
static int sizesUsed; // number of the elements of the arrays used
|
||||
static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted
|
||||
static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array)
|
||||
static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used)
|
||||
static int GrowInPlace[MAXSUPPORTS];
|
||||
|
||||
// these are per-allocation
|
||||
static int MaxElements[3000];
|
||||
|
||||
// very evil
|
||||
#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
|
||||
{ \
|
||||
if (sizesAlloced[i] == (int)(size)) \
|
||||
{ ((x)[i])++; break; } \
|
||||
} \
|
||||
if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \
|
||||
{ sizesAlloced[sizesUsed] = (size); \
|
||||
((x)[sizesUsed++])++; break; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
|
||||
{ \
|
||||
if (sizesAlloced[i] == (int)(size)) \
|
||||
{ ((x)[i])--; break; } \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
|
||||
SupportsStats::SupportsStats()
|
||||
{
|
||||
sizesUsed = 1;
|
||||
sizesAlloced[0] = 0;
|
||||
}
|
||||
|
||||
SupportsStats::~SupportsStats()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizesUsed; ++i) {
|
||||
printf("Size %d:\n", sizesAlloced[i]);
|
||||
printf("\tNumber of SupportsArrays this size (max): %d\n", NumberOfSize[i]);
|
||||
printf("\tNumber of allocations this size (total): %d\n", AllocedOfSize[i]);
|
||||
printf("\tNumber of GrowsInPlace this size (total): %d\n", GrowInPlace[i]);
|
||||
}
|
||||
printf("Max Size of SupportsArray:\n");
|
||||
for (i = 0; i < (int)(sizeof(MaxElements) / sizeof(MaxElements[0])); ++i) {
|
||||
if (MaxElements[i]) {
|
||||
printf("\t%d: %d\n", i, MaxElements[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just so constructor/destructor get called
|
||||
SupportsStats gSupportsStats;
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const
|
||||
@ -28,11 +96,88 @@ nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const
|
||||
|
||||
nsSupportsArray::nsSupportsArray()
|
||||
{
|
||||
mArray = mAutoArray;
|
||||
mArraySize = kAutoArraySize;
|
||||
mCount = 0;
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
mMaxCount = 0;
|
||||
mMaxSize = 0;
|
||||
ADD_TO_STATS(NumberOfSize, kAutoArraySize * sizeof(mArray[0]));
|
||||
MaxElements[0]++;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsSupportsArray::~nsSupportsArray()
|
||||
{
|
||||
Clear();
|
||||
DeleteArray();
|
||||
}
|
||||
|
||||
bool
|
||||
nsSupportsArray::GrowArrayBy(uint32_t aGrowBy)
|
||||
{
|
||||
const uint32_t kGrowArrayBy = 8;
|
||||
const uint32_t kLinearThreshold = 16 * sizeof(nsISupports*);
|
||||
|
||||
// We have to grow the array. Grow by kGrowArrayBy slots if we're smaller
|
||||
// than kLinearThreshold bytes, or a power of two if we're larger.
|
||||
// This is much more efficient with most memory allocators, especially
|
||||
// if it's very large, or of the allocator is binned.
|
||||
if (aGrowBy < kGrowArrayBy) {
|
||||
aGrowBy = kGrowArrayBy;
|
||||
}
|
||||
|
||||
CheckedUint32 newCount(mArraySize);
|
||||
newCount += aGrowBy; // Minimum increase
|
||||
CheckedUint32 newSize(sizeof(mArray[0]));
|
||||
newSize *= newCount;
|
||||
|
||||
if (!newSize.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newSize.value() >= kLinearThreshold) {
|
||||
// newCount includes enough space for at least kGrowArrayBy new slots.
|
||||
// Select the next power-of-two size in bytes above that if newSize is
|
||||
// not a power of two.
|
||||
if (newSize.value() & (newSize.value() - 1)) {
|
||||
newSize = UINT64_C(1) << mozilla::CeilingLog2(newSize.value());
|
||||
if (!newSize.isValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
newCount = newSize / sizeof(mArray[0]);
|
||||
}
|
||||
// XXX This would be far more efficient in many allocators if we used
|
||||
// XXX PR_Realloc(), etc
|
||||
nsISupports** oldArray = mArray;
|
||||
|
||||
mArray = new nsISupports*[newCount.value()];
|
||||
mArraySize = newCount.value();
|
||||
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
if (oldArray == mArray) { // can't happen without use of realloc
|
||||
ADD_TO_STATS(GrowInPlace, mCount);
|
||||
}
|
||||
ADD_TO_STATS(AllocedOfSize, mArraySize * sizeof(mArray[0]));
|
||||
if (mArraySize > mMaxSize) {
|
||||
ADD_TO_STATS(NumberOfSize, mArraySize * sizeof(mArray[0]));
|
||||
if (oldArray != &(mAutoArray[0])) {
|
||||
SUB_FROM_STATS(NumberOfSize, mCount * sizeof(mArray[0]));
|
||||
}
|
||||
mMaxSize = mArraySize;
|
||||
}
|
||||
#endif
|
||||
if (oldArray) { // need to move old data
|
||||
if (0 < mCount) {
|
||||
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
|
||||
}
|
||||
if (oldArray != &(mAutoArray[0])) {
|
||||
delete[] oldArray;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -53,8 +198,6 @@ NS_IMPL_ISUPPORTS(nsSupportsArray, nsISupportsArray, nsICollection,
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::Read(nsIObjectInputStream* aStream)
|
||||
{
|
||||
// TODO(ER): This used to leak when resizing the array. Not sure if that was
|
||||
// intentional, I'm guessing not.
|
||||
nsresult rv;
|
||||
|
||||
uint32_t newArraySize;
|
||||
@ -63,40 +206,43 @@ nsSupportsArray::Read(nsIObjectInputStream* aStream)
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t count;
|
||||
rv = aStream->Read32(&count);
|
||||
if (newArraySize <= kAutoArraySize) {
|
||||
if (mArray != mAutoArray) {
|
||||
delete[] mArray;
|
||||
mArray = mAutoArray;
|
||||
}
|
||||
newArraySize = kAutoArraySize;
|
||||
} else {
|
||||
if (newArraySize <= mArraySize) {
|
||||
// Keep non-default-size mArray, it's more than big enough.
|
||||
newArraySize = mArraySize;
|
||||
} else {
|
||||
nsISupports** array = new nsISupports*[newArraySize];
|
||||
if (mArray != mAutoArray) {
|
||||
delete[] mArray;
|
||||
}
|
||||
mArray = array;
|
||||
}
|
||||
}
|
||||
mArraySize = newArraySize;
|
||||
|
||||
rv = aStream->Read32(&mCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ASSERTION(count <= newArraySize, "overlarge mCount!");
|
||||
if (count > newArraySize) {
|
||||
count = newArraySize;
|
||||
NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!");
|
||||
if (mCount > mArraySize) {
|
||||
mCount = mArraySize;
|
||||
}
|
||||
|
||||
// Don't clear out our array until we know we have enough space for the new
|
||||
// one and have successfully copied everything out of the stream.
|
||||
ISupportsArray tmp;
|
||||
if (!tmp.SetCapacity(newArraySize, mozilla::fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
auto elems = tmp.AppendElements(count, mozilla::fallible);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
rv = aStream->ReadObject(true, &elems[i]);
|
||||
for (uint32_t i = 0; i < mCount; i++) {
|
||||
rv = aStream->ReadObject(true, &mArray[i]);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Now clear out existing refs and replace with the new array.
|
||||
for (auto& item : mArray) {
|
||||
NS_IF_RELEASE(item);
|
||||
}
|
||||
|
||||
mArray.Clear();
|
||||
mArray.SwapElements(tmp);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -105,18 +251,18 @@ nsSupportsArray::Write(nsIObjectOutputStream* aStream)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = aStream->Write32(mArray.Capacity());
|
||||
rv = aStream->Write32(mArraySize);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = aStream->Write32(mArray.Length());
|
||||
rv = aStream->Write32(mCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
for (auto& item : mArray) {
|
||||
rv = aStream->WriteObject(item, true);
|
||||
for (uint32_t i = 0; i < mCount; i++) {
|
||||
rv = aStream->WriteObject(mArray[i], true);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -125,42 +271,141 @@ nsSupportsArray::Write(nsIObjectOutputStream* aStream)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSupportsArray::DeleteArray(void)
|
||||
{
|
||||
Clear();
|
||||
if (mArray != &(mAutoArray[0])) {
|
||||
delete[] mArray;
|
||||
mArray = mAutoArray;
|
||||
mArraySize = kAutoArraySize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::Equals(const nsISupportsArray* aOther)
|
||||
{
|
||||
if (aOther) {
|
||||
uint32_t countOther;
|
||||
nsISupportsArray* other = const_cast<nsISupportsArray*>(aOther);
|
||||
nsresult rv = other->Count(&countOther);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mCount == countOther) {
|
||||
uint32_t index = mCount;
|
||||
nsCOMPtr<nsISupports> otherElem;
|
||||
while (index--) {
|
||||
if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem)))) {
|
||||
return false;
|
||||
}
|
||||
if (mArray[index] != otherElem) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr)
|
||||
{
|
||||
NS_IF_ADDREF(*aOutPtr = mArray.SafeElementAt(aIndex, nullptr));
|
||||
*aOutPtr = nullptr;
|
||||
if (aIndex < mCount) {
|
||||
NS_IF_ADDREF(*aOutPtr = mArray[aIndex]);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(int32_t)
|
||||
nsSupportsArray::IndexOf(const nsISupports* aPossibleElement)
|
||||
{
|
||||
return mArray.IndexOf(aPossibleElement);
|
||||
return IndexOfStartingAt(aPossibleElement, 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(int32_t)
|
||||
nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement,
|
||||
uint32_t aStartIndex)
|
||||
{
|
||||
if (aStartIndex < mCount) {
|
||||
const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior
|
||||
const nsISupports** ep = (start + aStartIndex);
|
||||
const nsISupports** end = (start + mCount);
|
||||
while (ep < end) {
|
||||
if (aPossibleElement == *ep) {
|
||||
return (ep - start);
|
||||
}
|
||||
ep++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(int32_t)
|
||||
nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement)
|
||||
{
|
||||
return mArray.LastIndexOf(aPossibleElement);
|
||||
if (0 < mCount) {
|
||||
const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior
|
||||
const nsISupports** ep = (start + mCount);
|
||||
while (start <= --ep) {
|
||||
if (aPossibleElement == *ep) {
|
||||
return (ep - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex)
|
||||
{
|
||||
if (aIndex <= mCount) {
|
||||
CheckedUint32 newCount(mCount);
|
||||
newCount += 1;
|
||||
if (!newCount.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aIndex > mArray.Length() ||
|
||||
!mArray.InsertElementAt(aIndex, aElement, mozilla::fallible)) {
|
||||
return false;
|
||||
if (mArraySize < newCount.value()) {
|
||||
// need to grow the array
|
||||
if (!GrowArrayBy(1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Could be slightly more efficient if GrowArrayBy knew about the
|
||||
// split, but the difference is trivial.
|
||||
uint32_t slide = (mCount - aIndex);
|
||||
if (0 < slide) {
|
||||
::memmove(mArray + aIndex + 1, mArray + aIndex,
|
||||
slide * sizeof(nsISupports*));
|
||||
}
|
||||
|
||||
mArray[aIndex] = aElement;
|
||||
NS_IF_ADDREF(aElement);
|
||||
mCount++;
|
||||
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
if (mCount > mMaxCount &&
|
||||
mCount < (int32_t)(sizeof(MaxElements) / sizeof(MaxElements[0]))) {
|
||||
MaxElements[mCount]++;
|
||||
MaxElements[mMaxCount]--;
|
||||
mMaxCount = mCount;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(aElement);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex)
|
||||
{
|
||||
if (aIndex < mArray.Length()) {
|
||||
if (aIndex < mCount) {
|
||||
NS_IF_ADDREF(aElement); // addref first in case it's the same object!
|
||||
NS_IF_RELEASE(mArray[aIndex]);
|
||||
mArray[aIndex] = aElement;
|
||||
@ -170,11 +415,18 @@ nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::RemoveElementAt(uint32_t aIndex)
|
||||
nsSupportsArray::RemoveElementsAt(uint32_t aIndex, uint32_t aCount)
|
||||
{
|
||||
if (aIndex + 1 <= mArray.Length()) {
|
||||
NS_IF_RELEASE(mArray[aIndex]);
|
||||
mArray.RemoveElementAt(aIndex);
|
||||
if (aIndex + aCount <= mCount) {
|
||||
for (uint32_t i = 0; i < aCount; i++) {
|
||||
NS_IF_RELEASE(mArray[aIndex + i]);
|
||||
}
|
||||
mCount -= aCount;
|
||||
int32_t slide = (mCount - aIndex);
|
||||
if (0 < slide) {
|
||||
::memmove(mArray + aIndex, mArray + aIndex + aCount,
|
||||
slide * sizeof(nsISupports*));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -183,7 +435,7 @@ nsSupportsArray::RemoveElementAt(uint32_t aIndex)
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::RemoveElement(nsISupports* aElement)
|
||||
{
|
||||
int32_t theIndex = IndexOf(aElement);
|
||||
int32_t theIndex = IndexOfStartingAt(aElement, 0);
|
||||
if (theIndex >= 0) {
|
||||
return RemoveElementAt(theIndex) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -191,25 +443,137 @@ nsSupportsArray::RemoveElement(nsISupports* aElement)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::RemoveLastElement(const nsISupports* aElement)
|
||||
{
|
||||
int32_t theIndex = LastIndexOf(aElement);
|
||||
if (theIndex >= 0) {
|
||||
return RemoveElementAt(theIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::MoveElement(int32_t aFrom, int32_t aTo)
|
||||
{
|
||||
nsISupports* tempElement;
|
||||
|
||||
if (aTo == aFrom) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aTo < 0 || aFrom < 0 ||
|
||||
(uint32_t)aTo >= mCount || (uint32_t)aFrom >= mCount) {
|
||||
// can't extend the array when moving an element. Also catches mImpl = null
|
||||
return false;
|
||||
}
|
||||
tempElement = mArray[aFrom];
|
||||
|
||||
if (aTo < aFrom) {
|
||||
// Moving one element closer to the head; the elements inbetween move down
|
||||
::memmove(mArray + aTo + 1, mArray + aTo,
|
||||
(aFrom - aTo) * sizeof(mArray[0]));
|
||||
mArray[aTo] = tempElement;
|
||||
} else { // already handled aFrom == aTo
|
||||
// Moving one element closer to the tail; the elements inbetween move up
|
||||
::memmove(mArray + aFrom, mArray + aFrom + 1,
|
||||
(aTo - aFrom) * sizeof(mArray[0]));
|
||||
mArray[aTo] = tempElement;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::Clear(void)
|
||||
{
|
||||
for (auto& item : mArray) {
|
||||
NS_IF_RELEASE(item);
|
||||
if (0 < mCount) {
|
||||
do {
|
||||
--mCount;
|
||||
NS_IF_RELEASE(mArray[mCount]);
|
||||
} while (0 != mCount);
|
||||
}
|
||||
|
||||
mArray.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::Compact(void)
|
||||
{
|
||||
mArray.Compact();
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
uint32_t oldArraySize = mArraySize;
|
||||
#endif
|
||||
if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) {
|
||||
nsISupports** oldArray = mArray;
|
||||
if (mCount <= kAutoArraySize) {
|
||||
mArray = mAutoArray;
|
||||
mArraySize = kAutoArraySize;
|
||||
} else {
|
||||
mArray = new nsISupports*[mCount];
|
||||
if (!mArray) {
|
||||
mArray = oldArray;
|
||||
return NS_OK;
|
||||
}
|
||||
mArraySize = mCount;
|
||||
}
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
if (oldArray == mArray &&
|
||||
oldArray != &(mAutoArray[0])) { // can't happen without use of realloc
|
||||
ADD_TO_STATS(GrowInPlace, oldArraySize);
|
||||
}
|
||||
if (oldArray != &(mAutoArray[0])) {
|
||||
ADD_TO_STATS(AllocedOfSize, mArraySize * sizeof(mArray[0]));
|
||||
}
|
||||
#endif
|
||||
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
|
||||
delete[] oldArray;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSupportsArray::SizeTo(int32_t aSize)
|
||||
{
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
uint32_t oldArraySize = mArraySize;
|
||||
#endif
|
||||
NS_ASSERTION(aSize >= 0, "negative aSize!");
|
||||
|
||||
// XXX for aSize < mCount we could resize to mCount
|
||||
if (mArraySize == (uint32_t)aSize || (uint32_t)aSize < mCount) {
|
||||
return true; // nothing to do
|
||||
}
|
||||
|
||||
// switch back to autoarray if possible
|
||||
nsISupports** oldArray = mArray;
|
||||
if ((uint32_t)aSize <= kAutoArraySize) {
|
||||
mArray = mAutoArray;
|
||||
mArraySize = kAutoArraySize;
|
||||
} else {
|
||||
mArray = new nsISupports*[aSize];
|
||||
if (!mArray) {
|
||||
mArray = oldArray;
|
||||
return false;
|
||||
}
|
||||
mArraySize = aSize;
|
||||
}
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
if (oldArray == mArray &&
|
||||
oldArray != &(mAutoArray[0])) { // can't happen without use of realloc
|
||||
ADD_TO_STATS(GrowInPlace, oldArraySize);
|
||||
}
|
||||
if (oldArray != &(mAutoArray[0])) {
|
||||
ADD_TO_STATS(AllocedOfSize, mArraySize * sizeof(mArray[0]));
|
||||
}
|
||||
#endif
|
||||
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
|
||||
if (oldArray != mAutoArray) {
|
||||
delete[] oldArray;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::Enumerate(nsIEnumerator** aResult)
|
||||
{
|
||||
@ -228,10 +592,10 @@ nsSupportsArray::Clone(nsISupportsArray** aResult)
|
||||
return rv;
|
||||
}
|
||||
|
||||
for (auto& item : mArray) {
|
||||
// AppendElement does an odd cast of bool to nsresult, we just cast back
|
||||
// here.
|
||||
if (!(bool)newArray->AppendElement(item)) {
|
||||
uint32_t count = 0;
|
||||
Count(&count);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (!newArray->InsertElementAt(mArray[i], i)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,13 @@
|
||||
#ifndef nsSupportsArray_h__
|
||||
#define nsSupportsArray_h__
|
||||
|
||||
//#define DEBUG_SUPPORTSARRAY 1
|
||||
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
static const uint32_t kAutoArraySize = 8;
|
||||
|
||||
class nsSupportsArray final : public nsISupportsArray
|
||||
{
|
||||
~nsSupportsArray(void); // nonvirtual since we're not subclassed
|
||||
@ -28,16 +31,18 @@ public:
|
||||
// nsICollection methods:
|
||||
NS_IMETHOD Count(uint32_t* aResult) override
|
||||
{
|
||||
*aResult = mArray.Length();
|
||||
*aResult = mCount;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD GetElementAt(uint32_t aIndex, nsISupports** aResult) override;
|
||||
MOZ_MUST_USE NS_IMETHOD
|
||||
QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult) override
|
||||
{
|
||||
nsISupports* element = mArray.SafeElementAt(aIndex, nullptr);
|
||||
if (element) {
|
||||
return element->QueryInterface(aIID, aResult);
|
||||
if (aIndex < mCount) {
|
||||
nsISupports* element = mArray[aIndex];
|
||||
if (element) {
|
||||
return element->QueryInterface(aIID, aResult);
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -49,15 +54,20 @@ public:
|
||||
MOZ_MUST_USE NS_IMETHOD AppendElement(nsISupports* aElement) override
|
||||
{
|
||||
// XXX Invalid cast of bool to nsresult (bug 778110)
|
||||
return (nsresult)InsertElementAt(aElement, mArray.Length())/* ? NS_OK : NS_ERROR_FAILURE*/;
|
||||
return (nsresult)InsertElementAt(aElement, mCount)/* ? NS_OK : NS_ERROR_FAILURE*/;
|
||||
}
|
||||
// XXX this is badly named - should be RemoveFirstElement
|
||||
MOZ_MUST_USE NS_IMETHOD RemoveElement(nsISupports* aElement) override;
|
||||
MOZ_MUST_USE NS_IMETHOD_(bool) MoveElement(int32_t aFrom, int32_t aTo) override;
|
||||
NS_IMETHOD Enumerate(nsIEnumerator** aResult) override;
|
||||
NS_IMETHOD Clear(void) override;
|
||||
|
||||
// nsISupportsArray methods:
|
||||
NS_IMETHOD_(bool) Equals(const nsISupportsArray* aOther) override;
|
||||
|
||||
NS_IMETHOD_(int32_t) IndexOf(const nsISupports* aPossibleElement) override;
|
||||
NS_IMETHOD_(int32_t) IndexOfStartingAt(const nsISupports* aPossibleElement,
|
||||
uint32_t aStartIndex = 0) override;
|
||||
NS_IMETHOD_(int32_t) LastIndexOf(const nsISupports* aPossibleElement) override;
|
||||
|
||||
NS_IMETHOD GetIndexOf(nsISupports* aPossibleElement, int32_t* aResult) override
|
||||
@ -66,6 +76,13 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetIndexOfStartingAt(nsISupports* aPossibleElement,
|
||||
uint32_t aStartIndex, int32_t* aResult) override
|
||||
{
|
||||
*aResult = IndexOfStartingAt(aPossibleElement, aStartIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetLastIndexOf(nsISupports* aPossibleElement, int32_t* aResult) override
|
||||
{
|
||||
*aResult = LastIndexOf(aPossibleElement);
|
||||
@ -79,7 +96,17 @@ public:
|
||||
ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) override;
|
||||
|
||||
MOZ_MUST_USE NS_IMETHOD_(bool)
|
||||
RemoveElementAt(uint32_t aIndex) override;
|
||||
RemoveElementAt(uint32_t aIndex) override
|
||||
{
|
||||
return RemoveElementsAt(aIndex, 1);
|
||||
}
|
||||
MOZ_MUST_USE NS_IMETHOD_(bool)
|
||||
RemoveLastElement(const nsISupports* aElement) override;
|
||||
|
||||
MOZ_MUST_USE NS_IMETHOD DeleteLastElement(nsISupports* aElement) override
|
||||
{
|
||||
return (RemoveLastElement(aElement) ? NS_OK : NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE NS_IMETHOD DeleteElementAt(uint32_t aIndex) override
|
||||
{
|
||||
@ -90,12 +117,28 @@ public:
|
||||
|
||||
MOZ_MUST_USE NS_IMETHOD Clone(nsISupportsArray** aResult) override;
|
||||
|
||||
MOZ_MUST_USE NS_IMETHOD_(bool)
|
||||
RemoveElementsAt(uint32_t aIndex, uint32_t aCount) override;
|
||||
|
||||
MOZ_MUST_USE NS_IMETHOD_(bool)
|
||||
SizeTo(int32_t aSize) override;
|
||||
protected:
|
||||
void DeleteArray(void);
|
||||
|
||||
bool GrowArrayBy(uint32_t aGrowBy);
|
||||
|
||||
nsISupports** mArray;
|
||||
uint32_t mArraySize;
|
||||
uint32_t mCount;
|
||||
nsISupports* mAutoArray[kAutoArraySize];
|
||||
#if DEBUG_SUPPORTSARRAY
|
||||
uint32_t mMaxCount;
|
||||
uint32_t mMaxSize;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Copy constructors are not allowed
|
||||
explicit nsSupportsArray(const nsISupportsArray& aOther);
|
||||
|
||||
typedef AutoTArray<nsISupports*, 8> ISupportsArray;
|
||||
ISupportsArray mArray;
|
||||
};
|
||||
|
||||
#endif // nsSupportsArray_h__
|
||||
|
@ -119,19 +119,26 @@ TEST(Array, main)
|
||||
|
||||
|
||||
// test IndexOf && LastIndexOf
|
||||
int32_t expectedIndex = 0;
|
||||
int32_t expectedIndex[5] = {0, 4, 6, 12, -1};
|
||||
int32_t count = 0;
|
||||
int32_t index = array->IndexOf(foo);
|
||||
EXPECT_EQ(index, expectedIndex);
|
||||
expectedIndex = 12;
|
||||
EXPECT_EQ(index, expectedIndex[count]);
|
||||
while (-1 != index) {
|
||||
count++;
|
||||
index = array->IndexOfStartingAt(foo, index + 1);
|
||||
if (-1 != index)
|
||||
EXPECT_EQ(index, expectedIndex[count]);
|
||||
}
|
||||
index = array->LastIndexOf(foo);
|
||||
EXPECT_EQ(index, expectedIndex);
|
||||
count--;
|
||||
EXPECT_EQ(index, expectedIndex[count]);
|
||||
|
||||
// test ReplaceElementAt
|
||||
array->ReplaceElementAt(foo, 8);
|
||||
int32_t replaceResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
|
||||
CheckArray(array, 13, replaceResult, 9);
|
||||
|
||||
// test RemoveElementAt, RemoveElement
|
||||
// test RemoveElementAt, RemoveElement RemoveLastElement
|
||||
array->RemoveElementAt(0);
|
||||
int32_t removeResult[12] = {0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
|
||||
CheckArray(array, 12, removeResult, 9);
|
||||
@ -141,6 +148,9 @@ TEST(Array, main)
|
||||
array->RemoveElement(foo);
|
||||
int32_t removeResult3[10] = {0, 1, 2, 4, 3, 5, 7, 8, 9, 3};
|
||||
CheckArray(array, 10, removeResult3, 9);
|
||||
array->RemoveLastElement(foo);
|
||||
int32_t removeResult4[9] = {0, 1, 2, 4, 3, 5, 7, 8, 9};
|
||||
CheckArray(array, 9, removeResult4, 9);
|
||||
|
||||
foo = nullptr;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user