]> arthur.barton.de Git - netdata.git/blob - src/web_buffer.c
better unit testing of storage numbers; added benchmarking
[netdata.git] / src / web_buffer.c
1 #include <stdlib.h>
2 #include <math.h>
3
4 #include "web_buffer.h"
5
6 #include "common.h"
7 #include "log.h"
8
9 void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
10 {
11         char *buffer = wb->buffer;
12         long bytes = wb->bytes, size = wb->size, i = 0;
13
14         while(txt[i] && bytes < size)
15                 buffer[bytes++] = txt[i++];
16
17         wb->bytes = bytes;
18 }
19
20 int print_calculated_number(char *str, calculated_number value)
21 {
22         char *wstr = str;
23
24         int sign = (value < 0) ? 1 : 0;
25         if(sign) value = -value;
26
27         // without llrint() there are rounding problems
28         // for example 0.9 becomes 0.89
29         unsigned long long uvalue = llrint(value * (calculated_number)100000);
30
31         // print each digit
32         do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
33
34         // make sure we have 6 bytes at least
35         while((wstr - str) < 6) *wstr++ = '0';
36
37         // put the sign back
38         if(sign) *wstr++ = '-';
39
40         // reverse it
41     char *begin = str, *end = --wstr, aux;
42     while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
43         // wstr--;
44         // strreverse(str, wstr);
45
46         // remove trailing zeros
47         int decimal = 5;
48         while(decimal > 0 && *wstr == '0') {
49                 *wstr-- = '\0';
50                 decimal--;
51         }
52
53         // terminate it, one position to the right
54         // to let space for a dot
55         wstr[2] = '\0';
56
57         // make space for the dot
58         int i;
59         for(i = 0; i < decimal ;i++) {
60                 wstr[1] = wstr[0];
61                 wstr--;
62         }
63
64         // put the dot
65         if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
66         else wstr[1] = '.';
67
68         // return the buffer length
69         return ( (wstr - str) + 2 + decimal );
70 }
71
72 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value)
73 {
74         if(wb->size - wb->bytes < 50) return;
75         wb->bytes += print_calculated_number(&wb->buffer[wb->bytes], value);
76 }
77
78 // generate a javascript date, the fastest possible way...
79 void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds)
80 {
81         //         10        20        30      = 35
82         // 01234567890123456789012345678901234
83         // Date(2014, 04, 01, 03, 28, 20, 065)
84
85         if(wb->size - wb->bytes < 36) return;
86
87         char *b = &wb->buffer[wb->bytes];
88
89         int i = 0;
90         b[i++]='D';
91         b[i++]='a';
92         b[i++]='t';
93         b[i++]='e';
94         b[i++]='(';
95         b[i++]= 48 + year / 1000; year -= (year / 1000) * 1000;
96         b[i++]= 48 + year / 100; year -= (year / 100) * 100;
97         b[i++]= 48 + year / 10;
98         b[i++]= 48 + year % 10;
99         b[i++]=',';
100         //b[i++]=' ';
101         b[i]= 48 + month / 10; if(b[i] != '0') i++;
102         b[i++]= 48 + month % 10;
103         b[i++]=',';
104         //b[i++]=' ';
105         b[i]= 48 + day / 10; if(b[i] != '0') i++;
106         b[i++]= 48 + day % 10;
107         b[i++]=',';
108         //b[i++]=' ';
109         b[i]= 48 + hours / 10; if(b[i] != '0') i++;
110         b[i++]= 48 + hours % 10;
111         b[i++]=',';
112         //b[i++]=' ';
113         b[i]= 48 + minutes / 10; if(b[i] != '0') i++;
114         b[i++]= 48 + minutes % 10;
115         b[i++]=',';
116         //b[i++]=' ';
117         b[i]= 48 + seconds / 10; if(b[i] != '0') i++;
118         b[i++]= 48 + seconds % 10;
119         b[i++]=')';
120         b[i]='\0';
121
122         wb->bytes += i;
123 }
124
125 struct web_buffer *web_buffer_create(long size)
126 {
127         struct web_buffer *b;
128
129         debug(D_WEB_BUFFER, "Creating new web buffer of size %d.", size);
130
131         b = calloc(1, sizeof(struct web_buffer));
132         if(!b) {
133                 error("Cannot allocate a web_buffer.");
134                 return NULL;
135         }
136
137         b->buffer = malloc(size);
138         if(!b->buffer) {
139                 error("Cannot allocate a buffer of size %u.", size);
140                 free(b);
141                 return NULL;
142         }
143         b->buffer[0] = '\0';
144         b->size = size;
145         b->contenttype = CT_TEXT_PLAIN;
146         return(b);
147 }
148
149 void web_buffer_free(struct web_buffer *b)
150 {
151         debug(D_WEB_BUFFER, "Freeing web buffer of size %d.", b->size);
152
153         if(b->buffer) free(b->buffer);
154         free(b);
155 }
156
157 void web_buffer_increase(struct web_buffer *b, long free_size_required)
158 {
159         long left = b->size - b->bytes;
160
161         if(left >= free_size_required) return;
162         long increase = free_size_required - left;
163         if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
164
165         debug(D_WEB_BUFFER, "Increasing data buffer from size %d to %d.", b->size, b->size + increase);
166
167         b->buffer = realloc(b->buffer, b->size + increase);
168         if(!b->buffer) fatal("Failed to increase data buffer from size %d to %d.", b->size, b->size + increase);
169         
170         b->size += increase;
171 }