1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*******************************************************************************
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* Copyright (C) 1996-2005, International Business Machines Corporation and    *
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* others. All Rights Reserved.                                                *
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*******************************************************************************
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*******************************************************************************
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*/
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
114dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughespackage libcore.icu;
124dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes
134dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughesimport java.text.CollationKey;
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
16ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes * A concrete implementation of the abstract java.text.CollationKey.
17ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes */
184dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughespublic final class CollationKeyICU extends CollationKey {
19ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    /**
20ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * The key.
21ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     */
22ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    private final byte[] bytes;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    /**
25ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * Cached hash value.
26ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     */
27ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    private int hashCode;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
294dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes    CollationKeyICU(String source, byte[] bytes) {
30ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        super(source);
31ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        this.bytes = bytes;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
344dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes    @Override public int compareTo(CollationKey other) {
35ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        // Get the bytes from the other collation key.
36ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        final byte[] rhsBytes;
374dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes        if (other instanceof CollationKeyICU) {
384dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes            rhsBytes = ((CollationKeyICU) other).bytes;
39ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        } else {
40ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            rhsBytes = other.toByteArray();
41ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
43ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (bytes == null || bytes.length == 0) {
44ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            if (rhsBytes == null || rhsBytes.length == 0) {
45ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                return 0;
46ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            }
47ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return -1;
48ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        } else {
49ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            if (rhsBytes == null || rhsBytes.length == 0) {
50ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                return 1;
51ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            }
52ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        int count = Math.min(bytes.length, rhsBytes.length);
55ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        for (int i = 0; i < count; ++i) {
56ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            int s = bytes[i] & 0xff;
57ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            int t = rhsBytes[i] & 0xff;
58ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            if (s < t) {
59ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                return -1;
60ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            }
61ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            if (s > t) {
62ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                return 1;
63ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            }
64ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
65ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (bytes.length < rhsBytes.length) {
66ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return -1;
67ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
68ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (bytes.length > rhsBytes.length) {
69ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return 1;
70ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
71ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        return 0;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
744dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes    @Override public boolean equals(Object object) {
75ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (object == this) {
76ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return true;
77ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
78ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (!(object instanceof CollationKey)) {
79ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return false;
80ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
81ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        return compareTo((CollationKey) object) == 0;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    /**
85ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * Creates a hash code for this CollationKey.
86ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * Compute the hash by iterating sparsely over about 32 (up to 63) bytes
87ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * spaced evenly through the string.  For each byte, multiply the previous
88ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * hash value by a prime number and add the new byte in, like a linear
89ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * congruential random number generator, producing a pseudo-random
90ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * deterministic value well distributed over the output range.
91ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * @return hash value of collation key. Hash value is never 0.
92ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     * @stable ICU 2.4
93ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes     */
944dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes    @Override public int hashCode() {
95ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (hashCode == 0) {
96ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            if (bytes != null && bytes.length != 0) {
97ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                int len = bytes.length;
98ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                int inc = ((len - 32) / 32) + 1;
99ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                for (int i = 0; i < len;) {
100ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                    hashCode = (hashCode * 37) + bytes[i];
101ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                    i += inc;
102ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                }
103ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            }
104ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            if (hashCode == 0) {
105ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes                hashCode = 1;
106ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            }
107ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
108ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        return hashCode;
109ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    }
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1114dfae7b3e2b56160646c17d93b32b3ff495c0053Elliott Hughes    @Override public byte[] toByteArray() {
112ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (bytes == null || bytes.length == 0) {
113ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return null;
114ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
115ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        return bytes.clone();
116ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes    }
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
118