/*
* JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jef.tools.string;
import jef.common.Entry;
/**
* @author jiyi
*/
public class Substring implements java.io.Serializable, Comparable<CharSequence>,CharSequence {
private static final long serialVersionUID = 3538223148105733732L;
private String source;
private int start;
private int end;
/*
* 比大小(non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(CharSequence o) {
int mlen=length();
int len=Math.min(mlen, o.length());
for(int i=0;i<len;i++){
char a=charAt(i);
char b=o.charAt(i);
if(a>b){
return 1;
}else if(a<b){
return -1;
}
}
if(mlen>o.length()){
return 1;
}else if(mlen<o.length()){
return -1;
}
return 0;
}
protected int getEnd() {
return end;
}
protected void setEnd(int end) {
this.end = end;
}
protected int getStart() {
return start;
}
protected void setStart(int start) {
this.start = start;
}
public char charAt(int index) {
return source.charAt(start + index);
}
public int length() {
return end - start;
}
public Substring sub(int startA,int endA){
int newStart = this.start + startA;
int newEnd = this.start + endA;
if (newStart < this.start)
throw new IndexOutOfBoundsException();
if (newEnd > end) {
throw new IndexOutOfBoundsException();
}
return new Substring(source, newStart, newEnd);
}
public CharSequence subSequence(int startA, int endA) {
return sub(startA,endA);
}
protected Substring subAbsoultOffset(int startA, int endA) {
if (startA < this.start)
throw new IllegalArgumentException();
if (endA > end) {
throw new IllegalArgumentException();
}
return new Substring(source, startA, endA);
}
public Substring(String source, int start, int end) {
this.source = source;
if (end > source.length()) {
throw new IllegalArgumentException("the end offset of Substring must not greater than the length.");
}
if (start < 0) {
throw new IllegalArgumentException("the begin of Substring must >=0");
}
if (start > end) {
throw new IllegalArgumentException("The begin (" + start
+ ") must not greater than end (" + end + ")");
}
this.start = start;
this.end = end;
}
public Substring(String s1, int i) {
this(s1,i,s1.length());
}
public Substring(String source) {
this.source = source;
this.start = 0;
this.end = source.length();
}
public String toString() {
return source.substring(start, end);
}
/**
* fromIndex 从左边数跳过的字符个数
*/
public int indexOf(char c, int fromIndex) {
for (int i = fromIndex; i < length(); i++) {
if (charAt(i) == c) {
return i;
}
}
return -1;
}
/**
* fromRightIndex 从右边数跳过的字符个数
*/
public int lastIndexOf(char c, int fromRightIndex) {
for (int i = length() - 1 - fromRightIndex; i > -1; i--) {
if (charAt(i) == c) {
return i;
}
}
return -1;
}
public int indexOf(String str, int fromIndex) {
char[] chs = str.toCharArray();
if (chs.length == 0)
return -1;
int skipChar = fromIndex;
while (true) {
int n = indexOf(chs[0], skipChar);
if (n > -1) {
if (matches(n, chs)) {
return n;
}
skipChar = n + 1;
} else {
return -1;
}
}
}
public int lastIndexOf(String str, int fromRightIndex) {
char[] chs = str.toCharArray();
int skipChar = fromRightIndex;
while (true) {
int x = skipChar + chs.length - 1;
int n = lastIndexOf(chs[0], x);
if (n > -1) {
if (matches(n, chs)) {
return n;
}
skipChar = length() - n;
} else {
return -1;
}
}
}
// 判断从第n开头的字符串是否和指定的系列相等
private boolean matches(int n, char[] chs) {
if (n + chs.length > length())
return false;
for (int i = 0; i < chs.length; i++) {
if (charAt(n + i) != chs[i]) {
return false;
}
}
return true;
}
public int lastIndexOf(char c) {
return lastIndexOf(c, 0);
}
public int indexOf(char c) {
return indexOf(c, 0);
}
public int lastIndexOf(String str) {
return lastIndexOf(str, 0);
}
public int indexOf(String str) {
return indexOf(str, 0);
}
/**
* 合并相邻的两个SubString, 如果不是从同一个Source建立的Substring会抛出异常。
*
* @param str1
* @return
*/
public static Substring merge(Substring str1, Substring str2) {
if (str1.source != str2.source) {
throw new IllegalArgumentException("two substring is not generate on the same string");
}
if (str1.start == str2.end) {
return new Substring(str1.source, str2.start, str1.end);
} else if (str1.end == str2.start) {
return new Substring(str1.source, str1.start, str2.end);
}
throw new IllegalArgumentException("the two Substring does not reached.");//不是相邻的。
}
public boolean startsWith(String key) {
return matches(0, key.toCharArray());
}
/**
* 是否以指定的任意字串开头,返回匹配到的长度最大的一个字串
*
* @param keys
* @return
*/
public String startsWithAny(String[] keys) {
String matched = null;
for (String key : keys) {
if (startsWith(key)) {
if (matched == null || key.length() > matched.length()) {
matched = key;
}
}
}
return matched;
}
public String endsWithAny(String[] keys) {
String matched = null;
for (String key : keys) {
if (endsWith(key)) {
if (matched == null || key.length() > matched.length()) {
matched = key;
}
}
}
return matched;
}
public boolean endsWith(String key) {
return matches(length() - key.length(), key.toCharArray());
}
public boolean isEmpty() {
return length() == 0;
}
public Character lastCharacter() {
int n = length();
if (n == 0)
return null;
return charAt(n - 1);
}
public Character firstCharacter() {
if (length() == 0)
return null;
return charAt(0);
}
public Substring siblingRight() {
return new Substring(source, end, source.length());
}
public Substring siblingLeft() {
return new Substring(source, 0, start);
}
/**
* 查找匹配字串中的任意一个,返回最先出现的那个关键字和位置
*
* @param ss
* @return
*/
public Entry<Integer, String> indexOfAny(String[] ss) {
int find = -1;
String key = null;
for (String str : ss) {
int n = source.indexOf(str);
if (n > -1 && (n < find || find == -1)) {
find = n;
key = str;
}
}
return new Entry<Integer, String>(find, key);
}
/**
* 从右向左查找匹配字串中的任意一个,返回最先出现的那个关键字和位置
*
* @param ss
* @return
*/
public Entry<Integer, String> lastIndexOfAny(String[] ss) {
int find = -1;
String key = null;
for (String str : ss) {
int n = source.lastIndexOf(str);
if (n > find || find == -1) {
find = n;
key = str;
}
}
return new Entry<Integer, String>(find, key);
}
/**
* 注意,此方法调用后是直接截取原对象上两边的空格,返回的也是原对象,并不会新建一个对象。
*
* @return
*/
public Substring trim() {
int tmp = -1;
for (int i = start; i < end; i++) {
if (source.charAt(i) == 32) {
tmp = i;
} else {
break;
}
}
if (tmp > -1)
start = tmp + 1;
tmp = -1;
for (int i = end - 1; i >= start; i--) {
if (source.charAt(i) == 32) {
tmp = i;
} else {
break;
}
}
if (tmp > -1)
end = tmp;
return this;
}
@Override
public int hashCode() {
int h = source.hashCode();
h=h+start*1024+end;
return h;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof CharSequence){
CharSequence cs=(CharSequence)obj;
if(this.length()!=cs.length())return false;
for(int i=0;i<this.length();i++){
if(this.charAt(i)!=cs.charAt(i))return false;
}
return true;
}else{
return false;
}
}
}