NetSurf
utils.c
Go to the documentation of this file.
1/*
2 * Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
3 * Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
4 * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
5 * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
6 * Copyright 2004 John Tytgat <joty@netsurf-browser.org>
7 *
8 * This file is part of NetSurf, http://www.netsurf-browser.org/
9 *
10 * NetSurf is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
13 *
14 * NetSurf is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <assert.h>
24#include <stdio.h>
25#include <string.h>
26#include <strings.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <unistd.h>
30
31#include "utils/messages.h"
32#include "utils/dirent.h"
33#include "utils/inet.h"
34#include "utils/string.h"
35#include "utils/utils.h"
36
37/* exported interface documented in utils/string.h */
38char *squash_whitespace(const char *s)
39{
40 char *c;
41 int i = 0, j = 0;
42
43 assert(s != NULL);
44
45 c = malloc(strlen(s) + 1);
46 if (c != NULL) {
47 do {
48 if (s[i] == ' ' ||
49 s[i] == '\n' ||
50 s[i] == '\r' ||
51 s[i] == '\t') {
52 c[j++] = ' ';
53 while (s[i] == ' ' ||
54 s[i] == '\n' ||
55 s[i] == '\r' ||
56 s[i] == '\t')
57 i++;
58 }
59 c[j++] = s[i++];
60 } while (s[i - 1] != 0);
61 }
62 return c;
63}
64
65
66/* exported interface documented in utils/utils.h */
67char *cnv_space2nbsp(const char *s)
68{
69 const char *srcP;
70 char *d, *d0;
71 unsigned int numNBS;
72 /* Convert space & TAB into non breaking space character (0xA0) */
73 for (numNBS = 0, srcP = (const char *)s; *srcP != '\0'; ++srcP) {
74 if (*srcP == ' ' || *srcP == '\t') {
75 ++numNBS;
76 }
77 }
78 if ((d = (char *)malloc((srcP - s) + numNBS + 1)) == NULL) {
79 return NULL;
80 }
81 for (d0 = d, srcP = (const char *)s; *srcP != '\0'; ++srcP) {
82 if (*srcP == ' ' || *srcP == '\t') {
83 *d0++ = 0xC2;
84 *d0++ = 0xA0;
85 } else
86 *d0++ = *srcP;
87 }
88 *d0 = '\0';
89 return d;
90}
91
92
93/* exported interface documented in utils/utils.h */
94bool is_dir(const char *path)
95{
96 struct stat s;
97
98 if (stat(path, &s)) {
99 return false;
100 }
101
102 return S_ISDIR(s.st_mode) ? true : false;
103}
104
105
106/* exported interface documented in utils/utils.h */
107nserror vsnstrjoin(char **str, size_t *size, char sep, size_t nelm, va_list ap)
108{
109 const char *elm[16];
110 size_t elm_len[16];
111 size_t elm_idx;
112 char *fname;
113 size_t fname_len = 0;
114 char *curp;
115
116 /* check the parameters are all sensible */
117 if ((nelm == 0) || (nelm > 16)) {
119 }
120 if ((*str != NULL) && (size == NULL)) {
121 /* if the caller is providing the buffer they must say
122 * how much space is available.
123 */
125 }
126
127 /* calculate how much storage we need for the complete path
128 * with all the elements.
129 */
130 for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
131 elm[elm_idx] = va_arg(ap, const char *);
132 /* check the argument is not NULL */
133 if (elm[elm_idx] == NULL) {
135 }
136 elm_len[elm_idx] = strlen(elm[elm_idx]);
137 fname_len += elm_len[elm_idx];
138 }
139 fname_len += nelm; /* allow for separators and terminator */
140
141 /* ensure there is enough space */
142 fname = *str;
143 if (fname != NULL) {
144 if (fname_len > *size) {
145 return NSERROR_NOSPACE;
146 }
147 } else {
148 fname = malloc(fname_len);
149 if (fname == NULL) {
150 return NSERROR_NOMEM;
151 }
152 }
153
154 /* copy the elements in with apropriate separator */
155 curp = fname;
156 for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
157 memmove(curp, elm[elm_idx], elm_len[elm_idx]);
158 curp += elm_len[elm_idx];
159 /* ensure string are separated */
160 if (curp[-1] != sep) {
161 *curp = sep;
162 curp++;
163 }
164 }
165 curp[-1] = 0; /* NULL terminate */
166
167 assert((curp - fname) <= (int)fname_len);
168
169 *str = fname;
170 if (size != NULL) {
171 *size = fname_len;
172 }
173
174 return NSERROR_OK;
175}
176
177
178/* exported interface documented in utils/utils.h */
179nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...)
180{
181 va_list ap;
182 nserror ret;
183
184 va_start(ap, nelm);
185 ret = vsnstrjoin(str, size, sep, nelm, ap);
186 va_end(ap);
187
188 return ret;
189}
190
191
192/**
193 * The size of buffers within human_friendly_bytesize.
194 *
195 * We can have a fairly good estimate of the output buffers maximum length.
196 *
197 * The unsigned long long int can store a value representing a maximum
198 * size of 16 EiB (exibytes). Therefore the greatest space required is to
199 * represent 1023 PiB.
200 * Currently that would be represented as "1023.00PiBytes" in english
201 * giving a 15 byte length including a null terminator.
202 * Ideally we would be able to accurately know this length for other
203 * languages, in the mean time a largeish buffer size is selected
204 * and should suffice.
205 */
206#define BYTESIZE_BUFFER_SIZE 32
207
208/* exported interface documented in utils/string.h */
209char *human_friendly_bytesize(unsigned long long int bsize) {
210 static char buffer1[BYTESIZE_BUFFER_SIZE];
211 static char buffer2[BYTESIZE_BUFFER_SIZE];
212 static char buffer3[BYTESIZE_BUFFER_SIZE];
213 static char *curbuffer = buffer3;
214 enum {
215 bytes,
216 kilobytes,
217 megabytes,
218 gibibytes,
219 tebibytes,
220 pebibytes,
221 exbibytes } unit = bytes;
222 static const char *const units[] = {
223 "Bytes",
224 "KiBytes",
225 "MiBytes",
226 "GiBytes",
227 "TiBytes",
228 "PiBytes",
229 "EiBytes" };
230 double bytesize = (double)bsize;
231 const char *fmt;
232
233 if (curbuffer == buffer1)
234 curbuffer = buffer2;
235 else if (curbuffer == buffer2)
236 curbuffer = buffer3;
237 else
238 curbuffer = buffer1;
239
240 if (bytesize > 1024) {
241 bytesize /= 1024;
242 unit = kilobytes;
243 }
244
245 if (bytesize > 1024) {
246 bytesize /= 1024;
247 unit = megabytes;
248 }
249
250 if (bytesize > 1024) {
251 bytesize /= 1024;
252 unit = gibibytes;
253 }
254
255 if (bytesize > 1024) {
256 bytesize /= 1024;
257 unit = tebibytes;
258 }
259
260 if (bytesize > 1024) {
261 bytesize /= 1024;
262 unit = pebibytes;
263 }
264
265 if (bytesize > 1024) {
266 bytesize /= 1024;
267 unit = exbibytes;
268 }
269
270 if (unit == bytes) {
271 fmt = "%.0f%s";
272 } else {
273 fmt = "%3.2f%s";
274 }
275
276 snprintf(curbuffer,
278 fmt,
279 bytesize,
280 messages_get(units[unit]));
281
282 return curbuffer;
283}
284
285
286#ifndef HAVE_STRTOULL
287#include <stdlib.h>
288
289/**
290 * string to unsigned long long
291 *
292 */
293unsigned long long int strtoull(const char *nptr, char **endptr, int base)
294{
295 return (unsigned long long int)strtoul(nptr, endptr, base);
296}
297
298#endif
299
300
301#ifndef HAVE_STRCASESTR
302
303/**
304 * Case insensitive strstr implementation
305 *
306 * \param haystack String to search in
307 * \param needle String to look for
308 * \return Pointer to start of found substring, or NULL if not found
309 */
310char *strcasestr(const char *haystack, const char *needle)
311{
312 size_t needle_len = strlen(needle);
313 const char * last_start = haystack + (strlen(haystack) - needle_len);
314
315 while (haystack <= last_start) {
316 if (strncasecmp(haystack, needle, needle_len) == 0)
317 return (char *)haystack;
318 haystack++;
319 }
320
321 return NULL;
322}
323
324#endif
325
326
327#ifndef HAVE_STRNDUP
328
329/**
330 * Duplicate up to n characters of a string.
331 */
332char *strndup(const char *s, size_t n)
333{
334 size_t len;
335 char *s2;
336
337 for (len = 0; len != n && s[len]; len++)
338 continue;
339
340 s2 = malloc(len + 1);
341 if (!s2)
342 return 0;
343
344 memcpy(s2, s, len);
345 s2[len] = 0;
346 return s2;
347}
348
349#endif
350
351
352#ifndef HAVE_SCANDIR
353
354/* exported function documented in utils/dirent.h */
355int alphasort(const struct dirent **d1, const struct dirent **d2)
356{
357 return strcasecmp((*d1)->d_name, (*d2)->d_name);
358}
359
360/* exported function documented in utils/dirent.h */
361int scandir(const char *dir, struct dirent ***namelist,
362 int (*sel)(const struct dirent *),
363 int (*compar)(const struct dirent **, const struct dirent **))
364{
365 struct dirent **entlist = NULL;
366 struct dirent **entlist_temp = NULL;
367 struct dirent *ent = NULL, *new_ent;
368 int alloc_n = 0;
369 int n = 0;
370 DIR *d;
371
372 d = opendir(dir);
373 if (d == NULL) {
374 goto error;
375 }
376
377 while ((ent = readdir(d)) != NULL) {
378 /* Avoid entries that caller doesn't want */
379 if (sel && (*sel)(ent) == 0)
380 continue;
381
382 /* Ensure buffer is big enough to list this entry */
383 if (n == alloc_n) {
384 alloc_n *= 4;
385 if (alloc_n == 0) {
386 alloc_n = 32;
387 }
388 entlist_temp = realloc(entlist,
389 sizeof(*entlist) * alloc_n);
390 if (entlist_temp == NULL) {
391 goto error;
392 }
393 entlist = entlist_temp;
394 }
395
396 /* Make copy of ent */
397 new_ent = malloc(sizeof(*new_ent));
398 if (new_ent == NULL) {
399 goto error;
400 }
401 memcpy(new_ent, ent, sizeof(struct dirent));
402
403 /* Make list entry point to this copy of ent */
404 entlist[n] = new_ent;
405
406 n++;
407 }
408
409 closedir(d);
410
411 /* Sort */
412 if (compar != NULL && n > 1)
413 qsort(entlist, n, sizeof(*entlist),
414 (int (*)(const void *, const void *))compar);
415 *namelist = entlist;
416 return n;
417
418error:
419
420 if (entlist != NULL) {
421 int i;
422 for (i = 0; i < n; i++) {
423 free(entlist[i]);
424 }
425 free(entlist);
426 }
427
428 if (d != NULL) {
429 closedir(d);
430 }
431
432 return -1;
433}
434
435#endif
436
437
438#ifndef HAVE_STRCHRNUL
439
440/**
441 * Find the first occurrence of C in S or the final NUL byte.
442 */
443char *strchrnul (const char *s, int c_in)
444{
445 const unsigned char *us = (const unsigned char *) s;
446
447 while (*us != c_in && *us != '\0')
448 us++;
449
450 return (void *) us;
451}
452
453#endif
454
455#ifndef HAVE_UTSNAME
456
457#include "utils/utsname.h"
458
459int uname(struct utsname *buf) {
460 strcpy(buf->sysname,"windows");
461 strcpy(buf->nodename,"nodename");
462 strcpy(buf->release,"release");
463 strcpy(buf->version,"version");
464 strcpy(buf->machine,"pc");
465
466 return 0;
467}
468
469#endif
470
471#ifndef HAVE_REALPATH
472
473char *realpath(const char *path, char *resolved_path)
474{
475 char *ret;
476 if (resolved_path == NULL) {
477 ret=strdup(path);
478 } else {
479 ret = resolved_path;
480 strcpy(resolved_path, path);
481 }
482 return ret;
483}
484
485#endif
486
487#ifndef HAVE_INETATON
488
489int inet_aton(const char *cp, struct in_addr *inp)
490{
491 unsigned int b1, b2, b3, b4;
492 unsigned char c;
493
494 if (strspn(cp, "0123456789.") < strlen(cp))
495 return 0;
496
497 if (sscanf(cp, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c) != 4)
498 return 0;
499
500 if ((b1 > 255) || (b2 > 255) || (b3 > 255) || (b4 > 255))
501 return 0;
502
503 inp->s_addr = b4 << 24 | b3 << 16 | b2 << 8 | b1;
504
505 return 1;
506}
507
508#endif
509
510#ifndef HAVE_INETPTON
511
512int inet_pton(int af, const char *src, void *dst)
513{
514 int ret;
515
516 if (af == AF_INET) {
517 ret = inet_aton(src, dst);
518 }
519#if !defined(NO_IPV6)
520 else if (af == AF_INET6) {
521 /* TODO: implement v6 address support */
522 ret = -1;
523 errno = EAFNOSUPPORT;
524 }
525#endif
526 else {
527 ret = -1;
528 errno = EAFNOSUPPORT;
529 }
530
531 return ret;
532}
533
534#endif
535
536
537#ifndef HAVE_REGEX
538
539#include "utils/regex.h"
540
541int
542regcomp(regex_t *restrict preg, const char *restrictregex, int cflags)
543{
544 return 0;
545}
546
547size_t
548regerror(int errorcode,
549 const regex_t *restrict preg,
550 char *restrict errbuf,
551 size_t errbuf_size)
552{
553 if ((errbuf != NULL) && (errbuf_size != 0)) {
554 *errbuf = 0;
555 }
556 return 0;
557}
558
559int
560regexec(const regex_t *restrict preg,
561 const char *restrict string,
562 size_t nmatch,
563 regmatch_t pmatch[restrict],
564 int eflags)
565{
566 return REG_NOMATCH;
567}
568
569void regfree(regex_t *preg)
570{
571}
572
573#endif
directory traversal and entry
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOSPACE
Insufficient space.
Definition: errors.h:59
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
static int compar(const void *va, const void *vb)
Quick sort comparison.
internet structures and defines
#define EAFNOSUPPORT
Definition: inet.h:58
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
@ base
Definition: punycode.c:19
#define REG_NOMATCH
Definition: regex.h:29
Interface to utility string handling.
Definition: regex.h:38
system information filled in by uname derived from posix spec.
Definition: utsname.h:31
char release[65]
OS release (e.g., "2.6.28")
Definition: utsname.h:36
char nodename[65]
Name within "some implementation-defined network".
Definition: utsname.h:33
char version[65]
OS version.
Definition: utsname.h:37
char machine[65]
Hardware identifier.
Definition: utsname.h:38
char sysname[65]
Operating system name (e.g., "Linux")
Definition: utsname.h:32
Interface to a number of general purpose functionality.
char * realpath(const char *path, char *resolved_path)
Definition: utils.c:473
char * cnv_space2nbsp(const char *s)
Converts NUL terminated UTF-8 encoded string s containing zero or more spaces (char 32) or TABs (char...
Definition: utils.c:67
bool is_dir(const char *path)
Check if a directory exists.
Definition: utils.c:94
nserror vsnstrjoin(char **str, size_t *size, char sep, size_t nelm, va_list ap)
Generate a string from one or more component elements separated with a single value.
Definition: utils.c:107
int inet_aton(const char *cp, struct in_addr *inp)
Definition: utils.c:489
char * squash_whitespace(const char *s)
Replace consecutive whitespace with a single space.
Definition: utils.c:38
int alphasort(const struct dirent **d1, const struct dirent **d2)
Definition: utils.c:355
#define BYTESIZE_BUFFER_SIZE
The size of buffers within human_friendly_bytesize.
Definition: utils.c:206
char * human_friendly_bytesize(unsigned long long int bsize)
Create a human readable representation of a size in bytes.
Definition: utils.c:209
char * strchrnul(const char *s, int c_in)
Find the first occurrence of C in S or the final NUL byte.
Definition: utils.c:443
int uname(struct utsname *buf)
Get the system information.
Definition: utils.c:459
size_t regerror(int errorcode, const regex_t *restrict preg, char *restrict errbuf, size_t errbuf_size)
Definition: utils.c:548
unsigned long long int strtoull(const char *nptr, char **endptr, int base)
string to unsigned long long
Definition: utils.c:293
int regexec(const regex_t *restrict preg, const char *restrict string, size_t nmatch, regmatch_t pmatch[restrict], int eflags)
Definition: utils.c:560
nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm,...)
Generate a string from one or more component elements separated with a single value.
Definition: utils.c:179
char * strcasestr(const char *haystack, const char *needle)
Case insensitive strstr implementation.
Definition: utils.c:310
int scandir(const char *dir, struct dirent ***namelist, int(*sel)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
Definition: utils.c:361
int inet_pton(int af, const char *src, void *dst)
Definition: utils.c:512
void regfree(regex_t *preg)
Definition: utils.c:569
char * strndup(const char *s, size_t n)
Duplicate up to n characters of a string.
Definition: utils.c:332
int regcomp(regex_t *restrict preg, const char *restrictregex, int cflags)
Definition: utils.c:542
Interface to uts API to get name and information about current kernel.
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821