/* radare - LGPL - Copyright 2007-2010 pancake */ #include "r_types.h" #include "r_util.h" #include #include #include /* stable code */ static const char *nullstr = ""; static const char *nullstr_c = "(null)"; R_API void r_str_subchr (char *s, int a, int b) { while (*s) { if(*s==a) { if (b) *s = b; else strcpy (s, s+1); } s++; } } // TODO: do not use toupper.. must support modes to also append lowercase chars like in r1 R_API int r_str_bits (char *strout, const ut8 *buf, int len, const char *bitz) { int i, j, *p = (int*)buf; for (i=j=0; i= 'A' && c <= 'F') *val = (ut8)(*val) * 16 + ( c - 'A' + 10); else if (c >= 'a' && c <= 'f') *val = (ut8)(*val) * 16 + ( c - 'a' + 10); else return 1; return 0; } R_API int r_str_rwx(const char *str) { int ret = atoi (str); if (!ret) { ret |= strchr (str, 'r')?4:0; ret |= strchr (str, 'w')?2:0; ret |= strchr (str, 'x')?1:0; } return ret; } R_API const char *r_str_rwx_i(int rwx) { static const char *rwxstr[16] = { [0] = "---", [1] = "--x", [2] = "-w-", [3] = "-wx", [4] = "r--", [5] = "r-x", [6] = "rw-", [7] = "rwx", /* ... */ }; return rwxstr[rwx&7]; // 15 for srwx } R_API const char *r_str_bool(int b) { if (b) return "true"; return "false"; } R_API void r_str_case(char *str, int up) { if (up) { while(*str) *str = tolower (*str); } else { while(*str) *str = toupper (*str); } } #if __WINDOWS__ #define __ENV_HOME "USERPROFILE" #define __ENV_DIR "\\" #else #define __ENV_HOME "HOME" #define __ENV_DIR "/" #endif R_API char *r_str_home(const char *str) { char *dst; const char *home = r_sys_getenv (__ENV_HOME); if (home == NULL) return NULL; dst = (char *)malloc (strlen (home) + strlen (str)+2); strcpy (dst, home); if (str && *str) { strcat (dst, __ENV_DIR); strcat (dst, str); } return dst; } /* XXX Fix new hash algo*/ R_API ut64 r_str_hash64(const char *str) { ut64 ret = 0; for (;*str; str++) ret ^= (ret<<7 | *str); return ret; } R_API int r_str_hash(const char *str) { int ret = 0; for (;*str; str++) ret ^= (ret<<7 | *str); return ret; } R_API int r_str_delta(char *p, char a, char b) { char *_a = strchr (p, a); char *_b = strchr (p, b); return (!_a||!_b)?0:(_a-_b); } R_API int r_str_word_set0(char *str) { int i; char *p; if (str[0]=='\0') return 0; /* TODO: sync with r1 code */ for (i=1,p=str; p[0]; p++) if (*p==' ') { i++; *p='\0'; } // s/ /\0/g return i; } R_API char *r_str_word_get0(char *str, int idx) { int i; char *ptr = str; if (ptr == NULL) return (char *)nullstr; for (i=0;*ptr && i != idx;i++) ptr = ptr + strlen(ptr) + 1; return ptr; } R_API int r_str_char_count(const char *string, char ch) { int i, count = 0; for (i=0; string[i]; i++) if (string[i]==ch) count++; return count; } R_API int r_str_word_count(const char *string) { const char *text, *tmp; int word; for (text = tmp = string; *text && isseparator (*text); text++); for (word = 0; *text; word++) { for (;*text && !isseparator (*text); text++); for (tmp = text; *text && isseparator (*text); text++); } return word; } R_API char *r_str_ichr(char *str, char chr) { while (*str==chr) str = str+1; return str; } R_API char *r_str_lchr(char *str, char chr) { int len = strlen(str)+1; for (;len>=0;len--) if (str[len]==chr) return str+len; return NULL; } R_API int r_str_nchr(const char *str, char chr) { int n; for (n = 0; *str; str++) if (*str==chr) n++; return n; } R_API int r_str_nstr(char *from, char *to, int size) { int i; for (i=0; i0) for (ptr = str+len-1;ptr!=str;ptr = ptr - 1) { if (iswhitechar (ptr[0])) *ptr = '\0'; else break; } return str; } R_API char *r_str_trim_head(char *str) { if (str) while (*str && iswhitechar(*str)) str++; return str; } R_API char *r_str_trim_tail(char *str) { char *ptr = str; if (str == NULL) return NULL; ptr += strlen(str)-1; while ((ptr > str) && iswhitechar(*ptr)) { *ptr = '\0'; ptr--; } return str; } R_API char *r_str_trim_head_tail(char *str) { return r_str_trim_tail(r_str_trim_head(str)); } R_API char *r_str_trim(char *str) { int i; char *ptr; if (str == NULL) return NULL; for (ptr=str, i=0;str[i];i++) if (!iswhitechar (str[i])) *ptr++ = str[i]; *ptr='\0'; return str; } /* memccmp("foo.bar", "foo.cow, '.') == 0 */ R_API int r_str_ccmp(const char *dst, const char *src, int ch) { int i; for (i=0;src[i] && src[i] != ch; i++) if (dst[i] != src[i]) return 1; return 0; } R_API int r_str_cmp(const char *a, const char *b, int len) { if (a==b) return R_TRUE; for (;len--;) { if (*a=='\0'||*b=='\0'||*a!=*b) return R_TRUE; a++; b++; } return R_FALSE; } R_API int r_str_ccpy(char *dst, char *src, int ch) { int i; for (i=0;src[i] && src[i] != ch; i++) dst[i] = src[i]; dst[i] = '\0'; return i; } R_API char *r_str_word_get_first(const char *text) { char *ret; int len = 0; for (;*text && isseparator (*text); text++); /* strdup */ len = strlen (text); ret = (char *)malloc (len+1); if (ret == NULL) { eprintf ("Cannot allocate %d bytes.\n", len+1); exit (1); } strncpy (ret, text, len); ret[len]='\0'; return ret; } R_API const char *r_str_get(const char *str) { if (str == NULL) return nullstr_c; return str; } R_API char *r_str_dup(char *ptr, const char *string) { if (ptr) free (ptr); ptr = strdup (string); return ptr; } // TODO: rename to r_str_dupfmt R_API char *r_str_dup_printf(const char *fmt, ...) { char *ret; va_list ap; va_start(ap, fmt); if ((ret = malloc (1024)) == NULL) return NULL; vsnprintf (ret, 1024, fmt, ap); va_end(ap); return ret; } R_API void r_str_writef(int fd, const char *fmt, ...) { char *buf; va_list ap; va_start (ap, fmt); if ((buf = malloc (4096)) != NULL) { vsnprintf (buf, 4096, fmt, ap); r_str_write (fd, buf); free (buf); } va_end (ap); } /* * return: the pointer ptr resized to string size. */ R_API char *r_str_concat(char *ptr, const char *string) { if (ptr == NULL) return strdup (string); ptr = realloc (ptr, strlen (string)+strlen (ptr)+1); if (ptr == NULL) return NULL; strcat (ptr, string); return ptr; } R_API char *r_str_concatf(char *ptr, const char *fmt, ...) { char string[1024]; va_list ap; va_start (ap, fmt); vsnprintf (string, 1023, fmt, ap); ptr = r_str_concat (ptr, string); va_end (ap); return ptr; } R_API char *r_str_concatch(char *x, char y) { char b[2] = {y, 0}; return r_str_concat (x,b); } R_API void *r_str_free(void *ptr) { free (ptr); return NULL; } R_API int r_str_inject(char *begin, char *end, char *str, int maxlen) { int len = strlen (end)+1; char *tmp; if (maxlen > 0 && ((strlen (begin)-(end-begin)+strlen (str)) > maxlen)) return 0; tmp = malloc (len); memcpy (tmp, end, len); strcpy (begin, str); strcat (begin, tmp); free (tmp); return 1; } /* unstable code (taken from GNU) */ /*------------------------------------------------*/ // FROM bash::stringlib #define RESIZE_MALLOCED_BUFFER(str,cind,room,csize,sincr) \ if ((cind) + (room) >= csize) { \ while ((cind) + (room) >= csize) \ csize += (sincr); \ str = realloc (str, csize); \ } /* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero, replace all occurrences, otherwise replace only the first. This returns a new string; the caller should free it. */ static int strsub_memcmp (char *string, char *pat, int len) { int res; for (res = 0; len-->0; pat++) { if (*pat!='?') res += *string - *pat; string++; } return res; } // TODO: rename r_str_replace R_API char *r_str_sub(char *string, char *pat, char *rep, int global) { int patlen, templen, tempsize, repl, i; char *temp, *r; patlen = strlen (pat); for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; ) { if (repl && !strsub_memcmp (string + i, pat, patlen)) { RESIZE_MALLOCED_BUFFER (temp, templen, patlen, tempsize, 4096); //UGLY HACK (patlen * 2)); if (temp == NULL) break; for (r = rep; *r; ) temp[templen++] = *r++; i += patlen; repl = (global != 0); } else { RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 4096); // UGLY HACK 16); temp[templen++] = string[i++]; } } if (temp) temp[templen] = '\0'; return (temp); } R_API char *r_str_clean(char *str) { int len; char *ptr; if (str != NULL) { while (*str && iswhitechar (*str)) str++; if ((len = strlen(str))>0) for (ptr = str+len-1; ptr!=str; ptr = ptr - 1) { if (iswhitechar (*ptr)) *ptr = '\0'; else break; } } return str; } R_API int r_str_escape(char *buf) { unsigned char ch = 0, ch2 = 0; int err = 0; int i; for (i=0; buf[i]; i++) { // only parse scaped characters // if (buf[i]!='\\') continue; if (buf[i+1]=='e') { buf[i] = 0x1b; strcpy (buf+i+1, buf+i+2); } else if (buf[i+1]=='r') { buf[i] = 0x0d; strcpy (buf+i+1, buf+i+2); } else if (buf[i+1]=='n') { buf[i] = 0x0a; strcpy (buf+i+1, buf+i+2); } else if (buf[i+1]=='x') { err = ch2 = ch = 0; if (!buf[i+2] || !buf[i+3]) { eprintf ("Unexpected end of string.\n"); return 0; } err |= hex2int (&ch, buf[i+2]); err |= hex2int (&ch2, buf[i+3]); if (err) { eprintf ("Incorrect hexadecimal characters for conversion.\n"); return 0; } buf[i] = (ch<<4)+ch2; strcpy (buf+i+1, buf+i+4); } else { eprintf ("'\\x' expected.\n"); return 0; } } //char *p = buf; while(*p) { eprintf("%d %c\n", *p, *p); p++; } //eprintf("OLEN=%d (%s)\n", strlen(buf), buf); return strlen(buf); } R_API char *r_str_unscape(char *buf) { char *ptr, *ret; int len = strlen (buf); ptr = ret = malloc (len*2); for (;*buf;buf++,ptr++) { if (*buf=='\n') { *ptr = '\\'; ptr++; *ptr = 'n'; } else if (*buf=='\t') { *ptr = '\\'; ptr++; *ptr = 't'; } else if (IS_PRINTABLE(*buf)) { *ptr = *buf; } else break; } *ptr = 0; return ret; } /* ansi helpers */ R_API int r_str_ansi_len(const char *str) { int i=0, len = 0; while (str[i]) { if (str[i]==0x1b && str[i+1]=='[') for (++i;str[i]&&str[i]!='J'&&str[i]!='m'&&str[i]!='H';i++); else len++; i++; } return len; } R_API const char *r_str_ansi_chrn(const char *str, int n) { int len, i; for (i=len=0; str[i] && (n!=len); i++) { if (str[i]==0x1b && str[i+1]=='[') for (++i;str[i]&&str[i]!='J'&&str[i]!='m'&&str[i]!='H';i++); else len++; } return str+i; } R_API int r_str_ansi_filter(char *str, int len) { char *tmp; int i, j; if (!(tmp = malloc (len))) return -1; memcpy (tmp, str, len); for (i=j=0; i