VirtualBox

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

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

Runtime/Sg: Add a method to advance the internal buffer pointer

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/* $Id: sg.cpp 28113 2010-04-08 20:11:33Z 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, pvBuf1, cbThisCmp);
169 if (rc)
170 return rc;
171
172 cbLeft -= cbThisCmp;
173 }
174
175 return 0;
176}
177
178
179RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet)
180{
181 AssertPtrReturn(pSgBuf, 0);
182
183 size_t cbLeft = cbSet;
184
185 while (cbLeft)
186 {
187 size_t cbThisSet = cbLeft;
188 void *pvBuf = sgBufGet(pSgBuf, &cbThisSet);
189
190 if (!cbThisSet)
191 break;
192
193 memset(pvBuf, ubFill, cbThisSet);
194
195 cbLeft -= cbThisSet;
196 }
197
198 return cbSet - cbLeft;
199}
200
201
202RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
203{
204 AssertPtrReturn(pSgBuf, 0);
205 AssertPtrReturn(pvBuf, 0);
206
207 size_t cbLeft = cbCopy;
208
209 while (cbLeft)
210 {
211 size_t cbThisCopy = cbLeft;
212 void *pvSrc = sgBufGet(pSgBuf, &cbThisCopy);
213
214 if (!cbThisCopy)
215 break;
216
217 memcpy(pvBuf, pvSrc, cbThisCopy);
218
219 cbLeft -= cbThisCopy;
220 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
221 }
222
223 return cbCopy - cbLeft;
224}
225
226
227RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy)
228{
229 AssertPtrReturn(pSgBuf, 0);
230 AssertPtrReturn(pvBuf, 0);
231
232 size_t cbLeft = cbCopy;
233
234 while (cbLeft)
235 {
236 size_t cbThisCopy = cbLeft;
237 void *pvDst = sgBufGet(pSgBuf, &cbThisCopy);
238
239 if (!cbThisCopy)
240 break;
241
242 memcpy(pvDst, pvBuf, cbThisCopy);
243
244 cbLeft -= cbThisCopy;
245 pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
246 }
247
248 return cbCopy - cbLeft;
249}
250
251
252RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance)
253{
254 AssertPtrReturn(pSgBuf, 0);
255
256 size_t cbLeft = cbAdvance;
257
258 while (cbLeft)
259 {
260 size_t cbThisAdvance = cbLeft;
261 void *pv = sgBufGet(pSgBuf, &cbThisAdvance);
262
263 NOREF(pv);
264
265 if (!cbThisAdvance)
266 break;
267
268 cbLeft -= cbThisAdvance;
269 }
270
271 return cbAdvance - cbLeft;
272}
273
274
275RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData)
276{
277 AssertPtrReturn(pSgBuf, 0);
278 AssertPtrReturn(paSeg, 0);
279 AssertPtrReturn(pcSeg, 0);
280
281 size_t cb = 0;
282 unsigned cSeg = 0;
283
284 while ( cbData
285 && cSeg < *pcSeg)
286 {
287 size_t cbThisSeg = cbData;
288 void *pvSeg = NULL;
289
290 pvSeg = sgBufGet(pSgBuf, &cbThisSeg);
291
292 AssertMsg(cbThisSeg <= cbData, ("Impossible!\n"));
293
294 paSeg[cSeg].cbSeg = cbThisSeg;
295 paSeg[cSeg].pvSeg = pvSeg;
296 cSeg++;
297 cbData -= cbThisSeg;
298 cb += cbThisSeg;
299 }
300
301 *pcSeg = cSeg;
302
303 return cb;
304}
305
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