/* 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; }