Revert "cleanup: mhl_str_dir_plus_file(): int -> size_t (suggested by Andrew Borodin)"
[midnight-commander.git] / mhl / string.h
blobf4c56e5ec19953b6335ad39bb1a30f2b05fa23c1
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)
76 if (a)
78 arg_ptr[count] = a;
79 arg_sz[count] = strlen(a);
80 totalsize += arg_sz[count];
81 count++;
85 if (!count)
86 return mhl_str_dup("");
88 /* now as we know how much to copy, allocate the buffer */
89 char* buffer = (char*)mhl_mem_alloc_u(totalsize+2);
90 char* current = buffer;
91 int x=0;
92 for (x=0; x<count; x++)
94 memcpy(current, arg_ptr[x], arg_sz[x]);
95 current += arg_sz[x];
98 *current = 0;
99 return buffer;
102 #define mhl_str_concat(...) (__mhl_str_concat_hlp(__VA_ARGS__, (char*)(1)))
104 static inline char* mhl_str_reverse(char* ptr)
106 if (!ptr) return NULL; /* missing string */
107 if (!(ptr[0] && ptr[1])) return ptr; /* empty or 1-ch string */
109 size_t _sz = strlen(ptr);
110 char* start = ptr;
111 char* end = ptr+_sz-1;
113 while (start<end)
115 char c = *start;
116 *start = *end;
117 *end = c;
118 start++;
119 end--;
122 return ptr;
126 * strcpy is unsafe on overlapping memory areas, so define memmove-alike
127 * string function. Has sense only when dest <= src.
129 static inline char * mhl_strmove(char * dest, const char * src)
131 size_t n = strlen (src) + 1; /* + '\0' */
133 assert (dest<=src);
135 return memmove(dest, src, n);
138 static inline char* mhl_str_dir_plus_file(const char* dirname, const char* filename)
140 /* make sure we have valid strings */
141 if (!dirname)
142 dirname="";
144 if (!filename)
145 filename="";
147 /* skip leading slashes on filename */
148 while (*filename == '/')
149 filename++;
151 /* skip trailing slashes on dirname */
152 int dnlen = strlen(dirname);
153 while (dnlen && (dirname[dnlen-1]=='/'))
154 dnlen--;
156 int fnlen = strlen(filename);
157 char* buffer = mhl_mem_alloc_z(dnlen+fnlen+2); /* enough space for dirname, /, filename, zero */
158 char* ptr = buffer;
160 memcpy(ptr, dirname, dnlen);
161 ptr+=dnlen;
162 *ptr = '/';
163 ptr++;
164 memcpy(ptr, filename, fnlen);
165 ptr+=fnlen;
166 *ptr = 0;
168 return buffer;
171 #endif /* __MHL_STRING_H */