1/* GENERATED SOURCE. DO NOT MODIFY. */ 2// © 2016 and later: Unicode, Inc. and others. 3// License & terms of use: http://www.unicode.org/copyright.html#License 4/* 5 ******************************************************************************* 6 * Copyright (C) 2015-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10package android.icu.impl; 11 12import java.nio.ByteBuffer; 13 14import android.icu.util.UResourceBundle; 15import android.icu.util.UResourceTypeMismatchException; 16 17// Class UResource is named consistently with the public class UResourceBundle, 18// in case we want to make it public at some point. 19 20/** 21 * ICU resource bundle key and value types. 22 * @hide Only a subset of ICU is exposed in Android 23 */ 24public final class UResource { 25 /** 26 * Represents a resource bundle item's key string. 27 * Avoids object creations as much as possible. 28 * Mutable, not thread-safe. 29 * For permanent storage, use clone() or toString(). 30 */ 31 public static final class Key implements CharSequence, Cloneable, Comparable<Key> { 32 // Stores a reference to the resource bundle key string bytes array, 33 // with an offset of the key, to avoid creating a String object 34 // until one is really needed. 35 // Alternatively, we could try to always just get the key String object, 36 // and cache it in the reader, and see if that performs better or worse. 37 private byte[] bytes; 38 private int offset; 39 private int length; 40 private String s; 41 42 /** 43 * Constructs an empty resource key string object. 44 */ 45 public Key() { 46 s = ""; 47 } 48 49 /** 50 * Constructs a resource key object equal to the given string. 51 */ 52 public Key(String s) { 53 setString(s); 54 } 55 56 private Key(byte[] keyBytes, int keyOffset, int keyLength) { 57 bytes = keyBytes; 58 offset = keyOffset; 59 length = keyLength; 60 } 61 62 /** 63 * Mutates this key for a new NUL-terminated resource key string. 64 * The corresponding ASCII-character bytes are not copied and 65 * must not be changed during the lifetime of this key 66 * (or until the next setBytes() call) 67 * and lifetimes of subSequences created from this key. 68 * 69 * @param keyBytes new key string byte array 70 * @param keyOffset new key string offset 71 */ 72 public Key setBytes(byte[] keyBytes, int keyOffset) { 73 bytes = keyBytes; 74 offset = keyOffset; 75 for (length = 0; keyBytes[keyOffset + length] != 0; ++length) {} 76 s = null; 77 return this; 78 } 79 80 /** 81 * Mutates this key to an empty resource key string. 82 */ 83 public Key setToEmpty() { 84 bytes = null; 85 offset = length = 0; 86 s = ""; 87 return this; 88 } 89 90 /** 91 * Mutates this key to be equal to the given string. 92 */ 93 public Key setString(String s) { 94 if (s.isEmpty()) { 95 setToEmpty(); 96 } else { 97 bytes = new byte[s.length()]; 98 offset = 0; 99 length = s.length(); 100 for (int i = 0; i < length; ++i) { 101 char c = s.charAt(i); 102 if (c <= 0x7f) { 103 bytes[i] = (byte)c; 104 } else { 105 throw new IllegalArgumentException('\"' + s + "\" is not an ASCII string"); 106 } 107 } 108 this.s = s; 109 } 110 return this; 111 } 112 113 /** 114 * {@inheritDoc} 115 * Does not clone the byte array. 116 */ 117 @Override 118 public Key clone() { 119 try { 120 return (Key)super.clone(); 121 } catch (CloneNotSupportedException cannotOccur) { 122 return null; 123 } 124 } 125 126 @Override 127 public char charAt(int i) { 128 assert(0 <= i && i < length); 129 return (char)bytes[offset + i]; 130 } 131 132 @Override 133 public int length() { 134 return length; 135 } 136 137 @Override 138 public Key subSequence(int start, int end) { 139 assert(0 <= start && start < length); 140 assert(start <= end && end <= length); 141 return new Key(bytes, offset + start, end - start); 142 } 143 144 /** 145 * Creates/caches/returns this resource key string as a Java String. 146 */ 147 @Override 148 public String toString() { 149 if (s == null) { 150 s = internalSubString(0, length); 151 } 152 return s; 153 } 154 155 private String internalSubString(int start, int end) { 156 StringBuilder sb = new StringBuilder(end - start); 157 for (int i = start; i < end; ++i) { 158 sb.append((char)bytes[offset + i]); 159 } 160 return sb.toString(); 161 } 162 163 /** 164 * Creates a new Java String for a sub-sequence of this resource key string. 165 */ 166 public String substring(int start) { 167 assert(0 <= start && start < length); 168 return internalSubString(start, length); 169 } 170 171 /** 172 * Creates a new Java String for a sub-sequence of this resource key string. 173 */ 174 public String substring(int start, int end) { 175 assert(0 <= start && start < length); 176 assert(start <= end && end <= length); 177 return internalSubString(start, end); 178 } 179 180 private boolean regionMatches(byte[] otherBytes, int otherOffset, int n) { 181 for (int i = 0; i < n; ++i) { 182 if (bytes[offset + i] != otherBytes[otherOffset + i]) { 183 return false; 184 } 185 } 186 return true; 187 } 188 189 private boolean regionMatches(int start, CharSequence cs, int n) { 190 for (int i = 0; i < n; ++i) { 191 if (bytes[offset + start + i] != cs.charAt(i)) { 192 return false; 193 } 194 } 195 return true; 196 } 197 198 @Override 199 public boolean equals(Object other) { 200 if (other == null) { 201 return false; 202 } else if (this == other) { 203 return true; 204 } else if (other instanceof Key) { 205 Key otherKey = (Key)other; 206 return length == otherKey.length && 207 regionMatches(otherKey.bytes, otherKey.offset, length); 208 } else { 209 return false; 210 } 211 } 212 213 public boolean contentEquals(CharSequence cs) { 214 if (cs == null) { 215 return false; 216 } 217 return this == cs || (cs.length() == length && regionMatches(0, cs, length)); 218 } 219 220 public boolean startsWith(CharSequence cs) { 221 int csLength = cs.length(); 222 return csLength <= length && regionMatches(0, cs, csLength); 223 } 224 225 public boolean endsWith(CharSequence cs) { 226 int csLength = cs.length(); 227 return csLength <= length && regionMatches(length - csLength, cs, csLength); 228 } 229 230 /** 231 * @return true if the substring of this key starting from the offset 232 * contains the same characters as the other sequence. 233 */ 234 public boolean regionMatches(int start, CharSequence cs) { 235 int csLength = cs.length(); 236 return csLength == (length - start) && regionMatches(start, cs, csLength); 237 } 238 239 @Override 240 public int hashCode() { 241 // Never return s.hashCode(), so that 242 // Key.hashCode() is the same whether we have cached s or not. 243 if (length == 0) { 244 return 0; 245 } 246 247 int h = bytes[offset]; 248 for (int i = 1; i < length; ++i) { 249 h = 37 * h + bytes[offset]; 250 } 251 return h; 252 } 253 254 @Override 255 public int compareTo(Key other) { 256 return compareTo((CharSequence)other); 257 } 258 259 public int compareTo(CharSequence cs) { 260 int csLength = cs.length(); 261 int minLength = length <= csLength ? length : csLength; 262 for (int i = 0; i < minLength; ++i) { 263 int diff = charAt(i) - cs.charAt(i); 264 if (diff != 0) { 265 return diff; 266 } 267 } 268 return length - csLength; 269 } 270 } 271 272 /** 273 * Interface for iterating over a resource bundle array resource. 274 * Does not use Java Iterator to reduce object creations. 275 */ 276 public interface Array { 277 /** 278 * @return The number of items in the array resource. 279 */ 280 public int getSize(); 281 /** 282 * @param i Array item index. 283 * @param value Output-only, receives the value of the i'th item. 284 * @return true if i is non-negative and less than getSize(). 285 */ 286 public boolean getValue(int i, Value value); 287 } 288 289 /** 290 * Interface for iterating over a resource bundle table resource. 291 * Does not use Java Iterator to reduce object creations. 292 */ 293 public interface Table { 294 /** 295 * @return The number of items in the array resource. 296 */ 297 public int getSize(); 298 /** 299 * @param i Array item index. 300 * @param key Output-only, receives the key of the i'th item. 301 * @param value Output-only, receives the value of the i'th item. 302 * @return true if i is non-negative and less than getSize(). 303 */ 304 public boolean getKeyAndValue(int i, Key key, Value value); 305 } 306 307 /** 308 * Represents a resource bundle item's value. 309 * Avoids object creations as much as possible. 310 * Mutable, not thread-safe. 311 */ 312 public static abstract class Value { 313 protected Value() {} 314 315 /** 316 * @return ICU resource type like {@link UResourceBundle#getType()}, 317 * for example, {@link UResourceBundle#STRING} 318 */ 319 public abstract int getType(); 320 321 /** 322 * @see UResourceBundle#getString() 323 * @throws UResourceTypeMismatchException if this is not a string resource 324 */ 325 public abstract String getString(); 326 327 /** 328 * @throws UResourceTypeMismatchException if this is not an alias resource 329 */ 330 public abstract String getAliasString(); 331 332 /** 333 * @see UResourceBundle#getInt() 334 * @throws UResourceTypeMismatchException if this is not an integer resource 335 */ 336 public abstract int getInt(); 337 338 /** 339 * @see UResourceBundle#getUInt() 340 * @throws UResourceTypeMismatchException if this is not an integer resource 341 */ 342 public abstract int getUInt(); 343 344 /** 345 * @see UResourceBundle#getIntVector() 346 * @throws UResourceTypeMismatchException if this is not an intvector resource 347 */ 348 public abstract int[] getIntVector(); 349 350 /** 351 * @see UResourceBundle#getBinary() 352 * @throws UResourceTypeMismatchException if this is not a binary-blob resource 353 */ 354 public abstract ByteBuffer getBinary(); 355 356 /** 357 * @throws UResourceTypeMismatchException if this is not an array resource 358 */ 359 public abstract Array getArray(); 360 361 /** 362 * @throws UResourceTypeMismatchException if this is not a table resource 363 */ 364 public abstract Table getTable(); 365 366 /** 367 * Is this a no-fallback/no-inheritance marker string? 368 * Such a marker is used for CLDR no-fallback data values of "∅∅∅" 369 * when enumerating tables with fallback from the specific resource bundle to root. 370 * 371 * @return true if this is a no-inheritance marker string 372 */ 373 public abstract boolean isNoInheritanceMarker(); 374 375 /** 376 * @return the array of strings in this array resource. 377 * @see UResourceBundle#getStringArray() 378 * @throws UResourceTypeMismatchException if this is not an array resource 379 * or if any of the array items is not a string 380 */ 381 public abstract String[] getStringArray(); 382 383 /** 384 * Same as 385 * <pre> 386 * if (getType() == STRING) { 387 * return new String[] { getString(); } 388 * } else { 389 * return getStringArray(); 390 * } 391 * </pre> 392 * 393 * @see #getString() 394 * @see #getStringArray() 395 * @throws UResourceTypeMismatchException if this is 396 * neither a string resource nor an array resource containing strings 397 */ 398 public abstract String[] getStringArrayOrStringAsArray(); 399 400 /** 401 * Same as 402 * <pre> 403 * if (getType() == STRING) { 404 * return getString(); 405 * } else { 406 * return getStringArray()[0]; 407 * } 408 * </pre> 409 * 410 * @see #getString() 411 * @see #getStringArray() 412 * @throws UResourceTypeMismatchException if this is 413 * neither a string resource nor an array resource containing strings 414 */ 415 public abstract String getStringOrFirstOfArray(); 416 417 /** 418 * Only for debugging. 419 */ 420 @Override 421 public String toString() { 422 switch(getType()) { 423 case UResourceBundle.STRING: 424 return getString(); 425 case UResourceBundle.INT: 426 return Integer.toString(getInt()); 427 case UResourceBundle.INT_VECTOR: 428 int[] iv = getIntVector(); 429 StringBuilder sb = new StringBuilder("["); 430 sb.append(iv.length).append("]{"); 431 if (iv.length != 0) { 432 sb.append(iv[0]); 433 for (int i = 1; i < iv.length; ++i) { 434 sb.append(", ").append(iv[i]); 435 } 436 } 437 return sb.append('}').toString(); 438 case UResourceBundle.BINARY: 439 return "(binary blob)"; 440 case UResourceBundle.ARRAY: 441 return "(array)"; 442 case UResourceBundle.TABLE: 443 return "(table)"; 444 default: // should not occur 445 return "???"; 446 } 447 } 448 } 449 450 /** 451 * Sink for ICU resource bundle contents. 452 */ 453 public static abstract class Sink { 454 /** 455 * Called once for each bundle (child-parent-...-root). 456 * The value is normally an array or table resource, 457 * and implementations of this method normally iterate over the 458 * tree of resource items stored there. 459 * 460 * @param key Initially the key string of the enumeration-start resource. 461 * Empty if the enumeration starts at the top level of the bundle. 462 * Reuse for output values from Array and Table getters. 463 * @param value Call getArray() or getTable() as appropriate. 464 * Then reuse for output values from Array and Table getters. 465 * @param noFallback true if the bundle has no parent; 466 * that is, its top-level table has the nofallback attribute, 467 * or it is the root bundle of a locale tree. 468 */ 469 public abstract void put(Key key, Value value, boolean noFallback); 470 } 471} 472