/*
* $Id: AnyString.java,v 1.75 2002/09/16 08:05:02 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.core;
import anvil.core.runtime.AnyFunction;
import anvil.script.Context;
import anvil.script.Function;
import anvil.java.util.BindingEnumeration;
import anvil.util.Conversions;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Comparator;
import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcherInput;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.Perl5Substitution;
import org.apache.oro.text.regex.StringSubstitution;
import org.apache.oro.text.regex.Substitution;
import org.apache.oro.text.regex.Util;
///
/// @class string
/// The <code>string</code> class represents character strings.
/// String is a sequence of characters.
/**
* class <code>AnyString</code>
*
* @author Jani Lehtim�ki
*/
public class AnyString extends AnySequence
{
/// @constructor string
/// Creates new string from the string representation of given parameter.
/// @synopsis string(object value)
public static final Object[] newInstance = { "value" };
public static final Any newInstance(Any value)
{
return value.toAnyString();
}
protected String _string;
protected int _hashcode = 0;
protected int _type = IS_NULL;
protected long _long = 0;
protected double _double = 0.0;
public AnyString(boolean bool)
{
_string = bool ? "true" : "false";
}
public AnyString(int integer)
{
_string = String.valueOf(integer);
}
public AnyString(double dbl)
{
_string = String.valueOf(dbl);
}
public AnyString(String string)
{
if (string == null) {
_string = "";
} else {
_string = string;
}
}
public boolean isCompatible(Any element)
{
int t = element.typeOf();
return (t == IS_STRING) || (t == IS_BUFFER) || (t == IS_BINARY);
}
public int getSize()
{
return _string.length();
}
public AnySequence setSize(int size)
{
int length = _string.length();
if (size < length) {
return new AnyString(_string.substring(0, size));
} else if (size > length) {
StringBuffer buffer =new StringBuffer(size);
buffer.append(_string);
size -= length;
while(size-->0) {
buffer.append(0);
}
return new AnyString(buffer.toString());
} else {
return this;
}
}
public AnySequence clear()
{
return new AnyString("");
}
public Any getElement(int index)
{
return ObjectPool.createChar(_string.charAt(index));
}
public AnySequence setElement(int index, Any element)
{
StringBuffer buffer = new StringBuffer(_string);
buffer.setCharAt(index, element.toChar());
return new AnyString(buffer.toString());
}
public AnySequence crop(int start, int length)
{
return new AnyString(_string.substring(start, start+length));
}
public AnySequence getSlice(int start, int length)
{
return new AnyString(_string.substring(start, start+length));
}
public AnySequence deleteSlice(int start, int length)
{
String string = _string;
int size = string.length();
StringBuffer buffer = new StringBuffer(size - length);
if (start > 0) {
buffer.append(string.substring(0, start));
}
if (start + length < size) {
buffer.append(string.substring(start+length, size));
}
return new AnyString(buffer.toString());
}
public AnySequence setSlice(int start, int length, Any element)
{
String string = _string;
int size = string.length();
char seq = element.toChar();
StringBuffer buffer = new StringBuffer(size + 1 - length);
if (start > 0) {
buffer.append(string.substring(0, start));
}
buffer.append(seq);
if (start + length < size) {
buffer.append(string.substring(start+length, size));
}
return new AnyString(buffer.toString());
}
public AnySequence setSlice(int start, int length, AnySequence sequence)
{
String string = _string;
int size = string.length();
String seq = sequence.toString();
int seq_length = seq.length();
StringBuffer buffer = new StringBuffer(size + seq_length - length);
if (start > 0) {
buffer.append(string.substring(0, start));
}
if (seq_length > 0) {
buffer.append(seq);
}
if (start + length < size) {
buffer.append(string.substring(start+length, size));
}
return new AnyString(buffer.toString());
}
public AnySequence append(AnySequence sequence)
{
return new AnyString(_string + sequence.toString());
}
public AnySequence append(Any element)
{
return new AnyString(_string + element.toString());
}
public AnySequence createSequence(Any element)
{
return new AnyString(element.toString());
}
public AnySequence createEmptySequence()
{
return new AnyString("");
}
public int compareAt(AnySequence sequence, int start, int length)
{
String haystack = _string;
String needle = sequence.toString();
int delta;
for(int i=0; i<length; i++) {
delta = haystack.charAt(start+i) - needle.charAt(i);
if (delta != 0) {
return (delta<0) ? -1 : ((delta>0) ? 1 : 0);
}
}
return 0;
}
public int compareAt(Any element, int start)
{
int delta = _string.charAt(start) - element.toChar();
return (delta<0) ? -1 : ((delta>0) ? 1 : 0);
}
public AnySequence fill(Any fill, int start, int length)
{
char[] array = _string.toCharArray();
java.util.Arrays.fill(array, start, start+length, fill.toChar());
return new AnyString(new String(array));
}
public AnySequence sort(int start, int length, Comparator comparator)
{
char[] array = _string.toCharArray();
java.util.Arrays.sort(array, start, start+length);
return new AnyString(new String(array));
}
public int search(Any element, Comparator comparator)
{
return java.util.Arrays.binarySearch(_string.toCharArray(), element.toChar());
}
public AnySequence swap(int index1, int index2)
{
char[] array = _string.toCharArray();
char ch = array[index1];
array[index1] = array[index2];
array[index2] = ch;
return new AnyString(new String(array));
}
public AnySequence reverse()
{
String string = _string;
int size = string.length();
StringBuffer buffer = new StringBuffer(size);
for(int p = size - 1; p>=0; p--) {
buffer.append(string.charAt(p));
}
return new AnyString(buffer.toString());
}
public int typeOf()
{
return IS_STRING;
}
public int sizeOf()
{
return _string.length();
}
public boolean isMutable()
{
return false;
}
public boolean isString()
{
return true;
}
public final anvil.script.ClassType classOf() {
return __class__;
}
public boolean toBoolean()
{
return _string.length() > 0;
}
private void parse()
{
int n = _string.length();
if (n == 0) {
return;
}
char ch = 0;
int i = 0;
if (n>0) {
ch = _string.charAt(0);
if (ch == '-' || ch == '+') {
i++;
}
}
while(i<n && Character.isDigit((ch = _string.charAt(i)))) {
i++;
}
_type = IS_STRING;
if (i<n) {
if (ch == '.' || ch == 'e' || ch == 'E') {
try {
_double = Double.parseDouble(_string);
_long = (long)_double;
_type = IS_DOUBLE;
} catch (NumberFormatException e) {
}
}
} else {
try {
_long = Long.parseLong(_string);
_double = (double)_long;
_type = IS_INT;
} catch (NumberFormatException e) {
}
}
}
public Any coerce()
{
if (_type == IS_NULL) {
parse();
}
switch(_type) {
case IS_INT:
return Any.create(_long);
case IS_DOUBLE:
return Any.create(_double);
case IS_STRING:
default:
return this;
}
}
public int toInt()
{
if (_type == IS_NULL) {
parse();
}
return (int)_long;
}
public long toLong()
{
if (_type == IS_NULL) {
parse();
}
return _long;
}
public double toDouble()
{
if (_type == IS_NULL) {
parse();
}
return _double;
}
public char toChar()
{
return (_string.length()>0) ? _string.charAt(0) : ' ';
}
public String toString()
{
return _string;
}
public byte[] toBinary()
{
return anvil.util.Conversions.getBytes(_string);
}
public Writer toAnvil(Writer writer) throws IOException
{
writer.write('"');
writer.write(anvil.util.Conversions.escape(_string, true));
writer.write('"');
return writer;
}
public Writer toJava(Writer writer) throws IOException
{
writer.write("anvil.core.Any.create(\"");
writer.write(anvil.util.Conversions.escape(_string, false));
writer.write('"');
writer.write(')');
return writer;
}
public anvil.codec.Code toCode(anvil.codec.Code code)
{
anvil.codec.ConstantPool pool = code.getPool();
int clazz = pool.addClass("anvil/core/AnyString");
code.anew(clazz);
code.dup();
code.astring(_string);
code.invokespecial(pool.addMethodRef(clazz, "<init>", "(Ljava/lang/String;)V"));
return code;
}
public Object toObject()
{
return _string;
}
public Any toAnyString()
{
return this;
}
public int hashCode()
{
if (_type == IS_NULL) {
parse();
}
switch(_type) {
case IS_INT:
return (int)_long;
case IS_DOUBLE:
return (int)_double;
default:
if (_hashcode == 0) {
_hashcode = _string.hashCode();
}
return _hashcode;
}
}
public Any increase() {
if (_type == IS_NULL) {
parse();
}
switch(_type) {
case IS_INT:
return Any.create(_long + 1);
case IS_DOUBLE:
return Any.create(_double + 1.0);
default:
return this;
}
}
public Any decrease() {
if (_type == IS_NULL) {
parse();
}
switch(_type) {
case IS_INT:
return Any.create(_long - 1);
case IS_DOUBLE:
return Any.create(_double - 1.0);
default:
return this;
}
}
public Any minus() {
if (_type == IS_NULL) {
parse();
}
switch(_type) {
case IS_INT:
return Any.create(-_long);
case IS_DOUBLE:
return Any.create(-_double);
default:
return this;
}
}
public Any plus() {
if (_type == IS_NULL) {
parse();
}
switch(_type) {
case IS_INT:
return Any.create(_long);
case IS_DOUBLE:
return Any.create(_double);
default:
return this;
}
}
public Any add(Any other)
{
return Any.create(_string + other.toString());
}
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj instanceof AnyString) {
return _string.equals(obj.toString());
}
return false;
}
protected int compare(Any other)
{
return _string.compareTo(other.toString());
}
public void serialize(Serializer serializer) throws IOException
{
if (serializer.register(this)) {
return;
}
String string = _string;
serializer.write('s');
serializer.write(string.length());
serializer.write(':');
serializer.writeUTF16(string);
}
public BindingEnumeration enumeration()
{
return new StringEnumeration(_string);
}
/********* Exposed methods ************/
/// @method length
/// Returns the length of this string.
/// @synopsis int length()
public Any m_length()
{
return Any.create(_string.length());
}
/// @method unquote
/// Unquotes all html entities from this string.
/// @synopsis string unquote()
public Any m_unquote()
{
return Any.create(Conversions.decodeEntities(_string));
}
/// @method quote
/// Converts all applicable characters with corresponding
/// html entity.
/// @synopsis string quote()
public Any m_quote()
{
return Any.create(Conversions.encodeEntities(_string));
}
/// @method quoteMeta
/// Converts all applicable characters under >127 with corresponding
/// html entity.
/// @synopsis string quoteMeta()
public Any m_quoteMeta()
{
return Any.create(Conversions.encodeMetaEntities(_string));
}
/// @method quoteText
/// Converts all applicable characters over >127 with corresponding
/// html entity.
/// @synopsis string quoteText()
public Any m_quoteText()
{
return Any.create(Conversions.encodeText(_string));
}
/// @method compress
/// Compresses consequtive white space characeters into single
/// space.
/// @synopsis string compress()
public Any m_compress()
{
return Any.create(Conversions.compress(_string));
}
/// @method capitalize
/// Capitalizes the first character of all words.
/// @synopsis string capitalize()
public Any m_capitalize()
{
return Any.create(Conversions.capitalizeAllWords(_string));
}
/// @method capitalizeFirst
/// Capitalizes first character of first word.
/// @synopsis string capitalizeFirst()
public Any m_capitalizeFirst()
{
return Any.create(Conversions.capitalizeFirstWord(_string));
}
/// @method nowrap
/// Converts white spaces into <code>&nbsp;</code>.
/// @synopsis string nowrap()
public Any m_nowrap()
{
return Any.create(Conversions.nowrap(_string));
}
/// @method encodeURL
/// URL encodes this string.
/// @synopsis string encodeURL()
public Any m_encodeURL()
{
return Any.create(Conversions.URLEncode(_string));
}
/// @method decodeURL
/// Decodes URL encoding from this string.
/// @synopsis string decodeURL()
public Any m_decodeURL()
{
return Any.create(Conversions.URLDecode(_string));
}
/// @method encode
/// URL encodes this string.
/// @synopsis string encode()
public Any m_encode()
{
return Any.create(Conversions.URLEncode(_string));
}
/// @method decode
/// Decodes URL encoding from this string.
/// @synopsis string decode()
public Any m_decode()
{
return Any.create(Conversions.URLDecode(_string));
}
/// @method escape
/// Escapes string using the rules of anvil string literal.
/// @synopsis string escape()
public Any m_escape()
{
return Any.create(Conversions.escape(_string));
}
/// @method unescape
/// Unescapes backslash quotes.
/// @synopsis string unescape()
/// @synopsis string unescape(boolean withQuotes)
public static final Object[] p_unescape = new Object[] { "*hasQuotes", Boolean.FALSE };
public Any m_unescape(boolean hasQuotes)
{
return Any.create(Conversions.unescape(_string, hasQuotes));
}
/// @method nl2br
/// Convers all line feeds into <code><br>\n</code>
/// @synopsis string nl2br()
public Any m_nl2br()
{
return Any.create(Conversions.nl2br(_string));
}
/// @method toUpper
/// Converts all lower case characeters into corresponding upper case
/// characeters.
/// @synopsis string toUpper()
public Any m_toUpper()
{
return Any.create(_string.toUpperCase());
}
/// @method toLower
/// Converts all upper case characeters into corresponding lower case
/// characeters.
/// @synopsis string toLower()
public Any m_toLower()
{
return Any.create(_string.toLowerCase());
}
/// @method trim
/// Removes whitespace characters from the beginning and end of this string.
/// @synopsis string trim()
public Any m_trim()
{
return Any.create(_string.trim());
}
/// @method trimLeft
/// Removes whitespace characters from the beginning this string.
/// @synopsis string trimLeft()
public Any m_trimLeft()
{
String value = _string;
int i = 0;
int n = value.length();
while((i<n) && Character.isWhitespace(value.charAt(i))) {
i++;
}
if (i>0) {
return Any.create(value.substring(i));
} else {
return this;
}
}
/// @method trimRight
/// Removes whitespace characters from the end this string.
/// @synopsis string trimRight()
public Any m_trimRight()
{
String value = _string;
int i = value.length();
while((i>0) && Character.isWhitespace(value.charAt(i-1))) {
i--;
}
if (i<value.length()) {
return Any.create(value.substring(0, i));
} else {
return this;
}
}
/// @method substring
/// Returns a substring from the given region of this string.
/// @synopsis string substring(int start)
/// @synopsis string substring(int start, int end)
/// @param start Starting index, included
/// @param end Ending index, excluded
public static final Object[] p_substring = new Object[] { "start", "*end", null };
public Any m_substring(int start, Any end_)
{
String string = _string;
int max = string.length();
if (start < 0) {
start = 0;
} else if (start > max) {
start = max;
}
if (end_ != null) {
int end = end_.toInt();
if (end < 0) {
end = 0;
} else if (end > max) {
end = max;
}
if (start <= end) {
if (end - start == 1) {
return ObjectPool.createChar(string.charAt(start));
} else {
return Any.create(string.substring(start, end));
}
} else {
return EMPTY_STRING;
}
} else {
if (start == max) {
return EMPTY_STRING;
} else {
return Any.create(string.substring(start));
}
}
}
/// @method charAt
/// Returns single character from this string.
/// @synopsis string charAt(int index)
/// @param index Index to string
public static final Object[] p_charAt = new Object[] { "index" };
public Any m_charAt(int index)
{
if ((index >= 0) && (index < _string.length())) {
return Any.create(_string.charAt(index));
} else {
return EMPTY_STRING;
}
}
/// @method charCodeAt
/// Returns the character code at the speicified index.
/// @synopsis int charCodeAt(int index)
/// @param index Index to string
public static final Object[] p_charCodeAt = new Object[] { "index" };
public Any m_charCodeAt(int index)
{
if ((index >= 0) && (index < _string.length())) {
return Any.create((int)_string.charAt(index));
} else {
return ZERO;
}
}
/// @method indexOf
/// Returns the index within this string of the first occurrence of the
/// specified string.
/// @synopsis int indexOf(string needle)
/// @synopsis int indexOf(string needle, int fromIndex)
/// @param needle String to search for
/// @param fromIndex Starting index of search
/// @return The index of first occurence, or -1 if it doesn't occur.
public static final Object[] p_indexOf = new Object[] { "needle", "*fromIndex", new Integer(0) };
public Any m_indexOf(String needle, int fromIndex)
{
return Any.create(_string.indexOf(needle, fromIndex));
}
/// @method lastIndexOf
/// Returns the index within this string of the last occurrence of the
/// specified string.
/// @synopsis int lastIndexOf(string needle)
/// @synopsis int lastIndexOf(string needle, int fromIndex)
/// @param needle String to search for
/// @param fromIndex Starting index of search
/// @return The index of last occurence, or -1 if it doesn't occur.
public static final Object[] p_lastIndexOf = new Object[] { "needle", "*fromIndex", null };
public Any m_lastIndexOf(String needle, Any fromIndex)
{
int start;
if (fromIndex != null) {
start = fromIndex.toInt();
} else {
start = _string.length();
}
return Any.create(_string.lastIndexOf(needle, start));
}
/// @method startsWith
/// Checks if this string starts with given prefix.
/// @synopsis boolean startsWith(string prefix)
public static final Object[] p_startsWith = new Object[] { "prefix" };
public Any m_startsWith(String prefix)
{
return _string.startsWith(prefix) ? TRUE : FALSE;
}
/// @method endsWith
/// Checks if this string ends with given suffix.
/// @synopsis boolean endsWith(string suffix)
public static final Object[] p_endsWith = new Object[] { "suffix" };
public Any m_endsWith(String suffix)
{
return _string.endsWith(suffix) ? TRUE : FALSE;
}
/// @method compareToIgnoreCase
/// Compares this string and given string, lower- and
/// uppercase characters are considered equal.
/// @synopsis int compareToIgnoreCase(string other)
/// @return -1 if <code>this<other</code>,
/// 0 if <code>this==other</code>,
/// 1 if <code>this>other</code>,
public static final Object[] p_compareToIgnoreCase = new Object[] { "str" };
public Any m_compareToIgnoreCase(String str)
{
int delta = _string.compareToIgnoreCase(str);
if (delta < 0) {
return MINUS_ONE;
} else if (delta > 0) {
return ONE;
} else {
return ZERO;
}
}
/// @method equalsIgnoreCase
/// Checks if this string is equal to given string, lower- and
/// uppercase characters are considered equal
/// @synopsis boolean equalsIgnoreCase(string other)
/// @param other String to compare with
public static final Object[] p_equalsIgnoreCase = new Object[] { "str" };
public Any m_equalsIgnoreCase(String str)
{
return _string.equalsIgnoreCase(str) ? TRUE: FALSE;
}
/// @method explode
/// Splits this string into regions using given set of delimiter
/// characters.
/// @synopsis list explode(string delimiters)
/// @synopsis list explode(string delimiters, boolean returnEmpty)
/// @param delimiters Set of delimiter characters
/// @param returnEmpty If <code>true</code> also empty regions are returned, if
/// omitted or <code>false</code> empty regions are not returned.
public static final Object[] p_explode = new Object[] { "delimiters", "*returnEmpty", Boolean.FALSE };
public Any m_explode(String delimiters, boolean returnEmpty)
{
AnyList list = new AnyList(new Any[8], 0);
if (returnEmpty) {
String str = _string;
int n = str.length();
int begin = 0;
for(int i=0; i<n; i++) {
if (delimiters.indexOf(str.charAt(i))>=0) {
list.append(Any.create(str.substring(begin, i)));
begin = i+1;
}
}
if (begin <= n) {
list.append(Any.create(str.substring(begin)));
}
} else {
StringTokenizer tokenizer = new StringTokenizer(_string, delimiters);
while(tokenizer.hasMoreElements()) {
list.append(Any.create((String)tokenizer.nextElement()));
}
}
return list;
}
/// @method repeat
/// Repeats this string <code>amount</code> times.
/// @synopsis string repeat(int amount)
public static final Object[] p_repeat = new Object[] { "count" };
public Any m_repeat(int count)
{
if (count < 0) {
count = 0;
}
String string = _string;
StringBuffer buffer = new StringBuffer(string.length() * count + 1);
for(; count > 0; count--) {
buffer.append(string);
}
return Any.create(buffer.toString());
}
/// @method translate
/// For each character in this string: if character appears
/// in <code>from</code> string, converts it to character
/// at the same index at <code>to</code>.
/// @synopsis string translate(string from, string to)
/// @param from Source character mapping
/// @param to Target character mapping
/// @return Translated string
public static final Object[] p_translate = new Object[] { "from", "to" };
public Any m_translate(String from, String to)
{
int pos;
char ch;
String string = _string;
int n = string.length();
int max = to.length();
StringBuffer buffer = new StringBuffer(n);
for(int i=0; i<n; i++) {
ch = string.charAt(i);
pos = from.indexOf(ch);
if (pos >= 0) {
if (pos < max) {
buffer.append(to.charAt(pos));
}
} else {
buffer.append(ch);
}
}
return Any.create(buffer.toString());
}
/// @method replace
/// Replaces all occurences of <code>from</code> into <code>to</code>.
/// @synopsis string replace(string from, string to)
/// @param from Regions to replace
/// @param to Replacement
public static final Object[] p_replace = new Object[] { "from", "to" };
public Any m_replace(String from, String to)
{
String string = _string;
int end = string.indexOf(from, 0);
if (end < 0) {
return this;
}
int max = string.length();
int begin = 0;
int toLen = to.length();
int fromLen = from.length();
StringBuffer buffer = new StringBuffer(max);
for(;;) {
end = string.indexOf(from, begin);
if (end < 0) {
end = max;
for(;begin<end; begin++) {
buffer.append(string.charAt(begin));
}
break;
} else {
for(; begin<end; begin++) {
buffer.append(string.charAt(begin));
}
buffer.append(to);
begin += fromLen;
}
}
return Any.create(buffer.toString());
}
/// @method unserialize
/// Unserializes data contained in this string.
/// @synopsis object unserialize()
/// @return Unserialized data
/// @throws CorruptedSerialization If serialized data is corrupted
public Any m_unserialize(Context context)
{
try {
return Serialization.unserialize(context, _string);
} catch (UnserializationException e) {
throw context.CorruptedSerialization();
}
}
private Any doMatch(Context context, Any pattern_, Any matches_, boolean isMatch)
{
Array array = null;
AnyList list = null;
if (matches_ != null) {
array = matches_.toArray();
if (matches_ instanceof AnyList) {
list = (AnyList)matches_;
}
}
Pattern pattern = ObjectPool.createPattern(context, pattern_);
Perl5Matcher matcher = new Perl5Matcher();
if (isMatch ? matcher.matches(_string, pattern)
: matcher.contains(_string, pattern))
{
if (array != null) {
MatchResult match = matcher.getMatch();
array.clear();
int n = match.groups();
for(int i=0; i<n; i++) {
array.append(Any.create(match.group(i)));
}
return array;
} else if (list != null) {
MatchResult match = matcher.getMatch();
list.clear();
int n = match.groups();
for(int i=0; i<n; i++) {
list.append(Any.create(match.group(i)));
}
return list;
}
return TRUE;
} else {
return FALSE;
}
}
/// @method matches
/// Checks if this (whole) string matches given
/// regular expression.
/// @synopsis boolean matches(string pattern)
/// @synopsis boolean matches(string pattern, array matches)
/// @synopsis boolean matches(string pattern, list matches)
/// @synopsis boolean matches(pattern pattern)
/// @synopsis boolean matches(pattern pattern, array matches)
/// @synopsis boolean matches(pattern pattern, list matches)
/// @param pattern Regular expression pattern
/// @return Matches or boolean
/// @throws MalformedPattern If pattern is invalid
public static final Object[] p_matches = new Object[] { null, "pattern", "*matches", null };
public Any m_matches(Context context, Any pattern, Any matches)
{
return doMatch(context, pattern, matches, true);
}
/// @method contains
/// Checks if some region of this string matches given
/// regular expression.
/// @synopsis boolean contains(string pattern)
/// @synopsis boolean contains(string pattern, array matches)
/// @synopsis boolean contains(string pattern, list matches)
/// @synopsis boolean contains(pattern pattern)
/// @synopsis boolean contains(pattern pattern, array matches)
/// @synopsis boolean contains(pattern pattern, list matches)
/// @param pattern Regular expression pattern
/// @return Matches or boolean
/// @throws MalformedPattern If pattern is invalid
public static final Object[] p_contains = new Object[] { null, "pattern", "*matches", null };
public Any m_contains(Context context, Any pattern, Any matches)
{
return doMatch(context, pattern, matches, false);
}
/// @method find
/// Finds all regions from this string mathing given regular
/// expression pattern.
/// @synopsis enumeration find(string pattern)
/// @synopsis enumeration find(pattern pattern)
/// @param pattern Regular expression pattern
/// @return Enumeration of strings
/// @throws MalformedPattern If pattern is invalid
public static final Object[] p_find = new Object[] { null, "pattern" };
public Any m_find(Context context, Any pattern_)
{
Pattern pattern = ObjectPool.createPattern(context, pattern_);
return new AnyBindingEnumeration(
new AnyUtils.StringPatternMatcher(pattern, _string));
}
/// @method split
/// Splits this string using given regular expression pattern as
/// delimiter.
/// @synopsis list split(string pattern)
/// @synopsis list split(pattern pattern)
/// @param pattern Regular expression pattern
/// @throws MalformedPattern If pattern is invalid
public static final Object[] p_split = new Object[] { null, "pattern" };
public Any m_split(Context context, Any pattern_)
{
Pattern pattern = ObjectPool.createPattern(context, pattern_);
Perl5Matcher matcher = new Perl5Matcher();
Vector parts = Util.split(matcher, pattern, _string);
int n = parts.size();
Any[] list = new Any[n];
for(int i=0; i<n; i++) {
list[i] = Any.create(parts.elementAt(i).toString());
}
return new AnyList(list);
}
/// @method divide
/// Divides string to two pieces, using <code>delim</code> as delimiter.
/// Example 1. "foo.bar.foo".divide(".") returns ("foo", "bar.foo")
/// Example 2. "foo.bar.foo".divide("|") returns ("foo.bar.foo", null)
/// Example 3. "foo.bar.fiu".divide(".", true) return ("fiu", "foo.bar")
/// @synopsis list divide(string delim)
/// @synopsis list divide(string delim, boolean dir)
/// @param delim Delimiter character(s)
/// @param dir Direction (default false), false = from start of the string,
/// true = from end of the string
public static final Object[] p_divide = new Object[] { "delim", "*dir", null };
public Any m_divide(String delim, Any dir)
{
if (delim == null) {
return UNDEFINED;
}
if (dir == null || !dir.toBoolean()) {
int i = _string.indexOf(delim);
if (i == -1) {
return new AnyList(new Any[] { this, NULL });
} else {
return new AnyList(new Any[] { Any.create(_string.substring(0, i)), Any.create(_string.substring(i+1)) });
}
} else {
int i = _string.lastIndexOf(delim);
if (i == -1) {
return new AnyList(new Any[] { this, NULL });
} else {
return new AnyList(new Any[] { Any.create(_string.substring(i+1)), Any.create(_string.substring(0, i)) });
}
}
}
private Any doSubstitute(Context context, Any pattern_, Any replacement, int flags)
{
Substitution substitution;
if (replacement.isString()) {
String s = replacement.toString();
if (s.indexOf('$') != -1) {
substitution = new Perl5Substitution(s);
} else {
substitution = new StringSubstitution(s);
}
} else {
substitution = new AnyUtils.FunctionSubstitute(context, replacement);
}
Pattern pattern = ObjectPool.createPattern(context, pattern_);
Perl5Matcher matcher = new Perl5Matcher();
return Any.create(Util.substitute(matcher, pattern, substitution, _string, flags));
}
/// @method substitute
/// Substitutes all regions from this string matching given
/// regular expression.
/// @synopsis string substitute(string pattern, string replacement [, int amount] )
/// @synopsis string substitute(pattern pattern, string replacement [, int amount] )
/// @synopsis string substitute(string pattern, Function replacer [, int amount] )
/// @synopsis string substitute(pattern pattern, Function replacer [, int amount] )
/// @param pattern Regular expression pattern
/// @param replacement Replacement string
/// @param replacer Replace function:
/// @param amount Number of occurences to replace, if omitted, all occurences are substituted.
/// <code>function replacer(list matchedGroups)</code>.
/// @throws MalformedPattern If pattern is invalid
public static final Object[] p_substitute = new Object[] { null, "pattern", "replacement", "*amount", null };
public Any m_substitute(Context context, Any pattern, Any replacement, Any amount)
{
int flag = Util.SUBSTITUTE_ALL;
if (amount != null) {
flag = amount.toInt();
}
return doSubstitute(context, pattern, replacement, flag);
}
/// @method substituteFirst
/// Substitutes first region from this string matching given
/// regular expression.
/// @synopsis string substituteFirst(string pattern, string replacement)
/// @synopsis string substituteFirst(pattern pattern, string replacement)
/// @synopsis string substituteFirst(string pattern, Function replacer)
/// @synopsis string substituteFirst(pattern pattern, Function replacer)
/// @param pattern Regular expression pattern
/// @param replacement Replacement string
/// @param replacer Replace function:
/// <code>function replacer(list matchedGroups)</code>.
/// @throws MalformedPattern If pattern is invalid
public static final Object[] p_substituteFirst = new Object[] { null, "pattern", "replacement" };
public Any m_substituteFirst(Context context, Any pattern, Any replacement)
{
return doSubstitute(context, pattern, replacement, 1);
}
/// @method hexToBinary
/// Converts string to binary,
/// assuming that two characters produce one byte: 414243 -> binary(abc)
/// @synopsis binary hexToBinary()
public Any m_hexToBinary()
{
String string = _string;
int n = string.length() / 2;
byte[] array = new byte[n];
for(int i=0; i<n; i++) {
array[i] = (byte)((Conversions.parseHex(string.charAt(i+i)) << 4) +
Conversions.parseHex(string.charAt(i+i+1)));
}
return new AnyBinary(array);
}
/// @method pad
/// Pads text left or right to field.
/// @synopsis string pad(int length)
/// @synopsis string pad(int length, string padding)
/// @param length Length of field, positive for right padding, negative
/// for left padding.
/// @param padding Padding character, default is space.
/// @return Given text padded to field
public static final Object[] p_pad = new Object[] { "length", "*pad", null };
public Any m_pad(int length, String pad)
{
if (pad == null) {
pad = " ";
}
boolean reverse = false;
if (length < 0) {
reverse = true;
length = -length;
}
StringBuffer buffer = new StringBuffer(length);
int i = _string.length();
int padlen = pad.length();
if (reverse) {
buffer.append(_string);
}
while(i < length) {
if (i + padlen > length) {
buffer.append(pad.substring(0, length - i));
break;
} else {
buffer.append(pad);
i += padlen;
}
}
if (!reverse) {
buffer.append(_string);
}
return new AnyString(buffer.toString());
}
/// @method chop
/// Chops suffix out of string.
/// @synopsis string chop() ; Chops all whitespaces
/// @synopsis string chop(string suffix) ; Chop given suffix
public static final Object[] p_chop = new Object[] { "*suffix", null };
public Any m_chop(String suffix)
{
String str = _string;
int len = str.length();
if (suffix != null) {
if (str.endsWith(suffix)) {
return Any.create(str.substring(0, len - suffix.length()));
}
} else {
int i = len;
while((i>0) && Character.isWhitespace(str.charAt(i-1))) {
i--;
}
if (i < len) {
return Any.create(str.substring(0, i));
}
}
return this;
}
/// @method eat
/// Removes given prefix out of string.
/// @synopsis string eat() ; Removes all whitespaces
/// @synopsis string eat(string prefix) ; Removes given prefix
public static final Object[] p_eat = new Object[] { "*prefix", null };
public Any m_eat(String prefix)
{
String str = _string;
int len = str.length();
if (prefix != null) {
if (str.startsWith(prefix)) {
return Any.create(str.substring(prefix.length()));
}
} else {
int i = 0;
while((i<len) && Character.isWhitespace(str.charAt(i))) {
i++;
}
if (i > 0) {
return Any.create(str.substring(i));
}
}
return this;
}
transient public static final anvil.script.compiler.NativeClass __class__ =
new anvil.script.compiler.NativeClass("string", AnyString.class, AnySequence.__class__,
//DOC{{
""+
"\n" +
" @class string\n" +
" The <code>string</code> class represents character strings. \n" +
" String is a sequence of characters.\n" +
" @constructor string\n" +
" Creates new string from the string representation of given parameter.\n" +
" @synopsis string(object value)\n" +
" @method length\n" +
" Returns the length of this string.\n" +
" @synopsis int length()\n" +
" @method unquote\n" +
" Unquotes all html entities from this string.\n" +
" @synopsis string unquote()\n" +
" @method quote\n" +
" Converts all applicable characters with corresponding\n" +
" html entity.\n" +
" @synopsis string quote()\n" +
" @method quoteMeta\n" +
" Converts all applicable characters under >127 with corresponding\n" +
" html entity.\n" +
" @synopsis string quoteMeta()\n" +
" @method quoteText\n" +
" Converts all applicable characters over >127 with corresponding\n" +
" html entity.\n" +
" @synopsis string quoteText()\n" +
" @method compress\n" +
" Compresses consequtive white space characeters into single\n" +
" space.\n" +
" @synopsis string compress()\n" +
" @method capitalize\n" +
" Capitalizes the first character of all words.\n" +
" @synopsis string capitalize()\n" +
" @method capitalizeFirst\n" +
" Capitalizes first character of first word.\n" +
" @synopsis string capitalizeFirst()\n" +
" @method nowrap\n" +
" Converts white spaces into <code>&nbsp;</code>.\n" +
" @synopsis string nowrap()\n" +
" @method encodeURL\n" +
" URL encodes this string.\n" +
" @synopsis string encodeURL()\n" +
" @method decodeURL\n" +
" Decodes URL encoding from this string.\n" +
" @synopsis string decodeURL()\n" +
" @method encode\n" +
" URL encodes this string.\n" +
" @synopsis string encode()\n" +
" @method decode\n" +
" Decodes URL encoding from this string.\n" +
" @synopsis string decode()\n" +
" @method escape\n" +
" Escapes string using the rules of anvil string literal.\n" +
" @synopsis string escape()\n" +
" @method unescape\n" +
" Unescapes backslash quotes.\n" +
" @synopsis string unescape()\n" +
" @synopsis string unescape(boolean withQuotes)\n" +
" @method nl2br\n" +
" Convers all line feeds into <code><br>\n</code>\n" +
" @synopsis string nl2br()\n" +
" @method toUpper\n" +
" Converts all lower case characeters into corresponding upper case\n" +
" characeters.\n" +
" @synopsis string toUpper()\n" +
" @method toLower\n" +
" Converts all upper case characeters into corresponding lower case\n" +
" characeters.\n" +
" @synopsis string toLower()\n" +
" @method trim\n" +
" Removes whitespace characters from the beginning and end of this string.\n" +
" @synopsis string trim()\n" +
" @method trimLeft\n" +
" Removes whitespace characters from the beginning this string.\n" +
" @synopsis string trimLeft()\n" +
" @method trimRight\n" +
" Removes whitespace characters from the end this string.\n" +
" @synopsis string trimRight()\n" +
" @method substring\n" +
" Returns a substring from the given region of this string.\n" +
" @synopsis string substring(int start)\n" +
" @synopsis string substring(int start, int end)\n" +
" @param start Starting index, included\n" +
" @param end Ending index, excluded\n" +
" @method charAt\n" +
" Returns single character from this string.\n" +
" @synopsis string charAt(int index)\n" +
" @param index Index to string\n" +
" @method charCodeAt\n" +
" Returns the character code at the speicified index.\n" +
" @synopsis int charCodeAt(int index)\n" +
" @param index Index to string\n" +
" @method indexOf\n" +
" Returns the index within this string of the first occurrence of the \n" +
" specified string.\n" +
" @synopsis int indexOf(string needle)\n" +
" @synopsis int indexOf(string needle, int fromIndex)\n" +
" @param needle String to search for\n" +
" @param fromIndex Starting index of search\n" +
" @return The index of first occurence, or -1 if it doesn't occur.\n" +
" @method lastIndexOf\n" +
" Returns the index within this string of the last occurrence of the \n" +
" specified string.\n" +
" @synopsis int lastIndexOf(string needle)\n" +
" @synopsis int lastIndexOf(string needle, int fromIndex)\n" +
" @param needle String to search for\n" +
" @param fromIndex Starting index of search\n" +
" @return The index of last occurence, or -1 if it doesn't occur.\n" +
" @method startsWith\n" +
" Checks if this string starts with given prefix.\n" +
" @synopsis boolean startsWith(string prefix)\n" +
" @method endsWith\n" +
" Checks if this string ends with given suffix.\n" +
" @synopsis boolean endsWith(string suffix)\n" +
" @method compareToIgnoreCase\n" +
" Compares this string and given string, lower- and\n" +
" uppercase characters are considered equal.\n" +
" @synopsis int compareToIgnoreCase(string other)\n" +
" @return -1 if <code>this<other</code>,\n" +
" 0 if <code>this==other</code>,\n" +
" 1 if <code>this>other</code>,\n" +
" @method equalsIgnoreCase\n" +
" Checks if this string is equal to given string, lower- and\n" +
" uppercase characters are considered equal\n" +
" @synopsis boolean equalsIgnoreCase(string other)\n" +
" @param other String to compare with\n" +
" @method explode\n" +
" Splits this string into regions using given set of delimiter \n" +
" characters.\n" +
" @synopsis list explode(string delimiters)\n" +
" @synopsis list explode(string delimiters, boolean returnEmpty)\n" +
" @param delimiters Set of delimiter characters\n" +
" @param returnEmpty If <code>true</code> also empty regions are returned, if\n" +
" omitted or <code>false</code> empty regions are not returned.\n" +
" @method repeat\n" +
" Repeats this string <code>amount</code> times.\n" +
" @synopsis string repeat(int amount)\n" +
" @method translate\n" +
" For each character in this string: if character appears\n" +
" in <code>from</code> string, converts it to character \n" +
" at the same index at <code>to</code>.\n" +
" @synopsis string translate(string from, string to)\n" +
" @param from Source character mapping\n" +
" @param to Target character mapping\n" +
" @return Translated string\n" +
" @method replace\n" +
" Replaces all occurences of <code>from</code> into <code>to</code>.\n" +
" @synopsis string replace(string from, string to)\n" +
" @param from Regions to replace\n" +
" @param to Replacement\n" +
" @method unserialize\n" +
" Unserializes data contained in this string.\n" +
" @synopsis object unserialize()\n" +
" @return Unserialized data\n" +
" @throws CorruptedSerialization If serialized data is corrupted\n" +
" @method matches\n" +
" Checks if this (whole) string matches given \n" +
" regular expression. \n" +
" @synopsis boolean matches(string pattern)\n" +
" @synopsis boolean matches(string pattern, array matches)\n" +
" @synopsis boolean matches(string pattern, list matches)\n" +
" @synopsis boolean matches(pattern pattern)\n" +
" @synopsis boolean matches(pattern pattern, array matches)\n" +
" @synopsis boolean matches(pattern pattern, list matches)\n" +
" @param pattern Regular expression pattern\n" +
" @return Matches or boolean\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method contains\n" +
" Checks if some region of this string matches given \n" +
" regular expression.\n" +
" @synopsis boolean contains(string pattern)\n" +
" @synopsis boolean contains(string pattern, array matches)\n" +
" @synopsis boolean contains(string pattern, list matches)\n" +
" @synopsis boolean contains(pattern pattern)\n" +
" @synopsis boolean contains(pattern pattern, array matches)\n" +
" @synopsis boolean contains(pattern pattern, list matches)\n" +
" @param pattern Regular expression pattern\n" +
" @return Matches or boolean\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method find\n" +
" Finds all regions from this string mathing given regular\n" +
" expression pattern.\n" +
" @synopsis enumeration find(string pattern)\n" +
" @synopsis enumeration find(pattern pattern)\n" +
" @param pattern Regular expression pattern\n" +
" @return Enumeration of strings\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method split\n" +
" Splits this string using given regular expression pattern as \n" +
" delimiter.\n" +
" @synopsis list split(string pattern)\n" +
" @synopsis list split(pattern pattern)\n" +
" @param pattern Regular expression pattern\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method divide\n" +
" Divides string to two pieces, using <code>delim</code> as delimiter.\n" +
" Example 1. \"foo.bar.foo\".divide(\".\") returns (\"foo\", \"bar.foo\")\n" +
" Example 2. \"foo.bar.foo\".divide(\"|\") returns (\"foo.bar.foo\", null)\n" +
" Example 3. \"foo.bar.fiu\".divide(\".\", true) return (\"fiu\", \"foo.bar\")\n" +
" @synopsis list divide(string delim)\n" +
" @synopsis list divide(string delim, boolean dir)\n" +
" @param delim Delimiter character(s)\n" +
" @param dir Direction (default false), false = from start of the string,\n" +
" true = from end of the string\n" +
" @method substitute\n" +
" Substitutes all regions from this string matching given\n" +
" regular expression.\n" +
" @synopsis string substitute(string pattern, string replacement [, int amount] )\n" +
" @synopsis string substitute(pattern pattern, string replacement [, int amount] )\n" +
" @synopsis string substitute(string pattern, Function replacer [, int amount] )\n" +
" @synopsis string substitute(pattern pattern, Function replacer [, int amount] )\n" +
" @param pattern Regular expression pattern\n" +
" @param replacement Replacement string\n" +
" @param replacer Replace function: \n" +
" @param amount Number of occurences to replace, if omitted, all occurences are substituted.\n" +
" <code>function replacer(list matchedGroups)</code>.\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method substituteFirst\n" +
" Substitutes first region from this string matching given\n" +
" regular expression.\n" +
" @synopsis string substituteFirst(string pattern, string replacement)\n" +
" @synopsis string substituteFirst(pattern pattern, string replacement)\n" +
" @synopsis string substituteFirst(string pattern, Function replacer)\n" +
" @synopsis string substituteFirst(pattern pattern, Function replacer)\n" +
" @param pattern Regular expression pattern\n" +
" @param replacement Replacement string\n" +
" @param replacer Replace function: \n" +
" <code>function replacer(list matchedGroups)</code>.\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method hexToBinary \n" +
" Converts string to binary, \n" +
" assuming that two characters produce one byte: 414243 -> binary(abc) \n" +
" @synopsis binary hexToBinary()\n" +
" @method pad\n" +
" Pads text left or right to field.\n" +
" @synopsis string pad(int length)\n" +
" @synopsis string pad(int length, string padding)\n" +
" @param length Length of field, positive for right padding, negative\n" +
" for left padding.\n" +
" @param padding Padding character, default is space.\n" +
" @return Given text padded to field\n" +
" @method chop\n" +
" Chops suffix out of string.\n" +
" @synopsis string chop() ; Chops all whitespaces\n" +
" @synopsis string chop(string suffix) ; Chop given suffix\n" +
" @method eat\n" +
" Removes given prefix out of string.\n" +
" @synopsis string eat() ; Removes all whitespaces\n" +
" @synopsis string eat(string prefix) ; Removes given prefix\n"
//}}DOC
);
}