forked from mozilla/rhino
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConsString.java
More file actions
103 lines (87 loc) · 3.21 KB
/
Copy pathConsString.java
File metadata and controls
103 lines (87 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.javascript;
import java.io.Serializable;
import java.util.ArrayDeque;
/**
* <p>This class represents a string composed of two components, each of which
* may be a <code>java.lang.String</code> or another ConsString.</p>
*
* <p>This string representation is optimized for concatenation using the "+"
* operator. Instead of immediately copying both components to a new character
* array, ConsString keeps references to the original components and only
* converts them to a String if either toString() is called or a certain depth
* level is reached.</p>
*
* <p>Note that instances of this class are only immutable if both parts are
* immutable, i.e. either Strings or ConsStrings that are ultimately composed
* of Strings.</p>
*
* <p>Both the name and the concept are borrowed from V8.</p>
*/
public class ConsString implements CharSequence, Serializable {
private static final long serialVersionUID = -8432806714471372570L;
private CharSequence left, right;
private final int length;
private boolean isFlat;
public ConsString(CharSequence str1, CharSequence str2) {
left = str1;
right = str2;
length = left.length() + right.length();
isFlat = false;
}
// Replace with string representation when serializing
private Object writeReplace() {
return this.toString();
}
@Override
public String toString() {
return isFlat ? (String)left : flatten();
}
private synchronized String flatten() {
if (!isFlat) {
final char[] chars = new char[length];
int charPos = length;
ArrayDeque<CharSequence> stack = new ArrayDeque<CharSequence>();
stack.addFirst(left);
CharSequence next = right;
do {
if (next instanceof ConsString) {
ConsString casted = (ConsString) next;
if (casted.isFlat) {
next = casted.left;
} else {
stack.addFirst(casted.left);
next = casted.right;
continue;
}
}
final String str = (String) next;
charPos -= str.length();
str.getChars(0, str.length(), chars, charPos);
next = stack.isEmpty() ? null : stack.removeFirst();
} while (next != null);
left = new String(chars);
right = "";
isFlat = true;
}
return (String)left;
}
@Override
public int length() {
return length;
}
@Override
public char charAt(int index) {
String str = isFlat ? (String)left : flatten();
return str.charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
String str = isFlat ? (String)left : flatten();
return str.substring(start, end);
}
}