Call va_end after the iteration as we need to free the list again.
[midnight-commander.git] / mhl / string.h
blobfcbbd864f177eb437dc327bddfe9a3902bd50592
1 #ifndef __MHL_STRING_H
2 #define __MHL_STRING_H
4 #include <ctype.h>
5 #include <stdarg.h>
6 #include <assert.h>
7 #include <mhl/memory.h>
9 #define mhl_str_dup(str) ((str ? strdup(str) : strdup("")))
10 #define mhl_str_ndup(str,len) ((str ? strndup(str,len) : strdup("")))
11 #define mhl_str_len(str) ((str ? strlen(str) : 0))
13 static inline char * mhl_str_dup_range(const char * s_start, const char * s_bound)
15 return mhl_str_ndup(s_start, s_bound - s_start);
18 static inline char* mhl_str_trim(char* str)
20 if (!str) return NULL; /* NULL string ?! bail out. */
22 /* find the first non-space */
23 char* start; for (start=str; ((*str) && (!isspace(*str))); str++);
25 /* only spaces ? */
26 if (!(*str)) { *str = 0; return str; }
28 /* get the size (cannot be empty - catched above) */
29 size_t _sz = strlen(str);
31 /* find the proper end */
32 char* end;
33 for (end=(str+_sz-1); ((end>str) && (isspace(*end))); end--);
34 end[1] = 0; /* terminate, just to be sure */
36 /* if we have no leading spaces, just trucate */
37 if (start==str) { end++; *end = 0; return str; }
39 /* if it' only one char, dont need memmove for that */
40 if (start==end) { str[0]=*start; str[1]=0; return str; }
42 /* by here we have a (non-empty) region between start end end */
43 memmove(str,start,(end-start+1));
44 return str;
47 static inline void mhl_str_toupper(char* str)
49 if (str)
50 for (;*str;str++)
51 *str = toupper(*str);
54 #define __STR_CONCAT_MAX 32
55 /* _NEVER_ call this function directly ! */
56 static inline char* __mhl_str_concat_hlp(const char* base, ...)
58 static const char* arg_ptr[__STR_CONCAT_MAX];
59 static size_t arg_sz[__STR_CONCAT_MAX];
60 int count = 0;
61 size_t totalsize = 0;
63 if (base)
65 arg_ptr[0] = base;
66 arg_sz[0] = totalsize = strlen(base);
67 count = 1;
70 va_list args;
71 va_start(args,base);
72 char* a;
73 /* note: we use ((char*)(1)) as terminator - NULL is a valid argument ! */
74 while ((a = va_arg(args, char*))!=(char*)1 && count < __STR_CONCAT_MAX )
76 if (a)
78 arg_ptr[count] = a;
79 arg_sz[count] = strlen(a);
80 totalsize += arg_sz[count];
81 count++;
84 va_end(args);
86 if (!count)
87 return mhl_str_dup("");
89 /* now as we know how much to copy, allocate the buffer */
90 char* buffer = (char*)mhl_mem_alloc_u(totalsize+2);
91 char* current = buffer;
92 int x=0;
93 for (x=0; x<count; x++)
95 memcpy(current, arg_ptr[x], arg_sz[x]);
96 current += arg_sz[x];
99 *current = 0;
100 return buffer;
103 #define mhl_str_concat(...) (__mhl_str_concat_hlp(__VA_ARGS__, (char*)(1)))
105 static inline char* mhl_str_reverse(char* ptr)
107 if (!ptr) return NULL; /* missing string */
108 if (!(ptr[0] && ptr[1])) return ptr; /* empty or 1-ch string */
110 size_t _sz = strlen(ptr);
111 char* start = ptr;
112 char* end = ptr+_sz-1;
114 while (start<end)
116 char c = *start;
117 *start = *end;
118 *end = c;
119 start++;
120 end--;
123 return ptr;
127 * strcpy is unsafe on overlapping memory areas, so define memmove-alike
128 * string function. Has sense only when dest <= src.
130 static inline char * mhl_strmove(char * dest, const char * src)
132 size_t n = strlen (src) + 1; /* + '\0' */
134 assert (dest<=src);
136 return memmove(dest, src, n);
139 static inline char* mhl_str_dir_plus_file(const char* dirname, const char* filename)
141 /* make sure we have valid strings */
142 if (!dirname)
143 dirname="";
145 if (!filename)
146 filename="";
148 /* skip leading slashes on filename */
149 while (*filename == '/')
150 filename++;
152 /* skip trailing slashes on dirname */
153 size_t dnlen = strlen(dirname);
154 while ((dnlen != 0) && (dirname[dnlen-1]=='/'))
155 dnlen--;
157 size_t fnlen = strlen(filename);
158 char* buffer = mhl_mem_alloc_z(dnlen+fnlen+2); /* enough space for dirname, /, filename, zero */
159 char* ptr = buffer;
161 memcpy(ptr, dirname, dnlen);
162 ptr+=dnlen;
163 *ptr = '/';
164 ptr++;
165 memcpy(ptr, filename, fnlen);
166 ptr+=fnlen;
167 *ptr = 0;
169 return buffer;
172 #endif /* __MHL_STRING_H */