tim

small extendable personal assistant
git clone git://edryd.org/tim
Log | Files | Refs | LICENSE

str.c (3776B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <assert.h>
      3 #include <ctype.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 
      8 #include "util.h"
      9 
     10 /* compress array of strings to single string */
     11 char *
     12 str_concat(char **s, int c)
     13 {
     14 	if (!s) die("strconcat: given null pointer");
     15 
     16 	int len = 0, i;
     17 	char *ret;
     18 
     19 	for (i = 0; i < c; i++)
     20 		len += strlen(s[i]) + 1;
     21 	ret = ecalloc(len, sizeof(char));
     22 
     23 	strcpy(ret, s[0]);
     24 	strcat(ret, " ");
     25 	for (i = 1; i < c; i++) {
     26 		strcat(ret, s[i]);
     27 		strcat(ret, " ");
     28 	}
     29 
     30 	return ret;
     31 }
     32 
     33 /* split string s into muiltple strings by a_delim */
     34 char **
     35 str_split(const char *s, const char a_delim, int *c)
     36 {
     37 	if (!s) die("strsplit: given null pointer");
     38 
     39 	char **ret = 0;
     40 	size_t count = 0;
     41 	char *last_delim = 0;
     42 	char delim[2] = { a_delim, 0 }; /* converet a_delim into string for strtok */
     43 	char *a_str = ecalloc(strlen(s)+1, sizeof(char));
     44 	strcpy(a_str, s);
     45 
     46 	/* count number of elements that will be extracted. */
     47 	for (char *tmp = a_str; *tmp; tmp++)
     48 		if (a_delim == *tmp) {
     49 			count++;
     50 			last_delim = tmp;
     51 		}
     52 
     53 	/* add space for trailing token. */
     54 	count += last_delim < (a_str + strlen(a_str) - 1);
     55 
     56 	/* add space for terminating null string so caller
     57 	 * knows where the list of returned strings ends. */
     58 	count++;
     59 
     60 	ret = ecalloc(count, sizeof(char*));
     61 
     62 	if (ret) {
     63 		size_t idx  = 0;
     64 		char *token = strtok(a_str, delim);
     65 
     66 		while (token) {
     67 			assert(idx < count);
     68 			*(ret + idx++) = estrdup(token);
     69 			token = strtok(0, delim);
     70 		}
     71 		assert(idx == count - 1);
     72 		*(ret + idx) = 0;
     73 	}
     74 
     75 	*c = count - 1;
     76 	free(a_str);
     77 	return ret;
     78 }
     79 
     80 /* replace rep in orig with with */
     81 char *
     82 str_replace(char *orig, char *rep, char *with)
     83 {
     84 	char *ret, *tmp, *ins; /* ins: the next insert point */
     85 	int len_rep, len_with, len_front, count; /* len_front: distance between rep and end of last rep */
     86 
     87 	/* checks, set lens, and init */
     88 	if (!orig || !rep)
     89 		return NULL;
     90 	len_rep = strlen(rep);
     91 	if (len_rep == 0)
     92 		return NULL; /* empty rep causes infinite loop during count */
     93 	if (!with)
     94 		with = "";
     95 	len_with = strlen(with);
     96 
     97 	/* count the number of replacements needed */
     98 	ins = orig;
     99 	for (count = 0; (tmp = strstr(ins, rep)); ++count)
    100 		ins = tmp + len_rep;
    101 
    102 	tmp = ret = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
    103 
    104 	if (!ret)
    105 		return NULL;
    106 
    107 	/* tmp: end of the ret string
    108 	 * ins: next occurrence of rep in orig
    109 	 * orig: remainder of orig after "end of rep" */
    110 	while (count--) {
    111 		ins = strstr(orig, rep);
    112 		len_front = ins - orig;
    113 		tmp = strncpy(tmp, orig, len_front) + len_front;
    114 		tmp = strcpy(tmp, with) + len_with;
    115 		orig += len_front + len_rep; /* move to next "end of rep" */
    116 	}
    117 	strcpy(tmp, orig);
    118 
    119 	return ret;
    120 }
    121 
    122 /* remove tailing or leading white space from s */
    123 char *
    124 str_trim(char *s)
    125 {
    126 	char *end;
    127 
    128 	/* trim leading space */
    129 	while (isspace(*s)) s++;
    130 
    131 	if (*s == 0) /* all spaces? */
    132 		return s;
    133 
    134 	/* trim trailing space */
    135 	end = s + strlen(s) - 1;
    136 	while (end > s && isspace(*end)) end--;
    137 
    138 	/* write new null terminator */
    139 	*(end+1) = 0;
    140 
    141 	return s;
    142 }
    143 
    144 char *
    145 str_rmspaces(char *s)
    146 {
    147 	int c = 0, d = 0;
    148 	char *start = emalloc(strlen(s)+1);
    149 
    150 	while (*(s+c) != '\0') {
    151 		if (*(s+c) == ' ') {
    152 			int temp = c + 1;
    153 			if (*(s+temp) != '\0') {
    154 				while (*(s+temp) == ' ' && *(s+temp) != '\0') {
    155 					if (*(s+temp) == ' ') c++;
    156 					temp++;
    157 				}
    158 			}
    159 		}
    160 		*(start+d) = *(s+c);
    161 		c++;
    162 		d++;
    163 	}
    164 	*(start+d)= '\0';
    165 
    166 	return start;
    167 }
    168 
    169 /* return if str is in the list */
    170 int
    171 strinlist(char *str, char **list, int listc)
    172 {
    173 	if (!str || !list) return 0;
    174 	int i;
    175 	for (i = 0; i < listc; i++)
    176 		if (list[i] && strcmp(str, list[i]) == 0)
    177 			return 1;
    178 	return 0;
    179 }
    180 
    181 int
    182 charinstr(char c, char *str)
    183 {
    184 	if (!str) return 0;
    185 	for (; *str; str++)
    186 		if (*str == c)
    187 			return 1;
    188 	return 0;
    189 }