/* OpenIDA - Outil d'analyse de fichiers binaires
* extstr.c - extension des fonctions relatives aux chaînes
*
* Copyright (C) 2009 Cyrille Bagard
*
* This file is part of OpenIDA.
*
* OpenIDA is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* OpenIDA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see .
*/
#include "extstr.h"
#include
#include
#include
/******************************************************************************
* *
* Paramètres : str1 = chaîne de caractères à compléter. *
* str2 = chaîne de caractères à ajouter. *
* *
* Description : Complète une chaîne de caractères avec une autre. *
* *
* Retour : Chaîne de caractères complétée, à libérer de la mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
char *stradd(char *str1, const char *str2)
{
char *result; /* Chaîne à renvoyer */
result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char));
strcat(result, str2);
return result;
}
/******************************************************************************
* *
* Paramètres : str1 = chaîne de caractères à compléter. *
* str2 = chaîne de caractères à ajouter. *
* *
* Description : Fait précéder une chaîne de caractères par une autre. *
* *
* Retour : Chaîne de caractères complétée, à libérer de la mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
char *strprep(char *str1, const char *str2)
{
char *result; /* Chaîne à renvoyer */
size_t len2; /* Taille de la seconde chaîne */
result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char));
len2 = strlen(str2);
memmove(&result[len2], result, strlen(result) + 1);
memcpy(result, str2, len2);
return result;
}
/******************************************************************************
* *
* Paramètres : str1 = chaîne de caractères à analyser. *
* str2 = chaîne de caractères à retrouver. *
* *
* Description : Compare deux chaînes de caractères en partant de la fin. *
* *
* Retour : -1, 0, ou 1 selon la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
int strrcmp(const char *str1, const char *str2)
{
int result; /* Bilan à renvoyer */
size_t len1; /* Longueur de la chaîne donnée*/
size_t len2; /* Longueur de la chaîne visée */
len1 = strlen(str1);
len2 = strlen(str2);
if (len1 <= len2)
result = strcmp(str1, str2);
else result = strcmp(&str1[len1 - len2], str2);
return result;
}
/******************************************************************************
* *
* Paramètres : haystack = botte de foin à fouiller. *
* needle1 = aiguille à trouver et remplacer. *
* needle2 = aiguille de remplacement. *
* *
* Description : Remplace des éléments d'une chaîne par d'autres. *
* *
* Retour : Adresse de la chaîne de caractères modifiée. *
* *
* Remarques : - *
* *
******************************************************************************/
char *strrpl(char *haystack, const char *needle1, const char *needle2)
{
size_t inlen; /* Taille en entrée */
size_t len1; /* Taille de l'aiguille n°1 */
size_t len2; /* Taille de l'aiguille n°2 */
regex_t preg; /* Expression régulière */
size_t curpos; /* Point de recherche */
regmatch_t pmatch; /* Résultats remontés */
inlen = strlen(haystack) + 1;
len1 = strlen(needle1);
len2 = strlen(needle2);
/* On considère que la compilation est toujours bonne... */
regcomp(&preg, needle1, REG_EXTENDED | REG_ICASE);
for (curpos = 0; regexec(&preg, &haystack[curpos], 1, &pmatch, 0) != REG_NOMATCH; )
{
if (len1 != len2)
{
if (len2 > len1)
inlen += len2 - len1;
else
inlen -= len1 - len2;
haystack = (char *)realloc(haystack, inlen * sizeof(char *));
if (len2 > len1)
memmove(&haystack[curpos + pmatch.rm_eo + len2 - len1], &haystack[curpos + pmatch.rm_eo],
inlen - (len2 - len1) - curpos - pmatch.rm_eo);
else
memmove(&haystack[curpos + pmatch.rm_eo + len1 - len2], &haystack[curpos + pmatch.rm_eo],
inlen - (len1 - len2) - curpos - pmatch.rm_eo);
}
memcpy(&haystack[curpos + pmatch.rm_so], needle2, len2);
curpos += pmatch.rm_eo + len2;
}
regfree(&preg);
return haystack;
}
/******************************************************************************
* *
* Paramètres : str = chaîne de caractères à traiter. *
* delim = séparateur entre les mots. *
* count = nombre de mots trouvés. [OUT] *
* *
* Description : Extrait une liste de mots d'une chaîne. *
* *
* Retour : Tableau construit à libérer de la mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
char **strtoka(const char *str, const char *delim, size_t *count)
{
char **result; /* Tableau à retourner */
char *tmp; /* Sauvegarde modifiable */
char *word; /* Nouveau mot détecté */
result = NULL;
*count = 0;
tmp = strdup(str);
for (word = strtok(tmp, delim); word != NULL; word = strtok(NULL, delim))
{
result = (char **)realloc(result, ++(*count) * sizeof(char *));
result[*count - 1] = strdup(word);
}
free(tmp);
return result;
}
/******************************************************************************
* *
* Paramètres : input = chaîne de caractères à traiter. *
* *
* Description : S'assure qu'une chaîne de caractères tient sur une ligne. *
* *
* Retour : Adresse de la chaîne de caractères modifiée. *
* *
* Remarques : - *
* *
******************************************************************************/
char *escape_crlf(char *input)
{
size_t inlen;
regex_t preg;
size_t curpos;
regmatch_t pmatch[2];
inlen = strlen(input);
/* On considère que la compilation est toujours bonne... */
regcomp(&preg, "(\t|\n|\r)", REG_EXTENDED | REG_ICASE);
for (curpos = 0; regexec(&preg, &input[curpos], 2, pmatch, 0) != REG_NOMATCH; )
{
inlen += 1 + 1;
input = (char *)realloc(input, inlen * sizeof(char *));
memmove(&input[curpos + pmatch[1].rm_eo + 1], &input[curpos + pmatch[1].rm_eo], inlen - 1 - curpos - pmatch[1].rm_eo);
switch (input[curpos + pmatch[1].rm_so])
{
case '\t':
memcpy(&input[curpos + pmatch[1].rm_so], "\\t", 2);
break;
case '\n':
memcpy(&input[curpos + pmatch[1].rm_so], "\\n", 2);
break;
case '\r':
memcpy(&input[curpos + pmatch[1].rm_so], "\\r", 2);
break;
}
curpos += pmatch[1].rm_eo + 1;
}
regfree(&preg);
return input;
}
/******************************************************************************
* *
* Paramètres : input = chaîne de caractères à traiter. *
* max = taille maximale de chaîne acceptable. *
* *
* Description : Borne la taille d'une chaîne à une valeur donnée. *
* *
* Retour : Adresse de la chaîne de caractères ou input si pas besoin. *
* *
* Remarques : - *
* *
******************************************************************************/
char *ellipsis(char *input, size_t max)
{
char *result; /* Chaîne à retourner */
if (strlen(input) > max)
{
result = strndup(input, max);
result = stradd(result, "...");
free(input);
}
else result = input;
return result;
}