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-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
  * Copyright (C) 2004 Joey Gibson <joey@joeygibson.com>
  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
  * Copyright (C) 2006 Derek Berner <derek.berner@state.nm.us>
  * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
  * Copyright (C) 2007 William N Dortch <bill.dortch@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 static org.jruby.util.StringSupport.codeLength;
 import static org.jruby.util.StringSupport.codePoint;
 
 
Represents a Ruby symbol (e.g. :bar)
 
 @JRubyClass(name="Symbol")
 public class RubySymbol extends RubyObject implements MarshalEncoding {
     public static final long symbolHashSeedK0 = 5238926673095087190l;
 
     private final String symbol;
     private final int id;
     private final ByteList symbolBytes;
     private final int hashCode;
    
    

Parameters:
runtime
internedSymbol the String value of the new Symbol. This must have been previously interned
 
     private RubySymbol(Ruby runtimeString internedSymbolByteList symbolBytes) {
         super(runtimeruntime.getSymbol(), false);
         // symbol string *must* be interned
 
         //        assert internedSymbol == internedSymbol.intern() : internedSymbol + " is not interned";
 
         if (!runtime.is1_9()) {
             int length = symbolBytes.getBegin() + symbolBytes.getRealSize();
             for (int i = symbolBytes.getBegin(); i < lengthi++) {
                 if (symbolBytes.getUnsafeBytes()[i] == 0) {
                     throw runtime.newSyntaxError("symbol cannot contain '\\0'");
                }
            }
        }
        this. = internedSymbol;
        this. = symbolBytes;
        this. = runtime.allocSymbolId();
        long hash = runtime.isSiphashEnabled() ? SipHashInline.hash24(
                , 0, symbolBytes.getUnsafeBytes(),
                symbolBytes.getBegin(), symbolBytes.getRealSize()) :
                PerlHash.hash(symbolBytes.getUnsafeBytes(),
                symbolBytes.getBegin(), symbolBytes.getRealSize());
        this. = (inthash;
    }
    private RubySymbol(Ruby runtimeString internedSymbol) {
        this(runtimeinternedSymbolsymbolBytesFromString(runtimeinternedSymbol));
    }
    public static RubyClass createSymbolClass(Ruby runtime) {
        RubyClass symbolClass = runtime.defineClass("Symbol"runtime.getObject(), .);
        runtime.setSymbol(symbolClass);
        RubyClass symbolMetaClass = symbolClass.getMetaClass();
        symbolClass.index = .;
        symbolClass.setReifiedClass(RubySymbol.class);
        symbolClass.kindOf = new RubyModule.JavaClassKindOf(RubySymbol.class);
        symbolClass.defineAnnotatedMethods(RubySymbol.class);
        symbolMetaClass.undefineMethod("new");
        if (runtime.is1_9()) {
            symbolClass.includeModule(runtime.getComparable());
        }
        
        return symbolClass;
    }
    
    @Override
    public int getNativeTypeIndex() {
        return .;
    }

    
rb_to_id

Returns:
a String representation of the symbol
    @Override
    public String asJavaString() {
        return ;
    }
    @Override
    public String toString() {
        return ;
    }
    final ByteList getBytes() {
        return ;
    }

    
RubySymbol is created by passing in a String and bytes are extracted from that. We will pass in encoding of that string after construction but before use so it does not forget what it is.
    public void associateEncoding(Encoding encoding) {
        .setEncoding(encoding);
    }

    
short circuit for Symbol key comparison
    @Override
    public final boolean eql(IRubyObject other) {
        return other == this;
    }
    @Override
    public boolean isImmediate() {
    	return true;
    }
    @Override
    public RubyClass getSingletonClass() {
        throw getRuntime().newTypeError("can't define singleton");
    }
    public static RubySymbol getSymbolLong(Ruby runtimelong id) {
        return runtime.getSymbolTable().lookup(id);
    }
    
    /* Symbol class methods.
     * 
     */
    
    public static RubySymbol newSymbol(Ruby runtimeIRubyObject name) {
        if (!(name instanceof RubyString)) return newSymbol(runtimename.asJavaString());
        
        return runtime.getSymbolTable().getSymbol(((RubyStringname).getByteList());
    }
    public static RubySymbol newSymbol(Ruby runtimeString name) {
        return runtime.getSymbolTable().getSymbol(name);
    }
    @Deprecated
    public RubyFixnum to_i() {
        return to_i(getRuntime());
    }
    @JRubyMethod(name = "to_i", compat = .)
    public RubyFixnum to_i(ThreadContext context) {
        return to_i(context.runtime);
    }
    private final RubyFixnum to_i(Ruby runtime) {
        return runtime.newFixnum();
    }
    @Deprecated
    public RubyFixnum to_int() {
        return to_int(getRuntime());
    }
    @JRubyMethod(name = "to_int", compat = .)
    public RubyFixnum to_int(ThreadContext context) {
        return to_int(context.runtime);
    }
    private final RubyFixnum to_int(Ruby runtime) {
        if (runtime.isVerbose()) runtime.getWarnings().warn(."treating Symbol as an integer");
        return to_i(runtime);
    }
    @Deprecated
    @Override
    public IRubyObject inspect() {
        return inspect(getRuntime());
    }
    @JRubyMethod(name = "inspect", compat = .)
    public IRubyObject inspect(ThreadContext context) {
        return inspect(context.runtime);
    }
    private final IRubyObject inspect(Ruby runtime) {
        final ByteList bytes = isSymbolName() ?  : 
                ((RubyString)RubyString.newString(runtime).dump()).getByteList();
        ByteList result = new ByteList(bytes.getRealSize() + 1);
        result.append((byte)':').append(bytes);
        return RubyString.newString(runtimeresult);
    }
    @Deprecated
    public IRubyObject inspect19() {
        return inspect19(getRuntime());
    }
    @JRubyMethod(name = "inspect", compat = .)
    public IRubyObject inspect19(ThreadContext context) {
        return inspect19(context.runtime);
    }
    private final IRubyObject inspect19(Ruby runtime) {
        ByteList result = new ByteList(.getRealSize() + 1);
        result.setEncoding(.getEncoding());
        result.append((byte)':');
        result.append();
        RubyString str = RubyString.newString(runtimeresult); 
        // TODO: 1.9 rb_enc_symname_p
        Encoding resenc = runtime.getDefaultInternalEncoding();
        if (resenc == null) {
            resenc = runtime.getDefaultExternalEncoding();
        }
        if (isPrintable() && (resenc.equals(.getEncoding()) || str.isAsciiOnly()) && isSymbolName19()) {
            return str;
        }
    
        str = (RubyString)str.inspect19();
        ByteList bytes = str.getByteList();
        bytes.set(0, ':');
        bytes.set(1, '"');
        
        return str;
    }
    @Override
    public IRubyObject to_s() {
        return to_s(getRuntime());
    }
    
    @JRubyMethod(name = "to_s")
    public IRubyObject to_s(ThreadContext context) {
        return to_s(context.runtime);
    }
    
    private final IRubyObject to_s(Ruby runtime) {
        return RubyString.newStringShared(runtime);
    }
    public IRubyObject id2name() {
        return to_s(getRuntime());
    }
    
    @JRubyMethod(name = "id2name")
    public IRubyObject id2name(ThreadContext context) {
        return to_s(context);
    }
    @JRubyMethod(name = "===", required = 1)
    @Override
    public IRubyObject op_eqq(ThreadContext contextIRubyObject other) {
        return super.op_equal(contextother);
    }
    @Deprecated
    @Override
    public RubyFixnum hash() {
        return getRuntime().newFixnum(hashCode());
    }
    @JRubyMethod(name = "hash")
    public RubyFixnum hash(ThreadContext context) {
        return context.runtime.newFixnum(hashCode());
    }
    
    @Override
    public int hashCode() {
        return ;
    }
    public int getId() {
        return ;
    }
    
    @Override
    public boolean equals(Object other) {
        return other == this;
    }
    
    @JRubyMethod(name = "to_sym")
    public IRubyObject to_sym() {
        return this;
    }
    @JRubyMethod(name = "intern", compat = .)
    public IRubyObject to_sym19() {
        return this;
    }
    @Override
    public IRubyObject taint(ThreadContext context) {
        return this;
    }
    private RubyString newShared(Ruby runtime) {
        return RubyString.newStringShared(runtime);
    }
    private RubyString rubyStringFromString(Ruby runtime) {
        return RubyString.newString(runtime);
    }
    @JRubyMethod(name = {"succ""next"}, compat = .)
    public IRubyObject succ(ThreadContext context) {
        Ruby runtime = context.runtime;
        return newSymbol(runtimenewShared(runtime).succ19(context).toString());
    }
    @JRubyMethod(name = "<=>", compat = .)
    @Override
    public IRubyObject op_cmp(ThreadContext contextIRubyObject other) {
        Ruby runtime = context.runtime;
        
        return !(other instanceof RubySymbol) ? runtime.getNil() :
                newShared(runtime).op_cmp19(context, ((RubySymbol)other).newShared(runtime));
    }
    @JRubyMethod(name = "casecmp", compat = .)
    public IRubyObject casecmp(ThreadContext contextIRubyObject other) {
        Ruby runtime = context.runtime;
        
        return !(other instanceof RubySymbol) ? runtime.getNil() :
                newShared(runtime).casecmp19(context, ((RubySymbolother).newShared(runtime));
    }
    @JRubyMethod(name = {"=~""match"}, compat = .)
    @Override
    public IRubyObject op_match19(ThreadContext contextIRubyObject other) {
        return newShared(context.runtime).op_match19(contextother);
    }
    @JRubyMethod(name = {"[]""slice"}, compat = .)
    public IRubyObject op_aref(ThreadContext contextIRubyObject arg) {
        return newShared(context.runtime).op_aref19(contextarg);
    }
    @JRubyMethod(name = {"[]""slice"}, compat = .)
    public IRubyObject op_aref(ThreadContext contextIRubyObject arg1IRubyObject arg2) {
        return newShared(context.runtime).op_aref19(contextarg1arg2);
    }
    @JRubyMethod(name = {"length""size"}, compat = .)
    public IRubyObject length() {
        return newShared(getRuntime()).length19();
    }
    @JRubyMethod(name = "empty?", compat = .)
    public IRubyObject empty_p(ThreadContext context) {
        return newShared(context.runtime).empty_p(context);
    }
    @JRubyMethod(name = "upcase", compat = .)
    public IRubyObject upcase(ThreadContext context) {
        Ruby runtime = context.runtime;
        
        return newSymbol(runtimerubyStringFromString(runtime).upcase19(context).toString());
    }
    @JRubyMethod(name = "downcase", compat = .)
    public IRubyObject downcase(ThreadContext context) {
        Ruby runtime = context.runtime;
        
        return newSymbol(runtimerubyStringFromString(runtime).downcase19(context).toString());
    }
    @JRubyMethod(name = "capitalize", compat = .)
    public IRubyObject capitalize(ThreadContext context) {
        Ruby runtime = context.runtime;
        
        return newSymbol(runtimerubyStringFromString(runtime).capitalize19(context).toString());
    }
    @JRubyMethod(name = "swapcase", compat = .)
    public IRubyObject swapcase(ThreadContext context) {
        Ruby runtime = context.runtime;
        
        return newSymbol(runtimerubyStringFromString(runtime).swapcase19(context).toString());
    }
    @JRubyMethod(name = "encoding", compat = .)
    public IRubyObject encoding(ThreadContext context) {
        return context.runtime.getEncodingService().getEncoding(.getEncoding());
    }
    
    public IRubyObject to_proc(ThreadContext context) {
        StaticScope scope = context.runtime.getStaticScopeFactory().getDummyScope();
        final CallSite site = new FunctionalCachingCallSite();
        BlockBody body = new ContextAwareBlockBody(scope..) {
            private IRubyObject yieldInner(ThreadContext contextRubyArray arrayBlock block) {
                if (array.isEmpty()) {
                    throw context.runtime.newArgumentError("no receiver given");
                }
                IRubyObject self = array.shift(context);
                return site.call(contextselfselfarray.toJavaArray(), block);
            }
            @Override
            public IRubyObject yield(ThreadContext contextIRubyObject valueIRubyObject self,
                    RubyModule klassboolean aValueBinding bindingBlock.Type typeBlock block) {
                RubyArray array = aValue && value instanceof RubyArray ?
                        (RubyArrayvalue : ArgsUtil.convertToRubyArray(context.runtimevaluefalse);
                return yieldInner(contextarrayblock);
            }
            @Override
            public IRubyObject yield(ThreadContext contextIRubyObject value,
                    Binding bindingBlock.Type typeBlock block) {
                return yieldInner(context, ArgsUtil.convertToRubyArray(context.runtimevaluefalse), block);
            }
            
            @Override
            public IRubyObject yield(ThreadContext contextIRubyObject valueBinding bindingType type) {
                return yieldInner(context, ArgsUtil.convertToRubyArray(context.runtimevaluefalse), .);
            }
            @Override
            public IRubyObject yield(ThreadContext contextIRubyObject valueIRubyObject selfRubyModule klassboolean aValueBinding bindingType type) {
                RubyArray array = aValue && value instanceof RubyArray ?
                        (RubyArrayvalue : ArgsUtil.convertToRubyArray(context.runtimevaluefalse);
                return yieldInner(contextarray.);
            }
            @Override
            public IRubyObject yieldSpecific(ThreadContext contextIRubyObject arg0Binding bindingBlock.Type type) {
                return site.call(contextarg0arg0);
            }
            @Override
            public IRubyObject yieldSpecific(ThreadContext contextIRubyObject arg0IRubyObject arg1Binding bindingBlock.Type type) {
                return site.call(contextarg0arg0arg1);
            }
            @Override
            public IRubyObject yieldSpecific(ThreadContext contextIRubyObject arg0IRubyObject arg1IRubyObject arg2Binding bindingBlock.Type type) {
                return site.call(contextarg0arg0arg1arg2);
            }
            public String getFile() {
                return ;
            }
            public int getLine() {
                return -1;
            }
        };
        return RubyProc.newProc(context.runtime,
                                new Block(bodycontext.currentBinding()),
                                ..);
    }
    
    private static boolean isIdentStart(char c) {
        return ((c >= 'a' && c <= 'z')|| (c >= 'A' && c <= 'Z') || c == '_' || !(c < 128));
    }
    
    private static boolean isIdentChar(char c) {
        return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || c == '_' || !(c < 128));
    }
    
    private static boolean isIdentifier(String s) {
        if (s == null || s.length() <= 0 || !isIdentStart(s.charAt(0))) return false;
        for (int i = 1; i < s.length(); i++) {
            if (!isIdentChar(s.charAt(i))) return false;
        }
        
        return true;
    }
    
    
is_special_global_name from parse.c.

Parameters:
s
Returns:
    private static boolean isSpecialGlobalName(String s) {
        if (s == null || s.length() <= 0) return false;
        int length = s.length();
           
        switch (s.charAt(0)) {        
        case '~'case '*'case '$'case '?'case '!'case '@'case '/'case '\\':        
        case ';'case ','case '.'case '='case ':'case '<'case '>'case '\"':        
        case '&'case '`'case '\''case '+'case '0':
            return length == 1;            
        case '-':
            return (length == 1 || (length == 2 && isIdentChar(s.charAt(1))));
            
        default:
            for (int i = 0; i < lengthi++) {
                if (!Character.isDigit(s.charAt(i))) return false;
            }
        }
        
        return true;
    }
    private boolean isPrintable() {
        Ruby runtime = getRuntime();
        int p = .getBegin();
        int end = p + .getRealSize();
        byte[]bytes = .getUnsafeBytes();
        Encoding enc = .getEncoding();
        while (p < end) {
            int c = codePoint(runtimeencbytespend);
            
            if (!enc.isPrint(c)) return false;
            
            p += codeLength(runtimeencc);
        }
        
        return true;
    }
    private static boolean isSymbolName19(String s) {
        if (s == null || s.length() < 1) return false;
        int length = s.length();
        char c = s.charAt(0);
        
        return isSymbolNameCommon(sclength) || 
                (c == '!' && (length == 1 ||
                             (length == 2 && (s.charAt(1) == '~' || s.charAt(1) == '=')))) ||
                isSymbolLocal(sclength);
    }
    private static boolean isSymbolName(String s) {
        if (s == null || s.length() < 1) return false;
        int length = s.length();
        char c = s.charAt(0);
        
        return isSymbolNameCommon(sclength) || isSymbolLocal(sclength);
    }
    private static boolean isSymbolNameCommon(String schar cint length) {        
        switch (c) {
        case '$':
            if (length > 1 && isSpecialGlobalName(s.substring(1))) return true;
            return isIdentifier(s.substring(1));
        case '@':
            int offset = 1;
            if (length >= 2 && s.charAt(1) == '@'offset++;
            return isIdentifier(s.substring(offset));
        case '<':
            return (length == 1 || (length == 2 && (s.equals("<<") || s.equals("<="))) ||
                    (length == 3 && s.equals("<=>")));
        case '>':
            return (length == 1) || (length == 2 && (s.equals(">>") || s.equals(">=")));
        case '=':
            return ((length == 2 && (s.equals("==") || s.equals("=~"))) ||
                    (length == 3 && s.equals("===")));
        case '*':
            return (length == 1 || (length == 2 && s.equals("**")));
        case '+':
            return (length == 1 || (length == 2 && s.equals("+@")));
        case '-':
            return (length == 1 || (length == 2 && s.equals("-@")));
        case '|'case '^'case '&'case '/'case '%'case '~'case '`':
            return length == 1;
        case '[':
            return s.equals("[]") || s.equals("[]=");
        }
        return false;
    }
    private static boolean isSymbolLocal(String schar cint length) {
        if (!isIdentStart(c)) return false;
        boolean localID = (c >= 'a' && c <= 'z');
        int last = 1;
        for (; last < lengthlast++) {
            char d = s.charAt(last);
            if (!isIdentChar(d)) break;
        }
        if (last == lengthreturn true;
        if (localID && last == length - 1) {
            char d = s.charAt(last);
            return d == '!' || d == '?' || d == '=';
        }
        return false;
    }
    
    @JRubyMethod(name = "all_symbols", meta = true)
    public static IRubyObject all_symbols(ThreadContext contextIRubyObject recv) {
        return context.runtime.getSymbolTable().all_symbols();
    }
    @Deprecated
    public static IRubyObject all_symbols(IRubyObject recv) {
        return recv.getRuntime().getSymbolTable().all_symbols();
    }
    public static RubySymbol unmarshalFrom(UnmarshalStream inputthrows java.io.IOException {
        RubySymbol result = newSymbol(input.getRuntime(), RubyString.byteListToString(input.unmarshalString()));
        
        input.registerLinkTarget(result);
        
        return result;
    }
    @Override
    public Object toJava(Class target) {
        if (target == String.class || target == CharSequence.classreturn ;
        return super.toJava(target);
    }
    private static ByteList symbolBytesFromString(Ruby runtimeString internedSymbol) {
        if (runtime.is1_9()) {
            return new ByteList(ByteList.plain(internedSymbol), .false);
        } else {
            return ByteList.create(internedSymbol);
        }
    }
    public static final class SymbolTable {
        static final int DEFAULT_INITIAL_CAPACITY = 2048; // *must* be power of 2!
        static final int MAXIMUM_CAPACITY = 1 << 30;
        static final float DEFAULT_LOAD_FACTOR = 0.75f;
        
        private final ReentrantLock tableLock = new ReentrantLock();
        private volatile SymbolEntry[] symbolTable;
        private final ConcurrentHashMap<ByteListRubySymbolbytelistTable = new ConcurrentHashMap<ByteListRubySymbol>(100, 0.75f, Runtime.getRuntime().availableProcessors());
        private int size;
        private int threshold;
        private final float loadFactor;
        private final Ruby runtime;
        
        public SymbolTable(Ruby runtime) {
            this. = runtime;
            this. = ;
            this. = (int)( * );
            this. = new SymbolEntry[];
        }
        
        // note all fields are final -- rehash creates new entries when necessary.
        // as documented in java.util.concurrent.ConcurrentHashMap.java, that will
        // statistically affect only a small percentage (< 20%) of entries for a given rehash.
        static class SymbolEntry {
            final int hash;
            final String name;
            final RubySymbol symbol;
            final SymbolEntry next;
            
            SymbolEntry(int hashString nameRubySymbol symbolSymbolEntry next) {
                this. = hash;
                this. = name;
                this. = symbol;
                this. = next;
            }
        }
        public RubySymbol getSymbol(String name) {
            int hash = name.hashCode();
            SymbolEntry[] table = ;
            
            for (SymbolEntry e = getEntryFromTable(tablehash); e != nulle = e.next) {
                if (isSymbolMatch(namehashe)) return e.symbol;
            }
            
            return createSymbol(namesymbolBytesFromString(name), hashtable);
        }
        public RubySymbol getSymbol(ByteList bytes) {
            RubySymbol symbol = .get(bytes);
            if (symbol != nullreturn symbol;
            String name = bytes.toString();
            int hash = name.hashCode();
            SymbolEntry[] table = ;
            
            for (SymbolEntry e = getEntryFromTable(tablehash); e != nulle = e.next) {
                if (isSymbolMatch(namehashe)) {
                    symbol = e.symbol;
                    break;
                }
            }
            if (symbol == null) {
                symbol = createSymbol(namebyteshashtable);
            }
            
            .put(bytessymbol);
            return symbol;
        }
        public RubySymbol fastGetSymbol(String internedName) {
            SymbolEntry[] table = ;
            
            for (SymbolEntry e = getEntryFromTable(internedName.hashCode()); e != nulle = e.next) {
                if (isSymbolMatch(internedNamee)) return e.symbol;
            }
            
            return fastCreateSymbol(internedNametable);
        }
        private static SymbolEntry getEntryFromTable(SymbolEntry[] tableint hash) {
            return table[hash & (table.length - 1)];
        }
        private static boolean isSymbolMatch(String nameint hashSymbolEntry entry) {
            return hash == entry.hash && name.equals(entry.name);
        }
        private static boolean isSymbolMatch(String internedNameSymbolEntry entry) {
            return internedName == entry.name;
        }
        private RubySymbol createSymbol(String nameByteList valueint hashSymbolEntry[] table) {
            ReentrantLock lock;
            (lock = ).lock();
            try {
                int index;                
                int potentialNewSize =  + 1;
                
                table = potentialNewSize >  ? rehash() : ;
                // try lookup again under lock
                for (SymbolEntry e = table[index = hash & (table.length - 1)]; e != nulle = e.next) {
                    if (hash == e.hash && name.equals(e.name)) return e.symbol;
                }
                String internedName = name.intern();
                RubySymbol symbol = new RubySymbol(internedNamevalue);
                table[index] = new SymbolEntry(hashinternedNamesymboltable[index]);
                 = potentialNewSize;
                // write-volatile
                 = table;
                return symbol;
            } finally {
                lock.unlock();
            }
        }
        private RubySymbol fastCreateSymbol(String internedNameSymbolEntry[] table) {
            ReentrantLock lock;
            (lock = ).lock();
            try {
                int index;
                int hash;
                int potentialNewSize =  + 1;
                
                table = potentialNewSize >  ? rehash() : ;
                // try lookup again under lock
                for (SymbolEntry e = table[index = (hash = internedName.hashCode()) & (table.length - 1)]; e != nulle = e.next) {
                    if (internedName == e.namereturn e.symbol;
                }
                RubySymbol symbol = new RubySymbol(internedName);
                table[index] = new SymbolEntry(hashinternedNamesymboltable[index]);
                 = potentialNewSize;
                // write-volatile
                 = table;
                return symbol;
            } finally {
                lock.unlock();
            }
        }
        
        // backwards-compatibility, but threadsafe now
        public RubySymbol lookup(String name) {
            int hash = name.hashCode();
            SymbolEntry[] table;
            
            for (SymbolEntry e = (table = )[hash & (table.length - 1)]; e != nulle = e.next) {
                if (hash == e.hash && name.equals(e.name)) return e.symbol;
            }
            return null;
        }
        
        public RubySymbol lookup(long id) {
            SymbolEntry[] table = ;
            
            for (int i = table.length; --i >= 0; ) {
                for (SymbolEntry e = table[i]; e != nulle = e.next) {
                    if (id == e.symbol.idreturn e.symbol;
                }
            }
            return null;
        }
        
        public RubyArray all_symbols() {
            SymbolEntry[] table = this.;
            RubyArray array = .newArray(this.);
            
            for (int i = table.length; --i >= 0; ) {
                for (SymbolEntry e = table[i]; e != nulle = e.next) {
                    array.append(e.symbol);
                }
            }
            return array;
        }
        
        // not so backwards-compatible here, but no one should have been
        // calling this anyway.
        @Deprecated
        public void store(RubySymbol symbol) {
            throw new UnsupportedOperationException();
        }
        
        private SymbolEntry[] rehash() {
            SymbolEntry[] oldTable = ;
            int oldCapacity = oldTable.length;
            
            if (oldCapacity >= return oldTable;
            
            int newCapacity = oldCapacity << 1;
            SymbolEntry[] newTable = new SymbolEntry[newCapacity];
             = (int)(newCapacity * );
            int sizeMask = newCapacity - 1;
            SymbolEntry e;
            for (int i = oldCapacity; --i >= 0; ) {
                // We need to guarantee that any existing reads of old Map can
                //  proceed. So we cannot yet null out each bin.
                e = oldTable[i];
                if (e != null) {
                    SymbolEntry next = e.next;
                    int idx = e.hash & sizeMask;
                    //  Single node on list
                    if (next == null) {
                        newTable[idx] = e;
                    } else {
                        // Reuse trailing consecutive sequence at same slot
                        SymbolEntry lastRun = e;
                        int lastIdx = idx;
                        for (SymbolEntry last = next;
                             last != null;
                             last = last.next) {
                            int k = last.hash & sizeMask;
                            if (k != lastIdx) {
                                lastIdx = k;
                                lastRun = last;
                            }
                        }
                        newTable[lastIdx] = lastRun;
                        // Clone all remaining nodes
                        for (SymbolEntry p = ep != lastRunp = p.next) {
                            int k = p.hash & sizeMask;
                            SymbolEntry n = newTable[k];
                            newTable[k] = new SymbolEntry(p.hashp.namep.symboln);
                        }
                    }
                }
            }
             = newTable;
            return newTable;
        }
    }
    public boolean shouldMarshalEncoding() {
        return getMarshalEncoding() != .;
    }
    public Encoding getMarshalEncoding() {
        return .getEncoding();
    }
    
    
Properly stringify an object for the current "raw bytes" representation of a symbol. Symbols are represented internally as a Java string, but decoded using raw bytes in ISO-8859-1 representation. This means they do not in their normal String form represent a readable Java string, but it does allow differently-encoded strings to map to different symbol objects. See #736

Parameters:
object the object to symbolify
Returns:
the symbol string associated with the object's string representation
    public static String objectToSymbolString(IRubyObject object) {
        if (object instanceof RubySymbol) {
            return ((RubySymbol)object).toString();
        } else if (object instanceof RubyString) {
            return ((RubyString)object).getByteList().toString();
        } else {
            return object.convertToString().getByteList().toString();
        }
    }