mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-30 08:30:53 +00:00
290 lines
5.5 KiB
C
290 lines
5.5 KiB
C
/* radare - LGPL - Copyright 2007-2022 - pancake */
|
|
|
|
#include <r_util.h>
|
|
|
|
// TODO: simplify this horrible loop
|
|
R_API void r_str_trim_path(char *s) {
|
|
R_RETURN_IF_FAIL (s);
|
|
char *src, *dst, *p;
|
|
int i = 0;
|
|
if (R_STR_ISEMPTY (s)) {
|
|
return;
|
|
}
|
|
dst = src = s + 1;
|
|
while (*src) {
|
|
if (*(src - 1) == '/' && *src == '.' && *(src + 1) == '.') {
|
|
if (*(src + 2) == '/' || *(src + 2) == '\0') {
|
|
p = dst - 1;
|
|
while (s != p) {
|
|
if (*p == '/') {
|
|
if (i) {
|
|
dst = p + 1;
|
|
i = 0;
|
|
break;
|
|
}
|
|
i = 1;
|
|
}
|
|
p--;
|
|
}
|
|
if (s == p && *p == '/') {
|
|
dst = p + 1;
|
|
}
|
|
src = src + 2;
|
|
} else {
|
|
*dst = *src;
|
|
dst++;
|
|
}
|
|
} else if (*src == '/' && *(src + 1) == '.' && (*(src + 2) == '/' || *(src + 2) == '\0')) {
|
|
src++;
|
|
} else if (*src != '/' || *(src - 1) != '/') {
|
|
*dst = *src;
|
|
dst++;
|
|
}
|
|
src++;
|
|
}
|
|
if (dst > s + 1 && *(dst - 1) == '/') {
|
|
*(dst - 1) = 0;
|
|
} else {
|
|
*dst = 0;
|
|
}
|
|
}
|
|
|
|
R_API char* r_str_trim_lines(char *str) {
|
|
RList *list = r_str_split_list (str, "\n", 0);
|
|
char *s;
|
|
RListIter *iter;
|
|
RStrBuf *sb = r_strbuf_new ("");
|
|
r_list_foreach (list, iter, s) {
|
|
//r_str_ansi_trim (s, -1, 99999);
|
|
r_str_ansi_filter (s, NULL, NULL, -1);
|
|
r_str_trim (s);
|
|
if (*s) {
|
|
r_strbuf_appendf (sb, "%s\n", s);
|
|
}
|
|
}
|
|
r_list_free (list);
|
|
free (str);
|
|
return r_strbuf_drain (sb);
|
|
}
|
|
|
|
R_API void r_str_trim_emptylines(char *str) {
|
|
r_str_trim_tail (str);
|
|
char *r = str;
|
|
while (*r) {
|
|
if (*r == '\n') {
|
|
r++;
|
|
// skip empty lines
|
|
char *nl = r;
|
|
while (*r && *r != '\n') {
|
|
if (!isspace (*r)) {
|
|
break;
|
|
}
|
|
r++;
|
|
}
|
|
if (*r == '\n') {
|
|
r_str_cpy (nl, r + 1);
|
|
}
|
|
}
|
|
if (!*r) {
|
|
break;
|
|
}
|
|
r++;
|
|
}
|
|
}
|
|
|
|
R_API char *r_str_trim_dup(const char *str) {
|
|
char *a = strdup (str);
|
|
r_str_trim (a);
|
|
return a;
|
|
}
|
|
|
|
R_API char *r_str_trim_ndup(const char *str, size_t n) {
|
|
char *a = r_str_ndup (str, n);
|
|
r_str_trim (a);
|
|
return a;
|
|
}
|
|
|
|
// Returns a pointer to the first non-whitespace character of str.
|
|
// TODO: Find a better name: to r_str_trim_head_ro(), r_str_skip_head or so
|
|
R_API const char *r_str_trim_head_ro(const char *str) {
|
|
R_RETURN_VAL_IF_FAIL (str, NULL);
|
|
for (; *str && IS_WHITECHAR (*str); str++) {
|
|
;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
// TODO: find better name
|
|
R_API const char *r_str_trim_head_wp(const char *str) {
|
|
R_RETURN_VAL_IF_FAIL (str, NULL);
|
|
for (; *str && !IS_WHITESPACE (*str); str++) {
|
|
;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
// remove in-place spaces from the head of the string.
|
|
R_API void r_str_trim_head(char *str) {
|
|
R_RETURN_IF_FAIL (str);
|
|
char *p = (char *)r_str_trim_head_ro (str);
|
|
if (p && p != str) {
|
|
memmove (str, p, strlen (p) + 1);
|
|
}
|
|
}
|
|
|
|
static bool is_escapable(char ch) {
|
|
switch (ch) {
|
|
case '@':
|
|
case '"':
|
|
case '\'':
|
|
case '|':
|
|
case ';':
|
|
case '`':
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
R_API void r_str_trim_args(char *str) {
|
|
R_RETURN_IF_FAIL (str);
|
|
char q = 0;
|
|
bool e = false;
|
|
char *s = str;
|
|
char *d = str;
|
|
while (*s) {
|
|
switch (*s) {
|
|
case '\'':
|
|
case '"':
|
|
if (e) {
|
|
e = false;
|
|
} else {
|
|
if (q) {
|
|
// needs to be escaped
|
|
if (q == *s) {
|
|
q = 0;
|
|
e = false;
|
|
s++;
|
|
continue;
|
|
}
|
|
} else {
|
|
q = *s;
|
|
s++;
|
|
e = false;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
case '\\':
|
|
if (e) {
|
|
e = false;
|
|
} else {
|
|
if (is_escapable (s[1])) {
|
|
e = true;
|
|
s++;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
e = false;
|
|
break;
|
|
}
|
|
*d = *s;
|
|
s++;
|
|
d++;
|
|
}
|
|
*d = 0;
|
|
}
|
|
|
|
// Remove whitespace chars from the tail of the string, replacing them with
|
|
// null bytes. The string is changed in-place.
|
|
R_API void r_str_trim_tail(char *str) {
|
|
R_RETURN_IF_FAIL (str);
|
|
size_t length = strlen (str);
|
|
while (length-- > 0) {
|
|
if (IS_WHITECHAR (str[length])) {
|
|
str[length] = '\0';
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Removes spaces from the head of the string, and zeros out whitespaces from
|
|
// the tail of the string. The string is changed in place.
|
|
R_API void r_str_trim(char *str) {
|
|
R_RETURN_IF_FAIL (str);
|
|
r_str_ntrim (str, strlen (str));
|
|
}
|
|
|
|
R_API int r_str_ntrim(char *str, int length) {
|
|
R_RETURN_VAL_IF_FAIL (str && length >= 0, -1);
|
|
// r_str_trim_head (str);
|
|
char *p = str;
|
|
for (; *p && IS_WHITECHAR (*p) && length > 0; p++) {
|
|
length--;
|
|
}
|
|
if (p != str && length > 0) {
|
|
memmove (str, p, length + 1);
|
|
}
|
|
// r_str_trim_tail (str);
|
|
while (length > 0) {
|
|
const int newlength = length - 1;
|
|
if (IS_WHITECHAR (str[newlength])) {
|
|
str[newlength] = '\0';
|
|
} else {
|
|
break;
|
|
}
|
|
length = newlength;
|
|
}
|
|
str[length] = 0;
|
|
return length;
|
|
}
|
|
|
|
// no copy, like trim_head+tail but with trim_head_ro, beware heap issues
|
|
// TODO: rename to r_str_trim_weak() ?
|
|
R_API char *r_str_trim_nc(char *str) {
|
|
char *s = (char *)r_str_trim_head_ro (str);
|
|
r_str_trim_tail (s);
|
|
return s;
|
|
}
|
|
|
|
/* supposed to chop a string with ansi controls to max length of n. */
|
|
R_API int r_str_ansi_trim(char *str, int str_len, int n) {
|
|
R_RETURN_VAL_IF_FAIL (str, 0);
|
|
char ch, ch2;
|
|
int back = 0, i = 0, len = 0;
|
|
/* simple case - no need to cut */
|
|
if (str_len < 0) {
|
|
str_len = strlen (str);
|
|
}
|
|
if (n >= str_len) {
|
|
str[str_len] = 0;
|
|
return str_len;
|
|
}
|
|
while ((i < str_len) && str[i] && len < n && n > 0) {
|
|
ch = str[i];
|
|
ch2 = str[i + 1];
|
|
if (ch == 0x1b) {
|
|
if (ch2 == '\\') {
|
|
i++;
|
|
} else if (ch2 == ']') {
|
|
if (!strncmp (str + 2 + 5, "rgb:", 4)) {
|
|
i += 18;
|
|
}
|
|
} else if (ch2 == '[') {
|
|
for (i++; (i < str_len) && str[i] && str[i] != 'J' && str[i] != 'm' && str[i] != 'H';
|
|
i++) {
|
|
;
|
|
}
|
|
}
|
|
} else if ((str[i] & 0xc0) != 0x80) {
|
|
len++;
|
|
}
|
|
i++;
|
|
back = i; /* index in the original array */
|
|
}
|
|
str[back] = 0;
|
|
return back;
|
|
}
|