1 /*! \file stringbuf.c
2 * \brief Implemetation of the dynamic string buffer helper object.
3 *
4 * \author Rainer Gerhards <rgerhards@adiscon.com>
5 * \date 2003-08-08
6 * Initial version begun.
7 *
8 * Copyright 2002-2014
9 * Rainer Gerhards and Adiscon GmbH. All Rights Reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are
13 * met:
14 *
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in
20 * the documentation and/or other materials provided with the
21 * distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <assert.h>
37 #include "settings.h"
38 #include "liblogging.h"
39 #include "stringbuf.h"
40 #include "srUtils.h"
41
42 /* ################################################################# *
43 * private members *
44 * ################################################################# */
45
46
47
48 /* ################################################################# *
49 * public members *
50 * ################################################################# */
51
52
sbStrBConstruct(void)53 sbStrBObj *sbStrBConstruct(void)
54 {
55 sbStrBObj *pThis;
56
57 if((pThis = calloc(1, sizeof(sbStrBObj))) == NULL)
58 return NULL;
59
60 pThis->OID = OIDsbStrB;
61 pThis->pBuf = NULL;
62 pThis->iBufSize = 0;
63 pThis->iBufPtr = 0;
64 pThis->iAllocIncrement = STRINGBUF_ALLOC_INCREMENT;
65
66 return pThis;
67 }
68
69
sbStrBDestruct(sbStrBObj * pThis)70 void sbStrBDestruct(sbStrBObj *pThis)
71 {
72 # if STRINGBUF_TRIM_ALLOCSIZE == 1
73 /* in this mode, a new buffer already was allocated,
74 * so we need to free the old one.
75 */
76 if(pThis->pBuf != NULL)
77 free(pThis->pBuf);
78 # endif
79
80 SRFREEOBJ(pThis);
81 }
82
83
sbStrBAppendStr(sbStrBObj * pThis,char * psz)84 srRetVal sbStrBAppendStr(sbStrBObj *pThis, char* psz)
85 {
86 srRetVal iRet;
87
88 sbSTRBCHECKVALIDOBJECT(pThis);
89 assert(psz != NULL);
90
91 while(*psz)
92 if((iRet = sbStrBAppendChar(pThis, *psz++)) != SR_RET_OK)
93 return iRet;
94
95 return SR_RET_OK;
96 }
97
98
sbStrBAppendInt(sbStrBObj * pThis,int i)99 srRetVal sbStrBAppendInt(sbStrBObj *pThis, int i)
100 {
101 srRetVal iRet;
102 char szBuf[32];
103
104 sbSTRBCHECKVALIDOBJECT(pThis);
105
106 if((iRet = srUtilItoA(szBuf, sizeof(szBuf), i)) != SR_RET_OK)
107 return iRet;
108
109 return sbStrBAppendStr(pThis, szBuf);
110 }
111
112
sbStrBAppendChar(sbStrBObj * pThis,char c)113 srRetVal sbStrBAppendChar(sbStrBObj *pThis, char c)
114 {
115 char* pNewBuf;
116
117 sbSTRBCHECKVALIDOBJECT(pThis);
118
119 if(pThis->iBufPtr >= pThis->iBufSize)
120 { /* need more memory! */
121 if((pNewBuf = malloc((pThis->iBufSize + pThis->iAllocIncrement) * sizeof(char))) == NULL)
122 return SR_RET_OUT_OF_MEMORY;
123 memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize);
124 pThis->iBufSize += pThis->iAllocIncrement;
125 if(pThis->pBuf != NULL)
126 free(pThis->pBuf);
127 pThis->pBuf = pNewBuf;
128 }
129
130 /* ok, when we reach this, we have sufficient memory */
131 *(pThis->pBuf + pThis->iBufPtr++) = c;
132
133 return SR_RET_OK;
134 }
135
136
sbStrBFinish(sbStrBObj * pThis)137 char* sbStrBFinish(sbStrBObj *pThis)
138 {
139 char* pRetBuf;
140
141 sbSTRBCHECKVALIDOBJECT(pThis);
142
143 sbStrBAppendChar(pThis, '\0');
144
145 # if STRINGBUF_TRIM_ALLOCSIZE == 1
146 /* in this mode, we need to trim the string. To do
147 * so, we must allocate a new buffer of the exact
148 * string size, and then copy the old one over.
149 * This new buffer is then to be returned.
150 */
151 if((pRetBuf = malloc((pThis->iBufSize + 1) * sizeof(char))) == NULL)
152 { /* OK, in this case we use the previous buffer. At least
153 * we have it ;)
154 */
155 pRetBuf = pThis->pBuf;
156 }
157 else
158 { /* got the new buffer, so let's use it */
159 memcpy(pRetBuf, pThis->pBuf, pThis->iBufPtr + 1);
160 }
161 # else
162 /* here, we can simply return a pointer to the
163 * currently existing buffer. We don't care about
164 * the extra memory, as we achieve a big performance
165 * gain.
166 */
167 pRetBuf = pThis->pBuf;
168 # endif
169
170 sbStrBDestruct(pThis);
171
172 return(pRetBuf);
173 }
174
sbStrBSetAllocIncrement(sbStrBObj * pThis,int iNewIncrement)175 void sbStrBSetAllocIncrement(sbStrBObj *pThis, int iNewIncrement)
176 {
177 sbSTRBCHECKVALIDOBJECT(pThis);
178 assert(iNewIncrement > 0);
179
180 pThis->iAllocIncrement = iNewIncrement;
181 }
182