Diffstat (limited to 'libical/src/libical/icalmemory.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libical/src/libical/icalmemory.c | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/libical/src/libical/icalmemory.c b/libical/src/libical/icalmemory.c new file mode 100644 index 0000000..297ead8 --- a/dev/null +++ b/libical/src/libical/icalmemory.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* -*- Mode: C -*- | ||
2 | ====================================================================== | ||
3 | FILE: icalmemory.c | ||
4 | CREATOR: eric 30 June 1999 | ||
5 | |||
6 | $Id$ | ||
7 | $Locker$ | ||
8 | |||
9 | The contents of this file are subject to the Mozilla Public License | ||
10 | Version 1.0 (the "License"); you may not use this file except in | ||
11 | compliance with the License. You may obtain a copy of the License at | ||
12 | http://www.mozilla.org/MPL/ | ||
13 | |||
14 | Software distributed under the License is distributed on an "AS IS" | ||
15 | basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | ||
16 | the License for the specific language governing rights and | ||
17 | limitations under the License. | ||
18 | |||
19 | |||
20 | This program is free software; you can redistribute it and/or modify | ||
21 | it under the terms of either: | ||
22 | |||
23 | The LGPL as published by the Free Software Foundation, version | ||
24 | 2.1, available at: http://www.fsf.org/copyleft/lesser.html | ||
25 | |||
26 | Or: | ||
27 | |||
28 | The Mozilla Public License Version 1.0. You may obtain a copy of | ||
29 | the License at http://www.mozilla.org/MPL/ | ||
30 | |||
31 | The Original Code is icalmemory.h | ||
32 | |||
33 | ======================================================================*/ | ||
34 | |||
35 | /* libical often passes strings back to the caller. To make these | ||
36 | * interfaces simple, I did not want the caller to have to pass in a | ||
37 | * memory buffer, but having libical pass out newly allocated memory | ||
38 | * makes it difficult to de-allocate the memory. | ||
39 | * | ||
40 | * The ring buffer in this scheme makes it possible for libical to pass | ||
41 | * out references to memory which the caller does not own, and be able | ||
42 | * to de-allocate the memory later. The ring allows libical to have | ||
43 | * several buffers active simultaneously, which is handy when creating | ||
44 | * string representations of components. */ | ||
45 | |||
46 | #define ICALMEMORY_C | ||
47 | |||
48 | #ifdef HAVE_CONFIG_H | ||
49 | #include "config.h" | ||
50 | #endif | ||
51 | |||
52 | #ifdef DMALLOC | ||
53 | #include "dmalloc.h" | ||
54 | #endif | ||
55 | |||
56 | #include "icalmemory.h" | ||
57 | #include "icalerror.h" | ||
58 | |||
59 | #include <stdio.h> /* for printf (debugging) */ | ||
60 | #include <stdlib.h> /* for malloc, realloc */ | ||
61 | #include <string.h> /* for memset(), strdup */ | ||
62 | |||
63 | #define BUFFER_RING_SIZE 25 | ||
64 | #define MIN_BUFFER_SIZE 200 | ||
65 | |||
66 | void icalmemory_free_tmp_buffer (void* buf); | ||
67 | |||
68 | |||
69 | /* HACK. Not threadsafe */ | ||
70 | void* buffer_ring[BUFFER_RING_SIZE]; | ||
71 | int buffer_pos = -1; | ||
72 | int initialized = 0; | ||
73 | |||
74 | /* Add an existing buffer to the buffer ring */ | ||
75 | void icalmemory_add_tmp_buffer(void* buf) | ||
76 | { | ||
77 | /* I don't think I need this -- I think static arrays are | ||
78 | initialized to 0 as a standard part of C, but I am not sure. */ | ||
79 | if (initialized == 0){ | ||
80 | int i; | ||
81 | for(i=0; i<BUFFER_RING_SIZE; i++){ | ||
82 | buffer_ring[i] = 0; | ||
83 | } | ||
84 | initialized = 1; | ||
85 | } | ||
86 | |||
87 | /* Wrap around the ring */ | ||
88 | if(++buffer_pos == BUFFER_RING_SIZE){ | ||
89 | buffer_pos = 0; | ||
90 | } | ||
91 | |||
92 | /* Free buffers as their slots are overwritten */ | ||
93 | if ( buffer_ring[buffer_pos] != 0){ | ||
94 | free( buffer_ring[buffer_pos]); | ||
95 | buffer_ring[buffer_pos] = 0; | ||
96 | } | ||
97 | |||
98 | /* Assign the buffer to a slot */ | ||
99 | buffer_ring[buffer_pos] = buf; | ||
100 | } | ||
101 | |||
102 | /* Create a new temporary buffer on the ring. Libical owns these and | ||
103 | wil deallocate them. */ | ||
104 | void* | ||
105 | icalmemory_tmp_buffer (size_t size) | ||
106 | { | ||
107 | char *buf; | ||
108 | |||
109 | if (size < MIN_BUFFER_SIZE){ | ||
110 | size = MIN_BUFFER_SIZE; | ||
111 | } | ||
112 | |||
113 | buf = (void*)malloc(size); | ||
114 | |||
115 | if( buf == 0){ | ||
116 | icalerror_set_errno(ICAL_NEWFAILED_ERROR); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | memset(buf,0,size); | ||
121 | |||
122 | icalmemory_add_tmp_buffer(buf); | ||
123 | |||
124 | return buf; | ||
125 | } | ||
126 | |||
127 | void icalmemory_free_ring() | ||
128 | { | ||
129 | |||
130 | int i; | ||
131 | for(i=0; i<BUFFER_RING_SIZE; i++){ | ||
132 | if ( buffer_ring[i] != 0){ | ||
133 | free( buffer_ring[i]); | ||
134 | } | ||
135 | buffer_ring[i] = 0; | ||
136 | } | ||
137 | |||
138 | initialized = 1; | ||
139 | |||
140 | } | ||
141 | |||
142 | |||
143 | |||
144 | /* Like strdup, but the buffer is on the ring. */ | ||
145 | char* | ||
146 | icalmemory_tmp_copy(const char* str) | ||
147 | { | ||
148 | char* b = icalmemory_tmp_buffer(strlen(str)+1); | ||
149 | |||
150 | strcpy(b,str); | ||
151 | |||
152 | return b; | ||
153 | } | ||
154 | |||
155 | |||
156 | char* icalmemory_strdup(const char *s) | ||
157 | { | ||
158 | return strdup(s); | ||
159 | } | ||
160 | |||
161 | void | ||
162 | icalmemory_free_tmp_buffer (void* buf) | ||
163 | { | ||
164 | if(buf == 0) | ||
165 | { | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | free(buf); | ||
170 | } | ||
171 | |||
172 | |||
173 | /* These buffer routines create memory the old fashioned way -- so the | ||
174 | caller will have to delocate the new memory */ | ||
175 | |||
176 | void* icalmemory_new_buffer(size_t size) | ||
177 | { | ||
178 | void *b = malloc(size); | ||
179 | |||
180 | if( b == 0){ | ||
181 | icalerror_set_errno(ICAL_NEWFAILED_ERROR); | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | memset(b,0,size); | ||
186 | |||
187 | return b; | ||
188 | } | ||
189 | |||
190 | void* icalmemory_resize_buffer(void* buf, size_t size) | ||
191 | { | ||
192 | void *b = realloc(buf, size); | ||
193 | |||
194 | if( b == 0){ | ||
195 | icalerror_set_errno(ICAL_NEWFAILED_ERROR); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | return b; | ||
200 | } | ||
201 | |||
202 | void icalmemory_free_buffer(void* buf) | ||
203 | { | ||
204 | free(buf); | ||
205 | } | ||
206 | |||
207 | void | ||
208 | icalmemory_append_string(char** buf, char** pos, size_t* buf_size, | ||
209 | const char* string) | ||
210 | { | ||
211 | char *new_buf; | ||
212 | char *new_pos; | ||
213 | |||
214 | size_t data_length, final_length, string_length; | ||
215 | |||
216 | #ifndef ICAL_NO_INTERNAL_DEBUG | ||
217 | icalerror_check_arg_rv( (buf!=0),"buf"); | ||
218 | icalerror_check_arg_rv( (*buf!=0),"*buf"); | ||
219 | icalerror_check_arg_rv( (pos!=0),"pos"); | ||
220 | icalerror_check_arg_rv( (*pos!=0),"*pos"); | ||
221 | icalerror_check_arg_rv( (buf_size!=0),"buf_size"); | ||
222 | icalerror_check_arg_rv( (*buf_size!=0),"*buf_size"); | ||
223 | icalerror_check_arg_rv( (string!=0),"string"); | ||
224 | #endif | ||
225 | |||
226 | string_length = strlen(string); | ||
227 | data_length = (size_t)*pos - (size_t)*buf; | ||
228 | final_length = data_length + string_length; | ||
229 | |||
230 | if ( final_length >= (size_t) *buf_size) { | ||
231 | |||
232 | |||
233 | *buf_size = (*buf_size) * 2 + final_length; | ||
234 | |||
235 | new_buf = realloc(*buf,*buf_size); | ||
236 | |||
237 | new_pos = (void*)((size_t)new_buf + data_length); | ||
238 | |||
239 | *pos = new_pos; | ||
240 | *buf = new_buf; | ||
241 | } | ||
242 | |||
243 | strcpy(*pos, string); | ||
244 | |||
245 | *pos += string_length; | ||
246 | } | ||
247 | |||
248 | |||
249 | void | ||
250 | icalmemory_append_char(char** buf, char** pos, size_t* buf_size, | ||
251 | char ch) | ||
252 | { | ||
253 | char *new_buf; | ||
254 | char *new_pos; | ||
255 | |||
256 | size_t data_length, final_length; | ||
257 | |||
258 | #ifndef ICAL_NO_INTERNAL_DEBUG | ||
259 | icalerror_check_arg_rv( (buf!=0),"buf"); | ||
260 | icalerror_check_arg_rv( (*buf!=0),"*buf"); | ||
261 | icalerror_check_arg_rv( (pos!=0),"pos"); | ||
262 | icalerror_check_arg_rv( (*pos!=0),"*pos"); | ||
263 | icalerror_check_arg_rv( (buf_size!=0),"buf_size"); | ||
264 | icalerror_check_arg_rv( (*buf_size!=0),"*buf_size"); | ||
265 | #endif | ||
266 | |||
267 | data_length = (size_t)*pos - (size_t)*buf; | ||
268 | |||
269 | final_length = data_length + 2; | ||
270 | |||
271 | if ( final_length > (size_t) *buf_size ) { | ||
272 | |||
273 | |||
274 | *buf_size = (*buf_size) * 2 + final_length +1; | ||
275 | |||
276 | new_buf = realloc(*buf,*buf_size); | ||
277 | |||
278 | new_pos = (void*)((size_t)new_buf + data_length); | ||
279 | |||
280 | *pos = new_pos; | ||
281 | *buf = new_buf; | ||
282 | } | ||
283 | |||
284 | **pos = ch; | ||
285 | *pos += 1; | ||
286 | **pos = 0; | ||
287 | } | ||