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