All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.util.text.CharSequenceSubSequence Maven / Gradle / Ivy

// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.

package com.intellij.util.text;

import com.intellij.openapi.util.text.CharSequenceWithStringHash;
import com.intellij.openapi.util.text.StringUtilRt;
import com.intellij.openapi.util.text.Strings;
import org.jetbrains.annotations.NotNull;

/**
 * {@code CharSequenceSubSequence} allows to save time and memory in text processing code. It avoids
 * creation of a new char array on every {@code subSequence(int, int)} call in contrast to {@link String#subSequence(int, int)},
 * which actually creates a new {@link String} instance every time it's invoked.
 * 

* The downside of using {@code CharSequenceSubSequence} is that it keeps reference to the original sequence, which may be large. * Therefore, results of text processing should always be stored as {@link String}, to allow garbage collection of the original sequence. *

* {@code CharSequenceSubSequence} implements `hashCode` and `equals` in such a way that it can be compared against {@link String} map keys * and set elements without creating a {@link String} instance. However, {@code CharSequenceSubSequence} should not be used * as a map key or set element, since it keeps reference to the original sequence and prevents its collection. **/ public class CharSequenceSubSequence implements CharSequence, CharArrayExternalizable, CharSequenceWithStringHash { private final CharSequence myChars; private final int myStart; private final int myEnd; public CharSequenceSubSequence(@NotNull CharSequence chars) { this(chars, 0, chars.length()); } public CharSequenceSubSequence(@NotNull CharSequence chars, int start, int end) { if (start < 0 || end > chars.length() || start > end) { throw new IndexOutOfBoundsException("chars sequence.length:" + chars.length() + ", start:" + start + ", end:" + end); } myChars = chars; myStart = start; myEnd = end; } @Override public final int length() { return myEnd - myStart; } @Override public final char charAt(int index) { return myChars.charAt(index + myStart); } @Override public @NotNull CharSequence subSequence(int start, int end) { if (start == myStart && end == myEnd) return this; return new CharSequenceSubSequence(myChars, myStart + start, myStart + end); } @Override public @NotNull String toString() { if (myChars instanceof String) return ((String) myChars).substring(myStart, myEnd); return new String(CharArrayUtil.fromSequence(myChars, myStart, myEnd)); } @NotNull CharSequence getBaseSequence() { return myChars; } @Override public void getChars(int start, int end, char @NotNull [] dest, int destPos) { assert end - start <= myEnd - myStart; CharArrayUtil.getChars(myChars, dest, start + myStart, destPos, end - start); } private transient int hash; @Override public int hashCode() { int h = hash; if (h == 0) { hash = h = Strings.stringHashCode(myChars, myStart, myEnd); } return h; } @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof CharSequence) { return StringUtilRt.equal(this, (CharSequence)obj, true); } else { return false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy