michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsSegmentedBuffer.h" michael@0: #include "nsMemory.h" michael@0: michael@0: nsresult michael@0: nsSegmentedBuffer::Init(uint32_t segmentSize, uint32_t maxSize) michael@0: { michael@0: if (mSegmentArrayCount != 0) michael@0: return NS_ERROR_FAILURE; // initialized more than once michael@0: mSegmentSize = segmentSize; michael@0: mMaxSize = maxSize; michael@0: #if 0 // testing... michael@0: mSegmentArrayCount = 2; michael@0: #else michael@0: mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT; michael@0: #endif michael@0: return NS_OK; michael@0: } michael@0: michael@0: char* michael@0: nsSegmentedBuffer::AppendNewSegment() michael@0: { michael@0: if (GetSize() >= mMaxSize) michael@0: return nullptr; michael@0: michael@0: if (mSegmentArray == nullptr) { michael@0: uint32_t bytes = mSegmentArrayCount * sizeof(char*); michael@0: mSegmentArray = (char**)nsMemory::Alloc(bytes); michael@0: if (mSegmentArray == nullptr) michael@0: return nullptr; michael@0: memset(mSegmentArray, 0, bytes); michael@0: } michael@0: michael@0: if (IsFull()) { michael@0: uint32_t newArraySize = mSegmentArrayCount * 2; michael@0: uint32_t bytes = newArraySize * sizeof(char*); michael@0: char** newSegArray = (char**)nsMemory::Realloc(mSegmentArray, bytes); michael@0: if (newSegArray == nullptr) michael@0: return nullptr; michael@0: mSegmentArray = newSegArray; michael@0: // copy wrapped content to new extension michael@0: if (mFirstSegmentIndex > mLastSegmentIndex) { michael@0: // deal with wrap around case michael@0: memcpy(&mSegmentArray[mSegmentArrayCount], michael@0: mSegmentArray, michael@0: mLastSegmentIndex * sizeof(char*)); michael@0: memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*)); michael@0: mLastSegmentIndex += mSegmentArrayCount; michael@0: memset(&mSegmentArray[mLastSegmentIndex], 0, michael@0: (newArraySize - mLastSegmentIndex) * sizeof(char*)); michael@0: } michael@0: else { michael@0: memset(&mSegmentArray[mLastSegmentIndex], 0, michael@0: (newArraySize - mLastSegmentIndex) * sizeof(char*)); michael@0: } michael@0: mSegmentArrayCount = newArraySize; michael@0: } michael@0: michael@0: char* seg = (char*)moz_malloc(mSegmentSize); michael@0: if (seg == nullptr) { michael@0: return nullptr; michael@0: } michael@0: mSegmentArray[mLastSegmentIndex] = seg; michael@0: mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1); michael@0: return seg; michael@0: } michael@0: michael@0: bool michael@0: nsSegmentedBuffer::DeleteFirstSegment() michael@0: { michael@0: NS_ASSERTION(mSegmentArray[mFirstSegmentIndex] != nullptr, "deleting bad segment"); michael@0: moz_free(mSegmentArray[mFirstSegmentIndex]); michael@0: mSegmentArray[mFirstSegmentIndex] = nullptr; michael@0: int32_t last = ModSegArraySize(mLastSegmentIndex - 1); michael@0: if (mFirstSegmentIndex == last) { michael@0: mLastSegmentIndex = last; michael@0: return true; michael@0: } michael@0: else { michael@0: mFirstSegmentIndex = ModSegArraySize(mFirstSegmentIndex + 1); michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: bool michael@0: nsSegmentedBuffer::DeleteLastSegment() michael@0: { michael@0: int32_t last = ModSegArraySize(mLastSegmentIndex - 1); michael@0: NS_ASSERTION(mSegmentArray[last] != nullptr, "deleting bad segment"); michael@0: moz_free(mSegmentArray[last]); michael@0: mSegmentArray[last] = nullptr; michael@0: mLastSegmentIndex = last; michael@0: return (bool)(mLastSegmentIndex == mFirstSegmentIndex); michael@0: } michael@0: michael@0: bool michael@0: nsSegmentedBuffer::ReallocLastSegment(size_t newSize) michael@0: { michael@0: int32_t last = ModSegArraySize(mLastSegmentIndex - 1); michael@0: NS_ASSERTION(mSegmentArray[last] != nullptr, "realloc'ing bad segment"); michael@0: char *newSegment = michael@0: (char*)moz_realloc(mSegmentArray[last], newSize); michael@0: if (newSegment) { michael@0: mSegmentArray[last] = newSegment; michael@0: return true; michael@0: } else { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsSegmentedBuffer::Empty() michael@0: { michael@0: if (mSegmentArray) { michael@0: for (uint32_t i = 0; i < mSegmentArrayCount; i++) { michael@0: if (mSegmentArray[i]) michael@0: moz_free(mSegmentArray[i]); michael@0: } michael@0: nsMemory::Free(mSegmentArray); michael@0: mSegmentArray = nullptr; michael@0: } michael@0: mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT; michael@0: mFirstSegmentIndex = mLastSegmentIndex = 0; michael@0: } michael@0: michael@0: #if 0 michael@0: void michael@0: TestSegmentedBuffer() michael@0: { michael@0: nsSegmentedBuffer* buf = new nsSegmentedBuffer(); michael@0: NS_ASSERTION(buf, "out of memory"); michael@0: buf->Init(4, 16); michael@0: char* seg; michael@0: bool empty; michael@0: seg = buf->AppendNewSegment(); michael@0: NS_ASSERTION(seg, "AppendNewSegment failed"); michael@0: seg = buf->AppendNewSegment(); michael@0: NS_ASSERTION(seg, "AppendNewSegment failed"); michael@0: seg = buf->AppendNewSegment(); michael@0: NS_ASSERTION(seg, "AppendNewSegment failed"); michael@0: empty = buf->DeleteFirstSegment(); michael@0: NS_ASSERTION(!empty, "DeleteFirstSegment failed"); michael@0: empty = buf->DeleteFirstSegment(); michael@0: NS_ASSERTION(!empty, "DeleteFirstSegment failed"); michael@0: seg = buf->AppendNewSegment(); michael@0: NS_ASSERTION(seg, "AppendNewSegment failed"); michael@0: seg = buf->AppendNewSegment(); michael@0: NS_ASSERTION(seg, "AppendNewSegment failed"); michael@0: seg = buf->AppendNewSegment(); michael@0: NS_ASSERTION(seg, "AppendNewSegment failed"); michael@0: empty = buf->DeleteFirstSegment(); michael@0: NS_ASSERTION(!empty, "DeleteFirstSegment failed"); michael@0: empty = buf->DeleteFirstSegment(); michael@0: NS_ASSERTION(!empty, "DeleteFirstSegment failed"); michael@0: empty = buf->DeleteFirstSegment(); michael@0: NS_ASSERTION(!empty, "DeleteFirstSegment failed"); michael@0: empty = buf->DeleteFirstSegment(); michael@0: NS_ASSERTION(empty, "DeleteFirstSegment failed"); michael@0: delete buf; michael@0: } michael@0: #endif michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////////