ZealOS/src/Kernel/StrScan.ZC

402 lines
7.2 KiB
HolyC
Raw Normal View History

I64 Str2I64(U8 *st, I64 radix=10, U8 **_end_ptr=NULL)
2020-02-15 20:01:48 +00:00
{//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;
}
2020-02-15 20:01:48 +00:00
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;
2020-02-15 20:01:48 +00:00
}
F64 Str2F64(U8 *src, U8 **_end_ptr=NULL)
2020-02-15 20:01:48 +00:00
{/*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
2020-03-01 01:59:50 +00:00
in 64-bits. Use exponentiated forms
2020-02-15 20:01:48 +00:00
to avoid this.
*/
I64 i, j, k, ch;
F64 d;
Bool neg = FALSE, neg_e = FALSE;
2020-02-15 20:01:48 +00:00
ch = *src++;
while (Bt(char_bmp_white_space, ch))
ch = *src++;
if (ch == '-')
{
neg = TRUE;
ch = *src++;
}
if (!StrNCompare(src - 1, "inf", 3))
{
d=<EFBFBD>;
src += 3;
goto a2f_end;
}
if (*src == '<EFBFBD>')
{
d = <EFBFBD>;
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++;
}
2020-02-15 20:01:48 +00:00
a2f_end:
if (_end_ptr)
*_end_ptr = src - 1;
if (neg)
return -d;
else
return d;
2020-02-15 20:01:48 +00:00
}
CDate Str2Date(U8 *_src)
{/*"*+nnnn", "*-nnnn", "mm/dd", "mm/dd/yy"
It also supports some functions
2020-02-15 20:01:48 +00:00
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;
2020-02-15 20:01:48 +00:00
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++;
2020-02-15 20:01:48 +00:00
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);
2020-02-15 20:01:48 +00:00
if (*ptr == '+' || *ptr == '-')
res.date += Str2I64(ptr);
Free(src);
Free(v);
return res - local_time_offset;
2020-02-15 20:01:48 +00:00
}
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.
2020-02-15 20:01:48 +00:00
*/
U8 *buf, *ptr, **pptr;
Bool left_justify = FALSE;
I64 ch, cur_arg = 0, i, len, *i_ptr, dec_len;
F64 *d_ptr;
if (!format)
2020-02-15 20:01:48 +00:00
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++;
2020-02-15 20:01:48 +00:00
}
return src;
2020-02-15 20:01:48 +00:00
}