]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | } |