luxos/SysCore/lib/stdlib.c
2021-09-14 18:35:52 +03:00

287 lines
7.1 KiB
C

#include <stdlib.h>
#include <ctype.h>
const char base_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void uitoa (unsigned int value, char *string, int radix)
{
if (radix == 1 || radix>36) return;
// Variables
int len; *string = '0';
unsigned int temp = value;
// Calculate string length needed
for (len = 0; temp > 0; len++) temp /= radix;
if (len == 0) len = 2;
// Last character is NULL
string[len] = 0;
// Write characters
for (len--; len >=0; len-- ) {
string[len] = base_chars[value%radix];
value/=radix;
}
}
void ultoa (unsigned long value, char *string, int radix)
{
if (radix == 1 || radix>36) return;
// Variables
int len; *string = '0';
unsigned long temp = value;
// Calculate string length needed
for (len = 0; temp > 0; len++) temp /= radix;
if (len == 0) len = 2;
// Last character is NULL
string[len] = 0;
// Write characters
for (len--; len >=0; len-- ) {
string[len] = base_chars[value%radix];
value/=radix;
}
}
void itoa (signed int value, char *string, int radix)
{
if (radix == 1 || radix>36) return;
// Variables
int len = 0; *string = '0';
unsigned int copy = value;
// If number is < 0
if (value < 0) {
if (radix == 10) {
len++; copy = abs(value);
}
else copy = (unsigned) value; // If base is not 10, set high bit
}
// Calculate string length needed
unsigned int temp = copy;
for (; temp > 0; len++) temp /= radix;
if (len == 0) len = 2;
// Last character is NULL
string[len] = 0;
// Write characters
for (len--; len >= 0; len-- ) {
string[len] = base_chars[copy%radix];
copy/=radix;
}
// Add minus sign
if (value < 0 && radix == 10) string[0] = '-';
}
void ltoa (signed long value, char *string, int radix)
{
if (radix == 1 || radix>36) return;
// Variables
int len = 0; *string = '0';
unsigned long copy = value;
// If number is < 0
if (value < 0) {
if (radix == 10) {
len++; copy = abs(value);
}
else copy = (unsigned) value; // If base is not 10, set high bit
}
// Calculate string length needed
unsigned long temp = copy;
for (; temp > 0; len++) temp /= radix;
if (len == 0) len = 2;
// Last character is NULL
string[len] = 0;
// Write characters
for (len--; len >= 0; len-- ) {
string[len] = base_chars[copy%radix];
copy/=radix;
}
// Add minus sign
if (value < 0 && radix == 10) string[0] = '-';
}
int atoi (const char* string)
{
int ret = 0;
unsigned char sign = 0;
for (;!isdigit((unsigned char)*string); string++) {
if (*string == NULL) return 0;
else if (*string == '-' && isdigit(*(string+1)))
sign = 1;
}
for (;isdigit(*string); string++)
ret = ret*10 + (*string - '0');
if (sign) ret*=-1;
return ret;
}
long atol (const char* string)
{
long int ret = 0;
unsigned char sign = 0;
for (;!isdigit(*string); string++) {
if (*string == NULL) return 0;
else if (*string == '-' && *(string+1) > '0' && *(string+1) < '9')
sign = 1;
}
for (;isdigit(*string); string++)
ret = ret*10 + (*string - '0');
if (sign) ret*=-1;
return ret;
}
unsigned int atox (const char* string)
{
unsigned ret = 0;
unsigned temp;
for (;!isxdigit(*string); string++)
if (*string == 0) return 0;
for (;isxdigit(*string); string++) {
if (isdigit(*string)) temp = (unsigned)*string - '0';
else if (isupper(*string)) temp = 10 + (unsigned)(*string) - 'A';
else temp = 10 + (unsigned)(*string) - 'a';
ret = ret*0x10 + temp;
}
return ret;
}
void* bsearch (const void* key, const void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*))
{
int beg = 0, end = nelem, mid, result;
unsigned addr;
while (beg != end && beg != end-1) {
mid = (beg + end) / 2;
addr = (unsigned)base + (mid * width);
result = (*fcmp)(key, (void*) addr);
if (result == 0) return (void*) addr;
else if (result > 0) beg = mid;
else end = mid;
}
return 0;
}
void* lfind (const void* key, const void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*))
{
int result = 1, i = 0;
while (result != 0 && i != nelem) {
base = (void*)((unsigned)base + width);
result = (*fcmp)(key, base);
i++;
}
if (result == 0) return (void*) base;
return 0;
}
div_t div (int numerator, int denominator)
{
div_t ret;
ret.quot = numerator / denominator;
ret.rem = numerator % denominator;
return ret;
}
ldiv_t ldiv (long numerator, long denominator)
{
ldiv_t ret;
ret.quot = numerator / denominator;
ret.rem = numerator % denominator;
return ret;
}
inline void __qassign (void *dest, void *source, unsigned width)
{
unsigned char* dst = (unsigned char*)dest;
unsigned char* src = (unsigned char*)source;
int i;
for (i = 0; i < width; i++, dst++, src++)
*dst = *src;
}
void __qsort(void* base, unsigned width, int (*fcmp)(const void*, const void*), int beg, int end)
{
unsigned char piv_str[width];
unsigned char tmp_str[width];
void* piv = (void*) piv_str; void* tmp = (void*) tmp_str;
int l,r,p;
while (beg<end) // This while loop will avoid the second recursive call
{
l = beg; p = (beg+end)/2; r = end;
__qassign(piv, (void*) ((unsigned)base + (width * p)), width);
//piv = (void*) ((unsigned)base + (width * p));
while (1)
{
while ( (l<=r) && ( (*fcmp)( (void*) ((unsigned)base + (width * l)) ,piv) <= 0 ) ) l++;
while ( (l<=r) && ( (*fcmp)( (void*) ((unsigned)base + (width * r)) ,piv) > 0 ) ) r--;
if (l>r) break;
__qassign (tmp, (void*) ((unsigned)base + (width * l)), width);
__qassign ((void*) ((unsigned)base + (width * l)), (void*) ((unsigned)base + (width * r)), width);
__qassign ((void*) ((unsigned)base + (width * r)), tmp, width);
//tmp=base[l]; base[l]=base[r]; base[r]=tmp;
if (p==r) p=l;
l++; r--;
}
__qassign((void*) ((unsigned)base + (width * p)), (void*) ((unsigned)base + (width * r)), width);
__qassign((void*) ((unsigned)base + (width * r)), piv, width);
//base[p]=base[r]; base[r]=piv;
r--;
// Recursion on the shorter side & loop (with new indexes) on the longer
if ((r-beg)<(end-l))
{
__qsort(base, width, *fcmp, beg, r);
beg=l;
}
else
{
__qsort(base, width, *fcmp, l, end);
end=r;
}
}
}
void qsort (void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*))
{
__qsort(base, width, *fcmp, 0, nelem-1);
}