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 * Prepends the stringly representation of boolean value into buffer,
143 * given the coder and final index. Index is measured in chars, not in bytes!
144 *
145 * @param index final char index in the buffer
146 * @param buf buffer to append to
147 * @param coder coder to add with
148 * @param value boolean value to encode
149 * @return new index
150 */
151 static int prepend(int index, byte[] buf, byte coder, boolean value) {
152 if (coder == String.LATIN1) {
153 if (value) {
154 buf[--index] = 'e';
155 buf[--index] = 'u';
156 buf[--index] = 'r';
157 buf[--index] = 't';
158 } else {
159 buf[--index] = 'e';
160 buf[--index] = 's';
161 buf[--index] = 'l';
162 buf[--index] = 'a';
163 buf[--index] = 'f';
164 }
165 } else {
166 if (value) {
167 StringUTF16.putChar(buf, --index, 'e');
168 StringUTF16.putChar(buf, --index, 'u');
169 StringUTF16.putChar(buf, --index, 'r');
170 StringUTF16.putChar(buf, --index, 't');
171 } else {
172 StringUTF16.putChar(buf, --index, 'e');
173 StringUTF16.putChar(buf, --index, 's');
174 StringUTF16.putChar(buf, --index, 'l');
175 StringUTF16.putChar(buf, --index, 'a');
176 StringUTF16.putChar(buf, --index, 'f');
177 }
178 }
179 return index;
180 }
181
182 /**
183 * Prepends the stringly representation of byte value into buffer,
184 * given the coder and final index. Index is measured in chars, not in bytes!
185 *
186 * @param index final char index in the buffer
187 * @param buf buffer to append to
188 * @param coder coder to add with
189 * @param value byte value to encode
190 * @return new index
191 */
192 static int prepend(int index, byte[] buf, byte coder, byte value) {
193 return prepend(index, buf, coder, (int)value);
194 }
195
196 /**
197 * Prepends the stringly representation of char 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 char value to encode
204 * @return new index
205 */
206 static int prepend(int index, byte[] buf, byte coder, char value) {
207 if (coder == String.LATIN1) {
208 buf[--index] = (byte) (value & 0xFF);
209 } else {
210 StringUTF16.putChar(buf, --index, value);
211 }
212 return index;
213 }
214
215 /**
216 * Prepends the stringly representation of short value into buffer,
217 * given the coder and final index. Index is measured in chars, not in bytes!
218 *
219 * @param index final char index in the buffer
220 * @param buf buffer to append to
221 * @param coder coder to add with
222 * @param value short value to encode
223 * @return new index
224 */
225 static int prepend(int index, byte[] buf, byte coder, short value) {
226 return prepend(index, buf, coder, (int)value);
227 }
228
229 /**
230 * Prepends the stringly representation of integer value into buffer,
231 * given the coder and final index. Index is measured in chars, not in bytes!
232 *
233 * @param index final char index in the buffer
234 * @param buf buffer to append to
235 * @param coder coder to add with
236 * @param value integer value to encode
237 * @return new index
238 */
239 static int prepend(int index, byte[] buf, byte coder, int value) {
240 if (coder == String.LATIN1) {
241 return Integer.getChars(value, index, buf);
242 } else {
243 return StringUTF16.getChars(value, index, buf);
244 }
245 }
246
247 /**
248 * Prepends the stringly representation of long value into buffer,
249 * given the coder and final index. Index is measured in chars, not in bytes!
250 *
251 * @param index final char index in the buffer
252 * @param buf buffer to append to
253 * @param coder coder to add with
254 * @param value long value to encode
255 * @return new index
256 */
257 static int prepend(int index, byte[] buf, byte coder, long value) {
258 if (coder == String.LATIN1) {
259 return Long.getChars(value, index, buf);
260 } else {
261 return StringUTF16.getChars(value, index, buf);
262 }
263 }
264
265 /**
266 * Prepends the stringly representation of String value into buffer,
267 * given the coder and final index. Index is measured in chars, not in bytes!
268 *
269 * @param index final char index in the buffer
270 * @param buf buffer to append to
271 * @param coder coder to add with
272 * @param value String value to encode
273 * @return new index
274 */
275 static int prepend(int index, byte[] buf, byte coder, String value) {
276 index -= value.length();
277 value.getBytes(buf, index, coder);
278 return index;
279 }
280
281 /**
282 * Instantiates the String with given buffer and coder
283 * @param buf buffer to use
284 * @param index remaining index
285 * @param coder coder to use
286 * @return String resulting string
287 */
288 static String newString(byte[] buf, int index, byte coder) {
289 // Use the private, non-copying constructor (unsafe!)
290 if (index != 0) {
291 throw new InternalError("Storage is not completely initialized, " + index + " bytes left");
292 }
293 return new String(buf, coder);
294 }
295
296 /**
297 * Provides the initial coder for the String.
298 * @return initial coder
299 */
300 static byte initialCoder() {
301 return String.COMPACT_STRINGS ? String.LATIN1 : String.UTF16;
302 }
303
304 }
|
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 exception on overflow.
41 * @param lengthCoder String length and coder
42 * @return lengthCoder
43 */
44 private static long checkOverflow(long lengthCoder) {
45 if ((int)lengthCoder >= 0) {
46 return lengthCoder;
47 }
48 throw new OutOfMemoryError("Overflow: String length out of range");
49 }
50
51 /**
52 * Mix value length and coder into current length and coder.
53 * @param current current length
54 * @param value value to mix in
55 * @return new length and coder
56 */
57 static long mix(long current, boolean value) {
58 return checkOverflow(current + (value ? 4 : 5));
59 }
60
61 /**
62 * Mix value length and coder into current length and coder.
63 * @param current current length
64 * @param value value to mix in
65 * @return new length and coder
66 */
67 static long mix(long current, byte value) {
68 return mix(current, (int)value);
69 }
70
71 /**
72 * Mix value length and coder into current length and coder.
73 * @param current current length
74 * @param value value to mix in
75 * @return new length and coder
76 */
77 static long mix(long current, char value) {
78 return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
79 }
80
81 /**
82 * Mix value length and coder into current length and coder.
83 * @param current current length
84 * @param value value to mix in
85 * @return new length and coder
86 */
87 static long mix(long current, short value) {
88 return mix(current, (int)value);
89 }
90
91 /**
92 * Mix value length and coder into current length and coder.
93 * @param current current length
94 * @param value value to mix in
95 * @return new length and coder
96 */
97 static long mix(long current, int value) {
98 return checkOverflow(current + Integer.stringSize(value));
99 }
100
101 /**
102 * Mix value length and coder into current length and coder.
103 * @param current current length
104 * @param value value to mix in
105 * @return new length and coder
106 */
107 static long mix(long current, long value) {
108 return checkOverflow(current + Long.stringSize(value));
109 }
110
111 /**
112 * Mix value length and coder into current length and coder.
113 * @param current current length
114 * @param value value to mix in
115 * @return new length and coder
116 */
117 static long mix(long current, String value) {
118 current += value.length();
119 if (value.coder() == String.UTF16) {
120 current |= UTF16;
121 }
122 return checkOverflow(current);
123 }
124
125 /**
126 * Prepends the stringly representation of boolean value into buffer,
127 * given the coder and final index. Index is measured in chars, not in bytes!
128 *
129 * @param indexCoder final char index in the buffer, along with coder packed
130 * into higher bits.
131 * @param buf buffer to append to
132 * @param value boolean value to encode
133 * @return updated index (coder value retained)
134 */
135 static long prepend(long indexCoder, byte[] buf, boolean value) {
136 int index = (int)indexCoder;
137 if (indexCoder < UTF16) {
138 if (value) {
139 buf[--index] = 'e';
140 buf[--index] = 'u';
141 buf[--index] = 'r';
142 buf[--index] = 't';
143 } else {
144 buf[--index] = 'e';
145 buf[--index] = 's';
146 buf[--index] = 'l';
147 buf[--index] = 'a';
148 buf[--index] = 'f';
149 }
150 return index;
151 } else {
152 if (value) {
153 StringUTF16.putChar(buf, --index, 'e');
154 StringUTF16.putChar(buf, --index, 'u');
155 StringUTF16.putChar(buf, --index, 'r');
156 StringUTF16.putChar(buf, --index, 't');
157 } else {
158 StringUTF16.putChar(buf, --index, 'e');
159 StringUTF16.putChar(buf, --index, 's');
160 StringUTF16.putChar(buf, --index, 'l');
161 StringUTF16.putChar(buf, --index, 'a');
162 StringUTF16.putChar(buf, --index, 'f');
163 }
164 return index | UTF16;
165 }
166 }
167
168 /**
169 * Prepends the stringly representation of byte value into buffer,
170 * given the coder and final index. Index is measured in chars, not in bytes!
171 *
172 * @param indexCoder final char index in the buffer, along with coder packed
173 * into higher bits.
174 * @param buf buffer to append to
175 * @param value byte value to encode
176 * @return updated index (coder value retained)
177 */
178 static long prepend(long indexCoder, byte[] buf, byte value) {
179 return prepend(indexCoder, buf, (int)value);
180 }
181
182 /**
183 * Prepends the stringly representation of char value into buffer,
184 * given the coder and final index. Index is measured in chars, not in bytes!
185 *
186 * @param indexCoder final char index in the buffer, along with coder packed
187 * into higher bits.
188 * @param buf buffer to append to
189 * @param value char value to encode
190 * @return updated index (coder value retained)
191 */
192 static long prepend(long indexCoder, byte[] buf, char value) {
193 if (indexCoder < UTF16) {
194 buf[(int)(--indexCoder)] = (byte) (value & 0xFF);
195 } else {
196 StringUTF16.putChar(buf, (int)(--indexCoder), value);
197 }
198 return indexCoder;
199 }
200
201 /**
202 * Prepends the stringly representation of short value into buffer,
203 * given the coder and final index. Index is measured in chars, not in bytes!
204 *
205 * @param indexCoder final char index in the buffer, along with coder packed
206 * into higher bits.
207 * @param buf buffer to append to
208 * @param value short value to encode
209 * @return updated index (coder value retained)
210 */
211 static long prepend(long indexCoder, byte[] buf, short value) {
212 return prepend(indexCoder, buf, (int)value);
213 }
214
215 /**
216 * Prepends the stringly representation of integer value into buffer,
217 * given the coder and final index. Index is measured in chars, not in bytes!
218 *
219 * @param indexCoder final char index in the buffer, along with coder packed
220 * into higher bits.
221 * @param buf buffer to append to
222 * @param value integer value to encode
223 * @return updated index (coder value retained)
224 */
225 static long prepend(long indexCoder, byte[] buf, int value) {
226 if (indexCoder < UTF16) {
227 return Integer.getChars(value, (int)indexCoder, buf);
228 } else {
229 return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16;
230 }
231 }
232
233 /**
234 * Prepends the stringly representation of long value into buffer,
235 * given the coder and final index. Index is measured in chars, not in bytes!
236 *
237 * @param indexCoder final char index in the buffer, along with coder packed
238 * into higher bits.
239 * @param buf buffer to append to
240 * @param value long value to encode
241 * @return updated index (coder value retained)
242 */
243 static long prepend(long indexCoder, byte[] buf, long value) {
244 if (indexCoder < UTF16) {
245 return Long.getChars(value, (int)indexCoder, buf);
246 } else {
247 return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16;
248 }
249 }
250
251 /**
252 * Prepends the stringly representation of String value into buffer,
253 * given the coder and final index. Index is measured in chars, not in bytes!
254 *
255 * @param indexCoder final char index in the buffer, along with coder packed
256 * into higher bits.
257 * @param buf buffer to append to
258 * @param value String value to encode
259 * @return updated index (coder value retained)
260 */
261 static long prepend(long indexCoder, byte[] buf, String value) {
262 indexCoder -= value.length();
263 if (indexCoder < UTF16) {
264 value.getBytes(buf, (int)indexCoder, String.LATIN1);
265 } else {
266 value.getBytes(buf, (int)indexCoder, String.UTF16);
267 }
268 return indexCoder;
269 }
270
271 /**
272 * Instantiates the String with given buffer and coder
273 * @param buf buffer to use
274 * @param indexCoder remaining index (should be zero) and coder
275 * @return String resulting string
276 */
277 static String newString(byte[] buf, long indexCoder) {
278 // Use the private, non-copying constructor (unsafe!)
279 if (indexCoder == LATIN1) {
280 return new String(buf, String.LATIN1);
281 } else if (indexCoder == UTF16) {
282 return new String(buf, String.UTF16);
283 } else {
284 throw new InternalError("Storage is not completely initialized, " + (int)indexCoder + " bytes left");
285 }
286 }
287
288 private static final long LATIN1 = (long)String.LATIN1 << 32;
289
290 private static final long UTF16 = (long)String.UTF16 << 32;
291
292 /**
293 * Provides the initial coder for the String.
294 * @return initial coder, adjusted into the upper half
295 */
296 static long initialCoder() {
297 return String.COMPACT_STRINGS ? LATIN1 : UTF16;
298 }
299
300 }
|