wmclockmon: update change-log
[dockapps.git] / wmhdplop / util.c
blobd66ec329efd03e2e57f0afc242accd5563865afc
1 #include <string.h>
2 #include <ctype.h>
3 #include <stdarg.h>
4 #include "util.h"
6 char *
7 str_dup(const char *src) {
8 char *s;
9 s = strdup(src);
10 if (s == NULL) abort();
11 return s;
15 verifie si la chaine est vide (cad si elle ne contient que des caractères non imprimables
17 int
18 str_is_empty(const char *s) {
19 int i;
20 if (s == NULL) return 1;
21 else if (strlen(s) == 0) return 1;
22 else {
23 i = 0;
24 while (s[i] && s[i] <= ' ') i++;
25 return (i == (int)strlen(s));
30 /* recherche la première occurence d'une des chaines 'keys' dans 'src' et renvoie un pointeur vers
31 cette occurence, ainsi que le numéro de la 'keys' trouvée
33 bien sûr c'est pas optimal du tout, mais ON S'EN FOUT(tm)
35 et oui, effectivement, 'str_multi_str' est un nom à la con
37 char *
38 str_multi_str(const char *src, const char **keys, int nb_keys, int *key_idx)
40 int i;
41 const char *res;
43 assert(key_idx);
44 *key_idx = 0;
45 res = NULL;
46 for (i=0; i < nb_keys; i++) {
47 const char *p;
48 p = strstr(src, keys[i]);
49 if (p && (res==NULL || p < res)) { res = p; *key_idx = i; }
51 return (char*)res;
54 /* renvoie une chaine (allouée correctement) contenant la substitution de toutes les occurences de
55 'key' dans 'src' par 'substitution' (key et substition sont des tableaux de chaines de
56 caractères, car pour faire plusieurs substitutions, mieux vaut les effectuer simultanement que
57 les enchainer pour eviter les effets de bords
59 char *
60 str_multi_substitute(const char *src, const char **keys, const char **substitutions, int nkeys)
62 const char *p, *p_key;
63 char *dest, *p_dest;
64 int dest_sz, p_len,j;
66 if (src == NULL) return NULL;
68 /* calcul de la longueur de la destination.. */
69 p = src;
70 dest_sz = strlen(src)+1;
72 while ((p_key=str_multi_str(p, keys, nkeys, &j))) {
73 dest_sz += (strlen(substitutions[j]) - strlen(keys[j]));
74 p = p_key+strlen(keys[j]);
77 dest = malloc(dest_sz);
79 /* et là PAF ! */
80 p = src;
81 p_dest = dest;
82 while ((p_key=str_multi_str(p, keys, nkeys, &j))) {
83 memcpy(p_dest, p, p_key-p);
84 p_dest += p_key-p;
85 memcpy(p_dest, substitutions[j], strlen(substitutions[j]));
86 p_dest += strlen(substitutions[j]);
87 p = p_key + strlen(keys[j]);
89 p_len = strlen(p);
90 if (p_len) {
91 memcpy(p_dest, p, p_len); p_dest += p_len;
93 *p_dest = 0;
94 assert(p_dest - dest == dest_sz-1); /* capote à bugs */
95 return dest;
98 char *
99 str_substitute(const char *src, const char *key, const char *substitution) {
100 return str_multi_substitute(src, &key, &substitution, 1);
103 /* quotage pour les commandes externes.. à priori c'est comme pour open_url
104 mais bon.. je me refuse à donner la moindre garantie sur la sécurité
106 be aware
108 char *
109 shell_quote(const char *src)
111 char *quote = "&;`'\\\"|*?~<>^()[]{}$ ";
112 int i,dest_sz;
113 const char *p;
114 char *dest;
116 if (src == NULL || strlen(src) == 0) return strdup("");
118 dest_sz = strlen(src)+1;
119 for (p=src; *p; p++) {
120 if (strchr(quote, *p)) dest_sz+=1;
122 dest = malloc(dest_sz);
124 for (p=src, i=0; *p; p++) {
125 if (strchr(quote, *p)) {
126 dest[i++] = '\\';
128 if (*p>=0 && *p < ' ') {
129 dest[i++] = ' ';
130 } else {
131 dest[i++] = *p;
134 dest[i] = 0;
135 assert(i == dest_sz-1); /* kapeaute à beugue */
136 return dest;
140 static unsigned *crc_table = NULL;
142 void gen_crc_table(void) /* build the crc table */
144 unsigned crc, poly;
145 int i, j;
147 poly = 0xEDB88320;
148 for (i = 0; i < 256; i++)
150 crc = i;
151 for (j = 8; j > 0; j--)
153 if (crc & 1)
154 crc = (crc >> 1) ^ poly;
155 else
156 crc >>= 1;
158 crc_table[i] = crc;
163 unsigned str_hash(const unsigned char *s, int max_len) /* calculate the crc value */
165 unsigned crc;
166 int i;
168 if (crc_table == NULL) {
169 crc_table = calloc(256, sizeof(unsigned));
170 gen_crc_table();
172 crc = 0xFFFFFFFF;
173 for (i=0; i < max_len && s[i]; i++) {
174 crc = ((crc>>8) & 0x00FFFFFF) ^ crc_table[ (crc^s[i]) & 0xFF ];
176 return( crc^0xFFFFFFFF );
180 unsigned char char_trans[256];
181 static int char_trans_init = 0;
183 static void
184 init_char_trans()
186 const unsigned char *trans_accents =
187 (const unsigned char*) "éèëêÊËÉÈàâáäÀÂÁÄûüùÙçÇîïíìÏÎÍÌôóòõÔÓÒÕñ";
188 const unsigned char *trans_accents2 =
189 (const unsigned char*) "eeeeeeeeaaaaaaaauuuucciiiiiiiioooooooon";
190 int i;
192 for (i=0; i < 256; i++) {
193 unsigned char *p;
194 if ((p=(unsigned char*)strchr((char*)trans_accents, i))) {
195 char_trans[i] = trans_accents2[(p - trans_accents)];
196 } else if (i < (unsigned char)'A' || i > (unsigned char)'Z') {
197 char_trans[i] = i;
198 } else {
199 char_trans[i] = i + 'a' - 'A';
202 char_trans_init = 1;
205 unsigned char
206 chr_noaccent_tolower(unsigned char c)
208 if (char_trans_init == 0) init_char_trans();
209 return char_trans[c];
212 void
213 str_noaccent_tolower(unsigned char *s)
215 int i;
216 if (s == NULL) return;
217 if (char_trans_init == 0) init_char_trans();
218 i = 0; while(s[i]) {
219 s[i] = char_trans[s[i]]; i++;
223 unsigned char *
224 str_noaccent_casestr(const unsigned char *meule, const unsigned char *aiguille)
226 unsigned char *res;
227 char *m = strdup((char*)meule);
228 char *a = strdup((char*)aiguille);
230 str_noaccent_tolower((unsigned char*)m);
231 str_noaccent_tolower((unsigned char*)a);
232 res = (unsigned char*)strstr(m, a);
233 free(a); free(m);
234 return res;
237 /* un printf pas très fin, mais avec allocation dynamique..
238 c'est pratique ces ptites choses */
239 char *
240 str_printf(const char *fmt, ...)
242 va_list ap;
243 char *s;
244 int s_sz;
246 s_sz = 10; /* a reaugmenter des que la fonction est validee : */
247 s = malloc(s_sz); assert(s);
248 while (1) {
249 int ret;
250 va_start(ap, fmt);
251 ret = vsnprintf(s, s_sz, fmt, ap);
252 va_end(ap);
253 if (ret == -1 || ret >= s_sz-1) {
254 s_sz *= 2;
255 assert(s_sz < 100000);
256 s = realloc(s, s_sz); assert(s);
257 } else
258 break;
260 s = realloc(s, strlen(s)+1); assert(s);
261 return s;
264 /* read a line in a file and return the result in a dynamically
265 allocated buffer */
266 char *
267 str_fget_line(FILE *f)
269 int i,c;
270 char *s;
271 int s_sz;
273 s_sz = 100; s = malloc(s_sz); assert(s);
274 i = 0;
275 while ((c = fgetc(f)) > 0) {
276 if (c >= ' ' || c == '\t') {
277 s[i++] = c;
278 if (i == s_sz) {
279 s_sz *= 2; assert(s_sz < 100000);
280 s = realloc(s, s_sz); assert(s);
283 if (c == '\n') break;
285 s[i] = 0; assert(i < s_sz);
286 s = realloc(s, strlen(s)+1); assert(s);
287 return s;
290 /* remove spaces at the beginning and at the end */
291 void
292 str_trim(unsigned char *s) {
293 int i,j;
295 if (s == NULL) return;
296 j = strlen((char*)s)-1;
297 while (j>=0 && s[j] <= ' ') s[j--] = 0;
299 i = 0;
300 while (s[i] && s[i] <= ' ') i++;
301 if (i<=j) {
302 memmove(s, s+i, j+2-i);
306 /* insertion into a string list */
307 strlist *strlist_ins(strlist *head, const char *s) {
308 strlist *p; ALLOC_OBJ(p);
309 p->s = strdup(s); p->next = head; return p;