Speed up FcConfigCompareValue

Avoid FcValueCanonicalize when we can, to avoid
unnecessary copying of FcValue structs.
This commit is contained in:
Matthias Clasen 2020-08-21 00:49:04 -04:00
parent 9d4e5d0f25
commit 09729c9032
1 changed files with 78 additions and 52 deletions

View File

@ -982,192 +982,215 @@ FcConfigCompareValue (const FcValue *left_o,
unsigned int op_, unsigned int op_,
const FcValue *right_o) const FcValue *right_o)
{ {
FcValue left = FcValueCanonicalize(left_o); FcValue left;
FcValue right = FcValueCanonicalize(right_o); FcValue right;
FcBool ret = FcFalse; FcBool ret = FcFalse;
FcOp op = FC_OP_GET_OP (op_); FcOp op = FC_OP_GET_OP (op_);
int flags = FC_OP_GET_FLAGS (op_); int flags = FC_OP_GET_FLAGS (op_);
if (left.type != right.type) if (left_o->type != right_o->type)
{ {
left = FcValueCanonicalize(left_o);
right = FcValueCanonicalize(right_o);
FcValuePromotionBuffer buf1, buf2; FcValuePromotionBuffer buf1, buf2;
left = FcConfigPromote (left, right, &buf1); left = FcConfigPromote (left, right, &buf1);
right = FcConfigPromote (right, left, &buf2); right = FcConfigPromote (right, left, &buf2);
if (left.type != right.type) left_o = &left;
right_o = &right;
if (left_o->type != right_o->type)
{ {
if (op == FcOpNotEqual || op == FcOpNotContains) if (op == FcOpNotEqual || op == FcOpNotContains)
ret = FcTrue; ret = FcTrue;
return ret; return ret;
} }
} }
switch (left.type) { switch (left_o->type) {
case FcTypeUnknown: case FcTypeUnknown:
break; /* No way to guess how to compare for this object */ break; /* No way to guess how to compare for this object */
case FcTypeInteger: case FcTypeInteger: {
int l = left_o->u.i;
int r = right_o->u.i;
switch ((int) op) { switch ((int) op) {
case FcOpEqual: case FcOpEqual:
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = left.u.i == right.u.i; ret = l == r;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
case FcOpNotContains: case FcOpNotContains:
ret = left.u.i != right.u.i; ret = l != r;
break; break;
case FcOpLess: case FcOpLess:
ret = left.u.i < right.u.i; ret = l < r;
break; break;
case FcOpLessEqual: case FcOpLessEqual:
ret = left.u.i <= right.u.i; ret = l <= r;
break; break;
case FcOpMore: case FcOpMore:
ret = left.u.i > right.u.i; ret = l > r;
break; break;
case FcOpMoreEqual: case FcOpMoreEqual:
ret = left.u.i >= right.u.i; ret = l >= r;
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeDouble: }
case FcTypeDouble: {
double l = left_o->u.d;
double r = right_o->u.d;
switch ((int) op) { switch ((int) op) {
case FcOpEqual: case FcOpEqual:
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = left.u.d == right.u.d; ret = l == r;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
case FcOpNotContains: case FcOpNotContains:
ret = left.u.d != right.u.d; ret = l != r;
break; break;
case FcOpLess: case FcOpLess:
ret = left.u.d < right.u.d; ret = l < r;
break; break;
case FcOpLessEqual: case FcOpLessEqual:
ret = left.u.d <= right.u.d; ret = l <= r;
break; break;
case FcOpMore: case FcOpMore:
ret = left.u.d > right.u.d; ret = l > r;
break; break;
case FcOpMoreEqual: case FcOpMoreEqual:
ret = left.u.d >= right.u.d; ret = l >= r;
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeBool: }
case FcTypeBool: {
FcBool l = left_o->u.b;
FcBool r = right_o->u.b;
switch ((int) op) { switch ((int) op) {
case FcOpEqual: case FcOpEqual:
ret = left.u.b == right.u.b; ret = l == r;
break; break;
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = left.u.b == right.u.b || left.u.b >= FcDontCare; ret = l == r || l >= FcDontCare;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = left.u.b != right.u.b; ret = l != r;
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = !(left.u.b == right.u.b || left.u.b >= FcDontCare); ret = !(l == r || l >= FcDontCare);
break; break;
case FcOpLess: case FcOpLess:
ret = left.u.b != right.u.b && right.u.b >= FcDontCare; ret = l != r && r >= FcDontCare;
break; break;
case FcOpLessEqual: case FcOpLessEqual:
ret = left.u.b == right.u.b || right.u.b >= FcDontCare; ret = l == r || r >= FcDontCare;
break; break;
case FcOpMore: case FcOpMore:
ret = left.u.b != right.u.b && left.u.b >= FcDontCare; ret = l != r && l >= FcDontCare;
break; break;
case FcOpMoreEqual: case FcOpMoreEqual:
ret = left.u.b == right.u.b || left.u.b >= FcDontCare; ret = l == r || l >= FcDontCare;
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeString: }
case FcTypeString: {
const FcChar8 *l = FcValueString (left_o);
const FcChar8 *r = FcValueString (right_o);
switch ((int) op) { switch ((int) op) {
case FcOpEqual: case FcOpEqual:
case FcOpListing: case FcOpListing:
if (flags & FcOpFlagIgnoreBlanks) if (flags & FcOpFlagIgnoreBlanks)
ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) == 0; ret = FcStrCmpIgnoreBlanksAndCase (l, r) == 0;
else else
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0; ret = FcStrCmpIgnoreCase (l, r) == 0;
break; break;
case FcOpContains: case FcOpContains:
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0; ret = FcStrStrIgnoreCase (l, r) != 0;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
if (flags & FcOpFlagIgnoreBlanks) if (flags & FcOpFlagIgnoreBlanks)
ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) != 0; ret = FcStrCmpIgnoreBlanksAndCase (l, r) != 0;
else else
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0; ret = FcStrCmpIgnoreCase (l, r) != 0;
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0; ret = FcStrStrIgnoreCase (l, r) == 0;
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeMatrix: }
case FcTypeMatrix: {
switch ((int) op) { switch ((int) op) {
case FcOpEqual: case FcOpEqual:
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = FcMatrixEqual (left.u.m, right.u.m); ret = FcMatrixEqual (left_o->u.m, right_o->u.m);
break; break;
case FcOpNotEqual: case FcOpNotEqual:
case FcOpNotContains: case FcOpNotContains:
ret = !FcMatrixEqual (left.u.m, right.u.m); ret = !FcMatrixEqual (left_o->u.m, right_o->u.m);
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeCharSet: }
case FcTypeCharSet: {
const FcCharSet *l = FcValueCharSet (left_o);
const FcCharSet *r = FcValueCharSet (right_o);
switch ((int) op) { switch ((int) op) {
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
/* left contains right if right is a subset of left */ /* left contains right if right is a subset of left */
ret = FcCharSetIsSubset (right.u.c, left.u.c); ret = FcCharSetIsSubset (r, l);
break; break;
case FcOpNotContains: case FcOpNotContains:
/* left contains right if right is a subset of left */ /* left contains right if right is a subset of left */
ret = !FcCharSetIsSubset (right.u.c, left.u.c); ret = !FcCharSetIsSubset (r, l);
break; break;
case FcOpEqual: case FcOpEqual:
ret = FcCharSetEqual (left.u.c, right.u.c); ret = FcCharSetEqual (l, r);
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = !FcCharSetEqual (left.u.c, right.u.c); ret = !FcCharSetEqual (l, r);
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeLangSet: }
case FcTypeLangSet: {
const FcLangSet *l = FcValueLangSet (left_o);
const FcLangSet *r = FcValueLangSet (right_o);
switch ((int) op) { switch ((int) op) {
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = FcLangSetContains (left.u.l, right.u.l); ret = FcLangSetContains (l, r);
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = !FcLangSetContains (left.u.l, right.u.l); ret = !FcLangSetContains (l, r);
break; break;
case FcOpEqual: case FcOpEqual:
ret = FcLangSetEqual (left.u.l, right.u.l); ret = FcLangSetEqual (l, r);
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = !FcLangSetEqual (left.u.l, right.u.l); ret = !FcLangSetEqual (l, r);
break; break;
default: default:
break; break;
} }
break; break;
}
case FcTypeVoid: case FcTypeVoid:
switch ((int) op) { switch ((int) op) {
case FcOpEqual: case FcOpEqual:
@ -1184,20 +1207,23 @@ FcConfigCompareValue (const FcValue *left_o,
case FcOpEqual: case FcOpEqual:
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = left.u.f == right.u.f; ret = left_o->u.f == right_o->u.f;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
case FcOpNotContains: case FcOpNotContains:
ret = left.u.f != right.u.f; ret = left_o->u.f != right_o->u.f;
break; break;
default: default:
break; break;
} }
break; break;
case FcTypeRange: case FcTypeRange: {
ret = FcRangeCompare (op, left.u.r, right.u.r); const FcRange *l = FcValueRange (left_o);
const FcRange *r = FcValueRange (right_o);
ret = FcRangeCompare (op, l, r);
break; break;
} }
}
return ret; return ret;
} }