|
Ivan Mahonin |
b53a5c |
#include "nuklear.h"
|
|
Ivan Mahonin |
b53a5c |
#include "nuklear_internal.h"
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* ===============================================================
|
|
Ivan Mahonin |
b53a5c |
*
|
|
Ivan Mahonin |
b53a5c |
* UTIL
|
|
Ivan Mahonin |
b53a5c |
*
|
|
Ivan Mahonin |
b53a5c |
* ===============================================================*/
|
|
Ivan Mahonin |
b53a5c |
NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
|
|
Ivan Mahonin |
b53a5c |
NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
|
|
Ivan Mahonin |
b53a5c |
NK_LIB nk_bool nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
|
|
Ivan Mahonin |
b53a5c |
NK_LIB nk_bool nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
|
|
Ivan Mahonin |
b53a5c |
NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
|
|
Ivan Mahonin |
b53a5c |
NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
#ifndef NK_MEMCPY
|
|
Ivan Mahonin |
b53a5c |
#define NK_MEMCPY nk_memcopy
|
|
Ivan Mahonin |
b53a5c |
NK_LIB void*
|
|
Ivan Mahonin |
b53a5c |
nk_memcopy(void *dst0, const void *src0, nk_size length)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
nk_ptr t;
|
|
Ivan Mahonin |
b53a5c |
char *dst = (char*)dst0;
|
|
Ivan Mahonin |
b53a5c |
const char *src = (const char*)src0;
|
|
Ivan Mahonin |
b53a5c |
if (length == 0 || dst == src)
|
|
Ivan Mahonin |
b53a5c |
goto done;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
#define nk_word int
|
|
Ivan Mahonin |
b53a5c |
#define nk_wsize sizeof(nk_word)
|
|
Ivan Mahonin |
b53a5c |
#define nk_wmask (nk_wsize-1)
|
|
Ivan Mahonin |
b53a5c |
#define NK_TLOOP(s) if (t) NK_TLOOP1(s)
|
|
Ivan Mahonin |
b53a5c |
#define NK_TLOOP1(s) do { s; } while (--t)
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (dst < src) {
|
|
Ivan Mahonin |
b53a5c |
t = (nk_ptr)src; /* only need low bits */
|
|
Ivan Mahonin |
b53a5c |
if ((t | (nk_ptr)dst) & nk_wmask) {
|
|
Ivan Mahonin |
b53a5c |
if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
|
|
Ivan Mahonin |
b53a5c |
t = length;
|
|
Ivan Mahonin |
b53a5c |
else
|
|
Ivan Mahonin |
b53a5c |
t = nk_wsize - (t & nk_wmask);
|
|
Ivan Mahonin |
b53a5c |
length -= t;
|
|
Ivan Mahonin |
b53a5c |
NK_TLOOP1(*dst++ = *src++);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
t = length / nk_wsize;
|
|
Ivan Mahonin |
b53a5c |
NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
|
|
Ivan Mahonin |
b53a5c |
src += nk_wsize; dst += nk_wsize);
|
|
Ivan Mahonin |
b53a5c |
t = length & nk_wmask;
|
|
Ivan Mahonin |
b53a5c |
NK_TLOOP(*dst++ = *src++);
|
|
Ivan Mahonin |
b53a5c |
} else {
|
|
Ivan Mahonin |
b53a5c |
src += length;
|
|
Ivan Mahonin |
b53a5c |
dst += length;
|
|
Ivan Mahonin |
b53a5c |
t = (nk_ptr)src;
|
|
Ivan Mahonin |
b53a5c |
if ((t | (nk_ptr)dst) & nk_wmask) {
|
|
Ivan Mahonin |
b53a5c |
if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
|
|
Ivan Mahonin |
b53a5c |
t = length;
|
|
Ivan Mahonin |
b53a5c |
else
|
|
Ivan Mahonin |
b53a5c |
t &= nk_wmask;
|
|
Ivan Mahonin |
b53a5c |
length -= t;
|
|
Ivan Mahonin |
b53a5c |
NK_TLOOP1(*--dst = *--src);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
t = length / nk_wsize;
|
|
Ivan Mahonin |
b53a5c |
NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
|
|
Ivan Mahonin |
b53a5c |
*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
|
|
Ivan Mahonin |
b53a5c |
t = length & nk_wmask;
|
|
Ivan Mahonin |
b53a5c |
NK_TLOOP(*--dst = *--src);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#undef nk_word
|
|
Ivan Mahonin |
b53a5c |
#undef nk_wsize
|
|
Ivan Mahonin |
b53a5c |
#undef nk_wmask
|
|
Ivan Mahonin |
b53a5c |
#undef NK_TLOOP
|
|
Ivan Mahonin |
b53a5c |
#undef NK_TLOOP1
|
|
Ivan Mahonin |
b53a5c |
done:
|
|
Ivan Mahonin |
b53a5c |
return (dst0);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
#ifndef NK_MEMSET
|
|
Ivan Mahonin |
b53a5c |
#define NK_MEMSET nk_memset
|
|
Ivan Mahonin |
b53a5c |
NK_LIB void
|
|
Ivan Mahonin |
b53a5c |
nk_memset(void *ptr, int c0, nk_size size)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
#define nk_word unsigned
|
|
Ivan Mahonin |
b53a5c |
#define nk_wsize sizeof(nk_word)
|
|
Ivan Mahonin |
b53a5c |
#define nk_wmask (nk_wsize - 1)
|
|
Ivan Mahonin |
b53a5c |
nk_byte *dst = (nk_byte*)ptr;
|
|
Ivan Mahonin |
b53a5c |
unsigned c = 0;
|
|
Ivan Mahonin |
b53a5c |
nk_size t = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if ((c = (nk_byte)c0) != 0) {
|
|
Ivan Mahonin |
b53a5c |
c = (c << 8) | c; /* at least 16-bits */
|
|
Ivan Mahonin |
b53a5c |
if (sizeof(unsigned int) > 2)
|
|
Ivan Mahonin |
b53a5c |
c = (c << 16) | c; /* at least 32-bits*/
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* too small of a word count */
|
|
Ivan Mahonin |
b53a5c |
dst = (nk_byte*)ptr;
|
|
Ivan Mahonin |
b53a5c |
if (size < 3 * nk_wsize) {
|
|
Ivan Mahonin |
b53a5c |
while (size--) *dst++ = (nk_byte)c0;
|
|
Ivan Mahonin |
b53a5c |
return;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* align destination */
|
|
Ivan Mahonin |
b53a5c |
if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
|
|
Ivan Mahonin |
b53a5c |
t = nk_wsize -t;
|
|
Ivan Mahonin |
b53a5c |
size -= t;
|
|
Ivan Mahonin |
b53a5c |
do {
|
|
Ivan Mahonin |
b53a5c |
*dst++ = (nk_byte)c0;
|
|
Ivan Mahonin |
b53a5c |
} while (--t != 0);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill word */
|
|
Ivan Mahonin |
b53a5c |
t = size / nk_wsize;
|
|
Ivan Mahonin |
b53a5c |
do {
|
|
Ivan Mahonin |
b53a5c |
*(nk_word*)((void*)dst) = c;
|
|
Ivan Mahonin |
b53a5c |
dst += nk_wsize;
|
|
Ivan Mahonin |
b53a5c |
} while (--t != 0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill trailing bytes */
|
|
Ivan Mahonin |
b53a5c |
t = (size & nk_wmask);
|
|
Ivan Mahonin |
b53a5c |
if (t != 0) {
|
|
Ivan Mahonin |
b53a5c |
do {
|
|
Ivan Mahonin |
b53a5c |
*dst++ = (nk_byte)c0;
|
|
Ivan Mahonin |
b53a5c |
} while (--t != 0);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
#undef nk_word
|
|
Ivan Mahonin |
b53a5c |
#undef nk_wsize
|
|
Ivan Mahonin |
b53a5c |
#undef nk_wmask
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
NK_LIB void
|
|
Ivan Mahonin |
b53a5c |
nk_zero(void *ptr, nk_size size)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(ptr);
|
|
Ivan Mahonin |
b53a5c |
NK_MEMSET(ptr, 0, size);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_strlen(const char *str)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int siz = 0;
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(str);
|
|
Ivan Mahonin |
b53a5c |
while (str && *str++ != '\0') siz++;
|
|
Ivan Mahonin |
b53a5c |
return siz;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_strtoi(const char *str, const char **endptr)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int neg = 1;
|
|
Ivan Mahonin |
b53a5c |
const char *p = str;
|
|
Ivan Mahonin |
b53a5c |
int value = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(str);
|
|
Ivan Mahonin |
b53a5c |
if (!str) return 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* skip whitespace */
|
|
Ivan Mahonin |
b53a5c |
while (*p == ' ') p++;
|
|
Ivan Mahonin |
b53a5c |
if (*p == '-') {
|
|
Ivan Mahonin |
b53a5c |
neg = -1;
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
while (*p && *p >= '0' && *p <= '9') {
|
|
Ivan Mahonin |
b53a5c |
value = value * 10 + (int) (*p - '0');
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (endptr)
|
|
Ivan Mahonin |
b53a5c |
*endptr = p;
|
|
Ivan Mahonin |
b53a5c |
return neg*value;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API double
|
|
Ivan Mahonin |
b53a5c |
nk_strtod(const char *str, const char **endptr)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
double m;
|
|
Ivan Mahonin |
b53a5c |
double neg = 1.0;
|
|
Ivan Mahonin |
b53a5c |
const char *p = str;
|
|
Ivan Mahonin |
b53a5c |
double value = 0;
|
|
Ivan Mahonin |
b53a5c |
double number = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(str);
|
|
Ivan Mahonin |
b53a5c |
if (!str) return 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* skip whitespace */
|
|
Ivan Mahonin |
b53a5c |
while (*p == ' ') p++;
|
|
Ivan Mahonin |
b53a5c |
if (*p == '-') {
|
|
Ivan Mahonin |
b53a5c |
neg = -1.0;
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
while (*p && *p != '.' && *p != 'e') {
|
|
Ivan Mahonin |
b53a5c |
value = value * 10.0 + (double) (*p - '0');
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (*p == '.') {
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
for(m = 0.1; *p && *p != 'e'; p++ ) {
|
|
Ivan Mahonin |
b53a5c |
value = value + (double) (*p - '0') * m;
|
|
Ivan Mahonin |
b53a5c |
m *= 0.1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (*p == 'e') {
|
|
Ivan Mahonin |
b53a5c |
int i, pow, div;
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
if (*p == '-') {
|
|
Ivan Mahonin |
b53a5c |
div = nk_true;
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
} else if (*p == '+') {
|
|
Ivan Mahonin |
b53a5c |
div = nk_false;
|
|
Ivan Mahonin |
b53a5c |
p++;
|
|
Ivan Mahonin |
b53a5c |
} else div = nk_false;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
for (pow = 0; *p; p++)
|
|
Ivan Mahonin |
b53a5c |
pow = pow * 10 + (int) (*p - '0');
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
for (m = 1.0, i = 0; i < pow; i++)
|
|
Ivan Mahonin |
b53a5c |
m *= 10.0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (div)
|
|
Ivan Mahonin |
b53a5c |
value /= m;
|
|
Ivan Mahonin |
b53a5c |
else value *= m;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
number = value * neg;
|
|
Ivan Mahonin |
b53a5c |
if (endptr)
|
|
Ivan Mahonin |
b53a5c |
*endptr = p;
|
|
Ivan Mahonin |
b53a5c |
return number;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API float
|
|
Ivan Mahonin |
b53a5c |
nk_strtof(const char *str, const char **endptr)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
float float_value;
|
|
Ivan Mahonin |
b53a5c |
double double_value;
|
|
Ivan Mahonin |
b53a5c |
double_value = NK_STRTOD(str, endptr);
|
|
Ivan Mahonin |
b53a5c |
float_value = (float)double_value;
|
|
Ivan Mahonin |
b53a5c |
return float_value;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_stricmp(const char *s1, const char *s2)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
nk_int c1,c2,d;
|
|
Ivan Mahonin |
b53a5c |
do {
|
|
Ivan Mahonin |
b53a5c |
c1 = *s1++;
|
|
Ivan Mahonin |
b53a5c |
c2 = *s2++;
|
|
Ivan Mahonin |
b53a5c |
d = c1 - c2;
|
|
Ivan Mahonin |
b53a5c |
while (d) {
|
|
Ivan Mahonin |
b53a5c |
if (c1 <= 'Z' && c1 >= 'A') {
|
|
Ivan Mahonin |
b53a5c |
d += ('a' - 'A');
|
|
Ivan Mahonin |
b53a5c |
if (!d) break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (c2 <= 'Z' && c2 >= 'A') {
|
|
Ivan Mahonin |
b53a5c |
d -= ('a' - 'A');
|
|
Ivan Mahonin |
b53a5c |
if (!d) break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
return ((d >= 0) << 1) - 1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
} while (c1);
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_stricmpn(const char *s1, const char *s2, int n)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int c1,c2,d;
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(n >= 0);
|
|
Ivan Mahonin |
b53a5c |
do {
|
|
Ivan Mahonin |
b53a5c |
c1 = *s1++;
|
|
Ivan Mahonin |
b53a5c |
c2 = *s2++;
|
|
Ivan Mahonin |
b53a5c |
if (!n--) return 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
d = c1 - c2;
|
|
Ivan Mahonin |
b53a5c |
while (d) {
|
|
Ivan Mahonin |
b53a5c |
if (c1 <= 'Z' && c1 >= 'A') {
|
|
Ivan Mahonin |
b53a5c |
d += ('a' - 'A');
|
|
Ivan Mahonin |
b53a5c |
if (!d) break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (c2 <= 'Z' && c2 >= 'A') {
|
|
Ivan Mahonin |
b53a5c |
d -= ('a' - 'A');
|
|
Ivan Mahonin |
b53a5c |
if (!d) break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
return ((d >= 0) << 1) - 1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
} while (c1);
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_INTERN int
|
|
Ivan Mahonin |
b53a5c |
nk_str_match_here(const char *regexp, const char *text)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
if (regexp[0] == '\0')
|
|
Ivan Mahonin |
b53a5c |
return 1;
|
|
Ivan Mahonin |
b53a5c |
if (regexp[1] == '*')
|
|
Ivan Mahonin |
b53a5c |
return nk_str_match_star(regexp[0], regexp+2, text);
|
|
Ivan Mahonin |
b53a5c |
if (regexp[0] == '$' && regexp[1] == '\0')
|
|
Ivan Mahonin |
b53a5c |
return *text == '\0';
|
|
Ivan Mahonin |
b53a5c |
if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
|
|
Ivan Mahonin |
b53a5c |
return nk_str_match_here(regexp+1, text+1);
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_INTERN int
|
|
Ivan Mahonin |
b53a5c |
nk_str_match_star(int c, const char *regexp, const char *text)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
do {/* a '* matches zero or more instances */
|
|
Ivan Mahonin |
b53a5c |
if (nk_str_match_here(regexp, text))
|
|
Ivan Mahonin |
b53a5c |
return 1;
|
|
Ivan Mahonin |
b53a5c |
} while (*text != '\0' && (*text++ == c || c == '.'));
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_strfilter(const char *text, const char *regexp)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
/*
|
|
Ivan Mahonin |
b53a5c |
c matches any literal character c
|
|
Ivan Mahonin |
b53a5c |
. matches any single character
|
|
Ivan Mahonin |
b53a5c |
^ matches the beginning of the input string
|
|
Ivan Mahonin |
b53a5c |
$ matches the end of the input string
|
|
Ivan Mahonin |
b53a5c |
* matches zero or more occurrences of the previous character*/
|
|
Ivan Mahonin |
b53a5c |
if (regexp[0] == '^')
|
|
Ivan Mahonin |
b53a5c |
return nk_str_match_here(regexp+1, text);
|
|
Ivan Mahonin |
b53a5c |
do { /* must look even if string is empty */
|
|
Ivan Mahonin |
b53a5c |
if (nk_str_match_here(regexp, text))
|
|
Ivan Mahonin |
b53a5c |
return 1;
|
|
Ivan Mahonin |
b53a5c |
} while (*text++ != '\0');
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_strmatch_fuzzy_text(const char *str, int str_len,
|
|
Ivan Mahonin |
b53a5c |
const char *pattern, int *out_score)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
/* Returns true if each character in pattern is found sequentially within str
|
|
Ivan Mahonin |
b53a5c |
* if found then out_score is also set. Score value has no intrinsic meaning.
|
|
Ivan Mahonin |
b53a5c |
* Range varies with pattern. Can only compare scores with same search pattern. */
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* bonus for adjacent matches */
|
|
Ivan Mahonin |
b53a5c |
#define NK_ADJACENCY_BONUS 5
|
|
Ivan Mahonin |
b53a5c |
/* bonus if match occurs after a separator */
|
|
Ivan Mahonin |
b53a5c |
#define NK_SEPARATOR_BONUS 10
|
|
Ivan Mahonin |
b53a5c |
/* bonus if match is uppercase and prev is lower */
|
|
Ivan Mahonin |
b53a5c |
#define NK_CAMEL_BONUS 10
|
|
Ivan Mahonin |
b53a5c |
/* penalty applied for every letter in str before the first match */
|
|
Ivan Mahonin |
b53a5c |
#define NK_LEADING_LETTER_PENALTY (-3)
|
|
Ivan Mahonin |
b53a5c |
/* maximum penalty for leading letters */
|
|
Ivan Mahonin |
b53a5c |
#define NK_MAX_LEADING_LETTER_PENALTY (-9)
|
|
Ivan Mahonin |
b53a5c |
/* penalty for every letter that doesn't matter */
|
|
Ivan Mahonin |
b53a5c |
#define NK_UNMATCHED_LETTER_PENALTY (-1)
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* loop variables */
|
|
Ivan Mahonin |
b53a5c |
int score = 0;
|
|
Ivan Mahonin |
b53a5c |
char const * pattern_iter = pattern;
|
|
Ivan Mahonin |
b53a5c |
int str_iter = 0;
|
|
Ivan Mahonin |
b53a5c |
int prev_matched = nk_false;
|
|
Ivan Mahonin |
b53a5c |
int prev_lower = nk_false;
|
|
Ivan Mahonin |
b53a5c |
/* true so if first letter match gets separator bonus*/
|
|
Ivan Mahonin |
b53a5c |
int prev_separator = nk_true;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* use "best" matched letter if multiple string letters match the pattern */
|
|
Ivan Mahonin |
b53a5c |
char const * best_letter = 0;
|
|
Ivan Mahonin |
b53a5c |
int best_letter_score = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* loop over strings */
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(str);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(pattern);
|
|
Ivan Mahonin |
b53a5c |
if (!str || !str_len || !pattern) return 0;
|
|
Ivan Mahonin |
b53a5c |
while (str_iter < str_len)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
const char pattern_letter = *pattern_iter;
|
|
Ivan Mahonin |
b53a5c |
const char str_letter = str[str_iter];
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
int next_match = *pattern_iter != '\0' &&
|
|
Ivan Mahonin |
b53a5c |
nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
|
|
Ivan Mahonin |
b53a5c |
int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
int advanced = next_match && best_letter;
|
|
Ivan Mahonin |
b53a5c |
int pattern_repeat = best_letter && *pattern_iter != '\0';
|
|
Ivan Mahonin |
b53a5c |
pattern_repeat = pattern_repeat &&
|
|
Ivan Mahonin |
b53a5c |
nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (advanced || pattern_repeat) {
|
|
Ivan Mahonin |
b53a5c |
score += best_letter_score;
|
|
Ivan Mahonin |
b53a5c |
best_letter = 0;
|
|
Ivan Mahonin |
b53a5c |
best_letter_score = 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (next_match || rematch)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int new_score = 0;
|
|
Ivan Mahonin |
b53a5c |
/* Apply penalty for each letter before the first pattern match */
|
|
Ivan Mahonin |
b53a5c |
if (pattern_iter == pattern) {
|
|
Ivan Mahonin |
b53a5c |
int count = (int)(&str[str_iter] - str);
|
|
Ivan Mahonin |
b53a5c |
int penalty = NK_LEADING_LETTER_PENALTY * count;
|
|
Ivan Mahonin |
b53a5c |
if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
|
|
Ivan Mahonin |
b53a5c |
penalty = NK_MAX_LEADING_LETTER_PENALTY;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
score += penalty;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* apply bonus for consecutive bonuses */
|
|
Ivan Mahonin |
b53a5c |
if (prev_matched)
|
|
Ivan Mahonin |
b53a5c |
new_score += NK_ADJACENCY_BONUS;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* apply bonus for matches after a separator */
|
|
Ivan Mahonin |
b53a5c |
if (prev_separator)
|
|
Ivan Mahonin |
b53a5c |
new_score += NK_SEPARATOR_BONUS;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* apply bonus across camel case boundaries */
|
|
Ivan Mahonin |
b53a5c |
if (prev_lower && nk_is_upper(str_letter))
|
|
Ivan Mahonin |
b53a5c |
new_score += NK_CAMEL_BONUS;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* update pattern iter IFF the next pattern letter was matched */
|
|
Ivan Mahonin |
b53a5c |
if (next_match)
|
|
Ivan Mahonin |
b53a5c |
++pattern_iter;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* update best letter in str which may be for a "next" letter or a rematch */
|
|
Ivan Mahonin |
b53a5c |
if (new_score >= best_letter_score) {
|
|
Ivan Mahonin |
b53a5c |
/* apply penalty for now skipped letter */
|
|
Ivan Mahonin |
b53a5c |
if (best_letter != 0)
|
|
Ivan Mahonin |
b53a5c |
score += NK_UNMATCHED_LETTER_PENALTY;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
best_letter = &str[str_iter];
|
|
Ivan Mahonin |
b53a5c |
best_letter_score = new_score;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
prev_matched = nk_true;
|
|
Ivan Mahonin |
b53a5c |
} else {
|
|
Ivan Mahonin |
b53a5c |
score += NK_UNMATCHED_LETTER_PENALTY;
|
|
Ivan Mahonin |
b53a5c |
prev_matched = nk_false;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* separators should be more easily defined */
|
|
Ivan Mahonin |
b53a5c |
prev_lower = nk_is_lower(str_letter) != 0;
|
|
Ivan Mahonin |
b53a5c |
prev_separator = str_letter == '_' || str_letter == ' ';
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
++str_iter;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* apply score for last match */
|
|
Ivan Mahonin |
b53a5c |
if (best_letter)
|
|
Ivan Mahonin |
b53a5c |
score += best_letter_score;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* did not match full pattern */
|
|
Ivan Mahonin |
b53a5c |
if (*pattern_iter != '\0')
|
|
Ivan Mahonin |
b53a5c |
return nk_false;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (out_score)
|
|
Ivan Mahonin |
b53a5c |
*out_score = score;
|
|
Ivan Mahonin |
b53a5c |
return nk_true;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_API int
|
|
Ivan Mahonin |
b53a5c |
nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_LIB int
|
|
Ivan Mahonin |
b53a5c |
nk_string_float_limit(char *string, int prec)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int dot = 0;
|
|
Ivan Mahonin |
b53a5c |
char *c = string;
|
|
Ivan Mahonin |
b53a5c |
while (*c) {
|
|
Ivan Mahonin |
b53a5c |
if (*c == '.') {
|
|
Ivan Mahonin |
b53a5c |
dot = 1;
|
|
Ivan Mahonin |
b53a5c |
c++;
|
|
Ivan Mahonin |
b53a5c |
continue;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (dot == (prec+1)) {
|
|
Ivan Mahonin |
b53a5c |
*c = 0;
|
|
Ivan Mahonin |
b53a5c |
break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (dot > 0) dot++;
|
|
Ivan Mahonin |
b53a5c |
c++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
return (int)(c - string);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_INTERN void
|
|
Ivan Mahonin |
b53a5c |
nk_strrev_ascii(char *s)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int len = nk_strlen(s);
|
|
Ivan Mahonin |
b53a5c |
int end = len / 2;
|
|
Ivan Mahonin |
b53a5c |
int i = 0;
|
|
Ivan Mahonin |
b53a5c |
char t;
|
|
Ivan Mahonin |
b53a5c |
for (; i < end; ++i) {
|
|
Ivan Mahonin |
b53a5c |
t = s[i];
|
|
Ivan Mahonin |
b53a5c |
s[i] = s[len - 1 - i];
|
|
Ivan Mahonin |
b53a5c |
s[len -1 - i] = t;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_LIB char*
|
|
Ivan Mahonin |
b53a5c |
nk_itoa(char *s, long n)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
long i = 0;
|
|
Ivan Mahonin |
b53a5c |
if (n == 0) {
|
|
Ivan Mahonin |
b53a5c |
s[i++] = '0';
|
|
Ivan Mahonin |
b53a5c |
s[i] = 0;
|
|
Ivan Mahonin |
b53a5c |
return s;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (n < 0) {
|
|
Ivan Mahonin |
b53a5c |
s[i++] = '-';
|
|
Ivan Mahonin |
b53a5c |
n = -n;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
while (n > 0) {
|
|
Ivan Mahonin |
b53a5c |
s[i++] = (char)('0' + (n % 10));
|
|
Ivan Mahonin |
b53a5c |
n /= 10;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
s[i] = 0;
|
|
Ivan Mahonin |
b53a5c |
if (s[0] == '-')
|
|
Ivan Mahonin |
b53a5c |
++s;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
nk_strrev_ascii(s);
|
|
Ivan Mahonin |
b53a5c |
return s;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#ifndef NK_DTOA
|
|
Ivan Mahonin |
b53a5c |
#define NK_DTOA nk_dtoa
|
|
Ivan Mahonin |
b53a5c |
NK_LIB char*
|
|
Ivan Mahonin |
b53a5c |
nk_dtoa(char *s, double n)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int useExp = 0;
|
|
Ivan Mahonin |
b53a5c |
int digit = 0, m = 0, m1 = 0;
|
|
Ivan Mahonin |
b53a5c |
char *c = s;
|
|
Ivan Mahonin |
b53a5c |
int neg = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(s);
|
|
Ivan Mahonin |
b53a5c |
if (!s) return 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (n == 0.0) {
|
|
Ivan Mahonin |
b53a5c |
s[0] = '0'; s[1] = '\0';
|
|
Ivan Mahonin |
b53a5c |
return s;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
neg = (n < 0);
|
|
Ivan Mahonin |
b53a5c |
if (neg) n = -n;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* calculate magnitude */
|
|
Ivan Mahonin |
b53a5c |
m = nk_log10(n);
|
|
Ivan Mahonin |
b53a5c |
useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
|
|
Ivan Mahonin |
b53a5c |
if (neg) *(c++) = '-';
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* set up for scientific notation */
|
|
Ivan Mahonin |
b53a5c |
if (useExp) {
|
|
Ivan Mahonin |
b53a5c |
if (m < 0)
|
|
Ivan Mahonin |
b53a5c |
m -= 1;
|
|
Ivan Mahonin |
b53a5c |
n = n / (double)nk_pow(10.0, m);
|
|
Ivan Mahonin |
b53a5c |
m1 = m;
|
|
Ivan Mahonin |
b53a5c |
m = 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (m < 1.0) {
|
|
Ivan Mahonin |
b53a5c |
m = 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* convert the number */
|
|
Ivan Mahonin |
b53a5c |
while (n > NK_FLOAT_PRECISION || m >= 0) {
|
|
Ivan Mahonin |
b53a5c |
double weight = nk_pow(10.0, m);
|
|
Ivan Mahonin |
b53a5c |
if (weight > 0) {
|
|
Ivan Mahonin |
b53a5c |
double t = (double)n / weight;
|
|
Ivan Mahonin |
b53a5c |
digit = nk_ifloord(t);
|
|
Ivan Mahonin |
b53a5c |
n -= ((double)digit * weight);
|
|
Ivan Mahonin |
b53a5c |
*(c++) = (char)('0' + (char)digit);
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (m == 0 && n > 0)
|
|
Ivan Mahonin |
b53a5c |
*(c++) = '.';
|
|
Ivan Mahonin |
b53a5c |
m--;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (useExp) {
|
|
Ivan Mahonin |
b53a5c |
/* convert the exponent */
|
|
Ivan Mahonin |
b53a5c |
int i, j;
|
|
Ivan Mahonin |
b53a5c |
*(c++) = 'e';
|
|
Ivan Mahonin |
b53a5c |
if (m1 > 0) {
|
|
Ivan Mahonin |
b53a5c |
*(c++) = '+';
|
|
Ivan Mahonin |
b53a5c |
} else {
|
|
Ivan Mahonin |
b53a5c |
*(c++) = '-';
|
|
Ivan Mahonin |
b53a5c |
m1 = -m1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
m = 0;
|
|
Ivan Mahonin |
b53a5c |
while (m1 > 0) {
|
|
Ivan Mahonin |
b53a5c |
*(c++) = (char)('0' + (char)(m1 % 10));
|
|
Ivan Mahonin |
b53a5c |
m1 /= 10;
|
|
Ivan Mahonin |
b53a5c |
m++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
c -= m;
|
|
Ivan Mahonin |
b53a5c |
for (i = 0, j = m-1; i
|
|
Ivan Mahonin |
b53a5c |
/* swap without temporary */
|
|
Ivan Mahonin |
b53a5c |
c[i] ^= c[j];
|
|
Ivan Mahonin |
b53a5c |
c[j] ^= c[i];
|
|
Ivan Mahonin |
b53a5c |
c[i] ^= c[j];
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
c += m;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
*(c) = '\0';
|
|
Ivan Mahonin |
b53a5c |
return s;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
#ifdef NK_INCLUDE_STANDARD_VARARGS
|
|
Ivan Mahonin |
b53a5c |
#ifndef NK_INCLUDE_STANDARD_IO
|
|
Ivan Mahonin |
b53a5c |
NK_INTERN int
|
|
Ivan Mahonin |
b53a5c |
nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
enum nk_arg_type {
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_TYPE_CHAR,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_TYPE_SHORT,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_TYPE_DEFAULT,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_TYPE_LONG
|
|
Ivan Mahonin |
b53a5c |
};
|
|
Ivan Mahonin |
b53a5c |
enum nk_arg_flags {
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_FLAG_LEFT = 0x01,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_FLAG_PLUS = 0x02,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_FLAG_SPACE = 0x04,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_FLAG_NUM = 0x10,
|
|
Ivan Mahonin |
b53a5c |
NK_ARG_FLAG_ZERO = 0x20
|
|
Ivan Mahonin |
b53a5c |
};
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
char number_buffer[NK_MAX_NUMBER_BUFFER];
|
|
Ivan Mahonin |
b53a5c |
enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
|
|
Ivan Mahonin |
b53a5c |
int precision = NK_DEFAULT;
|
|
Ivan Mahonin |
b53a5c |
int width = NK_DEFAULT;
|
|
Ivan Mahonin |
b53a5c |
nk_flags flag = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
int len = 0;
|
|
Ivan Mahonin |
b53a5c |
int result = -1;
|
|
Ivan Mahonin |
b53a5c |
const char *iter = fmt;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(buf);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(buf_size);
|
|
Ivan Mahonin |
b53a5c |
if (!buf || !buf_size || !fmt) return 0;
|
|
Ivan Mahonin |
b53a5c |
for (iter = fmt; *iter && len < buf_size; iter++) {
|
|
Ivan Mahonin |
b53a5c |
/* copy all non-format characters */
|
|
Ivan Mahonin |
b53a5c |
while (*iter && (*iter != '%') && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = *iter++;
|
|
Ivan Mahonin |
b53a5c |
if (!(*iter) || len >= buf_size) break;
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* flag arguments */
|
|
Ivan Mahonin |
b53a5c |
while (*iter) {
|
|
Ivan Mahonin |
b53a5c |
if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
|
|
Ivan Mahonin |
b53a5c |
else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
|
|
Ivan Mahonin |
b53a5c |
else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
|
|
Ivan Mahonin |
b53a5c |
else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
|
|
Ivan Mahonin |
b53a5c |
else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
|
|
Ivan Mahonin |
b53a5c |
else break;
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* width argument */
|
|
Ivan Mahonin |
b53a5c |
width = NK_DEFAULT;
|
|
Ivan Mahonin |
b53a5c |
if (*iter >= '1' && *iter <= '9') {
|
|
Ivan Mahonin |
b53a5c |
const char *end;
|
|
Ivan Mahonin |
b53a5c |
width = nk_strtoi(iter, &end);
|
|
Ivan Mahonin |
b53a5c |
if (end == iter)
|
|
Ivan Mahonin |
b53a5c |
width = -1;
|
|
Ivan Mahonin |
b53a5c |
else iter = end;
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == '*') {
|
|
Ivan Mahonin |
b53a5c |
width = va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* precision argument */
|
|
Ivan Mahonin |
b53a5c |
precision = NK_DEFAULT;
|
|
Ivan Mahonin |
b53a5c |
if (*iter == '.') {
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
if (*iter == '*') {
|
|
Ivan Mahonin |
b53a5c |
precision = va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
} else {
|
|
Ivan Mahonin |
b53a5c |
const char *end;
|
|
Ivan Mahonin |
b53a5c |
precision = nk_strtoi(iter, &end);
|
|
Ivan Mahonin |
b53a5c |
if (end == iter)
|
|
Ivan Mahonin |
b53a5c |
precision = -1;
|
|
Ivan Mahonin |
b53a5c |
else iter = end;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* length modifier */
|
|
Ivan Mahonin |
b53a5c |
if (*iter == 'h') {
|
|
Ivan Mahonin |
b53a5c |
if (*(iter+1) == 'h') {
|
|
Ivan Mahonin |
b53a5c |
arg_type = NK_ARG_TYPE_CHAR;
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
} else arg_type = NK_ARG_TYPE_SHORT;
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == 'l') {
|
|
Ivan Mahonin |
b53a5c |
arg_type = NK_ARG_TYPE_LONG;
|
|
Ivan Mahonin |
b53a5c |
iter++;
|
|
Ivan Mahonin |
b53a5c |
} else arg_type = NK_ARG_TYPE_DEFAULT;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* specifier */
|
|
Ivan Mahonin |
b53a5c |
if (*iter == '%') {
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(precision == NK_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(width == NK_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
if (len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '%';
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == 's') {
|
|
Ivan Mahonin |
b53a5c |
/* string */
|
|
Ivan Mahonin |
b53a5c |
const char *str = va_arg(args, const char*);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(precision == NK_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(width == NK_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
if (str == buf) return -1;
|
|
Ivan Mahonin |
b53a5c |
while (str && *str && len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = *str++;
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == 'n') {
|
|
Ivan Mahonin |
b53a5c |
/* current length callback */
|
|
Ivan Mahonin |
b53a5c |
signed int *n = va_arg(args, int*);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(precision == NK_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(width == NK_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
if (n) *n = len;
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
|
|
Ivan Mahonin |
b53a5c |
/* signed integer */
|
|
Ivan Mahonin |
b53a5c |
long value = 0;
|
|
Ivan Mahonin |
b53a5c |
const char *num_iter;
|
|
Ivan Mahonin |
b53a5c |
int num_len, num_print, padding;
|
|
Ivan Mahonin |
b53a5c |
int cur_precision = NK_MAX(precision, 1);
|
|
Ivan Mahonin |
b53a5c |
int cur_width = NK_MAX(width, 0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* retrieve correct value type */
|
|
Ivan Mahonin |
b53a5c |
if (arg_type == NK_ARG_TYPE_CHAR)
|
|
Ivan Mahonin |
b53a5c |
value = (signed char)va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
else if (arg_type == NK_ARG_TYPE_SHORT)
|
|
Ivan Mahonin |
b53a5c |
value = (signed short)va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
else if (arg_type == NK_ARG_TYPE_LONG)
|
|
Ivan Mahonin |
b53a5c |
value = va_arg(args, signed long);
|
|
Ivan Mahonin |
b53a5c |
else if (*iter == 'c')
|
|
Ivan Mahonin |
b53a5c |
value = (unsigned char)va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
else value = va_arg(args, signed int);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* convert number to string */
|
|
Ivan Mahonin |
b53a5c |
nk_itoa(number_buffer, value);
|
|
Ivan Mahonin |
b53a5c |
num_len = nk_strlen(number_buffer);
|
|
Ivan Mahonin |
b53a5c |
padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
|
|
Ivan Mahonin |
b53a5c |
if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
|
|
Ivan Mahonin |
b53a5c |
padding = NK_MAX(padding-1, 0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill left padding up to a total of `width` characters */
|
|
Ivan Mahonin |
b53a5c |
if (!(flag & NK_ARG_FLAG_LEFT)) {
|
|
Ivan Mahonin |
b53a5c |
while (padding-- > 0 && (len < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
else buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* copy string value representation into buffer */
|
|
Ivan Mahonin |
b53a5c |
if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '+';
|
|
Ivan Mahonin |
b53a5c |
else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill up to precision number of digits with '0' */
|
|
Ivan Mahonin |
b53a5c |
num_print = NK_MAX(cur_precision, num_len);
|
|
Ivan Mahonin |
b53a5c |
while (precision && (num_print > num_len) && (len < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
num_print--;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* copy string value representation into buffer */
|
|
Ivan Mahonin |
b53a5c |
num_iter = number_buffer;
|
|
Ivan Mahonin |
b53a5c |
while (precision && *num_iter && len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = *num_iter++;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill right padding up to width characters */
|
|
Ivan Mahonin |
b53a5c |
if (flag & NK_ARG_FLAG_LEFT) {
|
|
Ivan Mahonin |
b53a5c |
while ((padding-- > 0) && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
|
|
Ivan Mahonin |
b53a5c |
/* unsigned integer */
|
|
Ivan Mahonin |
b53a5c |
unsigned long value = 0;
|
|
Ivan Mahonin |
b53a5c |
int num_len = 0, num_print, padding = 0;
|
|
Ivan Mahonin |
b53a5c |
int cur_precision = NK_MAX(precision, 1);
|
|
Ivan Mahonin |
b53a5c |
int cur_width = NK_MAX(width, 0);
|
|
Ivan Mahonin |
b53a5c |
unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* print oct/hex/dec value */
|
|
Ivan Mahonin |
b53a5c |
const char *upper_output_format = "0123456789ABCDEF";
|
|
Ivan Mahonin |
b53a5c |
const char *lower_output_format = "0123456789abcdef";
|
|
Ivan Mahonin |
b53a5c |
const char *output_format = (*iter == 'x') ?
|
|
Ivan Mahonin |
b53a5c |
lower_output_format: upper_output_format;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* retrieve correct value type */
|
|
Ivan Mahonin |
b53a5c |
if (arg_type == NK_ARG_TYPE_CHAR)
|
|
Ivan Mahonin |
b53a5c |
value = (unsigned char)va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
else if (arg_type == NK_ARG_TYPE_SHORT)
|
|
Ivan Mahonin |
b53a5c |
value = (unsigned short)va_arg(args, int);
|
|
Ivan Mahonin |
b53a5c |
else if (arg_type == NK_ARG_TYPE_LONG)
|
|
Ivan Mahonin |
b53a5c |
value = va_arg(args, unsigned long);
|
|
Ivan Mahonin |
b53a5c |
else value = va_arg(args, unsigned int);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
do {
|
|
Ivan Mahonin |
b53a5c |
/* convert decimal number into hex/oct number */
|
|
Ivan Mahonin |
b53a5c |
int digit = output_format[value % base];
|
|
Ivan Mahonin |
b53a5c |
if (num_len < NK_MAX_NUMBER_BUFFER)
|
|
Ivan Mahonin |
b53a5c |
number_buffer[num_len++] = (char)digit;
|
|
Ivan Mahonin |
b53a5c |
value /= base;
|
|
Ivan Mahonin |
b53a5c |
} while (value > 0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
num_print = NK_MAX(cur_precision, num_len);
|
|
Ivan Mahonin |
b53a5c |
padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
|
|
Ivan Mahonin |
b53a5c |
if (flag & NK_ARG_FLAG_NUM)
|
|
Ivan Mahonin |
b53a5c |
padding = NK_MAX(padding-1, 0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill left padding up to a total of `width` characters */
|
|
Ivan Mahonin |
b53a5c |
if (!(flag & NK_ARG_FLAG_LEFT)) {
|
|
Ivan Mahonin |
b53a5c |
while ((padding-- > 0) && (len < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
else buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill up to precision number of digits */
|
|
Ivan Mahonin |
b53a5c |
if (num_print && (flag & NK_ARG_FLAG_NUM)) {
|
|
Ivan Mahonin |
b53a5c |
if ((*iter == 'o') && (len < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
} else if ((*iter == 'x') && ((len+1) < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = 'x';
|
|
Ivan Mahonin |
b53a5c |
} else if ((*iter == 'X') && ((len+1) < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = 'X';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
while (precision && (num_print > num_len) && (len < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
num_print--;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* reverse number direction */
|
|
Ivan Mahonin |
b53a5c |
while (num_len > 0) {
|
|
Ivan Mahonin |
b53a5c |
if (precision && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = number_buffer[num_len-1];
|
|
Ivan Mahonin |
b53a5c |
num_len--;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill right padding up to width characters */
|
|
Ivan Mahonin |
b53a5c |
if (flag & NK_ARG_FLAG_LEFT) {
|
|
Ivan Mahonin |
b53a5c |
while ((padding-- > 0) && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
} else if (*iter == 'f') {
|
|
Ivan Mahonin |
b53a5c |
/* floating point */
|
|
Ivan Mahonin |
b53a5c |
const char *num_iter;
|
|
Ivan Mahonin |
b53a5c |
int cur_precision = (precision < 0) ? 6: precision;
|
|
Ivan Mahonin |
b53a5c |
int prefix, cur_width = NK_MAX(width, 0);
|
|
Ivan Mahonin |
b53a5c |
double value = va_arg(args, double);
|
|
Ivan Mahonin |
b53a5c |
int num_len = 0, frac_len = 0, dot = 0;
|
|
Ivan Mahonin |
b53a5c |
int padding = 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
|
|
Ivan Mahonin |
b53a5c |
NK_DTOA(number_buffer, value);
|
|
Ivan Mahonin |
b53a5c |
num_len = nk_strlen(number_buffer);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* calculate padding */
|
|
Ivan Mahonin |
b53a5c |
num_iter = number_buffer;
|
|
Ivan Mahonin |
b53a5c |
while (*num_iter && *num_iter != '.')
|
|
Ivan Mahonin |
b53a5c |
num_iter++;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
|
|
Ivan Mahonin |
b53a5c |
padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
|
|
Ivan Mahonin |
b53a5c |
if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
|
|
Ivan Mahonin |
b53a5c |
padding = NK_MAX(padding-1, 0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill left padding up to a total of `width` characters */
|
|
Ivan Mahonin |
b53a5c |
if (!(flag & NK_ARG_FLAG_LEFT)) {
|
|
Ivan Mahonin |
b53a5c |
while (padding-- > 0 && (len < buf_size)) {
|
|
Ivan Mahonin |
b53a5c |
if (flag & NK_ARG_FLAG_ZERO)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
else buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* copy string value representation into buffer */
|
|
Ivan Mahonin |
b53a5c |
num_iter = number_buffer;
|
|
Ivan Mahonin |
b53a5c |
if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '+';
|
|
Ivan Mahonin |
b53a5c |
else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
while (*num_iter) {
|
|
Ivan Mahonin |
b53a5c |
if (dot) frac_len++;
|
|
Ivan Mahonin |
b53a5c |
if (len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = *num_iter;
|
|
Ivan Mahonin |
b53a5c |
if (*num_iter == '.') dot = 1;
|
|
Ivan Mahonin |
b53a5c |
if (frac_len >= cur_precision) break;
|
|
Ivan Mahonin |
b53a5c |
num_iter++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill number up to precision */
|
|
Ivan Mahonin |
b53a5c |
while (frac_len < cur_precision) {
|
|
Ivan Mahonin |
b53a5c |
if (!dot && len < buf_size) {
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '.';
|
|
Ivan Mahonin |
b53a5c |
dot = 1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (len < buf_size)
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = '0';
|
|
Ivan Mahonin |
b53a5c |
frac_len++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* fill right padding up to width characters */
|
|
Ivan Mahonin |
b53a5c |
if (flag & NK_ARG_FLAG_LEFT) {
|
|
Ivan Mahonin |
b53a5c |
while ((padding-- > 0) && (len < buf_size))
|
|
Ivan Mahonin |
b53a5c |
buf[len++] = ' ';
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
} else {
|
|
Ivan Mahonin |
b53a5c |
/* Specifier not supported: g,G,e,E,p,z */
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(0 && "specifier is not supported!");
|
|
Ivan Mahonin |
b53a5c |
return result;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
buf[(len >= buf_size)?(buf_size-1):len] = 0;
|
|
Ivan Mahonin |
b53a5c |
result = (len >= buf_size)?-1:len;
|
|
Ivan Mahonin |
b53a5c |
return result;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
NK_LIB int
|
|
Ivan Mahonin |
b53a5c |
nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int result = -1;
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(buf);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(buf_size);
|
|
Ivan Mahonin |
b53a5c |
if (!buf || !buf_size || !fmt) return 0;
|
|
Ivan Mahonin |
b53a5c |
#ifdef NK_INCLUDE_STANDARD_IO
|
|
Ivan Mahonin |
b53a5c |
result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
|
|
Ivan Mahonin |
b53a5c |
result = (result >= buf_size) ? -1: result;
|
|
Ivan Mahonin |
b53a5c |
buf[buf_size-1] = 0;
|
|
Ivan Mahonin |
b53a5c |
#else
|
|
Ivan Mahonin |
b53a5c |
result = nk_vsnprintf(buf, buf_size, fmt, args);
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
return result;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
NK_API nk_hash
|
|
Ivan Mahonin |
b53a5c |
nk_murmur_hash(const void * key, int len, nk_hash seed)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
/* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
|
|
Ivan Mahonin |
b53a5c |
#define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
nk_uint h1 = seed;
|
|
Ivan Mahonin |
b53a5c |
nk_uint k1;
|
|
Ivan Mahonin |
b53a5c |
const nk_byte *data = (const nk_byte*)key;
|
|
Ivan Mahonin |
b53a5c |
const nk_byte *keyptr = data;
|
|
Ivan Mahonin |
b53a5c |
nk_byte *k1ptr;
|
|
Ivan Mahonin |
b53a5c |
const int bsize = sizeof(k1);
|
|
Ivan Mahonin |
b53a5c |
const int nblocks = len/4;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
const nk_uint c1 = 0xcc9e2d51;
|
|
Ivan Mahonin |
b53a5c |
const nk_uint c2 = 0x1b873593;
|
|
Ivan Mahonin |
b53a5c |
const nk_byte *tail;
|
|
Ivan Mahonin |
b53a5c |
int i;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* body */
|
|
Ivan Mahonin |
b53a5c |
if (!key) return 0;
|
|
Ivan Mahonin |
b53a5c |
for (i = 0; i < nblocks; ++i, keyptr += bsize) {
|
|
Ivan Mahonin |
b53a5c |
k1ptr = (nk_byte*)&k1;
|
|
Ivan Mahonin |
b53a5c |
k1ptr[0] = keyptr[0];
|
|
Ivan Mahonin |
b53a5c |
k1ptr[1] = keyptr[1];
|
|
Ivan Mahonin |
b53a5c |
k1ptr[2] = keyptr[2];
|
|
Ivan Mahonin |
b53a5c |
k1ptr[3] = keyptr[3];
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
k1 *= c1;
|
|
Ivan Mahonin |
b53a5c |
k1 = NK_ROTL(k1,15);
|
|
Ivan Mahonin |
b53a5c |
k1 *= c2;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
h1 ^= k1;
|
|
Ivan Mahonin |
b53a5c |
h1 = NK_ROTL(h1,13);
|
|
Ivan Mahonin |
b53a5c |
h1 = h1*5+0xe6546b64;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* tail */
|
|
Ivan Mahonin |
b53a5c |
tail = (const nk_byte*)(data + nblocks*4);
|
|
Ivan Mahonin |
b53a5c |
k1 = 0;
|
|
Ivan Mahonin |
b53a5c |
switch (len & 3) {
|
|
Ivan Mahonin |
b53a5c |
case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
|
|
Ivan Mahonin |
b53a5c |
case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
|
|
Ivan Mahonin |
b53a5c |
case 1: k1 ^= tail[0];
|
|
Ivan Mahonin |
b53a5c |
k1 *= c1;
|
|
Ivan Mahonin |
b53a5c |
k1 = NK_ROTL(k1,15);
|
|
Ivan Mahonin |
b53a5c |
k1 *= c2;
|
|
Ivan Mahonin |
b53a5c |
h1 ^= k1;
|
|
Ivan Mahonin |
b53a5c |
break;
|
|
Ivan Mahonin |
b53a5c |
default: break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/* finalization */
|
|
Ivan Mahonin |
b53a5c |
h1 ^= (nk_uint)len;
|
|
Ivan Mahonin |
b53a5c |
/* fmix32 */
|
|
Ivan Mahonin |
b53a5c |
h1 ^= h1 >> 16;
|
|
Ivan Mahonin |
b53a5c |
h1 *= 0x85ebca6b;
|
|
Ivan Mahonin |
b53a5c |
h1 ^= h1 >> 13;
|
|
Ivan Mahonin |
b53a5c |
h1 *= 0xc2b2ae35;
|
|
Ivan Mahonin |
b53a5c |
h1 ^= h1 >> 16;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
#undef NK_ROTL
|
|
Ivan Mahonin |
b53a5c |
return h1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#ifdef NK_INCLUDE_STANDARD_IO
|
|
Ivan Mahonin |
b53a5c |
NK_LIB char*
|
|
Ivan Mahonin |
b53a5c |
nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
char *buf;
|
|
Ivan Mahonin |
b53a5c |
FILE *fd;
|
|
Ivan Mahonin |
b53a5c |
long ret;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(path);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(siz);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(alloc);
|
|
Ivan Mahonin |
b53a5c |
if (!path || !siz || !alloc)
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
fd = fopen(path, "rb");
|
|
Ivan Mahonin |
b53a5c |
if (!fd) return 0;
|
|
Ivan Mahonin |
b53a5c |
fseek(fd, 0, SEEK_END);
|
|
Ivan Mahonin |
b53a5c |
ret = ftell(fd);
|
|
Ivan Mahonin |
b53a5c |
if (ret < 0) {
|
|
Ivan Mahonin |
b53a5c |
fclose(fd);
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
*siz = (nk_size)ret;
|
|
Ivan Mahonin |
b53a5c |
fseek(fd, 0, SEEK_SET);
|
|
Ivan Mahonin |
b53a5c |
buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
|
|
Ivan Mahonin |
b53a5c |
NK_ASSERT(buf);
|
|
Ivan Mahonin |
b53a5c |
if (!buf) {
|
|
Ivan Mahonin |
b53a5c |
fclose(fd);
|
|
Ivan Mahonin |
b53a5c |
return 0;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
*siz = (nk_size)fread(buf, 1,*siz, fd);
|
|
Ivan Mahonin |
b53a5c |
fclose(fd);
|
|
Ivan Mahonin |
b53a5c |
return buf;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
#endif
|
|
Ivan Mahonin |
b53a5c |
NK_LIB int
|
|
Ivan Mahonin |
b53a5c |
nk_text_clamp(const struct nk_user_font *font, const char *text,
|
|
Ivan Mahonin |
b53a5c |
int text_len, float space, int *glyphs, float *text_width,
|
|
Ivan Mahonin |
b53a5c |
nk_rune *sep_list, int sep_count)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
int i = 0;
|
|
Ivan Mahonin |
b53a5c |
int glyph_len = 0;
|
|
Ivan Mahonin |
b53a5c |
float last_width = 0;
|
|
Ivan Mahonin |
b53a5c |
nk_rune unicode = 0;
|
|
Ivan Mahonin |
b53a5c |
float width = 0;
|
|
Ivan Mahonin |
b53a5c |
int len = 0;
|
|
Ivan Mahonin |
b53a5c |
int g = 0;
|
|
Ivan Mahonin |
b53a5c |
float s;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
int sep_len = 0;
|
|
Ivan Mahonin |
b53a5c |
int sep_g = 0;
|
|
Ivan Mahonin |
b53a5c |
float sep_width = 0;
|
|
Ivan Mahonin |
b53a5c |
sep_count = NK_MAX(sep_count,0);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
glyph_len = nk_utf_decode(text, &unicode, text_len);
|
|
Ivan Mahonin |
b53a5c |
while (glyph_len && (width < space) && (len < text_len)) {
|
|
Ivan Mahonin |
b53a5c |
len += glyph_len;
|
|
Ivan Mahonin |
b53a5c |
s = font->width(font->userdata, font->height, text, len);
|
|
Ivan Mahonin |
b53a5c |
for (i = 0; i < sep_count; ++i) {
|
|
Ivan Mahonin |
b53a5c |
if (unicode != sep_list[i]) continue;
|
|
Ivan Mahonin |
b53a5c |
sep_width = last_width = width;
|
|
Ivan Mahonin |
b53a5c |
sep_g = g+1;
|
|
Ivan Mahonin |
b53a5c |
sep_len = len;
|
|
Ivan Mahonin |
b53a5c |
break;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (i == sep_count){
|
|
Ivan Mahonin |
b53a5c |
last_width = sep_width = width;
|
|
Ivan Mahonin |
b53a5c |
sep_g = g+1;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
width = s;
|
|
Ivan Mahonin |
b53a5c |
glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
|
|
Ivan Mahonin |
b53a5c |
g++;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
if (len >= text_len) {
|
|
Ivan Mahonin |
b53a5c |
*glyphs = g;
|
|
Ivan Mahonin |
b53a5c |
*text_width = last_width;
|
|
Ivan Mahonin |
b53a5c |
return len;
|
|
Ivan Mahonin |
b53a5c |
} else {
|
|
Ivan Mahonin |
b53a5c |
*glyphs = sep_g;
|
|
Ivan Mahonin |
b53a5c |
*text_width = sep_width;
|
|
Ivan Mahonin |
b53a5c |
return (!sep_len) ? len: sep_len;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
NK_LIB struct nk_vec2
|
|
Ivan Mahonin |
b53a5c |
nk_text_calculate_text_bounds(const struct nk_user_font *font,
|
|
Ivan Mahonin |
b53a5c |
const char *begin, int byte_len, float row_height, const char **remaining,
|
|
Ivan Mahonin |
b53a5c |
struct nk_vec2 *out_offset, int *glyphs, int op)
|
|
Ivan Mahonin |
b53a5c |
{
|
|
Ivan Mahonin |
b53a5c |
float line_height = row_height;
|
|
Ivan Mahonin |
b53a5c |
struct nk_vec2 text_size = nk_vec2(0,0);
|
|
Ivan Mahonin |
b53a5c |
float line_width = 0.0f;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
float glyph_width;
|
|
Ivan Mahonin |
b53a5c |
int glyph_len = 0;
|
|
Ivan Mahonin |
b53a5c |
nk_rune unicode = 0;
|
|
Ivan Mahonin |
b53a5c |
int text_len = 0;
|
|
Ivan Mahonin |
b53a5c |
if (!begin || byte_len <= 0 || !font)
|
|
Ivan Mahonin |
b53a5c |
return nk_vec2(0,row_height);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
glyph_len = nk_utf_decode(begin, &unicode, byte_len);
|
|
Ivan Mahonin |
b53a5c |
if (!glyph_len) return text_size;
|
|
Ivan Mahonin |
b53a5c |
glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
*glyphs = 0;
|
|
Ivan Mahonin |
b53a5c |
while ((text_len < byte_len) && glyph_len) {
|
|
Ivan Mahonin |
b53a5c |
if (unicode == '\n') {
|
|
Ivan Mahonin |
b53a5c |
text_size.x = NK_MAX(text_size.x, line_width);
|
|
Ivan Mahonin |
b53a5c |
text_size.y += line_height;
|
|
Ivan Mahonin |
b53a5c |
line_width = 0;
|
|
Ivan Mahonin |
b53a5c |
*glyphs+=1;
|
|
Ivan Mahonin |
b53a5c |
if (op == NK_STOP_ON_NEW_LINE)
|
|
Ivan Mahonin |
b53a5c |
break;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
text_len++;
|
|
Ivan Mahonin |
b53a5c |
glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
|
|
Ivan Mahonin |
b53a5c |
continue;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (unicode == '\r') {
|
|
Ivan Mahonin |
b53a5c |
text_len++;
|
|
Ivan Mahonin |
b53a5c |
*glyphs+=1;
|
|
Ivan Mahonin |
b53a5c |
glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
|
|
Ivan Mahonin |
b53a5c |
continue;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
*glyphs = *glyphs + 1;
|
|
Ivan Mahonin |
b53a5c |
text_len += glyph_len;
|
|
Ivan Mahonin |
b53a5c |
line_width += (float)glyph_width;
|
|
Ivan Mahonin |
b53a5c |
glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
|
|
Ivan Mahonin |
b53a5c |
glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
|
|
Ivan Mahonin |
b53a5c |
continue;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if (text_size.x < line_width)
|
|
Ivan Mahonin |
b53a5c |
text_size.x = line_width;
|
|
Ivan Mahonin |
b53a5c |
if (out_offset)
|
|
Ivan Mahonin |
b53a5c |
*out_offset = nk_vec2(line_width, text_size.y + line_height);
|
|
Ivan Mahonin |
b53a5c |
if (line_width > 0 || text_size.y == 0.0f)
|
|
Ivan Mahonin |
b53a5c |
text_size.y += line_height;
|
|
Ivan Mahonin |
b53a5c |
if (remaining)
|
|
Ivan Mahonin |
b53a5c |
*remaining = begin+text_len;
|
|
Ivan Mahonin |
b53a5c |
return text_size;
|
|
Ivan Mahonin |
b53a5c |
}
|
|
Ivan Mahonin |
b53a5c |
|