private bool EvalChar (Mode mode, ref int ptr, ref int pc, bool multi) {
bool consumed = false;
char c = '\0';
bool negate;
bool ignore;
do {
ushort word = program[pc];
OpCode op = (OpCode)(word & 0x00ff);
OpFlags flags = (OpFlags)(word & 0xff00);
++ pc;
ignore = (flags & OpFlags.IgnoreCase) != 0;
// consume character: the direction of an In construct is
// determined by the direction of its first op
if (!consumed) {
if ((flags & OpFlags.RightToLeft) != 0) {
if (ptr <= 0)
return false;
c = text[-- ptr];
}
else {
if (ptr >= text_end)
return false;
c = text[ptr ++];
}
if (ignore)
c = Char.ToLower (c);
consumed = true;
}
// negate flag
negate = (flags & OpFlags.Negate) != 0;
// execute op
switch (op) {
case OpCode.True:
return true;
case OpCode.False:
return false;
case OpCode.Character: {
if (c == (char)program[pc ++])
return !negate;
break;
}
case OpCode.Category: {
if (CategoryUtils.IsCategory ((Category)program[pc ++], c))
return !negate;
break;
}
case OpCode.NotCategory: {
if (!CategoryUtils.IsCategory ((Category)program[pc ++], c))
return !negate;
break;
}
case OpCode.Range: {
int lo = (char)program[pc ++];
int hi = (char)program[pc ++];
if (lo <= c && c <= hi)
return !negate;
break;
}
case OpCode.Set: {
int lo = (char)program[pc ++];
int len = (char)program[pc ++];
int bits = pc;
pc += len;
int i = (int)c - lo;
if (i < 0 || i >= len << 4)
break;
if ((program[bits + (i >> 4)] & (1 << (i & 0xf))) != 0)
return !negate;
break;
}
}
} while (multi);
return negate;
}