]> git.ipfire.org Git - thirdparty/sarg.git/blob - stringbuffer.c
Generate redirector log even if -d is not given
[thirdparty/sarg.git] / stringbuffer.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2015
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
29 Store strings in a globaly allocated memory to avoid memory waste and
30 memory 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 */
45 struct 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 */
60 StringBufferObject 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 */
78 void 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 */
99 static 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 */
136 char *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 */
179 char *StringBuffer_Store(StringBufferObject SObj,const char *String)
180 {
181 return(StringBuffer_StoreLength(SObj,String,strlen(String)));
182 }