festring::sizetype festring::IgnoreCaseFind(const festring& Where, const festring& What, sizetype Begin) { if(What.IsEmpty()) return Begin; for(; Where.GetSize() >= What.GetSize() + Begin; ++Begin) if(::Capitalize(Where[Begin]) == ::Capitalize(What[0])) { truth Equal = true; for(sizetype c = 1; c < What.GetSize(); ++c) if(::Capitalize(Where[Begin + c]) != ::Capitalize(What[c])) { Equal = false; break; } if(Equal) return Begin; } return NPos; }
bool festring::IgnoreCaseCompare(const festring& First, const festring& Second) { for(sizetype Pos = 0; Pos < First.GetSize() && Pos < Second.GetSize(); ++Pos) { char Char1 = ::Capitalize(First[Pos]); char Char2 = ::Capitalize(Second[Pos]); if(Char1 != Char2) return Char1 < Char2; } return First.GetSize() < Second.GetSize(); }
void festring::SearchAndReplace(festring& Where, const festring& What, const festring& With, sizetype Begin) { for(sizetype Pos = Where.Find(What, Begin); Pos != NPos; Pos = Where.Find(What, Pos)) { Where.Erase(Pos, What.GetSize()); Where.Insert(Pos, With); } }
void festring::SplitString(festring& Source, festring& Result, sizetype Length) { if(Source.GetSize() <= Length) { Result << Source; Source.Empty(); return; } sizetype Pos = Source.FindLast(' ', Length); if(Pos != NPos) { Result.Append(Source, Pos); Source.Erase(0, Pos + 1); } else { Result.Append(Source, Length); Source.Erase(0, Length); } }
int inputfile::HandlePunct(festring& String, int Char, int Mode) { if(Char == '/') { if(!feof(Buffer)) { Char = fgetc(Buffer); if(Char == '*') { long StartPos = TellPos(); int OldChar = 0, CommentLevel = 1; for(;;) { if(feof(Buffer)) ABORT("Unterminated comment in file %s, beginning at line %ld!", FileName.CStr(), TellLineOfPos(StartPos)); Char = fgetc(Buffer); if(OldChar != '*' || Char != '/') { if(OldChar != '/' || Char != '*') OldChar = Char; else { ++CommentLevel; OldChar = 0; } } else { if(!--CommentLevel) break; else OldChar = 0; } } return PUNCT_CONTINUE; } else { ungetc(Char, Buffer); clearerr(Buffer); } } if(Mode) ungetc('/', Buffer); else String << '/'; return PUNCT_RETURN; } if(Mode) { ungetc(Char, Buffer); return PUNCT_RETURN; } if(Char == '"') { long StartPos = TellPos(); int OldChar = 0; for(;;) { if(feof(Buffer)) ABORT("Unterminated string in file %s, beginning at line %ld!", FileName.CStr(), TellLineOfPos(StartPos)); Char = fgetc(Buffer); if(Char != '"') { String << char(Char); OldChar = Char; } else if(OldChar == '\\') { String[String.GetSize() - 1] = '"'; OldChar = 0; } else return PUNCT_RETURN; } } String << char(Char); return PUNCT_RETURN; }
long inputfile::ReadNumber(int CallLevel, truth PreserveTerminator) { long Value = 0; static festring Word; truth NumberCorrect = false; for(;;) { ReadWord(Word); char First = Word[0]; if(isdigit(First)) { Value = atoi(Word.CStr()); NumberCorrect = true; continue; } if(Word.GetSize() == 1) { if(First == ';' || First == ',' || First == ':') { if(CallLevel != HIGHEST || PreserveTerminator) ungetc(First, Buffer); return Value; } if(First == ')') { if((CallLevel != HIGHEST && CallLevel != 4) || PreserveTerminator) ungetc(')', Buffer); return Value; } if(First == '~') { Value = ~ReadNumber(4); NumberCorrect = true; continue; } /* Convert this into an inline function! */ #define CHECK_OP(op, cl)\ if(First == #op[0])\ if(cl < CallLevel)\ {\ Value op##= ReadNumber(cl);\ NumberCorrect = true;\ continue;\ }\ else\ {\ ungetc(#op[0], Buffer);\ return Value;\ } CHECK_OP(&, 1); CHECK_OP(|, 1); CHECK_OP(^, 1); CHECK_OP(*, 2); CHECK_OP(/, 2); CHECK_OP(%, 2); CHECK_OP(+, 3); CHECK_OP(-, 3); if(First == '<') { char Next = Get(); if(Next == '<') if(1 < CallLevel) { Value <<= ReadNumber(1); NumberCorrect = true; continue; } else { ungetc('<', Buffer); ungetc('<', Buffer); return Value; } else ungetc(Next, Buffer); } if(First == '>') { char Next = Get(); if(Next == '>') if(1 < CallLevel) { Value >>= ReadNumber(1); NumberCorrect = true; continue; } else { ungetc('>', Buffer); ungetc('>', Buffer); return Value; } else