Implementation of Ruby String class
Concurrency: no synchronization is required among readers, but
all users must synchronize externally with writers.
| Method from org.jruby.RubyString Detail: |
public RubyString append(IRubyObject other) {
infectBy(other);
return cat(stringValue(other).value);
}
|
public String asJavaString() {
// TODO: This used to intern; but it didn't appear to change anything
// turning that off, and it's unclear if it was needed. Plus, we intern
//
return toString();
}
|
public RubyString asString() {
return this;
}
|
public static String byteListToString(ByteList bytes) {
return bytesToString(bytes.unsafeBytes(), bytes.begin(), bytes.length());
}
|
public static String bytesToString(byte[] bytes) {
return bytesToString(bytes, 0, bytes.length);
}
|
public static String bytesToString(byte[] bytes,
int beg,
int len) {
return new String(ByteList.plain(bytes, beg, len));
}
|
public IRubyObject capitalize(ThreadContext context) {
RubyString str = strDup(context.getRuntime());
str.capitalize_bang(context);
return str;
}
|
public IRubyObject capitalize_bang(ThreadContext context) {
if (value.realSize == 0) {
modifyCheck();
return context.getRuntime().getNil();
}
modify();
int s = value.begin;
int send = s + value.realSize;
byte[]buf = value.bytes;
boolean modify = false;
int c = buf[s] & 0xff;
if (ASCII.isLower(c)) {
buf[s] = (byte)ASCIIEncoding.asciiToUpper(c);
modify = true;
}
while (++s < send) {
c = (char)(buf[s] & 0xff);
if (ASCII.isUpper(c)) {
buf[s] = (byte)ASCIIEncoding.asciiToLower(c);
modify = true;
}
}
if (modify) return this;
return context.getRuntime().getNil();
}
|
public IRubyObject casecmp(IRubyObject other) {
int compare = value.caseInsensitiveCmp(stringValue(other).value);
return RubyFixnum.newFixnum(getRuntime(), compare);
}
|
public RubyString cat(byte[] str) {
modify(value.realSize + str.length);
System.arraycopy(str, 0, value.bytes, value.begin + value.realSize, str.length);
value.realSize += str.length;
return this;
}
|
public RubyString cat(ByteList str) {
modify(value.realSize + str.realSize);
System.arraycopy(str.bytes, str.begin, value.bytes, value.begin + value.realSize, str.realSize);
value.realSize += str.realSize;
return this;
}
|
public RubyString cat(byte ch) {
modify(value.realSize + 1);
value.bytes[value.begin + value.realSize] = ch;
value.realSize++;
return this;
}
|
public RubyString cat(byte[] str,
int beg,
int len) {
modify(value.realSize + len);
System.arraycopy(str, beg, value.bytes, value.begin + value.realSize, len);
value.realSize += len;
return this;
}
|
public IRubyObject center(IRubyObject[] args) {
switch (args.length) {
case 1:
return center(args[0]);
case 2:
return center(args[0], args[1]);
default:
Arity.raiseArgumentError(getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! use - the one or two argument versions.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject center(IRubyObject arg0) {
return justify(arg0, 'c");
}
|
public IRubyObject center(IRubyObject arg0,
IRubyObject arg1) {
return justify(arg0, arg1, 'c");
}
|
public IRubyObject checkStringType() {
return this;
}
|
public RubyString chomp() {
RubyString str = strDup(getRuntime());
str.chomp_bang();
return str;
}
|
public RubyString chomp(IRubyObject[] args) {
switch (args.length) {
case 0:
return chomp();
case 1:
return chomp(args[0]);
default:
Arity.raiseArgumentError(getRuntime(), args.length, 0, 1);
return null; // not reached
}
} Deprecated! Use - the zero or one argument versions.
Variable-arity version for compatibility. Not bound to Ruby |
public RubyString chomp(IRubyObject arg0) {
RubyString str = strDup(getRuntime());
str.chomp_bang(arg0);
return str;
}
|
public IRubyObject chomp_bang() {
IRubyObject rsObj;
int len = value.length();
if (len == 0) return getRuntime().getNil();
byte[]buff = value.bytes;
rsObj = getRuntime().getGlobalVariables().get("$/");
if (rsObj == getRuntime().getGlobalVariables().getDefaultSeparator()) {
int realSize = value.realSize;
int begin = value.begin;
if (buff[begin + len - 1] == (byte)'\n") {
realSize--;
if (realSize > 0 && buff[begin + realSize - 1] == (byte)'\r") realSize--;
view(0, realSize);
} else if (buff[begin + len - 1] == (byte)'\r") {
realSize--;
view(0, realSize);
} else {
modifyCheck();
return getRuntime().getNil();
}
return this;
}
return chompBangCommon(rsObj);
}
rb_str_chomp_bang
In the common case, removes CR and LF characters in various ways depending on the value of
the optional args[0].
If args.length==0 removes one instance of CR, CRLF or LF from the end of the string.
If args.length>0 and args[0] is "\n" then same behaviour as args.length==0 .
If args.length>0 and args[0] is "" then removes trailing multiple LF or CRLF (but no CRs at
all(!)). |
public IRubyObject chomp_bang(IRubyObject[] args) {
switch (args.length) {
case 0:
return chomp_bang();
case 1:
return chomp_bang(args[0]);
default:
Arity.raiseArgumentError(getRuntime(), args.length, 0, 1);
return null; // not reached
}
} Deprecated! Use - the zero or one argument versions.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject chomp_bang(IRubyObject arg0) {
return chompBangCommon(arg0);
}
rb_str_chomp_bang
In the common case, removes CR and LF characters in various ways depending on the value of
the optional args[0].
If args.length==0 removes one instance of CR, CRLF or LF from the end of the string.
If args.length>0 and args[0] is "\n" then same behaviour as args.length==0 .
If args.length>0 and args[0] is "" then removes trailing multiple LF or CRLF (but no CRs at
all(!)). |
public IRubyObject chop(ThreadContext context) {
RubyString str = strDup(context.getRuntime());
str.chop_bang();
return str;
}
|
public IRubyObject chop_bang() {
int end = value.realSize - 1;
if (end < 0) return getRuntime().getNil();
if ((value.bytes[value.begin + end]) == '\n") {
if (end > 0 && (value.bytes[value.begin + end - 1]) == '\r") end--;
}
view(0, end);
return this;
}
|
public RubyString concat(IRubyObject other) {
if (other instanceof RubyFixnum) {
long value = ((RubyFixnum) other).getLongValue();
if (value >= 0 && value < 256) return cat((byte) value);
}
return append(other);
}
|
public RubyString convertToString() {
return this;
}
|
public IRubyObject count(IRubyObject[] args) {
if (args.length < 1) throw getRuntime().newArgumentError("wrong number of arguments");
if (value.realSize == 0) return getRuntime().newFixnum(0);
boolean[]table = new boolean[TRANS_SIZE];
boolean init = true;
for (int i=0; i< args.length; i++) {
RubyString s = args[i].convertToString();
s.setup_table(table, init);
init = false;
}
int s = value.begin;
int send = s + value.realSize;
byte[]buf = value.bytes;
int i = 0;
while (s < send) if (table[buf[s++] & 0xff]) i++;
return getRuntime().newFixnum(i);
}
|
public static RubyClass createStringClass(Ruby runtime) {
RubyClass stringClass = runtime.defineClass("String", runtime.getObject(), STRING_ALLOCATOR);
runtime.setString(stringClass);
stringClass.index = ClassIndex.STRING;
stringClass.kindOf = new RubyModule.KindOf() {
@Override
public boolean isKindOf(IRubyObject obj, RubyModule type) {
return obj instanceof RubyString;
}
};
stringClass.includeModule(runtime.getComparable());
stringClass.includeModule(runtime.getEnumerable());
stringClass.defineAnnotatedMethods(RubyString.class);
return stringClass;
}
|
public RubyString crypt(ThreadContext context,
IRubyObject other) {
ByteList salt = stringValue(other).getByteList();
if (salt.realSize < 2) {
throw context.getRuntime().newArgumentError("salt too short(need >=2 bytes)");
}
salt = salt.makeShared(0, 2);
RubyString s = RubyString.newStringShared(context.getRuntime(), JavaCrypt.crypt(salt, this.getByteList()));
s.infectBy(this);
s.infectBy(other);
return s;
}
|
public IRubyObject delete(ThreadContext context,
IRubyObject[] args) {
RubyString str = strDup(context.getRuntime());
str.delete_bang(args);
return str;
}
|
public IRubyObject delete_bang(IRubyObject[] args) {
if (args.length < 1) throw getRuntime().newArgumentError("wrong number of arguments");
boolean[]squeeze = new boolean[TRANS_SIZE];
boolean init = true;
for (int i=0; i< args.length; i++) {
RubyString s = args[i].convertToString();
s.setup_table(squeeze, init);
init = false;
}
modify();
if (value.realSize == 0) return getRuntime().getNil();
int s = value.begin;
int t = s;
int send = s + value.realSize;
byte[]buf = value.bytes;
boolean modify = false;
while (s < send) {
if (squeeze[buf[s] & 0xff]) {
modify = true;
} else {
buf[t++] = buf[s];
}
s++;
}
value.realSize = t - value.begin;
if (modify) return this;
return getRuntime().getNil();
}
|
public IRubyObject doClone() {
return newString(getRuntime(), value.dup());
}
|
public RubyString downcase(ThreadContext context) {
RubyString str = strDup(context.getRuntime());
str.downcase_bang(context);
return str;
}
|
public IRubyObject downcase_bang(ThreadContext context) {
if (value.realSize == 0) {
modifyCheck();
return context.getRuntime().getNil();
}
modify();
int s = value.begin;
int send = s + value.realSize;
byte []buf = value.bytes;
boolean modify = false;
while (s < send) {
int c = buf[s] & 0xff;
if (ASCII.isUpper(c)) {
buf[s] = (byte)ASCIIEncoding.asciiToLower(c);
modify = true;
}
s++;
}
if (modify) return this;
return context.getRuntime().getNil();
}
|
public IRubyObject dump() {
RubyString s = new RubyString(getRuntime(), getMetaClass(), inspectIntoByteList(true));
s.infectBy(this);
return s;
}
|
public RubyString each_byte(ThreadContext context,
Block block) {
Ruby runtime = getRuntime();
// Check the length every iteration, since
// the block can modify this string.
for (int i = 0; i < value.length(); i++) {
block.yield(context, runtime.newFixnum(value.get(i) & 0xFF));
}
return this;
}
|
public IRubyObject each_line(ThreadContext context,
IRubyObject[] args,
Block block) {
byte newline;
int p = value.begin;
int pend = p + value.realSize;
int s;
int ptr = p;
int len = value.realSize;
int rslen;
IRubyObject line;
IRubyObject _rsep;
if (args.length == 0) {
_rsep = getRuntime().getGlobalVariables().get("$/");
} else {
_rsep = args[0];
}
if(_rsep.isNil()) {
block.yield(context, this);
return this;
}
RubyString rsep = stringValue(_rsep);
ByteList rsepValue = rsep.value;
byte[] strBytes = value.bytes;
rslen = rsepValue.realSize;
if(rslen == 0) {
newline = '\n";
} else {
newline = rsepValue.bytes[rsepValue.begin + rslen-1];
}
s = p;
p+=rslen;
for(; p < pend; p++) {
if(rslen == 0 && strBytes[p] == '\n") {
if(strBytes[++p] != '\n") {
continue;
}
while(p < pend && strBytes[p] == '\n") {
p++;
}
}
if(ptr< p && strBytes[p-1] == newline &&
(rslen < = 1 ||
ByteList.memcmp(rsepValue.bytes, rsepValue.begin, rslen, strBytes, p-rslen, rslen) == 0)) {
line = RubyString.newStringShared(getRuntime(), getMetaClass(), this.value.makeShared(s-ptr, p-s));
line.infectBy(this);
block.yield(context, line);
modifyCheck(strBytes,len);
s = p;
}
}
if(s != pend) {
if(p > pend) {
p = pend;
}
line = RubyString.newStringShared(getRuntime(), getMetaClass(), this.value.makeShared(s-ptr, p-s));
line.infectBy(this);
block.yield(context, line);
}
return this;
}
|
public void empty() {
value = ByteList.EMPTY_BYTELIST;
shareLevel = SHARE_LEVEL_BYTELIST;
}
|
public RubyBoolean empty_p(ThreadContext context) {
return isEmpty() ? context.getRuntime().getTrue() : context.getRuntime().getFalse();
}
|
public final boolean eql(IRubyObject other) {
if (other.getMetaClass() == getRuntime().getString()) return value.equal(((RubyString)other).value);
return super.eql(other);
}
short circuit for String key comparison |
public boolean equals(Object other) {
if (this == other) return true;
if (other instanceof RubyString) {
RubyString string = (RubyString) other;
if (string.value.equal(value)) return true;
}
return false;
}
|
public ByteList getByteList() {
return value;
}
|
public byte[] getBytes() {
return value.bytes();
}
|
public Class getJavaClass() {
return String.class;
}
|
public int getNativeTypeIndex() {
return ClassIndex.STRING;
}
|
public String getUnicodeValue() {
try {
return new String(value.bytes,value.begin,value.realSize, "UTF8");
} catch (Exception e) {
throw new RuntimeException("Something's seriously broken with encodings", e);
}
}
|
public CharSequence getValue() {
return toString();
}
|
public IRubyObject gsub(ThreadContext context,
IRubyObject[] args,
Block block) {
switch (args.length) {
case 1:
return gsub(context, args[0], block);
case 2:
return gsub(context, args[0], args[1], block);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! Use - the versions with one or two arguments.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject gsub(ThreadContext context,
IRubyObject arg0,
Block block) {
return gsub(context, arg0, block, false);
}
|
public IRubyObject gsub(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1,
Block block) {
return gsub(context, arg0, arg1, block, false);
}
|
public IRubyObject gsub_bang(ThreadContext context,
IRubyObject[] args,
Block block) {
switch (args.length) {
case 1:
return gsub_bang(context, args[0], block);
case 2:
return gsub_bang(context, args[0], args[1], block);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! Use - the versions with one or two arguments.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject gsub_bang(ThreadContext context,
IRubyObject arg0,
Block block) {
return gsub(context, arg0, block, true);
}
|
public IRubyObject gsub_bang(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1,
Block block) {
return gsub(context, arg0, arg1, block, true);
}
|
public RubyFixnum hash() {
return getRuntime().newFixnum(value.hashCode());
}
|
public int hashCode() {
return value.hashCode();
}
|
public IRubyObject hex(ThreadContext context) {
return RubyNumeric.str2inum(context.getRuntime(), this, 16);
}
|
public RubyBoolean include_p(ThreadContext context,
IRubyObject obj) {
if (obj instanceof RubyFixnum) {
int c = RubyNumeric.fix2int(obj);
for (int i = 0; i < value.length(); i++) {
if (value.get(i) == (byte)c) {
return context.getRuntime().getTrue();
}
}
return context.getRuntime().getFalse();
}
ByteList str = stringValue(obj).value;
return context.getRuntime().newBoolean(value.indexOf(str) != -1);
}
|
public IRubyObject index(ThreadContext context,
IRubyObject[] args) {
switch (args.length) {
case 1:
return index(context, args[0]);
case 2:
return index(context, args[0], args[1]);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! Use - the versions with one or two args.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject index(ThreadContext context,
IRubyObject arg0) {
return indexCommon(0, arg0, context);
}
|
public IRubyObject index(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1) {
int pos = RubyNumeric.num2int(arg1);
if (pos < 0) {
pos += value.realSize;
if (pos < 0) {
if (arg0 instanceof RubyRegexp) {
context.getPreviousFrame().setBackRef(context.getRuntime().getNil());
}
return context.getRuntime().getNil();
}
}
return indexCommon(pos, arg0, context);
}
|
public IRubyObject initialize() {
return this;
}
|
public IRubyObject initialize(IRubyObject arg0) {
replace(arg0);
return this;
}
|
public IRubyObject initialize(IRubyObject[] args,
Block unusedBlock) {
switch (args.length) {
case 0:
return this;
case 1:
return initialize(args[0]);
default:
Arity.raiseArgumentError(getRuntime(), args.length, 0, 1);
return null; // not reached
}
} Deprecated! Use - the versions with zero or one arguments
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject insert(ThreadContext context,
IRubyObject indexArg,
IRubyObject stringArg) {
// MRI behavior: first check for ability to convert to String...
RubyString s = (RubyString)stringArg.convertToString();
ByteList insert = s.value;
// ... and then the index
int index = (int) indexArg.convertToInteger().getLongValue();
if (index < 0) index += value.length() + 1;
if (index < 0 || index > value.length()) {
throw context.getRuntime().newIndexError("index " + index + " out of range");
}
modify();
value.unsafeReplace(index, 0, insert);
this.infectBy(s);
return this;
}
|
public IRubyObject inspect() {
RubyString s = getRuntime().newString(inspectIntoByteList(false));
s.infectBy(this);
return s;
}
|
public RubySymbol intern() {
String s = toString();
if (s.length() == 0) {
throw getRuntime().newArgumentError("interning empty string");
}
if (s.indexOf('\0") >= 0) {
throw getRuntime().newArgumentError("symbol string may not contain '\\0'");
}
return getRuntime().newSymbol(s);
}
|
public static boolean isAlnum(int c) {
return isUpper(c) || isLower(c) || isDigit(c);
}
|
public static boolean isDigit(int c) {
return c >= '0" && c < = '9";
}
|
public boolean isEmpty() {
return value.length() == 0;
}
|
public static boolean isLetter(int c) {
return isUpper(c) || isLower(c);
}
|
public static boolean isLower(int c) {
return c >= 'a" && c < = 'z";
}
|
public static boolean isPrint(int c) {
return c >= 0x20 && c < = 0x7E;
}
|
public static boolean isUpper(int c) {
return c >= 'A" && c < = 'Z";
}
|
public RubyFixnum length() {
return getRuntime().newFixnum(value.length());
}
|
public IRubyObject ljust(IRubyObject[] args) {
switch (args.length) {
case 1:
return ljust(args[0]);
case 2:
return ljust(args[0], args[1]);
default:
Arity.raiseArgumentError(getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! use - the one or two argument versions.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject ljust(IRubyObject arg0) {
return justify(arg0, 'l");
}
|
public IRubyObject ljust(IRubyObject arg0,
IRubyObject arg1) {
return justify(arg0, arg1, 'l");
}
|
public IRubyObject lstrip(ThreadContext context) {
RubyString str = strDup(context.getRuntime());
str.lstrip_bang();
return str;
}
|
public IRubyObject lstrip_bang() {
if (value.realSize == 0) return getRuntime().getNil();
int i=0;
while (i < value.realSize && ASCII.isSpace(value.bytes[value.begin + i] & 0xff)) i++;
if (i > 0) {
view(i, value.realSize - i);
return this;
}
return getRuntime().getNil();
}
|
public final RubyString makeShared(Ruby runtime,
int index,
int len) {
if (len == 0) {
RubyString s = newEmptyString(runtime, getMetaClass());
s.infectBy(this);
return s;
}
if (shareLevel == SHARE_LEVEL_NONE) shareLevel = SHARE_LEVEL_BUFFER;
RubyString shared = new RubyString(runtime, getMetaClass(), value.makeShared(index, len));
shared.shareLevel = SHARE_LEVEL_BUFFER;
shared.infectBy(this);
return shared;
}
|
public IRubyObject match(ThreadContext context,
IRubyObject pattern) {
return getPattern(pattern, false).callMethod(context, "match", this);
}
String#match(pattern)
rb_str_match_m |
public final void modify() {
modifyCheck();
if (shareLevel != SHARE_LEVEL_NONE) {
if (shareLevel == SHARE_LEVEL_BYTELIST) {
value = value.dup();
} else {
value.unshare();
}
shareLevel = SHARE_LEVEL_NONE;
}
value.invalidate();
}
|
public final void modify(int length) {
modifyCheck();
if (shareLevel != SHARE_LEVEL_NONE) {
if (shareLevel == SHARE_LEVEL_BYTELIST) {
value = value.dup(length);
} else {
value.unshare(length);
}
shareLevel = SHARE_LEVEL_NONE;
} else {
value.ensure(length);
}
value.invalidate();
}
rb_str_modify (with length bytes ensured) |
final void modifyCheck() {
if ((flags & FROZEN_F) != 0) throw getRuntime().newFrozenError("string");
if (!isTaint() && getRuntime().getSafeLevel() >= 4) {
throw getRuntime().newSecurityError("Insecure: can't modify string");
}
}
|
public static RubyString newEmptyString(Ruby runtime) {
return newEmptyString(runtime, runtime.getString());
}
|
public static RubyString newEmptyString(Ruby runtime,
RubyClass metaClass) {
RubyString empty = new RubyString(runtime, metaClass, ByteList.EMPTY_BYTELIST);
empty.shareLevel = SHARE_LEVEL_BYTELIST;
return empty;
}
|
public static RubyString newInstance(IRubyObject recv,
IRubyObject[] args,
Block block) {
RubyString newString = newStringShared(recv.getRuntime(), ByteList.EMPTY_BYTELIST);
newString.setMetaClass((RubyClass) recv);
newString.callInit(args, block);
return newString;
}
|
public RubyString newString(CharSequence s) {
return new RubyString(getRuntime(), getType(), s);
} Deprecated!
Create a new String which uses the same Ruby runtime and the same
class like this String.
This method should be used to satisfy RCR #38. |
public RubyString newString(ByteList s) {
return new RubyString(getRuntime(), getMetaClass(), s);
} Deprecated!
Create a new String which uses the same Ruby runtime and the same
class like this String.
This method should be used to satisfy RCR #38. |
public static RubyString newString(Ruby runtime,
CharSequence str) {
return new RubyString(runtime, runtime.getString(), str);
}
|
public static RubyString newString(Ruby runtime,
byte[] bytes) {
return new RubyString(runtime, runtime.getString(), bytes);
}
|
public static RubyString newString(Ruby runtime,
ByteList bytes) {
return new RubyString(runtime, runtime.getString(), bytes);
}
|
public static RubyString newString(Ruby runtime,
RubyClass clazz,
CharSequence str) {
return new RubyString(runtime, clazz, str);
}
|
public static RubyString newString(Ruby runtime,
byte[] bytes,
int start,
int length) {
byte[] copy = new byte[length];
System.arraycopy(bytes, start, copy, 0, length);
return new RubyString(runtime, runtime.getString(), new ByteList(copy, false));
}
|
public static RubyString newStringLight(Ruby runtime,
ByteList bytes) {
return new RubyString(runtime, runtime.getString(), bytes, false);
}
|
public static RubyString newStringShared(Ruby runtime,
RubyString orig) {
orig.shareLevel = SHARE_LEVEL_BYTELIST;
RubyString str = new RubyString(runtime, runtime.getString(), orig.value);
str.shareLevel = SHARE_LEVEL_BYTELIST;
return str;
}
|
public static RubyString newStringShared(Ruby runtime,
ByteList bytes) {
return newStringShared(runtime, runtime.getString(), bytes);
}
|
public static RubyString newStringShared(Ruby runtime,
RubyClass clazz,
ByteList bytes) {
RubyString str = new RubyString(runtime, clazz, bytes);
str.shareLevel = SHARE_LEVEL_BYTELIST;
return str;
}
|
public static RubyString newStringShared(Ruby runtime,
byte[] bytes,
int start,
int length) {
RubyString str = new RubyString(runtime, runtime.getString(), new ByteList(bytes, start, length, false));
str.shareLevel = SHARE_LEVEL_BUFFER;
return str;
}
|
public static RubyString newUnicodeString(Ruby runtime,
String str) {
try {
return new RubyString(runtime, runtime.getString(), new ByteList(str.getBytes("UTF8"), false));
} catch (UnsupportedEncodingException uee) {
return new RubyString(runtime, runtime.getString(), str);
}
}
|
public static RubyString objAsString(ThreadContext context,
IRubyObject obj) {
if (obj instanceof RubyString) return (RubyString) obj;
IRubyObject str = obj.callMethod(context, MethodIndex.TO_S, "to_s");
if (!(str instanceof RubyString)) return (RubyString) obj.anyToString();
if (obj.isTaint()) str.setTaint(true);
return (RubyString) str;
}
|
public IRubyObject oct(ThreadContext context) {
if (isEmpty()) return context.getRuntime().newFixnum(0);
int base = 8;
int ix = value.begin;
while(ix < value.begin+value.realSize && ASCII.isSpace(value.bytes[ix] & 0xff)) {
ix++;
}
int pos = (value.bytes[ix] == '-" || value.bytes[ix] == '+") ? ix+1 : ix;
if((pos+1) < value.begin+value.realSize && value.bytes[pos] == '0") {
if(value.bytes[pos+1] == 'x" || value.bytes[pos+1] == 'X") {
base = 16;
} else if(value.bytes[pos+1] == 'b" || value.bytes[pos+1] == 'B") {
base = 2;
} else if(value.bytes[pos+1] == 'd" || value.bytes[pos+1] == 'D") {
base = 10;
}
}
return RubyNumeric.str2inum(context.getRuntime(), this, base);
}
|
public IRubyObject op_aref(ThreadContext context,
IRubyObject[] args) {
switch (args.length) {
case 1:
return op_aref(context, args[0]);
case 2:
return op_aref(context, args[0], args[1]);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! Use - the versions with one or two args
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject op_aref(ThreadContext context,
IRubyObject arg) {
if (arg instanceof RubyRegexp) {
if(((RubyRegexp)arg).search(context, this, 0, false) >= 0) {
return RubyRegexp.nth_match(0, context.getCurrentFrame().getBackRef());
}
return context.getRuntime().getNil();
} else if (arg instanceof RubyString) {
return value.indexOf(stringValue(arg).value) != -1 ?
arg : context.getRuntime().getNil();
} else if (arg instanceof RubyRange) {
long[] begLen = ((RubyRange) arg).begLen(value.length(), 0);
return begLen == null ? context.getRuntime().getNil() :
substr(context.getRuntime(), (int) begLen[0], (int) begLen[1]);
}
int idx = (int) arg.convertToInteger().getLongValue();
if (idx < 0) idx += value.length();
if (idx < 0 || idx >= value.length()) return context.getRuntime().getNil();
return context.getRuntime().newFixnum(value.get(idx) & 0xFF);
}
rb_str_aref, rb_str_aref_m |
public IRubyObject op_aref(ThreadContext context,
IRubyObject arg1,
IRubyObject arg2) {
if (arg1 instanceof RubyRegexp) {
if(((RubyRegexp)arg1).search(context, this, 0, false) >= 0) {
return RubyRegexp.nth_match(RubyNumeric.fix2int(arg2), context.getCurrentFrame().getBackRef());
}
return context.getRuntime().getNil();
}
return substr(context.getRuntime(), RubyNumeric.fix2int(arg1), RubyNumeric.fix2int(arg2));
}
rb_str_aref, rb_str_aref_m |
public IRubyObject op_aset(ThreadContext context,
IRubyObject[] args) {
switch (args.length) {
case 2:
return op_aset(context, args[0], args[1]);
case 3:
return op_aset(context, args[0], args[1], args[2]);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 2, 3);
return null; // not reached
}
} Deprecated! Use - the versions with two or three args.
Variable arity version for compatibility. Not bound to a Ruby method. |
public IRubyObject op_aset(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1) {
if (arg0 instanceof RubyFixnum || arg0.respondsTo("to_int")) { // FIXME: RubyNumeric or RubyInteger instead?
int idx = RubyNumeric.fix2int(arg0);
if (idx < 0) idx += value.length();
if (idx < 0 || idx >= value.length()) {
throw context.getRuntime().newIndexError("string index out of bounds");
}
if (arg1 instanceof RubyFixnum) {
modify();
value.set(idx, (byte) RubyNumeric.fix2int(arg1));
} else {
replace(idx, 1, stringValue(arg1));
}
return arg1;
}
if (arg0 instanceof RubyRegexp) {
RubyString repl = stringValue(arg1);
subpatSet(context, (RubyRegexp) arg0, 0, repl);
return repl;
}
if (arg0 instanceof RubyString) {
RubyString orig = (RubyString)arg0;
int beg = value.indexOf(orig.value);
if (beg < 0) throw context.getRuntime().newIndexError("string not matched");
replace(beg, orig.value.length(), stringValue(arg1));
return arg1;
}
if (arg0 instanceof RubyRange) {
long[] begLen = ((RubyRange) arg0).begLen(value.realSize, 2);
replace((int) begLen[0], (int) begLen[1], stringValue(arg1));
return arg1;
}
throw context.getRuntime().newTypeError("wrong argument type");
}
rb_str_aset, rb_str_aset_m |
public IRubyObject op_aset(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1,
IRubyObject arg2) {
if (arg0 instanceof RubyRegexp) {
RubyString repl = stringValue(arg2);
int nth = RubyNumeric.fix2int(arg1);
subpatSet(context, (RubyRegexp) arg0, nth, repl);
return repl;
}
RubyString repl = stringValue(arg2);
int beg = RubyNumeric.fix2int(arg0);
int len = RubyNumeric.fix2int(arg1);
if (len < 0) throw context.getRuntime().newIndexError("negative length");
int strLen = value.length();
if (beg < 0) beg += strLen;
if (beg < 0 || (beg > 0 && beg > strLen)) {
throw context.getRuntime().newIndexError("string index out of bounds");
}
if (beg + len > strLen) len = strLen - beg;
replace(beg, len, repl);
return repl;
}
rb_str_aset, rb_str_aset_m |
public int op_cmp(RubyString other) {
return value.cmp(other.value);
}
|
public IRubyObject op_cmp(ThreadContext context,
IRubyObject other) {
if (other instanceof RubyString) {
return context.getRuntime().newFixnum(op_cmp((RubyString)other));
}
// deal with case when "other" is not a string
if (other.respondsTo("to_str") && other.respondsTo("< = >")) {
IRubyObject result = other.callMethod(context, MethodIndex.OP_SPACESHIP, "< = >", this);
if (result instanceof RubyNumeric) {
return ((RubyNumeric) result).op_uminus(context);
}
}
return context.getRuntime().getNil();
}
|
public IRubyObject op_equal(ThreadContext context,
IRubyObject other) {
Ruby runtime = context.getRuntime();
if (this == other) return runtime.getTrue();
if (!(other instanceof RubyString)) {
if (!other.respondsTo("to_str")) return runtime.getFalse();
return other.callMethod(context, MethodIndex.EQUALEQUAL, "==", this).isTrue() ? runtime.getTrue() : runtime.getFalse();
}
return value.equal(((RubyString)other).value) ? runtime.getTrue() : runtime.getFalse();
}
|
public IRubyObject op_format(ThreadContext context,
IRubyObject arg) {
final RubyString s;
IRubyObject tmp = arg.checkArrayType();
if (tmp.isNil()) {
tmp = arg;
}
// FIXME: Should we make this work with platform's locale,
// or continue hardcoding US?
s = Sprintf.sprintf(context.getRuntime(), Locale.US, value, tmp);
s.infectBy(this);
return s;
}
|
public IRubyObject op_ge(ThreadContext context,
IRubyObject other) {
if (other instanceof RubyString) {
return context.getRuntime().newBoolean(op_cmp((RubyString) other) >= 0);
}
return RubyComparable.op_ge(context, this, other);
}
|
public IRubyObject op_gt(ThreadContext context,
IRubyObject other) {
if (other instanceof RubyString) {
return context.getRuntime().newBoolean(op_cmp((RubyString) other) > 0);
}
return RubyComparable.op_gt(context, this, other);
}
|
public IRubyObject op_le(ThreadContext context,
IRubyObject other) {
if (other instanceof RubyString) {
return context.getRuntime().newBoolean(op_cmp((RubyString) other) < = 0);
}
return RubyComparable.op_le(context, this, other);
}
|
public IRubyObject op_lt(ThreadContext context,
IRubyObject other) {
if (other instanceof RubyString) {
return context.getRuntime().newBoolean(op_cmp((RubyString) other) < 0);
}
return RubyComparable.op_lt(context, this, other);
}
|
public IRubyObject op_match(ThreadContext context,
IRubyObject other) {
if (other instanceof RubyRegexp) return ((RubyRegexp) other).op_match(context, this);
if (other instanceof RubyString) {
throw context.getRuntime().newTypeError("type mismatch: String given");
}
return other.callMethod(context, "=~", this);
}
|
public IRubyObject op_match2(ThreadContext context) {
return RubyRegexp.newRegexp(context.getRuntime(), value, 0, false).op_match2(context);
}
|
public IRubyObject op_mul(ThreadContext context,
IRubyObject other) {
RubyInteger otherInteger = (RubyInteger) other.convertToInteger();
long len = otherInteger.getLongValue();
if (len < 0) throw context.getRuntime().newArgumentError("negative argument");
// we limit to int because ByteBuffer can only allocate int sizes
if (len > 0 && Integer.MAX_VALUE / len < value.length()) {
throw context.getRuntime().newArgumentError("argument too big");
}
ByteList newBytes = new ByteList(value.length() * (int)len);
for (int i = 0; i < len; i++) {
newBytes.append(value);
}
RubyString newString = new RubyString(context.getRuntime(), getMetaClass(), newBytes);
newString.setTaint(isTaint());
return newString;
}
|
public IRubyObject op_plus(ThreadContext context,
IRubyObject other) {
RubyString str = other.convertToString();
ByteList result = new ByteList(value.realSize + str.value.realSize);
result.realSize = value.realSize + str.value.realSize;
System.arraycopy(value.bytes, value.begin, result.bytes, 0, value.realSize);
System.arraycopy(str.value.bytes, str.value.begin, result.bytes, value.realSize, str.value.realSize);
RubyString resultStr = newString(context.getRuntime(), result);
if (isTaint() || str.isTaint()) resultStr.setTaint(true);
return resultStr;
}
|
public RubyString replace(IRubyObject other) {
if (this == other) return this;
modifyCheck();
RubyString otherStr = stringValue(other);
otherStr.shareLevel = shareLevel = SHARE_LEVEL_BYTELIST;
value = otherStr.value;
infectBy(other);
return this;
}
|
public IRubyObject replace(int beg,
int len,
RubyString replaceWith) {
if (beg + len >= value.length()) len = value.length() - beg;
modify();
value.unsafeReplace(beg,len,replaceWith.value);
return infectBy(replaceWith);
}
|
public RubyString reverse(ThreadContext context) {
if (value.length() < = 1) return strDup(context.getRuntime());
ByteList buf = new ByteList(value.length()+2);
buf.realSize = value.length();
int src = value.length() - 1;
int dst = 0;
while (src >= 0) buf.set(dst++, value.get(src--));
RubyString rev = new RubyString(context.getRuntime(), getMetaClass(), buf);
rev.infectBy(this);
return rev;
}
|
public RubyString reverse_bang() {
if (value.length() > 1) {
modify();
for (int i = 0; i < (value.length() / 2); i++) {
byte b = (byte) value.get(i);
value.set(i, value.get(value.length() - i - 1));
value.set(value.length() - i - 1, b);
}
}
return this;
}
|
public IRubyObject rindex(ThreadContext context,
IRubyObject[] args) {
switch (args.length) {
case 1:
return rindex(context, args[0]);
case 2:
return rindex(context, args[0], args[1]);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! Use - the versions with one or two arguments.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject rindex(ThreadContext context,
IRubyObject arg0) {
return rindexCommon(arg0, value.realSize, context);
}
|
public IRubyObject rindex(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1) {
int pos = RubyNumeric.num2int(arg1);
if (pos < 0) {
pos += value.realSize;
if (pos < 0) {
if (arg0 instanceof RubyRegexp) {
context.getPreviousFrame().setBackRef(context.getRuntime().getNil());
}
return context.getRuntime().getNil();
}
}
if (pos > value.realSize) pos = value.realSize;
return rindexCommon(arg0, pos, context);
}
|
public IRubyObject rjust(IRubyObject[] args) {
switch (args.length) {
case 1:
return rjust(args[0]);
case 2:
return rjust(args[0], args[1]);
default:
Arity.raiseArgumentError(getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! use - the one or two argument versions.
Variable-arity version for compatibility. Not bound to Ruby. |
public IRubyObject rjust(IRubyObject arg0) {
return justify(arg0, 'r");
}
|
public IRubyObject rjust(IRubyObject arg0,
IRubyObject arg1) {
return justify(arg0, arg1, 'r");
}
|
public IRubyObject rstrip(ThreadContext context) {
RubyString str = strDup(context.getRuntime());
str.rstrip_bang();
return str;
}
|
public IRubyObject rstrip_bang() {
if (value.realSize == 0) return getRuntime().getNil();
int i=value.realSize - 1;
while (i >= 0 && value.bytes[value.begin+i] == 0) i--;
while (i >= 0 && ASCII.isSpace(value.bytes[value.begin + i] & 0xff)) i--;
if (i < value.realSize - 1) {
view(0, i + 1);
return this;
}
return getRuntime().getNil();
}
|
public IRubyObject scan(ThreadContext context,
IRubyObject arg,
Block block) {
Ruby runtime = context.getRuntime();
Frame frame = context.getPreviousFrame();
final RubyRegexp rubyRegex = getPattern(arg, true);
final Regex regex = rubyRegex.getPattern();
int range = value.begin + value.realSize;
final Matcher matcher = regex.matcher(value.bytes, value.begin, range);
matcher.value = 0; // implicit start argument to scanOnce(NG)
IRubyObject result;
if (!block.isGiven()) {
RubyArray ary = runtime.newArray();
if (regex.numberOfCaptures() == 0) {
while ((result = scanOnceNG(rubyRegex, matcher, range)) != null) ary.append(result);
} else {
while ((result = scanOnce(rubyRegex, matcher, range)) != null) ary.append(result);
}
if (ary.size() > 0) {
rubyRegex.updateBackRef(context, this, frame, matcher);
} else {
frame.setBackRef(runtime.getNil());
}
return ary;
} else {
byte[]bytes = value.bytes;
int size = value.realSize;
RubyMatchData match = null;
if (regex.numberOfCaptures() == 0) {
while ((result = scanOnceNG(rubyRegex, matcher, range)) != null) {
match = rubyRegex.updateBackRef(context, this, frame, matcher);
match.use();
block.yield(context, result);
modifyCheck(bytes, size);
}
} else {
while ((result = scanOnce(rubyRegex, matcher, range)) != null) {
match = rubyRegex.updateBackRef(context, this, frame, matcher);
match.use();
block.yield(context, result);
modifyCheck(bytes, size);
}
}
frame.setBackRef(match == null ? runtime.getNil() : match);
return this;
}
}
|
public void setValue(CharSequence value) {
view(ByteList.plain(value));
} Deprecated!
Mutator for internal string representation. |
public void setValue(ByteList value) {
view(value);
}
|
public IRubyObject slice_bang(ThreadContext context,
IRubyObject[] args) {
switch (args.length) {
case 1:
return slice_bang(context, args[0]);
case 2:
return slice_bang(context, args[0], args[1]);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 1, 2);
return null; // not reached
}
} Deprecated! Use - the versions with one or two args.
Variable arity version for compatibility. Not bound as a Ruby method. |
public IRubyObject slice_bang(ThreadContext context,
IRubyObject arg0) {
IRubyObject result = op_aref(context, arg0);
if (result.isNil()) return result;
op_aset(context, arg0, RubyString.newEmptyString(context.getRuntime()));
return result;
}
|
public IRubyObject slice_bang(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1) {
IRubyObject result = op_aref(context, arg0, arg1);
if (result.isNil()) return result;
op_aset(context, arg0, arg1, RubyString.newEmptyString(context.getRuntime()));
return result;
}
|
public RubyArray split(ThreadContext context) {
return split(context, context.getRuntime().getNil());
}
|
public RubyArray split(ThreadContext context,
IRubyObject[] args) {
switch (args.length) {
case 0:
return split(context);
case 1:
return split(context, args[0]);
case 2:
return split(context, args[0], args[1]);
default:
Arity.raiseArgumentError(context.getRuntime(), args.length, 0, 2);
return null; // not reached
}
} Deprecated! Use - the versions with zero, one, or two args.
Variable arity version for compatibility. Not bound to a Ruby method. |
public RubyArray split(ThreadContext context,
IRubyObject arg0) {
return splitCommon(arg0, false, 0, 0, context);
}
|
public RubyArray split(ThreadContext context,
IRubyObject arg0,
IRubyObject arg1) {
final int lim = RubyNumeric.fix2int(arg1);
if (lim < = 0) {
return splitCommon(arg0, false, lim, 1, context);
} else {
if (lim == 1) return value.realSize == 0 ? context.getRuntime().newArray() : context.getRuntime().newArray(this);
return splitCommon(arg0, true, lim, 1, context);
}
}
|
public IRubyObject squeeze(ThreadContext context,
IRubyObject[] args) {
RubyString str = strDup(context.getRuntime());
str.squeeze_bang(args);
return str;
}
|
public IRubyObject squeeze_bang(IRubyObject[] args) {
if (value.realSize == 0) {
modifyCheck();
return getRuntime().getNil();
}
final boolean squeeze[] = new boolean[TRANS_SIZE];
if (args.length == 0) {
for (int i=0; i< TRANS_SIZE; i++) squeeze[i] = true;
} else {
boolean init = true;
for (int i=0; i< args.length; i++) {
RubyString s = args[i].convertToString();
s.setup_table(squeeze, init);
init = false;
}
}
modify();
int s = value.begin;
int t = s;
int send = s + value.realSize;
byte[]buf = value.bytes;
int save = -1;
while (s < send) {
int c = buf[s++] & 0xff;
if (c != save || !squeeze[c]) buf[t++] = (byte)(save = c);
}
if (t - value.begin != value.realSize) { // modified
value.realSize = t - value.begin;
return this;
}
return getRuntime().getNil();
}
|
public final RubyString strDup() {
return strDup(getRuntime(), getMetaClass());
}
|
public final RubyString strDup(Ruby runtime) {
return strDup(runtime, getMetaClass());
}
|
final RubyString strDup(RubyClass clazz) {
return strDup(getRuntime(), getMetaClass());
}
|
final RubyString
|