mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 16:45:47 -04:00
Initial community commit
This commit is contained in:
316
Src/ns-eel2/wdlcstring.h
Normal file
316
Src/ns-eel2/wdlcstring.h
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
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
|
Reference in New Issue
Block a user