2016-10-17 08:57:44 -07:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
2017-03-12 13:34:21 -07:00
|
|
|
// Copyright © 2016-2017 Project Golan
|
2016-10-17 08:57:44 -07:00
|
|
|
//
|
2017-03-12 13:34:21 -07:00
|
|
|
// See "LICENSE.lithos3" for more information.
|
2016-10-17 08:57:44 -07:00
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Miscallaneous library functions.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2017-03-12 13:55:50 -07:00
|
|
|
#include "Lth_libinfo.h"
|
|
|
|
|
|
|
|
#if !LITHOS3_NO_STDLIB
|
|
|
|
|
2016-10-17 08:57:44 -07:00
|
|
|
#include "Lth.h"
|
|
|
|
|
2017-03-12 13:34:21 -07:00
|
|
|
#include <GDCC.h>
|
2016-10-21 11:49:11 -07:00
|
|
|
|
2016-10-17 08:57:44 -07:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2016-10-23 18:20:09 -07:00
|
|
|
#include <ctype.h>
|
2017-03-12 13:34:21 -07:00
|
|
|
#include <stdfix.h>
|
|
|
|
#include <ACS_ZDoom.h>
|
2016-10-21 14:55:00 -07:00
|
|
|
|
2016-10-17 08:57:44 -07:00
|
|
|
|
2016-10-18 14:20:32 -07:00
|
|
|
// Extern Functions ----------------------------------------------------------|
|
2016-10-17 08:57:44 -07:00
|
|
|
|
2016-10-21 11:49:11 -07:00
|
|
|
//
|
|
|
|
// Lth_fpeekc
|
|
|
|
//
|
|
|
|
int Lth_fpeekc(FILE *fp)
|
|
|
|
{
|
|
|
|
int ret = fgetc(fp);
|
|
|
|
ungetc(ret, fp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-17 08:57:44 -07:00
|
|
|
//
|
|
|
|
// Lth_strdup
|
|
|
|
//
|
|
|
|
// Duplicates a string, allocating a new one.
|
|
|
|
//
|
|
|
|
char *Lth_strdup(char const *s)
|
|
|
|
{
|
|
|
|
size_t len = strlen(s);
|
2017-03-12 13:34:21 -07:00
|
|
|
char *ret = malloc(len + 1);
|
2016-11-20 22:03:52 -08:00
|
|
|
memmove(ret, s, len);
|
2016-10-21 11:49:11 -07:00
|
|
|
ret[len] = '\0';
|
2016-10-17 08:57:44 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-18 10:44:22 -07:00
|
|
|
//
|
|
|
|
// Lth_strdup_str
|
|
|
|
//
|
2016-10-19 07:00:10 -07:00
|
|
|
// Duplicates a string entity, allocating a new string.
|
|
|
|
//
|
|
|
|
char *Lth_strdup_str(__str s)
|
|
|
|
{
|
|
|
|
size_t len = ACS_StrLen(s);
|
2017-03-12 13:34:21 -07:00
|
|
|
char *ret = malloc(len + 1);
|
2016-10-21 11:49:11 -07:00
|
|
|
ACS_StrArsCpyToGlobalCharRange((int)ret, __GDCC__Sta, 0, len, s);
|
|
|
|
ret[len] = '\0';
|
2016-10-19 07:00:10 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_strentdup
|
|
|
|
//
|
2016-10-18 10:44:22 -07:00
|
|
|
// Duplicates a string into a new string entity.
|
|
|
|
//
|
2016-10-19 07:00:10 -07:00
|
|
|
__str Lth_strentdup(char const *s)
|
2016-10-18 10:44:22 -07:00
|
|
|
{
|
|
|
|
ACS_BeginPrint();
|
|
|
|
Lth_PrintString(s);
|
|
|
|
return ACS_EndStrParam();
|
|
|
|
}
|
|
|
|
|
2016-10-19 07:00:10 -07:00
|
|
|
//
|
|
|
|
// Lth_strlocal
|
|
|
|
//
|
|
|
|
__str Lth_strlocal(__str s)
|
|
|
|
{
|
|
|
|
ACS_BeginPrint();
|
|
|
|
ACS_PrintLocalized(s);
|
|
|
|
return ACS_EndStrParam();
|
|
|
|
}
|
|
|
|
|
2016-10-21 11:49:11 -07:00
|
|
|
//
|
|
|
|
// Lth_strealoc
|
|
|
|
//
|
|
|
|
// Reallocates a string and replaces its contents.
|
|
|
|
//
|
|
|
|
char *Lth_strealoc(char *p, char const *s)
|
|
|
|
{
|
|
|
|
size_t len = strlen(s);
|
|
|
|
p = realloc(p, len + 1);
|
2016-11-20 22:03:52 -08:00
|
|
|
memmove(p, s, len);
|
2016-10-21 11:49:11 -07:00
|
|
|
p[len] = '\0';
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_strealoc_str
|
|
|
|
//
|
|
|
|
char *Lth_strealoc_str(char *p, __str s)
|
|
|
|
{
|
|
|
|
size_t len = ACS_StrLen(s);
|
|
|
|
p = realloc(p, len + 1);
|
|
|
|
ACS_StrArsCpyToGlobalCharRange((int)p, __GDCC__Sta, 0, len, s);
|
|
|
|
p[len] = '\0';
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_strcontains
|
|
|
|
//
|
|
|
|
bool Lth_strcontains(char const *s, char ch)
|
|
|
|
{
|
|
|
|
for(; *s; s++) if(*s == ch) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-23 18:20:09 -07:00
|
|
|
//
|
|
|
|
// Lth_stricmp
|
|
|
|
//
|
|
|
|
int Lth_stricmp(char const *s1, char const *s2)
|
|
|
|
{
|
2017-03-12 13:34:21 -07:00
|
|
|
for(; *s1 && *s2; s1++, s2++)
|
|
|
|
if(toupper(*s1) != toupper(*s2))
|
2016-10-23 18:20:09 -07:00
|
|
|
break;
|
2017-03-12 13:34:21 -07:00
|
|
|
|
|
|
|
return (int)toupper(*s1) - (int)toupper(*s2);
|
2016-10-23 18:20:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_wcsdup
|
|
|
|
//
|
|
|
|
wchar_t *Lth_wcsdup(wchar_t const *s)
|
|
|
|
{
|
|
|
|
size_t len = wcslen(s);
|
|
|
|
wchar_t *ret = malloc(sizeof(wchar_t) * (len + 1));
|
2016-11-20 22:03:52 -08:00
|
|
|
wmemmove(ret, s, len);
|
2016-10-23 18:20:09 -07:00
|
|
|
ret[len] = '\0';
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_wcsdupstr
|
|
|
|
//
|
|
|
|
wchar_t *Lth_wcsdupstr(char const *s)
|
|
|
|
{
|
|
|
|
size_t len = strlen(s);
|
|
|
|
wchar_t *ret = malloc(sizeof(wchar_t) * (len + 1));
|
|
|
|
for(size_t i = 0; i < len; i++) ret[i] = s[i];
|
|
|
|
ret[len] = '\0';
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_mbslen
|
|
|
|
//
|
|
|
|
size_t Lth_mbslen(char const *s)
|
|
|
|
{
|
|
|
|
size_t ret = 0;
|
|
|
|
|
|
|
|
Lth_WithMbState()
|
|
|
|
for(char const *end = s + strlen(s); s < end; ret++)
|
|
|
|
{
|
|
|
|
int next = mbrlen(s, end - s, &state);
|
|
|
|
if(next < 0)
|
|
|
|
return ret;
|
|
|
|
s += next;
|
|
|
|
}
|
2016-11-20 22:03:52 -08:00
|
|
|
|
2016-10-23 18:20:09 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-11-20 22:03:52 -08:00
|
|
|
//
|
|
|
|
// Lth_ceilk
|
|
|
|
//
|
2017-03-12 13:34:21 -07:00
|
|
|
int Lth_ceilk(accum n)
|
2016-11-20 22:03:52 -08:00
|
|
|
{
|
2017-03-12 13:34:21 -07:00
|
|
|
union {int_k_t i; accum a;} u = {.a = n};
|
2016-11-20 22:03:52 -08:00
|
|
|
if(u.i & 0xFFF1)
|
|
|
|
return u.i &= 0xFFFF0000, u.a + 1;
|
|
|
|
else
|
|
|
|
return (int)u.a;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lth_fractk
|
|
|
|
//
|
2017-03-12 13:34:21 -07:00
|
|
|
accum Lth_fractk(accum n)
|
2016-11-20 22:03:52 -08:00
|
|
|
{
|
2017-03-12 13:34:21 -07:00
|
|
|
union {int_k_t i; accum a;} u = {.a = n};
|
2016-11-20 22:03:52 -08:00
|
|
|
u.i &= 0xFFFF;
|
|
|
|
return u.a;
|
|
|
|
}
|
|
|
|
|
2016-10-17 08:57:44 -07:00
|
|
|
//
|
|
|
|
// Lth_PrintString
|
|
|
|
//
|
|
|
|
// Print a C string into the ACS print buffer.
|
|
|
|
//
|
|
|
|
void Lth_PrintString(char const *s)
|
|
|
|
{
|
2016-11-20 22:03:52 -08:00
|
|
|
ACS_PrintGlobalCharArray((int)s, __GDCC__Sta);
|
2016-10-17 08:57:44 -07:00
|
|
|
}
|
|
|
|
|
2016-10-19 07:03:32 -07:00
|
|
|
//
|
|
|
|
// Lth_Hash_char
|
|
|
|
//
|
|
|
|
size_t Lth_Hash_char(char const *s)
|
|
|
|
{
|
2017-03-12 13:34:21 -07:00
|
|
|
if(s == NULL) return 0;
|
|
|
|
|
|
|
|
size_t ret = 0;
|
|
|
|
while(*s)
|
|
|
|
ret = ret * 101 + ((unsigned char)(*s++) & 0xff);
|
|
|
|
return ret;
|
2016-10-19 07:03:32 -07:00
|
|
|
}
|
|
|
|
|
2016-10-21 11:49:11 -07:00
|
|
|
//
|
|
|
|
// Lth_Hash_str
|
|
|
|
//
|
2016-10-23 18:20:09 -07:00
|
|
|
size_t Lth_Hash_str(Lth__strchar *s)
|
2016-10-21 11:49:11 -07:00
|
|
|
{
|
2017-03-12 13:34:21 -07:00
|
|
|
if(s == NULL) return 0;
|
|
|
|
|
|
|
|
size_t ret = 0;
|
|
|
|
while(*s)
|
|
|
|
ret = ret * 101 + ((unsigned char)(*s++) & 0xff);
|
|
|
|
return ret;
|
2016-10-21 11:49:11 -07:00
|
|
|
}
|
|
|
|
|
2016-10-23 18:20:09 -07:00
|
|
|
//
|
|
|
|
// Lth_Hash_wchar
|
|
|
|
//
|
|
|
|
size_t Lth_Hash_wchar(wchar_t const *s)
|
|
|
|
{
|
|
|
|
if(s == NULL) return 0;
|
|
|
|
|
|
|
|
size_t ret = 0;
|
|
|
|
|
|
|
|
Lth_WithMbState()
|
|
|
|
for(; *s; s++)
|
|
|
|
{
|
|
|
|
char mb[MB_CUR_MAX];
|
|
|
|
int conv = wcrtomb(mb, *s, &state);
|
|
|
|
if(conv <= 0) break;
|
|
|
|
for(int i = 0; i < conv; i++)
|
|
|
|
ret = ret * 101 + ((unsigned char)(mb[i]) & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-03-12 13:55:50 -07:00
|
|
|
#endif//LITHOS3_NO_STDLIB
|