blob: 73dfd296a8ca3ca601dd4b61423ca27ba8e529d1 [file] [log] [blame]
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType;
public final class StringNode extends Node implements StringType {
private static final int NODE_STR_MARGIN = 16;
private static final int NODE_STR_BUF_SIZE = 24;
public static final StringNode EMPTY = new StringNode(null, Integer.MAX_VALUE, Integer.MAX_VALUE);
public char[] chars;
public int p;
public int end;
public int flag;
public StringNode() {
this.chars = new char[NODE_STR_BUF_SIZE];
}
public StringNode(final char[] chars, final int p, final int end) {
this.chars = chars;
this.p = p;
this.end = end;
setShared();
}
public StringNode(final char c) {
this();
chars[end++] = c;
}
/* Ensure there is ahead bytes available in node's buffer
* (assumes that the node is not shared)
*/
public void ensure(final int ahead) {
final int len = (end - p) + ahead;
if (len >= chars.length) {
final char[] tmp = new char[len + NODE_STR_MARGIN];
System.arraycopy(chars, p, tmp, 0, end - p);
chars = tmp;
}
}
/* COW and/or ensure there is ahead bytes available in node's buffer
*/
private void modifyEnsure(final int ahead) {
if (isShared()) {
final int len = (end - p) + ahead;
final char[] tmp = new char[len + NODE_STR_MARGIN];
System.arraycopy(chars, p, tmp, 0, end - p);
chars = tmp;
end = end - p;
p = 0;
clearShared();
} else {
ensure(ahead);
}
}
@Override
public int getType() {
return STR;
}
@Override
public String getName() {
return "String";
}
@Override
public String toString(final int level) {
final StringBuilder value = new StringBuilder();
value.append("\n bytes: '");
for (int i=p; i<end; i++) {
if (chars[i] >= 0x20 && chars[i] < 0x7f) {
value.append(chars[i]);
} else {
value.append(String.format("[0x%04x]", (int)chars[i]));
}
}
value.append("'");
return value.toString();
}
public int length() {
return end - p;
}
public StringNode splitLastChar() {
StringNode n = null;
if (end > p) {
final int prev = EncodingHelper.prevCharHead(p, end);
if (prev != -1 && prev > p) { /* can be splitted. */
n = new StringNode(chars, prev, end);
if (isRaw()) n.setRaw();
end = prev;
}
}
return n;
}
public boolean canBeSplit() {
return end > p && 1 < (end - p);
}
public void set(final char[] chars, final int p, final int end) {
this.chars = chars;
this.p = p;
this.end = end;
setShared();
}
public void cat(final char[] cat, final int catP, final int catEnd) {
final int len = catEnd - catP;
modifyEnsure(len);
System.arraycopy(cat, catP, chars, end, len);
end += len;
}
public void cat(final char c) {
modifyEnsure(1);
chars[end++] = c;
}
public void catCode(final int code) {
cat((char)code);
}
public void clear() {
if (chars.length > NODE_STR_BUF_SIZE) chars = new char[NODE_STR_BUF_SIZE];
flag = 0;
p = end = 0;
}
public void setRaw() {
flag |= NSTR_RAW;
}
public void clearRaw() {
flag &= ~NSTR_RAW;
}
public boolean isRaw() {
return (flag & NSTR_RAW) != 0;
}
public void setAmbig() {
flag |= NSTR_AMBIG;
}
public void clearAmbig() {
flag &= ~NSTR_AMBIG;
}
public boolean isAmbig() {
return (flag & NSTR_AMBIG) != 0;
}
public void setDontGetOptInfo() {
flag |= NSTR_DONT_GET_OPT_INFO;
}
public void clearDontGetOptInfo() {
flag &= ~NSTR_DONT_GET_OPT_INFO;
}
public boolean isDontGetOptInfo() {
return (flag & NSTR_DONT_GET_OPT_INFO) != 0;
}
public void setShared() {
flag |= NSTR_SHARED;
}
public void clearShared() {
flag &= ~NSTR_SHARED;
}
public boolean isShared() {
return (flag & NSTR_SHARED) != 0;
}
}