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