Forgot to remove some more .s strings and do a rename in order to prevent compiler...
[midnight-commander.git] / mhl / string.h
blob3b4c421f180ba0fbf2b895e4c5b81eb864146f49
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 #define ISSPACE(c) isspace((unsigned char)(c))
14 #define TOUPPER(c) toupper((unsigned char)(c))
16 static inline char * mhl_str_dup_range(const char * s_start, const char * s_bound)
18 return mhl_str_ndup(s_start, s_bound - s_start);
21 static inline char* mhl_str_trim(char* str)
23 if (!str) return NULL; /* NULL string ?! bail out. */
25 /* find the first non-space */
26 char* start; for (start=str; ((*str) && (!ISSPACE(*str))); str++);
28 /* only spaces ? */
29 if (!(*str)) { *str = 0; return str; }
31 /* get the size (cannot be empty - caught above) */
32 size_t _sz = strlen(str);
34 /* find the proper end */
35 char* end;
36 for (end=(str+_sz-1); ((end>str) && (ISSPACE(*end))); end--);
37 end[1] = 0; /* terminate, just to be sure */
39 /* if we have no leading spaces, just trucate */
40 if (start==str) { end++; *end = 0; return str; }
42 /* if it's only one char, dont need memmove for that */
43 if (start==end) { str[0]=*start; str[1]=0; return str; }
45 /* by here we have a (non-empty) region between start and end */
46 memmove(str,start,(end-start+1));
47 return str;
50 static inline void mhl_str_toupper(char* str)
52 if (str)
53 for (;*str;str++)
54 *str = TOUPPER(*str);
57 /* note: we use ((char*)(1)) as terminator - NULL is a valid argument ! */
58 static const char * mhl_s_c_sep__ = (const char *)1;
59 /* _NEVER_ call this function directly ! */
60 static inline char* mhl_str_concat_hlp__(const char* va_start_dummy, ...)
62 char * result;
63 size_t result_len = 0;
64 char * p;
65 const char * chunk;
67 va_list args;
68 va_start(args,va_start_dummy);
69 while ((chunk = va_arg(args, const char*)) != mhl_s_c_sep__)
71 if (chunk)
73 result_len += strlen (chunk);
76 va_end(args);
78 if (result_len == 0)
79 return mhl_str_dup("");
81 /* now as we know how much to copy, allocate the buffer + '\0'*/
82 result = (char*)mhl_mem_alloc_u (result_len + 1);
84 p = result;
86 va_start(args,va_start_dummy);
87 while ((chunk = va_arg(args, const char*)) != mhl_s_c_sep__)
89 if (chunk)
91 size_t chunk_len = strlen (chunk);
92 memcpy (p, chunk, chunk_len);
93 p += chunk_len;
96 va_end(args);
98 *p = '\0';
99 return result;
102 #define mhl_str_concat(...) (mhl_str_concat_hlp__(mhl_s_c_sep__, __VA_ARGS__, mhl_s_c_sep__))
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 /* strictly speaking, this invokes undefined behavior as soon as dest and src are pointers into different objects. */
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 */