mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-30 17:26:31 +00:00
d9ac154e76
Reformatted KMathA.CC, KMathB.CC, KMisc.CC, KTask.CC, KUtils.CC, Kernel.PRJ, KernelA.HH, KernelB.HH, KernelC.HH, KeyDev.CC, MultiProc.CC, PCIBIOS.CC, QuickSort.CC, Sched.CC, StrA.CC, StrB.CC, StrPrint.CC, StrScan.CC. All top-level Kernel files are now reformatted. Remaining are files in Kernel/ subdirectories.
753 lines
15 KiB
HolyC
Executable file
753 lines
15 KiB
HolyC
Executable file
U8 *StrPrintHex(U8 *dst, I64 num; I64 width)
|
|
{
|
|
U8 *res = dst + width;
|
|
|
|
dst = res;
|
|
while (width--)
|
|
{
|
|
*--dst = "0123456789ABCDEF"(U8 *)[num & 15];
|
|
num >>= 4;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
U0 PutHex(I64 num, I64 width)
|
|
{
|
|
U8 buf[17];
|
|
|
|
if (width > 16)
|
|
width = 16;
|
|
|
|
*StrPrintHex(buf, num, width) = 0;
|
|
"%s", buf;
|
|
}
|
|
|
|
asm {
|
|
// IN: RAX=NUM TO PRINT
|
|
PUT_HEX_U64::
|
|
PUSH_C_REGS
|
|
PUSH 16
|
|
PUSH RAX
|
|
CALL &PutHex
|
|
POP_C_REGS
|
|
RET
|
|
PUT_HEX_U32::
|
|
PUSH_C_REGS
|
|
PUSH 8
|
|
PUSH RAX
|
|
CALL &PutHex
|
|
POP_C_REGS
|
|
RET
|
|
PUT_HEX_U16::
|
|
PUSH_C_REGS
|
|
PUSH 4
|
|
PUSH RAX
|
|
CALL &PutHex
|
|
POP_C_REGS
|
|
RET
|
|
PUT_HEX_U8::
|
|
PUSH_C_REGS
|
|
PUSH 2
|
|
PUSH RAX
|
|
CALL &PutHex
|
|
POP_C_REGS
|
|
RET
|
|
PUT_CHARS::
|
|
// IN: RAX=Char
|
|
PUSH_C_REGS
|
|
PUSH RAX
|
|
CALL &PutChars
|
|
POP_C_REGS
|
|
RET
|
|
PUT_STR::
|
|
// IN: RSI=String
|
|
PUSH_C_REGS
|
|
PUSH RSI
|
|
CALL &PutS
|
|
POP_C_REGS
|
|
RET
|
|
_STRCOPY::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
TEST RDI, RDI
|
|
JZ @@15
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
TEST RSI, RSI
|
|
JNZ @@05
|
|
XOR RAX, RAX
|
|
JMP @@10
|
|
@@05: LODSB
|
|
@@10: STOSB
|
|
TEST AL, AL
|
|
JNZ @@05
|
|
@@15: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 16
|
|
_STRCOMPARE::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
@@05: LODSB
|
|
TEST AL, AL
|
|
JZ @@20
|
|
SCASB
|
|
JE @@05
|
|
JA @@15
|
|
@@10: MOV RAX, 1
|
|
JMP @@25
|
|
@@15: MOV RAX, -1
|
|
JMP @@25
|
|
@@20: SCASB
|
|
JNE @@10
|
|
XOR RAX, RAX
|
|
@@25: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 16
|
|
TO_UPPER::
|
|
CMP AL, 'a'
|
|
JB @@05
|
|
CMP AL, 'z'
|
|
JA @@05
|
|
ADD AL, 'A' - 'a'
|
|
@@05: RET
|
|
_STRICOMPARE::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
@@05: LODSB
|
|
TEST AL, AL
|
|
JZ @@30
|
|
CMP AL, 'a'
|
|
JB @@10
|
|
CMP AL, 'z'
|
|
JA @@10
|
|
ADD AL, 'A' - 'a'
|
|
@@10: MOV BL, U8 [RDI]
|
|
INC RDI
|
|
CMP BL, 'a'
|
|
JB @@15
|
|
CMP BL, 'z'
|
|
JA @@15
|
|
ADD BL, 'A' - 'a'
|
|
@@15: CMP AL, BL
|
|
JE @@05
|
|
JA @@25
|
|
@@20: MOV RAX, 1
|
|
JMP @@35
|
|
@@25: MOV RAX, -1
|
|
JMP @@35
|
|
@@30: MOV BL, U8 [RDI]
|
|
TEST BL, BL
|
|
JNE @@20
|
|
XOR RAX, RAX
|
|
@@35: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 16
|
|
_STRNCOMPARE::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RCX, U64 SF_ARG3[RBP]
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
@@05: TEST RCX, RCX
|
|
JZ @@25
|
|
DEC RCX
|
|
LODSB
|
|
TEST AL, AL
|
|
JZ @@20
|
|
SCASB
|
|
JE @@05
|
|
JA @@15
|
|
@@10: MOV RAX, 1
|
|
JMP @@30
|
|
@@15: MOV RAX, -1
|
|
JMP @@30
|
|
@@20: MOV BL, U8 [RDI]
|
|
TEST BL, BL
|
|
JNE @@10
|
|
@@25: XOR RAX, RAX
|
|
@@30: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 24
|
|
_STRNICOMPARE::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RCX, U64 SF_ARG3[RBP]
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
@@05: TEST RCX, RCX
|
|
JZ @@35
|
|
DEC RCX
|
|
LODSB
|
|
TEST AL, AL
|
|
JZ @@30
|
|
CMP AL, 'a'
|
|
JB @@10
|
|
CMP AL, 'z'
|
|
JA @@10
|
|
ADD AL, 'A' - 'a'
|
|
@@10: MOV BL, U8 [RDI]
|
|
INC RDI
|
|
CMP BL, 'a'
|
|
JB @@15
|
|
CMP BL, 'z'
|
|
JA @@15
|
|
ADD BL, 'A' - 'a'
|
|
@@15: CMP AL, BL
|
|
JE @@05
|
|
JA @@25
|
|
@@20: MOV RAX, 1
|
|
JMP @@40
|
|
@@25: MOV RAX, -1
|
|
JMP @@40
|
|
@@30: SCASB
|
|
JNE @@20
|
|
@@35: XOR RAX, RAX
|
|
@@40: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 24
|
|
_STRMATCH::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
TEST RSI, RSI
|
|
JZ @@25
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
TEST RDI, RDI
|
|
JZ @@25
|
|
MOV DL, U8 [RDI]
|
|
TEST DL, DL
|
|
JZ @@20
|
|
JMP @@10
|
|
@@05: INC RSI
|
|
@@10: LODSB
|
|
TEST AL, AL
|
|
JZ @@25
|
|
CMP AL, DL
|
|
JNE @@10
|
|
DEC RSI
|
|
MOV RCX, 1
|
|
@@15: MOV AL, U8 [RDI + RCX]
|
|
TEST AL, AL
|
|
JZ @@20
|
|
CMP AL, U8 [RSI + RCX]
|
|
JNE @@05
|
|
INC RCX
|
|
JMP @@15
|
|
|
|
DEC RSI
|
|
@@20: MOV RAX, RSI
|
|
JMP @@30
|
|
@@25: XOR RAX, RAX
|
|
@@30: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 16
|
|
_STRIMATCH::
|
|
PUSH RBP
|
|
MOV RBP, RSP
|
|
PUSH RSI
|
|
PUSH RDI
|
|
MOV RSI, U64 SF_ARG2[RBP]
|
|
TEST RSI, RSI
|
|
JZ @@25
|
|
MOV RDI, U64 SF_ARG1[RBP]
|
|
TEST RDI, RDI
|
|
JZ @@25
|
|
MOV AL, U8 [RDI]
|
|
CALL TO_UPPER
|
|
MOV DL, AL
|
|
TEST DL, DL
|
|
JZ @@20
|
|
JMP @@10
|
|
@@05: INC RSI
|
|
@@10: LODSB
|
|
CALL TO_UPPER
|
|
TEST AL, AL
|
|
JZ @@25
|
|
CMP AL, DL
|
|
JNE @@10
|
|
DEC RSI
|
|
MOV RCX, 1
|
|
@@15: MOV AL, U8 [RDI + RCX]
|
|
CALL TO_UPPER
|
|
TEST AL, AL
|
|
JZ @@20
|
|
MOV BL, U8 [RSI + RCX]
|
|
XCHG AL, BL
|
|
CALL TO_UPPER
|
|
CMP AL, BL
|
|
JNE @@05
|
|
INC RCX
|
|
JMP @@15
|
|
|
|
DEC RSI
|
|
@@20: MOV RAX, RSI
|
|
JMP @@30
|
|
@@25: XOR RAX, RAX
|
|
@@30: POP RDI
|
|
POP RSI
|
|
POP RBP
|
|
RET1 16
|
|
}
|
|
_extern _STRCOMPARE I64 StrCompare(U8 *st1, U8 *st2); //Compare two strings.
|
|
_extern _STRICOMPARE I64 StrICompare(U8 *st1, U8 *st2); //Compare two strings, ignoring case.
|
|
_extern _STRNCOMPARE I64 StrNCompare(U8 *st1, U8 *st2, I64 n); //Compare N bytes in two strings.
|
|
_extern _STRNICOMPARE I64 StrNICompare(U8 *st1, U8 *st2, I64 n); //Compare N bytes in two strings, ignoring case.
|
|
_extern _STRMATCH U8 *StrMatch(U8 *needle, U8 *haystack_str);//Scan for string in string.
|
|
_extern _STRIMATCH U8 *StrIMatch(U8 *needle, U8 *haystack_str);//Scan for string in string, ignoring case.
|
|
_extern _STRCOPY U0 StrCopy(U8 *dst, U8 *src); //Copy string.
|
|
|
|
//These bitmaps go to 0-511 so that $LK,"Lex",A="MN:Lex"$() can use them with $LK,"Token Codes",A="MN:TK_EOF"$.
|
|
U32
|
|
char_bmp_alpha[16] =
|
|
{0x0000000, 0x00000000, 0x87FFFFFF, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_alpha_numeric[16] =
|
|
{0x0000000, 0x03FF0000, 0x87FFFFFF, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_alpha_numeric_no_at[16] =
|
|
{0x0000000, 0x03FF0000, 0x87FFFFFE, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_word[16] =
|
|
{0x0000000, 0x03FF0080, 0x87FFFFFE, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_filename[16] =
|
|
{0x0000000, 0x03FF73FB, 0xEFFFFFFF, 0x6FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_dec_numeric[16] =
|
|
{0x0000000, 0x03FF0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_hex_numeric[16] =
|
|
{0x0000000, 0x03FF0000, 0x7E, 0x7E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_white_space[16] =
|
|
{0x80002600, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_non_eol_white_space[16] =
|
|
{0x80000200, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_zero_cr_nl_cursor[16] =
|
|
{0x00002421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_zero_tab_cr_nl_cursor[16] =
|
|
{0x00002621, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_zero_tab_cr_nl_cursor_dollar[16] =
|
|
{0x00002621, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_macro[16] =
|
|
{0x80002600, 0xFFFFFFDF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_printable[16] =
|
|
{0x80002600, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_displayable[16] =
|
|
{0x80000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
char_bmp_safe_dollar[16] =
|
|
{0x80000000, 0xFFFFFFEF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
//same but no dollar sign
|
|
|
|
char_bmp_non_eol[16] =
|
|
{0xFFFFDBFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
|
|
|
|
U8 *ListSub(I64 sub, U8 *list)
|
|
{//Point to list entry.
|
|
//Not efficient. Use an array of U8 ptrs for efficiency.
|
|
if (!list)
|
|
return NULL;
|
|
while (*list && sub > 0)
|
|
{
|
|
while (*list) //Advance to end of cur entry.
|
|
list++;
|
|
list++; //Skip trailing zero.
|
|
if (*list == '@') //Check for '@' alias list entry.
|
|
list++;
|
|
else
|
|
sub--;
|
|
}
|
|
if (sub || !*list)
|
|
return NULL;
|
|
else
|
|
return list;
|
|
}
|
|
|
|
I64 ListMatch(U8 *needle, U8 *haystack_list, I64 flags=0)
|
|
{//-2 if Ambiguous
|
|
// -1 if not found
|
|
// Not efficient. Use hash tables for efficiency.
|
|
I64 n, sub = 0, res = -1;
|
|
U8 *ptr;
|
|
Bool exact_match = FALSE;
|
|
|
|
if (!haystack_list)
|
|
return -1;
|
|
|
|
n = StrLen(needle);
|
|
while (*haystack_list)
|
|
{
|
|
if (*haystack_list == '@')
|
|
{ //Check for '@' alias haystack_list entry
|
|
sub--;
|
|
haystack_list++;
|
|
}
|
|
ptr = needle;
|
|
if (flags & LMF_IGNORE_CASE)
|
|
while (*ptr && ToUpper(*ptr) == ToUpper(*haystack_list))
|
|
{
|
|
ptr++;
|
|
haystack_list++;
|
|
}
|
|
else
|
|
while (*ptr && *ptr == *haystack_list)
|
|
{
|
|
ptr++;
|
|
haystack_list++;
|
|
}
|
|
if (!*ptr)
|
|
{ //Did we reach end of needle?
|
|
if (!*haystack_list) //Did we reach end of haystack_list?
|
|
return sub; //Found Exact match
|
|
else
|
|
{
|
|
if (res != -1)
|
|
{
|
|
if (!exact_match)
|
|
res = -2; //Ambiguous unless later exact match.
|
|
}
|
|
else
|
|
{
|
|
if (!(flags & LMF_EXACT))
|
|
res = sub;
|
|
}
|
|
}
|
|
}
|
|
while (*haystack_list) //Advance to end of cur entry.
|
|
haystack_list++;
|
|
haystack_list++; //Skip trailing zero
|
|
sub++;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
I64 StrOcc(U8 *src, I64 ch)
|
|
{//Count occurrences of a char.
|
|
I64 i = 0;
|
|
|
|
if (!src)
|
|
return 0;
|
|
while (*src)
|
|
if (*src++ == ch)
|
|
i++;
|
|
return i;
|
|
}
|
|
|
|
I64 Spaces2Tabs(U8 *dst, U8 *src)
|
|
{//Src buf with spaces to dst buf without.
|
|
U8 *src2;
|
|
I64 chged = 0, space_count, space_count2, col = 0;
|
|
|
|
if (*src)
|
|
while (TRUE)
|
|
{
|
|
src2 = src;
|
|
while (*src2 == CH_SPACE)
|
|
src2++;
|
|
space_count = src2 - src;
|
|
while (col + space_count >= 4)
|
|
{
|
|
space_count2 = 4 - col;
|
|
if (space_count2 == 1)
|
|
*dst++ = CH_SPACE;
|
|
else
|
|
{
|
|
*dst++ = '\t';
|
|
chged += space_count2 - 1;
|
|
}
|
|
space_count -= space_count2;
|
|
col = 0;
|
|
}
|
|
if (*src2 == '\t')
|
|
{
|
|
if (space_count == 1 && col == 3)
|
|
*dst++ = CH_SPACE;
|
|
else
|
|
chged += space_count;
|
|
*dst++ = '\t';
|
|
col = 0;
|
|
}
|
|
else
|
|
{
|
|
while (space_count--)
|
|
{
|
|
*dst++ = CH_SPACE;
|
|
if (++col == 4)
|
|
col = 0;
|
|
}
|
|
if (*src2)
|
|
{
|
|
*dst++ = *src2;
|
|
if (++col == 4)
|
|
col = 0;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
src = ++src2;
|
|
}
|
|
*dst = 0;
|
|
return chged;
|
|
}
|
|
|
|
U8 *StrUtil(U8 *_src, I64 flags)
|
|
{//Modifies in place. See $LK,"flags",A="MN:SUF_REM_SPACES"$ for all the options.
|
|
U8 *src = _src, *dst = _src;
|
|
I64 ch;
|
|
|
|
if (flags & SUF_REM_LEADING)
|
|
while (Bt(char_bmp_white_space, *src))
|
|
src++;
|
|
while (ch = *src++)
|
|
if (Bt(char_bmp_white_space, ch))
|
|
{
|
|
if (!(flags & SUF_REM_SPACES))
|
|
{
|
|
if (flags & SUF_SINGLE_SPACE)
|
|
{
|
|
*dst++ = CH_SPACE;
|
|
while ((ch = *src++) && Bt(char_bmp_white_space, ch));
|
|
src--;
|
|
}
|
|
else
|
|
*dst++ = ch;
|
|
}
|
|
}
|
|
else if (!(flags & SUF_REM_CTRL_CHARS) || ch >= CH_SPACE)
|
|
*dst++ = ch;
|
|
*dst = 0;
|
|
|
|
if (flags & SUF_REM_TRAILING)
|
|
while (dst != _src && (!*dst || Bt(char_bmp_white_space, *dst)))
|
|
*dst-- = 0;
|
|
if (flags & SUF_TO_UPPER)
|
|
for (dst = _src; *dst; dst++)
|
|
{
|
|
ch = *dst;
|
|
if ('a' <= ch <= 'z')
|
|
*dst = ch - 0x20;
|
|
}
|
|
if (flags & SUF_TO_LOWER)
|
|
for (dst = _src; *dst; dst++)
|
|
{
|
|
ch = *dst;
|
|
if ('A' <= ch <= 'Z')
|
|
*dst = ch + 0x20;
|
|
}
|
|
if (flags & SUF_SAFE_DOLLAR)
|
|
for (dst = _src; *dst; dst++)
|
|
{
|
|
ch = *dst;
|
|
if (!Bt(char_bmp_safe_dollar, *dst))
|
|
*dst = '.';
|
|
}
|
|
if (flags & SUF_S2T)
|
|
Spaces2Tabs(_src, _src);
|
|
return _src;
|
|
}
|
|
|
|
U8 *StrFirstOcc(U8 *src, U8 *marker)
|
|
{//Point to 1st occurrence of marker set in str.
|
|
I64 ch;
|
|
|
|
while ((ch = *src++) && !StrOcc(marker, ch));
|
|
if (ch)
|
|
return src - 1;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
U8 *StrFirstRemove(U8 *src, U8 *marker, U8 *dst=NULL)
|
|
{//Remove first str segment and place in dst buf or NULL.
|
|
I64 ch;
|
|
U8 *ptr = src, *res = dst;
|
|
|
|
if (dst)
|
|
{
|
|
while ((ch = *ptr++) && !StrOcc(marker, ch))
|
|
*dst++ = ch;
|
|
*dst = 0;
|
|
}
|
|
else
|
|
while ((ch = *ptr++) && !StrOcc(marker, ch));
|
|
if (ch)
|
|
StrCopy(src, ptr);
|
|
else
|
|
*src = 0;
|
|
return res;
|
|
}
|
|
|
|
U8 *StrLastOcc(U8 *src, U8 *marker)
|
|
{//Point to last occurrence of market set in str.
|
|
I64 ch;
|
|
U8 *res = NULL;
|
|
|
|
while (ch = *src++)
|
|
if (StrOcc(marker, ch))
|
|
res = src - 1;
|
|
return res;
|
|
}
|
|
|
|
U8 *StrLastRemove(U8 *src, U8 *marker, U8 *dst=NULL)
|
|
{//Remove last str segment and place in dst buf or NULL.
|
|
U8 *ptr;
|
|
|
|
if (ptr = StrLastOcc(src, marker))
|
|
{
|
|
if (dst)
|
|
StrCopy(dst, ptr + 1);
|
|
*ptr = 0;
|
|
}
|
|
else
|
|
{
|
|
if (dst)
|
|
StrCopy(dst, src);
|
|
*src = 0;
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
U8 *StrFind(U8 *needle, U8 *haystack_str, I64 flags=0)
|
|
{//Find needle_str in haystack_str with options.
|
|
Bool cont;
|
|
U8 *saved_haystack_str = haystack_str;
|
|
I64 plen = StrLen(needle);
|
|
|
|
do
|
|
{
|
|
cont = FALSE;
|
|
if (flags & SFF_IGNORE_CASE)
|
|
haystack_str = StrIMatch(needle, haystack_str);
|
|
else
|
|
haystack_str = StrMatch(needle, haystack_str);
|
|
if (haystack_str && flags & SFF_WHOLE_LABELS_BEFORE && haystack_str != saved_haystack_str &&
|
|
Bt(char_bmp_alpha_numeric, *(haystack_str - 1)))
|
|
{
|
|
haystack_str++;
|
|
if (*haystack_str)
|
|
cont = TRUE;
|
|
else
|
|
haystack_str = NULL;
|
|
}
|
|
if (haystack_str && flags & SFF_WHOLE_LABELS_AFTER && Bt(char_bmp_alpha_numeric, *(haystack_str + plen)))
|
|
{
|
|
haystack_str++;
|
|
if (*haystack_str)
|
|
cont = TRUE;
|
|
else
|
|
haystack_str = NULL;
|
|
}
|
|
}
|
|
while (cont);
|
|
|
|
return haystack_str;
|
|
}
|
|
|
|
U8 *StrReplace(U8 *str, U8 *old, U8 *new, I64 sff_flags=NONE, Bool free_str=FALSE)
|
|
{//Replace all instances of old with new in str. New MAlloc()ed string. free_str aids in chain replacement.
|
|
U8 *str_start, *str_end = str, *str_loc, *tmpm = NULL;
|
|
|
|
if (!*old)
|
|
{
|
|
str_start = StrNew(new);
|
|
goto sr_end2;
|
|
}
|
|
|
|
if (!StrCompare(old, new))
|
|
goto sr_end;
|
|
|
|
while (str_loc = str_end = StrFind(old, str_end, sff_flags))
|
|
{
|
|
str_start = str;
|
|
str_end += StrLen(old); //Move start marker past old str, cutting it out
|
|
str_start[StrLen(str_start) - StrLen(str_loc)] = '\0'; //End str_start right before where old was
|
|
Free(tmpm);
|
|
tmpm = MStrPrint("%s%s%s", str_start, new, str_end);
|
|
str = tmpm;
|
|
}
|
|
sr_end:
|
|
str_start = StrNew(str);
|
|
sr_end2:
|
|
if (free_str)
|
|
Free(str);
|
|
return str_start;
|
|
}
|
|
|
|
Bool WildMatch(U8 *test_str, U8 *wild_str)
|
|
{//Wildcard match with '*' and '?'.
|
|
I64 ch1, ch2;
|
|
U8 *fall_back_src = NULL, *fall_back_wild = NULL;
|
|
|
|
while (TRUE)
|
|
{
|
|
if (!(ch1 = *test_str++))
|
|
{
|
|
if (*wild_str && *wild_str != '*')
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (!(ch2 = *wild_str++))
|
|
return FALSE;
|
|
else
|
|
{
|
|
if (ch2 == '*')
|
|
{
|
|
fall_back_wild = wild_str - 1;
|
|
fall_back_src = test_str;
|
|
if (!(ch2 = *wild_str++))
|
|
return TRUE;
|
|
while (ch2 != ch1)
|
|
if (!(ch1 = *test_str++))
|
|
return FALSE;
|
|
}
|
|
else
|
|
if (ch2 != '?' && ch1 != ch2)
|
|
{
|
|
if (fall_back_wild)
|
|
{
|
|
wild_str = fall_back_wild;
|
|
test_str = fall_back_src;
|
|
fall_back_wild = NULL;
|
|
fall_back_src = NULL;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|