blob: f43a9453916e0380a8701510c735b62d46dbe4c2 [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
Pierre Ossman546b2ad2019-05-02 12:32:03 +02002 * Copyright 2011-2019 Pierre Ossman for Cendio AB
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00003 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19
Adam Tkac8aee1a82009-09-04 12:08:56 +000020#ifdef HAVE_CONFIG_H
21#include <config.h>
Adam Tkacad1cbd92008-10-06 14:08:00 +000022#endif
23
Pierre Ossmanba6fbfe2015-03-03 16:41:29 +010024#include <stdarg.h>
Pierre Ossman64624342015-03-03 16:30:13 +010025#include <stdio.h>
Pierre Ossman5bc20a62011-11-08 12:42:41 +000026#include <sys/time.h>
27
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000028#include <rfb/util.h>
29
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000030namespace rfb {
31
Pierre Ossmanba6fbfe2015-03-03 16:41:29 +010032 void CharArray::format(const char *fmt, ...) {
33 va_list ap;
Steve Kondikb3c9f7b2017-07-08 02:08:43 -070034 int len;
Pierre Ossmanba6fbfe2015-03-03 16:41:29 +010035
36 va_start(ap, fmt);
37 len = vsnprintf(NULL, 0, fmt, ap);
38 va_end(ap);
39
40 delete [] buf;
41
42 if (len < 0) {
43 buf = new char[1];
44 buf[0] = '\0';
45 return;
46 }
47
48 buf = new char[len+1];
49
50 va_start(ap, fmt);
51 vsnprintf(buf, len+1, fmt, ap);
52 va_end(ap);
53 }
54
Adam Tkacd36b6262009-09-04 10:57:20 +000055 char* strDup(const char* s) {
56 if (!s) return 0;
57 int l = strlen(s);
58 char* r = new char[l+1];
59 memcpy(r, s, l+1);
60 return r;
61 };
62
63 void strFree(char* s) {
64 delete [] s;
65 }
66
67
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000068 bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) {
69 CharArray out1old, out2old;
70 if (out1) out1old.buf = *out1;
71 if (out2) out2old.buf = *out2;
72 int len = strlen(src);
73 int i=0, increment=1, limit=len;
74 if (fromEnd) {
75 i=len-1; increment = -1; limit = -1;
76 }
77 while (i!=limit) {
78 if (src[i] == limiter) {
79 if (out1) {
80 *out1 = new char[i+1];
81 if (i) memcpy(*out1, src, i);
82 (*out1)[i] = 0;
83 }
84 if (out2) {
85 *out2 = new char[len-i];
86 if (len-i-1) memcpy(*out2, &src[i+1], len-i-1);
87 (*out2)[len-i-1] = 0;
88 }
89 return true;
90 }
91 i+=increment;
92 }
Adam Tkacd36b6262009-09-04 10:57:20 +000093 if (out1) *out1 = strDup(src);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000094 if (out2) *out2 = 0;
95 return false;
96 }
97
98 bool strContains(const char* src, char c) {
99 int l=strlen(src);
100 for (int i=0; i<l; i++)
101 if (src[i] == c) return true;
102 return false;
103 }
104
105 void strCopy(char* dest, const char* src, int destlen) {
106 if (src)
107 strncpy(dest, src, destlen-1);
108 dest[src ? destlen-1 : 0] = 0;
109 }
110
Pierre Ossman546b2ad2019-05-02 12:32:03 +0200111 char* convertLF(const char* src, size_t bytes)
112 {
113 char* buffer;
114 size_t sz;
115
116 char* out;
117 const char* in;
118 size_t in_len;
119
120 // Always include space for a NULL
121 sz = 1;
122
123 // Compute output size
124 in = src;
125 in_len = bytes;
126 while ((*in != '\0') && (in_len > 0)) {
127 if (*in != '\r') {
128 sz++;
129 in++;
130 in_len--;
131 continue;
132 }
133
134 if ((in_len == 0) || (*(in+1) != '\n'))
135 sz++;
136
137 in++;
138 in_len--;
139 }
140
141 // Alloc
142 buffer = new char[sz];
143 memset(buffer, 0, sz);
144
145 // And convert
146 out = buffer;
147 in = src;
148 in_len = bytes;
149 while ((*in != '\0') && (in_len > 0)) {
150 if (*in != '\r') {
151 *out++ = *in++;
152 in_len--;
153 continue;
154 }
155
156 if ((in_len == 0) || (*(in+1) != '\n'))
157 *out++ = '\n';
158
159 in++;
160 in_len--;
161 }
162
163 return buffer;
164 }
165
Pierre Ossmana99d14d2015-12-13 15:43:46 +0100166 unsigned msBetween(const struct timeval *first,
167 const struct timeval *second)
168 {
169 unsigned diff;
170
171 diff = (second->tv_sec - first->tv_sec) * 1000;
172
173 diff += second->tv_usec / 1000;
174 diff -= first->tv_usec / 1000;
175
176 return diff;
177 }
178
Pierre Ossman5bc20a62011-11-08 12:42:41 +0000179 unsigned msSince(const struct timeval *then)
180 {
181 struct timeval now;
Pierre Ossman5bc20a62011-11-08 12:42:41 +0000182
183 gettimeofday(&now, NULL);
184
Pierre Ossmana99d14d2015-12-13 15:43:46 +0100185 return msBetween(then, &now);
186 }
Pierre Ossman5bc20a62011-11-08 12:42:41 +0000187
Pierre Ossmana99d14d2015-12-13 15:43:46 +0100188 bool isBefore(const struct timeval *first,
189 const struct timeval *second)
190 {
191 if (first->tv_sec < second->tv_sec)
192 return true;
193 if (first->tv_sec > second->tv_sec)
194 return false;
195 if (first->tv_usec < second->tv_usec)
196 return true;
197 return false;
Pierre Ossman5bc20a62011-11-08 12:42:41 +0000198 }
Pierre Ossman64624342015-03-03 16:30:13 +0100199
200 static size_t doPrefix(long long value, const char *unit,
201 char *buffer, size_t maxlen,
202 unsigned divisor, const char **prefixes,
Pierre Ossman921f6c82017-02-24 12:33:09 +0100203 size_t prefixCount, int precision) {
Pierre Ossman64624342015-03-03 16:30:13 +0100204 double newValue;
205 size_t prefix, len;
206
207 newValue = value;
208 prefix = 0;
209 while (newValue >= divisor) {
210 if (prefix >= prefixCount)
211 break;
212 newValue /= divisor;
213 prefix++;
214 }
215
Pierre Ossman921f6c82017-02-24 12:33:09 +0100216 len = snprintf(buffer, maxlen, "%.*g %s%s", precision, newValue,
Pierre Ossman64624342015-03-03 16:30:13 +0100217 (prefix == 0) ? "" : prefixes[prefix-1], unit);
218 buffer[maxlen-1] = '\0';
219
220 return len;
221 }
222
223 static const char *siPrefixes[] =
224 { "k", "M", "G", "T", "P", "E", "Z", "Y" };
225 static const char *iecPrefixes[] =
226 { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
227
228 size_t siPrefix(long long value, const char *unit,
Pierre Ossman921f6c82017-02-24 12:33:09 +0100229 char *buffer, size_t maxlen, int precision) {
Pierre Ossman64624342015-03-03 16:30:13 +0100230 return doPrefix(value, unit, buffer, maxlen, 1000, siPrefixes,
Pierre Ossman921f6c82017-02-24 12:33:09 +0100231 sizeof(siPrefixes)/sizeof(*siPrefixes),
232 precision);
Pierre Ossman64624342015-03-03 16:30:13 +0100233 }
234
235 size_t iecPrefix(long long value, const char *unit,
Pierre Ossman921f6c82017-02-24 12:33:09 +0100236 char *buffer, size_t maxlen, int precision) {
Pierre Ossman64624342015-03-03 16:30:13 +0100237 return doPrefix(value, unit, buffer, maxlen, 1024, iecPrefixes,
Pierre Ossman921f6c82017-02-24 12:33:09 +0100238 sizeof(iecPrefixes)/sizeof(*iecPrefixes),
239 precision);
Pierre Ossman64624342015-03-03 16:30:13 +0100240 }
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000241};