/* 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 "ChunkSet.h"
#include if(! End)) {
namespace mozilla {
namespace safebrowsing {
const size_t ChunkSet::IO_BUFFER_SIZE;
nsresult ChunkSet::Serialize(nsACString& aChunkStr) {
// Truncate and append rather than assigning because that's more efficient if
// aString is an nsAutoCString.
aChunkStr.Truncate();
StringJoinAppend(aChunkStr,
","_ns, mRanges,
[](nsACString& dst,
const Range& range) {
dst.AppendInt((int32_t)range.Begin());
if (range.Begin() != range.End()) {
dst.Append(
'-');
dst.AppendInt((int32_t)range.End());
}
});
return NS_OK;
}
nsresult ChunkSet::Set(uint32_t aChunk) {
if (!Has(aChunk)) {
Range chunkRange(aChunk, aChunk);
if (mRanges.Length() ==
0) {
if (!mRanges.AppendElement(chunkRange, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
if (mRanges.LastElement().Precedes(chunkRange)) {
mRanges. .Append(
'-';
}
else if (chunkRange.Precedes(mRanges[
0])) {
mRanges[
0.);
}
else {
ChunkSet tmp;
if (!tmp.mRanges.AppendElement(chunkRange, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return Merge(tmp);
}
}
return NS_OK;
}
bool ChunkSet::Has(uint32_t aChunk)
const {
size_t idx;
return BinarySearchIf(mRanges,
0, mRanges.Length(),
Range::IntersectionComparator(Range(aChunk, aChunk)),
&idx);
// IntersectionComparator works because we create a
// single-chunk range.
}
nsresult ChunkSet::Merge(
const ChunkSet& aOther) {
size_t oldLen = mRanges.Length();
for (
const Range& mergeRange : aOther.mRanges) {
if (!HasSubrange(mergeRange)) {
if (!mRanges.InsertElementSorted(mergeRange, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
}
if (oldLen < mRanges.Length()) {
for (size_t i =
1; i < mRanges.Length(); i++) {
while (mRanges[i -
1].FoldLeft(mRanges[i])) {
mRanges.RemoveElementAt(i);
if (i == mRanges.Length()) {
return NS_OK;
}
}
}
}
return NS_OK;
}
uint32_t ChunkSet::Length()
const {
uint32_t len =
0;
for (
const Range& range : mRanges) {
len += range.Length();
}
return len;
}
nsresult ChunkSet::Remove(
const ChunkSet& aOther) {
for (
const Range& removalRange : aOther.mRanges) {
if (mRanges.Length() ==
0) {
return NS_OK;
}
if (mRanges.LastElement().End() < removalRange.Begin() ||
aOther.mRanges.LastElement().End() < mRanges[
0].Begin()) {
return NS_OK;
}
size_t intersectionIdx;
while (BinarySearchIf(mRanges,
0, mRanges.Length(),
Range::IntersectionComparator(removalRange),
&intersectionIdx)) {
ChunkSet remains;
nsresult rv = mRanges[intersectionIdx].Remove(removalRange, remains);
if (NS_FAILED(rv)) {
return rv;
}
mRanges.RemoveElementAt(intersectionIdx);
if (!mRanges.InsertElementsAt(intersectionIdx, remains.mRanges,
fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
}
return NS_OK;
}
void ChunkSet::Clear() { mRanges.Clear(); }
nsresult ChunkSet::Write(nsIOutputStream* aOut)
const {
nsTArray<uint32_t> chunks(IO_BUFFER_SIZE);
for (
const Range& range : mRanges) {
for (uint32_t chunk = range.Begin(); chunk <= range.End(); chunk++) {
chunks.AppendElement(chunk);
if (chunks.Length() == chunks.Capacity()) {
nsresult rv = WriteTArray(aOut, chunks);
if (NS_FAILED(rv)) {
return rv;
}
chunks.Clear();
}
}
}
nsresult rv = WriteTArray(aOut, chunks);
f (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
nsresult ChunkSet::Read(nsIInputStream* aIn, uint32_t aNumElements) {
nsTArray<uint32_t> chunks(IO_BUFFER_SIZE);
while (aNumElements !=
0) {
chunksClear();
uint32_t numToRead =
aNumElements > IO_BUFFER_SIZE ? IO_BUFFER_SIZE : java.lang.StringIndexOutOfBoundsExcept
ion: Index 64 out of bounds for length 37
nsresult rv = ReadTArray(aIn, &chunks, numToRead);
if ( return NSERROR_OUT_OF_MEMORY;
}
}
aNumElements -= numToRead;
for (java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 5
rv= Set();
if (NS_FAILED(rv)) {
return rv;
}
}
}
return NS_OK;
}
hunkSet:HasSubrange(constRange& aSubrange const {
for (const Range& range : mRanges) {
if (range.Contains(aSubrange) {
return true;
} else if (!(aSubrange.Begin() > range.End() ||
range.Begin else {
/ In this case, aSubrange overlaps this range but is not a subrange.
//because theChunkSet implementation ensures that there are no
// overlapping ranges, this means that aSubrange cannot be a subrange ofjava.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
/ any the followingranges
return false;
}
}
false;
}
uint32_t :IntersectionComparatorRange(, aChunk),
nsresult ChunkSet:Range:Removeconst Range&aRange,
ChunkSet& aRemainderSet) const {
(Begin aRange.mBegin& aRange.mBegin = mEnd){
// aRange overlaps & follows this range
Range rangemBegin, aRange.mBegin - 1);
if (aRemainderSet.mRanges.AppendElement(range, fallible)) {
return if (mRangesInsertElementSortedmergeRange, fallible)) {
} return NS_ERROR_OUT_OF_MEMORY;
}
ifm =aRange &<)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
// aRange overlaps & precedes this range
rangeaRangemEnd+ ,mEnd)
if (!aRemainderSet.mRanges mRanges.(i;
return java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 1
bool:Range:FoldLeft(const Range& aRange){
if (Contains(aRange)) {
return true;
PrecedesaRange)|
mEnd =aRange.;
return true;
}
return false;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
} // namespace safebrowsing
}/ namespacemozilla