1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2 
3 #include "r_types.h"
4 #include "r_util.h"
5 #include "r_cons.h"
6 #include "r_bin.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdarg.h>
12 
13 // TODO: simplify this horrible loop
r_str_trim_path(char * s)14 R_API void r_str_trim_path(char *s) {
15 	char *src, *dst, *p;
16 	int i = 0;
17 	if (!s || !*s) {
18 		return;
19 	}
20 	dst = src = s + 1;
21 	while (*src) {
22 		if (*(src - 1) == '/' && *src == '.' && *(src + 1) == '.') {
23 			if (*(src + 2) == '/' || *(src + 2) == '\0') {
24 				p = dst - 1;
25 				while (s != p) {
26 					if (*p == '/') {
27 						if (i) {
28 							dst = p + 1;
29 							i = 0;
30 							break;
31 						}
32 						i = 1;
33 					}
34 					p--;
35 				}
36 				if (s == p && *p == '/') {
37 					dst = p + 1;
38 				}
39 				src = src + 2;
40 			} else {
41 				*dst = *src;
42 				dst++;
43 			}
44 		} else if (*src == '/' && *(src + 1) == '.' && (*(src + 2) == '/' || *(src + 2) == '\0')) {
45 			src++;
46 		} else if (*src != '/' || *(src - 1) != '/') {
47 			*dst = *src;
48 			dst++;
49 		}
50 		src++;
51 	}
52 	if (dst > s + 1 && *(dst - 1) == '/') {
53 		*(dst - 1) = 0;
54 	} else {
55 		*dst = 0;
56 	}
57 }
58 
r_str_trim_lines(char * str)59 R_API char* r_str_trim_lines(char *str) {
60 	RList *list = r_str_split_list (str, "\n", 0);
61 	char *s;
62 	RListIter *iter;
63 	RStrBuf *sb = r_strbuf_new ("");
64 	r_list_foreach (list, iter, s) {
65 		//r_str_ansi_trim (s, -1, 99999);
66 		r_str_ansi_filter (s, NULL, NULL, -1);
67 		r_str_trim (s);
68 		if (*s) {
69 			r_strbuf_appendf (sb, "%s\n", s);
70 		}
71 	}
72 	r_list_free (list);
73 	free (str);
74 	return r_strbuf_drain (sb);
75 }
76 
r_str_trim_dup(const char * str)77 R_API char *r_str_trim_dup(const char *str) {
78 	char *a = strdup (str);
79 	r_str_trim (a);
80 	return a;
81 }
82 
83 // Returns a pointer to the first non-whitespace character of str.
84 // TODO: Find a better name: to r_str_trim_head_ro(), r_str_skip_head or so
r_str_trim_head_ro(const char * str)85 R_API const char *r_str_trim_head_ro(const char *str) {
86 	r_return_val_if_fail (str, NULL);
87 	for (; *str && IS_WHITECHAR (*str); str++) {
88 		;
89 	}
90 	return str;
91 }
92 
93 // TODO: find better name
r_str_trim_head_wp(const char * str)94 R_API const char *r_str_trim_head_wp(const char *str) {
95 	r_return_val_if_fail (str, NULL);
96 	for (; *str && !IS_WHITESPACE (*str); str++) {
97 		;
98 	}
99 	return str;
100 }
101 
102 /* remove spaces from the head of the string.
103  * the string is changed in place */
r_str_trim_head(char * str)104 R_API void r_str_trim_head(char *str) {
105 	char *p = (char *)r_str_trim_head_ro (str);
106 	if (p) {
107 		memmove (str, p, strlen (p) + 1);
108 	}
109 }
110 
111 // Remove whitespace chars from the tail of the string, replacing them with
112 // null bytes. The string is changed in-place.
r_str_trim_tail(char * str)113 R_API void r_str_trim_tail(char *str) {
114 	r_return_if_fail (str);
115 	size_t length = strlen (str);
116 	while (length-- > 0) {
117 		if (IS_WHITECHAR (str[length])) {
118 			str[length] = '\0';
119 		} else {
120 			break;
121 		}
122 	}
123 }
124 
125 // Removes spaces from the head of the string, and zeros out whitespaces from
126 // the tail of the string. The string is changed in place.
r_str_trim(char * str)127 R_API void r_str_trim(char *str) {
128 	r_str_trim_head (str);
129 	r_str_trim_tail (str);
130 }
131 
132 // no copy, like trim_head+tail but with trim_head_ro, beware heap issues
133 // TODO: rename to r_str_trim_weak() ?
r_str_trim_nc(char * str)134 R_API char *r_str_trim_nc(char *str) {
135 	char *s = (char *)r_str_trim_head_ro (str);
136 	r_str_trim_tail (s);
137 	return s;
138 }
139 
140 /* supposed to chop a string with ansi controls to max length of n. */
r_str_ansi_trim(char * str,int str_len,int n)141 R_API int r_str_ansi_trim(char *str, int str_len, int n) {
142 	r_return_val_if_fail (str, 0);
143 	char ch, ch2;
144 	int back = 0, i = 0, len = 0;
145 	/* simple case - no need to cut */
146 	if (str_len < 0) {
147 		str_len = strlen (str);
148 	}
149 	if (n >= str_len) {
150 		str[str_len] = 0;
151 		return str_len;
152 	}
153 	while ((i < str_len) && str[i] && len < n && n > 0) {
154 		ch = str[i];
155 		ch2 = str[i + 1];
156 		if (ch == 0x1b) {
157 			if (ch2 == '\\') {
158 				i++;
159 			} else if (ch2 == ']') {
160 				if (!strncmp (str + 2 + 5, "rgb:", 4)) {
161 					i += 18;
162 				}
163 			} else if (ch2 == '[') {
164 				for (++i; (i < str_len) && str[i] && str[i] != 'J' && str[i] != 'm' && str[i] != 'H';
165 					i++) {
166 					;
167 				}
168 			}
169 		} else if ((str[i] & 0xc0) != 0x80) {
170 			len++;
171 		}
172 		i++;
173 		back = i; /* index in the original array */
174 	}
175 	str[back] = 0;
176 	return back;
177 }
178