2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include "Scavenger.h"
28 #include "CaseFolding.h"
31 SInt32
FastUnicodeCompare ( register ConstUniCharArrayPtr str1
, register ItemCount length1
,
32 register ConstUniCharArrayPtr str2
, register ItemCount length2
);
34 //_______________________________________________________________________
36 // Routine: FastRelString
38 // Output: returns -1 if str1 < str2
39 // returns 1 if str1 > str2
42 //_______________________________________________________________________
44 SInt32
FastRelString( ConstStr255Param str1
, ConstStr255Param str2
)
47 UInt8 length
, length2
;
53 if (length
== length2
)
55 else if (length
< length2
)
70 if (aChar
!= bChar
) /* If they don't match exacly, do case conversion */
72 UInt16 aSortWord
, bSortWord
;
74 aSortWord
= gCompareTable
[aChar
];
75 bSortWord
= gCompareTable
[bChar
];
77 if (aSortWord
> bSortWord
)
80 if (aSortWord
< bSortWord
)
85 * If characters match exactly, then go on to next character
86 * immediately without doing any extra work.
90 /* if you got to here, then return bestGuess */
97 // FastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
100 // --------------------------
105 // The lower case table starts with 256 entries (one for each of the upper bytes
106 // of the original Unicode char). If that entry is zero, then all characters with
107 // that upper byte are already case folded. If the entry is non-zero, then it is
108 // the _index_ (not byte offset) of the start of the sub-table for the characters
109 // with that upper byte. All ignorable characters are folded to the value zero.
113 // Let c = source Unicode character
114 // Let table[] = lower case table
116 // lower = table[highbyte(c)]
120 // lower = table[lower+lowbyte(c)]
123 // ignore this character
125 // To handle ignorable characters, we now need a loop to find the next valid character.
126 // Also, we can't pre-compute the number of characters to compare; the string length might
127 // be larger than the number of non-ignorable characters. Further, we must be able to handle
128 // ignorable characters at any point in the string, including as the first or last characters.
129 // We use a zero value as a sentinel to detect both end-of-string and ignorable characters.
130 // Since the File Manager doesn't prevent the NUL character (value zero) as part of a filename,
131 // the case mapping table is assumed to map u+0000 to some non-zero value (like 0xFFFF, which is
132 // an invalid Unicode character).
137 // c1 = GetNextValidChar(str1) // returns zero if at end of string
138 // c2 = GetNextValidChar(str2)
140 // if (c1 != c2) break // found a difference
142 // if (c1 == 0) // reached end of string on both strings at once?
143 // return 0; // yes, so strings are equal
146 // // When we get here, c1 != c2. So, we just need to determine which one is less.
153 SInt32
FastUnicodeCompare ( register ConstUniCharArrayPtr str1
, register ItemCount length1
,
154 register ConstUniCharArrayPtr str2
, register ItemCount length2
)
156 register UInt16 c1
,c2
;
157 register UInt16 temp
;
160 /* Set default values for c1, c2 in case there are no more valid chars */
164 /* Find next non-ignorable char from str1, or zero if no more */
165 while (length1
&& c1
== 0) {
168 if ((temp
= gLowerCaseTable
[c1
>>8]) != 0) // is there a subtable for this upper byte?
169 c1
= gLowerCaseTable
[temp
+ (c1
& 0x00FF)]; // yes, so fold the char
173 /* Find next non-ignorable char from str2, or zero if no more */
174 while (length2
&& c2
== 0) {
177 if ((temp
= gLowerCaseTable
[c2
>>8]) != 0) // is there a subtable for this upper byte?
178 c2
= gLowerCaseTable
[temp
+ (c2
& 0x00FF)]; // yes, so fold the char
181 if (c1
!= c2
) /* found a difference, so stop looping */
184 if (c1
== 0) /* did we reach the end of both strings at the same time? */
185 return 0; /* yes, so strings are equal */
195 //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
196 // Routine: CompareCatalogKeys
198 // Function: Compares two catalog keys (a search key and a trial key).
200 // Result: +n search key > trial key
201 // 0 search key = trial key
202 // -n search key < trial key
203 //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
206 CompareCatalogKeys(HFSCatalogKey
*searchKey
, HFSCatalogKey
*trialKey
)
208 HFSCatalogNodeID searchParentID
, trialParentID
;
211 searchParentID
= searchKey
->parentID
;
212 trialParentID
= trialKey
->parentID
;
214 if ( searchParentID
> trialParentID
) /* parent dirID is unsigned */
216 else if ( searchParentID
< trialParentID
)
218 else /* parent dirID's are equal, compare names */
219 result
= FastRelString(searchKey
->nodeName
, trialKey
->nodeName
);
226 * Routine: CompareExtendedCatalogKeys
228 * Function: Compares two large catalog keys (a search key and a trial key).
230 * Result: +n search key > trial key
231 * 0 search key = trial key
232 * -n search key < trial key
236 CompareExtendedCatalogKeys(HFSPlusCatalogKey
*searchKey
, HFSPlusCatalogKey
*trialKey
)
239 HFSCatalogNodeID searchParentID
, trialParentID
;
241 searchParentID
= searchKey
->parentID
;
242 trialParentID
= trialKey
->parentID
;
244 if ( searchParentID
> trialParentID
) // parent node IDs are unsigned
248 else if ( searchParentID
< trialParentID
)
252 else // parent node ID's are equal, compare names
254 if ( searchKey
->nodeName
.length
== 0 || trialKey
->nodeName
.length
== 0 )
255 result
= searchKey
->nodeName
.length
- trialKey
->nodeName
.length
;
257 result
= FastUnicodeCompare(&searchKey
->nodeName
.unicode
[0], searchKey
->nodeName
.length
,
258 &trialKey
->nodeName
.unicode
[0], trialKey
->nodeName
.length
);
266 * Routine: CaseSensitiveCatalogKeyCompare
268 * Function: Compares two catalog keys using a 16-bit binary comparison
269 * for the name portion of the key.
271 * Result: +n search key > trial key
272 * 0 search key = trial key
273 * -n search key < trial key
277 CaseSensitiveCatalogKeyCompare(HFSPlusCatalogKey
*searchKey
, HFSPlusCatalogKey
*trialKey
)
279 HFSCatalogNodeID searchParentID
, trialParentID
;
282 searchParentID
= searchKey
->parentID
;
283 trialParentID
= trialKey
->parentID
;
286 if (searchParentID
> trialParentID
) {
288 } else if (searchParentID
< trialParentID
) {
291 UInt16
* str1
= &searchKey
->nodeName
.unicode
[0];
292 UInt16
* str2
= &trialKey
->nodeName
.unicode
[0];
293 int length1
= searchKey
->nodeName
.length
;
294 int length2
= trialKey
->nodeName
.length
;
298 if (length1
< length2
) {
301 } else if (length1
> length2
) {
325 //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
326 // Routine: CompareExtentKeys
328 // Function: Compares two extent file keys (a search key and a trial key) for
330 //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
332 SInt32
CompareExtentKeys( const HFSExtentKey
*searchKey
, const HFSExtentKey
*trialKey
)
334 SInt32 result
; // ± 1
337 if (searchKey
->keyLength
!= kHFSExtentKeyMaximumLength
)
338 DebugStr("\pHFS: search Key is wrong length");
339 if (trialKey
->keyLength
!= kHFSExtentKeyMaximumLength
)
340 DebugStr("\pHFS: trial Key is wrong length");
343 result
= -1; // assume searchKey < trialKey
345 if (searchKey
->fileID
== trialKey
->fileID
) {
347 // FileNum's are equal; compare fork types
349 if (searchKey
->forkType
== trialKey
->forkType
) {
351 // Fork types are equal; compare allocation block number
353 if (searchKey
->startBlock
== trialKey
->startBlock
) {
355 // Everything is equal
361 // Allocation block numbers differ; determine sign
363 if (searchKey
->startBlock
> trialKey
->startBlock
)
369 // Fork types differ; determine sign
371 if (searchKey
->forkType
> trialKey
->forkType
)
377 // FileNums differ; determine sign
379 if (searchKey
->fileID
> trialKey
->fileID
)
388 //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
389 // Routine: CompareExtentKeysPlus
391 // Function: Compares two extent file keys (a search key and a trial key) for
393 //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
395 SInt32
CompareExtentKeysPlus( const HFSPlusExtentKey
*searchKey
, const HFSPlusExtentKey
*trialKey
)
397 SInt32 result
; // ± 1
400 if (searchKey
->keyLength
!= kHFSPlusExtentKeyMaximumLength
)
401 DebugStr("\pHFS: search Key is wrong length");
402 if (trialKey
->keyLength
!= kHFSPlusExtentKeyMaximumLength
)
403 DebugStr("\pHFS: trial Key is wrong length");
406 result
= -1; // assume searchKey < trialKey
408 if (searchKey
->fileID
== trialKey
->fileID
) {
410 // FileNum's are equal; compare fork types
412 if (searchKey
->forkType
== trialKey
->forkType
) {
414 // Fork types are equal; compare allocation block number
416 if (searchKey
->startBlock
== trialKey
->startBlock
) {
418 // Everything is equal
424 // Allocation block numbers differ; determine sign
426 if (searchKey
->startBlock
> trialKey
->startBlock
)
432 // Fork types differ; determine sign
434 if (searchKey
->forkType
> trialKey
->forkType
)
440 // FileNums differ; determine sign
442 if (searchKey
->fileID
> trialKey
->fileID
)
451 * Compare two attribute b-tree keys.
453 * The name portion of the key is compared using a 16-bit binary comparison.
454 * This is called from the b-tree code.
458 CompareAttributeKeys(const AttributeKey
*searchKey
, const AttributeKey
*trialKey
)
460 UInt32 searchFileID
, trialFileID
;
463 searchFileID
= searchKey
->cnid
;
464 trialFileID
= trialKey
->cnid
;
467 if (searchFileID
> trialFileID
) {
469 } else if (searchFileID
< trialFileID
) {
472 const UInt16
* str1
= searchKey
->attrName
;
473 const UInt16
* str2
= trialKey
->attrName
;
474 int length1
= searchKey
->attrNameLen
;
475 int length2
= trialKey
->attrNameLen
;
479 if (length1
< length2
) {
482 } else if (length1
> length2
) {
505 * Names are equal; compare startBlock
507 if (searchKey
->startBlock
== trialKey
->startBlock
)
510 return (searchKey
->startBlock
< trialKey
->startBlock
? -1 : 1);