VirtualBox

Changeset 77236 in vbox for trunk/include/iprt/sg.h


Ignore:
Timestamp:
Feb 9, 2019 6:30:19 PM (6 years ago)
Author:
vboxsync
Message:

IPRT: Implemented RTFileSgWriteAt and RTfileSgReadAt for linux and freebsd. Clearified RTFileWriteAt and RTFileSgWriteAt specs wrt RTFILE_O_APPEND. bugref:9172

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/sg.h

    r76585 r77236  
    3333
    3434RT_C_DECLS_BEGIN
     35
     36/** @defgroup grp_rt_sgbuf  RTSgBuf - Scatter / Gather Buffers
     37 * @ingroup grp_rt
     38 * @{
     39 */
    3540
    3641/**
     
    5560 *
    5661 * The members should be treated as private.
     62 *
     63 * @warning There is a lot of code, especially in the VFS area of IPRT, that
     64 *          totally ignores the idxSeg, pvSegCur and cbSegLeft members!  So,
     65 *          it is not recommended to pass buffers that aren't fully reset or
     66 *          where cbSegLeft is shorter than what paSegs describes.
    5767 */
    5868typedef struct RTSGBUF
     
    6272    /** Number of segments. */
    6373    unsigned  cSegs;
     74
    6475    /** Current segment we are in. */
    6576    unsigned  idxSeg;
     
    7687typedef PRTSGBUF *PPRTSGBUF;
    7788
     89
     90/**
     91 * Sums up the length of all the segments.
     92 *
     93 * @returns The complete segment length.
     94 * @param   pSgBuf      The S/G buffer to check out.
     95 */
     96DECLINLINE(size_t) RTSgBufCalcTotalLength(PCRTSGBUF pSgBuf)
     97{
     98    size_t   cb = 0;
     99    unsigned i  = pSgBuf->cSegs;
     100    while (i-- > 0)
     101        cb += pSgBuf->paSegs[i].cbSeg;
     102    return cb;
     103}
     104
     105/**
     106 * Sums up the number of bytes left from the current position.
     107 *
     108 * @returns Number of bytes left.
     109 * @param   pSgBuf      The S/G buffer to check out.
     110 */
     111DECLINLINE(size_t) RTSgBufCalcLengthLeft(PCRTSGBUF pSgBuf)
     112{
     113    size_t   cb = pSgBuf->cbSegLeft;
     114    unsigned i  = pSgBuf->cSegs;
     115    while (i-- > pSgBuf->idxSeg + 1)
     116        cb += pSgBuf->paSegs[i].cbSeg;
     117    return cb;
     118}
     119
     120/**
     121 * Checks if the current buffer position is at the start of the first segment.
     122 *
     123 * @returns true / false.
     124 * @param   pSgBuf      The S/G buffer to check out.
     125 */
     126DECLINLINE(bool) RTSgBufIsAtStart(PCRTSGBUF pSgBuf)
     127{
     128    return pSgBuf->idxSeg == 0
     129        && (   pSgBuf->cSegs == 0
     130            || pSgBuf->pvSegCur == pSgBuf->paSegs[0].pvSeg);
     131}
     132
     133/**
     134 * Checks if the current buffer position is at the end of all the segments.
     135 *
     136 * @returns true / false.
     137 * @param   pSgBuf      The S/G buffer to check out.
     138 */
     139DECLINLINE(bool) RTSgBufIsAtEnd(PCRTSGBUF pSgBuf)
     140{
     141    return pSgBuf->idxSeg > pSgBuf->cSegs
     142        || (   pSgBuf->idxSeg == pSgBuf->cSegs
     143            && pSgBuf->cbSegLeft == 0);
     144}
     145
     146/**
     147 * Checks if the current buffer position is at the start of the current segment.
     148 *
     149 * @returns true / false.
     150 * @param   pSgBuf      The S/G buffer to check out.
     151 */
     152DECLINLINE(bool) RTSgBufIsAtStartOfSegment(PCRTSGBUF pSgBuf)
     153{
     154    return pSgBuf->idxSeg < pSgBuf->cSegs
     155        && pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg == pSgBuf->pvSegCur;
     156}
     157
    78158/**
    79159 * Initialize a S/G buffer structure.
     
    84164 * @param   cSegs     Number of segments in the array.
    85165 *
    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.
     166 * @note paSegs and cSegs can be NULL and 0 respectively to indicate an empty
     167 *       S/G buffer.  Operations on the S/G buffer will not do anything in this
     168 *       case.
    89169 */
    90170RTDECL(void) RTSgBufInit(PRTSGBUF pSgBuf, PCRTSGSEG paSegs, size_t cSegs);
     
    109189 */
    110190RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufNew, PCRTSGBUF pSgBufOld);
     191
     192/**
     193 * Returns the next segment in the S/G buffer or NULL if no segments left.
     194 *
     195 * @returns Pointer to the next segment in the S/G buffer.
     196 * @param   pSgBuf      The S/G buffer.
     197 * @param   cbDesired   The max number of bytes to get.
     198 * @param   pcbSeg      Where to store the size of the returned segment, this is
     199 *                      equal or smaller than @a cbDesired.
     200 *
     201 * @note    Use RTSgBufAdvance() to advance after read/writing into the buffer.
     202 */
     203DECLINLINE(void *) RTSgBufGetCurrentSegment(PRTSGBUF pSgBuf, size_t cbDesired, size_t *pcbSeg)
     204{
     205    if (!RTSgBufIsAtEnd(pSgBuf))
     206    {
     207        *pcbSeg = RT_MIN(cbDesired, pSgBuf->cbSegLeft);
     208        return pSgBuf->pvSegCur;
     209    }
     210    *pcbSeg = 0;
     211    return NULL;
     212}
    111213
    112214/**
Note: See TracChangeset for help on using the changeset viewer.

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