Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsSegmentedBuffer.h"
8 : #include "nsMemory.h"
9 :
10 : nsresult
11 76 : nsSegmentedBuffer::Init(uint32_t aSegmentSize, uint32_t aMaxSize)
12 : {
13 76 : if (mSegmentArrayCount != 0) {
14 0 : return NS_ERROR_FAILURE; // initialized more than once
15 : }
16 76 : mSegmentSize = aSegmentSize;
17 76 : mMaxSize = aMaxSize;
18 : #if 0 // testing...
19 : mSegmentArrayCount = 2;
20 : #else
21 76 : mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
22 : #endif
23 76 : return NS_OK;
24 : }
25 :
26 : char*
27 91 : nsSegmentedBuffer::AppendNewSegment()
28 : {
29 91 : if (GetSize() >= mMaxSize) {
30 0 : return nullptr;
31 : }
32 :
33 91 : if (!mSegmentArray) {
34 76 : uint32_t bytes = mSegmentArrayCount * sizeof(char*);
35 76 : mSegmentArray = (char**)moz_xmalloc(bytes);
36 76 : if (!mSegmentArray) {
37 0 : return nullptr;
38 : }
39 76 : memset(mSegmentArray, 0, bytes);
40 : }
41 :
42 91 : if (IsFull()) {
43 0 : uint32_t newArraySize = mSegmentArrayCount * 2;
44 0 : uint32_t bytes = newArraySize * sizeof(char*);
45 0 : char** newSegArray = (char**)moz_xrealloc(mSegmentArray, bytes);
46 0 : if (!newSegArray) {
47 0 : return nullptr;
48 : }
49 0 : mSegmentArray = newSegArray;
50 : // copy wrapped content to new extension
51 0 : if (mFirstSegmentIndex > mLastSegmentIndex) {
52 : // deal with wrap around case
53 0 : memcpy(&mSegmentArray[mSegmentArrayCount],
54 0 : mSegmentArray,
55 0 : mLastSegmentIndex * sizeof(char*));
56 0 : memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*));
57 0 : mLastSegmentIndex += mSegmentArrayCount;
58 0 : memset(&mSegmentArray[mLastSegmentIndex], 0,
59 0 : (newArraySize - mLastSegmentIndex) * sizeof(char*));
60 : } else {
61 0 : memset(&mSegmentArray[mLastSegmentIndex], 0,
62 0 : (newArraySize - mLastSegmentIndex) * sizeof(char*));
63 : }
64 0 : mSegmentArrayCount = newArraySize;
65 : }
66 :
67 91 : char* seg = (char*)malloc(mSegmentSize);
68 91 : if (!seg) {
69 0 : return nullptr;
70 : }
71 91 : mSegmentArray[mLastSegmentIndex] = seg;
72 91 : mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1);
73 91 : return seg;
74 : }
75 :
76 : bool
77 10 : nsSegmentedBuffer::DeleteFirstSegment()
78 : {
79 10 : NS_ASSERTION(mSegmentArray[mFirstSegmentIndex] != nullptr, "deleting bad segment");
80 10 : free(mSegmentArray[mFirstSegmentIndex]);
81 10 : mSegmentArray[mFirstSegmentIndex] = nullptr;
82 10 : int32_t last = ModSegArraySize(mLastSegmentIndex - 1);
83 10 : if (mFirstSegmentIndex == last) {
84 0 : mLastSegmentIndex = last;
85 0 : return true;
86 : } else {
87 10 : mFirstSegmentIndex = ModSegArraySize(mFirstSegmentIndex + 1);
88 10 : return false;
89 : }
90 : }
91 :
92 : bool
93 0 : nsSegmentedBuffer::DeleteLastSegment()
94 : {
95 0 : int32_t last = ModSegArraySize(mLastSegmentIndex - 1);
96 0 : NS_ASSERTION(mSegmentArray[last] != nullptr, "deleting bad segment");
97 0 : free(mSegmentArray[last]);
98 0 : mSegmentArray[last] = nullptr;
99 0 : mLastSegmentIndex = last;
100 0 : return (bool)(mLastSegmentIndex == mFirstSegmentIndex);
101 : }
102 :
103 : bool
104 0 : nsSegmentedBuffer::ReallocLastSegment(size_t aNewSize)
105 : {
106 0 : int32_t last = ModSegArraySize(mLastSegmentIndex - 1);
107 0 : NS_ASSERTION(mSegmentArray[last] != nullptr, "realloc'ing bad segment");
108 0 : char* newSegment = (char*)realloc(mSegmentArray[last], aNewSize);
109 0 : if (newSegment) {
110 0 : mSegmentArray[last] = newSegment;
111 0 : return true;
112 : }
113 0 : return false;
114 : }
115 :
116 : void
117 75 : nsSegmentedBuffer::Empty()
118 : {
119 75 : if (mSegmentArray) {
120 2475 : for (uint32_t i = 0; i < mSegmentArrayCount; i++) {
121 2400 : if (mSegmentArray[i]) {
122 80 : free(mSegmentArray[i]);
123 : }
124 : }
125 75 : free(mSegmentArray);
126 75 : mSegmentArray = nullptr;
127 : }
128 75 : mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
129 75 : mFirstSegmentIndex = mLastSegmentIndex = 0;
130 75 : }
131 :
132 : #if 0
133 : void
134 : TestSegmentedBuffer()
135 : {
136 : nsSegmentedBuffer* buf = new nsSegmentedBuffer();
137 : NS_ASSERTION(buf, "out of memory");
138 : buf->Init(4, 16);
139 : char* seg;
140 : bool empty;
141 : seg = buf->AppendNewSegment();
142 : NS_ASSERTION(seg, "AppendNewSegment failed");
143 : seg = buf->AppendNewSegment();
144 : NS_ASSERTION(seg, "AppendNewSegment failed");
145 : seg = buf->AppendNewSegment();
146 : NS_ASSERTION(seg, "AppendNewSegment failed");
147 : empty = buf->DeleteFirstSegment();
148 : NS_ASSERTION(!empty, "DeleteFirstSegment failed");
149 : empty = buf->DeleteFirstSegment();
150 : NS_ASSERTION(!empty, "DeleteFirstSegment failed");
151 : seg = buf->AppendNewSegment();
152 : NS_ASSERTION(seg, "AppendNewSegment failed");
153 : seg = buf->AppendNewSegment();
154 : NS_ASSERTION(seg, "AppendNewSegment failed");
155 : seg = buf->AppendNewSegment();
156 : NS_ASSERTION(seg, "AppendNewSegment failed");
157 : empty = buf->DeleteFirstSegment();
158 : NS_ASSERTION(!empty, "DeleteFirstSegment failed");
159 : empty = buf->DeleteFirstSegment();
160 : NS_ASSERTION(!empty, "DeleteFirstSegment failed");
161 : empty = buf->DeleteFirstSegment();
162 : NS_ASSERTION(!empty, "DeleteFirstSegment failed");
163 : empty = buf->DeleteFirstSegment();
164 : NS_ASSERTION(empty, "DeleteFirstSegment failed");
165 : delete buf;
166 : }
167 : #endif
168 :
169 : ////////////////////////////////////////////////////////////////////////////////
|