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
31*418b791dSBob Badour FILE: AEEBufBound.c
32*418b791dSBob Badour
33*418b791dSBob Badour SERVICES:
34*418b791dSBob Badour AEEBufBound APIs
35*418b791dSBob Badour
36*418b791dSBob Badour GENERAL DESCRIPTION:
37*418b791dSBob Badour AEEBufBound provides a "bounded buffer" API that facilitates
38*418b791dSBob Badour measuring strings or character output. It's design accomodates
39*418b791dSBob Badour the implementation of functions that can have the same exact logic
40*418b791dSBob Badour for measuring and outputting char buffer content.
41*418b791dSBob Badour
42*418b791dSBob Badour REVISION HISTORY:
43*418b791dSBob Badour Sun Mar 06 11:23:10 2005 Created
44*418b791dSBob Badour
45*418b791dSBob Badour ==============================================================================*/
46*418b791dSBob Badour #include <limits.h>
47*418b791dSBob Badour #include "AEEBufBound.h"
48*418b791dSBob Badour #include "AEEstd.h"
49*418b791dSBob Badour
50*418b791dSBob Badour // Note on bounds-checking logic and saturation:
51*418b791dSBob Badour //
52*418b791dSBob Badour // Simple pointer comparisons are not adequate for bounds checking. pcBuf
53*418b791dSBob Badour // and pcEnd are assumed to be valid pointers in the address space. But
54*418b791dSBob Badour // pcWrite is not ... it is a theoretical value that can exceed pcEnd, and
55*418b791dSBob Badour // may in fact wrap around the end of the address space. In that case the
56*418b791dSBob Badour // test for (pcWrite < pcEnd) will yield TRUE, although pcWrite is outside
57*418b791dSBob Badour // the buffer. Use (pcEnd-pcWrite) > 0 to be accurate.
58*418b791dSBob Badour //
59*418b791dSBob Badour // In order to ensure this works in all cases, we need to avoid integer
60*418b791dSBob Badour // overflows. We do this by restricting pcWrite to the range
61*418b791dSBob Badour // [pcBuf..pcBuf+INT_MAX]. The ensures that pcWrite-pcBuf and pcWrite-pcBuf
62*418b791dSBob Badour // will always be valid integers. It also allows us to ensure that
63*418b791dSBob Badour // BufBound_Wrote() will not return wildly misleading results.
64*418b791dSBob Badour //
65*418b791dSBob Badour // PCSAT
66*418b791dSBob Badour // pcBuf pcEnd pcBuf+MAXINT
67*418b791dSBob Badour // |-------------------| . . . . . . . . . |
68*418b791dSBob Badour // ^ ^
69*418b791dSBob Badour // pcWrite: (a) (b)
70*418b791dSBob Badour //
71*418b791dSBob Badour
72*418b791dSBob Badour #define PCSAT(me) ((me)->pcBuf + INT_MAX)
73*418b791dSBob Badour
74*418b791dSBob Badour
75*418b791dSBob Badour // Advance me->pcWrite, saturating.
76*418b791dSBob Badour //
77*418b791dSBob Badour // On entry:
78*418b791dSBob Badour // *pnLen = number of bytes to be written (non-negative)
79*418b791dSBob Badour // On exit:
80*418b791dSBob Badour // return value = where to write (pointer into the buffer)
81*418b791dSBob Badour // *pnLen = number of bytes to write
82*418b791dSBob Badour //
83*418b791dSBob Badour static char *
BufBound_ValidateWrite(BufBound * me,int * pnLen)84*418b791dSBob Badour BufBound_ValidateWrite(BufBound *me, int *pnLen)
85*418b791dSBob Badour {
86*418b791dSBob Badour int nLen = *pnLen;
87*418b791dSBob Badour char *pcWrite = me->pcWrite;
88*418b791dSBob Badour int nMaxCopy = me->pcEnd - pcWrite; // could be negative!
89*418b791dSBob Badour
90*418b791dSBob Badour if ( nMaxCopy < nLen ) {
91*418b791dSBob Badour // Must check PCSAT to validate advance
92*418b791dSBob Badour int nMaxAdvance = PCSAT(me) - pcWrite; // max amount to advance
93*418b791dSBob Badour
94*418b791dSBob Badour if (nLen > nMaxAdvance) {
95*418b791dSBob Badour nLen = nMaxAdvance;
96*418b791dSBob Badour }
97*418b791dSBob Badour if (nMaxCopy < 0) {
98*418b791dSBob Badour nMaxCopy = 0;
99*418b791dSBob Badour }
100*418b791dSBob Badour } else {
101*418b791dSBob Badour // Simple case: all fits in the buffer
102*418b791dSBob Badour nMaxCopy = nLen;
103*418b791dSBob Badour }
104*418b791dSBob Badour
105*418b791dSBob Badour *pnLen = nMaxCopy;
106*418b791dSBob Badour me->pcWrite = pcWrite + nLen;
107*418b791dSBob Badour return pcWrite;
108*418b791dSBob Badour }
109*418b791dSBob Badour
BufBound_Write(BufBound * me,const char * pc,int nLen)110*418b791dSBob Badour void BufBound_Write(BufBound *me, const char *pc, int nLen)
111*418b791dSBob Badour {
112*418b791dSBob Badour if (nLen > 0) {
113*418b791dSBob Badour char *pcDest = BufBound_ValidateWrite(me, &nLen);
114*418b791dSBob Badour
115*418b791dSBob Badour while (--nLen >= 0) {
116*418b791dSBob Badour pcDest[nLen] = pc[nLen];
117*418b791dSBob Badour }
118*418b791dSBob Badour }
119*418b791dSBob Badour }
120*418b791dSBob Badour
BufBound_Putnc(BufBound * me,char c,int nLen)121*418b791dSBob Badour void BufBound_Putnc(BufBound *me, char c, int nLen)
122*418b791dSBob Badour {
123*418b791dSBob Badour if (nLen > 0) {
124*418b791dSBob Badour char *pcDest = BufBound_ValidateWrite(me, &nLen);
125*418b791dSBob Badour
126*418b791dSBob Badour while (--nLen >= 0) {
127*418b791dSBob Badour pcDest[nLen] = c;
128*418b791dSBob Badour }
129*418b791dSBob Badour }
130*418b791dSBob Badour }
131*418b791dSBob Badour
BufBound_Advance(BufBound * me,int nLen)132*418b791dSBob Badour void BufBound_Advance(BufBound *me, int nLen)
133*418b791dSBob Badour {
134*418b791dSBob Badour uint32 uOffset = (uint32)((me->pcWrite - me->pcBuf) + nLen);
135*418b791dSBob Badour
136*418b791dSBob Badour if (uOffset > INT_MAX) {
137*418b791dSBob Badour uOffset = INT_MAX;
138*418b791dSBob Badour if (nLen < 0) {
139*418b791dSBob Badour uOffset = 0;
140*418b791dSBob Badour }
141*418b791dSBob Badour }
142*418b791dSBob Badour me->pcWrite = me->pcBuf + uOffset;
143*418b791dSBob Badour }
144*418b791dSBob Badour
BufBound_Init(BufBound * me,char * pBuf,int nLen)145*418b791dSBob Badour void BufBound_Init(BufBound *me, char *pBuf, int nLen)
146*418b791dSBob Badour {
147*418b791dSBob Badour if (nLen < 0) {
148*418b791dSBob Badour nLen = 0;
149*418b791dSBob Badour }
150*418b791dSBob Badour me->pcWrite = me->pcBuf = pBuf;
151*418b791dSBob Badour me->pcEnd = pBuf + nLen;
152*418b791dSBob Badour }
153*418b791dSBob Badour
BufBound_Putc(BufBound * me,char c)154*418b791dSBob Badour void BufBound_Putc(BufBound *me, char c)
155*418b791dSBob Badour {
156*418b791dSBob Badour if ( (me->pcEnd - me->pcWrite) > 0) {
157*418b791dSBob Badour *me->pcWrite++ = c;
158*418b791dSBob Badour } else if (me->pcWrite != PCSAT(me)) {
159*418b791dSBob Badour ++me->pcWrite;
160*418b791dSBob Badour }
161*418b791dSBob Badour }
162*418b791dSBob Badour
BufBound_ForceNullTerm(BufBound * me)163*418b791dSBob Badour void BufBound_ForceNullTerm(BufBound *me)
164*418b791dSBob Badour {
165*418b791dSBob Badour if ( (me->pcEnd - me->pcWrite) > 0) {
166*418b791dSBob Badour *me->pcWrite++ = '\0';
167*418b791dSBob Badour } else {
168*418b791dSBob Badour if (me->pcWrite != PCSAT(me)) {
169*418b791dSBob Badour ++me->pcWrite;
170*418b791dSBob Badour }
171*418b791dSBob Badour // ensure null termination if non-empty buffer
172*418b791dSBob Badour if (me->pcEnd != me->pcBuf) {
173*418b791dSBob Badour me->pcEnd[-1] = '\0';
174*418b791dSBob Badour }
175*418b791dSBob Badour }
176*418b791dSBob Badour }
177*418b791dSBob Badour
BufBound_Puts(BufBound * me,const char * cpsz)178*418b791dSBob Badour void BufBound_Puts(BufBound *me, const char* cpsz)
179*418b791dSBob Badour {
180*418b791dSBob Badour BufBound_Write(me, cpsz, std_strlen(cpsz));
181*418b791dSBob Badour }
182*418b791dSBob Badour
BufBound_BufSize(BufBound * me)183*418b791dSBob Badour int BufBound_BufSize(BufBound* me)
184*418b791dSBob Badour {
185*418b791dSBob Badour return me->pcEnd - me->pcBuf;
186*418b791dSBob Badour }
187*418b791dSBob Badour
BufBound_Left(BufBound * me)188*418b791dSBob Badour int BufBound_Left(BufBound* me)
189*418b791dSBob Badour {
190*418b791dSBob Badour return (me->pcEnd - me->pcWrite);
191*418b791dSBob Badour }
192*418b791dSBob Badour
BufBound_ReallyWrote(BufBound * me)193*418b791dSBob Badour int BufBound_ReallyWrote(BufBound* me)
194*418b791dSBob Badour {
195*418b791dSBob Badour return STD_MIN(me->pcEnd - me->pcBuf, me->pcWrite - me->pcBuf);
196*418b791dSBob Badour }
197*418b791dSBob Badour
BufBound_Wrote(BufBound * me)198*418b791dSBob Badour int BufBound_Wrote(BufBound* me)
199*418b791dSBob Badour {
200*418b791dSBob Badour return (me->pcWrite - me->pcBuf);
201*418b791dSBob Badour }
202*418b791dSBob Badour
BufBound_WriteLE(BufBound * me,const void * pvSrc,int nSrcSize,const char * pszFields)203*418b791dSBob Badour void BufBound_WriteLE(BufBound *me,
204*418b791dSBob Badour const void *pvSrc, int nSrcSize,
205*418b791dSBob Badour const char *pszFields)
206*418b791dSBob Badour {
207*418b791dSBob Badour if (nSrcSize > 0) {
208*418b791dSBob Badour int nLen = nSrcSize;
209*418b791dSBob Badour char *pcDest = BufBound_ValidateWrite(me, &nLen);
210*418b791dSBob Badour
211*418b791dSBob Badour (void)std_CopyLE(pcDest, nLen, pvSrc, nSrcSize, pszFields);
212*418b791dSBob Badour }
213*418b791dSBob Badour }
214*418b791dSBob Badour
BufBound_WriteBE(BufBound * me,const void * pvSrc,int nSrcSize,const char * pszFields)215*418b791dSBob Badour void BufBound_WriteBE(BufBound *me,
216*418b791dSBob Badour const void *pvSrc, int nSrcSize,
217*418b791dSBob Badour const char *pszFields)
218*418b791dSBob Badour {
219*418b791dSBob Badour if (nSrcSize > 0) {
220*418b791dSBob Badour int nLen = nSrcSize;
221*418b791dSBob Badour char *pcDest = BufBound_ValidateWrite(me, &nLen);
222*418b791dSBob Badour
223*418b791dSBob Badour (void)std_CopyBE(pcDest, nLen, pvSrc, nSrcSize, pszFields);
224*418b791dSBob Badour }
225*418b791dSBob Badour }
226