butt/src/strfuncs.cpp
audioprog 031ca812ad init
2025-08-13 22:05:17 +02:00

227 lines
5.9 KiB
C++

// string manipulation functions for butt
//
// Copyright 2007-2018 by Daniel Noethen.
//
// This program 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 2, or (at your option)
// any later version.
//
// This program 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.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "strfuncs.h"
int strinsrt(char **dest, char *insert, char *pos)
{
char *pre;
char *post;
char *temp;
int pre_len;
int post_len;
int new_len;
new_len = strlen(*dest) + strlen(insert);
pre_len = strlen(*dest) - strlen(pos);
post_len = strlen(pos);
pre = (char *)malloc(pre_len * sizeof(char) + 1);
post = (char *)malloc(post_len * sizeof(char) + 1);
temp = (char *)malloc(new_len * sizeof(char) + 1);
memcpy(pre, *dest, pre_len);
pre[pre_len] = '\0';
memcpy(post, *dest + pre_len, post_len);
post[post_len] = '\0';
sprintf(temp, "%s%s%s", pre, insert, post);
*dest = (char *)realloc(*dest, new_len * sizeof(char) + 1);
strcpy(*dest, temp);
free(pre);
free(post);
free(temp);
return 0;
}
// returns a pointer to the last occurance of string "needle" in string "haystack"
char *strrstr(char *haystack, char *needle)
{
char *last;
char *found = NULL;
do {
last = found;
found = strstr(haystack, needle);
if (found != NULL) {
haystack = found + strlen(needle);
}
} while (found != NULL);
return last;
}
// replaces all strings named by search with strings named by replace in dest
int strrpl(char **dest, char *search, char *replace, int mode)
{
char *loc;
char *temp;
char *orig;
char *result;
int search_len, repl_len, diff;
int size;
int count;
// do nothing if there is not at least one string of "search" in "*dest"
if (strstr(*dest, search) == NULL) {
return -1;
}
search_len = strlen(search);
repl_len = strlen(replace);
diff = repl_len - search_len;
// how many strings do we need to replace?
if (mode == MODE_ALL) {
temp = *dest;
for (count = 0; (temp = strstr(temp, search)); count++) {
temp += search_len;
}
}
else {
count = 1;
}
// length of the new string
size = strlen(*dest) + (diff * count);
temp = strdup(*dest);
orig = temp;
result = (char *)malloc(size * sizeof(char) + 1);
if (!result) {
free(orig);
return -1;
}
memset(result, 0, size);
// build the new string
switch (mode) {
case MODE_ALL:
while ((loc = strstr(temp, search))) {
strncat(result, temp, loc - temp);
strcat(result, replace);
temp = loc + strlen(search);
}
// append remaining characaters (if any)
if (strlen(temp) > 0) {
strcat(result, temp);
}
break;
case MODE_FIRST:
loc = strstr(temp, search);
strncat(result, temp, loc - temp);
strcat(result, replace);
temp = loc + strlen(search);
// append remaining characters
if (strlen(temp) > 0) {
strcat(result, temp);
}
break;
case MODE_LAST:
loc = strrstr(temp, search);
strncat(result, temp, loc - temp);
strcat(result, replace);
temp = loc + strlen(search);
// append remaininc characaters (if any)
if (strlen(temp) > 0) {
strcat(result, temp);
}
break;
default:
return -1;
}
if (strlen(result) > strlen(*dest)) {
*dest = (char *)realloc(*dest, size * sizeof(char) + 1);
if (!*dest) {
free(result);
free(orig);
return -1;
}
}
// save the new string back to orig position in memory
strcpy(*dest, result);
free(orig);
free(result);
return 0;
}
char *strtolower(char *str)
{
if (str != NULL) {
for (int i = 0; i < strlen(str); i++) {
str[i] = tolower(str[i]);
}
}
return str;
}
char *strtoupper(char *str)
{
if (str != NULL) {
for (int i = 0; i < strlen(str); i++) {
str[i] = toupper(str[i]);
}
}
return str;
}
// "Percent encode" reserved characters according to RFC3986 section 2.2 for use in URIs
void strencoderfc3986(char **buf)
{
/* Reserved characters: % :/?#[]@!$&'()*+,;= */
/* Results in: %3d%20%3a%2f%3f%23%5b%5d%40%21%24%26%27%28%29%2a%2b%2c%3b%25 */
strrpl(buf, (char *)"%", (char *)"%25", MODE_ALL); // this must come first
strrpl(buf, (char *)" ", (char *)"%20", MODE_ALL);
strrpl(buf, (char *)":", (char *)"%3a", MODE_ALL);
strrpl(buf, (char *)"/", (char *)"%2f", MODE_ALL);
strrpl(buf, (char *)"?", (char *)"%3f", MODE_ALL);
strrpl(buf, (char *)"#", (char *)"%23", MODE_ALL);
strrpl(buf, (char *)"[", (char *)"%5b", MODE_ALL);
strrpl(buf, (char *)"]", (char *)"%5d", MODE_ALL);
strrpl(buf, (char *)"@", (char *)"%40", MODE_ALL);
strrpl(buf, (char *)"!", (char *)"%21", MODE_ALL);
strrpl(buf, (char *)"$", (char *)"%24", MODE_ALL);
strrpl(buf, (char *)"&", (char *)"%26", MODE_ALL);
strrpl(buf, (char *)"'", (char *)"%27", MODE_ALL);
strrpl(buf, (char *)"(", (char *)"%28", MODE_ALL);
strrpl(buf, (char *)")", (char *)"%29", MODE_ALL);
strrpl(buf, (char *)"*", (char *)"%2a", MODE_ALL);
strrpl(buf, (char *)"+", (char *)"%2b", MODE_ALL);
strrpl(buf, (char *)",", (char *)"%2c", MODE_ALL);
strrpl(buf, (char *)";", (char *)"%3b", MODE_ALL);
strrpl(buf, (char *)"=", (char *)"%3d", MODE_ALL);
}