VirtualBox

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

Last change on this file since 28117 was 28117, checked in by vboxsync, 15 years ago

Runtime/Sg: Add advanced compare method

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: sg.cpp 28117 2010-04-08 21:38:35Z vboxsync $ */
2/** @file
3 * IPRT - S/G buffer handling.
4 */
5
6/*
7 * Copyright (C) 2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/sg.h>
36#include <iprt/string.h>
37#include <iprt/assert.h>
38
39
40static void *sgBufGet(PRTSGBUF pSgBuf, size_t *pcbData)
41{
42 size_t cbData = RT_MIN(*pcbData, pSgBuf->cbSegLeft);
43 void *pvBuf = pSgBuf->pvSegCurr;
44
45 pSgBuf->cbSegLeft -= cbData;
46
47 /* Advance to the next segment if required. */
48 if (!pSgBuf->cbSegLeft)
49 {
50 pSgBuf->idxSeg++;
51
52 if (RT_UNLIKELY(pSgBuf->idxSeg == pSgBuf->cSeg))
53 {
54 pSgBuf->cbSegLeft = 0;
55 pSgBuf->pvSegCurr = NULL;
56 }
57 else
58 {
59 pSgBuf->pvSegCurr = pSgBuf->pcaSeg[pSgBuf->idxSeg].pvSeg;
60 pSgBuf->cbSegLeft = pSgBuf->pcaSeg[pSgBuf->idxSeg].cbSeg;
61 }
62
63 *pcbData = cbData;
64 }
65 else
66 pSgBuf->pvSegCurr = (void *)((uintptr_t)pSgBuf->pvSegCurr + cbData);
67
68 return pvBuf;
69}
70
71
72RTDECL(void) RTSgBufInit(PRTSGBUF pSgBuf, PCRTSGSEG pcaSeg, unsigned cSeg)
73{
74 AssertPtrReturnVoid(pSgBuf);
75 AssertPtrReturnVoid(pcaSeg);
76 AssertReturnVoid(cSeg > 0);
77
78 pSgBuf->pcaSeg = pcaSeg;
79 pSgBuf->cSeg = cSeg;
80 pSgBuf->idxSeg = 0;
81 pSgBuf->pvSegCurr = pcaSeg[0].pvSeg;
82 pSgBuf->cbSegLeft = pcaSeg[0].cbSeg;
83}
84
85
86RTDECL(void) RTSgBufReset(PRTSGBUF pSgBuf)
87{
88 AssertPtrReturnVoid(pSgBuf);
89
90 pSgBuf->idxSeg = 0;
91 pSgBuf->pvSegCurr = pSgBuf->pcaSeg[0].pvSeg;
92 pSgBuf->cbSegLeft = pSgBuf->pcaSeg[0].cbSeg;
93}
94
95
96RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufTo, PCRTSGBUF pSgBufFrom)
97{
98 AssertPtrReturnVoid(pSgBufTo);
99 AssertPtrReturnVoid(pSgBufFrom);
100
101 pSgBufTo->pcaSeg = pSgBufFrom->pcaSeg;
102 pSgBufTo->cSeg = pSgBufFrom->cSeg;
103 pSgBufTo->idxSeg = pSgBufFrom->idxSeg;
104 pSgBufTo->pvSegCurr = pSgBufFrom->pvSegCurr;
105 pSgBufTo->cbSegLeft = pSgBufFrom->cbSegLeft;
106}
107
108
109RTDECL(size_t) RTSgBufCopy(PRTSGBUF pSgBufDst, PRTSGBUF pSgBufSrc, size_t cbCopy)
110{
111 AssertPtrReturn(pSgBufDst, 0);
112 AssertPtrReturn(pSgBufSrc, 0);
113
114 size_t cbLeft = cbCopy;
115
116 while (cbLeft)
117 {
118 size_t cbThisCopy = RT_MIN(RT_MIN(pSgBufDst->cbSegLeft, cbLeft), pSgBufSrc->cbSegLeft);
119 size_t cbTmp = cbThisCopy;
120 void *pvBufDst;
121 void *pvBufSrc;
122
123 if (!cbCopy)
124 break;
125
126 pvBufDst = sgBufGet(pSgBufDst, &cbTmp);
127 Assert(cbTmp == cbThisCopy);
128 pvBufSrc = sgBufGet(pSgBufDst, &cbTmp);
129 Assert(cbTmp == cbThisCopy);
130
131 memcpy(pvBufDst, pvBufSrc, cbThisCopy);
132
133 cbLeft -= cbThisCopy;
134 }
135
136 return cbCopy - cbLeft;
137}
138
139
140RTDECL(int) RTSgBufCmp(PCRTSGBUF pSgBuf1, PCRTSGBUF pSgBuf2, size_t cbCmp)
141{
142 AssertPtrReturn(pSgBuf1, 0);
143 AssertPtrReturn(pSgBuf2, 0);
144
145 size_t cbLeft = cbCmp;
146 RTSGBUF SgBuf1;
147 RTSGBUF SgBuf2;
148
149 /* Set up the temporary buffers */
150 RTSgBufClone(&SgBuf1, pSgBuf1);
151 RTSgBufClone(&SgBuf2, pSgBuf2);
152
153 while (cbLeft)
154 {
155 size_t cbThisCmp = RT_MIN(RT_MIN(SgBuf1.cbSegLeft, cbLeft), SgBuf2.cbSegLeft);
156 size_t cbTmp = cbThisCmp;
157 void *pvBuf1;
158 void *pvBuf2;
159
160 if (!cbCmp)
161 break;
162
163 pvBuf1 = sgBufGet(&SgBuf1, &cbTmp);
164 Assert(cbTmp == cbThisCmp);
165 pvBuf2 = sgBufGet(&SgBuf2, &cbTmp);
166 Assert(cbTmp == cbThisCmp);
167
168 int rc = memcmp(pvBuf1, pvBuf2, cbThisCmp);
169 if (rc)
170 return rc;
171
172 cbLeft -= cbThisCmp;
173 }
174
175 return 0;
176}
177
178
179RTDECL(int) RTSgBufCmpEx(PRTSGBUF pSgBuf1, PRTSGBUF pSgBuf2, size_t cbCmp,
180 size_t *pcbOff, bool fAdvance)
181{
182 AssertPtrReturn(pSgBuf1, 0);
183 AssertPtrReturn(pSgBuf2, 0);
184
185 size_t cbLeft = cbCmp;
186 size_t cbOff = 0;
187 RTSGBUF SgBuf1Tmp;
188 RTSGBUF SgBuf2Tmp;
189 PRTSGBUF pSgBuf1Tmp;
190 PRTSGBUF pSgBuf2Tmp;
191
192 if (!fAdvance)
193 {
194 /* Set up the temporary buffers */
195 RTSgBufClone(&SgBuf1Tmp, pSgBuf1);
196 RTSgBufClone(&SgBuf2Tmp, pSgBuf2);
197 pSgBuf1Tmp = &SgBuf1Tmp;
198 pSgBuf2Tmp = &SgBuf2Tmp;
199 }
200 else
201 {
202 pSgBuf1Tmp = pSgBuf1;
203 pSgBuf2Tmp = pSgBuf2;
204 }
205
206 while (cbLeft)
207 {
208 size_t cbThisCmp = RT_MIN(RT_MIN(pSgBuf1Tmp->cbSegLeft, cbLeft), pSgBuf2Tmp->cbSegLeft);
209 size_t cbTmp = cbThisCmp;
210 uint8_t *pbBuf1;
211 uint8_t *pbBuf2;
212
213 if (!cbCmp)
214 break;
215
216 pbBuf1 = (uint8_t *)sgBufGet(pSgBuf1Tmp, &cbTmp);
217 Assert(cbTmp == cbThisCmp);
218 pbBuf2 = (uint8_t *)sgBufGet(pSgBuf2Tmp, &cbTmp);
219 Assert(cbTmp == cbThisCmp);
220
221 int rc = memcmp(pbBuf1, pbBuf2, cbThisCmp);
222 if (rc)
223 {
224 if (pcbOff)
225 {
226 /* Search for the correct offset */
227 while ( cbThisCmp-- > 0
228 && (*pbBuf1 == *pbBuf2))
229 {
230 pbBuf1++;
231 pbBuf2++;
232 cbOff++;
233 }
234
235 *pcbOff = cbOff;
236 }
237 return rc;
238 }
239
240 cbLeft -= cbThisCmp;
241 cbOff += cbThisCmp;
242 }
243
244 return 0;
245}
246
247
248RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet)
249{
250 AssertPtrReturn(pSgBuf, 0);
251
252 size_t cbLeft = cbSet;
253
254 while (cbLeft)
255 {
256 size_t cbThisSet = cbLeft;
257 void *pvBuf = sgBufGet(pSgBuf, &cbThisSet);
258
259 if (!cbThisSet)
260 break;
261
262 memset(pvBuf, ubFill, cbThisSet);
263
264 cbLeft -= cbThisSet;
265 }
266
267 return cbSet - cbLeft;
268}
269
270
271RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
272{
273 AssertPtrReturn(pSgBuf, 0);
274 AssertPtrReturn(pvBuf, 0);
275
276 size_t cbLeft = cbCopy;
277
278 while (cbLeft)
279 {
280 size_t cbThisCopy = cbLeft;
281 void *pvSrc = sgBufGet(pSgBuf, &cbThisCopy);
282
283 if (!cbThisCopy)
284 break;
285
286 memcpy(pvBuf, pvSrc, cbThisCopy);
287
288 cbLeft -= cbThisCopy;
289 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
290 }
291
292 return cbCopy - cbLeft;
293}
294
295
296RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
297{
298 AssertPtrReturn(pSgBuf, 0);
299 AssertPtrReturn(pvBuf, 0);
300
301 size_t cbLeft = cbCopy;
302
303 while (cbLeft)
304 {
305 size_t cbThisCopy = cbLeft;
306 void *pvDst = sgBufGet(pSgBuf, &cbThisCopy);
307
308 if (!cbThisCopy)
309 break;
310
311 memcpy(pvDst, pvBuf, cbThisCopy);
312
313 cbLeft -= cbThisCopy;
314 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
315 }
316
317 return cbCopy - cbLeft;
318}
319
320
321RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance)
322{
323 AssertPtrReturn(pSgBuf, 0);
324
325 size_t cbLeft = cbAdvance;
326
327 while (cbLeft)
328 {
329 size_t cbThisAdvance = cbLeft;
330 void *pv = sgBufGet(pSgBuf, &cbThisAdvance);
331
332 NOREF(pv);
333
334 if (!cbThisAdvance)
335 break;
336
337 cbLeft -= cbThisAdvance;
338 }
339
340 return cbAdvance - cbLeft;
341}
342
343
344RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData)
345{
346 AssertPtrReturn(pSgBuf, 0);
347 AssertPtrReturn(paSeg, 0);
348 AssertPtrReturn(pcSeg, 0);
349
350 size_t cb = 0;
351 unsigned cSeg = 0;
352
353 while ( cbData
354 && cSeg < *pcSeg)
355 {
356 size_t cbThisSeg = cbData;
357 void *pvSeg = NULL;
358
359 pvSeg = sgBufGet(pSgBuf, &cbThisSeg);
360
361 AssertMsg(cbThisSeg <= cbData, ("Impossible!\n"));
362
363 paSeg[cSeg].cbSeg = cbThisSeg;
364 paSeg[cSeg].pvSeg = pvSeg;
365 cSeg++;
366 cbData -= cbThisSeg;
367 cb += cbThisSeg;
368 }
369
370 *pcSeg = cSeg;
371
372 return cb;
373}
374
Note: See TracBrowser for help on using the repository browser.

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