123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- /*
- WDL - wdlcstring.h
- Copyright (C) 2005 and later, Cockos Incorporated
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- */
- /*
- C string manipulation utilities -- [v]snprintf for Win32, also snprintf_append, lstrcatn, etc
- */
- #ifndef _WDL_CSTRING_H_
- #define _WDL_CSTRING_H_
- #include <stdarg.h>
- #include <stdio.h>
- #include <ctype.h>
- #include "wdltypes.h"
- #ifdef _WDL_CSTRING_IMPL_ONLY_
- #ifdef _WDL_CSTRING_IF_ONLY_
- #undef _WDL_CSTRING_IF_ONLY_
- #endif
- #define _WDL_CSTRING_PREFIX
- #else
- #define _WDL_CSTRING_PREFIX static WDL_STATICFUNC_UNUSED
- #endif
- #if defined(_WIN32) && defined(_MSC_VER)
- // provide snprintf()/vsnprintf() for win32 -- note that these have no way of knowing
- // what the amount written was, code should(must) be written to not depend on this.
- #ifdef snprintf
- #undef snprintf
- #endif
- #define snprintf WDL_snprintf
- #ifdef vsnprintf
- #undef vsnprintf
- #endif
- #define vsnprintf WDL_vsnprintf
- #endif // win32 snprintf/vsnprintf
- // use wdlcstring.h's lstrcpyn_safe rather than the real lstrcpyn.
- #ifdef _WIN32
- #ifdef lstrcpyn
- #undef lstrcpyn
- #endif
- #define lstrcpyn lstrcpyn_safe
- #endif
- #ifdef __cplusplus
- extern "C" {
- #endif
- #ifdef _WDL_CSTRING_IF_ONLY_
- void lstrcpyn_safe(char *o, const char *in, INT_PTR count);
- void lstrcatn(char *o, const char *in, INT_PTR count);
- void WDL_VARARG_WARN(printf,3,4) snprintf_append(char *o, INT_PTR count, const char *format, ...);
- void vsnprintf_append(char *o, INT_PTR count, const char *format, va_list va);
- const char *WDL_get_filepart(const char *str); // returns whole string if no dir chars
- const char *WDL_get_fileext(const char *str); // returns ".ext" or end of string "" if no extension
- char *WDL_remove_fileext(char *str); // returns pointer to "ext" if ".ext" was removed (zero-d dot), or NULL
- char WDL_remove_filepart(char *str); // returns dir character that was zeroed, or 0 if new string is empty
- int WDL_remove_trailing_dirchars(char *str); // returns trailing dirchar count removed, will not convert "/" into ""
- size_t WDL_remove_trailing_crlf(char *str); // returns new length
- #if defined(_WIN32) && defined(_MSC_VER)
- void WDL_vsnprintf(char *o, size_t count, const char *format, va_list args);
- void WDL_VARARG_WARN(printf,3,4) WDL_snprintf(char *o, size_t count, const char *format, ...);
- #endif
- int WDL_strcmp_logical(const char *s1, const char *s2, int case_sensitive);
- #else
- #if defined(_WIN32) && defined(_MSC_VER)
- _WDL_CSTRING_PREFIX void WDL_vsnprintf(char *o, size_t count, const char *format, va_list args)
- {
- if (count>0)
- {
- int rv;
- o[0]=0;
- rv=_vsnprintf(o,count,format,args); // returns -1 if over, and does not null terminate, ugh
- if (rv < 0 || rv>=(int)count-1) o[count-1]=0;
- }
- }
- _WDL_CSTRING_PREFIX void WDL_VARARG_WARN(printf,3,4) WDL_snprintf(char *o, size_t count, const char *format, ...)
- {
- if (count>0)
- {
- int rv;
- va_list va;
- va_start(va,format);
- o[0]=0;
- rv=_vsnprintf(o,count,format,va); // returns -1 if over, and does not null terminate, ugh
- va_end(va);
- if (rv < 0 || rv>=(int)count-1) o[count-1]=0;
- }
- }
- #endif
- _WDL_CSTRING_PREFIX void lstrcpyn_safe(char *o, const char *in, INT_PTR count)
- {
- if (count>0)
- {
- while (--count>0 && *in) *o++ = *in++;
- *o=0;
- }
- }
- _WDL_CSTRING_PREFIX void lstrcatn(char *o, const char *in, INT_PTR count)
- {
- if (count>0)
- {
- while (*o) { if (--count < 1) return; o++; }
- while (--count>0 && *in) *o++ = *in++;
- *o=0;
- }
- }
- _WDL_CSTRING_PREFIX const char *WDL_get_filepart(const char *str) // returns whole string if no dir chars
- {
- const char *p = str;
- while (*p) p++;
- while (p >= str && !WDL_IS_DIRCHAR(*p)) --p;
- return p + 1;
- }
- _WDL_CSTRING_PREFIX const char *WDL_get_fileext(const char *str) // returns ".ext" or end of string "" if no extension
- {
- const char *p=str, *ep;
- while (*p) p++;
- ep = p;
- while (p >= str && !WDL_IS_DIRCHAR(*p))
- {
- if (*p == '.') return p;
- --p;
- }
- return ep;
- }
- _WDL_CSTRING_PREFIX char *WDL_remove_fileext(char *str) // returns pointer to "ext" if ".ext" was removed (zero-d dot), or NULL
- {
- char *p=str;
- while (*p) p++;
- while (p >= str && !WDL_IS_DIRCHAR(*p))
- {
- if (*p == '.')
- {
- *p = 0;
- return p+1;
- }
- --p;
- }
- return NULL;
- }
- _WDL_CSTRING_PREFIX char WDL_remove_filepart(char *str) // returns dir character that was zeroed, or 0 if new string is empty
- {
- char *p=str;
- while (*p) p++;
- while (p >= str)
- {
- char c = *p;
- if (WDL_IS_DIRCHAR(c))
- {
- *p = 0;
- return c;
- }
- --p;
- }
- str[0] = 0;
- return 0;
- }
- _WDL_CSTRING_PREFIX int WDL_remove_trailing_dirchars(char *str) // returns trailing dirchar count removed
- {
- int cnt = 0;
- char *p=str;
- while (*p) p++;
- while (p > str+1 && WDL_IS_DIRCHAR(p[-1]))
- {
- cnt++;
- p--;
- }
- *p = 0;
- return cnt;
- }
- _WDL_CSTRING_PREFIX size_t WDL_remove_trailing_crlf(char *str) // returns new length
- {
- char *p=str;
- while (*p) p++;
- while (p > str && (p[-1] == '\r' || p[-1] == '\n')) p--;
- *p = 0;
- return p-str;
- }
- _WDL_CSTRING_PREFIX void WDL_VARARG_WARN(printf,3,4) snprintf_append(char *o, INT_PTR count, const char *format, ...)
- {
- if (count>0)
- {
- va_list va;
- while (*o) { if (--count < 1) return; o++; }
- va_start(va,format);
- vsnprintf(o,count,format,va);
- va_end(va);
- }
- }
- _WDL_CSTRING_PREFIX void vsnprintf_append(char *o, INT_PTR count, const char *format, va_list va)
- {
- if (count>0)
- {
- while (*o) { if (--count < 1) return; o++; }
- vsnprintf(o,count,format,va);
- }
- }
- _WDL_CSTRING_PREFIX int WDL_strcmp_logical(const char *s1, const char *s2, int case_sensitive)
- {
- // also exists as WDL_LogicalSortStringKeyedArray::_cmpstr()
- char lastNonZeroChar=0;
- // last matching character, updated if not 0. this allows us to track whether
- // we are inside of a number with the same leading digits
- for (;;)
- {
- char c1=*s1++, c2=*s2++;
- if (!c1) return c1-c2;
-
- if (c1!=c2)
- {
- if (c1 >= '0' && c1 <= '9' && c2 >= '0' && c2 <= '9')
- {
- int lzdiff=0, cnt=0;
- if (lastNonZeroChar < '1' || lastNonZeroChar > '9')
- {
- while (c1 == '0') { c1=*s1++; lzdiff--; }
- while (c2 == '0') { c2=*s2++; lzdiff++; } // lzdiff = lz2-lz1, more leading 0s = earlier in list
- }
- for (;;)
- {
- if (c1 >= '0' && c1 <= '9')
- {
- if (c2 < '0' || c2 > '9') return 1;
- c1=s1[cnt];
- c2=s2[cnt++];
- }
- else
- {
- if (c2 >= '0' && c2 <= '9') return -1;
- break;
- }
- }
- s1--;
- s2--;
-
- while (cnt--)
- {
- const int d = *s1++ - *s2++;
- if (d) return d;
- }
- if (lzdiff) return lzdiff;
- }
- else
- {
- if (!case_sensitive)
- {
- if (c1>='a' && c1<='z') c1+='A'-'a';
- if (c2>='a' && c2<='z') c2+='A'-'a';
- }
- if (c1 != c2) return c1-c2;
- }
- }
- else if (c1 != '0') lastNonZeroChar=c1;
- }
- }
- #endif
- #ifdef __cplusplus
- };
- #endif
- #undef _WDL_CSTRING_PREFIX
- #endif
|