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