int KeyCompare(const Value &a, const Value &b, bool rec = false) { if (a.type != b.type) g_vm->BuiltinError("binary search: key type doesn't match type of vector elements"); switch (a.type) { case V_INT: return a.ival < b.ival ? -1 : a.ival > b.ival; case V_FLOAT: return a.fval < b.fval ? -1 : a.fval > b.fval; case V_STRING: return strcmp(a.sval->str(), b.sval->str()); case V_VECTOR: if (a.vval->len && b.vval->len && !rec) return KeyCompare(a.vval->at(0), b.vval->at(0), true); // fall thru: default: g_vm->BuiltinError("binary search: illegal key type"); return 0; } }
ExtractCompare(const KeyExtractor& ext = KeyExtractor(), const KeyCompare& comp = KeyCompare()) : m_extractor(ext), m_comp(comp) {}
ALERROR CDesignTable::Merge (const CDesignTable &Source, CDesignList *ioOverride) // Merge // // Merge the given table into ours. Entries in Table override our entries // if they have the same UNID. { int i; TArray<CDesignType *> Replaced; // We move through both tables in order and handle when we get an // addition or overlap. int iSrcPos = 0; int iDestPos = 0; // Merge while (iSrcPos < Source.GetCount()) { // If we're at the end of the destination then just insert if (iDestPos == m_Table.GetCount()) { m_Table.InsertSorted(Source.m_Table.GetKey(iSrcPos), Source.m_Table.GetValue(iSrcPos)); // Advance iDestPos++; iSrcPos++; } // Otherwise, see if we need to insert or replace else { int iCompare = AscendingSort * KeyCompare(Source.m_Table.GetKey(iSrcPos), m_Table.GetKey(iDestPos)); // If the same key then we replace if (iCompare == 0) { CDesignType *pNewType = Source.m_Table.GetValue(iSrcPos); // If this is an override then we put it on a different table and // leave the type alone. // // NOTE: It is OK if we add multiple types of the same UNID. As long // as we add them in order, we're OK. if (pNewType->IsModification()) { if (ioOverride) ioOverride->AddEntry(pNewType); } // Otherwise we just replace the type else { // If we have to free our originals, then remember them here. if (m_bFreeTypes) { CDesignType *pOriginalType = m_Table.GetValue(iDestPos); Replaced.Insert(pOriginalType); } // Replace m_Table.GetValue(iDestPos) = pNewType; } // Advance iDestPos++; iSrcPos++; } // If the source is less than dest then we insert at this // position. else if (iCompare == 1) { m_Table.InsertSorted(Source.m_Table.GetKey(iSrcPos), Source.m_Table.GetValue(iSrcPos), iDestPos); // Advance iDestPos++; iSrcPos++; } // Otherwise, go to the next destination slot else iDestPos++; } } // Delete replaced entries for (i = 0; i < Replaced.GetCount(); i++) delete Replaced[i]; return NOERROR; }
int CDatum::DefaultCompare (void *pCtx, const CDatum &dKey1, const CDatum &dKey2) // DefaultCompare // // Default comparison routine used for sorting. Returns: // // -1: If dKey1 < dKey2 // 0: If dKey1 == dKey2 // 1: If dKey1 > dKey2 // // NOTES: // // Nil == "" // Nil == {} // Nil == () // "abc" != "ABC" { int i; // If both are the same datatype, then compare CDatum::Types iType1 = dKey1.GetBasicType(); CDatum::Types iType2 = dKey2.GetBasicType(); // If both types are equal, then compare if (iType1 == iType2) { switch (iType1) { case CDatum::typeNil: case CDatum::typeTrue: return 0; case CDatum::typeInteger32: if ((int)dKey1 > (int)dKey2) return 1; else if ((int)dKey1 < (int)dKey2) return -1; else return 0; case CDatum::typeInteger64: if ((DWORDLONG)dKey1 > (DWORDLONG)dKey2) return 1; else if ((DWORDLONG)dKey1 < (DWORDLONG)dKey2) return -1; else return 0; case CDatum::typeDouble: if ((double)dKey1 > (double)dKey2) return 1; else if ((double)dKey1 < (double)dKey2) return -1; else return 0; case CDatum::typeIntegerIP: return KeyCompare((const CIPInteger &)dKey1, (const CIPInteger &)dKey2); case CDatum::typeString: return KeyCompare((const CString &)dKey1, (const CString &)dKey2); case CDatum::typeDateTime: return ((const CDateTime &)dKey1).Compare((const CDateTime &)dKey2); case CDatum::typeArray: if (dKey1.GetCount() > dKey2.GetCount()) return 1; else if (dKey1.GetCount() < dKey2.GetCount()) return -1; else { for (i = 0; i < dKey1.GetCount(); i++) { CDatum dItem1 = dKey1.GetElement(i); CDatum dItem2 = dKey2.GetElement(i); int iItemCompare = CDatum::DefaultCompare(pCtx, dItem1, dItem2); if (iItemCompare != 0) return iItemCompare; } return 0; } case CDatum::typeStruct: if (dKey1.GetCount() > dKey2.GetCount()) return 1; else if (dKey1.GetCount() < dKey2.GetCount()) return -1; else { for (i = 0; i < dKey1.GetCount(); i++) { CString sItemKey1 = dKey1.GetKey(i); CString sItemKey2 = dKey2.GetKey(i); int iKeyCompare = KeyCompare(sItemKey1, sItemKey2); if (iKeyCompare != 0) return iKeyCompare; CDatum dItem1 = dKey1.GetElement(i); CDatum dItem2 = dKey2.GetElement(i); int iItemCompare = CDatum::DefaultCompare(pCtx, dItem1, dItem2); if (iItemCompare != 0) return iItemCompare; } return 0; } // LATER: Not yet supported default: return 0; } } // If one of the types is nil, then compare else if (iType1 == CDatum::typeNil || iType2 == CDatum::typeNil) { CDatum dNonNil; int iResult; if (iType2 == CDatum::typeNil) { dNonNil = dKey1; Swap(iType1, iType2); iResult = 1; } else { dNonNil = dKey2; iResult = -1; } switch (iType2) { case CDatum::typeString: if (((const CString &)dNonNil).IsEmpty()) return 0; else return iResult; case CDatum::typeArray: case CDatum::typeStruct: if (dNonNil.GetCount() == 0) return 0; else return iResult; default: // nil is always less return iResult; } } // If one of the types is a number, then compare as numbers else if (dKey1.IsNumber() || dKey2.IsNumber()) { CNumberValue Number1(dKey1); CNumberValue Number2(dKey2); if (Number1.IsValidNumber() && Number2.IsValidNumber()) return Number1.Compare(Number2); else if (Number1.IsValidNumber()) return 1; else if (Number2.IsValidNumber()) return -1; else return 0; } // Otherwise, cannot compare else return 0; }