Back to index

lightning-sunbird  0.9+nobinonly
icalmemory.c
Go to the documentation of this file.
00001 /* -*- Mode: C -*-
00002   ======================================================================
00003   FILE: icalmemory.c
00004   CREATOR: eric 30 June 1999
00005   
00006   $Id: icalmemory.c,v 1.10 2002/08/09 14:28:56 lindner Exp $
00007   $Locker:  $
00008     
00009  The contents of this file are subject to the Mozilla Public License
00010  Version 1.0 (the "License"); you may not use this file except in
00011  compliance with the License. You may obtain a copy of the License at
00012  http://www.mozilla.org/MPL/
00013  
00014  Software distributed under the License is distributed on an "AS IS"
00015  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00016  the License for the specific language governing rights and
00017  limitations under the License.
00018  
00019 
00020  This program is free software; you can redistribute it and/or modify
00021  it under the terms of either: 
00022 
00023     The LGPL as published by the Free Software Foundation, version
00024     2.1, available at: http://www.fsf.org/copyleft/lesser.html
00025 
00026   Or:
00027 
00028     The Mozilla Public License Version 1.0. You may obtain a copy of
00029     the License at http://www.mozilla.org/MPL/
00030 
00031  The Original Code is icalmemory.h
00032 
00033  ======================================================================*/
00034 
00051 #define ICALMEMORY_C
00052 
00053 #ifdef HAVE_CONFIG_H
00054 #include "config.h"
00055 #endif
00056 
00057 #ifdef DMALLOC
00058 #include "dmalloc.h"
00059 #endif
00060 
00061 #include "icalmemory.h"
00062 #include "icalerror.h"
00063 
00064 #include <stdio.h> /* for printf (debugging) */
00065 #include <stdlib.h> /* for malloc, realloc */
00066 #include <string.h> /* for memset(), strdup */
00067 
00068 #ifdef WIN32
00069 #include <windows.h>
00070 #endif
00071 
00072 #define BUFFER_RING_SIZE 2500
00073 #define MIN_BUFFER_SIZE 200
00074 
00075 
00076 /* HACK. Not threadsafe */
00077 
00078 typedef struct {
00079        int pos;
00080        void *ring[BUFFER_RING_SIZE];
00081 } buffer_ring;
00082 
00083 void icalmemory_free_tmp_buffer (void* buf);
00084 void icalmemory_free_ring_byval(buffer_ring *br);
00085 
00086 static buffer_ring* global_buffer_ring = 0;
00087 
00088 #ifdef HAVE_PTHREAD
00089 #include <pthread.h>
00090 
00091 static pthread_key_t  ring_key;
00092 static pthread_once_t ring_key_once = PTHREAD_ONCE_INIT;
00093 
00094 static void ring_destroy(void * buf) {
00095     if (buf) icalmemory_free_ring_byval((buffer_ring *) buf);
00096     pthread_setspecific(ring_key, NULL);
00097 }
00098 
00099 static void ring_key_alloc(void) {  
00100     pthread_key_create(&ring_key, ring_destroy);
00101 }
00102 #endif
00103 
00104 
00105 static buffer_ring * buffer_ring_new(void) {
00106        buffer_ring *br;
00107        int i;
00108 
00109        br = (buffer_ring *)malloc(sizeof(buffer_ring));
00110 
00111        for(i=0; i<BUFFER_RING_SIZE; i++){
00112            br->ring[i]  = 0;
00113        }
00114        br->pos = 0;
00115         return(br);
00116 }
00117 
00118 
00119 #ifdef HAVE_PTHREAD
00120 static buffer_ring* get_buffer_ring_pthread(void) {
00121     buffer_ring *br;
00122 
00123     pthread_once(&ring_key_once, ring_key_alloc);
00124 
00125     br = pthread_getspecific(ring_key);
00126 
00127     if (!br) {
00128        br = buffer_ring_new();
00129        pthread_setspecific(ring_key, br);
00130     }
00131     return(br);
00132 }
00133 #endif
00134 
00135 /* get buffer ring via a single global for a non-threaded program */
00136 static buffer_ring* get_buffer_ring_global(void) {
00137     if (global_buffer_ring == 0) {
00138        global_buffer_ring = buffer_ring_new();
00139     }
00140     return(global_buffer_ring);
00141 }
00142 
00143 static buffer_ring *get_buffer_ring(void) {
00144 #ifdef HAVE_PTHREAD
00145        return(get_buffer_ring_pthread());
00146 #else
00147        return get_buffer_ring_global();
00148 #endif
00149 }
00150 
00151 
00153 void  icalmemory_add_tmp_buffer(void* buf)
00154 {
00155     buffer_ring *br = get_buffer_ring();
00156 
00157 
00158     /* Wrap around the ring */
00159     if(++(br->pos) == BUFFER_RING_SIZE){
00160        br->pos = 0;
00161     }
00162 
00163     /* Free buffers as their slots are overwritten */
00164     if ( br->ring[br->pos] != 0){
00165        free( br->ring[br->pos]);
00166     }
00167 
00168     /* Assign the buffer to a slot */
00169     br->ring[br->pos] = buf; 
00170 }
00171 
00172 
00178 void*
00179 icalmemory_tmp_buffer (size_t size)
00180 {
00181     char *buf;
00182 
00183     if (size < MIN_BUFFER_SIZE){
00184        size = MIN_BUFFER_SIZE;
00185     }
00186     
00187     buf = (void*)malloc(size);
00188 
00189     if( buf == 0){
00190        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
00191        return 0;
00192     }
00193 
00194     memset(buf,0,size); 
00195 
00196     icalmemory_add_tmp_buffer(buf);
00197 
00198     return buf;
00199 }
00200 
00202 void icalmemory_free_ring_byval(buffer_ring *br) {
00203    int i;
00204    for(i=0; i<BUFFER_RING_SIZE; i++){
00205     if ( br->ring[i] != 0){
00206        free( br->ring[i]);
00207     }
00208     }
00209    free(br);
00210 }
00211 
00212 void icalmemory_free_ring()
00213 {
00214    buffer_ring *br;
00215    br = get_buffer_ring();
00216 
00217    icalmemory_free_ring_byval(br);
00218 }
00219 
00220 
00221 
00223 char*
00224 icalmemory_tmp_copy(const char* str)
00225 {
00226     char* b = icalmemory_tmp_buffer(strlen(str)+1);
00227 
00228     strcpy(b,str);
00229 
00230     return b;
00231 }
00232     
00233 
00234 char* icalmemory_strdup(const char *s)
00235 {
00236     return strdup(s);
00237 }
00238 
00239 void
00240 icalmemory_free_tmp_buffer (void* buf)
00241 {
00242    if(buf == 0)
00243    {
00244        return;
00245    }
00246 
00247    free(buf);
00248 }
00249 
00250 
00251 /*
00252  * These buffer routines create memory the old fashioned way -- so the
00253  * caller will have to deallocate the new memory 
00254  */
00255 
00256 void* icalmemory_new_buffer(size_t size)
00257 {
00258     void *b = malloc(size);
00259 
00260     if( b == 0){
00261        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
00262        return 0;
00263     }
00264 
00265     memset(b,0,size); 
00266 
00267     return b;
00268 }
00269 
00270 void* icalmemory_resize_buffer(void* buf, size_t size)
00271 {
00272     void *b = realloc(buf, size);
00273 
00274     if( b == 0){
00275        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
00276        return 0;
00277     }
00278 
00279    return b;
00280 }
00281 
00282 void icalmemory_free_buffer(void* buf)
00283 {
00284     free(buf);
00285 }
00286 
00287 void 
00288 icalmemory_append_string(char** buf, char** pos, size_t* buf_size, 
00289                            const char* string)
00290 {
00291     char *new_buf;
00292     char *new_pos;
00293 
00294     size_t data_length, final_length, string_length;
00295 
00296 #ifndef ICAL_NO_INTERNAL_DEBUG
00297     icalerror_check_arg_rv( (buf!=0),"buf");
00298     icalerror_check_arg_rv( (*buf!=0),"*buf");
00299     icalerror_check_arg_rv( (pos!=0),"pos");
00300     icalerror_check_arg_rv( (*pos!=0),"*pos");
00301     icalerror_check_arg_rv( (buf_size!=0),"buf_size");
00302     icalerror_check_arg_rv( (*buf_size!=0),"*buf_size");
00303     icalerror_check_arg_rv( (string!=0),"string");
00304 #endif 
00305 
00306     string_length = strlen(string);
00307     data_length = (size_t)*pos - (size_t)*buf;    
00308     final_length = data_length + string_length; 
00309 
00310     if ( final_length >= (size_t) *buf_size) {
00311 
00312        
00313        *buf_size  = (*buf_size) * 2  + final_length;
00314 
00315        new_buf = realloc(*buf,*buf_size);
00316 
00317        new_pos = (void*)((size_t)new_buf + data_length);
00318        
00319        *pos = new_pos;
00320        *buf = new_buf;
00321     }
00322     
00323     strcpy(*pos, string);
00324 
00325     *pos += string_length;
00326 }
00327 
00328 
00329 void 
00330 icalmemory_append_char(char** buf, char** pos, size_t* buf_size, 
00331                            char ch)
00332 {
00333     char *new_buf;
00334     char *new_pos;
00335 
00336     size_t data_length, final_length;
00337 
00338 #ifndef ICAL_NO_INTERNAL_DEBUG
00339     icalerror_check_arg_rv( (buf!=0),"buf");
00340     icalerror_check_arg_rv( (*buf!=0),"*buf");
00341     icalerror_check_arg_rv( (pos!=0),"pos");
00342     icalerror_check_arg_rv( (*pos!=0),"*pos");
00343     icalerror_check_arg_rv( (buf_size!=0),"buf_size");
00344     icalerror_check_arg_rv( (*buf_size!=0),"*buf_size");
00345 #endif
00346 
00347     data_length = (size_t)*pos - (size_t)*buf;
00348 
00349     final_length = data_length + 2; 
00350 
00351     if ( final_length > (size_t) *buf_size ) {
00352 
00353        
00354        *buf_size  = (*buf_size) * 2  + final_length +1;
00355 
00356        new_buf = realloc(*buf,*buf_size);
00357 
00358        new_pos = (void*)((size_t)new_buf + data_length);
00359        
00360        *pos = new_pos;
00361        *buf = new_buf;
00362     }
00363 
00364     **pos = ch;
00365     *pos += 1;
00366     **pos = 0;
00367 }