Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    **** BEGIN LICENSE BLOCK *****
    * Version: EPL 1.0/GPL 2.0/LGPL 2.1
    *
    * The contents of this file are subject to the Eclipse Public
    * License Version 1.0 (the "License"); you may not use this file
    * except in compliance with the License. You may obtain a copy of
    * the License at http://www.eclipse.org/legal/epl-v10.html
    *
   * Software distributed under the License is distributed on an "AS
   * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
   * implied. See the License for the specific language governing
   * rights and limitations under the License.
   *
   * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
   * Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
   * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
   * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
   * Copyright (C) 2002-2006 Thomas E Enebo <enebo@acm.org>
   * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
   * Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
   * Copyright (C) 2005 Tim Azzopardi <tim@tigerfive.com>
   * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
   * Copyright (C) 2006 Ola Bini <ola@ologix.com>
   * Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
   *
   * Alternatively, the contents of this file may be used under the terms of
   * either of the GNU General Public License Version 2 or later (the "GPL"),
   * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   * in which case the provisions of the GPL or the LGPL are applicable instead
   * of those above. If you wish to allow use of your version of this file only
   * under the terms of either the GPL or the LGPL, and not to allow others to
   * use your version of this file under the terms of the EPL, indicate your
   * decision by deleting the provisions above and replace them with the notice
   * and other provisions required by the GPL or the LGPL. If you do not delete
   * the provisions above, a recipient may use your version of this file under
   * the terms of any one of the EPL, the GPL or the LGPL.
   ***** END LICENSE BLOCK *****/
  package org.jruby;
  
  import org.joni.Matcher;
  import org.joni.Option;
  import org.joni.Regex;
  import org.joni.Region;
  
  import java.util.Locale;
  
  import static org.jruby.CompatVersion.RUBY1_8;
  import static org.jruby.CompatVersion.RUBY1_9;
  import static org.jruby.CompatVersion.RUBY2_0;
  import static org.jruby.RubyEnumerator.enumeratorize;
  import static org.jruby.anno.FrameField.BACKREF;
  import static org.jruby.runtime.Helpers.invokedynamic;
  import static org.jruby.runtime.Visibility.PRIVATE;
  import static org.jruby.runtime.invokedynamic.MethodNames.OP_CMP;
  import static org.jruby.runtime.invokedynamic.MethodNames.OP_EQUAL;
  import static org.jruby.util.StringSupport.CR_7BIT;
  import static org.jruby.util.StringSupport.CR_BROKEN;
  import static org.jruby.util.StringSupport.CR_MASK;
  import static org.jruby.util.StringSupport.CR_UNKNOWN;
  import static org.jruby.util.StringSupport.CR_VALID;
  import static org.jruby.util.StringSupport.codeLength;
  import static org.jruby.util.StringSupport.codePoint;
 import static org.jruby.util.StringSupport.codeRangeScan;
 import static org.jruby.util.StringSupport.searchNonAscii;
 import static org.jruby.util.StringSupport.strLengthWithCodeRange;
 import static org.jruby.util.StringSupport.toLower;
 import static org.jruby.util.StringSupport.toUpper;
 import static org.jruby.util.StringSupport.unpackArg;
 import static org.jruby.util.StringSupport.unpackResult;
