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