int DaoValue_Compare( DaoValue *left, DaoValue *right ) { double L, R; int res = 0; if( left == right ) return 0; if( left == NULL || right == NULL ) return left < right ? -100 : 100; if( left->type != right->type ){ res = left->type < right->type ? -100 : 100; if( right->type == DAO_TUPLE && right->xTuple.subtype == DAO_PAIR ){ if( (res = DaoValue_Compare( left, right->xTuple.items[0] )) <= 0 ) return res; if( (res = DaoValue_Compare( left, right->xTuple.items[1] )) >= 0 ) return res; return 0; }else if( left->type == DAO_TUPLE && left->xTuple.subtype == DAO_PAIR ){ if( (res = DaoValue_Compare( left->xTuple.items[0], right )) >= 0 ) return res; if( (res = DaoValue_Compare( left->xTuple.items[1], right )) <= 0 ) return res; return 0; } #ifdef DAO_WITH_LONGINT if( left->type == DAO_LONG && (right->type && right->type <= DAO_DOUBLE) ){ if( right->type == DAO_INTEGER ){ return DLong_CompareToInteger( left->xLong.value, right->xInteger.value ); } return DLong_CompareToDouble( left->xLong.value, DaoValue_GetDouble( right ) ); }else if( right->type == DAO_LONG && (left->type && left->type <= DAO_DOUBLE) ){ if( left->type == DAO_INTEGER ){ return - DLong_CompareToInteger( right->xLong.value, left->xInteger.value ); } return - DLong_CompareToDouble( right->xLong.value, DaoValue_GetDouble( left ) ); } #endif if( left->type < DAO_INTEGER || left->type > DAO_DOUBLE ) return res; if( right->type < DAO_INTEGER || right->type > DAO_DOUBLE ) return res; L = DaoValue_GetDouble( left ); R = DaoValue_GetDouble( right ); return L == R ? 0 : (L < R ? -1 : 1); } switch( left->type ){ case DAO_NONE : return 0; case DAO_INTEGER : return number_compare( left->xInteger.value, right->xInteger.value ); case DAO_FLOAT : return number_compare( left->xFloat.value, right->xFloat.value ); case DAO_DOUBLE : return number_compare( left->xDouble.value, right->xDouble.value ); case DAO_COMPLEX : return DaoComplex_Compare( & left->xComplex, & right->xComplex ); #ifdef DAO_WITH_LONGINT case DAO_LONG : return DLong_Compare( left->xLong.value, right->xLong.value ); #endif case DAO_STRING : return DString_Compare( left->xString.data, right->xString.data ); case DAO_ENUM : return DaoEnum_Compare( & left->xEnum, & right->xEnum ); case DAO_TUPLE : return DaoTuple_Compare( & left->xTuple, & right->xTuple ); case DAO_LIST : return DaoList_Compare( & left->xList, & right->xList ); case DAO_CDATA : case DAO_CSTRUCT : case DAO_CTYPE : return DaoCstruct_Compare( left, right ); #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : return DaoArray_Compare( & left->xArray, & right->xArray ); #endif } return left < right ? -100 : 100; /* needed for map */ }
int DaoValue_CompareExt( DaoValue *left, DaoValue *right, DMap *cycmap ) { DMap *input = cycmap; void *pters[2]; int res = 0; if( left == right ) return 0; if( left == NULL || right == NULL ) return left < right ? -100 : 100; if( left->type != right->type ){ double L, R; res = left->type < right->type ? -100 : 100; if( left->type < DAO_BOOLEAN || left->type > DAO_FLOAT ) return res; if( right->type < DAO_BOOLEAN || right->type > DAO_FLOAT ) return res; L = DaoValue_GetFloat( left ); R = DaoValue_GetFloat( right ); return L == R ? 0 : (L < R ? -1 : 1); } switch( left->type ){ case DAO_TUPLE : case DAO_LIST : case DAO_OBJECT : case DAO_CDATA : case DAO_CSTRUCT : pters[0] = left; pters[1] = right; if( cycmap != NULL ){ DNode *it = DMap_Find( cycmap, pters ); if( it != NULL ) return left < right ? -100 : 100; } if( cycmap == NULL ) cycmap = DHash_New(DAO_DATA_VOID2,0); DMap_Insert( cycmap, pters, NULL ); break; } switch( left->type ){ case DAO_NONE : break; case DAO_BOOLEAN : res = number_compare( left->xBoolean.value, right->xBoolean.value ); break; case DAO_INTEGER : res = number_compare( left->xInteger.value, right->xInteger.value ); break; case DAO_FLOAT : res = number_compare( left->xFloat.value, right->xFloat.value ); break; case DAO_COMPLEX : res = DaoComplex_Compare( (DaoComplex*) left, (DaoComplex*) right ); break; case DAO_STRING : res = DString_CompareUTF8( left->xString.value, right->xString.value ); break; case DAO_ENUM : res = DaoEnum_Compare( (DaoEnum*) left, (DaoEnum*) right ); break; case DAO_TUPLE : res = DaoTuple_Compare( (DaoTuple*) left, (DaoTuple*) right, cycmap ); break; case DAO_LIST : res = DaoList_Compare( (DaoList*) left, (DaoList*) right, cycmap ); break; case DAO_OBJECT : res = DaoObject_Compare( (DaoObject*)left, (DaoObject*)right, cycmap ); break; case DAO_CDATA : case DAO_CSTRUCT : res = DaoCstruct_Compare( (DaoCstruct*)left, (DaoCstruct*)right, cycmap ); break; case DAO_TYPE : res = DaoType_Compare( (DaoType*) left, (DaoType*) right ); break; #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : res = DaoArray_Compare( (DaoArray*) left, (DaoArray*) right ); break; #endif default: res = left < right ? -100 : 100; break; /* Needed for map; */ } if( cycmap != input ) DMap_Delete( cycmap ); return res; }