1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.value; |
7 | |
8 | import java.sql.PreparedStatement; |
9 | import java.sql.SQLException; |
10 | import java.util.Arrays; |
11 | |
12 | import org.h2.engine.SysProperties; |
13 | import org.h2.util.MathUtils; |
14 | import org.h2.util.StringUtils; |
15 | import org.h2.util.Utils; |
16 | |
17 | /** |
18 | * Implementation of the BINARY data type. |
19 | * It is also the base class for ValueJavaObject. |
20 | */ |
21 | public class ValueBytes extends Value { |
22 | |
23 | private static final ValueBytes EMPTY = new ValueBytes(Utils.EMPTY_BYTES); |
24 | |
25 | /** |
26 | * The value. |
27 | */ |
28 | protected byte[] value; |
29 | |
30 | /** |
31 | * The hash code. |
32 | */ |
33 | protected int hash; |
34 | |
35 | protected ValueBytes(byte[] v) { |
36 | this.value = v; |
37 | } |
38 | |
39 | /** |
40 | * Get or create a bytes value for the given byte array. |
41 | * Clone the data. |
42 | * |
43 | * @param b the byte array |
44 | * @return the value |
45 | */ |
46 | public static ValueBytes get(byte[] b) { |
47 | if (b.length == 0) { |
48 | return EMPTY; |
49 | } |
50 | b = Utils.cloneByteArray(b); |
51 | return getNoCopy(b); |
52 | } |
53 | |
54 | /** |
55 | * Get or create a bytes value for the given byte array. |
56 | * Do not clone the date. |
57 | * |
58 | * @param b the byte array |
59 | * @return the value |
60 | */ |
61 | public static ValueBytes getNoCopy(byte[] b) { |
62 | if (b.length == 0) { |
63 | return EMPTY; |
64 | } |
65 | ValueBytes obj = new ValueBytes(b); |
66 | if (b.length > SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE) { |
67 | return obj; |
68 | } |
69 | return (ValueBytes) Value.cache(obj); |
70 | } |
71 | |
72 | @Override |
73 | public int getType() { |
74 | return Value.BYTES; |
75 | } |
76 | |
77 | @Override |
78 | public String getSQL() { |
79 | return "X'" + StringUtils.convertBytesToHex(getBytesNoCopy()) + "'"; |
80 | } |
81 | |
82 | @Override |
83 | public byte[] getBytesNoCopy() { |
84 | return value; |
85 | } |
86 | |
87 | @Override |
88 | public byte[] getBytes() { |
89 | return Utils.cloneByteArray(getBytesNoCopy()); |
90 | } |
91 | |
92 | @Override |
93 | protected int compareSecure(Value v, CompareMode mode) { |
94 | byte[] v2 = ((ValueBytes) v).value; |
95 | if (mode.isBinaryUnsigned()) { |
96 | return Utils.compareNotNullUnsigned(value, v2); |
97 | } |
98 | return Utils.compareNotNullSigned(value, v2); |
99 | } |
100 | |
101 | @Override |
102 | public String getString() { |
103 | return StringUtils.convertBytesToHex(value); |
104 | } |
105 | |
106 | @Override |
107 | public long getPrecision() { |
108 | return value.length; |
109 | } |
110 | |
111 | @Override |
112 | public int hashCode() { |
113 | if (hash == 0) { |
114 | hash = Utils.getByteArrayHash(value); |
115 | } |
116 | return hash; |
117 | } |
118 | |
119 | @Override |
120 | public Object getObject() { |
121 | return getBytes(); |
122 | } |
123 | |
124 | @Override |
125 | public void set(PreparedStatement prep, int parameterIndex) |
126 | throws SQLException { |
127 | prep.setBytes(parameterIndex, value); |
128 | } |
129 | |
130 | @Override |
131 | public int getDisplaySize() { |
132 | return MathUtils.convertLongToInt(value.length * 2L); |
133 | } |
134 | |
135 | @Override |
136 | public int getMemory() { |
137 | return value.length + 24; |
138 | } |
139 | |
140 | @Override |
141 | public boolean equals(Object other) { |
142 | return other instanceof ValueBytes |
143 | && Arrays.equals(value, ((ValueBytes) other).value); |
144 | } |
145 | |
146 | @Override |
147 | public Value convertPrecision(long precision, boolean force) { |
148 | if (value.length <= precision) { |
149 | return this; |
150 | } |
151 | int len = MathUtils.convertLongToInt(precision); |
152 | byte[] buff = new byte[len]; |
153 | System.arraycopy(value, 0, buff, 0, len); |
154 | return get(buff); |
155 | } |
156 | |
157 | } |