// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. /** * An abstract string representation. */ class ByteString implements SourceString { final List bytes; final int offset; final int length; int _hashCode; ByteString(List this.bytes, int this.offset, int this.length); abstract String get charset(); String slowToString() => new String.fromCharCodes( new Utf8Decoder(bytes, offset, length).decodeRest()); String toString() => "ByteString(${slowToString()})"; bool operator ==(other) { throw "should be overridden in subclass"; } Iterator iterator() => new Utf8Decoder(bytes, offset, length); int hashCode() { if (_hashCode === null) { _hashCode = computeHashCode(); } return _hashCode; } int computeHashCode() { int code = 1; int end = offset + length; for (int i = offset; i < end; i++) { code += 19 * code + bytes[i]; } return code; } printOn(StringBuffer sb) { sb.add(slowToString()); } bool isEmpty() => length == 0; bool isPrivate() => !isEmpty() && bytes[offset] === $_; String get stringValue() => null; } /** * A string that consists purely of 7bit ASCII characters. */ class AsciiString extends ByteString { final String charset = "ASCII"; AsciiString(List bytes, int offset, int length) : super(bytes, offset, length); static AsciiString of(List bytes, int offset, int length) { AsciiString string = new AsciiString(bytes, offset, length); return string; } Iterator iterator() => new AsciiStringIterator(bytes); SourceString copyWithoutQuotes(int initial, int terminal) { return new AsciiString(bytes, offset + initial, length - initial - terminal); } static AsciiString fromString(String string) { List bytes = string.charCodes(); return AsciiString.of(bytes, 0, bytes.length); } } class AsciiStringIterator implements Iterator { final List bytes; int offset; final int end; AsciiStringIterator(List bytes) : this.bytes = bytes, offset = 0, end = bytes.length; AsciiStringIterator.range(List bytes, int from, int length) : this.bytes = bytes, offset = from, end = from + length; bool hasNext() => offset < end; int next() => bytes[offset++]; } /** * A string that consists of characters that can be encoded as UTF-8. */ class Utf8String extends ByteString { final String charset = "UTF8"; Utf8String(List bytes, int offset, int length) : super(bytes, offset, length); static Utf8String of(List bytes, int offset, int length) { return new Utf8String(bytes, offset, length); } static Utf8String fromString(String string) { throw "not implemented yet"; } Iterator iterator() => new Utf8Decoder(bytes, 0, length); SourceString copyWithoutQuotes(int initial, int terminal) { assert((){ // Only allow dropping ASCII characters, to guarantee that // the resulting Utf8String is still valid. for (int i = 0; i < initial; i++) { if (bytes[offset + i] >= 0x80) return false; } for (int i = 0; i < terminal; i++) { if (bytes[offset + length - terminal + i] >= 0x80) return false; } return true; }); // TODO(lrn): Check that first and last bytes use the same type of quotes. return new Utf8String(bytes, offset + initial, length - initial - terminal); } } /** * A ByteString-valued token. */ class ByteStringToken extends Token { final ByteString value; ByteStringToken(PrecedenceInfo info, ByteString this.value, int charOffset) : super(info, charOffset); String toString() => value.toString(); }