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