/* Chrysalide - Outil d'analyse de fichiers binaires
* extstr.c - extension des fonctions relatives aux chaînes
*
* Copyright (C) 2009-2013 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* 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 */
if (str1 == NULL)
result = strdup(str2);
else
{
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. *
* n = taille de la seconde chaîne. *
* *
* 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 *strnadd(char *str1, const char *str2, size_t n)
{
char *result; /* Chaîne à renvoyer */
if (str1 == NULL)
result = strndup(str2, n);
else
{
result = (char *)realloc(str1, (strlen(str1) + n + 1) * sizeof(char));
strncat(result, str2, n);
}
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 */
size_t index; /* Conversion en indice */
char *found; /* Position d'une trouvaille */
inlen = strlen(haystack) + 1;
len1 = strlen(needle1);
len2 = strlen(needle2);
index = 0;
for (found = strstr(haystack + index, needle1);
found != NULL;
found = strstr(haystack + index, needle1))
{
index = found - haystack;
if (len1 != len2)
{
if (len2 > len1)
inlen += len2 - len1;
else
inlen -= len1 - len2;
haystack = (char *)realloc(haystack, inlen * sizeof(char *));
found = haystack + index;
if (len2 > len1)
memmove(found + len2, found + len1, inlen - len1 - (found - haystack));
else
memmove(found + len1, found + len2, inlen - len1 - (found - haystack));
}
memcpy(found, needle2, len2);
}
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;
}