]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/utils/utils.c
moor boogz
[OpenSRF.git] / src / utils / utils.c
1 /*
2 Copyright (C) 2005  Georgia Public Library Service 
3 Bill Erickson <highfalutin@gmail.com>
4 Mike Rylander <mrylander@gmail.com>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 */
16
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <sys/timeb.h>
23 #include "utils.h"
24
25 inline void* safe_malloc( int size ) {
26         void* ptr = (void*) malloc( size );
27         if( ptr == NULL ) {
28                 perror("safe_malloc(): Out of Memory" );
29                 exit(99);
30         }
31         memset( ptr, 0, size );
32         return ptr;
33 }
34
35 /* utility method for profiling */
36 double get_timestamp_millis() {
37         struct timeb t;
38         ftime(&t);
39         double time     = ( 
40                 (int)t.time     + ( ((double)t.millitm) / 1000 ) );
41         return time;
42 }
43
44
45 /* setting/clearing file flags */
46 int set_fl( int fd, int flags ) {
47         
48         int val;
49
50         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
51                 fprintf(stderr, "fcntl F_GETFL error");
52                 return -1;
53         }
54
55         val |= flags;
56
57         if( fcntl( fd, F_SETFL, val ) < 0 ) {
58                 fprintf(stderr, "fcntl F_SETFL error");
59                 return -1;
60         }
61         return 0;
62 }
63         
64 int clr_fl( int fd, int flags ) {
65         
66         int val;
67
68         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
69                 fprintf(stderr, "fcntl F_GETFL error" );
70                 return -1;
71         }
72
73         val &= ~flags;
74
75         if( fcntl( fd, F_SETFL, val ) < 0 ) {
76                 fprintf( stderr, "fcntl F_SETFL error" );
77                 return -1;
78         }
79         return 0;
80 }
81
82 // ---------------------------------------------------------------------------------
83 // Flesh out a ubiqitous growing string buffer
84 // ---------------------------------------------------------------------------------
85
86 growing_buffer* buffer_init(int num_initial_bytes) {
87
88         if( num_initial_bytes > BUFFER_MAX_SIZE ) {
89                 return NULL;
90         }
91
92
93         size_t len = sizeof(growing_buffer);
94
95         growing_buffer* gb = (growing_buffer*) safe_malloc(len);
96
97         gb->n_used = 0;/* nothing stored so far */
98         gb->size = num_initial_bytes;
99         gb->buf = (char *) safe_malloc(gb->size + 1);
100
101         return gb;
102 }
103
104 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
105
106         if(!gb || !format) return 0; 
107
108         int len = 0;
109         va_list args;
110         va_list a_copy;
111
112         char* f_copy = strdup(format);
113
114         va_copy(a_copy,args);
115
116         va_start(a_copy, f_copy);
117         len = vsnprintf(NULL, 0, f_copy, a_copy);
118         va_end(a_copy);
119
120         len += 1;
121
122         char buf[len];
123         memset(buf, 0, len);
124
125         va_start(args, format);
126         vsnprintf(buf, len - 1, format, args);
127         va_end(args);
128
129         free(f_copy);
130
131         return buffer_add(gb, buf);
132
133 }
134
135 int buffer_add(growing_buffer* gb, char* data) {
136
137
138         if( ! gb || ! data  ) { return 0; }
139         int data_len = strlen( data );
140
141         if( data_len == 0 ) { return 0; }
142         int total_len = data_len + gb->n_used;
143
144         while( total_len >= gb->size ) {
145                 gb->size *= 2;
146         }
147
148         if( gb->size > BUFFER_MAX_SIZE ) {
149                 fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
150                 buffer_free( gb );
151                 return 0;
152         }
153
154         char* new_data = (char*) safe_malloc( gb->size );
155
156         strcpy( new_data, gb->buf );
157         free( gb->buf );
158         gb->buf = new_data;
159
160         strcat( gb->buf, data );
161         gb->n_used = total_len;
162         return total_len;
163 }
164
165
166 int buffer_reset( growing_buffer *gb){
167         if( gb == NULL ) { return 0; }
168         if( gb->buf == NULL ) { return 0; }
169         memset( gb->buf, 0, gb->size );
170         gb->n_used = 0;
171         return 1;
172 }
173
174 int buffer_free( growing_buffer* gb ) {
175         if( gb == NULL ) 
176                 return 0;
177         free( gb->buf );
178         free( gb );
179         return 1;
180 }
181
182 char* buffer_data( growing_buffer *gb) {
183         return strdup( gb->buf );
184 }
185
186
187 int buffer_add_char(growing_buffer* gb, char c) {
188         char buf[2];
189         buf[0] = c;
190         buf[1] = '\0';
191         buffer_add(gb, buf);
192         return 1;
193 }
194
195
196
197 char* uescape( const char* string, int size, int full_escape ) {
198
199         growing_buffer* buf = buffer_init(size + 64);
200         int idx = 0;
201         long unsigned int c = 0;
202
203         while (string[idx]) {
204         
205                 c ^= c;
206                 
207                 if ((string[idx] & 0xF0) == 0xF0) {
208                         c = string[idx]<<18;
209
210                         if( size - idx < 4 ) return NULL;
211                         
212                         idx++;
213                         c |= (string[idx] & 0x3F)<<12;
214                         
215                         idx++;
216                         c |= (string[idx] & 0x3F)<<6;
217                         
218                         idx++;
219                         c |= (string[idx] & 0x3F);
220                         
221                         c ^= 0xFF000000;
222                         
223                         buffer_fadd(buf, "\\u%0.4x", c);
224
225                 } else if ((string[idx] & 0xE0) == 0xE0) {
226                         c = string[idx]<<12;
227                         if( size - idx < 3 ) return NULL;
228                         
229                         idx++;
230                         c |= (string[idx] & 0x3F)<<6;
231                         
232                         idx++;
233                         c |= (string[idx] & 0x3F);
234                         
235                         c ^= 0xFFF80000;
236                         
237                         buffer_fadd(buf, "\\u%0.4x", c);
238
239                 } else if ((string[idx] & 0xC0) == 0xC0) {
240                         // Two byte char
241                         c = string[idx]<<6;
242                         if( size - idx < 2 ) return NULL;
243                         
244                         idx++;
245                         c |= (string[idx] & 0x3F);
246                         
247                         c ^= 0xFFFFF000;
248                         
249                         buffer_fadd(buf, "\\u%0.4x", c);
250
251                 } else {
252                         c = string[idx];
253
254                         /* escape the usual suspects */
255                         if(full_escape) {
256                                 switch(c) {
257                                         case '"':
258                                                 buffer_add_char(buf, '\\');
259                                                 buffer_add_char(buf, '"');
260                                                 break;
261         
262                                         case '\b':
263                                                 buffer_add_char(buf, '\\');
264                                                 buffer_add_char(buf, 'b');
265                                                 break;
266         
267                                         case '\f':
268                                                 buffer_add_char(buf, '\\');
269                                                 buffer_add_char(buf, 'f');
270                                                 break;
271         
272                                         case '\t':
273                                                 buffer_add_char(buf, '\\');
274                                                 buffer_add_char(buf, 't');
275                                                 break;
276         
277                                         case '\n':
278                                                 buffer_add_char(buf, '\\');
279                                                 buffer_add_char(buf, 'n');
280                                                 break;
281         
282                                         case '\r':
283                                                 buffer_add_char(buf, '\\');
284                                                 buffer_add_char(buf, 'r');
285                                                 break;
286
287                                         default:
288                                                 buffer_add_char(buf, c);
289                                 }
290
291                         } else {
292                                 buffer_add_char(buf, c);
293                         }
294                 }
295
296                 idx++;
297         }
298
299         char* d = buffer_data(buf);
300         buffer_free(buf);
301         return d;
302 }
303