Back to index

lightning-sunbird  0.9+nobinonly
nsAECompare.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Simon Fraser <sfraser@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 
00040 
00041 #include <StringCompare.h>
00042 
00043 #include "nsAEUtils.h"
00044 #include "nsAECompare.h"
00045 
00046 // ----------------------------------------------------------------------------------------
00047 
00048 Boolean AEComparisons::CompareTexts(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00049 {
00050        Boolean       result = false;
00051        
00052        short  compareResult;
00053        Handle  lhsHandle = 0, rhsHandle = 0;
00054        char   *lhs;
00055        char   *rhs;
00056        long          lhsSize;
00057        long          rhsSize;
00058        
00059        // FIXME:  this can leak lhsHandle if second conversion fails.
00060        if (DescToTextHandle(desc1, &lhsHandle) != noErr || DescToTextHandle(desc2, &rhsHandle) != noErr)
00061            goto fail;
00062        
00063        lhsSize = GetHandleSize(lhsHandle);
00064        HLock(lhsHandle);
00065        lhs = *(lhsHandle);
00066        
00067        rhsSize = GetHandleSize(rhsHandle);
00068        HLock(rhsHandle);
00069        rhs = *(rhsHandle);
00070 
00071        compareResult = ::CompareText(lhs, rhs, lhsSize, rhsSize, nil);
00072 
00073        switch (oper) 
00074        {
00075               case kAEEquals:
00076                      result = (compareResult == 0);
00077                      break;
00078               
00079               case kAELessThan:
00080                      result = (compareResult < 0);
00081                      break;
00082               
00083               case kAELessThanEquals:
00084                      result = (compareResult <= 0);
00085                      break;
00086               
00087               case kAEGreaterThan:
00088                      result = (compareResult > 0);
00089                      break;
00090               
00091               case kAEGreaterThanEquals:
00092                      result = (compareResult >= 0);
00093                      break;
00094               
00095               case kAEBeginsWith:
00096                      if (rhsSize > lhsSize)
00097                      {
00098                             result = false;
00099                      }
00100                      else
00101                      {
00102                             // compare only the number of characters in rhs
00103                             // begin comparing at the beginning of lhs
00104                             compareResult = CompareText(lhs, rhs, rhsSize, rhsSize, nil);
00105                             result = (compareResult == 0);
00106                      }
00107                      break;
00108                      
00109               case kAEEndsWith:
00110                      if (rhsSize > lhsSize)
00111                      {
00112                             result = false;
00113                      }
00114                      else
00115                      {
00116                             // compare only the number of characters in rhs
00117                             // begin comparing rhsSize characters from the end of lhs
00118                             // start 
00119                             
00120                             lhs += (lhsSize - rhsSize);
00121                             compareResult = CompareText(lhs, rhs, rhsSize, rhsSize, nil);
00122                             result = (compareResult == 0);
00123                      }
00124                      break;
00125 
00126               case kAEContains:
00127                      // Here I use an inefficient search strategy, but we're dealing with small amounts
00128                      // of text and by using CompareText(), we're doing the same style of comparison
00129                      // as in the other cases above.
00130                      
00131                      result = false;
00132                      while (lhsSize >= rhsSize)
00133                      {
00134                             compareResult = CompareText(lhs, rhs, rhsSize, rhsSize, nil);
00135                             if (compareResult == 0)
00136                             {
00137                                    result = true;
00138                                    break;
00139                             }
00140                             lhs++;
00141                             lhsSize--;
00142                      }
00143                      break;
00144 
00145               default:
00146                      ThrowOSErr(errAEBadTestKey);
00147        }
00148 
00149 fail:
00150     if (lhsHandle) DisposeHandle(lhsHandle);
00151     if (rhsHandle) DisposeHandle(rhsHandle);
00152        
00153        return result;
00154 }
00155 
00156 // ----------------------------------------------------------------------------------------
00157 
00158 Boolean AEComparisons::CompareEnumeration(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00159 {
00160        OSErr         err    = noErr;
00161        Boolean              result = false;
00162        long                 lhs;
00163        long                 rhs;
00164        StAEDesc             charDesc;
00165        
00166        // Make each number is a long integer (in case it's a short integer or other integer type) 
00167        // before extracting the data */
00168        
00169        err = AECoerceDesc(desc1, typeChar, &charDesc);
00170        ThrowIfOSErr(err);
00171 
00172        lhs = **(long **)(charDesc.dataHandle);
00173        AEDisposeDesc(&charDesc);
00174        
00175        err = AECoerceDesc(desc2, typeChar, &charDesc);
00176        ThrowIfOSErr(err);
00177 
00178        rhs = **(long **)charDesc.dataHandle;
00179        AEDisposeDesc(&charDesc);
00180        
00181        switch (oper) 
00182        {
00183               case kAEEquals:
00184                      result = (lhs == rhs);      // equality is the only test that makes sense for enumerators
00185                      break;
00186               
00187               default:
00188                      ThrowOSErr(errAEBadTestKey);
00189        }
00190 
00191        return result;
00192 }
00193 
00194 // ----------------------------------------------------------------------------------------
00195 
00196 Boolean AEComparisons::CompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00197 {
00198        OSErr         err    = noErr;
00199        Boolean              result = false;
00200        long                 lhs;
00201        long                 rhs;
00202        StAEDesc             longDesc;
00203        
00204        // Make each number is a long integer (in case it's a short integer or other integer type) 
00205        // before extracting the data */
00206        
00207        err = AECoerceDesc(desc1, typeLongInteger, &longDesc);
00208        ThrowIfOSErr(err);
00209 
00210        lhs = **(long **)(longDesc.dataHandle);
00211        AEDisposeDesc(&longDesc);
00212        
00213        err = AECoerceDesc(desc2, typeLongInteger, &longDesc);
00214        ThrowIfOSErr(err);
00215 
00216        rhs = **(long **)longDesc.dataHandle;
00217        AEDisposeDesc(&longDesc);
00218        
00219        switch (oper) 
00220        {
00221               case kAEEquals:
00222                      result = (lhs == rhs);
00223                      break;
00224               
00225               case kAELessThan:
00226                      result = (lhs < rhs);
00227                      break;
00228               
00229               case kAELessThanEquals:
00230                      result = (lhs <= rhs);
00231                      break;
00232               
00233               case kAEGreaterThan:
00234                      result = (lhs > rhs);
00235                      break;
00236               
00237               case kAEGreaterThanEquals:
00238                      result = (lhs >= rhs);
00239                      break;
00240               
00241               default:
00242                      ThrowOSErr(errAEBadTestKey);
00243        }
00244 
00245        return result;
00246 }
00247 
00248 // ----------------------------------------------------------------------------------------
00249 
00250 Boolean AEComparisons::CompareFixed(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00251 {
00252        OSErr         err    = noErr;
00253        Boolean              result = false;
00254        Fixed         lhs;
00255        Fixed         rhs;
00256        
00257        err = DescToFixed(desc1, &lhs);
00258        ThrowIfOSErr(err);
00259               
00260        err = DescToFixed(desc2, &rhs);
00261        ThrowIfOSErr(err);
00262        
00263        switch (oper) 
00264        {
00265               case kAEEquals:
00266                      result = (lhs == rhs);
00267                      break;
00268               
00269               case kAELessThan:
00270                      result = (lhs < rhs);
00271                      break;
00272               
00273               case kAELessThanEquals:
00274                      result = (lhs <= rhs);
00275                      break;
00276               
00277               case kAEGreaterThan:
00278                      result = (lhs > rhs);
00279                      break;
00280               
00281                      case kAEGreaterThanEquals:
00282                      result = (lhs >= rhs);
00283                      break;
00284               
00285               default:
00286                      ThrowOSErr(errAEBadTestKey);
00287        }
00288        
00289        return result;
00290 }
00291 
00292 // ----------------------------------------------------------------------------------------
00293 
00294 Boolean AEComparisons::CompareFloat(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00295 {
00296        OSErr  err    = noErr;
00297        Boolean       result = false;
00298        float          lhs;
00299        float   rhs;
00300        
00301        err = DescToFloat(desc1, &lhs);
00302        ThrowIfOSErr(err);
00303               
00304        err = DescToFloat(desc2, &rhs);
00305        ThrowIfOSErr(err);
00306        
00307        switch (oper) 
00308        {
00309               case kAEEquals:
00310                      result = (lhs == rhs);
00311                      break;
00312               
00313               case kAELessThan:
00314                      result = (lhs < rhs);
00315                      break;
00316               
00317               case kAELessThanEquals:
00318                      result = (lhs <= rhs);
00319                      break;
00320               
00321               case kAEGreaterThan:
00322                      result = (lhs > rhs);
00323                      break;
00324               
00325                      case kAEGreaterThanEquals:
00326                      result = (lhs >= rhs);
00327                      break;
00328               
00329               default:
00330                      ThrowOSErr(errAEBadTestKey);
00331        }
00332        
00333        return result;
00334 }
00335 
00336 // ----------------------------------------------------------------------------------------
00337 // Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE
00338 
00339 Boolean AEComparisons::CompareBoolean(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00340 {
00341        OSErr  err    = noErr;
00342        Boolean       result = false;
00343        
00344        Boolean       bool1  = ((**(char **)desc1->dataHandle) != 0);
00345        Boolean       bool2  = ((**(char **)desc2->dataHandle) != 0);
00346               
00347        if (oper == kAEEquals) 
00348               result = (bool1 == bool2);
00349        else
00350               ThrowOSErr(errAEBadTestKey);              // No other tests make sense
00351 
00352        return result;
00353 }
00354 
00355 // ----------------------------------------------------------------------------------------
00356 
00357 Boolean AEComparisons::CompareRGBColor(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00358 {
00359        OSErr  err = noErr;
00360        Boolean       result = false;
00361        
00362        RGBColor lhs;
00363        RGBColor rhs;
00364        
00365        err = DescToRGBColor(desc1, &lhs);
00366        ThrowIfOSErr(err);
00367               
00368        err = DescToRGBColor(desc2, &rhs);
00369        ThrowIfOSErr(err);
00370 
00371        if (oper == kAEEquals) 
00372               result = EqualRGB(lhs, rhs);
00373        else
00374               ThrowOSErr(errAEBadTestKey);              // No other tests make sense
00375 
00376        return result;
00377 }
00378 
00379 // ----------------------------------------------------------------------------------------
00380 
00381 Boolean AEComparisons::ComparePoint(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00382 {
00383        OSErr  err = noErr;
00384        Boolean       result = false;
00385        
00386        Point         lhs;
00387        Point         rhs;
00388        
00389        err = DescToPoint(desc1, &lhs);
00390        ThrowIfOSErr(err);
00391               
00392        err = DescToPoint(desc2, &rhs);
00393        ThrowIfOSErr(err);
00394               
00395        switch (oper)
00396        {
00397               case kAEEquals:
00398                      result = (lhs.h = rhs.h && lhs.v == rhs.v);
00399                      break;
00400                      
00401               case kAELessThan:
00402                      result = (lhs.h < rhs.h && lhs.v < rhs.v);
00403                      break;
00404               
00405               case kAELessThanEquals:
00406                      result = (lhs.h <= rhs.h && lhs.v <= rhs.v);
00407                      break;
00408               
00409               case kAEGreaterThan:
00410                      result = (lhs.h > rhs.h && lhs.v > rhs.v);
00411                      break;
00412               
00413               case kAEGreaterThanEquals:
00414                      result = (lhs.h >= rhs.h && lhs.v >= rhs.v);
00415                      break;
00416               
00417               default:
00418                      ThrowOSErr(errAEBadTestKey);              // No other tests make sense
00419        }
00420 
00421        return result;
00422 }
00423 
00424 // ----------------------------------------------------------------------------------------
00425 
00426 Boolean AEComparisons::CompareRect(DescType oper, const AEDesc *desc1, const AEDesc *desc2)
00427 {
00428        OSErr  err = noErr;
00429        Boolean       result = false;
00430        Rect          lhs;
00431        Rect          rhs;
00432        
00433        err = DescToRect(desc1, &lhs);
00434        ThrowIfOSErr(err);
00435               
00436        err = DescToRect(desc2, &rhs);
00437        ThrowIfOSErr(err);
00438               
00439        switch (oper)
00440        {
00441               // compare size AND location
00442               case kAEEquals:      
00443                      result = ((lhs.top == rhs.top) && (lhs.left == rhs.left) && (lhs.bottom == rhs.bottom) && (lhs.right == rhs.right));
00444                      break;
00445                      
00446               // compare size only on the rest of the tests
00447               case kAELessThan:    
00448                      result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left)));
00449                      break;
00450               
00451               case kAELessThanEquals:
00452                      result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left)));
00453                      break;
00454               
00455               case kAEGreaterThan:
00456                      result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left)));
00457                      break;
00458               
00459               case kAEGreaterThanEquals:
00460                      result = (((lhs.bottom - lhs.top) < (rhs.bottom - rhs.top)) && ((lhs.right - lhs.left) < (lhs.right - rhs.left)));
00461                      break;
00462               
00463               case kAEContains:
00464                      // Note: two identical Rects contain each other, according to this test:
00465                      result = ((lhs.top <= rhs.top) && (lhs.left <= rhs.left) && (lhs.bottom >= rhs.bottom) && (lhs.right >= rhs.right));
00466                      break;
00467                      
00468               default:
00469                      ThrowOSErr(errAEBadTestKey);              // No other tests make sense
00470        }
00471 
00472        return result;
00473 }
00474 
00475 #pragma mark -
00476 
00477 /*----------------------------------------------------------------------------
00478        TryPrimitiveComparison 
00479        
00480 ----------------------------------------------------------------------------*/
00481 
00482 Boolean AEComparisons::TryPrimitiveComparison(DescType comparisonOperator, const AEDesc *desc1, const AEDesc *desc2)
00483 {
00484        Boolean       result = false;
00485        
00486        // This has to handle all the data types used in the application's
00487        // object model implementation.
00488        switch (desc1->descriptorType) 
00489        {
00490               case typeChar:
00491                      result = CompareTexts(comparisonOperator, desc1, desc2);
00492                      break;
00493               
00494               case typeShortInteger:             // also covers typeSMInt           'shor'
00495               case typeLongInteger:              // also covers typeInteger  'long'
00496               case typeMagnitude:                //                                        'magn'
00497                      result = CompareInteger(comparisonOperator, desc1, desc2);
00498                      break;
00499 
00500               case typeEnumerated:
00501                      result = CompareEnumeration(comparisonOperator, desc1, desc2);
00502                      break;
00503               
00504               case typeFixed:
00505                      result = CompareFixed(comparisonOperator, desc1, desc2);
00506                      break;
00507 
00508               case typeFloat:
00509                      result = CompareFloat(comparisonOperator, desc1, desc2);
00510                      break;
00511               
00512               case typeBoolean:
00513                      result = CompareBoolean(comparisonOperator, desc1, desc2);
00514                      break;
00515                             
00516               case typeRGBColor:
00517                      result = CompareRGBColor(comparisonOperator, desc1, desc2);
00518                      break;
00519                             
00520               case typeQDRectangle:
00521                      result = CompareRect(comparisonOperator, desc1, desc2);
00522                      break;
00523                             
00524               case typeQDPoint:
00525                      result = ComparePoint(comparisonOperator, desc1, desc2);
00526                      break;
00527                             
00528               default:
00529                      ThrowOSErr(errAEWrongDataType);
00530        }
00531 
00532        return result;
00533 }