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
++);
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 */
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));
50 static inline void mhl_str_toupper(char* 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
, ...)
63 size_t result_len
= 0;
68 va_start(args
,va_start_dummy
);
69 while ((chunk
= va_arg(args
, const char*)) != mhl_s_c_sep__
)
73 result_len
+= strlen (chunk
);
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);
86 va_start(args
,va_start_dummy
);
87 while ((chunk
= va_arg(args
, const char*)) != mhl_s_c_sep__
)
91 size_t chunk_len
= strlen (chunk
);
92 memcpy (p
, chunk
, chunk_len
);
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
);
111 char* end
= ptr
+_sz
-1;
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. */
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 */
148 /* skip leading slashes on filename */
149 while (*filename
== '/')
152 /* skip trailing slashes on dirname */
153 size_t dnlen
= strlen(dirname
);
154 while ((dnlen
!= 0) && (dirname
[dnlen
-1]=='/'))
157 size_t fnlen
= strlen(filename
);
158 char* buffer
= mhl_mem_alloc_z(dnlen
+fnlen
+2); /* enough space for dirname, /, filename, zero */
161 memcpy(ptr
, dirname
, dnlen
);
165 memcpy(ptr
, filename
, fnlen
);
172 #endif /* MHL_STRING_H */