1 /* 2 * Permission is hereby granted, free of charge, to any person obtaining a copy of 3 * this software and associated documentation files (the "Software"), to deal in 4 * the Software without restriction, including without limitation the rights to 5 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 6 * of the Software, and to permit persons to whom the Software is furnished to do 7 * so, subject to the following conditions: 8 * 9 * The above copyright notice and this permission notice shall be included in all 10 * copies or substantial portions of the Software. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 * SOFTWARE. 19 */ 20 package jdk.nashorn.internal.runtime.regexp.joni.ast; 21 22 import jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper; 23 import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType; 24 25 @SuppressWarnings("javadoc") 26 public final class StringNode extends Node implements StringType { 27 28 private static final int NODE_STR_MARGIN = 16; 29 private static final int NODE_STR_BUF_SIZE = 24; 30 public static final StringNode EMPTY = new StringNode(null, Integer.MAX_VALUE, Integer.MAX_VALUE); 31 32 public char[] chars; 33 public int p; 34 public int end; 35 36 public int flag; 37 38 public StringNode() { 39 this.chars = new char[NODE_STR_BUF_SIZE]; 40 } 41 42 public StringNode(final char[] chars, final int p, final int end) { 43 this.chars = chars; 44 this.p = p; 45 this.end = end; 46 setShared(); 47 } 48 49 public StringNode(final char c) { 50 this(); 51 chars[end++] = c; 52 } 53 54 /* Ensure there is ahead bytes available in node's buffer 55 * (assumes that the node is not shared) 56 */ 57 public void ensure(final int ahead) { 58 final int len = (end - p) + ahead; 59 if (len >= chars.length) { 60 final char[] tmp = new char[len + NODE_STR_MARGIN]; 61 System.arraycopy(chars, p, tmp, 0, end - p); 62 chars = tmp; 63 } 64 } 65 66 /* COW and/or ensure there is ahead bytes available in node's buffer 67 */ 68 private void modifyEnsure(final int ahead) { 69 if (isShared()) { 70 final int len = (end - p) + ahead; 71 final char[] tmp = new char[len + NODE_STR_MARGIN]; 72 System.arraycopy(chars, p, tmp, 0, end - p); 73 chars = tmp; 74 end -= p; 75 p = 0; 76 clearShared(); 77 } else { 78 ensure(ahead); 79 } 80 } 81 82 @Override 83 public int getType() { 84 return STR; 85 } 86 87 @Override 88 public String getName() { 89 return "String"; 90 } 91 92 @Override 93 public String toString(final int level) { 94 final StringBuilder value = new StringBuilder(); 95 value.append("\n bytes: '"); 96 for (int i=p; i<end; i++) { 97 if (chars[i] >= 0x20 && chars[i] < 0x7f) { 98 value.append(chars[i]); 99 } else { 100 value.append(String.format("[0x%04x]", (int)chars[i])); 101 } 102 } 103 value.append("'"); 104 return value.toString(); 105 } 106 107 public int length() { 108 return end - p; 109 } 110 111 public StringNode splitLastChar() { 112 StringNode n = null; 113 114 if (end > p) { 115 final int prev = EncodingHelper.prevCharHead(p, end); 116 if (prev != -1 && prev > p) { /* can be splitted. */ 117 n = new StringNode(chars, prev, end); 118 if (isRaw()) n.setRaw(); 119 end = prev; 120 } 121 } 122 return n; 123 } 124 125 public boolean canBeSplit() { 126 return end > p && 1 < (end - p); 127 } 128 129 public void set(final char[] chars, final int p, final int end) { 130 this.chars = chars; 131 this.p = p; 132 this.end = end; 133 setShared(); 134 } 135 136 public void cat(final char[] cat, final int catP, final int catEnd) { 137 final int len = catEnd - catP; 138 modifyEnsure(len); 139 System.arraycopy(cat, catP, chars, end, len); 140 end += len; 141 } 142 143 public void cat(final char c) { 144 modifyEnsure(1); 145 chars[end++] = c; 146 } 147 148 public void catCode(final int code) { 149 cat((char)code); 150 } 151 152 public void clear() { 153 if (chars.length > NODE_STR_BUF_SIZE) chars = new char[NODE_STR_BUF_SIZE]; 154 flag = 0; 155 p = end = 0; 156 } 157 158 public void setRaw() { 159 flag |= NSTR_RAW; 160 } 161 162 public void clearRaw() { 163 flag &= ~NSTR_RAW; 164 } 165 166 public boolean isRaw() { 167 return (flag & NSTR_RAW) != 0; 168 } 169 170 public void setAmbig() { 171 flag |= NSTR_AMBIG; 172 } 173 174 public void clearAmbig() { 175 flag &= ~NSTR_AMBIG; 176 } 177 178 public boolean isAmbig() { 179 return (flag & NSTR_AMBIG) != 0; 180 } 181 182 public void setDontGetOptInfo() { 183 flag |= NSTR_DONT_GET_OPT_INFO; 184 } 185 186 public void clearDontGetOptInfo() { 187 flag &= ~NSTR_DONT_GET_OPT_INFO; 188 } 189 190 public boolean isDontGetOptInfo() { 191 return (flag & NSTR_DONT_GET_OPT_INFO) != 0; 192 } 193 194 public void setShared() { 195 flag |= NSTR_SHARED; 196 } 197 198 public void clearShared() { 199 flag &= ~NSTR_SHARED; 200 } 201 202 public boolean isShared() { 203 return (flag & NSTR_SHARED) != 0; 204 } 205 }