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