org.mobicents.media.server.utils.Text Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.media.server.utils;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/**
* Case insensitive text block representation.
*
* This class provides time deterministic and fast methods for creating
* and comparing short character strings like format names, attribute values, etc.
*
* @author kulikov
*/
public class Text implements CharSequence {
//reference on the local buffer
protected byte[] chars;
//the start position
protected int pos;
//the length of the string
protected int len;
/** points to the line separator */
private int linePointer;
private int hash = -1;
private byte zero_byte=(byte)'0';
private byte nine_byte=(byte)'9';
private byte a_byte=(byte)'a';
private byte f_byte=(byte)'f';
private byte A_byte=(byte)'A';
private byte F_byte=(byte)'F';
private byte minus_byte=(byte)'-';
/**
* Create an empty text object.
*
* This object later can be strained on some memory area
*/
public Text() {
}
/**
* Creates new object with specified text.
*
* @param another the text object.
*/
protected Text(Text another) {
this.chars = another.chars;
this.pos = another.pos;
this.len = another.len;
}
/**
* Creates new instance with specified text.
*
* @param s the text value.
*/
public Text(String s) {
this.chars = s.getBytes();
this.pos = 0;
this.len = chars.length;
}
/**
* Creates new text matching to specified integer number.
*
* @param i the integer number.
*/
public Text(int i) {
chars = new byte[10];
int remainder = i;
while (remainder >= 10) {
chars[len++] = (byte)(remainder % 10 + 48);
remainder /= 10;
}
chars[len++] = (byte)(remainder + 48);
int n = len/ 2;
byte b = 0;
for (int k = 0; k < n; k++) {
b = chars[len - 1 - k];
chars[len - 1 - k] = chars[k];
chars[k] = b;
}
pos = 0;
}
/**
* Creates new instance and straining it into memory.
* @param data memory
* @param pos initial position
* @param len the length from the initial position
*/
public Text(byte[] data, int pos, int len) {
this.chars = data;
this.pos = pos;
this.len = len;
}
/**
* Strains this object into the memory area.
*
* @param data the memory area
* @param pos the initial position
* @param len the length of area to use
*/
public void strain(byte[] data, int pos, int len) {
this.chars = data;
this.pos = pos;
this.len = len;
this.linePointer = 0;
}
/**
* (Non Java-doc.)
* @see java.lang.CharSequence#length()
*/
public int length() {
return len;
}
/**
* (Non Java-doc.)
* @see java.lang.CharSequence#charAt(int)
*/
public char charAt(int index) {
return (char) chars[pos + index];
}
/**
* Copies reference to another text object.
*
* @param destination the another text object
*/
public void copy(Text destination) {
destination.strain(chars, pos, len);
}
/**
* Copies data from this buffer to another buffer.
*
* @param destination the pointer to another buffer.
*/
public void duplicate(Text destination) {
System.arraycopy(chars, pos, destination.chars, destination.pos, len);
destination.len = len;
}
/**
* Divides text into parts using given separator and writes results
* into the parts array.
*
* @param separator the character used for splitting
* @param parts the array used to hold parts of the text
* @return the number of parts.
*/
public int divide(char separator, Text[] parts) {
int pointer = pos;
int limit = pos + len;
int mark = pointer;
int count = 0;
while (pointer < limit) {
if (chars[pointer] == separator) {
parts[count].strain(chars, mark, pointer - mark);
mark = pointer + 1;
count++;
if (count == parts.length - 1) {
break;
}
}
pointer++;
}
if(limit > mark)
{
parts[count].strain(chars, mark, limit - mark);
count++;
}
return count;
}
public int divide(char[] separators, Text[] parts) {
int pointer = pos;
int limit = pos + len;
int mark = pointer;
int count = 0;
int k = 0;
while (pointer < limit) {
if (chars[pointer] == separators[k]) {
parts[count].strain(chars, mark, pointer - mark);
mark = pointer + 1;
k++;
count++;
// if (count == parts.length - 1) {
// break;
// }
}
pointer++;
}
if (limit > mark) {
parts[count].strain(chars, mark, limit - mark);
count++;
}
return count;
}
/**
* (Non Java-doc.)
* @see java.lang.CharSequence#subSequence(int, int);
*/
public CharSequence subSequence(int start, int end) {
return subtext(start, end);
}
public Text subtext(int start, int end) {
return new Text(chars, this.pos + start, end - start);
}
public Text subtext(int start) {
return new Text(this.chars, this.pos + start, this.len);
}
/**
* Splits text into partitions.
*
* @param separator character used for partitioning
* @return array of text strings.
*/
public Collection split(char separator) {
int pointer = pos;
int limit = pos + len;
int mark = pointer;
ArrayList tokens = new ArrayList();
while (pointer < limit) {
if (chars[pointer] == separator) {
tokens.add(new Text(chars, mark, pointer - mark));
mark = pointer + 1;
}
pointer++;
}
tokens.add(new Text(chars, mark, limit - mark));
return tokens;
}
/**
* Splits text into partitions.
*
* @param separator character used for partitioning
* @return array of text strings.
*/
public Collection split(Text separator) {
ArrayList tokens = new ArrayList();
int pointer = pos;
int limit = pos + len;
int mark = pointer;
if(separator.length()==0)
{
tokens.add(new Text(chars, mark, pointer - mark));
return tokens;
}
int index=0;
while (pointer < limit) {
if (chars[pointer] == separator.charAt(index))
index++;
else
index=0;
if(index==separator.length())
{
tokens.add(new Text(chars, mark, pointer - mark));
mark = pointer + 1;
index=0;
}
pointer++;
}
tokens.add(new Text(chars, mark, limit - mark));
return tokens;
}
public int indexOf(Text value) {
int pointer = pos;
int limit = pos + len;
int mark = pointer;
if(value.length()==0)
return 0;
int index=0;
while (pointer < limit) {
if (chars[pointer] == value.charAt(index))
index++;
else
{
index=0;
mark++;
pointer=mark;
}
if(index==value.length())
return mark;
pointer++;
}
return -1;
}
public int indexOf(char value) {
int limit = this.pos + this.len;
for (int pointer = this.pos; pointer < limit; pointer++) {
if(value == this.chars[pointer]) {
return pointer;
}
}
return -1;
}
/**
* Removes whitespace from the head and tail of the string.
*
*/
public void trim() {
try
{
//cut white spaces from the head
while (len>0 && chars[pos] == ' ') {
pos++;
len--;
}
//cut from the end
while (len>0 && (chars[pos + len - 1] == ' ' || chars[pos + len - 1] == '\n' || chars[pos + len - 1] == '\r')) {
len--;
}
}
catch(Exception e)
{
System.out.println("len:" + len + ",pos:" + pos);
}
}
/**
* Extracts next line from this text.
*
* @return
*/
public Text nextLine() {
if (linePointer == 0) {
linePointer = pos;
} else {
linePointer++;
}
int mark = linePointer;
int limit = pos + len;
while (linePointer < limit && chars[linePointer] != '\n') {
linePointer++;
}
return new Text(chars, mark, linePointer - mark);
}
/**
* Shows is this text contains more lines.
*
* @return true if there are more lines
*/
public boolean hasMoreLines() {
return linePointer < pos + len;
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (!(other instanceof Text)) {
return false;
}
Text t = (Text) other;
if (this.len != t.len) {
return false;
}
//return this.hashCode() == t.hashCode();
return compareChars(t.chars, t.pos);
}
@Override
public int hashCode() {
if (hash == -1) {
hash = 67 * 7 + Arrays.hashCode(this.chars);
}
return hash;
}
/**
* Compares specified character string with current string.
* The upper and lower case characters are considered as equals.
*
* @param chars the string to be compared
* @return true if specified string equals to current
*/
private boolean compareChars(byte[] chars, int pos) {
for (int i = 0; i < len; i++) {
if (differentChars((char) this.chars[i + this.pos], (char) chars[i + pos])) return false;
}
return true;
}
/**
* Indicates whether the text starts with a certain pattern.
*
* @param pattern
* The pattern to match
* @return true
if this text starts with the pattern.
* Otherwise, or if the pattern is null, returns false
.
* @author hrosa
*/
public boolean startsWith(Text pattern) {
if (pattern == null) {
return false;
}
return this.subSequence(0, pattern.len).equals(pattern);
}
/**
* Compares two chars.
*
* @param c1 the first char
* @param c2 the second char
* @return true if first and second chars are different.
*/
private boolean differentChars(char c1, char c2) {
if (65 <= c1 && c1 < 97) {
c1 +=32;
}
if (65 <= c2 && c2 < 97) {
c2 +=32;
}
return c1 != c2;
}
@Override
public String toString() {
return new String(chars, pos, len).trim();
}
/**
* Converts string value to integer
* @return integer value
*/
public int toInteger() throws NumberFormatException {
int res = 0;
byte currChar;
int i=1;
currChar=chars[pos];
boolean isMinus=false;
if(currChar==minus_byte)
isMinus=true;
else if(currChar>=zero_byte && currChar<=nine_byte)
res+=currChar-zero_byte;
else
throw new NumberFormatException("value is not numeric");
for (; i < len; i++) {
currChar=chars[pos+i];
if(currChar>=zero_byte && currChar<=nine_byte)
{
res*=10;
res+=currChar-zero_byte;
}
else
throw new NumberFormatException("value is not numeric");
}
if(isMinus)
return 0-res;
else
return res;
}
/**
* Converts string value to long
* @return long value
*/
public long toLong() throws NumberFormatException {
long res = 0;
byte currChar;
int i=1;
currChar=chars[pos];
boolean isMinus=false;
if(currChar==minus_byte)
isMinus=true;
else if(currChar>=zero_byte && currChar<=nine_byte)
res+=currChar-zero_byte;
else
throw new NumberFormatException("value is not numeric");
for (; i < len; i++) {
currChar=chars[pos+i];
if(currChar>=zero_byte && currChar<=nine_byte)
{
res*=10;
res+=currChar-zero_byte;
}
else
throw new NumberFormatException("value is not numeric");
}
if(isMinus)
return 0-res;
else
return res;
}
public int hexToInteger() throws NumberFormatException {
int res = 0;
byte currChar;
for (int i = 0; i < len; i++) {
res<<=4;
currChar=chars[pos+i];
if(currChar>=zero_byte && currChar<=nine_byte)
res|=currChar-zero_byte;
else if(currChar>=a_byte && currChar<=f_byte)
res|=currChar-a_byte+10;
else if(currChar>=A_byte && currChar<=F_byte)
res|=currChar-a_byte+10;
else
{
System.out.println("THROWING 1");
throw new NumberFormatException("value is not numeric");
}
}
return res;
}
/**
* 10^a
*
* @param a the power
* @return the value of 10^a
*/
private int pow(int a) {
int res = 1;
for (int i = 0; i < a; i++) {
res *= 10;
}
return res;
}
/**
* Converts character to digit.
*
* @param pos the position of the character
* @return the digit value
*/
private int digit(int pos) {
return chars[pos] - 48;
}
/**
* Writes this text into byte buffer.
*
* @param buffer the buffer for writing.
*/
public void write(ByteBuffer buffer) {
buffer.put(chars, pos, len);
}
/**
* Copies substring from the current line upto the end to the specified destination.
*
* @param other the destination object
*/
public void copyRemainder(Text other) {
other.chars = this.chars;
other.pos = this.linePointer + 1;
other.len = this.len - this.linePointer - 1;
}
/**
* Checks does specified symbol is present in this text.
*
* @param c the character to verify.
* @return true if character c is presented in this text and false otherwise.
*/
public boolean contains(char c) {
for (int k = pos; k < len; k++) {
if (chars[k] == c) return true;
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy