311 lines
6.8 KiB
C
311 lines
6.8 KiB
C
|
#include <string.h>
|
|||
|
#include <ctype.h>
|
|||
|
#include <stdarg.h>
|
|||
|
#include "util.h"
|
|||
|
|
|||
|
char *
|
|||
|
str_dup(const char *src) {
|
|||
|
char *s;
|
|||
|
s = strdup(src);
|
|||
|
if (s == NULL) abort();
|
|||
|
return s;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
verifie si la chaine est vide (cad si elle ne contient que des caract<EFBFBD>res non imprimables
|
|||
|
*/
|
|||
|
int
|
|||
|
str_is_empty(const char *s) {
|
|||
|
int i;
|
|||
|
if (s == NULL) return 1;
|
|||
|
else if (strlen(s) == 0) return 1;
|
|||
|
else {
|
|||
|
i = 0;
|
|||
|
while (s[i] && s[i] <= ' ') i++;
|
|||
|
return (i == (int)strlen(s));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* recherche la premi<6D>re occurence d'une des chaines 'keys' dans 'src' et renvoie un pointeur vers
|
|||
|
cette occurence, ainsi que le num<EFBFBD>ro de la 'keys' trouv<EFBFBD>e
|
|||
|
|
|||
|
bien s<EFBFBD>r c'est pas optimal du tout, mais ON S'EN FOUT(tm)
|
|||
|
|
|||
|
et oui, effectivement, 'str_multi_str' est un nom <EFBFBD> la con
|
|||
|
*/
|
|||
|
char *
|
|||
|
str_multi_str(const char *src, const char **keys, int nb_keys, int *key_idx)
|
|||
|
{
|
|||
|
int i;
|
|||
|
const char *res;
|
|||
|
|
|||
|
assert(key_idx);
|
|||
|
*key_idx = 0;
|
|||
|
res = NULL;
|
|||
|
for (i=0; i < nb_keys; i++) {
|
|||
|
const char *p;
|
|||
|
p = strstr(src, keys[i]);
|
|||
|
if (p && (res==NULL || p < res)) { res = p; *key_idx = i; }
|
|||
|
}
|
|||
|
return (char*)res;
|
|||
|
}
|
|||
|
|
|||
|
/* renvoie une chaine (allou<6F>e correctement) contenant la substitution de toutes les occurences de
|
|||
|
'key' dans 'src' par 'substitution' (key et substition sont des tableaux de chaines de
|
|||
|
caract<EFBFBD>res, car pour faire plusieurs substitutions, mieux vaut les effectuer simultanement que
|
|||
|
les enchainer pour eviter les effets de bords
|
|||
|
*/
|
|||
|
char *
|
|||
|
str_multi_substitute(const char *src, const char **keys, const char **substitutions, int nkeys)
|
|||
|
{
|
|||
|
const char *p, *p_key;
|
|||
|
char *dest, *p_dest;
|
|||
|
int dest_sz, p_len,j;
|
|||
|
|
|||
|
if (src == NULL) return NULL;
|
|||
|
|
|||
|
/* calcul de la longueur de la destination.. */
|
|||
|
p = src;
|
|||
|
dest_sz = strlen(src)+1;
|
|||
|
|
|||
|
while ((p_key=str_multi_str(p, keys, nkeys, &j))) {
|
|||
|
dest_sz += (strlen(substitutions[j]) - strlen(keys[j]));
|
|||
|
p = p_key+strlen(keys[j]);
|
|||
|
}
|
|||
|
|
|||
|
dest = malloc(dest_sz);
|
|||
|
|
|||
|
/* et l<> PAF ! */
|
|||
|
p = src;
|
|||
|
p_dest = dest;
|
|||
|
while ((p_key=str_multi_str(p, keys, nkeys, &j))) {
|
|||
|
memcpy(p_dest, p, p_key-p);
|
|||
|
p_dest += p_key-p;
|
|||
|
memcpy(p_dest, substitutions[j], strlen(substitutions[j]));
|
|||
|
p_dest += strlen(substitutions[j]);
|
|||
|
p = p_key + strlen(keys[j]);
|
|||
|
}
|
|||
|
p_len = strlen(p);
|
|||
|
if (p_len) {
|
|||
|
memcpy(p_dest, p, p_len); p_dest += p_len;
|
|||
|
}
|
|||
|
*p_dest = 0;
|
|||
|
assert(p_dest - dest == dest_sz-1); /* capote <20> bugs */
|
|||
|
return dest;
|
|||
|
}
|
|||
|
|
|||
|
char *
|
|||
|
str_substitute(const char *src, const char *key, const char *substitution) {
|
|||
|
return str_multi_substitute(src, &key, &substitution, 1);
|
|||
|
}
|
|||
|
|
|||
|
/* quotage pour les commandes externes.. <20> priori c'est comme pour open_url
|
|||
|
mais bon.. je me refuse <EFBFBD> donner la moindre garantie sur la s<EFBFBD>curit<EFBFBD>
|
|||
|
|
|||
|
be aware
|
|||
|
*/
|
|||
|
char *
|
|||
|
shell_quote(const char *src)
|
|||
|
{
|
|||
|
char *quote = "&;`'\\\"|*?~<>^()[]{}$ ";
|
|||
|
int i,dest_sz;
|
|||
|
const char *p;
|
|||
|
char *dest;
|
|||
|
|
|||
|
if (src == NULL || strlen(src) == 0) return strdup("");
|
|||
|
|
|||
|
dest_sz = strlen(src)+1;
|
|||
|
for (p=src; *p; p++) {
|
|||
|
if (strchr(quote, *p)) dest_sz+=1;
|
|||
|
}
|
|||
|
dest = malloc(dest_sz);
|
|||
|
|
|||
|
for (p=src, i=0; *p; p++) {
|
|||
|
if (strchr(quote, *p)) {
|
|||
|
dest[i++] = '\\';
|
|||
|
}
|
|||
|
if (*p>=0 && *p < ' ') {
|
|||
|
dest[i++] = ' ';
|
|||
|
} else {
|
|||
|
dest[i++] = *p;
|
|||
|
}
|
|||
|
}
|
|||
|
dest[i] = 0;
|
|||
|
assert(i == dest_sz-1); /* kapeaute <20> beugue */
|
|||
|
return dest;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static unsigned *crc_table = NULL;
|
|||
|
|
|||
|
void gen_crc_table(void) /* build the crc table */
|
|||
|
{
|
|||
|
unsigned crc, poly;
|
|||
|
int i, j;
|
|||
|
|
|||
|
poly = 0xEDB88320;
|
|||
|
for (i = 0; i < 256; i++)
|
|||
|
{
|
|||
|
crc = i;
|
|||
|
for (j = 8; j > 0; j--)
|
|||
|
{
|
|||
|
if (crc & 1)
|
|||
|
crc = (crc >> 1) ^ poly;
|
|||
|
else
|
|||
|
crc >>= 1;
|
|||
|
}
|
|||
|
crc_table[i] = crc;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
unsigned str_hash(const unsigned char *s, int max_len) /* calculate the crc value */
|
|||
|
{
|
|||
|
unsigned crc;
|
|||
|
int i;
|
|||
|
|
|||
|
if (crc_table == NULL) {
|
|||
|
crc_table = calloc(256, sizeof(unsigned));
|
|||
|
gen_crc_table();
|
|||
|
}
|
|||
|
crc = 0xFFFFFFFF;
|
|||
|
for (i=0; i < max_len && s[i]; i++) {
|
|||
|
crc = ((crc>>8) & 0x00FFFFFF) ^ crc_table[ (crc^s[i]) & 0xFF ];
|
|||
|
}
|
|||
|
return( crc^0xFFFFFFFF );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
unsigned char char_trans[256];
|
|||
|
static int char_trans_init = 0;
|
|||
|
|
|||
|
static void
|
|||
|
init_char_trans()
|
|||
|
{
|
|||
|
const unsigned char *trans_accents =
|
|||
|
(const unsigned char*) "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
|||
|
const unsigned char *trans_accents2 =
|
|||
|
(const unsigned char*) "eeeeeeeeaaaaaaaauuuucciiiiiiiioooooooon";
|
|||
|
int i;
|
|||
|
|
|||
|
for (i=0; i < 256; i++) {
|
|||
|
unsigned char *p;
|
|||
|
if ((p=(unsigned char*)strchr((char*)trans_accents, i))) {
|
|||
|
char_trans[i] = trans_accents2[(p - trans_accents)];
|
|||
|
} else if (i < (unsigned char)'A' || i > (unsigned char)'Z') {
|
|||
|
char_trans[i] = i;
|
|||
|
} else {
|
|||
|
char_trans[i] = i + 'a' - 'A';
|
|||
|
}
|
|||
|
}
|
|||
|
char_trans_init = 1;
|
|||
|
}
|
|||
|
|
|||
|
unsigned char
|
|||
|
chr_noaccent_tolower(unsigned char c)
|
|||
|
{
|
|||
|
if (char_trans_init == 0) init_char_trans();
|
|||
|
return char_trans[c];
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
str_noaccent_tolower(unsigned char *s)
|
|||
|
{
|
|||
|
int i;
|
|||
|
if (s == NULL) return;
|
|||
|
if (char_trans_init == 0) init_char_trans();
|
|||
|
i = 0; while(s[i]) {
|
|||
|
s[i] = char_trans[s[i]]; i++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
unsigned char *
|
|||
|
str_noaccent_casestr(const unsigned char *meule, const unsigned char *aiguille)
|
|||
|
{
|
|||
|
unsigned char *res;
|
|||
|
char *m = strdup((char*)meule);
|
|||
|
char *a = strdup((char*)aiguille);
|
|||
|
|
|||
|
str_noaccent_tolower((unsigned char*)m);
|
|||
|
str_noaccent_tolower((unsigned char*)a);
|
|||
|
res = (unsigned char*)strstr(m, a);
|
|||
|
free(a); free(m);
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
/* un printf pas tr<74>s fin, mais avec allocation dynamique..
|
|||
|
c'est pratique ces ptites choses */
|
|||
|
char *
|
|||
|
str_printf(const char *fmt, ...)
|
|||
|
{
|
|||
|
va_list ap;
|
|||
|
char *s;
|
|||
|
int s_sz;
|
|||
|
|
|||
|
s_sz = 10; /* a reaugmenter des que la fonction est validee : */
|
|||
|
s = malloc(s_sz); assert(s);
|
|||
|
while (1) {
|
|||
|
int ret;
|
|||
|
va_start(ap, fmt);
|
|||
|
ret = vsnprintf(s, s_sz, fmt, ap);
|
|||
|
va_end(ap);
|
|||
|
if (ret == -1 || ret >= s_sz-1) {
|
|||
|
s_sz *= 2;
|
|||
|
assert(s_sz < 100000);
|
|||
|
s = realloc(s, s_sz); assert(s);
|
|||
|
} else
|
|||
|
break;
|
|||
|
}
|
|||
|
s = realloc(s, strlen(s)+1); assert(s);
|
|||
|
return s;
|
|||
|
}
|
|||
|
|
|||
|
/* read a line in a file and return the result in a dynamically
|
|||
|
allocated buffer */
|
|||
|
char *
|
|||
|
str_fget_line(FILE *f)
|
|||
|
{
|
|||
|
int i,c;
|
|||
|
char *s;
|
|||
|
int s_sz;
|
|||
|
|
|||
|
s_sz = 100; s = malloc(s_sz); assert(s);
|
|||
|
i = 0;
|
|||
|
while ((c = fgetc(f)) > 0) {
|
|||
|
if (c >= ' ' || c == '\t') {
|
|||
|
s[i++] = c;
|
|||
|
if (i == s_sz) {
|
|||
|
s_sz *= 2; assert(s_sz < 100000);
|
|||
|
s = realloc(s, s_sz); assert(s);
|
|||
|
}
|
|||
|
}
|
|||
|
if (c == '\n') break;
|
|||
|
}
|
|||
|
s[i] = 0; assert(i < s_sz);
|
|||
|
s = realloc(s, strlen(s)+1); assert(s);
|
|||
|
return s;
|
|||
|
}
|
|||
|
|
|||
|
/* remove spaces at the beginning and at the end */
|
|||
|
void
|
|||
|
str_trim(unsigned char *s) {
|
|||
|
int i,j;
|
|||
|
|
|||
|
if (s == NULL) return;
|
|||
|
j = strlen((char*)s)-1;
|
|||
|
while (j>=0 && s[j] <= ' ') s[j--] = 0;
|
|||
|
|
|||
|
i = 0;
|
|||
|
while (s[i] && s[i] <= ' ') i++;
|
|||
|
if (i<=j) {
|
|||
|
memmove(s, s+i, j+2-i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* insertion into a string list */
|
|||
|
strlist *strlist_ins(strlist *head, const char *s) {
|
|||
|
strlist *p; ALLOC_OBJ(p);
|
|||
|
p->s = strdup(s); p->next = head; return p;
|
|||
|
}
|