VirtualBox

source: vbox/trunk/include/iprt/sg.h@ 77035

Last change on this file since 77035 was 76585, checked in by vboxsync, 6 years ago

*: scm --fix-header-guard-endif

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/** @file
2 * IPRT - S/G buffer handling.
3 */
4
5/*
6 * Copyright (C) 2010-2019 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef IPRT_INCLUDED_sg_h
27#define IPRT_INCLUDED_sg_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/types.h>
33
34RT_C_DECLS_BEGIN
35
36/**
37 * A S/G entry.
38 */
39typedef struct RTSGSEG
40{
41 /** Pointer to the segment buffer. */
42 void *pvSeg;
43 /** Size of the segment buffer. */
44 size_t cbSeg;
45} RTSGSEG;
46/** Pointer to a S/G entry. */
47typedef RTSGSEG *PRTSGSEG;
48/** Pointer to a const S/G entry. */
49typedef const RTSGSEG *PCRTSGSEG;
50/** Pointer to a S/G entry pointer. */
51typedef PRTSGSEG *PPRTSGSEG;
52
53/**
54 * A S/G buffer.
55 *
56 * The members should be treated as private.
57 */
58typedef struct RTSGBUF
59{
60 /** Pointer to the scatter/gather array. */
61 PCRTSGSEG paSegs;
62 /** Number of segments. */
63 unsigned cSegs;
64 /** Current segment we are in. */
65 unsigned idxSeg;
66 /** Pointer to the current segment start. */
67 void *pvSegCur;
68 /** Number of bytes left in the current buffer. */
69 size_t cbSegLeft;
70} RTSGBUF;
71/** Pointer to a S/G entry. */
72typedef RTSGBUF *PRTSGBUF;
73/** Pointer to a const S/G entry. */
74typedef const RTSGBUF *PCRTSGBUF;
75/** Pointer to a S/G entry pointer. */
76typedef PRTSGBUF *PPRTSGBUF;
77
78/**
79 * Initialize a S/G buffer structure.
80 *
81 * @returns nothing.
82 * @param pSgBuf Pointer to the S/G buffer to initialize.
83 * @param paSegs Pointer to the start of the segment array.
84 * @param cSegs Number of segments in the array.
85 *
86 * @note paSegs and cSegs can be NULL and 0 respectively to indicate
87 * an empty S/G buffer. All operations on the S/G buffer will
88 * not do anything in this case.
89 */
90RTDECL(void) RTSgBufInit(PRTSGBUF pSgBuf, PCRTSGSEG paSegs, size_t cSegs);
91
92/**
93 * Resets the internal buffer position of the S/G buffer to the beginning.
94 *
95 * @returns nothing.
96 * @param pSgBuf The S/G buffer to reset.
97 */
98RTDECL(void) RTSgBufReset(PRTSGBUF pSgBuf);
99
100/**
101 * Clones a given S/G buffer.
102 *
103 * @returns nothing.
104 * @param pSgBufNew The new S/G buffer to clone to.
105 * @param pSgBufOld The source S/G buffer to clone from.
106 *
107 * @note This is only a shallow copy. Both S/G buffers will point to the
108 * same segment array.
109 */
110RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufNew, PCRTSGBUF pSgBufOld);
111
112/**
113 * Returns the next segment in the S/G buffer or NULL if no segment is left.
114 *
115 * @returns Pointer to the next segment in the S/G buffer.
116 * @param pSgBuf The S/G buffer.
117 * @param pcbSeg Where to store the size of the returned segment.
118 * Holds the number of bytes requested initially or 0 to
119 * indicate that the size doesn't matter.
120 * This may contain fewer bytes on success if the current segment
121 * is smaller than the amount of bytes requested.
122 *
123 * @note This operation advances the internal buffer pointer of both S/G buffers.
124 */
125RTDECL(void *) RTSgBufGetNextSegment(PRTSGBUF pSgBuf, size_t *pcbSeg);
126
127/**
128 * Copy data between two S/G buffers.
129 *
130 * @returns The number of bytes copied.
131 * @param pSgBufDst The destination S/G buffer.
132 * @param pSgBufSrc The source S/G buffer.
133 * @param cbCopy Number of bytes to copy.
134 *
135 * @note This operation advances the internal buffer pointer of both S/G buffers.
136 */
137RTDECL(size_t) RTSgBufCopy(PRTSGBUF pSgBufDst, PRTSGBUF pSgBufSrc, size_t cbCopy);
138
139/**
140 * Compares the content of two S/G buffers.
141 *
142 * @returns Whatever memcmp returns.
143 * @param pSgBuf1 First S/G buffer.
144 * @param pSgBuf2 Second S/G buffer.
145 * @param cbCmp How many bytes to compare.
146 *
147 * @note This operation doesn't change the internal position of the S/G buffers.
148 */
149RTDECL(int) RTSgBufCmp(PCRTSGBUF pSgBuf1, PCRTSGBUF pSgBuf2, size_t cbCmp);
150
151/**
152 * Compares the content of two S/G buffers - advanced version.
153 *
154 * @returns Whatever memcmp returns.
155 * @param pSgBuf1 First S/G buffer.
156 * @param pSgBuf2 Second S/G buffer.
157 * @param cbCmp How many bytes to compare.
158 * @param poffDiff Where to store the offset of the first different byte
159 * in the buffer starting from the position of the S/G
160 * buffer before this call.
161 * @param fAdvance Flag whether the internal buffer position should be advanced.
162 *
163 */
164RTDECL(int) RTSgBufCmpEx(PRTSGBUF pSgBuf1, PRTSGBUF pSgBuf2, size_t cbCmp, size_t *poffDiff, bool fAdvance);
165
166/**
167 * Fills an S/G buf with a constant byte.
168 *
169 * @returns The number of actually filled bytes.
170 * Can be less than than cbSet if the end of the S/G buffer was reached.
171 * @param pSgBuf The S/G buffer.
172 * @param ubFill The byte to fill the buffer with.
173 * @param cbSet How many bytes to set.
174 *
175 * @note This operation advances the internal buffer pointer of the S/G buffer.
176 */
177RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet);
178
179/**
180 * Copies data from an S/G buffer into a given non scattered buffer.
181 *
182 * @returns Number of bytes copied.
183 * @param pSgBuf The S/G buffer to copy from.
184 * @param pvBuf Buffer to copy the data into.
185 * @param cbCopy How many bytes to copy.
186 *
187 * @note This operation advances the internal buffer pointer of the S/G buffer.
188 */
189RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy);
190
191/**
192 * Copies data from a non scattered buffer into an S/G buffer.
193 *
194 * @returns Number of bytes copied.
195 * @param pSgBuf The S/G buffer to copy to.
196 * @param pvBuf Buffer to copy the data from.
197 * @param cbCopy How many bytes to copy.
198 *
199 * @note This operation advances the internal buffer pointer of the S/G buffer.
200 */
201RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, const void *pvBuf, size_t cbCopy);
202
203/**
204 * Advances the internal buffer pointer.
205 *
206 * @returns Number of bytes the pointer was moved forward.
207 * @param pSgBuf The S/G buffer.
208 * @param cbAdvance Number of bytes to move forward.
209 */
210RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance);
211
212/**
213 * Constructs a new segment array starting from the current position
214 * and describing the given number of bytes.
215 *
216 * @returns Number of bytes the array describes.
217 * @param pSgBuf The S/G buffer.
218 * @param paSeg The uninitialized segment array.
219 * If NULL pcSeg will contain the number of segments needed
220 * to describe the requested amount of data.
221 * @param pcSeg The number of segments the given array has.
222 * This will hold the actual number of entries needed upon return.
223 * @param cbData Number of bytes the new array should describe.
224 *
225 * @note This operation advances the internal buffer pointer of the S/G buffer if paSeg is not NULL.
226 */
227RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData);
228
229/**
230 * Returns whether the given S/G buffer is zeroed out from the current position
231 * upto the number of bytes to check.
232 *
233 * @returns true if the buffer has only zeros
234 * false otherwise.
235 * @param pSgBuf The S/G buffer.
236 * @param cbCheck Number of bytes to check.
237 */
238RTDECL(bool) RTSgBufIsZero(PRTSGBUF pSgBuf, size_t cbCheck);
239
240/**
241 * Maps the given S/G buffer to a segment array of another type (for example to
242 * iovec on POSIX or WSABUF on Windows).
243 *
244 * @param paMapped Where to store the pointer to the start of the native
245 * array or NULL. The memory needs to be freed with
246 * RTMemTmpFree().
247 * @param pSgBuf The S/G buffer to map.
248 * @param Struct Struct used as the destination.
249 * @param pvBufField Name of the field holding the pointer to a buffer.
250 * @param TypeBufPtr Type of the buffer pointer.
251 * @param cbBufField Name of the field holding the size of the buffer.
252 * @param TypeBufSize Type of the field for the buffer size.
253 * @param cSegsMapped Where to store the number of segments the native array
254 * has.
255 *
256 * @note This operation maps the whole S/G buffer starting at the current
257 * internal position. The internal buffer position is unchanged by
258 * this operation.
259 *
260 * @remark Usage is a bit ugly but saves a few lines of duplicated code
261 * somewhere else and makes it possible to keep the S/G buffer members
262 * private without going through RTSgBufSegArrayCreate() first.
263 */
264#define RTSgBufMapToNative(paMapped, pSgBuf, Struct, pvBufField, TypeBufPtr, cbBufField, TypeBufSize, cSegsMapped) \
265 do \
266 { \
267 AssertCompileMemberSize(Struct, pvBufField, RT_SIZEOFMEMB(RTSGSEG, pvSeg)); \
268 /*AssertCompile(RT_SIZEOFMEMB(Struct, cbBufField) >= RT_SIZEOFMEMB(RTSGSEG, cbSeg));*/ \
269 (cSegsMapped) = (pSgBuf)->cSegs - (pSgBuf)->idxSeg; \
270 \
271 /* We need room for at least one segment. */ \
272 if ((pSgBuf)->cSegs == (pSgBuf)->idxSeg) \
273 (cSegsMapped)++; \
274 \
275 (paMapped) = (Struct *)RTMemTmpAllocZ((cSegsMapped) * sizeof(Struct)); \
276 if ((paMapped)) \
277 { \
278 /* The first buffer is special because we could be in the middle of a segment. */ \
279 (paMapped)[0].pvBufField = (TypeBufPtr)(pSgBuf)->pvSegCur; \
280 (paMapped)[0].cbBufField = (TypeBufSize)(pSgBuf)->cbSegLeft; \
281 \
282 for (unsigned i = 1; i < (cSegsMapped); i++) \
283 { \
284 (paMapped)[i].pvBufField = (TypeBufPtr)(pSgBuf)->paSegs[(pSgBuf)->idxSeg + i].pvSeg; \
285 (paMapped)[i].cbBufField = (TypeBufSize)(pSgBuf)->paSegs[(pSgBuf)->idxSeg + i].cbSeg; \
286 } \
287 } \
288 } while (0)
289
290RT_C_DECLS_END
291
292/** @} */
293
294#endif /* !IPRT_INCLUDED_sg_h */
295
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