VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/sg.cpp@ 30651

Last change on this file since 30651 was 30470, checked in by vboxsync, 14 years ago

RTSgBufInit: cSegs must be size_t so RT_ELEMENTS and similar will work without causing warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: sg.cpp 30470 2010-06-28 14:03:18Z vboxsync $ */
2/** @file
3 * IPRT - S/G buffer handling.
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/sg.h>
32#include <iprt/string.h>
33#include <iprt/assert.h>
34
35
36static void *sgBufGet(PRTSGBUF pSgBuf, size_t *pcbData)
37{
38 size_t cbData = RT_MIN(*pcbData, pSgBuf->cbSegLeft);
39 void *pvBuf = pSgBuf->pvSegCur;
40
41 pSgBuf->cbSegLeft -= cbData;
42
43 /* Advance to the next segment if required. */
44 if (!pSgBuf->cbSegLeft)
45 {
46 pSgBuf->idxSeg++;
47
48 if (RT_UNLIKELY(pSgBuf->idxSeg == pSgBuf->cSegs))
49 {
50 pSgBuf->cbSegLeft = 0;
51 pSgBuf->pvSegCur = NULL;
52 }
53 else
54 {
55 pSgBuf->pvSegCur = pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg;
56 pSgBuf->cbSegLeft = pSgBuf->paSegs[pSgBuf->idxSeg].cbSeg;
57 }
58
59 *pcbData = cbData;
60 }
61 else
62 pSgBuf->pvSegCur = (uint8_t *)pSgBuf->pvSegCur + cbData;
63
64 return pvBuf;
65}
66
67
68RTDECL(void) RTSgBufInit(PRTSGBUF pSgBuf, PCRTSGSEG paSegs, size_t cSegs)
69{
70 AssertPtr(pSgBuf);
71 AssertPtr(paSegs);
72 Assert(cSegs > 0);
73 Assert(cSegs < (~(unsigned)0 >> 1));
74
75 pSgBuf->paSegs = paSegs;
76 pSgBuf->cSegs = (unsigned)cSegs;
77 pSgBuf->idxSeg = 0;
78 pSgBuf->pvSegCur = paSegs[0].pvSeg;
79 pSgBuf->cbSegLeft = paSegs[0].cbSeg;
80}
81
82
83RTDECL(void) RTSgBufReset(PRTSGBUF pSgBuf)
84{
85 AssertPtrReturnVoid(pSgBuf);
86
87 pSgBuf->idxSeg = 0;
88 pSgBuf->pvSegCur = pSgBuf->paSegs[0].pvSeg;
89 pSgBuf->cbSegLeft = pSgBuf->paSegs[0].cbSeg;
90}
91
92
93RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufTo, PCRTSGBUF pSgBufFrom)
94{
95 AssertPtr(pSgBufTo);
96 AssertPtr(pSgBufFrom);
97
98 pSgBufTo->paSegs = pSgBufFrom->paSegs;
99 pSgBufTo->cSegs = pSgBufFrom->cSegs;
100 pSgBufTo->idxSeg = pSgBufFrom->idxSeg;
101 pSgBufTo->pvSegCur = pSgBufFrom->pvSegCur;
102 pSgBufTo->cbSegLeft = pSgBufFrom->cbSegLeft;
103}
104
105
106RTDECL(size_t) RTSgBufCopy(PRTSGBUF pSgBufDst, PRTSGBUF pSgBufSrc, size_t cbCopy)
107{
108 AssertPtrReturn(pSgBufDst, 0);
109 AssertPtrReturn(pSgBufSrc, 0);
110
111 size_t cbLeft = cbCopy;
112
113 while (cbLeft)
114 {
115 size_t cbThisCopy = RT_MIN(RT_MIN(pSgBufDst->cbSegLeft, cbLeft), pSgBufSrc->cbSegLeft);
116 size_t cbTmp = cbThisCopy;
117 void *pvBufDst;
118 void *pvBufSrc;
119
120 if (!cbThisCopy)
121 break;
122
123 pvBufDst = sgBufGet(pSgBufDst, &cbTmp);
124 Assert(cbTmp == cbThisCopy);
125 pvBufSrc = sgBufGet(pSgBufSrc, &cbTmp);
126 Assert(cbTmp == cbThisCopy);
127
128 memcpy(pvBufDst, pvBufSrc, cbThisCopy);
129
130 cbLeft -= cbThisCopy;
131 }
132
133 return cbCopy - cbLeft;
134}
135
136
137RTDECL(int) RTSgBufCmp(PCRTSGBUF pSgBuf1, PCRTSGBUF pSgBuf2, size_t cbCmp)
138{
139 AssertPtrReturn(pSgBuf1, 0);
140 AssertPtrReturn(pSgBuf2, 0);
141
142 size_t cbLeft = cbCmp;
143 RTSGBUF SgBuf1;
144 RTSGBUF SgBuf2;
145
146 /* Set up the temporary buffers */
147 RTSgBufClone(&SgBuf1, pSgBuf1);
148 RTSgBufClone(&SgBuf2, pSgBuf2);
149
150 while (cbLeft)
151 {
152 size_t cbThisCmp = RT_MIN(RT_MIN(SgBuf1.cbSegLeft, cbLeft), SgBuf2.cbSegLeft);
153 size_t cbTmp = cbThisCmp;
154 void *pvBuf1;
155 void *pvBuf2;
156
157 if (!cbCmp)
158 break;
159
160 pvBuf1 = sgBufGet(&SgBuf1, &cbTmp);
161 Assert(cbTmp == cbThisCmp);
162 pvBuf2 = sgBufGet(&SgBuf2, &cbTmp);
163 Assert(cbTmp == cbThisCmp);
164
165 int rc = memcmp(pvBuf1, pvBuf2, cbThisCmp);
166 if (rc)
167 return rc;
168
169 cbLeft -= cbThisCmp;
170 }
171
172 return 0;
173}
174
175
176RTDECL(int) RTSgBufCmpEx(PRTSGBUF pSgBuf1, PRTSGBUF pSgBuf2, size_t cbCmp,
177 size_t *pcbOff, bool fAdvance)
178{
179 AssertPtrReturn(pSgBuf1, 0);
180 AssertPtrReturn(pSgBuf2, 0);
181
182 size_t cbLeft = cbCmp;
183 size_t cbOff = 0;
184 RTSGBUF SgBuf1Tmp;
185 RTSGBUF SgBuf2Tmp;
186 PRTSGBUF pSgBuf1Tmp;
187 PRTSGBUF pSgBuf2Tmp;
188
189 if (!fAdvance)
190 {
191 /* Set up the temporary buffers */
192 RTSgBufClone(&SgBuf1Tmp, pSgBuf1);
193 RTSgBufClone(&SgBuf2Tmp, pSgBuf2);
194 pSgBuf1Tmp = &SgBuf1Tmp;
195 pSgBuf2Tmp = &SgBuf2Tmp;
196 }
197 else
198 {
199 pSgBuf1Tmp = pSgBuf1;
200 pSgBuf2Tmp = pSgBuf2;
201 }
202
203 while (cbLeft)
204 {
205 size_t cbThisCmp = RT_MIN(RT_MIN(pSgBuf1Tmp->cbSegLeft, cbLeft), pSgBuf2Tmp->cbSegLeft);
206 size_t cbTmp = cbThisCmp;
207 uint8_t *pbBuf1;
208 uint8_t *pbBuf2;
209
210 if (!cbCmp)
211 break;
212
213 pbBuf1 = (uint8_t *)sgBufGet(pSgBuf1Tmp, &cbTmp);
214 Assert(cbTmp == cbThisCmp);
215 pbBuf2 = (uint8_t *)sgBufGet(pSgBuf2Tmp, &cbTmp);
216 Assert(cbTmp == cbThisCmp);
217
218 int rc = memcmp(pbBuf1, pbBuf2, cbThisCmp);
219 if (rc)
220 {
221 if (pcbOff)
222 {
223 /* Search for the correct offset */
224 while ( cbThisCmp-- > 0
225 && (*pbBuf1 == *pbBuf2))
226 {
227 pbBuf1++;
228 pbBuf2++;
229 cbOff++;
230 }
231
232 *pcbOff = cbOff;
233 }
234 return rc;
235 }
236
237 cbLeft -= cbThisCmp;
238 cbOff += cbThisCmp;
239 }
240
241 return 0;
242}
243
244
245RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet)
246{
247 AssertPtrReturn(pSgBuf, 0);
248
249 size_t cbLeft = cbSet;
250
251 while (cbLeft)
252 {
253 size_t cbThisSet = cbLeft;
254 void *pvBuf = sgBufGet(pSgBuf, &cbThisSet);
255
256 if (!cbThisSet)
257 break;
258
259 memset(pvBuf, ubFill, cbThisSet);
260
261 cbLeft -= cbThisSet;
262 }
263
264 return cbSet - cbLeft;
265}
266
267
268RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
269{
270 AssertPtrReturn(pSgBuf, 0);
271 AssertPtrReturn(pvBuf, 0);
272
273 size_t cbLeft = cbCopy;
274
275 while (cbLeft)
276 {
277 size_t cbThisCopy = cbLeft;
278 void *pvSrc = sgBufGet(pSgBuf, &cbThisCopy);
279
280 if (!cbThisCopy)
281 break;
282
283 memcpy(pvBuf, pvSrc, cbThisCopy);
284
285 cbLeft -= cbThisCopy;
286 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
287 }
288
289 return cbCopy - cbLeft;
290}
291
292
293RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
294{
295 AssertPtrReturn(pSgBuf, 0);
296 AssertPtrReturn(pvBuf, 0);
297
298 size_t cbLeft = cbCopy;
299
300 while (cbLeft)
301 {
302 size_t cbThisCopy = cbLeft;
303 void *pvDst = sgBufGet(pSgBuf, &cbThisCopy);
304
305 if (!cbThisCopy)
306 break;
307
308 memcpy(pvDst, pvBuf, cbThisCopy);
309
310 cbLeft -= cbThisCopy;
311 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
312 }
313
314 return cbCopy - cbLeft;
315}
316
317
318RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance)
319{
320 AssertPtrReturn(pSgBuf, 0);
321
322 size_t cbLeft = cbAdvance;
323
324 while (cbLeft)
325 {
326 size_t cbThisAdvance = cbLeft;
327 void *pv = sgBufGet(pSgBuf, &cbThisAdvance);
328
329 NOREF(pv);
330
331 if (!cbThisAdvance)
332 break;
333
334 cbLeft -= cbThisAdvance;
335 }
336
337 return cbAdvance - cbLeft;
338}
339
340
341RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData)
342{
343 AssertPtrReturn(pSgBuf, 0);
344 AssertPtrReturn(paSeg, 0);
345 AssertPtrReturn(pcSeg, 0);
346
347 size_t cb = 0;
348 unsigned cSeg = 0;
349
350 while ( cbData
351 && cSeg < *pcSeg)
352 {
353 size_t cbThisSeg = cbData;
354 void *pvSeg = NULL;
355
356 pvSeg = sgBufGet(pSgBuf, &cbThisSeg);
357
358 if (!cbThisSeg)
359 {
360 Assert(!pvSeg);
361 break;
362 }
363
364 AssertMsg(cbThisSeg <= cbData, ("Impossible!\n"));
365
366 paSeg[cSeg].cbSeg = cbThisSeg;
367 paSeg[cSeg].pvSeg = pvSeg;
368 cSeg++;
369 cbData -= cbThisSeg;
370 cb += cbThisSeg;
371 }
372
373 *pcSeg = cSeg;
374
375 return cb;
376}
377
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