1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/io/nsSegmentedBuffer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,167 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsSegmentedBuffer.h" 1.10 +#include "nsMemory.h" 1.11 + 1.12 +nsresult 1.13 +nsSegmentedBuffer::Init(uint32_t segmentSize, uint32_t maxSize) 1.14 +{ 1.15 + if (mSegmentArrayCount != 0) 1.16 + return NS_ERROR_FAILURE; // initialized more than once 1.17 + mSegmentSize = segmentSize; 1.18 + mMaxSize = maxSize; 1.19 +#if 0 // testing... 1.20 + mSegmentArrayCount = 2; 1.21 +#else 1.22 + mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT; 1.23 +#endif 1.24 + return NS_OK; 1.25 +} 1.26 + 1.27 +char* 1.28 +nsSegmentedBuffer::AppendNewSegment() 1.29 +{ 1.30 + if (GetSize() >= mMaxSize) 1.31 + return nullptr; 1.32 + 1.33 + if (mSegmentArray == nullptr) { 1.34 + uint32_t bytes = mSegmentArrayCount * sizeof(char*); 1.35 + mSegmentArray = (char**)nsMemory::Alloc(bytes); 1.36 + if (mSegmentArray == nullptr) 1.37 + return nullptr; 1.38 + memset(mSegmentArray, 0, bytes); 1.39 + } 1.40 + 1.41 + if (IsFull()) { 1.42 + uint32_t newArraySize = mSegmentArrayCount * 2; 1.43 + uint32_t bytes = newArraySize * sizeof(char*); 1.44 + char** newSegArray = (char**)nsMemory::Realloc(mSegmentArray, bytes); 1.45 + if (newSegArray == nullptr) 1.46 + return nullptr; 1.47 + mSegmentArray = newSegArray; 1.48 + // copy wrapped content to new extension 1.49 + if (mFirstSegmentIndex > mLastSegmentIndex) { 1.50 + // deal with wrap around case 1.51 + memcpy(&mSegmentArray[mSegmentArrayCount], 1.52 + mSegmentArray, 1.53 + mLastSegmentIndex * sizeof(char*)); 1.54 + memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*)); 1.55 + mLastSegmentIndex += mSegmentArrayCount; 1.56 + memset(&mSegmentArray[mLastSegmentIndex], 0, 1.57 + (newArraySize - mLastSegmentIndex) * sizeof(char*)); 1.58 + } 1.59 + else { 1.60 + memset(&mSegmentArray[mLastSegmentIndex], 0, 1.61 + (newArraySize - mLastSegmentIndex) * sizeof(char*)); 1.62 + } 1.63 + mSegmentArrayCount = newArraySize; 1.64 + } 1.65 + 1.66 + char* seg = (char*)moz_malloc(mSegmentSize); 1.67 + if (seg == nullptr) { 1.68 + return nullptr; 1.69 + } 1.70 + mSegmentArray[mLastSegmentIndex] = seg; 1.71 + mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1); 1.72 + return seg; 1.73 +} 1.74 + 1.75 +bool 1.76 +nsSegmentedBuffer::DeleteFirstSegment() 1.77 +{ 1.78 + NS_ASSERTION(mSegmentArray[mFirstSegmentIndex] != nullptr, "deleting bad segment"); 1.79 + moz_free(mSegmentArray[mFirstSegmentIndex]); 1.80 + mSegmentArray[mFirstSegmentIndex] = nullptr; 1.81 + int32_t last = ModSegArraySize(mLastSegmentIndex - 1); 1.82 + if (mFirstSegmentIndex == last) { 1.83 + mLastSegmentIndex = last; 1.84 + return true; 1.85 + } 1.86 + else { 1.87 + mFirstSegmentIndex = ModSegArraySize(mFirstSegmentIndex + 1); 1.88 + return false; 1.89 + } 1.90 +} 1.91 + 1.92 +bool 1.93 +nsSegmentedBuffer::DeleteLastSegment() 1.94 +{ 1.95 + int32_t last = ModSegArraySize(mLastSegmentIndex - 1); 1.96 + NS_ASSERTION(mSegmentArray[last] != nullptr, "deleting bad segment"); 1.97 + moz_free(mSegmentArray[last]); 1.98 + mSegmentArray[last] = nullptr; 1.99 + mLastSegmentIndex = last; 1.100 + return (bool)(mLastSegmentIndex == mFirstSegmentIndex); 1.101 +} 1.102 + 1.103 +bool 1.104 +nsSegmentedBuffer::ReallocLastSegment(size_t newSize) 1.105 +{ 1.106 + int32_t last = ModSegArraySize(mLastSegmentIndex - 1); 1.107 + NS_ASSERTION(mSegmentArray[last] != nullptr, "realloc'ing bad segment"); 1.108 + char *newSegment = 1.109 + (char*)moz_realloc(mSegmentArray[last], newSize); 1.110 + if (newSegment) { 1.111 + mSegmentArray[last] = newSegment; 1.112 + return true; 1.113 + } else { 1.114 + return false; 1.115 + } 1.116 +} 1.117 + 1.118 +void 1.119 +nsSegmentedBuffer::Empty() 1.120 +{ 1.121 + if (mSegmentArray) { 1.122 + for (uint32_t i = 0; i < mSegmentArrayCount; i++) { 1.123 + if (mSegmentArray[i]) 1.124 + moz_free(mSegmentArray[i]); 1.125 + } 1.126 + nsMemory::Free(mSegmentArray); 1.127 + mSegmentArray = nullptr; 1.128 + } 1.129 + mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT; 1.130 + mFirstSegmentIndex = mLastSegmentIndex = 0; 1.131 +} 1.132 + 1.133 +#if 0 1.134 +void 1.135 +TestSegmentedBuffer() 1.136 +{ 1.137 + nsSegmentedBuffer* buf = new nsSegmentedBuffer(); 1.138 + NS_ASSERTION(buf, "out of memory"); 1.139 + buf->Init(4, 16); 1.140 + char* seg; 1.141 + bool empty; 1.142 + seg = buf->AppendNewSegment(); 1.143 + NS_ASSERTION(seg, "AppendNewSegment failed"); 1.144 + seg = buf->AppendNewSegment(); 1.145 + NS_ASSERTION(seg, "AppendNewSegment failed"); 1.146 + seg = buf->AppendNewSegment(); 1.147 + NS_ASSERTION(seg, "AppendNewSegment failed"); 1.148 + empty = buf->DeleteFirstSegment(); 1.149 + NS_ASSERTION(!empty, "DeleteFirstSegment failed"); 1.150 + empty = buf->DeleteFirstSegment(); 1.151 + NS_ASSERTION(!empty, "DeleteFirstSegment failed"); 1.152 + seg = buf->AppendNewSegment(); 1.153 + NS_ASSERTION(seg, "AppendNewSegment failed"); 1.154 + seg = buf->AppendNewSegment(); 1.155 + NS_ASSERTION(seg, "AppendNewSegment failed"); 1.156 + seg = buf->AppendNewSegment(); 1.157 + NS_ASSERTION(seg, "AppendNewSegment failed"); 1.158 + empty = buf->DeleteFirstSegment(); 1.159 + NS_ASSERTION(!empty, "DeleteFirstSegment failed"); 1.160 + empty = buf->DeleteFirstSegment(); 1.161 + NS_ASSERTION(!empty, "DeleteFirstSegment failed"); 1.162 + empty = buf->DeleteFirstSegment(); 1.163 + NS_ASSERTION(!empty, "DeleteFirstSegment failed"); 1.164 + empty = buf->DeleteFirstSegment(); 1.165 + NS_ASSERTION(empty, "DeleteFirstSegment failed"); 1.166 + delete buf; 1.167 +} 1.168 +#endif 1.169 + 1.170 +////////////////////////////////////////////////////////////////////////////////