Implementation of Ruby String class Concurrency: no synchronization is required among readers, but all users must synchronize externally with writers.
 
 @JRubyClass(name="String", include={"Enumerable""Comparable"})
 public class RubyString extends RubyObject implements EncodingCapableMarshalEncoding {
 
     private static final ASCIIEncoding ASCII = .;
     private static final UTF8Encoding UTF8 = .;
     private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
 
     // string doesn't share any resources
     private static final int SHARE_LEVEL_NONE = 0;
     // string has it's own ByteList, but it's pointing to a shared buffer (byte[])
     private static final int SHARE_LEVEL_BUFFER = 1;
     // string doesn't have it's own ByteList (values)
     private static final int SHARE_LEVEL_BYTELIST = 2;
 
     private volatile int shareLevel = ;
 
     private ByteList value;
     
     private static final String[][] opTable19 = {
         { "+""+(binary)" }, 
         { "-""-(binary)" }
     };
     
     private static final String[][] opTable18 = {
         { "!""!@" },
         { "~""~@" },
         { "+""+(binary)" }, 
         { "-""-(binary)" },
         { "+@""+(unary)" }, 
         { "-@""-(unary)" },
         { "!""!(unary)" }, 
         { "~""~(unary)" }
     };
 
     public static RubyClass createStringClass(Ruby runtime) {
         RubyClass stringClass = runtime.defineClass("String"runtime.getObject(), );
         runtime.setString(stringClass);
         stringClass.index = .;
         stringClass.setReifiedClass(RubyString.class);
         stringClass.kindOf = new RubyModule.JavaClassKindOf(RubyString.class);
 
         stringClass.includeModule(runtime.getComparable());
         if (!runtime.is1_9()) stringClass.includeModule(runtime.getEnumerable());
         stringClass.defineAnnotatedMethods(RubyString.class);
 
         return stringClass;
     }
 
     private static ObjectAllocator STRING_ALLOCATOR = new ObjectAllocator() {
         @Override
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return RubyString.newAllocatedString(runtimeklass);
         }
     };
 
     @Override
     public Encoding getEncoding() {
         return .getEncoding();
     }
 
     @Override
     public void setEncoding(Encoding encoding) {
         .setEncoding(encoding);
     }
 
     @Override
     public boolean shouldMarshalEncoding() {
         return getEncoding() != .;
     }
 
     @Override
     public Encoding getMarshalEncoding() {
         return getEncoding();
     }
 
     public void associateEncoding(Encoding enc) {
         if (.getEncoding() != enc) {
             if (!isCodeRangeAsciiOnly() || !enc.isAsciiCompatible()) clearCodeRange();
             .setEncoding(enc);
         }
     }
 
     public final void setEncodingAndCodeRange(Encoding encint cr) {
         .setEncoding(enc);
         setCodeRange(cr);
     }
 
     public final Encoding toEncoding(Ruby runtime) {
         return runtime.getEncodingService().findEncoding(this);
     }
 
     public final int getCodeRange() {
         return  & ;
     }
 
     public final void setCodeRange(int codeRange) {
         clearCodeRange();
          |= codeRange & ;
     }
 
     public final void clearCodeRange() {
          &= ~;
     }
 
     private void keepCodeRange() {
         if (getCodeRange() == clearCodeRange();
     }
 
     // ENC_CODERANGE_ASCIIONLY
     public final boolean isCodeRangeAsciiOnly() {
         return getCodeRange() == ;
     }
 
     // rb_enc_str_asciionly_p
     public final boolean isAsciiOnly() {
         return .getEncoding().isAsciiCompatible() && scanForCodeRange() == ;
     }
 
     public final boolean isCodeRangeValid() {
         return ( & ) == ;
     }
 
     public final boolean isCodeRangeBroken() {
         return ( & ) == ;
     }
 
     static int codeRangeAnd(int cr1int cr2) {
         if (cr1 == return cr2;
         if (cr1 == return cr2 ==  ?  : cr2;
         return ;
     }
 
     private void copyCodeRangeForSubstr(RubyString fromEncoding enc) {
         int fromCr = from.getCodeRange();
         if (fromCr == ) {
             setCodeRange(fromCr);
         } else if (fromCr == ) {
             if (!enc.isAsciiCompatible() || searchNonAscii() != -1) {
                 setCodeRange();
             } else {
                 setCodeRange();
             }
         } else
             if (.getRealSize() == 0) {
                 setCodeRange(!enc.isAsciiCompatible() ?  : );
             }
         }
     }
 
     private void copyCodeRange(RubyString from) {
         .setEncoding(from.value.getEncoding());
         setCodeRange(from.getCodeRange());
     }
 
     // rb_enc_str_coderange
     public final int scanForCodeRange() {
         int cr = getCodeRange();
         if (cr == ) {
             cr = codeRangeScan(.getEncoding(), );
             setCodeRange(cr);
         }
         return cr;
     }
 
     final boolean singleByteOptimizable() {
         return getCodeRange() ==  || .getEncoding().isSingleByte();
     }
 
     final boolean singleByteOptimizable(Encoding enc) {
         return getCodeRange() ==  || enc.isSingleByte();
     }
 
     // rb_enc_compatible
     private Encoding isCompatibleWith(RubyString other) { 
         Encoding enc1 = .getEncoding();
         Encoding enc2 = other.value.getEncoding();
 
         if (enc1 == enc2return enc1;
 
         if (other.value.getRealSize() == 0) return enc1;
         if (.getRealSize() == 0) {
             return (enc1.isAsciiCompatible() && other.isAsciiOnly()) ? enc1 : enc2;
         }
 
         if (!enc1.isAsciiCompatible() || !enc2.isAsciiCompatible()) return null;
 
         return RubyEncoding.areCompatible(enc1scanForCodeRange(), enc2other.scanForCodeRange());
     }
 
     final Encoding isCompatibleWith(EncodingCapable other) {
         if (other instanceof RubyStringreturn checkEncoding((RubyString)other);
         Encoding enc1 = .getEncoding();
         Encoding enc2 = other.getEncoding();
 
         if (enc1 == enc2return enc1;
         if (.getRealSize() == 0) return enc2;
         if (!enc1.isAsciiCompatible() || !enc2.isAsciiCompatible()) return null;
         if (enc2 instanceof USASCIIEncodingreturn enc1;
         if (scanForCodeRange() == return enc2;
         return null;
     }
 
     // rb_enc_check
     public final Encoding checkEncoding(RubyString other) {
         Encoding enc = isCompatibleWith(other);
         if (enc == nullthrow getRuntime().newEncodingCompatibilityError("incompatible character encodings: " + 
                                 .getEncoding() + " and " + other.value.getEncoding());
         return enc;
     }
 
     final Encoding checkEncoding(EncodingCapable other) {
         Encoding enc = isCompatibleWith(other);
         if (enc == nullthrow getRuntime().newEncodingCompatibilityError("incompatible character encodings: " + 
                                 .getEncoding() + " and " + other.getEncoding());
         return enc;
     }
 
     private Encoding checkDummyEncoding() {
         Encoding enc = .getEncoding();
         if (enc.isDummy()) throw getRuntime().newEncodingCompatibilityError(
                 "incompatible encoding with this operation: " + enc);
         return enc;
     }
 
     private boolean isComparableWith(RubyString other) {
         ByteList otherValue = other.value;
         if (.getEncoding() == otherValue.getEncoding() ||
             .getRealSize() == 0 || otherValue.getRealSize() == 0) return true;
         return isComparableViaCodeRangeWith(other);
     }
 
     private boolean isComparableViaCodeRangeWith(RubyString other) {
         int cr1 = scanForCodeRange();
         int cr2 = other.scanForCodeRange();
 
         if (cr1 ==  && (cr2 ==  || other.value.getEncoding().isAsciiCompatible())) return true;
         if (cr2 ==  && .getEncoding().isAsciiCompatible()) return true;
         return false;
     }
 
     private int strLength(Encoding enc) {
         if (singleByteOptimizable(enc)) return .getRealSize();
         return strLength(enc);
     }
 
     public final int strLength() {
         if (singleByteOptimizable()) return .getRealSize();
         return strLength();
     }
 
     private int strLength(ByteList bytes) {
         return strLength(bytesbytes.getEncoding());
     }
 
     private int strLength(ByteList bytesEncoding enc) {
         if (isCodeRangeValid() && enc instanceof UTF8Encodingreturn StringSupport.utf8Length();
 
         long lencr = strLengthWithCodeRange(bytesenc);
         int cr = unpackArg(lencr);
         if (cr != 0) setCodeRange(cr);
         return unpackResult(lencr);
     }
 
     final int subLength(int pos) {
         if (singleByteOptimizable() || pos < 0) return pos;
         return StringSupport.strLength(.getEncoding(), .getUnsafeBytes(), .getBegin(), .getBegin() + pos);
     }

    
short circuit for String key comparison
 
     @Override
     public final boolean eql(IRubyObject other) {
         RubyClass metaclass = getMetaClass();
         Ruby runtime = metaclass.getClassRuntime();
         if (metaclass != runtime.getString() || metaclass != other.getMetaClass()) return super.eql(other);
         return runtime.is1_9() ? eql19(runtimeother) : eql18(runtimeother);
     }
 
     private boolean eql18(Ruby runtimeIRubyObject other) {
         return .equal(((RubyString)other).);
     }
 
     // rb_str_hash_cmp
     private boolean eql19(Ruby runtimeIRubyObject other) {
         RubyString otherString = (RubyString)other;
         return isComparableWith(otherString) && .equal(((RubyString)other).);
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClass) {
         this(runtimerubyClass);
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClassCharSequence value) {
         super(runtimerubyClass);
         assert value != null;
 
         Encoding defaultEncoding = runtime.getEncodingService().getLocaleEncoding();
         if (defaultEncoding == nulldefaultEncoding = ;
 
         this. = encodeBytelist(valuedefaultEncoding);
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClassCharSequence valueEncoding defaultEncoding) {
         super(runtimerubyClass);
         assert value != null;
 
         this. = encodeBytelist(valuedefaultEncoding);
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClassbyte[] value) {
         super(runtimerubyClass);
         assert value != null;
         this. = new ByteList(value);
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClassByteList value) {
         super(runtimerubyClass);
         assert value != null;
         this. = value;
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClassByteList valueboolean objectSpace) {
         super(runtimerubyClassobjectSpace);
         assert value != null;
         this. = value;
     }
 
     public RubyString(Ruby runtimeRubyClass rubyClassByteList valueEncoding encodingboolean objectSpace) {
         this(runtimerubyClassvalueobjectSpace);
         value.setEncoding(encoding);
     }
 
     protected RubyString(Ruby runtimeRubyClass rubyClassByteList valueEncoding encint cr) {
         this(runtimerubyClassvalue);
         value.setEncoding(enc);
          |= cr;
     }
 
     protected RubyString(Ruby runtimeRubyClass rubyClassByteList valueEncoding enc) {
         this(runtimerubyClassvalue);
         value.setEncoding(enc);
     }
 
     protected RubyString(Ruby runtimeRubyClass rubyClassByteList valueint cr) {
         this(runtimerubyClassvalue);
          |= cr;
     }
 
     // Deprecated String construction routines
     
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.

Deprecated:
 
     @Deprecated
     public RubyString newString(CharSequence s) {
         return new RubyString(getRuntime(), getType(), s);
     }

    
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.

Deprecated:
 
     @Deprecated
     public RubyString newString(ByteList s) {
         return new RubyString(getRuntime(), getMetaClass(), s);
     }
 
     @Deprecated
     public static RubyString newString(Ruby runtimeRubyClass clazzCharSequence str) {
         return new RubyString(runtimeclazzstr);
     }
 
     public static RubyString newStringLight(Ruby runtimeByteList bytes) {
         return new RubyString(runtimeruntime.getString(), bytesfalse);
     }
 
     public static RubyString newStringLight(Ruby runtimeint size) {
         return new RubyString(runtimeruntime.getString(), new ByteList(size), false);
     }
 
     public static RubyString newStringLight(Ruby runtimeint sizeEncoding encoding) {
         return new RubyString(runtimeruntime.getString(), new ByteList(size), encodingfalse);
     }
   
     public static RubyString newString(Ruby runtimeCharSequence str) {
         return new RubyString(runtimeruntime.getString(), str);
     }
 
     public static RubyString newString(Ruby runtimeString str) {
         return new RubyString(runtimeruntime.getString(), str);
     }
 
     public static RubyString newUSASCIIString(Ruby runtimeString str) {
         return new RubyString(runtimeruntime.getString(), str.);
     }
     
     public static RubyString newString(Ruby runtimebyte[] bytes) {
         return new RubyString(runtimeruntime.getString(), bytes);
     }
 
     public static RubyString newString(Ruby runtimebyte[] bytesint startint length) {
         byte[] copy = new byte[length];
         System.arraycopy(bytesstartcopy, 0, length);
         return new RubyString(runtimeruntime.getString(), new ByteList(copyfalse));
     }
 
     public static RubyString newString(Ruby runtimeByteList bytes) {
         return new RubyString(runtimeruntime.getString(), bytes);
     }
 
     public static RubyString newString(Ruby runtimeByteList bytesEncoding encoding) {
         return new RubyString(runtimeruntime.getString(), bytesencoding);
     }
 
     public static RubyString newUnicodeString(Ruby runtimeString str) {
         Encoding defaultInternal = runtime.getDefaultInternalEncoding();
         if (defaultInternal == .) {
             return newUTF16String(runtimestr);
         } else {
             return newUTF8String(runtimestr);
         }
     }
 
     public static RubyString newUTF8String(Ruby runtimeString str) {
         ByteList byteList = new ByteList(RubyEncoding.encodeUTF8(str), .false);
         return new RubyString(runtimeruntime.getString(), byteList);
     }
 
     public static RubyString newUTF16String(Ruby runtimeString str) {
         ByteList byteList = new ByteList(RubyEncoding.encodeUTF16(str), .false);
         return new RubyString(runtimeruntime.getString(), byteList);
     }
     
     public static RubyString newUnicodeString(Ruby runtimeCharSequence str) {
         Encoding defaultInternal = runtime.getDefaultInternalEncoding();
         if (defaultInternal == .) {
             return newUTF16String(runtimestr);
         } else {
             return newUTF8String(runtimestr);
         }
     }
 
     public static RubyString newUTF8String(Ruby runtimeCharSequence str) {
         ByteList byteList = new ByteList(RubyEncoding.encodeUTF8(str), .false);
         return new RubyString(runtimeruntime.getString(), byteList);
     }
 
     public static RubyString newUTF16String(Ruby runtimeCharSequence str) {
         ByteList byteList = new ByteList(RubyEncoding.encodeUTF16(str.toString()), .false);
         return new RubyString(runtimeruntime.getString(), byteList);
     }

    
Return a new Ruby String encoded as the default internal encoding given a Java String that has come from an external source. If there is no default internal encoding set, the Ruby String will be encoded using Java's default external encoding. If an internal encoding is set, that encoding will be used for the Ruby String.

Parameters:
runtime
str
Returns:
 
     public static RubyString newInternalFromJavaExternal(Ruby runtimeString str) {
         // Ruby internal
         Encoding internal = runtime.getDefaultInternalEncoding();
         Charset rubyInt = null;
         if (internal != null && internal.getCharset() != nullrubyInt = internal.getCharset();
 
         Encoding javaExtEncoding = runtime.getEncodingService().getJavaDefault();
 
         if (rubyInt == null) {
             return RubyString.newString(
                     runtime,
                     new ByteList(str.getBytes(), javaExtEncoding));
         } else {
             return RubyString.newString(
                     runtime,
                     new ByteList(RubyEncoding.encode(strrubyInt), internal));
         }
     }
 
     // String construction routines by NOT byte[] buffer and making the target String shared 
     public static RubyString newStringShared(Ruby runtimeRubyString orig) {
         orig.shareLevel = ;
         RubyString str = new RubyString(runtimeruntime.getString(), orig.value);
         str.shareLevel = ;
         return str;
     }       
 
     public static RubyString newStringShared(Ruby runtimeByteList bytes) {
         return newStringShared(runtimeruntime.getString(), bytes);
     }
 
     public static RubyString newStringShared(Ruby runtimeByteList bytesEncoding encoding) {
         return newStringShared(runtimeruntime.getString(), bytesencoding);
     }
 
 
     public static RubyString newStringShared(Ruby runtimeByteList bytesint codeRange) {
         RubyString str = new RubyString(runtimeruntime.getString(), bytescodeRange);
         str.shareLevel = ;
         return str;
     }
 
     public static RubyString newStringShared(Ruby runtimeRubyClass clazzByteList bytes) {
         RubyString str = new RubyString(runtimeclazzbytes);
         str.shareLevel = ;
         return str;
     }
 
     public static RubyString newStringShared(Ruby runtimeRubyClass clazzByteList bytesEncoding encoding) {
         RubyString str = new RubyString(runtimeclazzbytesencoding);
         str.shareLevel = ;
         return str;
     }
 
     public static RubyString newStringShared(Ruby runtimebyte[] bytes) {
         return newStringShared(runtimenew ByteList(bytesfalse));
     }
 
     public static RubyString newStringShared(Ruby runtimebyte[] bytesEncoding encoding) {
         return newStringShared(runtimenew ByteList(bytesencodingfalse));
     }
 
     public static RubyString newStringShared(Ruby runtimebyte[] bytesint startint length) {
         return newStringShared(runtimenew ByteList(bytesstartlengthfalse));
     }
 
     public static RubyString newStringShared(Ruby runtimebyte[] bytesint startint lengthEncoding encoding) {
         return newStringShared(runtimenew ByteList(bytesstartlengthencodingfalse));
     }
 
     public static RubyString newEmptyString(Ruby runtime) {
         return newEmptyString(runtimeruntime.getString());
     }
 
     private static final ByteList EMPTY_ASCII8BIT_BYTELIST = new ByteList(new byte[0], .);
     private static final ByteList EMPTY_USASCII_BYTELIST = new ByteList(new byte[0], .);
 
     public static RubyString newAllocatedString(Ruby runtimeRubyClass metaClass) {
         RubyString empty = new RubyString(runtimemetaClass);
         empty.shareLevel = ;
         return empty;
     }
 
     public static RubyString newEmptyString(Ruby runtimeRubyClass metaClass) {
         RubyString empty = new RubyString(runtimemetaClassruntime.is1_9() ?  : );
         empty.shareLevel = ;
         return empty;
     }
 
     // String construction routines by NOT byte[] buffer and NOT making the target String shared 
     public static RubyString newStringNoCopy(Ruby runtimeByteList bytes) {
         return newStringNoCopy(runtimeruntime.getString(), bytes);
     }    
 
     public static RubyString newStringNoCopy(Ruby runtimeRubyClass clazzByteList bytes) {
         return new RubyString(runtimeclazzbytes);
     }    
 
     public static RubyString newStringNoCopy(Ruby runtimebyte[] bytesint startint length) {
         return newStringNoCopy(runtimenew ByteList(bytesstartlengthfalse));
     }
 
     public static RubyString newStringNoCopy(Ruby runtimebyte[] bytes) {
         return newStringNoCopy(runtimenew ByteList(bytesfalse));
     }

    
Encoding aware String construction routines for 1.9
 
     private static final class EmptyByteListHolder {
         final ByteList bytes;
         final int cr;
         EmptyByteListHolder(Encoding enc) {
             this. = new ByteList(.enc);
             this. = .getEncoding().isAsciiCompatible() ?  : ;
         }
     }
 
     private static EmptyByteListHolder EMPTY_BYTELISTS[] = new EmptyByteListHolder[4];
 
         if (enc == nullenc = .;
         int index = enc.getIndex();
         EmptyByteListHolder bytes;
         if (index < . && (bytes = [index]) != null) {
             return bytes;
         }
         return prepareEmptyByteList(enc);
     }
 
     private static EmptyByteListHolder prepareEmptyByteList(Encoding enc) {
         if (enc == nullenc = .;
         int index = enc.getIndex();
         if (index >= .) {
             EmptyByteListHolder tmp[] = new EmptyByteListHolder[index + 4];
             System.arraycopy(,0, tmp, 0, .);
              = tmp;
         }
         return [index] = new EmptyByteListHolder(enc);
     }
 
     public static RubyString newEmptyString(Ruby runtimeRubyClass metaClassEncoding enc) {
         EmptyByteListHolder holder = getEmptyByteList(enc);
         RubyString empty = new RubyString(runtimemetaClassholder.bytesholder.cr);
         empty.shareLevel = ;
         return empty;
     }
 
     public static RubyString newEmptyString(Ruby runtimeEncoding enc) {
         return newEmptyString(runtimeruntime.getString(), enc);
     }
 
     public static RubyString newStringNoCopy(Ruby runtimeRubyClass clazzByteList bytesEncoding encint cr) {
         return new RubyString(runtimeclazzbytesenccr);
     }
 
     public static RubyString newStringNoCopy(Ruby runtimeByteList bytesEncoding encint cr) {
         return newStringNoCopy(runtimeruntime.getString(), bytesenccr);
     }
 
     public static RubyString newUsAsciiStringNoCopy(Ruby runtimeByteList bytes) {
         return newStringNoCopy(runtimebytes.);
     }
 
     public static RubyString newUsAsciiStringShared(Ruby runtimeByteList bytes) {
         RubyString str = newStringNoCopy(runtimebytes.);
         str.shareLevel = ;
         return str;
     }
     
     public static RubyString newUsAsciiStringShared(Ruby runtimebyte[] bytesint startint length) {
         byte[] copy = new byte[length];
         System.arraycopy(bytesstartcopy, 0, length);
         return newUsAsciiStringShared(runtimenew ByteList(copyfalse));
     }
 
     @Override
     public int getNativeTypeIndex() {
         return .;
     }
 
     @Override
     public Class getJavaClass() {
         return String.class;
     }
 
     @Override
     public RubyString convertToString() {
         return this;
     }
 
     @Override
     public String toString() {
         return decodeString();
     }

    
Convert this Ruby string to a Java String. This version is encoding-aware.

Returns:
A decoded Java String, based on this Ruby string's encoding.
 
     public String decodeString() {
         return Helpers.decodeByteList(getRuntime(), );
     }

    
Overridden dup for fast-path logic.

Returns:
A new RubyString sharing the original backing store.
 
     @Override
     public IRubyObject dup() {
         RubyClass mc = .getRealClass();
         if (mc.index != .return super.dup();
 
         return strDup(mc.getClassRuntime(), mc.getRealClass());
     }

    
rb_str_dup
 
     @Deprecated
     public final RubyString strDup() {
         return strDup(getRuntime(), getMetaClass());
     }
     
     public final RubyString strDup(Ruby runtime) {
         return strDup(runtimegetMetaClass());
     }
     
     @Deprecated
     final RubyString strDup(RubyClass clazz) {
         return strDup(getRuntime(), getMetaClass());
     }
 
     final RubyString strDup(Ruby runtimeRubyClass clazz) {
          = ;
         RubyString dup = new RubyString(runtimeclazz);
         dup.shareLevel = ;
         dup.flags |=  & ( |  | );
         
         return dup;
     }
     
     /* rb_str_subseq */
     public final RubyString makeSharedString(Ruby runtimeint indexint len) {
         return runtime.is1_9()
                 ? makeShared19(runtimeruntime.getString(), indexlen)
                 : makeShared(runtimeruntime.getString(), indexlen);
     }
     
     public RubyString makeSharedString19(Ruby runtimeint indexint len) {
         return makeShared19(runtimeruntime.getString(), indexlen);
     }
 
     public final RubyString makeShared(Ruby runtimeint indexint len) {
         return runtime.is1_9()
                 ? makeShared19(runtimegetType(), indexlen)
                 : makeShared(runtimegetType(), indexlen);
     }
 
     public final RubyString makeShared(Ruby runtimeRubyClass metaint indexint len) {
         final RubyString shared;
         if (len == 0) {
             shared = newEmptyString(runtimemeta);
         } else if (len == 1) {
             shared = newStringShared(runtimemeta
                     .[.getUnsafeBytes()[.getBegin() + index] & 0xff]);
         } else {
             if ( ==  = ;
             shared = new RubyString(runtimemeta.makeShared(indexlen));
             shared.shareLevel = ;
         }
 
         shared.infectBy(this);
         return shared;
     }
 
     public final RubyString makeShared19(Ruby runtimeint indexint len) {
         return makeShared19(runtimeindexlen);
     }
 
     public final RubyString makeShared19(Ruby runtimeRubyClass metaint indexint len) {
         return makeShared19(runtimemetaindexlen);
     }
 
     private RubyString makeShared19(Ruby runtimeByteList valueint indexint len) {
         return makeShared19(runtimegetType(), valueindexlen);
     }
     
     private RubyString makeShared19(Ruby runtimeRubyClass metaByteList valueint indexint len) {
         final RubyString shared;
         Encoding enc = value.getEncoding();
 
         if (len == 0) {
             shared = newEmptyString(runtimemetaenc);
         } else if (len == 1) {
             // as with the 1.8 makeShared, don't bother sharing for substrings that are a single byte
             // to get a good speed boost in a number of common scenarios (note though that unlike 1.8,
             // we can't take advantage of SINGLE_CHAR_BYTELISTS since our encoding may not be ascii, but the
             // single byte copy is pretty much negligible)
             shared = newStringShared(runtime,
                                      meta,
                                      new ByteList(new byte[] { (bytevalue.get(index) }, enc),
                                      enc);
         } else {
             if ( ==  = ;
             shared = new RubyString(runtimemetavalue.makeShared(indexlen));
             shared.shareLevel = ;
             shared.copyCodeRangeForSubstr(thisenc); // no need to assign encoding, same bytelist shared
         }
         shared.infectBy(this);
         return shared;
     }
 
     public final void setByteListShared() {
     }

    
Check that the string can be modified, raising error otherwise. If you plan to modify a string with shared backing store, this method is not sufficient; you will need to call modify() instead.
 
     public final void modifyCheck() {
         frozenCheck();
     }
 
     private void modifyCheck(byte[] bint len) {
         if (.getUnsafeBytes() != b || .getRealSize() != lenthrow getRuntime().newRuntimeError("string modified");
     }
 
     private void modifyCheck(byte[] bint lenEncoding enc) {
         if (.getUnsafeBytes() != b || .getRealSize() != len || .getEncoding() != encthrow getRuntime().newRuntimeError("string modified");
     }
 
     private void frozenCheck() {
         frozenCheck(false);
     }
 
     private void frozenCheck(boolean runtimeError) {
         if (isFrozen()) throw getRuntime().newFrozenError("string"runtimeError);
     }

    
rb_str_modify
 
     public final void modify() {
         modifyCheck();
 
         if ( != ) {
             if ( == ) {
                  = .dup();
             } else {
                 .unshare();
             }
              = ;
         }
 
         .invalidate();
     }
 
     public final void modify19() {
         modify();
         clearCodeRange();
     }
 
     private void modifyAndKeepCodeRange() {
         modify();
         keepCodeRange();
     }

    
rb_str_modify (with length bytes ensured)
 
     public final void modify(int length) {
         modifyCheck();
 
         if ( != ) {
             if ( == ) {
                  = .dup(length);
             } else {
                 .unshare(length);
             }
              = ;
         } else {
             .ensure(length);
         }
 
         .invalidate();
     }
 
     public final void modify19(int length) {
         modify(length);
         clearCodeRange();
     }

    
rb_str_resize
 
     public final void resize(int length) {
         modify();
         if (.getRealSize() > length) {
             .setRealSize(length);
         } else if (.length() < length) {
             .length(length);
         }
     }
 
     public final void view(ByteList bytes) {
         modifyCheck();
 
          = bytes;
          = ;
     }
 
     private void view(byte[]bytes) {