]> git.saurik.com Git - apple/hfs.git/blame - fsck_hfs/dfalib/SKeyCompare.c
hfs-366.30.3.tar.gz
[apple/hfs.git] / fsck_hfs / dfalib / SKeyCompare.c
CommitLineData
51e135ce
A
1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25
26#include "Scavenger.h"
27#include "BTree.h"
28#include "CaseFolding.h"
29
30
31SInt32 FastUnicodeCompare ( register ConstUniCharArrayPtr str1, register ItemCount length1,
32 register ConstUniCharArrayPtr str2, register ItemCount length2);
33
34//_______________________________________________________________________
35//
36// Routine: FastRelString
37//
38// Output: returns -1 if str1 < str2
39// returns 1 if str1 > str2
40// return 0 if equal
41//
42//_______________________________________________________________________
43
44SInt32 FastRelString( ConstStr255Param str1, ConstStr255Param str2 )
45{
46 SInt32 bestGuess;
47 UInt8 length, length2;
48
49
50 length = *(str1++);
51 length2 = *(str2++);
52
53 if (length == length2)
54 bestGuess = 0;
55 else if (length < length2)
56 bestGuess = -1;
57 else
58 {
59 bestGuess = 1;
60 length = length2;
61 }
62
63 while (length--)
64 {
65 UInt32 aChar, bChar;
66
67 aChar = *(str1++);
68 bChar = *(str2++);
69
70 if (aChar != bChar) /* If they don't match exacly, do case conversion */
71 {
72 UInt16 aSortWord, bSortWord;
73
74 aSortWord = gCompareTable[aChar];
75 bSortWord = gCompareTable[bChar];
76
77 if (aSortWord > bSortWord)
78 return 1;
79
80 if (aSortWord < bSortWord)
81 return -1;
82 }
83
84 /*
85 * If characters match exactly, then go on to next character
86 * immediately without doing any extra work.
87 */
88 }
89
90 /* if you got to here, then return bestGuess */
91 return bestGuess;
92}
93
94
95
96//
97// FastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
98//
99// IF RESULT
100// --------------------------
101// str1 < str2 => -1
102// str1 = str2 => 0
103// str1 > str2 => +1
104//
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.
110//
111// In pseudocode:
112//
113// Let c = source Unicode character
114// Let table[] = lower case table
115//
116// lower = table[highbyte(c)]
117// if (lower == 0)
118// lower = c
119// else
120// lower = table[lower+lowbyte(c)]
121//
122// if (lower == 0)
123// ignore this character
124//
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).
133//
134// Pseudocode:
135//
136// while (1) {
137// c1 = GetNextValidChar(str1) // returns zero if at end of string
138// c2 = GetNextValidChar(str2)
139//
140// if (c1 != c2) break // found a difference
141//
142// if (c1 == 0) // reached end of string on both strings at once?
143// return 0; // yes, so strings are equal
144// }
145//
146// // When we get here, c1 != c2. So, we just need to determine which one is less.
147// if (c1 < c2)
148// return -1;
149// else
150// return 1;
151//
152
153SInt32 FastUnicodeCompare ( register ConstUniCharArrayPtr str1, register ItemCount length1,
154 register ConstUniCharArrayPtr str2, register ItemCount length2)
155{
156 register UInt16 c1,c2;
157 register UInt16 temp;
158
159 while (1) {
160 /* Set default values for c1, c2 in case there are no more valid chars */
161 c1 = 0;
162 c2 = 0;
163
164 /* Find next non-ignorable char from str1, or zero if no more */
165 while (length1 && c1 == 0) {
166 c1 = *(str1++);
167 --length1;
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
170 }
171
172
173 /* Find next non-ignorable char from str2, or zero if no more */
174 while (length2 && c2 == 0) {
175 c2 = *(str2++);
176 --length2;
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
179 }
180
181 if (c1 != c2) /* found a difference, so stop looping */
182 break;
183
184 if (c1 == 0) /* did we reach the end of both strings at the same time? */
185 return 0; /* yes, so strings are equal */
186 }
187
188 if (c1 < c2)
189 return -1;
190 else
191 return 1;
192}
193
194
195