VirtualBox

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

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

IPRT:

  • Corrected RTSGBUF member names.
  • Corrected RTSgBufInit parameter names.
  • Don't use AssertReturnVoid (and variations) in RTSgBuf* as there the result is that we use uninitialized structures. Better to crash and burn in IPRT then.
  • Added RTSocketSgWriteL/LV and RTTcpSgWriteL/LV for lazy guys like me.
  • RTSocketSgWrite doesn't need a do {} while (0).
  • 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 30468 2010-06-28 13:58:04Z 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, unsigned cSegs)
69{
70 AssertPtr(pSgBuf);
71 AssertPtr(paSegs);
72 Assert(cSegs > 0);
73
74 pSgBuf->paSegs = paSegs;
75 pSgBuf->cSegs = cSegs;
76 pSgBuf->idxSeg = 0;
77 pSgBuf->pvSegCur = paSegs[0].pvSeg;
78 pSgBuf->cbSegLeft = paSegs[0].cbSeg;
79}
80
81
82RTDECL(void) RTSgBufReset(PRTSGBUF pSgBuf)
83{
84 AssertPtrReturnVoid(pSgBuf);
85
86 pSgBuf->idxSeg = 0;
87 pSgBuf->pvSegCur = pSgBuf->paSegs[0].pvSeg;
88 pSgBuf->cbSegLeft = pSgBuf->paSegs[0].cbSeg;
89}
90
91
92RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufTo, PCRTSGBUF pSgBufFrom)
93{
94 AssertPtr(pSgBufTo);
95 AssertPtr(pSgBufFrom);
96
97 pSgBufTo->paSegs = pSgBufFrom->paSegs;
98 pSgBufTo->cSegs = pSgBufFrom->cSegs;
99 pSgBufTo->idxSeg = pSgBufFrom->idxSeg;
100 pSgBufTo->pvSegCur = pSgBufFrom->pvSegCur;
101 pSgBufTo->cbSegLeft = pSgBufFrom->cbSegLeft;
102}
103
104
105RTDECL(size_t) RTSgBufCopy(PRTSGBUF pSgBufDst, PRTSGBUF pSgBufSrc, size_t cbCopy)
106{
107 AssertPtrReturn(pSgBufDst, 0);
108 AssertPtrReturn(pSgBufSrc, 0);
109
110 size_t cbLeft = cbCopy;
111
112 while (cbLeft)
113 {
114 size_t cbThisCopy = RT_MIN(RT_MIN(pSgBufDst->cbSegLeft, cbLeft), pSgBufSrc->cbSegLeft);
115 size_t cbTmp = cbThisCopy;
116 void *pvBufDst;
117 void *pvBufSrc;
118
119 if (!cbThisCopy)
120 break;
121
122 pvBufDst = sgBufGet(pSgBufDst, &cbTmp);
123 Assert(cbTmp == cbThisCopy);
124 pvBufSrc = sgBufGet(pSgBufSrc, &cbTmp);
125 Assert(cbTmp == cbThisCopy);
126
127 memcpy(pvBufDst, pvBufSrc, cbThisCopy);
128
129 cbLeft -= cbThisCopy;
130 }
131
132 return cbCopy - cbLeft;
133}
134
135
136RTDECL(int) RTSgBufCmp(PCRTSGBUF pSgBuf1, PCRTSGBUF pSgBuf2, size_t cbCmp)
137{
138 AssertPtrReturn(pSgBuf1, 0);
139 AssertPtrReturn(pSgBuf2, 0);
140
141 size_t cbLeft = cbCmp;
142 RTSGBUF SgBuf1;
143 RTSGBUF SgBuf2;
144
145 /* Set up the temporary buffers */
146 RTSgBufClone(&SgBuf1, pSgBuf1);
147 RTSgBufClone(&SgBuf2, pSgBuf2);
148
149 while (cbLeft)
150 {
151 size_t cbThisCmp = RT_MIN(RT_MIN(SgBuf1.cbSegLeft, cbLeft), SgBuf2.cbSegLeft);
152 size_t cbTmp = cbThisCmp;
153 void *pvBuf1;
154 void *pvBuf2;
155
156 if (!cbCmp)
157 break;
158
159 pvBuf1 = sgBufGet(&SgBuf1, &cbTmp);
160 Assert(cbTmp == cbThisCmp);
161 pvBuf2 = sgBufGet(&SgBuf2, &cbTmp);
162 Assert(cbTmp == cbThisCmp);
163
164 int rc = memcmp(pvBuf1, pvBuf2, cbThisCmp);
165 if (rc)
166 return rc;
167
168 cbLeft -= cbThisCmp;
169 }
170
171 return 0;
172}
173
174
175RTDECL(int) RTSgBufCmpEx(PRTSGBUF pSgBuf1, PRTSGBUF pSgBuf2, size_t cbCmp,
176 size_t *pcbOff, bool fAdvance)
177{
178 AssertPtrReturn(pSgBuf1, 0);
179 AssertPtrReturn(pSgBuf2, 0);
180
181 size_t cbLeft = cbCmp;
182 size_t cbOff = 0;
183 RTSGBUF SgBuf1Tmp;
184 RTSGBUF SgBuf2Tmp;
185 PRTSGBUF pSgBuf1Tmp;
186 PRTSGBUF pSgBuf2Tmp;
187
188 if (!fAdvance)
189 {
190 /* Set up the temporary buffers */
191 RTSgBufClone(&SgBuf1Tmp, pSgBuf1);
192 RTSgBufClone(&SgBuf2Tmp, pSgBuf2);
193 pSgBuf1Tmp = &SgBuf1Tmp;
194 pSgBuf2Tmp = &SgBuf2Tmp;
195 }
196 else
197 {
198 pSgBuf1Tmp = pSgBuf1;
199 pSgBuf2Tmp = pSgBuf2;
200 }
201
202 while (cbLeft)
203 {
204 size_t cbThisCmp = RT_MIN(RT_MIN(pSgBuf1Tmp->cbSegLeft, cbLeft), pSgBuf2Tmp->cbSegLeft);
205 size_t cbTmp = cbThisCmp;
206 uint8_t *pbBuf1;
207 uint8_t *pbBuf2;
208
209 if (!cbCmp)
210 break;
211
212 pbBuf1 = (uint8_t *)sgBufGet(pSgBuf1Tmp, &cbTmp);
213 Assert(cbTmp == cbThisCmp);
214 pbBuf2 = (uint8_t *)sgBufGet(pSgBuf2Tmp, &cbTmp);
215 Assert(cbTmp == cbThisCmp);
216
217 int rc = memcmp(pbBuf1, pbBuf2, cbThisCmp);
218 if (rc)
219 {
220 if (pcbOff)
221 {
222 /* Search for the correct offset */
223 while ( cbThisCmp-- > 0
224 && (*pbBuf1 == *pbBuf2))
225 {
226 pbBuf1++;
227 pbBuf2++;
228 cbOff++;
229 }
230
231 *pcbOff = cbOff;
232 }
233 return rc;
234 }
235
236 cbLeft -= cbThisCmp;
237 cbOff += cbThisCmp;
238 }
239
240 return 0;
241}
242
243
244RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet)
245{
246 AssertPtrReturn(pSgBuf, 0);
247
248 size_t cbLeft = cbSet;
249
250 while (cbLeft)
251 {
252 size_t cbThisSet = cbLeft;
253 void *pvBuf = sgBufGet(pSgBuf, &cbThisSet);
254
255 if (!cbThisSet)
256 break;
257
258 memset(pvBuf, ubFill, cbThisSet);
259
260 cbLeft -= cbThisSet;
261 }
262
263 return cbSet - cbLeft;
264}
265
266
267RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
268{
269 AssertPtrReturn(pSgBuf, 0);
270 AssertPtrReturn(pvBuf, 0);
271
272 size_t cbLeft = cbCopy;
273
274 while (cbLeft)
275 {
276 size_t cbThisCopy = cbLeft;
277 void *pvSrc = sgBufGet(pSgBuf, &cbThisCopy);
278
279 if (!cbThisCopy)
280 break;
281
282 memcpy(pvBuf, pvSrc, cbThisCopy);
283
284 cbLeft -= cbThisCopy;
285 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
286 }
287
288 return cbCopy - cbLeft;
289}
290
291
292RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
293{
294 AssertPtrReturn(pSgBuf, 0);
295 AssertPtrReturn(pvBuf, 0);
296
297 size_t cbLeft = cbCopy;
298
299 while (cbLeft)
300 {
301 size_t cbThisCopy = cbLeft;
302 void *pvDst = sgBufGet(pSgBuf, &cbThisCopy);
303
304 if (!cbThisCopy)
305 break;
306
307 memcpy(pvDst, pvBuf, cbThisCopy);
308
309 cbLeft -= cbThisCopy;
310 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
311 }
312
313 return cbCopy - cbLeft;
314}
315
316
317RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance)
318{
319 AssertPtrReturn(pSgBuf, 0);
320
321 size_t cbLeft = cbAdvance;
322
323 while (cbLeft)
324 {
325 size_t cbThisAdvance = cbLeft;
326 void *pv = sgBufGet(pSgBuf, &cbThisAdvance);
327
328 NOREF(pv);
329
330 if (!cbThisAdvance)
331 break;
332
333 cbLeft -= cbThisAdvance;
334 }
335
336 return cbAdvance - cbLeft;
337}
338
339
340RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData)
341{
342 AssertPtrReturn(pSgBuf, 0);
343 AssertPtrReturn(paSeg, 0);
344 AssertPtrReturn(pcSeg, 0);
345
346 size_t cb = 0;
347 unsigned cSeg = 0;
348
349 while ( cbData
350 && cSeg < *pcSeg)
351 {
352 size_t cbThisSeg = cbData;
353 void *pvSeg = NULL;
354
355 pvSeg = sgBufGet(pSgBuf, &cbThisSeg);
356
357 if (!cbThisSeg)
358 {
359 Assert(!pvSeg);
360 break;
361 }
362
363 AssertMsg(cbThisSeg <= cbData, ("Impossible!\n"));
364
365 paSeg[cSeg].cbSeg = cbThisSeg;
366 paSeg[cSeg].pvSeg = pvSeg;
367 cSeg++;
368 cbData -= cbThisSeg;
369 cb += cbThisSeg;
370 }
371
372 *pcSeg = cSeg;
373
374 return cb;
375}
376
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