3 Copyright (C) 2005 and later, Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
24 C string manipulation utilities -- [v]snprintf for Win32, also snprintf_append, lstrcatn, etc
26 #ifndef _WDL_CSTRING_H_
27 #define _WDL_CSTRING_H_
35 #ifdef _WDL_CSTRING_IMPL_ONLY_
36 #ifdef _WDL_CSTRING_IF_ONLY_
37 #undef _WDL_CSTRING_IF_ONLY_
39 #define _WDL_CSTRING_PREFIX
41 #define _WDL_CSTRING_PREFIX static WDL_STATICFUNC_UNUSED
46 #if defined(_WIN32) && defined(_MSC_VER)
47 // provide snprintf()/vsnprintf() for win32 -- note that these have no way of knowing
48 // what the amount written was, code should(must) be written to not depend on this.
52 #define snprintf WDL_snprintf
57 #define vsnprintf WDL_vsnprintf
59 #endif // win32 snprintf/vsnprintf
61 // use wdlcstring.h's lstrcpyn_safe rather than the real lstrcpyn.
66 #define lstrcpyn lstrcpyn_safe
73 #ifdef _WDL_CSTRING_IF_ONLY_
75 void lstrcpyn_safe(char *o
, const char *in
, int count
);
76 void lstrcatn(char *o
, const char *in
, int count
);
77 void WDL_VARARG_WARN(printf
,3,4) snprintf_append(char *o
, int count
, const char *format
, ...);
78 void vsnprintf_append(char *o
, int count
, const char *format
, va_list va
);
80 const char *WDL_get_filepart(const char *str
); // returns whole string if no dir chars
81 const char *WDL_get_fileext(const char *str
); // returns ".ext" or end of string "" if no extension
82 char *WDL_remove_fileext(char *str
); // returns pointer to "ext" if ".ext" was removed (zero-d dot), or NULL
83 char WDL_remove_filepart(char *str
); // returns dir character that was zeroed, or 0 if new string is empty
84 int WDL_remove_trailing_dirchars(char *str
); // returns trailing dirchar count removed, will not convert "/" into ""
85 size_t WDL_remove_trailing_crlf(char *str
); // returns new length
88 #if defined(_WIN32) && defined(_MSC_VER)
89 void WDL_vsnprintf(char *o
, size_t count
, const char *format
, va_list args
);
90 void WDL_VARARG_WARN(printf
,3,4) WDL_snprintf(char *o
, size_t count
, const char *format
, ...);
93 int WDL_strcmp_logical(const char *s1
, const char *s2
, int case_sensitive
);
97 #if defined(_WIN32) && defined(_MSC_VER)
99 _WDL_CSTRING_PREFIX
void WDL_vsnprintf(char *o
, size_t count
, const char *format
, va_list args
)
105 rv
=_vsnprintf(o
,count
,format
,args
); // returns -1 if over, and does not null terminate, ugh
106 if (rv
< 0 || rv
>=(int)count
-1) o
[count
-1]=0;
109 _WDL_CSTRING_PREFIX
void WDL_VARARG_WARN(printf
,3,4) WDL_snprintf(char *o
, size_t count
, const char *format
, ...)
117 rv
=_vsnprintf(o
,count
,format
,va
); // returns -1 if over, and does not null terminate, ugh
120 if (rv
< 0 || rv
>=(int)count
-1) o
[count
-1]=0;
125 _WDL_CSTRING_PREFIX
void lstrcpyn_safe(char *o
, const char *in
, int count
)
129 while (--count
>0 && *in
) *o
++ = *in
++;
134 _WDL_CSTRING_PREFIX
void lstrcatn(char *o
, const char *in
, int count
)
138 while (*o
) { if (--count
< 1) return; o
++; }
139 while (--count
>0 && *in
) *o
++ = *in
++;
144 _WDL_CSTRING_PREFIX
const char *WDL_get_filepart(const char *str
) // returns whole string if no dir chars
148 while (p
>= str
&& !WDL_IS_DIRCHAR(*p
)) --p
;
151 _WDL_CSTRING_PREFIX
const char *WDL_get_fileext(const char *str
) // returns ".ext" or end of string "" if no extension
153 const char *p
=str
, *ep
;
156 while (p
>= str
&& !WDL_IS_DIRCHAR(*p
))
158 if (*p
== '.') return p
;
164 _WDL_CSTRING_PREFIX
char *WDL_remove_fileext(char *str
) // returns pointer to "ext" if ".ext" was removed (zero-d dot), or NULL
168 while (p
>= str
&& !WDL_IS_DIRCHAR(*p
))
180 _WDL_CSTRING_PREFIX
char WDL_remove_filepart(char *str
) // returns dir character that was zeroed, or 0 if new string is empty
187 if (WDL_IS_DIRCHAR(c
))
198 _WDL_CSTRING_PREFIX
int WDL_remove_trailing_dirchars(char *str
) // returns trailing dirchar count removed
203 while (p
> str
+1 && WDL_IS_DIRCHAR(p
[-1]))
212 _WDL_CSTRING_PREFIX
size_t WDL_remove_trailing_crlf(char *str
) // returns new length
216 while (p
> str
&& (p
[-1] == '\r' || p
[-1] == '\n')) p
--;
221 _WDL_CSTRING_PREFIX
void WDL_VARARG_WARN(printf
,3,4) snprintf_append(char *o
, int count
, const char *format
, ...)
226 while (*o
) { if (--count
< 1) return; o
++; }
228 vsnprintf(o
,count
,format
,va
);
233 _WDL_CSTRING_PREFIX
void vsnprintf_append(char *o
, int count
, const char *format
, va_list va
)
237 while (*o
) { if (--count
< 1) return; o
++; }
238 vsnprintf(o
,count
,format
,va
);
242 _WDL_CSTRING_PREFIX
int WDL_strcmp_logical(const char *s1
, const char *s2
, int case_sensitive
)
244 // also exists as WDL_LogicalSortStringKeyedArray::_cmpstr()
246 char lastNonZeroChar
=0;
247 // last matching character, updated if not 0. this allows us to track whether
248 // we are inside of a number with the same leading digits
252 char c1
=*s1
++, c2
=*s2
++;
253 if (!c1
) return c1
-c2
;
257 if (c1
>= '0' && c1
<= '9' && c2
>= '0' && c2
<= '9')
260 if (lastNonZeroChar
< '1' || lastNonZeroChar
> '9')
262 while (c1
== '0') { c1
=*s1
++; lzdiff
--; }
263 while (c2
== '0') { c2
=*s2
++; lzdiff
++; } // lzdiff = lz2-lz1, more leading 0s = earlier in list
268 if (c1
>= '0' && c1
<= '9')
270 if (c2
< '0' || c2
> '9') return 1;
277 if (c2
>= '0' && c2
<= '9') return -1;
287 const int d
= *s1
++ - *s2
++;
291 if (lzdiff
) return lzdiff
;
297 if (c1
>='a' && c1
<='z') c1
+='A'-'a';
298 if (c2
>='a' && c2
<='z') c2
+='A'-'a';
300 if (c1
!= c2
) return c1
-c2
;
303 else if (c1
!= '0') lastNonZeroChar
=c1
;
314 #undef _WDL_CSTRING_PREFIX