VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp@ 95259

Last change on this file since 95259 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include "nsSegmentedBuffer.h"
39#include "nsCRT.h"
40
41nsresult
42nsSegmentedBuffer::Init(PRUint32 segmentSize, PRUint32 maxSize,
43 nsIMemory* allocator)
44{
45 if (mSegmentArrayCount != 0)
46 return NS_ERROR_FAILURE; // initialized more than once
47 mSegmentSize = segmentSize;
48 mMaxSize = maxSize;
49 mSegAllocator = allocator;
50 if (mSegAllocator == nsnull) {
51 mSegAllocator = nsMemory::GetGlobalMemoryService();
52 }
53 else {
54 NS_ADDREF(mSegAllocator);
55 }
56#if 0 // testing...
57 mSegmentArrayCount = 2;
58#else
59 mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
60#endif
61 return NS_OK;
62}
63
64char*
65nsSegmentedBuffer::AppendNewSegment()
66{
67 if (GetSize() >= mMaxSize)
68 return nsnull;
69
70 if (mSegmentArray == nsnull) {
71 PRUint32 bytes = mSegmentArrayCount * sizeof(char*);
72 mSegmentArray = (char**)nsMemory::Alloc(bytes);
73 if (mSegmentArray == nsnull)
74 return nsnull;
75 memset(mSegmentArray, 0, bytes);
76 }
77
78 if (IsFull()) {
79 PRUint32 newArraySize = mSegmentArrayCount * 2;
80 PRUint32 bytes = newArraySize * sizeof(char*);
81 char** newSegArray = (char**)nsMemory::Realloc(mSegmentArray, bytes);
82 if (newSegArray == nsnull)
83 return nsnull;
84 mSegmentArray = newSegArray;
85 // copy wrapped content to new extension
86 if (mFirstSegmentIndex > mLastSegmentIndex) {
87 // deal with wrap around case
88 memcpy(&mSegmentArray[mSegmentArrayCount],
89 mSegmentArray,
90 mLastSegmentIndex * sizeof(char*));
91 memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*));
92 mLastSegmentIndex += mSegmentArrayCount;
93 memset(&mSegmentArray[mLastSegmentIndex], 0,
94 (newArraySize - mLastSegmentIndex) * sizeof(char*));
95 }
96 else {
97 memset(&mSegmentArray[mLastSegmentIndex], 0,
98 (newArraySize - mLastSegmentIndex) * sizeof(char*));
99 }
100 mSegmentArrayCount = newArraySize;
101 }
102
103 char* seg = (char*)mSegAllocator->Alloc(mSegmentSize);
104 if (seg == nsnull) {
105 return nsnull;
106 }
107 mSegmentArray[mLastSegmentIndex] = seg;
108 mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1);
109 return seg;
110}
111
112PRBool
113nsSegmentedBuffer::DeleteFirstSegment()
114{
115 NS_ASSERTION(mSegmentArray[mFirstSegmentIndex] != nsnull, "deleting bad segment");
116 (void)mSegAllocator->Free(mSegmentArray[mFirstSegmentIndex]);
117 mSegmentArray[mFirstSegmentIndex] = nsnull;
118 PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
119 if (mFirstSegmentIndex == last) {
120 mLastSegmentIndex = last;
121 return PR_TRUE;
122 }
123 else {
124 mFirstSegmentIndex = ModSegArraySize(mFirstSegmentIndex + 1);
125 return PR_FALSE;
126 }
127}
128
129PRBool
130nsSegmentedBuffer::DeleteLastSegment()
131{
132 PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
133 NS_ASSERTION(mSegmentArray[last] != nsnull, "deleting bad segment");
134 (void)mSegAllocator->Free(mSegmentArray[last]);
135 mSegmentArray[last] = nsnull;
136 mLastSegmentIndex = last;
137 return (PRBool)(mLastSegmentIndex == mFirstSegmentIndex);
138}
139
140PRBool
141nsSegmentedBuffer::ReallocLastSegment(size_t newSize)
142{
143 PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
144 NS_ASSERTION(mSegmentArray[last] != nsnull, "realloc'ing bad segment");
145 char *newSegment =
146 (char*)mSegAllocator->Realloc(mSegmentArray[last], newSize);
147 if (newSegment) {
148 mSegmentArray[last] = newSegment;
149 return PR_TRUE;
150 } else {
151 return PR_FALSE;
152 }
153}
154
155void
156nsSegmentedBuffer::Empty()
157{
158 if (mSegmentArray) {
159 for (PRUint32 i = 0; i < mSegmentArrayCount; i++) {
160 if (mSegmentArray[i])
161 mSegAllocator->Free(mSegmentArray[i]);
162 }
163 nsMemory::Free(mSegmentArray);
164 mSegmentArray = nsnull;
165 }
166 mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
167 mFirstSegmentIndex = mLastSegmentIndex = 0;
168}
169
170#ifdef DEBUG
171NS_COM void
172TestSegmentedBuffer()
173{
174 nsSegmentedBuffer* buf = new nsSegmentedBuffer();
175 NS_ASSERTION(buf, "out of memory");
176 buf->Init(4, 16);
177 char* seg;
178 PRBool empty;
179 seg = buf->AppendNewSegment();
180 NS_ASSERTION(seg, "AppendNewSegment failed");
181 seg = buf->AppendNewSegment();
182 NS_ASSERTION(seg, "AppendNewSegment failed");
183 seg = buf->AppendNewSegment();
184 NS_ASSERTION(seg, "AppendNewSegment failed");
185 empty = buf->DeleteFirstSegment();
186 NS_ASSERTION(!empty, "DeleteFirstSegment failed");
187 empty = buf->DeleteFirstSegment();
188 NS_ASSERTION(!empty, "DeleteFirstSegment failed");
189 seg = buf->AppendNewSegment();
190 NS_ASSERTION(seg, "AppendNewSegment failed");
191 seg = buf->AppendNewSegment();
192 NS_ASSERTION(seg, "AppendNewSegment failed");
193 seg = buf->AppendNewSegment();
194 NS_ASSERTION(seg, "AppendNewSegment failed");
195 empty = buf->DeleteFirstSegment();
196 NS_ASSERTION(!empty, "DeleteFirstSegment failed");
197 empty = buf->DeleteFirstSegment();
198 NS_ASSERTION(!empty, "DeleteFirstSegment failed");
199 empty = buf->DeleteFirstSegment();
200 NS_ASSERTION(!empty, "DeleteFirstSegment failed");
201 empty = buf->DeleteFirstSegment();
202 NS_ASSERTION(empty, "DeleteFirstSegment failed");
203 delete buf;
204}
205#endif
206
207////////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette