]> git.ipfire.org Git - thirdparty/sarg.git/blame - stringbuffer.c
Optimize away a useless strcpy.
[thirdparty/sarg.git] / stringbuffer.c
CommitLineData
6068ae56
FM
1/*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
6068ae56
FM
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26/*!\file
27\brief Efficient? strings storage
28
29Store strings in a globaly allocated memory to avoid memory waste and
30memory fragmentation.
31*/
32
33#include "include/conf.h"
34#include "include/stringbuffer.h"
35
36//! Default size of the string buffer (I hope it fits inside one memory page).
37#define STRINGBUFFER_SIZE (4096-sizeof(struct StringBufferStruct))
38
39/*!
40 * \brief String storage data.
41 *
42 * Strings are concatenated in fixed size buffers. The buffers are linked
43 * in a list. New buffers are added as the previous buffers are filled.
44 */
45struct StringBufferStruct
46{
47 //! Next buffer in the chained list.
48 StringBufferObject Next;
49 //! How many buffer bytes are left.
50 int BytesLeft;
51 //! Where the strings are stored.
52 char *Buffer;
53};
54
55/*!
56 * Create an object to store constant strings.
57 *
58 * \return The created object or NULL if it failed.
59 */
60StringBufferObject StringBuffer_Create(void)
61{
62 StringBufferObject SObj;
63
64 SObj=(StringBufferObject)calloc(1,sizeof(*SObj));
65 if (!SObj) return(NULL);
66 return(SObj);
67}
68
69/*!
70 * Destroy the object created by StringBuffer_Create().
71 *
72 * Any string pointer to the destroyed object becomes invalid.
73 *
74 * \param SPtr A pointer to the object created by StringBuffer_Create().
75 * The pointer is reset to NULL before the functrion returns to prevent
76 * subsequent use of the freed pointer.
77 */
78void StringBuffer_Destroy(StringBufferObject *SPtr)
79{
80 StringBufferObject SObj;
81 StringBufferObject Next;
82
83 if (!SPtr || !*SPtr) return;
84 SObj=*SPtr;
85 *SPtr=NULL;
86
87 while (SObj)
88 {
89 Next=SObj->Next;
90 if (SObj->Buffer) free(SObj->Buffer);
91 free(SObj);
92 SObj=Next;
93 }
94}
95
96/*!
97 * Store a string in an existing buffer.
98 */
99static char *StringBuffer_StoreInBuffer(StringBufferObject SObj,const char *String,int Length)
100{
101 int Start=0;
102
103 if (SObj->Buffer)
104 {
105 Start=STRINGBUFFER_SIZE-SObj->BytesLeft;
106 }
107 else if (Length>=STRINGBUFFER_SIZE)
108 {
109 SObj->BytesLeft=Length+1;
110 SObj->Buffer=malloc(SObj->BytesLeft);
111 }
112 else
113 {
114 SObj->BytesLeft=STRINGBUFFER_SIZE;
115 SObj->Buffer=malloc(SObj->BytesLeft);
116 }
117 if (!SObj->Buffer) return(NULL);
118 strncpy(SObj->Buffer+Start,String,Length);
119 SObj->Buffer[Start+Length]='\0';
120 SObj->BytesLeft-=Length+1;
121 return(SObj->Buffer+Start);
122}
123
124/*!
125 * Add a string to the buffer. Duplicate strings are not merged.
126 * Each call to this function stores one copy of the string.
127 *
128 * \param SObj The string buffer object.
129 * \param String The string to store.
130 * \param Length The length of the string.
131 *
132 * \return The pointer to the stored string or NULL if the function
133 * failed. The returned string may be altered or truncated but not
134 * appended to.
135 */
136char *StringBuffer_StoreLength(StringBufferObject SObj,const char *String,int Length)
137{
138 StringBufferObject SLast;
139 char *Ptr;
140
141 if (!SObj) return(NULL);
142
143 // find a suitable buffer
144 SLast=NULL;
145 while (SObj)
146 {
147 if (!SObj->Buffer || Length<SObj->BytesLeft)
148 {
149 return(StringBuffer_StoreInBuffer(SObj,String,Length));
150 }
151 SLast=SObj;
152 SObj=SObj->Next;
153 }
154
155 // create a new buffer
156 SObj=(StringBufferObject)calloc(1,sizeof(*SObj));
157 if (!SObj) return(NULL);
158 Ptr=StringBuffer_StoreInBuffer(SObj,String,Length);
159 if (!Ptr)
160 {
161 free(SObj);
162 return(NULL);
163 }
164 SLast->Next=SObj;
165 return(Ptr);
166}
167
168/*!
169 * Add a string to the buffer. Duplicate strings are not merged.
170 * Each call to this function stores one copy of the string.
171 *
172 * \param SObj The string buffer object.
173 * \param String The string to store.
174 *
175 * \return The pointer to the stored string or NULL if the function
176 * failed. The returned string may be altered or truncated but not
177 * appended to.
178 */
179char *StringBuffer_Store(StringBufferObject SObj,const char *String)
180{
181 return(StringBuffer_StoreLength(SObj,String,strlen(String)));
182}