1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package java.lang; 25 26 /** 27 * Helper for string concatenation. These methods are mostly looked up with private lookups 28 * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle} 29 * combinators there. 30 */ 31 final class StringConcatHelper { 32 33 private StringConcatHelper() { 34 // no instantiation 35 } 36 37 /** 38 * Check for overflow, throw the exception on overflow. 39 * @param len String length 40 * @return length 41 */ 42 private static int checkOverflow(int len) { 43 if (len < 0) { 44 throw new OutOfMemoryError("Overflow: String length out of range"); 45 } 46 return len; 47 } 48 49 /** 50 * Mix value length into current length 51 * @param current current length 52 * @param value value to mix in 53 * @return new length 54 */ 55 static int mixLen(int current, boolean value) { 56 return checkOverflow(current + (value ? 4 : 5)); 57 } 58 59 /** 60 * Mix value length into current length 61 * @param current current length 62 * @param value value to mix in 63 * @return new length 64 */ 65 static int mixLen(int current, byte value) { 66 return mixLen(current, (int)value); 67 } 68 69 /** 70 * Mix value length into current length 71 * @param current current length 72 * @param value value to mix in 73 * @return new length 74 */ 75 static int mixLen(int current, char value) { 76 return checkOverflow(current + 1); 77 } 78 79 /** 80 * Mix value length into current length 81 * @param current current length 82 * @param value value to mix in 83 * @return new length 84 */ 85 static int mixLen(int current, short value) { 86 return mixLen(current, (int)value); 87 } 88 89 /** 90 * Mix value length into current length 91 * @param current current length 92 * @param value value to mix in 93 * @return new length 94 */ 95 static int mixLen(int current, int value) { 96 return checkOverflow(current + Integer.stringSize(value)); 97 } 98 99 /** 100 * Mix value length into current length 101 * @param current current length 102 * @param value value to mix in 103 * @return new length 104 */ 105 static int mixLen(int current, long value) { 106 return checkOverflow(current + Long.stringSize(value)); 107 } 108 109 /** 110 * Mix value length into current length 111 * @param current current length 112 * @param value value to mix in 113 * @return new length 114 */ 115 static int mixLen(int current, String value) { 116 return checkOverflow(current + value.length()); 117 } 118 119 /** 120 * Mix coder into current coder 121 * @param current current coder 122 * @param value value to mix in 123 * @return new coder 124 */ 125 static byte mixCoder(byte current, char value) { 126 return (byte)(current | (StringLatin1.canEncode(value) ? 0 : 1)); 127 } 128 129 /** 130 * Mix coder into current coder 131 * @param current current coder 132 * @param value value to mix in 133 * @return new coder 134 */ 135 static byte mixCoder(byte current, String value) { 136 return (byte)(current | value.coder()); 137 } 138 139 /** 140 * Mix coder into current coder 141 * @param current current coder 142 * @param value value to mix in 143 * @return new coder 144 */ 145 static byte mixCoder(byte current, boolean value) { 146 // Booleans are represented with Latin1 147 return current; 148 } 149 150 /** 151 * Mix coder into current coder 152 * @param current current coder 153 * @param value value to mix in 154 * @return new coder 155 */ 156 static byte mixCoder(byte current, byte value) { 157 // Bytes are represented with Latin1 158 return current; 159 } 160 161 /** 162 * Mix coder into current coder 163 * @param current current coder 164 * @param value value to mix in 165 * @return new coder 166 */ 167 static byte mixCoder(byte current, short value) { 168 // Shorts are represented with Latin1 169 return current; 170 } 171 172 /** 173 * Mix coder into current coder 174 * @param current current coder 175 * @param value value to mix in 176 * @return new coder 177 */ 178 static byte mixCoder(byte current, int value) { 179 // Ints are represented with Latin1 180 return current; 181 } 182 183 /** 184 * Mix coder into current coder 185 * @param current current coder 186 * @param value value to mix in 187 * @return new coder 188 */ 189 static byte mixCoder(byte current, long value) { 190 // Longs are represented with Latin1 191 return current; 192 } 193 194 /** 195 * Prepends the stringly representation of boolean value into buffer, 196 * given the coder and final index. Index is measured in chars, not in bytes! 197 * 198 * @param index final char index in the buffer 199 * @param buf buffer to append to 200 * @param coder coder to add with 201 * @param value boolean value to encode 202 * @return new index 203 */ 204 static int prepend(int index, byte[] buf, byte coder, boolean value) { 205 if (coder == String.LATIN1) { 206 if (value) { 207 buf[--index] = 'e'; 208 buf[--index] = 'u'; 209 buf[--index] = 'r'; 210 buf[--index] = 't'; 211 } else { 212 buf[--index] = 'e'; 213 buf[--index] = 's'; 214 buf[--index] = 'l'; 215 buf[--index] = 'a'; 216 buf[--index] = 'f'; 217 } 218 } else { 219 if (value) { 220 StringUTF16.putChar(buf, --index, 'e'); 221 StringUTF16.putChar(buf, --index, 'u'); 222 StringUTF16.putChar(buf, --index, 'r'); 223 StringUTF16.putChar(buf, --index, 't'); 224 } else { 225 StringUTF16.putChar(buf, --index, 'e'); 226 StringUTF16.putChar(buf, --index, 's'); 227 StringUTF16.putChar(buf, --index, 'l'); 228 StringUTF16.putChar(buf, --index, 'a'); 229 StringUTF16.putChar(buf, --index, 'f'); 230 } 231 } 232 return index; 233 } 234 235 /** 236 * Prepends the stringly representation of byte value into buffer, 237 * given the coder and final index. Index is measured in chars, not in bytes! 238 * 239 * @param index final char index in the buffer 240 * @param buf buffer to append to 241 * @param coder coder to add with 242 * @param value byte value to encode 243 * @return new index 244 */ 245 static int prepend(int index, byte[] buf, byte coder, byte value) { 246 return prepend(index, buf, coder, (int)value); 247 } 248 249 /** 250 * Prepends the stringly representation of char value into buffer, 251 * given the coder and final index. Index is measured in chars, not in bytes! 252 * 253 * @param index final char index in the buffer 254 * @param buf buffer to append to 255 * @param coder coder to add with 256 * @param value char value to encode 257 * @return new index 258 */ 259 static int prepend(int index, byte[] buf, byte coder, char value) { 260 if (coder == String.LATIN1) { 261 buf[--index] = (byte) (value & 0xFF); 262 } else { 263 StringUTF16.putChar(buf, --index, value); 264 } 265 return index; 266 } 267 268 /** 269 * Prepends the stringly representation of short value into buffer, 270 * given the coder and final index. Index is measured in chars, not in bytes! 271 * 272 * @param index final char index in the buffer 273 * @param buf buffer to append to 274 * @param coder coder to add with 275 * @param value short value to encode 276 * @return new index 277 */ 278 static int prepend(int index, byte[] buf, byte coder, short value) { 279 return prepend(index, buf, coder, (int)value); 280 } 281 282 /** 283 * Prepends the stringly representation of integer value into buffer, 284 * given the coder and final index. Index is measured in chars, not in bytes! 285 * 286 * @param index final char index in the buffer 287 * @param buf buffer to append to 288 * @param coder coder to add with 289 * @param value integer value to encode 290 * @return new index 291 */ 292 static int prepend(int index, byte[] buf, byte coder, int value) { 293 if (coder == String.LATIN1) { 294 return Integer.getChars(value, index, buf); 295 } else { 296 return Integer.getCharsUTF16(value, index, buf); 297 } 298 } 299 300 /** 301 * Prepends the stringly representation of long value into buffer, 302 * given the coder and final index. Index is measured in chars, not in bytes! 303 * 304 * @param index final char index in the buffer 305 * @param buf buffer to append to 306 * @param coder coder to add with 307 * @param value long value to encode 308 * @return new index 309 */ 310 static int prepend(int index, byte[] buf, byte coder, long value) { 311 if (coder == String.LATIN1) { 312 return Long.getChars(value, index, buf); 313 } else { 314 return Long.getCharsUTF16(value, index, buf); 315 } 316 } 317 318 /** 319 * Prepends the stringly representation of String value into buffer, 320 * given the coder and final index. Index is measured in chars, not in bytes! 321 * 322 * @param index final char index in the buffer 323 * @param buf buffer to append to 324 * @param coder coder to add with 325 * @param value String value to encode 326 * @return new index 327 */ 328 static int prepend(int index, byte[] buf, byte coder, String value) { 329 index -= value.length(); 330 value.getBytes(buf, index, coder); 331 return index; 332 } 333 334 /** 335 * Instantiates the String with given buffer and coder 336 * @param buf buffer to use 337 * @param coder coder to use 338 * @return String resulting string 339 */ 340 static String newString(byte[] buf, byte coder) { 341 // Use the private, non-copying constructor (unsafe!) 342 return new String(buf, coder); 343 } 344 345 /** 346 * Provides the initial coder for the String. 347 * @return initial coder 348 */ 349 static byte initialCoder() { 350 return String.COMPACT_STRINGS ? String.LATIN1 : String.UTF16; 351 } 352 353 }