mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-01-19 10:46:03 +00:00
3a33e6baaf
Rename all .CC files to .ZC extension.
401 lines
7.2 KiB
HolyC
Executable file
401 lines
7.2 KiB
HolyC
Executable file
I64 Str2I64(U8 *st, I64 radix=10, U8 **_end_ptr=NULL)
|
|
{//String to I64. Similar to strtoul().
|
|
//Allows radix change with "0x20" "0b1010" "0d123" "0o18".
|
|
//Be careful of Str2I64("0b101", 16)-->0xB101.
|
|
Bool neg = FALSE;
|
|
I64 ch, res = 0;
|
|
|
|
if (!st || !(2 <= radix <= 36))
|
|
{
|
|
if (_end_ptr)
|
|
*_end_ptr = st;
|
|
return 0;
|
|
}
|
|
while (Bt(char_bmp_white_space, *st))
|
|
st++;
|
|
while (TRUE)
|
|
switch (*st)
|
|
{
|
|
case '-':
|
|
st++;
|
|
neg = !neg;
|
|
break;
|
|
|
|
case '+':
|
|
st++;
|
|
break;
|
|
|
|
case '0':
|
|
st++;
|
|
ch = ToUpper(*st);
|
|
if (ch >= 'B' && (radix <= 10 || ch > 'A' + radix - 11))
|
|
switch (ch)
|
|
{
|
|
case 'B': radix = 2; st++; break;
|
|
case 'D': radix = 10; st++; break;
|
|
case 'X': radix = 16; st++; break;
|
|
}
|
|
default:
|
|
goto ai_cont;
|
|
}
|
|
ai_cont:
|
|
while (ch = ToUpper(*st++))
|
|
{
|
|
if (radix > 10)
|
|
{
|
|
if ('0' <= ch <= '9')
|
|
res = res * radix + ch - '0';
|
|
else if ('A' <= ch <= 'A' + radix - 11)
|
|
res = res * radix + ch - 'A' + 10;
|
|
else
|
|
break;
|
|
}
|
|
else if ('0' <= ch <= '0' + radix - 1)
|
|
res = res * radix + ch - '0';
|
|
else
|
|
break;
|
|
}
|
|
if (_end_ptr)
|
|
*_end_ptr = st - 1;
|
|
if (neg)
|
|
return -res;
|
|
else
|
|
return res;
|
|
}
|
|
|
|
F64 Str2F64(U8 *src, U8 **_end_ptr=NULL)
|
|
{/*String to F64.
|
|
Does not allow more than 18-digits
|
|
before or after the decimal point
|
|
because the numbers before and after
|
|
the decimal point are stored
|
|
in 64-bits. Use exponentiated forms
|
|
to avoid this.
|
|
*/
|
|
I64 i, j, k, ch;
|
|
F64 d;
|
|
Bool neg = FALSE, neg_e = FALSE;
|
|
|
|
ch = *src++;
|
|
while (Bt(char_bmp_white_space, ch))
|
|
ch = *src++;
|
|
if (ch == '-')
|
|
{
|
|
neg = TRUE;
|
|
ch = *src++;
|
|
}
|
|
if (!StrNCompare(src - 1, "inf", 3))
|
|
{
|
|
d=ì;
|
|
src += 3;
|
|
goto a2f_end;
|
|
}
|
|
if (*src == 'ì')
|
|
{
|
|
d = ì;
|
|
src++;
|
|
goto a2f_end;
|
|
}
|
|
i = 0;
|
|
while (TRUE)
|
|
{
|
|
if (Bt(char_bmp_dec_numeric, ch))
|
|
i = i * 10 + ch - '0';
|
|
else
|
|
{
|
|
if (ch == '.' || ch == 'e' || ch == 'E')
|
|
break;
|
|
d = i;
|
|
goto a2f_end;
|
|
}
|
|
ch = *src++;
|
|
}
|
|
if (ch == '.')
|
|
ch = *src++;
|
|
k = 0;
|
|
while (TRUE)
|
|
{
|
|
if (Bt(char_bmp_dec_numeric, ch))
|
|
{
|
|
i = i * 10 + ch - '0';
|
|
k++;
|
|
}
|
|
else
|
|
{
|
|
if (ch == 'e' || ch == 'E')
|
|
break;
|
|
d = i * Pow10I64(-k);
|
|
goto a2f_end;
|
|
}
|
|
ch = *src++;
|
|
}
|
|
ch = *src++;
|
|
if (ch == '-')
|
|
{
|
|
neg_e = TRUE;
|
|
ch = *src++;
|
|
}
|
|
j = 0;
|
|
while (TRUE)
|
|
{
|
|
if (Bt(char_bmp_dec_numeric, ch))
|
|
j = j * 10 + ch - '0';
|
|
else
|
|
{
|
|
if (neg_e)
|
|
d = i * Pow10I64(-j - k);
|
|
else
|
|
d = i * Pow10I64(j - k);
|
|
goto a2f_end;
|
|
}
|
|
ch = *src++;
|
|
}
|
|
a2f_end:
|
|
if (_end_ptr)
|
|
*_end_ptr = src - 1;
|
|
if (neg)
|
|
return -d;
|
|
else
|
|
return d;
|
|
}
|
|
|
|
CDate Str2Date(U8 *_src)
|
|
{/*"*+nnnn", "*-nnnn", "mm/dd", "mm/dd/yy"
|
|
It also supports some functions
|
|
SM() start of mon
|
|
EM() end of mon
|
|
SY() start of year
|
|
EY() end of year
|
|
Full expressions are not implimented
|
|
but you can do stuff like SM(*-7)+3
|
|
and it will return the 3rd day after
|
|
the start of mon for seven days before
|
|
today.
|
|
*/
|
|
CDate res = 0;
|
|
CDateStruct ds, ds_now;
|
|
U8 *src = MStrUtil(_src, SUF_REM_SPACES | SUF_TO_UPPER), *v = StrNew(src), *ptr = src;
|
|
Bool start_mon = FALSE, end_mon = FALSE, start_year = FALSE, end_year = FALSE;
|
|
|
|
MemSet(&ds, 0, sizeof(CDateStruct));
|
|
if (!StrNCompare(ptr, "SM(", 3))
|
|
{
|
|
ptr += 3;
|
|
start_mon = TRUE;
|
|
}
|
|
else if (!StrNCompare(ptr, "EM(", 3))
|
|
{
|
|
ptr += 3;
|
|
end_mon = TRUE;
|
|
}
|
|
else if (!StrNCompare(ptr, "SY(", 3))
|
|
{
|
|
ptr += 3;
|
|
start_year = TRUE;
|
|
}
|
|
else if (!StrNCompare(ptr, "EY(", 3))
|
|
{
|
|
ptr += 3;
|
|
end_year = TRUE;
|
|
}
|
|
if (*ptr == '*')
|
|
{
|
|
ptr++;
|
|
if (*ptr == '+' || *ptr == '-')
|
|
res.date = Str2I64(ptr,, &ptr);
|
|
res += Now + local_time_offset;
|
|
}
|
|
else
|
|
{
|
|
StrFirstRemove(ptr, "/", v); //Put mon into v
|
|
ds.mon = Str2I64(v);
|
|
if (StrOcc(ptr, '/'))
|
|
{
|
|
StrFirstRemove(ptr, "/", v); //Put day into v leaving year in pointer
|
|
ds.day_of_mon = Str2I64(v);
|
|
ds.year = Str2I64(ptr,, &ptr);
|
|
if (ds.year < 100) //if not 4 digit year
|
|
ds.year += 2000;
|
|
}
|
|
else
|
|
{
|
|
ds.day_of_mon = Str2I64(ptr,, &ptr);
|
|
Date2Struct(&ds_now, Now + local_time_offset);
|
|
ds.year = ds_now.year;
|
|
}
|
|
res = Struct2Date(&ds);
|
|
}
|
|
if (*ptr == ')')
|
|
ptr++;
|
|
|
|
if (start_mon)
|
|
res.date = FirstDayOfMon(res.date);
|
|
else if (end_mon)
|
|
res.date = LastDayOfMon(res.date);
|
|
else if (start_year)
|
|
res.date = FirstDayOfYear(res.date);
|
|
else if (end_year)
|
|
res.date = LastDayOfYear(res.date);
|
|
|
|
if (*ptr == '+' || *ptr == '-')
|
|
res.date += Str2I64(ptr);
|
|
Free(src);
|
|
Free(v);
|
|
|
|
return res - local_time_offset;
|
|
}
|
|
|
|
U8 *StrScan(U8 *src, U8 *format, ...)
|
|
{/*Opposite of sprintf(). Pass pointers to data to be scanned-in.
|
|
For "%s", pass pointer to pointer (be careful because address
|
|
of array is the same as array--create pointer to array
|
|
and take address.
|
|
*/
|
|
U8 *buf, *ptr, **pptr;
|
|
Bool left_justify = FALSE;
|
|
I64 ch, cur_arg = 0, i, len, *i_ptr, dec_len;
|
|
F64 *d_ptr;
|
|
|
|
if (!format)
|
|
throw('Scan');
|
|
while (ch = *format++)
|
|
{
|
|
if (ch == '%')
|
|
{
|
|
if (*format == '%')
|
|
{
|
|
src++;
|
|
format++;
|
|
}
|
|
else
|
|
{
|
|
if (*format == '-')
|
|
{
|
|
left_justify = TRUE;
|
|
format++;
|
|
}
|
|
else
|
|
left_justify = FALSE;
|
|
len = 0;
|
|
while ('0' <= *format <= '9')
|
|
len = len * 10 + (*format++ - '0');
|
|
if (*format == '*')
|
|
{
|
|
format++;
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
len = argv[cur_arg++];
|
|
}
|
|
ch = *format++;
|
|
if (ch && !len)
|
|
{
|
|
ptr = src;
|
|
while (*ptr && *ptr != *format)
|
|
ptr++;
|
|
len = ptr - src;
|
|
}
|
|
else
|
|
{
|
|
if (ch == '.')
|
|
{
|
|
dec_len = 0;
|
|
while ('0' <= *format <= '9')
|
|
dec_len = dec_len * 10 + (*format++ - '0');
|
|
if (*format == '*')
|
|
{
|
|
format++;
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
dec_len = argv[cur_arg++];
|
|
}
|
|
ch = *format++;
|
|
}
|
|
}
|
|
buf = MAlloc(len + 1);
|
|
for (i = 0; i < len; i++)
|
|
buf[i] = *src++;
|
|
buf[i] = 0;
|
|
switch (ch)
|
|
{
|
|
case 's':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
pptr = argv[cur_arg++];
|
|
StrCopy(*pptr, buf);
|
|
break;
|
|
|
|
case 'c':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
ptr = argv[cur_arg++];
|
|
*ptr = *buf;
|
|
break;
|
|
|
|
case 'C':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
ptr = argv[cur_arg++];
|
|
*ptr = ToUpper(*buf);
|
|
break;
|
|
|
|
case 'z':
|
|
if (cur_arg + 1 >= argc)
|
|
throw('Scan');
|
|
i_ptr = argv[cur_arg++];
|
|
*i_ptr = ListMatch(buf, argv[cur_arg++]);
|
|
break;
|
|
|
|
case 'Z':
|
|
if (cur_arg + 1 >= argc)
|
|
throw('Scan');
|
|
i_ptr = argv[cur_arg++];
|
|
*i_ptr = DefineMatch(buf, argv[cur_arg++]);
|
|
break;
|
|
|
|
case 'd':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
i_ptr = argv[cur_arg++];
|
|
*i_ptr = Str2I64(buf);
|
|
break;
|
|
|
|
case 'X':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
i_ptr = argv[cur_arg++];
|
|
*i_ptr = Str2I64(buf, 16);
|
|
break;
|
|
|
|
case 'b':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
i_ptr = argv[cur_arg++];
|
|
*i_ptr = Str2I64(buf, 2);
|
|
break;
|
|
|
|
case 'e':
|
|
case 'f':
|
|
case 'g':
|
|
case 'n':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
d_ptr = argv[cur_arg++];
|
|
*d_ptr = Str2F64(buf);
|
|
break;
|
|
|
|
case 'D':
|
|
if (cur_arg >= argc)
|
|
throw('Scan');
|
|
i_ptr = argv[cur_arg++];
|
|
*i_ptr = Str2Date(buf);
|
|
break;
|
|
}
|
|
Free(buf);
|
|
}
|
|
}
|
|
else
|
|
src++;
|
|
}
|
|
|
|
return src;
|
|
}
|