1 /*
2 * Copyright © 1994-2017 World Wide Web Consortium
3 * See http://www.w3.org/Consortium/Legal/copyright-software
4 *
5 * Author: Bert Bos <bert@w3.org>
6 * Created: 1997
7 **/
8 #include "config.h"
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #ifdef HAVE_STRING_H
12 # include <string.h>
13 #elif HAVE_STRINGS_H
14 # include <strings.h>
15 #endif
16 #include <ctype.h>
17 #include <stdbool.h>
18 #include "export.h"
19 #include "heap.e"
20
21 EXPORT typedef char *string;
22 EXPORT typedef const char *conststring;
23
24 EXPORT typedef struct _pairlist {
25 string name;
26 string value;
27 struct _pairlist *next;
28 } *pairlist;
29
30 EXPORT typedef unsigned int MediaSet;
31 EXPORT enum _Media {
32 MediaNone = 0,
33 MediaPrint = (1 << 0),
34 MediaScreen = (1 << 1),
35 MediaTTY = (1 << 2),
36 MediaBraille = (1 << 3),
37 MediaTV = (1 << 4),
38 MediaProjection = (1 << 5),
39 MediaEmbossed = (1 << 6),
40 MediaAll = 0xFF
41 };
42
43 #define eq(s, t) (*(s) == *(t) && strcmp(s, t) == 0)
44 EXPORTDEF(eq(s, t))
45
46 #define hexval(c) ((c) <= '9' ? (c)-'0' : (c) <= 'F' ? 10+(c)-'A' : 10+(c)-'a')
EXPORTDEF(hexval (c))47 EXPORTDEF(hexval(c))
48
49 /* pairlist_delete -- free all memory occupied by a pairlist */
50 EXPORT void pairlist_delete(pairlist p)
51 {
52 if (p) {
53 pairlist_delete(p->next);
54 dispose(p->name);
55 dispose(p->value);
56 dispose(p);
57 }
58 }
59
60 /* pairlist_copy -- make a deep copy of a pairlist */
pairlist_copy(const pairlist p)61 EXPORT pairlist pairlist_copy(const pairlist p)
62 {
63 pairlist h = NULL;
64
65 if (p) {
66 new(h);
67 h->name = newstring(p->name);
68 h->value = newstring(p->value);
69 h->next = pairlist_copy(p->next);
70 }
71 return h;
72 }
73
74 /* pairlist_get -- get value corresponding to name, or NULL */
pairlist_get(pairlist p,const conststring name)75 EXPORT conststring pairlist_get(pairlist p, const conststring name)
76 {
77 for (; p && strcasecmp(p->name, name) != 0; p = p->next);
78 return p ? p->value : NULL;
79 }
80
81 /* pairlist_set -- add or change a name/value pair */
pairlist_set(pairlist * p,const conststring name,const conststring val)82 EXPORT void pairlist_set(pairlist *p, const conststring name,
83 const conststring val)
84 {
85 pairlist h;
86
87 for (h = *p; h && strcasecmp(h->name, name) != 0; h = h->next);
88 if (h) {
89 free(h->value);
90 h->value = newstring(val);
91 } else {
92 new(h);
93 h->name = newstring(name);
94 h->value = newstring(val);
95 h->next = *p;
96 *p = h;
97 }
98 }
99
100 /* pairlist_unset -- remove a name/value pair from list, false if not found */
pairlist_unset(pairlist * p,const conststring name)101 EXPORT bool pairlist_unset(pairlist *p, const conststring name)
102 {
103
104 pairlist h, h1;
105
106 if (! *p) return false;
107 if (strcasecmp((*p)->name, name) == 0) {
108 /* Remove first pair in list */
109 h = *p;
110 free(h->name);
111 free(h->value);
112 *p = h->next;
113 free(h);
114 return true;
115 }
116 for (h = *p; h->next && strcasecmp(h->next->name, name) != 0; h = h->next);
117 if (! h->next) return false; /* Not found */
118 free(h->next->name);
119 free(h->next->value);
120 h1 = h->next;
121 h->next = h->next->next;
122 free(h1);
123 return true;
124 }
125
126 /* strapp -- append to a string, re-allocating memory; last arg must be 0 */
strapp(string * s,...)127 EXPORT string strapp(string *s,...)
128 {
129 va_list ap;
130 int i, j;
131 conststring h;
132
133 va_start(ap, s);
134 if (!s) {new(s); *s = NULL;}
135 i = *s ? strlen(*s) : 0;
136 while ((h = va_arg(ap, conststring))) {
137 j = strlen(h);
138 renewarray(*s, i + j + 1);
139 strcpy(*s + i, h);
140 i += j;
141 }
142 va_end(ap);
143 return *s;
144 }
145
146 /* chomp -- remove trailing \n or \r\n (if any) from string */
chomp(string s)147 EXPORT void chomp(string s)
148 {
149 int i;
150
151 if (s && (i = strlen(s)) != 0 && s[i-1] == '\n') {
152 s[i-1] = '\0';
153 if (i > 1 && s[i-2] == '\r') s[i-2] = '\0';
154 }
155 }
156
min(int a,int b)157 EXPORT int min(int a, int b) { return a < b ? a : b; }
max(int a,int b)158 EXPORT int max(int a, int b) { return a > b ? a : b; }
159
160 /* down -- convert a string to lowercase, return pointer to arg */
down(const string s)161 EXPORT string down(const string s)
162 {
163 string t;
164
165 for (t = s; *t; t++) *t = tolower(*t);
166 return s;
167 }
168
169 /* hasprefix -- true if s starts with prefix */
hasprefix(conststring s,conststring prefix)170 EXPORT bool hasprefix(conststring s, conststring prefix)
171 {
172 if (!prefix) return true; /* NULL is prefix of everything */
173 if (!s) return !prefix; /* Only NULL is prefix of NULL */
174 while (*prefix && *prefix == *s) prefix++, s++;
175 return *prefix == '\0';
176 }
177
178 /* hasaffix -- true if s ends with affix */
hasaffix(conststring s,conststring affix)179 EXPORT bool hasaffix(conststring s, conststring affix)
180 {
181 size_t i, j;
182
183 if (!affix) return true;
184 if (!s) return !affix;
185 i = strlen(s);
186 j = strlen(affix);
187 if (i < j) return false;
188 s = s + i - j;
189 while (*affix && *affix == *s) affix++, s++;
190 return *affix == '\0';
191 }
192
193 /* only_space -- check if s contains only whitespace */
only_space(conststring s)194 EXPORT bool only_space(conststring s)
195 {
196 while (*s == ' ' || *s == '\n' || *s == '\r' || *s == '\t' || *s == '\f')
197 s++;
198 return *s == '\0';
199 }
200
201