1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.thrift; 19 20 import java.io.Serializable; 21 import java.nio.ByteBuffer; 22 import java.util.Comparator; 23 import java.util.Iterator; 24 import java.util.List; 25 import java.util.Map; 26 import java.util.Set; 27 import java.util.SortedMap; 28 import java.util.TreeMap; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.Collection; 32 import java.util.Collections; 33 34 public final class TBaseHelper { 35 TBaseHelper()36 private TBaseHelper(){} 37 38 private static final Comparator comparator = new NestedStructureComparator(); 39 compareTo(Object o1, Object o2)40 public static int compareTo(Object o1, Object o2) { 41 if (o1 instanceof Comparable) { 42 return compareTo((Comparable)o1, (Comparable)o2); 43 } else if (o1 instanceof List) { 44 return compareTo((List)o1, (List)o2); 45 } else if (o1 instanceof Set) { 46 return compareTo((Set)o1, (Set)o2); 47 } else if (o1 instanceof Map) { 48 return compareTo((Map)o1, (Map)o2); 49 } else if (o1 instanceof byte[]) { 50 return compareTo((byte[])o1, (byte[])o2); 51 } else { 52 throw new IllegalArgumentException("Cannot compare objects of type " + o1.getClass()); 53 } 54 } 55 compareTo(boolean a, boolean b)56 public static int compareTo(boolean a, boolean b) { 57 return Boolean.compare(a, b); 58 } 59 compareTo(byte a, byte b)60 public static int compareTo(byte a, byte b) { 61 return Byte.compare(a, b); 62 } 63 compareTo(short a, short b)64 public static int compareTo(short a, short b) { 65 return Short.compare(a,b); 66 } 67 compareTo(int a, int b)68 public static int compareTo(int a, int b) { 69 return Integer.compare(a, b); 70 } 71 compareTo(long a, long b)72 public static int compareTo(long a, long b) { 73 return Long.compare(a, b); 74 } 75 compareTo(double a, double b)76 public static int compareTo(double a, double b) { 77 return Double.compare(a, b); 78 } 79 compareTo(String a, String b)80 public static int compareTo(String a, String b) { 81 return a.compareTo(b); 82 } 83 compareTo(byte[] a, byte[] b)84 public static int compareTo(byte[] a, byte[] b) { 85 int compare = compareTo(a.length, b.length); 86 if (compare == 0) { 87 for (int i = 0; i < a.length; i++) { 88 compare = compareTo(a[i], b[i]); 89 if (compare != 0) { 90 break; 91 } 92 } 93 } 94 return compare; 95 } 96 compareTo(Comparable a, Comparable b)97 public static int compareTo(Comparable a, Comparable b) { 98 return a.compareTo(b); 99 } 100 compareTo(List a, List b)101 public static int compareTo(List a, List b) { 102 int compare = compareTo(a.size(), b.size()); 103 if (compare == 0) { 104 for (int i = 0; i < a.size(); i++) { 105 compare = comparator.compare(a.get(i), b.get(i)); 106 if (compare != 0) { 107 break; 108 } 109 } 110 } 111 return compare; 112 } 113 compareTo(Set a, Set b)114 public static int compareTo(Set a, Set b) { 115 int compare = compareTo(a.size(), b.size()); 116 if (compare == 0) { 117 ArrayList sortedA = new ArrayList(a); 118 ArrayList sortedB = new ArrayList(b); 119 120 Collections.sort(sortedA, comparator); 121 Collections.sort(sortedB, comparator); 122 123 Iterator iterA = sortedA.iterator(); 124 Iterator iterB = sortedB.iterator(); 125 126 // Compare each item. 127 while (iterA.hasNext() && iterB.hasNext()) { 128 compare = comparator.compare(iterA.next(), iterB.next()); 129 if (compare != 0) { 130 break; 131 } 132 } 133 } 134 return compare; 135 } 136 compareTo(Map a, Map b)137 public static int compareTo(Map a, Map b) { 138 int lastComparison = compareTo(a.size(), b.size()); 139 if (lastComparison != 0) { 140 return lastComparison; 141 } 142 143 // Sort a and b so we can compare them. 144 SortedMap sortedA = new TreeMap(comparator); 145 sortedA.putAll(a); 146 Iterator<Map.Entry> iterA = sortedA.entrySet().iterator(); 147 SortedMap sortedB = new TreeMap(comparator); 148 sortedB.putAll(b); 149 Iterator<Map.Entry> iterB = sortedB.entrySet().iterator(); 150 151 // Compare each item. 152 while (iterA.hasNext() && iterB.hasNext()) { 153 Map.Entry entryA = iterA.next(); 154 Map.Entry entryB = iterB.next(); 155 lastComparison = comparator.compare(entryA.getKey(), entryB.getKey()); 156 if (lastComparison != 0) { 157 return lastComparison; 158 } 159 lastComparison = comparator.compare(entryA.getValue(), entryB.getValue()); 160 if (lastComparison != 0) { 161 return lastComparison; 162 } 163 } 164 165 return 0; 166 } 167 168 /** 169 * Comparator to compare items inside a structure (e.g. a list, set, or map). 170 */ 171 private static class NestedStructureComparator implements Comparator, Serializable { compare(Object oA, Object oB)172 public int compare(Object oA, Object oB) { 173 if (oA == null && oB == null) { 174 return 0; 175 } else if (oA == null) { 176 return -1; 177 } else if (oB == null) { 178 return 1; 179 } else if (oA instanceof List) { 180 return compareTo((List)oA, (List)oB); 181 } else if (oA instanceof Set) { 182 return compareTo((Set)oA, (Set)oB); 183 } else if (oA instanceof Map) { 184 return compareTo((Map)oA, (Map)oB); 185 } else if (oA instanceof byte[]) { 186 return compareTo((byte[])oA, (byte[])oB); 187 } else { 188 return compareTo((Comparable)oA, (Comparable)oB); 189 } 190 } 191 } 192 toString(Collection<ByteBuffer> bbs, StringBuilder sb)193 public static void toString(Collection<ByteBuffer> bbs, StringBuilder sb) { 194 Iterator<ByteBuffer> it = bbs.iterator(); 195 if (!it.hasNext()) { 196 sb.append("[]"); 197 } else { 198 sb.append("["); 199 while (true) { 200 ByteBuffer bb = it.next(); 201 org.apache.thrift.TBaseHelper.toString(bb, sb); 202 if (!it.hasNext()) { 203 sb.append("]"); 204 return; 205 } else { 206 sb.append(", "); 207 } 208 } 209 } 210 } 211 toString(ByteBuffer bb, StringBuilder sb)212 public static void toString(ByteBuffer bb, StringBuilder sb) { 213 byte[] buf = bb.array(); 214 215 int arrayOffset = bb.arrayOffset(); 216 int offset = arrayOffset + bb.position(); 217 int origLimit = arrayOffset + bb.limit(); 218 int limit = (origLimit - offset > 128) ? offset + 128 : origLimit; 219 220 for (int i = offset; i < limit; i++) { 221 if (i > offset) { 222 sb.append(" "); 223 } 224 sb.append(paddedByteString(buf[i])); 225 } 226 if (origLimit != limit) { 227 sb.append("..."); 228 } 229 } 230 paddedByteString(byte b)231 public static String paddedByteString(byte b) { 232 int extended = (b | 0x100) & 0x1ff; 233 return Integer.toHexString(extended).toUpperCase().substring(1); 234 } 235 byteBufferToByteArray(ByteBuffer byteBuffer)236 public static byte[] byteBufferToByteArray(ByteBuffer byteBuffer) { 237 if (wrapsFullArray(byteBuffer)) { 238 return byteBuffer.array(); 239 } 240 byte[] target = new byte[byteBuffer.remaining()]; 241 byteBufferToByteArray(byteBuffer, target, 0); 242 return target; 243 } 244 wrapsFullArray(ByteBuffer byteBuffer)245 public static boolean wrapsFullArray(ByteBuffer byteBuffer) { 246 return byteBuffer.hasArray() 247 && byteBuffer.position() == 0 248 && byteBuffer.arrayOffset() == 0 249 && byteBuffer.remaining() == byteBuffer.capacity(); 250 } 251 byteBufferToByteArray(ByteBuffer byteBuffer, byte[] target, int offset)252 public static int byteBufferToByteArray(ByteBuffer byteBuffer, byte[] target, int offset) { 253 int remaining = byteBuffer.remaining(); 254 System.arraycopy(byteBuffer.array(), 255 byteBuffer.arrayOffset() + byteBuffer.position(), 256 target, 257 offset, 258 remaining); 259 return remaining; 260 } 261 rightSize(ByteBuffer in)262 public static ByteBuffer rightSize(ByteBuffer in) { 263 if (in == null) { 264 return null; 265 } 266 if (wrapsFullArray(in)) { 267 return in; 268 } 269 return ByteBuffer.wrap(byteBufferToByteArray(in)); 270 } 271 copyBinary(final ByteBuffer orig)272 public static ByteBuffer copyBinary(final ByteBuffer orig) { 273 if (orig == null) { 274 return null; 275 } 276 ByteBuffer copy = ByteBuffer.wrap(new byte[orig.remaining()]); 277 if (orig.hasArray()) { 278 System.arraycopy(orig.array(), orig.arrayOffset() + orig.position(), copy.array(), 0, orig.remaining()); 279 } else { 280 orig.slice().get(copy.array()); 281 } 282 283 return copy; 284 } 285 copyBinary(final byte[] orig)286 public static byte[] copyBinary(final byte[] orig) { 287 return (orig == null) ? null : Arrays.copyOf(orig, orig.length); 288 } 289 hashCode(long value)290 public static int hashCode(long value) { 291 return Long.hashCode(value); 292 } 293 hashCode(double value)294 public static int hashCode(double value) { 295 return Double.hashCode(value); 296 } 297 } 298