pupnp (libupnp) snapshot from SourceForge: git clone git://pupnp.git.sourceforge...
[igd2-for-linux:pandonghui1211s-igd2-for-linux.git] / pupnp_branch-1.6.x / upnp / src / genlib / util / membuffer.c
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000-2003 Intel Corporation 
4 // All rights reserved. 
5 //
6 // Redistribution and use in source and binary forms, with or without 
7 // modification, are permitted provided that the following conditions are met: 
8 //
9 // * Redistributions of source code must retain the above copyright notice, 
10 // this list of conditions and the following disclaimer. 
11 // * Redistributions in binary form must reproduce the above copyright notice, 
12 // this list of conditions and the following disclaimer in the documentation 
13 // and/or other materials provided with the distribution. 
14 // * Neither name of Intel Corporation nor the names of its contributors 
15 // may be used to endorse or promote products derived from this software 
16 // without specific prior written permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
25 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
26 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 ///////////////////////////////////////////////////////////////////////////
31
32 /************************************************************************
33 * Purpose: This file contains functions that operate on memory and 
34 *       buffers, allocation, re-allocation, and modification of the memory 
35 ************************************************************************/
36
37 #include "config.h"
38 #include <assert.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <membuffer.h>
42 #include "upnp.h"
43 #include "unixutil.h"
44
45 /************************************************************************
46 *                                                                string                                                                 *
47 ************************************************************************/
48
49 /************************************************************************
50 *       Function :      str_alloc
51 *
52 *       Parameters :
53 *               IN const char* str ;    input string object
54 *               IN size_t str_len ;             input string length
55 *
56 *       Description :   Allocate memory and copy information from the input 
57 *               string to the newly allocated memory.
58 *
59 *       Return : char* ;
60 *               Pointer to the newly allocated memory.
61 *               NULL if memory cannot be allocated.
62 *
63 *       Note :
64 ************************************************************************/
65 char *
66 str_alloc( IN const char *str,
67            IN size_t str_len )
68 {
69     char *s;
70
71     s = ( char * )malloc( str_len + 1 );
72     if( s == NULL ) {
73         return NULL;            // no mem
74     }
75
76     memcpy( s, str, str_len );
77     s[str_len] = '\0';
78
79     return s;
80 }
81
82 /************************************************************************
83 *                                                               memptr                                                                  *
84 ************************************************************************/
85
86 /************************************************************************
87 *       Function :      memptr_cmp
88 *
89 *       Parameters :
90 *               IN memptr* m ;  input memory object
91 *               IN const char* s ;      constatnt string for the memory object to be 
92 *                                       compared with
93 *
94 *       Description : Compares characters of strings passed for number of 
95 *               bytes. If equal for the number of bytes, the length of the bytes 
96 *               determines which buffer is shorter.
97 *
98 *       Return : int ;
99 *               < 0 string1 substring less than string2 substring 
100 *               0 string1 substring identical to string2 substring 
101 *               > 0 string1 substring greater than string2 substring 
102 *
103 *       Note :
104 ************************************************************************/
105 int
106 memptr_cmp( IN memptr * m,
107             IN const char *s )
108 {
109     int cmp;
110
111     cmp = strncmp( m->buf, s, m->length );
112
113     if( cmp == 0 && m->length < strlen( s ) ) {
114         // both strings equal for 'm->length' chars
115         //  if m is shorter than s, then s is greater
116         return -1;
117     }
118
119     return cmp;
120 }
121
122 /************************************************************************
123 *       Function :      memptr_cmp_nocase
124 *
125 *       Parameters :
126 *               IN memptr* m ;  input memory object
127 *               IN const char* s ;      constatnt string for the memory object to be 
128 *                                       compared with
129 *
130 *       Description : Compares characters of 2 strings irrespective of the 
131 *               case for a specific count of bytes  If the character comparison 
132 *               is the same the length of the 2 srings determines the shorter 
133 *               of the 2 strings.
134 *
135 *       Return : int ;
136 *               < 0 string1 substring less than string2 substring 
137 *               0 string1 substring identical to string2 substring 
138 *               > 0 string1 substring greater than string2 substring 
139 *  
140 *       Note :
141 ************************************************************************/
142 int
143 memptr_cmp_nocase( IN memptr * m,
144                    IN const char *s )
145 {
146     int cmp;
147
148     cmp = strncasecmp( m->buf, s, m->length );
149     if( cmp == 0 && m->length < strlen( s ) ) {
150         // both strings equal for 'm->length' chars
151         //  if m is shorter than s, then s is greater
152         return -1;
153     }
154
155     return cmp;
156 }
157
158 /************************************************************************
159 *                                                        membuffer                                                                      *
160 ************************************************************************/
161
162 /************************************************************************
163 *       Function :      membuffer_initialize
164 *
165 *       Parameters :
166 *               INOUT membuffer* m ;    buffer to be initialized
167 *
168 *       Description :   Initialize the buffer
169 *
170 *       Return : void ;
171 *
172 *       Note :
173 ************************************************************************/
174 static UPNP_INLINE void
175 membuffer_initialize( INOUT membuffer * m )
176 {
177     m->buf = NULL;
178     m->length = 0;
179     m->capacity = 0;
180 }
181
182 /************************************************************************
183 *       Function :      membuffer_set_size
184 *
185 *       Parameters :
186 *               INOUT membuffer* m ;    buffer whose size is to be modified
187 *               IN size_t new_length ;  new size to which the buffer will be 
188 *                                       modified
189 *
190 *       Description : Increases or decreases buffer cap so that at least
191 *          'new_length' bytes can be stored
192 *
193 *       Return : int ;
194 *               UPNP_E_SUCCESS - On Success
195 *               UPNP_E_OUTOF_MEMORY - On failure to allocate memory.
196 *
197 *       Note :
198 ************************************************************************/
199 int
200 membuffer_set_size( INOUT membuffer * m,
201                     IN size_t new_length )
202 {
203     size_t diff;
204     size_t alloc_len;
205     char *temp_buf;
206
207     if( new_length >= m->length )   // increase length
208     {
209         // need more mem?
210         if( new_length <= m->capacity ) {
211             return 0;           // have enough mem; done
212         }
213
214         diff = new_length - m->length;
215         alloc_len = MAXVAL( m->size_inc, diff ) + m->capacity;
216     } else                      // decrease length
217     {
218         assert( new_length <= m->length );
219
220         // if diff is 0..m->size_inc, don't free
221         if( ( m->capacity - new_length ) <= m->size_inc ) {
222             return 0;
223         }
224
225         alloc_len = new_length + m->size_inc;
226     }
227
228     assert( alloc_len >= new_length );
229
230     temp_buf = realloc( m->buf, alloc_len + 1 );    //LEAK_FIX_MK
231
232     //temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );//LEAK_FIX_MK
233
234     if( temp_buf == NULL ) {
235         // try smaller size
236         alloc_len = new_length;
237         temp_buf = realloc( m->buf, alloc_len + 1 );    //LEAK_FIX_MK
238         //temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );//LEAK_FIX_MK
239
240         if( temp_buf == NULL ) {
241             return UPNP_E_OUTOF_MEMORY;
242         }
243     }
244     // save
245     m->buf = temp_buf;
246     m->capacity = alloc_len;
247     return 0;
248 }
249
250 /************************************************************************
251 *       Function :      membuffer_init
252 *
253 *       Parameters :
254 *               INOUT membuffer* m ; buffer     to be initialized
255 *
256 *       Description : Wrapper to membuffer_initialize().
257 *               Set the size of the buffer to MEMBUF_DEF_SIZE_INC
258 *               Initializes m->buf to NULL, length=0
259 *
260 *       Return : void ;
261 *
262 *       Note :
263 ************************************************************************/
264 void
265 membuffer_init( INOUT membuffer * m )
266 {
267     assert( m != NULL );
268
269     m->size_inc = MEMBUF_DEF_SIZE_INC;
270     membuffer_initialize( m );
271 }
272
273 /************************************************************************
274 *       Function :      membuffer_destroy
275 *
276 *       Parameters :
277 *               INOUT membuffer* m ;    buffer to be destroyed
278 *
279 *       Description : Free's memory allocated for membuffer* m.
280 *
281 *       Return : void ;
282 *
283 *       Note :
284 ************************************************************************/
285 void
286 membuffer_destroy( INOUT membuffer * m )
287 {
288     if( m == NULL ) {
289         return;
290     }
291
292     free( m->buf );
293     membuffer_init( m );
294 }
295
296 /************************************************************************
297 *       Function :      membuffer_assign
298 *
299 *       Parameters :
300 *               INOUT membuffer* m ; buffer whose memory is to be allocated and 
301 *                                       assigned.
302 *               IN const void* buf ; source buffer whose contents will be copied
303 *               IN size_t buf_len ;      length of the source buffer
304 *
305 *       Description : Allocate memory to membuffer* m and copy the contents 
306 *               of the in parameter IN const void* buf.
307 *
308 *       Return : int ;
309 *        UPNP_E_SUCCESS
310 *        UPNP_E_OUTOF_MEMORY
311 *
312 *       Note :
313 ************************************************************************/
314 int
315 membuffer_assign( INOUT membuffer * m,
316                   IN const void *buf,
317                   IN size_t buf_len )
318 {
319     int return_code;
320
321     assert( m != NULL );
322
323     // set value to null
324     if( buf == NULL ) {
325         membuffer_destroy( m );
326         return 0;
327     }
328     // alloc mem
329     return_code = membuffer_set_size( m, buf_len );
330     if( return_code != 0 ) {
331         return return_code;
332     }
333     // copy
334     if( buf_len ) {
335         memcpy( m->buf, buf, buf_len );
336         m->buf[buf_len] = 0;        // null-terminate
337     }
338     m->length = buf_len;
339
340     return 0;
341 }
342
343 /************************************************************************
344 *       Function :      membuffer_assign_str
345 *
346 *       Parameters :
347 *               INOUT membuffer* m ;    buffer to be allocated and assigned
348 *               IN const char* c_str ;  source buffer whose contents will be 
349 *                                       copied
350 *
351 *       Description : Wrapper function for membuffer_assign()
352 *
353 *       Return : int ;
354 *        UPNP_E_SUCCESS
355 *        UPNP_E_OUTOF_MEMORY
356 *
357 *       Note :
358 ************************************************************************/
359 int
360 membuffer_assign_str( INOUT membuffer * m,
361                       IN const char *c_str )
362 {
363     return membuffer_assign( m, c_str, strlen( c_str ) );
364 }
365
366 /************************************************************************
367 *       Function :      membuffer_append
368 *
369 *       Parameters :
370 *               INOUT membuffer* m ; buffer whose memory is to be appended.
371 *               IN const void* buf ; source buffer whose contents will be 
372 *                                       copied
373 *               IN size_t buf_len ;     length of the source buffer
374 *
375 *       Description : Invokes function to appends data from a constant buffer 
376 *               to the buffer 
377 *
378 *       Return : int ;
379 *
380 *       Note :
381 ************************************************************************/
382 int
383 membuffer_append( INOUT membuffer * m,
384                   IN const void *buf,
385                   IN size_t buf_len )
386 {
387     assert( m != NULL );
388
389     return membuffer_insert( m, buf, buf_len, m->length );
390 }
391
392 /************************************************************************
393 *       Function :      membuffer_append_str
394 *
395 *       Parameters :
396 *               INOUT membuffer* m ;    buffer whose memory is to be appended.
397 *               IN const char* c_str ;  source buffer whose contents will be 
398 *                                       copied
399 *
400 *       Description : Invokes function to appends data from a constant string 
401 *               to the buffer   
402 *
403 *       Return : int ;
404 *
405 *       Note :
406 ************************************************************************/
407 int
408 membuffer_append_str( INOUT membuffer * m,
409                       IN const char *c_str )
410 {
411     return membuffer_insert( m, c_str, strlen( c_str ), m->length );
412 }
413
414 /************************************************************************
415 *       Function :      membuffer_insert
416 *
417 *       Parameters :
418 *               INOUT membuffer* m ; buffer whose memory size is to be increased  
419 *                                       and appended.
420 *               IN const void* buf ; source buffer whose contents will be 
421 *                                       copied
422 *                IN size_t buf_len ; size of the source buffer
423 *               int index ;     index to determine the bounds while movinf the data
424 *
425 *       Description : Allocates memory for the new data to be inserted. Does
426 *               memory management by moving the data from the existing memory to 
427 *               the newly allocated memory and then appending the new data.
428 *
429 *       Return : int ;
430 *
431 *       Note :
432 ************************************************************************/
433 int
434 membuffer_insert( INOUT membuffer * m,
435                   IN const void *buf,
436                   IN size_t buf_len,
437                   int index )
438 {
439     int return_code;
440
441     assert( m != NULL );
442
443     if( index < 0 || index > ( int )m->length )
444         return UPNP_E_OUTOF_BOUNDS;
445
446     if( buf == NULL || buf_len == 0 ) {
447         return 0;
448     }
449     // alloc mem
450     return_code = membuffer_set_size( m, m->length + buf_len );
451     if( return_code != 0 ) {
452         return return_code;
453     }
454     // insert data
455
456     // move data to right of insertion point
457     memmove( m->buf + index + buf_len, m->buf + index, m->length - index );
458     memcpy( m->buf + index, buf, buf_len );
459     m->length += buf_len;
460     m->buf[m->length] = 0;      // null-terminate
461
462     return 0;
463 }
464
465 /************************************************************************
466 *       Function :      membuffer_delete
467 *
468 *       Parameters :
469 *               INOUT membuffer* m ; buffer whose memory size is to be decreased
470 *                                       and copied to the odified location
471 *               IN int index ;  index to determine bounds while moving data
472 *               IN size_t num_bytes ;   number of bytes that the data needs to 
473 *                                       shrink by
474 *
475 *       Description : Shrink the size of the buffer depending on the current 
476 *               size of the bufer and te input parameters. Move contents from the 
477 *               old buffer to the new sized buffer.
478 *
479 *       Return : void ;
480 *
481 *       Note :
482 ************************************************************************/
483 void
484 membuffer_delete( INOUT membuffer * m,
485                   IN int index,
486                   IN size_t num_bytes )
487 {
488     int return_value;
489     int new_length;
490     size_t copy_len;
491
492     assert( m != NULL );
493
494     if( m->length == 0 ) {
495         return;
496     }
497
498     assert( index >= 0 && index < ( int )m->length );
499
500     // shrink count if it goes beyond buffer
501     if( index + num_bytes > m->length ) {
502         num_bytes = m->length - ( size_t ) index;
503         copy_len = 0;           // every thing at and after index purged
504     } else {
505         // calc num bytes after deleted string
506         copy_len = m->length - ( index + num_bytes );
507     }
508
509     memmove( m->buf + index, m->buf + index + num_bytes, copy_len );
510
511     new_length = m->length - num_bytes;
512     return_value = membuffer_set_size( m, new_length ); // trim buffer
513     assert( return_value == 0 );    // shrinking should always work
514
515     // don't modify until buffer is set
516     m->length = new_length;
517     m->buf[new_length] = 0;
518 }
519
520 /************************************************************************
521 *       Function :      membuffer_detach
522 *
523 *       Parameters :
524 *               INOUT membuffer* m ; buffer to be returned and updated. 
525 *
526 *       Description : Detaches current buffer and returns it. The caller
527 *               must free the returned buffer using free().
528 *               After this call, length becomes 0.
529 *
530 *       Return : char* ;
531 *               a pointer to the current buffer
532 *
533 *       Note :
534 ************************************************************************/
535 char *
536 membuffer_detach( INOUT membuffer * m )
537 {
538     char *buf;
539
540     assert( m != NULL );
541
542     buf = m->buf;
543
544     // free all
545     membuffer_initialize( m );
546
547     return buf;
548 }
549
550 /************************************************************************
551 *       Function :      membuffer_attach
552 *
553 *       Parameters :
554 *               INOUT membuffer* m ;    buffer to be updated
555 *               IN char* new_buf ;       source buffer which will be assigned to the 
556 *                                       buffer to be updated
557 *               IN size_t buf_len ;     length of the source buffer 
558 *
559 *       Description : Free existing memory in membuffer and assign the new 
560 *               buffer in its place.
561 *
562 *       Return : void ;
563 *
564 *       Note : 'new_buf' must be allocted using malloc or realloc so
565 *               that it can be freed using free()
566 ************************************************************************/
567 void
568 membuffer_attach( INOUT membuffer * m,
569                   IN char *new_buf,
570                   IN size_t buf_len )
571 {
572     assert( m != NULL );
573
574     membuffer_destroy( m );
575     m->buf = new_buf;
576     m->length = buf_len;
577     m->capacity = buf_len;
578 }