xref: /aosp_15_r20/external/fastrpc/inc/sbuf.h (revision 418b791d679beb2078b579a3b6936cf330c41799)
1*418b791dSBob Badour /**
2*418b791dSBob Badour  * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3*418b791dSBob Badour  *
4*418b791dSBob Badour  * Redistribution and use in source and binary forms, with or without
5*418b791dSBob Badour  * modification, are permitted provided that the following conditions are
6*418b791dSBob Badour  * met:
7*418b791dSBob Badour  *    * Redistributions of source code must retain the above copyright
8*418b791dSBob Badour  *      notice, this list of conditions and the following disclaimer.
9*418b791dSBob Badour  *    * Redistributions in binary form must reproduce the above
10*418b791dSBob Badour  *      copyright notice, this list of conditions and the following
11*418b791dSBob Badour  *      disclaimer in the documentation and/or other materials provided
12*418b791dSBob Badour  *      with the distribution.
13*418b791dSBob Badour  *    * Neither the name of The Linux Foundation nor the names of its
14*418b791dSBob Badour  *      contributors may be used to endorse or promote products derived
15*418b791dSBob Badour  *      from this software without specific prior written permission.
16*418b791dSBob Badour  *
17*418b791dSBob Badour  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18*418b791dSBob Badour  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*418b791dSBob Badour  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20*418b791dSBob Badour  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21*418b791dSBob Badour  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*418b791dSBob Badour  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*418b791dSBob Badour  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24*418b791dSBob Badour  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25*418b791dSBob Badour  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26*418b791dSBob Badour  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*418b791dSBob Badour  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*418b791dSBob Badour  */
29*418b791dSBob Badour 
30*418b791dSBob Badour #ifndef SBUF_H
31*418b791dSBob Badour #define SBUF_H
32*418b791dSBob Badour 
33*418b791dSBob Badour #include <string.h>
34*418b791dSBob Badour #include <stdint.h>
35*418b791dSBob Badour #include "AEEstd.h"
36*418b791dSBob Badour 
37*418b791dSBob Badour /**
38*418b791dSBob Badour  * lightweight serialize/deserialize buffer.
39*418b791dSBob Badour 
40*418b791dSBob Badour    For example
41*418b791dSBob Badour 
42*418b791dSBob Badour    struct sbuf;
43*418b791dSBob Badour    //initialize empty buffer;
44*418b791dSBob Badour    sbuf_init(&sbuf, 0, 0, 0);
45*418b791dSBob Badour 
46*418b791dSBob Badour    //fill it with data
47*418b791dSBob Badour    sbuf_align(&sbuf, 8);
48*418b791dSBob Badour    sbuf_write(&sbuf, ptr1, 10);
49*418b791dSBob Badour    sbuf_align(&sbuf, 8);
50*418b791dSBob Badour    sbuf_write(&sbuf, ptr2, 20);
51*418b791dSBob Badour 
52*418b791dSBob Badour    //allocate the memory needed
53*418b791dSBob Badour    mem = malloc(sbuf_needed(&sbuf));
54*418b791dSBob Badour 
55*418b791dSBob Badour    //initialize with the data
56*418b791dSBob Badour    sbuf_init(&sbuf, 0, mem, sbuf_needed(&sbuf));
57*418b791dSBob Badour 
58*418b791dSBob Badour    //fill it with data, since it has memory, it will actually copy
59*418b791dSBob Badour    sbuf_align(&sbuf, 8);
60*418b791dSBob Badour    sbuf_write(&sbuf, ptr1, 10);
61*418b791dSBob Badour    sbuf_align(&sbuf, 8);
62*418b791dSBob Badour    sbuf_write(&sbuf, ptr2, 20);
63*418b791dSBob Badour 
64*418b791dSBob Badour    See sbuf_q.c for more examples
65*418b791dSBob Badour  */
66*418b791dSBob Badour 
67*418b791dSBob Badour 
68*418b791dSBob Badour struct sbuf {
69*418b791dSBob Badour    uintptr_t buf;      //! start of valid memory
70*418b791dSBob Badour    uintptr_t bufEnd;   //! end of valid memory
71*418b791dSBob Badour    uintptr_t bufStart; //! start with optinal offset from valid mem
72*418b791dSBob Badour    uintptr_t bufCur;   //! current position, could be outside of valid range
73*418b791dSBob Badour };
74*418b791dSBob Badour 
75*418b791dSBob Badour /**
76*418b791dSBob Badour  * @param buf, the buffer structure instance
77*418b791dSBob Badour  * @param offset, this value indicates how far ahead the data buffer is
78*418b791dSBob Badour  *                start = data - offset
79*418b791dSBob Badour  * @param data, the valid memory
80*418b791dSBob Badour  * @param dataLen, the length ov valid memory
81*418b791dSBob Badour  */
sbuf_init(struct sbuf * buf,int offset,void * data,int dataLen)82*418b791dSBob Badour static __inline void sbuf_init(struct sbuf* buf, int offset, void* data, int dataLen) {
83*418b791dSBob Badour    buf->buf = (uintptr_t)data;
84*418b791dSBob Badour    buf->bufStart = buf->bufCur = (uintptr_t)data - offset;
85*418b791dSBob Badour    buf->bufEnd = (uintptr_t)data + dataLen;
86*418b791dSBob Badour }
87*418b791dSBob Badour 
88*418b791dSBob Badour //! move the current pointer by len
sbuf_advance(struct sbuf * buf,int len)89*418b791dSBob Badour static __inline void sbuf_advance(struct sbuf* buf, int len) {
90*418b791dSBob Badour    buf->bufCur += len;
91*418b791dSBob Badour }
92*418b791dSBob Badour 
93*418b791dSBob Badour /**
94*418b791dSBob Badour  * @retval, the amount of memory needed for everything from the start (with the offset)
95*418b791dSBob Badour  * to the current position of the buffer
96*418b791dSBob Badour  */
sbuf_needed(struct sbuf * buf)97*418b791dSBob Badour static __inline int sbuf_needed(struct sbuf* buf) {
98*418b791dSBob Badour    return buf->bufCur - buf->bufStart;
99*418b791dSBob Badour }
100*418b791dSBob Badour /**
101*418b791dSBob Badour  * @retval, the space left in the buffer. A negative value indicates overflow.
102*418b791dSBob Badour  *          A positive value includes the offset.
103*418b791dSBob Badour  */
sbuf_left(struct sbuf * buf)104*418b791dSBob Badour static __inline int sbuf_left(struct sbuf* buf) {
105*418b791dSBob Badour    return buf->bufEnd - buf->bufCur;
106*418b791dSBob Badour }
107*418b791dSBob Badour 
108*418b791dSBob Badour //! @retval the current head pointer
sbuf_head(struct sbuf * buf)109*418b791dSBob Badour static __inline void* sbuf_head(struct sbuf* buf) {
110*418b791dSBob Badour    return (void*)buf->bufCur;
111*418b791dSBob Badour }
112*418b791dSBob Badour 
113*418b791dSBob Badour //! @retval true if the current pointer is valid
sbuf_valid(struct sbuf * buf)114*418b791dSBob Badour static __inline int sbuf_valid(struct sbuf* buf) {
115*418b791dSBob Badour    return buf->bufCur >= buf->buf && buf->bufCur < buf->bufEnd;
116*418b791dSBob Badour }
117*418b791dSBob Badour 
118*418b791dSBob Badour //! advance the head pointer so the "needed" is aligned to the align value
119*418b791dSBob Badour #define _SBUF_ALIGN(x, y) (((x) + ((y)-1)) & ~((y)-1))
sbuf_align(struct sbuf * buf,uint32_t align)120*418b791dSBob Badour static __inline void sbuf_align(struct sbuf* buf, uint32_t align) {
121*418b791dSBob Badour    sbuf_advance(buf, _SBUF_ALIGN(sbuf_needed(buf), align) - sbuf_needed(buf));
122*418b791dSBob Badour }
123*418b791dSBob Badour 
124*418b791dSBob Badour /**
125*418b791dSBob Badour  * Write to the buffer.
126*418b791dSBob Badour  * @param src, the memory to read from.  Will write srcLen bytes to buf from src
127*418b791dSBob Badour  *             from the buf's current position.  Only the valid portion of data will
128*418b791dSBob Badour  *             be written.
129*418b791dSBob Badour  * @param srcLen, the length of src.  The buffer will be advanced by srcLen.
130*418b791dSBob Badour  */
sbuf_write(struct sbuf * buf,void * psrc,int srcLen)131*418b791dSBob Badour static __inline void sbuf_write(struct sbuf* buf, void *psrc, int srcLen) {
132*418b791dSBob Badour    uintptr_t src = (uintptr_t)psrc;
133*418b791dSBob Badour    if(buf->bufCur + srcLen > buf->buf) {
134*418b791dSBob Badour       int writeLen;
135*418b791dSBob Badour       if(buf->bufCur < buf->buf) {
136*418b791dSBob Badour          int len = buf->buf - buf->bufCur;
137*418b791dSBob Badour          srcLen -= len;
138*418b791dSBob Badour          src += len;
139*418b791dSBob Badour          sbuf_advance(buf, len);
140*418b791dSBob Badour       }
141*418b791dSBob Badour       writeLen = STD_MIN(srcLen, sbuf_left(buf));
142*418b791dSBob Badour       if(writeLen > 0) {
143*418b791dSBob Badour          std_memsmove((void*)buf->bufCur, buf->bufEnd - buf->bufCur, (void*)src, writeLen);
144*418b791dSBob Badour       }
145*418b791dSBob Badour    }
146*418b791dSBob Badour    sbuf_advance(buf, srcLen);
147*418b791dSBob Badour }
148*418b791dSBob Badour 
149*418b791dSBob Badour /**
150*418b791dSBob Badour  * Read from the buffer into dst.
151*418b791dSBob Badour  * @param dst, the data to write to. Will write dstLen to dst from buf
152*418b791dSBob Badour  *             from the current position of buf.  Only valid memory
153*418b791dSBob Badour  *             will be written to dst.  Invalid overlapping memory will
154*418b791dSBob Badour  *             remain untouched.
155*418b791dSBob Badour  * @param dstLen, the length of dst.  buf will be advanced by dstLen
156*418b791dSBob Badour  */
sbuf_read(struct sbuf * buf,void * pdst,int dstLen)157*418b791dSBob Badour static __inline void sbuf_read(struct sbuf* buf, void *pdst, int dstLen) {
158*418b791dSBob Badour    uintptr_t dst = (uintptr_t)pdst;
159*418b791dSBob Badour    if(buf->bufCur + dstLen > buf->buf) {
160*418b791dSBob Badour       int readLen;
161*418b791dSBob Badour       if(buf->bufCur < buf->buf) {
162*418b791dSBob Badour          int len = buf->buf - buf->bufCur;
163*418b791dSBob Badour          dstLen -= len;
164*418b791dSBob Badour          dst += len;
165*418b791dSBob Badour          sbuf_advance(buf, len);
166*418b791dSBob Badour       }
167*418b791dSBob Badour       readLen = STD_MIN(dstLen, sbuf_left(buf));
168*418b791dSBob Badour       if(readLen > 0) {
169*418b791dSBob Badour          std_memsmove((void*)dst, dstLen, (void*)buf->bufCur, readLen);
170*418b791dSBob Badour       }
171*418b791dSBob Badour    }
172*418b791dSBob Badour    sbuf_advance(buf, dstLen);
173*418b791dSBob Badour }
174*418b791dSBob Badour 
175*418b791dSBob Badour #endif
176